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') 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') 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') 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') 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') 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') 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') 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') 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 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') 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') 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 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') 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 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') 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') 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') 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') 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') 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') 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') 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 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') 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') 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') 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') 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') 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') 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') 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') 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 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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 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') 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 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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 [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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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') 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 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') 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') 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 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') 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 ba25d977571e1551b7032d6104e49efd6f88f8ad Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Thu, 9 Jul 2020 15:09:56 +0800 Subject: drm/i915/gvt: Do not destroy ppgtt_mm during vGPU D3->D0. When system enters S3 state, device enters D3 state while RAM remains powered. From vGPU/GVT perspective, ppgtt_mm is residual in guest memory during vGPU in D3 state, so that when guest state transits from S3->S0, ppgtt_mm can be re-used and no need rebuild. Previous implementation invalidate and destroy ppgtt_mm at DMLR, regardless the power state transition is S0->S3->S0 (guest suspend or resume) or OFF->S0 (normal boot/reboot), invalidate and destroy ppgtt_mm is unnecessary in the former transition case. The patch saves the vGPU D3/D0 transition state when guest writes the PCI_PM_CTRL in vGPU's configure space, then in later DMLR, GVT can decide whether or not invalidate and destroy ppgtt_mm is required. The d3_entered flags is reset after DMLR. To test this feature, make sure S3 is enabled in QEMU parameters: i440fx: PIIX4_PM.disable_s3=0 q35: ICH9-LPC.disable_s3=0 Also need enable sleep option in guest OS if it's disabled. v2: - Revise commit message to more accurate description. (Kevin) - Split patch by logic. (Zhenyu) Reviewed-by: Zhenyu Wang Signed-off-by: Hang Yuan Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20200709071002.247960-2-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/cfg_space.c | 24 ++++++++++++++++++++++++ drivers/gpu/drm/i915/gvt/gtt.c | 2 +- drivers/gpu/drm/i915/gvt/gtt.h | 2 ++ drivers/gpu/drm/i915/gvt/gvt.h | 3 +++ drivers/gpu/drm/i915/gvt/vgpu.c | 17 +++++++++++++++-- 5 files changed, 45 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 072725a448db..ad86c5eb5bba 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -70,6 +70,7 @@ static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, { u8 *cfg_base = vgpu_cfg_space(vgpu); u8 mask, new, old; + pci_power_t pwr; int i = 0; for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) { @@ -91,6 +92,15 @@ static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off, /* For other configuration space directly copy as it is. */ if (i < bytes) memcpy(cfg_base + off + i, src + i, bytes - i); + + if (off == vgpu->cfg_space.pmcsr_off && vgpu->cfg_space.pmcsr_off) { + pwr = (pci_power_t __force)(*(u16*)(&vgpu_cfg_space(vgpu)[off]) + & PCI_PM_CTRL_STATE_MASK); + if (pwr == PCI_D3hot) + vgpu->d3_entered = true; + gvt_dbg_core("vgpu-%d power status changed to %d\n", + vgpu->id, pwr); + } } /** @@ -366,6 +376,7 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, struct intel_gvt *gvt = vgpu->gvt; const struct intel_gvt_device_info *info = &gvt->device_info; u16 *gmch_ctl; + u8 next; memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, info->cfg_space_size); @@ -401,6 +412,19 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu, pci_resource_len(gvt->gt->i915->drm.pdev, 2); memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4); + + /* PM Support */ + vgpu->cfg_space.pmcsr_off = 0; + if (vgpu_cfg_space(vgpu)[PCI_STATUS] & PCI_STATUS_CAP_LIST) { + next = vgpu_cfg_space(vgpu)[PCI_CAPABILITY_LIST]; + do { + if (vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_ID] == PCI_CAP_ID_PM) { + vgpu->cfg_space.pmcsr_off = next + PCI_PM_CTRL; + break; + } + next = vgpu_cfg_space(vgpu)[next + PCI_CAP_LIST_NEXT]; + } while (next); + } } /** diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 210016192ce7..a3a4305eda01 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -2501,7 +2501,7 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) return create_scratch_page_tree(vgpu); } -static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu) +void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu) { struct list_head *pos, *n; struct intel_vgpu_mm *mm; diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 320b8d6ad92f..52d0d88abd86 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -279,4 +279,6 @@ int intel_vgpu_emulate_ggtt_mmio_read(struct intel_vgpu *vgpu, int intel_vgpu_emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, void *p_data, unsigned int bytes); +void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu); + #endif /* _GVT_GTT_H_ */ diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index a4a6db6b7f90..ff7f2515a6fe 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -106,6 +106,7 @@ struct intel_vgpu_pci_bar { struct intel_vgpu_cfg_space { unsigned char virtual_cfg_space[PCI_CFG_SPACE_EXP_SIZE]; struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM]; + u32 pmcsr_off; }; #define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space) @@ -198,6 +199,8 @@ struct intel_vgpu { struct intel_vgpu_submission submission; struct radix_tree_root page_track_tree; u32 hws_pga[I915_NUM_ENGINES]; + /* Set on PCI_D3, reset on DMLR, not reflecting the actual PM state */ + bool d3_entered; struct dentry *debugfs; diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 7d361623ff67..fb12448fe353 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -257,6 +257,7 @@ void intel_gvt_release_vgpu(struct intel_vgpu *vgpu) intel_gvt_deactivate_vgpu(vgpu); mutex_lock(&vgpu->vgpu_lock); + vgpu->d3_entered = false; intel_vgpu_clean_workloads(vgpu, ALL_ENGINES); intel_vgpu_dmabuf_cleanup(vgpu); mutex_unlock(&vgpu->vgpu_lock); @@ -393,6 +394,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt, INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL); idr_init(&vgpu->object_idr); intel_vgpu_init_cfg_space(vgpu, param->primary); + vgpu->d3_entered = false; ret = intel_vgpu_init_mmio(vgpu); if (ret) @@ -557,10 +559,15 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, /* full GPU reset or device model level reset */ if (engine_mask == ALL_ENGINES || dmlr) { intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0); - intel_vgpu_invalidate_ppgtt(vgpu); + if (engine_mask == ALL_ENGINES) + intel_vgpu_invalidate_ppgtt(vgpu); /*fence will not be reset during virtual reset */ if (dmlr) { - intel_vgpu_reset_gtt(vgpu); + if(!vgpu->d3_entered) { + intel_vgpu_invalidate_ppgtt(vgpu); + intel_vgpu_destroy_all_ppgtt_mm(vgpu); + } + intel_vgpu_reset_ggtt(vgpu, true); intel_vgpu_reset_resource(vgpu); } @@ -573,6 +580,12 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, /* only reset the failsafe mode when dmlr reset */ vgpu->failsafe = false; vgpu->pv_notified = false; + /* + * PCI_D0 is set before dmlr, so reset d3_entered here + * after done using. + */ + if(vgpu->d3_entered) + vgpu->d3_entered = false; } } -- cgit v1.2.3 From 9e7c0efadb86ddb58965561bbca638d44792d78f Mon Sep 17 00:00:00 2001 From: Colin Xu Date: Thu, 9 Jul 2020 15:09:57 +0800 Subject: drm/i915/gvt: Do not reset pv_notified when vGPU transit from D3->D0 Unlike full initialization like normal boot, guest driver won't pv_notified GVT when vGPU transit from D3->D0. If pv_notified is reset, later vGPU operations will trigger enter into failsafe mode. Considering the fact that vGPU will at least notify GVT pv_notified once before D3/D0 transition, it's safe to skip reset pv_notified in D3->D0. To test this feature, make sure S3 is enabled in QEMU parameters: i440fx: PIIX4_PM.disable_s3=0 q35: ICH9-LPC.disable_s3=0 Also need enable sleep option in guest OS if it's disabled. v2: - Revise commit message to more accurate description. (Kevin) - Split patch by logic. (Zhenyu) Reviewed-by: Zhenyu Wang Signed-off-by: Hang Yuan Signed-off-by: Colin Xu Signed-off-by: Zhenyu Wang Link: http://patchwork.freedesktop.org/patch/msgid/20200709071002.247960-3-colin.xu@intel.com --- drivers/gpu/drm/i915/gvt/vgpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index fb12448fe353..8fa9b31a2484 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -579,13 +579,14 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, intel_vgpu_reset_cfg_space(vgpu); /* only reset the failsafe mode when dmlr reset */ vgpu->failsafe = false; - vgpu->pv_notified = false; /* * PCI_D0 is set before dmlr, so reset d3_entered here * after done using. */ if(vgpu->d3_entered) vgpu->d3_entered = false; + else + vgpu->pv_notified = false; } } -- cgit v1.2.3 From 473e2d16777030ca9b3a0178b179efdb2548b415 Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Tue, 30 Jun 2020 17:55:29 +0800 Subject: drm/amd/display: Fix dmesg warning from setting abm level [Why] Setting abm level does not correctly update CRTC state. As a result no surface update is added to dc stream state and triggers warning. [How] Correctly update CRTC state when setting abm level property. CC: Stable Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/gpu') 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 5109ee032b72..9b4808529a53 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8656,6 +8656,29 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; + /* Check connector changes */ + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + struct dm_connector_state *dm_old_con_state = to_dm_connector_state(old_con_state); + struct dm_connector_state *dm_new_con_state = to_dm_connector_state(new_con_state); + + /* Skip connectors that are disabled or part of modeset already. */ + if (!old_con_state->crtc && !new_con_state->crtc) + continue; + + if (!new_con_state->crtc) + continue; + + new_crtc_state = drm_atomic_get_crtc_state(state, new_con_state->crtc); + if (IS_ERR(new_crtc_state)) { + ret = PTR_ERR(new_crtc_state); + goto fail; + } + + if (dm_old_con_state->abm_level != + dm_new_con_state->abm_level) + new_crtc_state->connectors_changed = true; + } + #if defined(CONFIG_DRM_AMD_DC_DCN) if (adev->asic_type >= CHIP_NAVI10) { for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { -- cgit v1.2.3 From 9b6ca29e093660241002c91e2c8abf771c726921 Mon Sep 17 00:00:00 2001 From: Jun Lei Date: Thu, 25 Jun 2020 13:24:12 -0400 Subject: drm/amd/display: Disable idle optimizations before programming DCN [Why] Programming DCN is explicitly forbidden during idle optimzations allowed state. Existing implemenation relies on OS/DM, which is not robust. Instead DC should sequence this. Note that DC will not re-enter idle optimized state on its own, it is only responsible for catching out of sequence calls. It is still DM responsibility to sequence appropriate for optimized power, but this change removes the requirement for DM to cover the .1% case. [How] - elevate updates during idle optimized state to full updates - disable idle power optimizations prior to programming Signed-off-by: Jun Lei Reviewed-by: Jun Lei Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ef0b5941bc50..92eb1ca1634f 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1250,6 +1250,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c int i, k, l; struct dc_stream_state *dc_streams[MAX_STREAMS] = {0}; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + dc_allow_idle_optimizations(dc, false); +#endif for (i = 0; i < context->stream_count; i++) dc_streams[i] = context->streams[i]; @@ -1838,6 +1841,11 @@ static enum surface_update_type check_update_surfaces_for_stream( int i; enum surface_update_type overall_type = UPDATE_TYPE_FAST; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (dc->idle_optimizations_allowed) + overall_type = UPDATE_TYPE_FULL; + +#endif if (stream_status == NULL || stream_status->plane_count != surface_count) overall_type = UPDATE_TYPE_FULL; @@ -2306,8 +2314,14 @@ static void commit_planes_for_stream(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FULL && dc->optimize_seamless_boot_streams == 0) { - dc->hwss.prepare_bandwidth(dc, context); + if (update_type == UPDATE_TYPE_FULL) { +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + dc_allow_idle_optimizations(dc, false); + +#endif + if (dc->optimize_seamless_boot_streams == 0) + dc->hwss.prepare_bandwidth(dc, context); + context_clock_trace(dc, context); } -- cgit v1.2.3 From cc0f379dd2bb34ee247222ff822b52319a755652 Mon Sep 17 00:00:00 2001 From: Reza Amini Date: Wed, 15 Jul 2020 11:33:23 -0400 Subject: drm/amd/display: Allow asic specific FSFT timing optimization [Why] Each asic can optimize best based on its capabilities [How] Optimizing timing for a new pixel clock Signed-off-by: Reza Amini Reviewed-by: Anthony Koo Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 18 +++++++-------- drivers/gpu/drm/amd/display/dc/dc_stream.h | 4 ++-- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 27 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 5 ++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 ++++ .../drm/amd/display/modules/freesync/freesync.c | 5 +++- 8 files changed, 57 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 10d69ada88e3..0257a900fe2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -246,20 +246,18 @@ struct dc_stream_status *dc_stream_get_status( #ifndef TRIM_FSFT /** - * dc_optimize_timing() - dc to optimize timing + * dc_optimize_timing_for_fsft() - dc to optimize timing */ -bool dc_optimize_timing( - struct dc_crtc_timing *timing, +bool dc_optimize_timing_for_fsft( + struct dc_stream_state *pStream, unsigned int max_input_rate_in_khz) { - //optimization is expected to assing a value to these: - //timing->pix_clk_100hz - //timing->v_front_porch - //timing->v_total - //timing->fast_transport_output_rate_100hz; - timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz; + struct dc *dc; - return true; + dc = pStream->ctx->dc; + + return (dc->hwss.optimize_timing_for_fsft && + dc->hwss.optimize_timing_for_fsft(dc, &pStream->timing, max_input_rate_in_khz)); } #endif diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index e4e85a159462..633442bc7ef2 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -424,8 +424,8 @@ struct dc_stream_status *dc_stream_get_status( struct dc_stream_state *dc_stream); #ifndef TRIM_FSFT -bool dc_optimize_timing( - struct dc_crtc_timing *timing, +bool dc_optimize_timing_for_fsft( + struct dc_stream_state *pStream, unsigned int max_input_rate_in_khz); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 7725a406c16e..66180b4332f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2498,3 +2498,30 @@ void dcn20_fpga_init_hw(struct dc *dc) tg->funcs->tg_init(tg); } } +#ifndef TRIM_FSFT +bool dcn20_optimize_timing_for_fsft(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz) +{ + unsigned int old_v_front_porch; + unsigned int old_v_total; + unsigned int max_input_rate_in_100hz; + unsigned long long new_v_total; + + max_input_rate_in_100hz = max_input_rate_in_khz * 10; + if (max_input_rate_in_100hz < timing->pix_clk_100hz) + return false; + + old_v_total = timing->v_total; + old_v_front_porch = timing->v_front_porch; + + timing->fast_transport_output_rate_100hz = timing->pix_clk_100hz; + timing->pix_clk_100hz = max_input_rate_in_100hz; + + new_v_total = div_u64((unsigned long long)old_v_total * max_input_rate_in_100hz, timing->pix_clk_100hz); + + timing->v_total = new_v_total; + timing->v_front_porch = old_v_front_porch + (timing->v_total - old_v_total); + return true; +} +#endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 63ce763f148e..83220e34c1a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -132,5 +132,10 @@ int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); +#ifndef TRIM_FSFT +bool dcn20_optimize_timing_for_fsft(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz); +#endif #endif /* __DC_HWSS_DCN20_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 2380392b916e..3dde6f26de47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -88,6 +88,9 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .set_backlight_level = dce110_set_backlight_level, .set_abm_immediate_disable = dce110_set_abm_immediate_disable, .set_pipe = dce110_set_pipe, +#ifndef TRIM_FSFT + .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, +#endif }; static const struct hwseq_private_funcs dcn20_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 177d0dc8927a..b187f71afa65 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -92,6 +92,9 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .set_backlight_level = dcn21_set_backlight_level, .set_abm_immediate_disable = dcn21_set_abm_immediate_disable, .set_pipe = dcn21_set_pipe, +#ifndef TRIM_FSFT + .optimize_timing_for_fsft = dcn20_optimize_timing_for_fsft, +#endif }; static const struct hwseq_private_funcs dcn21_private_funcs = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 720ce5e458d8..3c986717dcd5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -116,6 +116,11 @@ struct hw_sequencer_funcs { void (*set_static_screen_control)(struct pipe_ctx **pipe_ctx, int num_pipes, const struct dc_static_screen_params *events); +#ifndef TRIM_FSFT + bool (*optimize_timing_for_fsft)(struct dc *dc, + struct dc_crtc_timing *timing, + unsigned int max_input_rate_in_khz); +#endif /* Stream Related */ void (*enable_stream)(struct pipe_ctx *pipe_ctx); diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 7a2500fbf3f2..81820f3d6b3b 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -829,10 +829,13 @@ void mod_freesync_build_vrr_infopacket(struct mod_freesync *mod_freesync, switch (packet_type) { case PACKET_TYPE_FS_V3: #ifndef TRIM_FSFT + // always populate with pixel rate. build_vrr_infopacket_v3( stream->signal, vrr, stream->timing.flags.FAST_TRANSPORT, - stream->timing.fast_transport_output_rate_100hz, + (stream->timing.flags.FAST_TRANSPORT) ? + stream->timing.fast_transport_output_rate_100hz : + stream->timing.pix_clk_100hz, app_tf, infopacket); #else build_vrr_infopacket_v3(stream->signal, vrr, app_tf, infopacket); -- cgit v1.2.3 From 097e6d98c98fc79625e44c03c56924a6bb2569ef Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Tue, 14 Jul 2020 13:42:05 -0400 Subject: drm/amd/display: DSC Clock enable debugfs write entry [Why] Need a mechanism to force enable DSC on any connector [How] Debugfs entry overwrites newly added connector's dsc preffered settings structure and sets dsc_clock_en flag on it. During the attomic commit, depending if connector is SST or MST, we will enable DSC manually by overwriting stream's DSC flag. Signed-off-by: Eryk Brol 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.c | 5 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 5 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 89 ++++++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 11 ++- 4 files changed, 107 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 9b4808529a53..eaec386b31c9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4659,7 +4659,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, dc_link_get_link_cap(aconnector->dc_link)); #if defined(CONFIG_DRM_AMD_DC_DCN) - if (dsc_caps.is_dsc_supported) + if (dsc_caps.is_dsc_supported) { if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], &dsc_caps, aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, @@ -4667,6 +4667,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, &stream->timing, &stream->timing.dsc_cfg)) stream->timing.flags.DSC = 1; + if (aconnector->dsc_settings.dsc_clock_en) + stream->timing.flags.DSC = 1; + } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index dd1559c743c2..56f50a309eba 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -342,6 +342,10 @@ struct amdgpu_display_manager { struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; }; +struct dsc_preferred_settings { + bool dsc_clock_en; +}; + struct amdgpu_dm_connector { struct drm_connector base; @@ -389,6 +393,7 @@ struct amdgpu_dm_connector { uint32_t debugfs_dpcd_size; #endif bool force_yuv420_output; + struct dsc_preferred_settings dsc_settings; }; #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index e5a6d9115949..5322bc13af3c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -980,6 +980,21 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +/* function: read DSC status on the connector + * + * The read function: dp_dsc_clock_en_read + * returns current status of DSC clock on the connector. + * The return is a boolean flag: 1 or 0. + * + * Access it with the following command (you need to specify + * connector like DP-1): + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + * Expected output: + * 1 - means that DSC is currently enabled + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1037,6 +1052,79 @@ static ssize_t dp_dsc_clock_en_read(struct file *f, char __user *buf, return result; } +/* function: write force DSC on the connector + * + * The write function: dp_dsc_clock_en_write + * enables to force DSC on the connector. + * User can write to either force enable DSC + * on the next modeset or set it to driver default + * + * Writing DSC settings is done with the following command: + * - To force enable DSC (you need to specify + * connector like DP-1): + * + * echo 0x1 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + * - To return to default state set the flag to zero and + * let driver deal with DSC automatically + * (you need to specify connector like DP-1): + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_clock_en + * + */ +static ssize_t dp_dsc_clock_en_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_clock_en = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1446,6 +1534,7 @@ DEFINE_SHOW_ATTRIBUTE(hdcp_sink_capability); static const struct file_operations dp_dsc_clock_en_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_clock_en_read, + .write = dp_dsc_clock_en_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e85b58f0f416..bb03aa608123 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -450,6 +450,7 @@ struct dsc_mst_fairness_params { struct dc_dsc_bw_range bw_range; bool compression_possible; struct drm_dp_mst_port *port; + bool clock_overwrite; }; struct dsc_mst_fairness_vars { @@ -615,7 +616,9 @@ static void try_disable_dsc(struct drm_atomic_state *state, int remaining_to_try = 0; for (i = 0; i < count; i++) { - if (vars[i].dsc_enabled && vars[i].bpp_x16 == params[i].bw_range.max_target_bpp_x16) { + if (vars[i].dsc_enabled + && vars[i].bpp_x16 == params[i].bw_range.max_target_bpp_x16 + && !params[i].clock_overwrite) { kbps_increase[i] = params[i].bw_range.stream_kbps - params[i].bw_range.max_kbps; tried[i] = false; remaining_to_try += 1; @@ -676,6 +679,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, struct dsc_mst_fairness_vars vars[MAX_PIPES]; struct amdgpu_dm_connector *aconnector; int count = 0; + bool debugfs_overwrite = false; memset(params, 0, sizeof(params)); @@ -694,6 +698,9 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].sink = stream->sink; aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; params[count].port = aconnector->port; + params[count].clock_overwrite = aconnector->dsc_settings.dsc_clock_en; + if (params[count].clock_overwrite) + debugfs_overwrite = true; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( @@ -719,7 +726,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, dm_mst_get_pbn_divider(dc_link)) < 0) return false; } - if (!drm_dp_mst_atomic_check(state)) { + if (!drm_dp_mst_atomic_check(state) && !debugfs_overwrite) { set_dsc_configs_from_fairness_vars(params, vars, count); return true; } -- cgit v1.2.3 From 68d90e066df1e14641749cc1821ff36452b64368 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sat, 18 Jul 2020 15:25:22 -0400 Subject: drm/amd/display: [FW Promotion] Release 0.0.26 Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index e013875b89ed..8b27cf0f1d51 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xe6d590b09 +#define DMUB_FW_VERSION_GIT_HASH 0x636e7b294 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 25 +#define DMUB_FW_VERSION_REVISION 26 #define DMUB_FW_VERSION_UCODE ((DMUB_FW_VERSION_MAJOR << 24) | (DMUB_FW_VERSION_MINOR << 16) | DMUB_FW_VERSION_REVISION) #endif -- cgit v1.2.3 From 31f34d19f87ee9fa475bc8556e298ea1ec3e7e1d Mon Sep 17 00:00:00 2001 From: hersen wu Date: Sun, 19 Jul 2020 17:21:59 -0400 Subject: drm/amd/display: dchubbub p-state warning during surface planes switch [Why] ramp_up_dispclk_with_dpp is to change dispclk, dppclk and dprefclk according to bandwidth requirement. call stack: rv1_update_clocks --> update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, prepare_bandwidth will be called first to allow enough clock, watermark for change, after end of dcn hw change, optimize_bandwidth is executed to lower clock to save power for new dcn hw settings. below is sequence of commit_planes_for_stream: step 1: prepare_bandwidth - raise clock to have enough bandwidth step 2: lock_doublebuffer_enable step 3: pipe_control_lock(true) - make dchubp register change will not take effect right way step 4: apply_ctx_for_surface - program dchubp step 5: pipe_control_lock(false) - dchubp register change take effect step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream for full_date, optimize clock to save power at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be changed for new dchubp configuration. but real dcn hub dchubps are still running with old configuration until end of step 5. this need clocks settings at step 1 should not less than that before step 1. this is checked by two conditions: 1. if (should_set_clock(safe_to_lower , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz the second condition is based on new dchubp configuration. dppclk for new dchubp may be different from dppclk before step 1. for example, before step 1, dchubps are as below: pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) for dppclk for pipe0 need dppclk = dispclk new dchubp pipe split configuration: pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) dppclk only needs dppclk = dispclk /2. dispclk, dppclk are not lock by otg master lock. they take effect after step 1. during this transition, dispclk are the same, but dppclk is changed to half of previous clock for old dchubp configuration between step 1 and step 6. This may cause p-state warning intermittently. [How] for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we need make sure dppclk are not changed to less between step 1 and 6. for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, new display clock is raised, but we do not know ratio of new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, new_clocks->dispclk_khz /2 does not guarantee equal or higher than old dppclk. we could ignore power saving different between dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. as long as safe_to_lower = false, set dpclk = dispclk to simplify condition check. CC: Stable Signed-off-by: Hersen Wu Reviewed-by: Aric Cyr Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c | 69 +++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c index 3fab9296918a..e133edc587d3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn10/rv1_clk_mgr.c @@ -85,12 +85,77 @@ static int rv1_determine_dppclk_threshold(struct clk_mgr_internal *clk_mgr, stru return disp_clk_threshold; } -static void ramp_up_dispclk_with_dpp(struct clk_mgr_internal *clk_mgr, struct dc *dc, struct dc_clocks *new_clocks) +static void ramp_up_dispclk_with_dpp( + struct clk_mgr_internal *clk_mgr, + struct dc *dc, + struct dc_clocks *new_clocks, + bool safe_to_lower) { int i; int dispclk_to_dpp_threshold = rv1_determine_dppclk_threshold(clk_mgr, new_clocks); bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz; + /* this function is to change dispclk, dppclk and dprefclk according to + * bandwidth requirement. Its call stack is rv1_update_clocks --> + * update_clocks --> dcn10_prepare_bandwidth / dcn10_optimize_bandwidth + * --> prepare_bandwidth / optimize_bandwidth. before change dcn hw, + * prepare_bandwidth will be called first to allow enough clock, + * watermark for change, after end of dcn hw change, optimize_bandwidth + * is executed to lower clock to save power for new dcn hw settings. + * + * below is sequence of commit_planes_for_stream: + * + * step 1: prepare_bandwidth - raise clock to have enough bandwidth + * step 2: lock_doublebuffer_enable + * step 3: pipe_control_lock(true) - make dchubp register change will + * not take effect right way + * step 4: apply_ctx_for_surface - program dchubp + * step 5: pipe_control_lock(false) - dchubp register change take effect + * step 6: optimize_bandwidth --> dc_post_update_surfaces_to_stream + * for full_date, optimize clock to save power + * + * at end of step 1, dcn clocks (dprefclk, dispclk, dppclk) may be + * changed for new dchubp configuration. but real dcn hub dchubps are + * still running with old configuration until end of step 5. this need + * clocks settings at step 1 should not less than that before step 1. + * this is checked by two conditions: 1. if (should_set_clock(safe_to_lower + * , new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || + * new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) + * 2. request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz + * + * the second condition is based on new dchubp configuration. dppclk + * for new dchubp may be different from dppclk before step 1. + * for example, before step 1, dchubps are as below: + * pipe 0: recout=(0,40,1920,980) viewport=(0,0,1920,979) + * pipe 1: recout=(0,0,1920,1080) viewport=(0,0,1920,1080) + * for dppclk for pipe0 need dppclk = dispclk + * + * new dchubp pipe split configuration: + * pipe 0: recout=(0,0,960,1080) viewport=(0,0,960,1080) + * pipe 1: recout=(960,0,960,1080) viewport=(960,0,960,1080) + * dppclk only needs dppclk = dispclk /2. + * + * dispclk, dppclk are not lock by otg master lock. they take effect + * after step 1. during this transition, dispclk are the same, but + * dppclk is changed to half of previous clock for old dchubp + * configuration between step 1 and step 6. This may cause p-state + * warning intermittently. + * + * for new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz, we + * need make sure dppclk are not changed to less between step 1 and 6. + * for new_clocks->dispclk_khz > clk_mgr_base->clks.dispclk_khz, + * new display clock is raised, but we do not know ratio of + * new_clocks->dispclk_khz and clk_mgr_base->clks.dispclk_khz, + * new_clocks->dispclk_khz /2 does not guarantee equal or higher than + * old dppclk. we could ignore power saving different between + * dppclk = displck and dppclk = dispclk / 2 between step 1 and step 6. + * as long as safe_to_lower = false, set dpclk = dispclk to simplify + * condition check. + * todo: review this change for other asic. + **/ + if (!safe_to_lower) + request_dpp_div = false; + /* set disp clk to dpp clk threshold */ clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold); @@ -209,7 +274,7 @@ static void rv1_update_clocks(struct clk_mgr *clk_mgr_base, /* program dispclk on = as a w/a for sleep resume clock ramping issues */ if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz) || new_clocks->dispclk_khz == clk_mgr_base->clks.dispclk_khz) { - ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks); + ramp_up_dispclk_with_dpp(clk_mgr, dc, new_clocks, safe_to_lower); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; send_request_to_lower = true; } -- cgit v1.2.3 From 42a614800b0647af3c4944f2ac04eb1613b30161 Mon Sep 17 00:00:00 2001 From: Wyatt Wood Date: Wed, 17 Jun 2020 11:29:27 -0400 Subject: drm/amd/display: Use hw lock mgr [Why] Feature requires synchronization of dig, pipe, and cursor locking between driver and fw. [How] Set flag to force psr to use hw lock mgr. Signed-off-by: Wyatt Wood Reviewed-by: Anthony Koo Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c index 82e67bd81f2d..5167d6b8a48d 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c @@ -233,8 +233,8 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub, copy_settings_data->frame_cap_ind = psr_context->psrFrameCaptureIndicationReq; copy_settings_data->debug.bitfields.visual_confirm = dc->dc->debug.visual_confirm == VISUAL_CONFIRM_PSR ? true : false; + copy_settings_data->debug.bitfields.use_hw_lock_mgr = 1; copy_settings_data->init_sdp_deadline = psr_context->sdpTransmitLineNumDeadline; - copy_settings_data->debug.bitfields.use_hw_lock_mgr = 0; dc_dmub_srv_cmd_queue(dc->dmub_srv, &cmd); dc_dmub_srv_cmd_execute(dc->dmub_srv); -- cgit v1.2.3 From 27e84dd7b4490fad29118d5bddfc0018f38a1c66 Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Wed, 17 Jun 2020 14:39:50 -0400 Subject: drm/amd/display: DSC Slice width debugfs write entry [Why] We need to be able to specify slice width for DSC on aconnector [How] Getting slice width parameter from debugfs entry, if it is a valid the value is set in connector's dsc preffered settings structure. Which then overwrites dsc_cfg structure's parameters if DSC is decided to be enabled. Works for both SST and MST. Signed-off-by: Eryk Brol 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.c | 4 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 93 ++++++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 6 ++ 4 files changed, 104 insertions(+) (limited to 'drivers/gpu') 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 eaec386b31c9..09da24e8806f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4667,8 +4667,12 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, &stream->timing, &stream->timing.dsc_cfg)) stream->timing.flags.DSC = 1; + /* Overwrite the stream flag if DSC is enabled through debugfs */ if (aconnector->dsc_settings.dsc_clock_en) stream->timing.flags.DSC = 1; + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) + stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable, + aconnector->dsc_settings.dsc_slice_width); } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 56f50a309eba..a06ad133a23a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -344,6 +344,7 @@ struct amdgpu_display_manager { struct dsc_preferred_settings { bool dsc_clock_en; + uint32_t dsc_slice_width; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 5322bc13af3c..550138012123 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1125,6 +1125,22 @@ done: return size; } +/* function: read DSC slice width parameter on the connector + * + * The read function: dp_dsc_slice_width_read + * returns dsc slice width used in the current configuration + * The return is an integer: 0 or other positive number + * + * Access the status with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + * 0 - means that DSC is disabled + * + * Any other number more than zero represents the + * slice width currently used by DSC in pixels + * + */ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1182,6 +1198,82 @@ static ssize_t dp_dsc_slice_width_read(struct file *f, char __user *buf, return result; } +/* function: write DSC slice width parameter + * + * The write function: dp_dsc_slice_width_write + * overwrites automatically generated DSC configuration + * of slice width. + * + * The user has to write the slice width divisible by the + * picture width. + * + * Also the user has to write width in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite slice width: (example sets to 1920 pixels) + * + * echo 0x780 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + * - To stop overwriting and let driver find the optimal size, + * set the width to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_width + * + */ +static ssize_t dp_dsc_slice_width_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_slice_width = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1541,6 +1633,7 @@ static const struct file_operations dp_dsc_clock_en_debugfs_fops = { static const struct file_operations dp_dsc_slice_width_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_slice_width_read, + .write = dp_dsc_slice_width_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index bb03aa608123..b8a900e963d3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -451,6 +451,7 @@ struct dsc_mst_fairness_params { bool compression_possible; struct drm_dp_mst_port *port; bool clock_overwrite; + uint32_t slice_width_overwrite; }; struct dsc_mst_fairness_vars { @@ -485,6 +486,10 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p ¶ms[i].timing->dsc_cfg)) { params[i].timing->flags.DSC = 1; params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + if (params[i].slice_width_overwrite) + params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( + params[i].timing->h_addressable, + params[i].slice_width_overwrite); } else { params[i].timing->flags.DSC = 0; } @@ -701,6 +706,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, params[count].clock_overwrite = aconnector->dsc_settings.dsc_clock_en; if (params[count].clock_overwrite) debugfs_overwrite = true; + params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- cgit v1.2.3 From 746565c25abf9e0bc603aaf520cb33bed7510842 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 20 Jul 2020 11:07:46 -0400 Subject: drm/amd/display: 3.2.96 Signed-off-by: Aric Cyr Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f50ef4255020..ae0e27c67ef9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.95" +#define DC_VER "3.2.96" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From d9b91b1ea26b0e528c44c12f9b5637ba41b9006c Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Wed, 22 Jul 2020 15:40:06 -0400 Subject: drm/amd/display: Fix DP Compliance tests 4.3.2.1 and 4.3.2.2 [Why] Test expects that we also read HPD_IRQ_VECTOR when checking for symbol loss as well lane status. [How] Read bytes 0x200-0x205 instead of just 0x202-0x205 Signed-off-by: Aric Cyr Reviewed-by: Jun Lei Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') 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 1a3dbed3becb..d7d2dcd49c06 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1138,23 +1138,22 @@ static enum link_training_result check_link_loss_status( const struct link_training_settings *link_training_setting) { enum link_training_result status = LINK_TRAINING_SUCCESS; - unsigned int lane01_status_address = DP_LANE0_1_STATUS; union lane_status lane_status; - uint8_t dpcd_buf[4] = {0}; + uint8_t dpcd_buf[6] = {0}; uint32_t lane; core_link_read_dpcd( - link, - lane01_status_address, - (uint8_t *)(dpcd_buf), - sizeof(dpcd_buf)); + link, + DP_SINK_COUNT, + (uint8_t *)(dpcd_buf), + sizeof(dpcd_buf)); /*parse lane status*/ for (lane = 0; lane < link->cur_link_settings.lane_count; lane++) { /* * check lanes status */ - lane_status.raw = get_nibble_at_index(&dpcd_buf[0], lane); + lane_status.raw = get_nibble_at_index(&dpcd_buf[2], lane); if (!lane_status.bits.CHANNEL_EQ_DONE_0 || !lane_status.bits.CR_DONE_0 || -- cgit v1.2.3 From 35dab589de1309c485935ede35870adf155bba6e Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Mon, 27 Jul 2020 16:19:45 +0800 Subject: drm/amdgpu: skip crit temperature values on APU (v2) It doesn't expose PPTable descriptor on APU platform. So max/min temperature values cannot be got from APU platform. v2: Stoney needs to skip crit temperature as well. Signed-off-by: Huang Rui Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 581b2d6bea3b..f44157daf3ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -3467,6 +3467,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) return 0; + /* Skip crit temp on APU */ + if ((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ) && + (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) + return 0; + /* Skip limit attributes if DPM is not enabled */ if (!adev->pm.dpm_enabled && (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || -- cgit v1.2.3 From 01eee24fceb9a64b2dc3b3ccb7b7c6852aa7a403 Mon Sep 17 00:00:00 2001 From: John Clements Date: Tue, 28 Jul 2020 14:22:54 +0800 Subject: drm/amdgpu: enable umc 8.7 functions in gmc v10 add support for umc 8.7 initialization add umc 8.7 source to makefile Reviewed-by: Guchun Chen Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 50 +++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 403ec3db29df..0ba396e9d7e4 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -85,7 +85,7 @@ amdgpu-y += \ # add UMC block amdgpu-y += \ - umc_v6_1.o umc_v6_0.o + umc_v6_1.o umc_v6_0.o umc_v8_7.o # add IH block amdgpu-y += \ diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 1a78073c2f05..35d21f330b0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -25,6 +25,7 @@ #include "amdgpu.h" #include "amdgpu_atomfirmware.h" #include "gmc_v10_0.h" +#include "umc_v8_7.h" #include "hdp/hdp_5_0_0_offset.h" #include "hdp/hdp_5_0_0_sh_mask.h" @@ -55,6 +56,14 @@ static const struct soc15_reg_golden golden_settings_navi10_hdp[] = }; #endif +static int gmc_v10_0_ecc_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + static int gmc_v10_0_vm_fault_interrupt_state(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type, @@ -131,10 +140,20 @@ static const struct amdgpu_irq_src_funcs gmc_v10_0_irq_funcs = { .process = gmc_v10_0_process_interrupt, }; -static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev) +static const struct amdgpu_irq_src_funcs gmc_v10_0_ecc_funcs = { + .set = gmc_v10_0_ecc_interrupt_state, + .process = amdgpu_umc_process_ecc_irq, +}; + + static void gmc_v10_0_set_irq_funcs(struct amdgpu_device *adev) { adev->gmc.vm_fault.num_types = 1; adev->gmc.vm_fault.funcs = &gmc_v10_0_irq_funcs; + + if (!amdgpu_sriov_vf(adev)) { + adev->gmc.ecc_irq.num_types = 1; + adev->gmc.ecc_irq.funcs = &gmc_v10_0_ecc_funcs; + } } /** @@ -569,12 +588,29 @@ static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev) adev->gmc.gmc_funcs = &gmc_v10_0_gmc_funcs; } +static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: + adev->umc.max_ras_err_cnt_per_query = UMC_V8_7_TOTAL_CHANNEL_NUM; + adev->umc.channel_inst_num = UMC_V8_7_CHANNEL_INSTANCE_NUM; + adev->umc.umc_inst_num = UMC_V8_7_UMC_INSTANCE_NUM; + adev->umc.channel_offs = UMC_V8_7_PER_CHANNEL_OFFSET_SIENNA; + adev->umc.channel_idx_tbl = &umc_v8_7_channel_idx_tbl[0][0]; + adev->umc.funcs = &umc_v8_7_funcs; + break; + default: + break; + } +} + static int gmc_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; gmc_v10_0_set_gmc_funcs(adev); gmc_v10_0_set_irq_funcs(adev); + gmc_v10_0_set_umc_funcs(adev); adev->gmc.shared_aperture_start = 0x2000000000000000ULL; adev->gmc.shared_aperture_end = @@ -790,6 +826,14 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; + if (!amdgpu_sriov_vf(adev)) { + /* interrupt sent to DF. */ + r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_DF, 0, + &adev->gmc.ecc_irq); + if (r) + return r; + } + /* * Set the internal MC address mask This is the max address of the GPU's * internal address space. @@ -950,6 +994,9 @@ static int gmc_v10_0_hw_init(void *handle) if (r) return r; + if (adev->umc.funcs && adev->umc.funcs->init_registers) + adev->umc.funcs->init_registers(adev); + return 0; } @@ -981,6 +1028,7 @@ static int gmc_v10_0_hw_fini(void *handle) return 0; } + amdgpu_irq_put(adev, &adev->gmc.ecc_irq, 0); amdgpu_irq_put(adev, &adev->gmc.vm_fault, 0); gmc_v10_0_gart_disable(adev); -- cgit v1.2.3 From da82cbd8328ff7574d5f42c09562572890338309 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Tue, 28 Jul 2020 19:14:22 +0800 Subject: drm/amd/powerplay: update driver if version for navy_flounder It's in accordance with pmfw 65.5.0 for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 9504f9954fd3..6a42331aba8a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -31,7 +31,7 @@ #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x34 -#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x2 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 /* MP Apertures */ #define MP0_Public 0x03800000 -- cgit v1.2.3 From defa489636a67bb64ecd3bd9ae9ddedb163adccf Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Wed, 29 Jul 2020 11:58:21 +0800 Subject: drm/amdgpu: update GC golden setting for navy_flounder Update GC golden setting for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index db9f1e89a0f8..ca16f01956d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3127,7 +3127,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA0_CLK_CTRL, 0xff7f0fff, 0x30000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCGTT_SPI_RA1_CLK_CTRL, 0xff7f0fff, 0x7e000100), SOC15_REG_GOLDEN_VALUE(GC, 0, mmCPF_GCR_CNTL, 0x0007ffff, 0x0000c000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000280), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x00800000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_EXCEPTION_CONTROL, 0x7fff0f1f, 0x00b80000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL_Sienna_Cichlid, 0x1ff1ffff, 0x00000500), @@ -3158,7 +3158,7 @@ static const struct soc15_reg_golden golden_settings_gc_10_3_2[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER7_SELECT, 0xf0f001ff, 0x00000000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER8_SELECT, 0xf0f001ff, 0x00000000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_PERFCOUNTER9_SELECT, 0xf0f001ff, 0x00000000), - SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xffffffff, 0x010b0000), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffbfffff, 0x00a00000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff) }; -- cgit v1.2.3 From 7619517598ad5ba04beb855cde6558e72c73dbb5 Mon Sep 17 00:00:00 2001 From: Mazin Rezk Date: Mon, 27 Jul 2020 05:40:46 +0000 Subject: drm/amd/display: Clear dm_state for fast updates This patch fixes a race condition that causes a use-after-free during amdgpu_dm_atomic_commit_tail. This can occur when 2 non-blocking commits are requested and the second one finishes before the first. Essentially, this bug occurs when the following sequence of events happens: 1. Non-blocking commit #1 is requested w/ a new dm_state #1 and is deferred to the workqueue. 2. Non-blocking commit #2 is requested w/ a new dm_state #2 and is deferred to the workqueue. 3. Commit #2 starts before commit #1, dm_state #1 is used in the commit_tail and commit #2 completes, freeing dm_state #1. 4. Commit #1 starts after commit #2 completes, uses the freed dm_state 1 and dereferences a freelist pointer while setting the context. Since this bug has only been spotted with fast commits, this patch fixes the bug by clearing the dm_state instead of using the old dc_state for fast updates. In addition, since dm_state is only used for its dc_state and amdgpu_dm_atomic_commit_tail will retain the dc_state if none is found, removing the dm_state should not have any consequences in fast updates. This use-after-free bug has existed for a while now, but only caused a noticeable issue starting from 5.7-rc1 due to 3202fa62f ("slub: relocate freelist pointer to middle of object") moving the freelist pointer from dm_state->base (which was unused) to dm_state->context (which is dereferenced). Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=207383 Fixes: bd200d190f45 ("drm/amd/display: Don't replace the dc_state for fast updates") Reported-by: Duncan <1i5t5.duncan@cox.net> Signed-off-by: Mazin Rezk Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 +++++++++++++++++------ 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') 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 09da24e8806f..4b3286287913 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8901,20 +8901,38 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, * the same resource. If we have a new DC context as part of * the DM atomic state from validation we need to free it and * retain the existing one instead. + * + * Furthermore, since the DM atomic state only contains the DC + * context and can safely be annulled, we can free the state + * and clear the associated private object now to free + * some memory and avoid a possible use-after-free later. */ - struct dm_atomic_state *new_dm_state, *old_dm_state; - new_dm_state = dm_atomic_get_new_state(state); - old_dm_state = dm_atomic_get_old_state(state); + for (i = 0; i < state->num_private_objs; i++) { + struct drm_private_obj *obj = state->private_objs[i].ptr; - if (new_dm_state && old_dm_state) { - if (new_dm_state->context) - dc_release_state(new_dm_state->context); + if (obj->funcs == adev->dm.atomic_obj.funcs) { + int j = state->num_private_objs-1; - new_dm_state->context = old_dm_state->context; + dm_atomic_destroy_state(obj, + state->private_objs[i].state); + + /* If i is not at the end of the array then the + * last element needs to be moved to where i was + * before the array can safely be truncated. + */ + if (i != j) + state->private_objs[i] = + state->private_objs[j]; - if (old_dm_state->context) - dc_retain_state(old_dm_state->context); + state->private_objs[j].ptr = NULL; + state->private_objs[j].state = NULL; + state->private_objs[j].old_state = NULL; + state->private_objs[j].new_state = NULL; + + state->num_private_objs = j; + break; + } } } -- cgit v1.2.3 From 8e326285924cd13d9d94edc209440ef5b6f85085 Mon Sep 17 00:00:00 2001 From: Peilin Ye Date: Tue, 28 Jul 2020 15:29:24 -0400 Subject: drm/amdgpu: Prevent kernel-infoleak in amdgpu_info_ioctl() Compiler leaves a 4-byte hole near the end of `dev_info`, causing amdgpu_info_ioctl() to copy uninitialized kernel stack memory to userspace when `size` is greater than 356. In 2015 we tried to fix this issue by doing `= {};` on `dev_info`, which unfortunately does not initialize that 4-byte hole. Fix it by using memset() instead. Cc: stable@vger.kernel.org Fixes: c193fa91b918 ("drm/amdgpu: information leak in amdgpu_info_ioctl()") Fixes: d38ceaf99ed0 ("drm/amdgpu: add core driver (v4)") Suggested-by: Dan Carpenter Reviewed-by: Christian König Signed-off-by: Peilin Ye Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index b9c1fce6da79..e99ad031efd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -707,9 +707,10 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return n ? -EFAULT : 0; } case AMDGPU_INFO_DEV_INFO: { - struct drm_amdgpu_info_device dev_info = {}; + struct drm_amdgpu_info_device dev_info; uint64_t vm_size; + memset(&dev_info, 0, sizeof(dev_info)); dev_info.device_id = dev->pdev->device; dev_info.chip_rev = adev->rev_id; dev_info.external_rev = adev->external_rev_id; -- cgit v1.2.3 From 317469f695c27e290b8001a0df0fdbb95f27bfa9 Mon Sep 17 00:00:00 2001 From: Li Heng Date: Wed, 29 Jul 2020 16:34:01 +0800 Subject: drm/amd/powerplay: Remove unneeded cast from memory allocation Remove casting the values returned by memory allocation function. Coccinelle emits WARNING: ./drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c:893:37-46: WARNING: casting value returned by memory allocation function to (PPTable_t *) is useless. Signed-off-by: Li Heng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c index 7a7f15d0c53a..f56a3cbdfa3b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c @@ -890,7 +890,7 @@ static int init_powerplay_table_information( power_saving_clock_count); } - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; -- cgit v1.2.3 From 178b0013f074da545492662ec76dc2be363ca85c Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 27 Jul 2020 23:30:18 +0200 Subject: drm/amdgpu/dc: Stop dma_resv_lock inversion in commit_tail Trying to grab dma_resv_lock while in commit_tail before we've done all the code that leads to the eventual signalling of the vblank event (which can be a dma_fence) is deadlock-y. Don't do that. Here the solution is easy because just grabbing locks to read something races anyway. We don't need to bother, READ_ONCE is equivalent. And avoids the locking issue. v2: Also take into account tmz_surface boolean, plus just delete the old code. Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Cc: linux-rdma@vger.kernel.org Cc: amd-gfx@lists.freedesktop.org Cc: intel-gfx@lists.freedesktop.org Cc: Chris Wilson Cc: Maarten Lankhorst Cc: Christian König Reviewed-by: Christian König Signed-off-by: Daniel Vetter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') 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 4b3286287913..342663fcd44d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7081,20 +7081,13 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, DRM_ERROR("Waiting for fences timed out!"); /* - * TODO This might fail and hence better not used, wait - * explicitly on fences instead - * and in general should be called for - * blocking commit to as per framework helpers + * We cannot reserve buffers here, which means the normal flag + * access functions don't work. Paper over this with READ_ONCE, + * but maybe the flags are invariant enough that not even that + * would be needed. */ - r = amdgpu_bo_reserve(abo, true); - if (unlikely(r != 0)) - DRM_ERROR("failed to reserve buffer before flip\n"); - - amdgpu_bo_get_tiling_flags(abo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(abo); - - amdgpu_bo_unreserve(abo); + tiling_flags = READ_ONCE(abo->tiling_flags); + tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; fill_dc_plane_info_and_addr( dm->adev, new_plane_state, tiling_flags, -- cgit v1.2.3 From 392cf6a739271a70311b6a3c4f60900039721a68 Mon Sep 17 00:00:00 2001 From: Liu ChengZhe Date: Fri, 24 Jul 2020 17:22:15 +0800 Subject: drm/amdgpu: fix PSP autoload twice in FLR Assigning false to block->status.hw overwrites PSP's previous hardware status, which causes the PSP to Resume operation after hardware init. Remove this assignment and let the PSP execute Resume operation when it is told to. v2: Remove the braces. v3: Modify the description. Signed-off-by: Liu ChengZhe Reviewed-by: Luben Tuikov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 638c2cc426c1..40caa7437ce2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2574,6 +2574,9 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; + for (i = 0; i < adev->num_ip_blocks; i++) + adev->ip_blocks[i].status.hw = false; + for (i = 0; i < ARRAY_SIZE(ip_order); i++) { int j; struct amdgpu_ip_block *block; @@ -2581,7 +2584,6 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) for (j = 0; j < adev->num_ip_blocks; j++) { block = &adev->ip_blocks[j]; - block->status.hw = false; if (block->version->type != ip_order[i] || !block->status.valid) continue; -- cgit v1.2.3 From f61772cd132e09bd9e0b52627d8a82631e860a10 Mon Sep 17 00:00:00 2001 From: Liu ChengZhe Date: Fri, 24 Jul 2020 15:55:33 +0800 Subject: drm amdgpu: Skip tmr load for SRIOV 1. For Navi12, CHIP_SIENNA_CICHLID, skip tmr load operation; 2. Check pointer before release firmware. v2: use CHIP_SIENNA_CICHLID instead v3: remove local "bool ret"; fix grammer issue v4: use my name instead of "root" v5: fix grammer issue and indent issue Signed-off-by: Liu ChengZhe Reviewed-by: Luben Tuikov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 35 +++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index a053b7af0680..c68369731b20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -193,12 +193,18 @@ static int psp_sw_fini(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; psp_memory_training_fini(&adev->psp); - release_firmware(adev->psp.sos_fw); - adev->psp.sos_fw = NULL; - release_firmware(adev->psp.asd_fw); - adev->psp.asd_fw = NULL; - release_firmware(adev->psp.ta_fw); - adev->psp.ta_fw = NULL; + if (adev->psp.sos_fw) { + release_firmware(adev->psp.sos_fw); + adev->psp.sos_fw = NULL; + } + if (adev->psp.asd_fw) { + release_firmware(adev->psp.asd_fw); + adev->psp.asd_fw = NULL; + } + if (adev->psp.ta_fw) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + } if (adev->asic_type == CHIP_NAVI10) psp_sysfs_fini(adev); @@ -409,11 +415,28 @@ static int psp_clear_vf_fw(struct psp_context *psp) return ret; } +static bool psp_skip_tmr(struct psp_context *psp) +{ + switch (psp->adev->asic_type) { + case CHIP_NAVI12: + case CHIP_SIENNA_CICHLID: + return true; + default: + return false; + } +} + static int psp_tmr_load(struct psp_context *psp) { int ret; struct psp_gfx_cmd_resp *cmd; + /* For Navi12 and CHIP_SIENNA_CICHLID SRIOV, do not set up TMR. + * Already set up by host driver. + */ + if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp)) + return 0; + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); if (!cmd) return -ENOMEM; -- cgit v1.2.3 From 74b3595913cc22efe77dbdf2f00bf33b9243f566 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Thu, 30 Jul 2020 18:09:47 +0800 Subject: drm/amdgpu: enable GFXOFF for navy_flounder Enable GFXOFF for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Likun Gao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 1 + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index ca16f01956d3..fe8ccc9be682 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7529,6 +7529,7 @@ static int gfx_v10_0_set_powergating_state(void *handle, case CHIP_NAVI14: case CHIP_NAVI12: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: amdgpu_gfx_off_ctrl(adev, enable); break; default: diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index a9453ec01619..7d7de854a826 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -1029,6 +1029,7 @@ int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) case CHIP_NAVI14: case CHIP_NAVI12: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) return 0; if (enable) -- cgit v1.2.3 From 2456c290a7889be492cb96092b62d16c11176f72 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jul 2020 11:02:30 -0400 Subject: Revert "drm/amdgpu: Fix NULL dereference in dpm sysfs handlers" This regressed some working configurations so revert it. Will fix this properly for 5.9 and backport then. This reverts commit 38e0c89a19fd13f28d2b4721035160a3e66e270b. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f44157daf3ec..576e3ac98365 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -872,7 +872,8 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, tmp_str++; while (isspace(*++tmp_str)); - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; @@ -1165,7 +1166,8 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) memcpy(buf_cpy, buf, bytes); buf_cpy[bytes] = '\0'; tmp = buf_cpy; - while ((sub_str = strsep(&tmp, delimiter)) != NULL) { + while (tmp[0]) { + sub_str = strsep(&tmp, delimiter); if (strlen(sub_str)) { ret = kstrtol(sub_str, 0, &level); if (ret) @@ -1858,7 +1860,8 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, i++; memcpy(buf_cpy, buf, count-i); tmp_str = buf_cpy; - while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; -- cgit v1.2.3 From 522ec6e0eed0ab0678e7d5b5bf00487dfe83f7ce Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Thu, 30 Jul 2020 18:04:33 -0400 Subject: drm/amdkfd: Replace bitmask with event idx in SMI event msg Event bitmask is a 64-bit mask with only 1 bit set. Sending this event bitmask in KFD SMI event message is both wasteful of memory and potentially limiting to only 64 events. Instead send event index in SMI event message. Please note this change does not break the ABI for the two event types defined so far. The new index is identical to the mask used before. Signed-off-by: Mukul Joshi Suggested-by: Felix Kuehling Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 24 +++++++++++++----------- include/uapi/linux/kfd_ioctl.h | 10 +++++++--- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 86c2c3e97944..4d4b6e3ab697 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -149,7 +149,7 @@ static int kfd_smi_ev_release(struct inode *inode, struct file *filep) return 0; } -static void add_event_to_kfifo(struct kfd_dev *dev, unsigned long long smi_event, +static void add_event_to_kfifo(struct kfd_dev *dev, unsigned int smi_event, char *event_msg, int len) { struct kfd_smi_client *client; @@ -157,14 +157,15 @@ static void add_event_to_kfifo(struct kfd_dev *dev, unsigned long long smi_event rcu_read_lock(); list_for_each_entry_rcu(client, &dev->smi_clients, list) { - if (!(READ_ONCE(client->events) & smi_event)) + if (!(READ_ONCE(client->events) & + KFD_SMI_EVENT_MASK_FROM_INDEX(smi_event))) continue; spin_lock(&client->lock); if (kfifo_avail(&client->fifo) >= len) { kfifo_in(&client->fifo, event_msg, len); wake_up_all(&client->wait_queue); } else { - pr_debug("smi_event(EventID: %llu): no space left\n", + pr_debug("smi_event(EventID: %u): no space left\n", smi_event); } spin_unlock(&client->lock); @@ -180,21 +181,21 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, /* * ThermalThrottle msg = throttle_bitmask(8): * thermal_interrupt_count(16): - * 16 bytes event + 1 byte space + 8 byte throttle_bitmask + + * 1 byte event + 1 byte space + 8 byte throttle_bitmask + * 1 byte : + 16 byte thermal_interupt_counter + 1 byte \n + - * 1 byte \0 = 44 + * 1 byte \0 = 29 */ - char fifo_in[44]; + char fifo_in[29]; int len; if (list_empty(&dev->smi_clients)) return; - len = snprintf(fifo_in, 44, "%x %x:%llx\n", + len = snprintf(fifo_in, 29, "%x %x:%llx\n", KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, atomic64_read(&adev->smu.throttle_int_counter)); - add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); + add_event_to_kfifo(dev, KFD_SMI_EVENT_THERMAL_THROTTLE, fifo_in, len); } void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) @@ -202,9 +203,10 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) struct amdgpu_device *adev = (struct amdgpu_device *)dev->kgd; struct amdgpu_task_info task_info; /* VmFault msg = (hex)uint32_pid(8) + :(1) + task name(16) = 25 */ - /* 16 bytes event + 1 byte space + 25 bytes msg + 1 byte \n = 43 + /* 1 byte event + 1 byte space + 25 bytes msg + 1 byte \n + + * 1 byte \0 = 29 */ - char fifo_in[43]; + char fifo_in[29]; int len; if (list_empty(&dev->smi_clients)) @@ -216,7 +218,7 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) if (!task_info.pid) return; - len = snprintf(fifo_in, 43, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, + len = snprintf(fifo_in, 29, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, task_info.pid, task_info.task_name); add_event_to_kfifo(dev, KFD_SMI_EVENT_VMFAULT, fifo_in, len); diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index df6c7a43aadc..cb1f963a84e0 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -449,9 +449,13 @@ struct kfd_ioctl_import_dmabuf_args { /* * KFD SMI(System Management Interface) events */ -/* Event type (defined by bitmask) */ -#define KFD_SMI_EVENT_VMFAULT 0x0000000000000001 -#define KFD_SMI_EVENT_THERMAL_THROTTLE 0x0000000000000002 +enum kfd_smi_event { + KFD_SMI_EVENT_NONE = 0, /* not used */ + KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ + KFD_SMI_EVENT_THERMAL_THROTTLE = 2, +}; + +#define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) struct kfd_ioctl_smi_events_args { __u32 gpuid; /* to KFD */ -- cgit v1.2.3 From acc0204cdb8e60d2e57053ed766d8280eb01118b Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Tue, 21 Jul 2020 18:02:00 +0800 Subject: drm/amdgpu: add bad page count threshold in module parameter(v3) bad_page_threshold could be configured to enable/disable the associated bad page retirement feature in RAS. When it's -1, ras will use typical bad page failure value to handle bad page retirement. When it's 0, disable bad page retirement, and no bad page will be recorded and saved. For other valid value, driver will use this manual value as the threshold value of totoal bad pages. v2: correct documentation of this parameter. v3: remove confused statement in documentation. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 11 +++++++++++ 2 files changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 58e39429395f..e2eed5c630fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -178,6 +178,7 @@ extern uint amdgpu_dm_abm_level; extern struct amdgpu_mgpu_info mgpu_info; extern int amdgpu_ras_enable; extern uint amdgpu_ras_mask; +extern int amdgpu_bad_page_threshold; extern int amdgpu_async_gfx_ring; extern int amdgpu_mcbp; extern int amdgpu_discovery; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 26127c7d2f32..dc47549641e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -156,6 +156,7 @@ struct amdgpu_mgpu_info mgpu_info = { }; int amdgpu_ras_enable = -1; uint amdgpu_ras_mask = 0xffffffff; +int amdgpu_bad_page_threshold = -1; /** * DOC: vramlimit (int) @@ -765,6 +766,16 @@ module_param_named(tmz, amdgpu_tmz, int, 0444); MODULE_PARM_DESC(reset_method, "GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco)"); module_param_named(reset_method, amdgpu_reset_method, int, 0444); +/** + * DOC: bad_page_threshold (int) + * Bad page threshold is to specify the threshold value of faulty pages + * detected by RAS ECC, that may result in GPU entering bad status if total + * faulty pages by ECC exceed threshold value and leave it for user's further + * check. + */ +MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); +module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); + static const struct pci_device_id pciidlist[] = { #ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, -- cgit v1.2.3 From c84d46707ebbfc303268e27d5aeb8bb4e6d5b1ff Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Wed, 22 Jul 2020 10:00:27 +0800 Subject: drm/amdgpu: validate bad page threshold in ras(v3) Bad page threshold value should be valid in the range between -1 and max records length of eeprom. It could determine when saved bad pages exceed threshold value, and proceed corresponding actions. v2: When using the default typical value, it should be min value between typical value and eeprom max records length. v3: drop the case of setting bad_page_cnt_threshold to be 0xFFFFFFFF, as it confuses user. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 48 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 5 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 2 ++ 4 files changed, 58 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 5680f7eafcb1..6660094a1063 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -69,6 +69,9 @@ const char *ras_block_string[] = { /* inject address is 52 bits */ #define RAS_UMC_INJECT_ADDR_LIMIT (0x1ULL << 52) +/* typical ECC bad page rate(1 bad page per 100MB VRAM) */ +#define RAS_BAD_PAGE_RATE (100 * 1024 * 1024ULL) + enum amdgpu_ras_retire_page_reservation { AMDGPU_RAS_RETIRE_PAGE_RESERVED, AMDGPU_RAS_RETIRE_PAGE_PENDING, @@ -1699,6 +1702,47 @@ out: return ret; } +static void amdgpu_ras_validate_threshold(struct amdgpu_device *adev, + uint32_t max_length) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + int tmp_threshold = amdgpu_bad_page_threshold; + u64 val; + + /* + * Justification of value bad_page_cnt_threshold in ras structure + * + * Generally, -1 <= amdgpu_bad_page_threshold <= max record length + * in eeprom, and introduce two scenarios accordingly. + * + * Bad page retirement enablement: + * - If amdgpu_bad_page_threshold = -1, + * bad_page_cnt_threshold = typical value by formula. + * + * - When the value from user is 0 < amdgpu_bad_page_threshold < + * max record length in eeprom, use it directly. + * + * Bad page retirement disablement: + * - If amdgpu_bad_page_threshold = 0, bad page retirement + * functionality is disabled, and bad_page_cnt_threshold will + * take no effect. + */ + + if (tmp_threshold < -1) + tmp_threshold = -1; + else if (tmp_threshold > max_length) + tmp_threshold = max_length; + + if (tmp_threshold == -1) { + val = adev->gmc.mc_vram_size; + do_div(val, RAS_BAD_PAGE_RATE); + con->bad_page_cnt_threshold = min(lower_32_bits(val), + max_length); + } else { + con->bad_page_cnt_threshold = tmp_threshold; + } +} + /* called in gpu recovery/init */ int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev) { @@ -1776,6 +1820,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_err_handler_data **data; + uint32_t max_eeprom_records_len = 0; int ret; if (con) @@ -1794,6 +1839,9 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) atomic_set(&con->in_recovery, 0); con->adev = adev; + max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); + amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); + ret = amdgpu_ras_eeprom_init(&con->eeprom_control); if (ret) goto free; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index b2667342cf67..4672649a9293 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -336,6 +336,9 @@ struct amdgpu_ras { struct amdgpu_ras_eeprom_control eeprom_control; bool error_query_ready; + + /* bad page count threshold */ + uint32_t bad_page_cnt_threshold; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index c0096097bbcf..a2c982b1eac6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -499,6 +499,11 @@ free_buff: return ret == num ? 0 : -EIO; } +inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void) +{ + return EEPROM_MAX_RECORD_NUM; +} + /* Used for testing if bugs encountered */ #if 0 void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 9e7d640920fb..e285e8cafd48 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -84,6 +84,8 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, bool write, int num); +inline uint32_t amdgpu_ras_eeprom_get_record_max_length(void); + void amdgpu_ras_eeprom_test(struct amdgpu_ras_eeprom_control *control); #endif // _AMDGPU_RAS_EEPROM_H -- cgit v1.2.3 From 1d6a9d122d2c7817ad1bae0e59c8a29450c2b14d Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 23 Jul 2020 15:35:53 +0800 Subject: drm/amdgpu: add bad gpu tag definition This tag will be hired for bad gpu detection in eeprom's access. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index a2c982b1eac6..35c0c849d49b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -46,6 +46,9 @@ #define EEPROM_TABLE_HDR_VAL 0x414d4452 #define EEPROM_TABLE_VER 0x00010000 +/* Bad GPU tag ‘BADG’ */ +#define EEPROM_TABLE_HDR_BAD 0x42414447 + /* Assume 2 Mbit size */ #define EEPROM_SIZE_BYTES 256000 #define EEPROM_PAGE__SIZE_BYTES 256 -- cgit v1.2.3 From b82e65a93510465cb4c203c938245f137a4e95dc Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 23 Jul 2020 15:42:19 +0800 Subject: drm/amdgpu: break driver init process when it's bad GPU(v5) When retrieving bad gpu tag from eeprom, GPU init should fail as the GPU needs to be retired for further check. v2: Fix spelling typo, correct the condition to detect bad gpu tag and refine error message. v3: Refine function argument name. v4: Fix missing check of returning value of i2c initialization error case. v5: Use dev_err to print PCI information in dmesg instead of DRM_ERROR. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 +++++++++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 18 ++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 10 +++++++++- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 3 ++- 4 files changed, 36 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 40caa7437ce2..905c5ab486a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2055,13 +2055,19 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev) * it should be called after amdgpu_device_ip_hw_init_phase2 since * for some ASICs the RAS EEPROM code relies on SMU fully functioning * for I2C communication which only true at this point. - * recovery_init may fail, but it can free all resources allocated by - * itself and its failure should not stop amdgpu init process. + * + * amdgpu_ras_recovery_init may fail, but the upper only cares the + * failure from bad gpu situation and stop amdgpu init process + * accordingly. For other failed cases, it will still release all + * the resource and print error message, rather than returning one + * negative value to upper level. * * Note: theoretically, this should be called before all vram allocations * to protect retired page from abusing */ - amdgpu_ras_recovery_init(adev); + r = amdgpu_ras_recovery_init(adev); + if (r) + goto init_failed; if (adev->gmc.xgmi.num_physical_nodes > 1) amdgpu_xgmi_add_device(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 6660094a1063..1a1652ea76b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1821,6 +1821,7 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_err_handler_data **data; uint32_t max_eeprom_records_len = 0; + bool exc_err_limit = false; int ret; if (con) @@ -1842,8 +1843,12 @@ int amdgpu_ras_recovery_init(struct amdgpu_device *adev) max_eeprom_records_len = amdgpu_ras_eeprom_get_record_max_length(); amdgpu_ras_validate_threshold(adev, max_eeprom_records_len); - ret = amdgpu_ras_eeprom_init(&con->eeprom_control); - if (ret) + ret = amdgpu_ras_eeprom_init(&con->eeprom_control, &exc_err_limit); + /* + * This calling fails when exc_err_limit is true or + * ret != 0. + */ + if (exc_err_limit || ret) goto free; if (con->eeprom_control.num_recs) { @@ -1867,6 +1872,15 @@ free: out: dev_warn(adev->dev, "Failed to initialize ras recovery!\n"); + /* + * Except error threshold exceeding case, other failure cases in this + * function would not fail amdgpu driver init. + */ + if (!exc_err_limit) + ret = 0; + else + ret = -EINVAL; + return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 35c0c849d49b..da8b35a5b41c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -241,7 +241,8 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) } -int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) +int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit) { int ret = 0; struct amdgpu_device *adev = to_amdgpu_device(control); @@ -254,6 +255,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) .buf = buff, }; + *exceed_err_limit = false; + /* Verify i2c adapter is initialized */ if (!adev->pm.smu_i2c.algo) return -ENOENT; @@ -282,6 +285,11 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control) DRM_DEBUG_DRIVER("Found existing EEPROM table with %d records", control->num_recs); + } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && + (amdgpu_bad_page_threshold != 0)) { + *exceed_err_limit = true; + dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " + "disabling the GPU.\n"); } else { DRM_INFO("Creating new EEPROM table"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index e285e8cafd48..9839b4ea5e18 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -76,7 +76,8 @@ struct eeprom_table_record { unsigned char mcumc_id; }__attribute__((__packed__)); -int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control); +int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit); int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, -- cgit v1.2.3 From 35cd2cdadbccf08e9b4d5a8fca4914dc37ab48e0 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 23 Jul 2020 15:50:42 +0800 Subject: drm/amdgpu: skip bad page reservation once issuing from eeprom write Once the ras recovery is issued from eeprom write itself, bad page reservation should be ignored, otherwise, recursive calling of writting to eeprom would happen. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 14 +++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 1a1652ea76b0..d081de232c66 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -62,8 +62,6 @@ const char *ras_block_string[] = { #define ras_err_str(i) (ras_error_string[ffs(i)]) #define ras_block_str(i) (ras_block_string[i]) -#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS 1 -#define AMDGPU_RAS_FLAG_INIT_NEED_RESET 2 #define RAS_DEFAULT_FLAGS (AMDGPU_RAS_FLAG_INIT_BY_VBIOS) /* inject address is 52 bits */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 4672649a9293..cf9f60202334 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -31,6 +31,10 @@ #include "ta_ras_if.h" #include "amdgpu_ras_eeprom.h" +#define AMDGPU_RAS_FLAG_INIT_BY_VBIOS (0x1 << 0) +#define AMDGPU_RAS_FLAG_INIT_NEED_RESET (0x1 << 1) +#define AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV (0x1 << 2) + enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__UMC = 0, AMDGPU_RAS_BLOCK__SDMA, @@ -503,10 +507,14 @@ static inline int amdgpu_ras_reset_gpu(struct amdgpu_device *adev) { struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - /* save bad page to eeprom before gpu reset, - * i2c may be unstable in gpu reset + /* + * Save bad page to eeprom before gpu reset, i2c may be unstable + * in gpu reset. + * + * Also, exclude the case when ras recovery issuer is + * eeprom page write itself. */ - if (in_task()) + if (!(ras->flags & AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV) && in_task()) amdgpu_ras_reserve_bad_pages(adev); if (atomic_cmpxchg(&ras->in_recovery, 0, 1) == 0) -- cgit v1.2.3 From 9c06f91ff2349da67651cddf88507aa967b58b08 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 23 Jul 2020 16:05:00 +0800 Subject: drm/amdgpu: schedule ras recovery when reaching bad page threshold(v2) Once the bad page saved to eeprom reaches the configured threshold, ras recovery will be issued to notify user. v2: Fix spelling typo. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 37 +++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index da8b35a5b41c..461dfd22bc1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -394,8 +394,10 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, int i, ret = 0; struct i2c_msg *msgs, *msg; unsigned char *buffs, *buff; + bool sched_ras_recovery = false; struct eeprom_table_record *record; struct amdgpu_device *adev = to_amdgpu_device(control); + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); if (adev->asic_type != CHIP_VEGA20 && adev->asic_type != CHIP_ARCTURUS) return 0; @@ -413,11 +415,30 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, goto free_buff; } + /* + * If saved bad pages number exceeds the bad page threshold for + * the whole VRAM, update table header to mark the BAD GPU tag + * and schedule one ras recovery after eeprom write is done, + * this can avoid the missing for latest records. + * + * This new header will be picked up and checked in the bootup + * by ras recovery, which may break bootup process to notify + * user this GPU is in bad state and to retire such GPU for + * further check. + */ + if (write && (amdgpu_bad_page_threshold != 0) && + ((control->num_recs + num) >= ras->bad_page_cnt_threshold)) { + dev_warn(adev->dev, + "Saved bad pages(%d) reaches threshold value(%d).\n", + control->num_recs + num, ras->bad_page_cnt_threshold); + control->tbl_hdr.header = EEPROM_TABLE_HDR_BAD; + sched_ras_recovery = true; + } + /* In case of overflow just start from beginning to not lose newest records */ if (write && (control->next_addr + EEPROM_TABLE_RECORD_SIZE * num > EEPROM_SIZE_BYTES)) control->next_addr = EEPROM_RECORD_START; - /* * TODO Currently makes EEPROM writes for each record, this creates * internal fragmentation. Optimized the code to do full page write of @@ -493,6 +514,20 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, __update_tbl_checksum(control, records, num, old_hdr_byte_sum); __update_table_header(control, buffs); + + if (sched_ras_recovery) { + /* + * Before scheduling ras recovery, assert the related + * flag first, which shall bypass common bad page + * reservation execution in amdgpu_ras_reset_gpu. + */ + amdgpu_ras_get_context(adev)->flags |= + AMDGPU_RAS_FLAG_SKIP_BAD_PAGE_RESV; + + dev_warn(adev->dev, "Conduct ras recovery due to bad " + "page threshold reached.\n"); + amdgpu_ras_reset_gpu(adev); + } } else if (!__validate_tbl_checksum(control, records, num)) { DRM_WARN("EEPROM Table checksum mismatch!"); /* TODO Uncomment when EEPROM read/write is relliable */ -- cgit v1.2.3 From e8fbaf03429d085b05e66b153a8363b746c94b43 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 23 Jul 2020 16:20:02 +0800 Subject: drm/amdgpu: break GPU recovery once it's in bad state(v4) When GPU executes recovery and retriving bad GPU tag from external eerpom device, the recovery will be broken and error message is printed as well for user's awareness. v2: Refine warning message in threshold reaching case, and fix spelling typo. v3: Fix explicit calling of bad gpu. v4: Rename function names. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 +++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 16 +++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 40 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h | 4 +++ 5 files changed, 79 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 905c5ab486a1..d01d7969d47b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4125,8 +4125,23 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, amdgpu_fbdev_set_suspend(tmp_adev, 0); - /* must succeed. */ - amdgpu_ras_resume(tmp_adev); + /* + * The GPU enters bad state once faulty pages + * by ECC has reached the threshold, and ras + * recovery is scheduled next. So add one check + * here to break recovery if it indeed exceeds + * bad page threshold, and remind user to + * retire this GPU or setting one bigger + * bad_page_threshold value to fix this once + * probing driver again. + */ + if (!amdgpu_ras_check_err_threshold(tmp_adev)) { + /* must succeed. */ + amdgpu_ras_resume(tmp_adev); + } else { + r = -EINVAL; + goto out; + } /* Update PSP FW topology after reset */ if (hive && tmp_adev->gmc.xgmi.num_physical_nodes > 1) @@ -4134,7 +4149,6 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, } } - out: if (!r) { amdgpu_irq_gpu_reset_resume_helper(tmp_adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index d081de232c66..ab65dfd71927 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2205,3 +2205,19 @@ bool amdgpu_ras_need_emergency_restart(struct amdgpu_device *adev) return false; } + +bool amdgpu_ras_check_err_threshold(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + bool exc_err_limit = false; + + if (con && (amdgpu_bad_page_threshold != 0)) + amdgpu_ras_eeprom_check_err_threshold(&con->eeprom_control, + &exc_err_limit); + + /* + * We are only interested in variable exc_err_limit, + * as it says if GPU is in bad state or not. + */ + return exc_err_limit; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index cf9f60202334..70a6fca73617 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -497,6 +497,8 @@ void amdgpu_ras_suspend(struct amdgpu_device *adev); unsigned long amdgpu_ras_query_error_count(struct amdgpu_device *adev, bool is_ce); +bool amdgpu_ras_check_err_threshold(struct amdgpu_device *adev); + /* error handling functions */ int amdgpu_ras_add_bad_pages(struct amdgpu_device *adev, struct eeprom_table_record *bps, int pages); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 461dfd22bc1c..7848a426c95b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -386,6 +386,46 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address) return curr_address; } +int amdgpu_ras_eeprom_check_err_threshold( + struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + unsigned char buff[EEPROM_ADDRESS_SIZE + + EEPROM_TABLE_HEADER_SIZE] = { 0 }; + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + struct i2c_msg msg = { + .addr = control->i2c_address, + .flags = I2C_M_RD, + .len = EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE, + .buf = buff, + }; + int ret; + + *exceed_err_limit = false; + + /* read EEPROM table header */ + mutex_lock(&control->tbl_mutex); + ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); + if (ret < 1) { + dev_err(adev->dev, "Failed to read EEPROM table header.\n"); + goto err; + } + + __decode_table_header_from_buff(hdr, &buff[2]); + + if (hdr->header == EEPROM_TABLE_HDR_BAD) { + dev_warn(adev->dev, "This GPU is in BAD status."); + dev_warn(adev->dev, "Please retire it or setting one bigger " + "threshold value when reloading driver.\n"); + *exceed_err_limit = true; + } + +err: + mutex_unlock(&control->tbl_mutex); + return 0; +} + int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records, bool write, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h index 9839b4ea5e18..c7a5e5c7c61e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h @@ -80,6 +80,10 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, bool *exceed_err_limit); int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control); +int amdgpu_ras_eeprom_check_err_threshold( + struct amdgpu_ras_eeprom_control *control, + bool *exceed_err_limit); + int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct eeprom_table_record *records, bool write, -- cgit v1.2.3 From bf0b91b78f002faa1be1902a75eeb0797f9fbcf3 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Wed, 22 Jul 2020 10:37:01 +0800 Subject: drm/amdgpu: restore ras flags when user resets eeprom(v2) RAS flags needs to be cleaned as well when user requires one clean eeprom. v2: RAS flags shall be restored after eeprom reset succeeds. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index ab65dfd71927..19ac2e6ad60e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -368,12 +368,19 @@ static ssize_t amdgpu_ras_debugfs_ctrl_write(struct file *f, const char __user * static ssize_t amdgpu_ras_debugfs_eeprom_write(struct file *f, const char __user *buf, size_t size, loff_t *pos) { - struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; + struct amdgpu_device *adev = + (struct amdgpu_device *)file_inode(f)->i_private; int ret; - ret = amdgpu_ras_eeprom_reset_table(&adev->psp.ras.ras->eeprom_control); + ret = amdgpu_ras_eeprom_reset_table( + &(amdgpu_ras_get_context(adev)->eeprom_control)); - return ret == 1 ? size : -EIO; + if (ret == 1) { + amdgpu_ras_get_context(adev)->flags = RAS_DEFAULT_FLAGS; + return size; + } else { + return -EIO; + } } static const struct file_operations amdgpu_ras_debugfs_ctrl_ops = { -- cgit v1.2.3 From eb0c3cd48f5f27abf3ba92bd142b71ef76229706 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 31 Jul 2020 14:39:57 +0800 Subject: drm/amdgpu: add one definition for RAS's sysfs/debugfs name(v2) Add one definition for the RAS module's FS name. It's used in both debugfs and sysfs cases. v2: Use static variable instead of macro definition. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 19ac2e6ad60e..08869e4a5374 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -34,6 +34,8 @@ #include "amdgpu_xgmi.h" #include "ivsrcid/nbio/irqsrcs_nbif_7_4.h" +static const char *RAS_FS_NAME = "ras"; + const char *ras_error_string[] = { "none", "parity", @@ -1037,7 +1039,7 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) NULL }; struct attribute_group group = { - .name = "ras", + .name = RAS_FS_NAME, .attrs = attrs, .bin_attrs = bin_attrs, }; @@ -1078,7 +1080,7 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) NULL }; struct attribute_group group = { - .name = "ras", + .name = RAS_FS_NAME, .attrs = attrs, .bin_attrs = bin_attrs, }; @@ -1113,7 +1115,7 @@ int amdgpu_ras_sysfs_create(struct amdgpu_device *adev, if (sysfs_add_file_to_group(&adev->dev->kobj, &obj->sysfs_attr.attr, - "ras")) { + RAS_FS_NAME)) { put_obj(obj); return -EINVAL; } @@ -1133,7 +1135,7 @@ int amdgpu_ras_sysfs_remove(struct amdgpu_device *adev, sysfs_remove_file_from_group(&adev->dev->kobj, &obj->sysfs_attr.attr, - "ras"); + RAS_FS_NAME); obj->attr_inuse = 0; put_obj(obj); @@ -1179,7 +1181,7 @@ static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct drm_minor *minor = adev->ddev->primary; - con->dir = debugfs_create_dir("ras", minor->debugfs_root); + con->dir = debugfs_create_dir(RAS_FS_NAME, minor->debugfs_root); debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir, adev, &amdgpu_ras_debugfs_ctrl_ops); debugfs_create_file("ras_eeprom_reset", S_IWUGO | S_IRUGO, con->dir, -- cgit v1.2.3 From f848159b570ecdcd157ad5b52eb58e5cb3a075a7 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Fri, 31 Jul 2020 15:06:32 +0800 Subject: drm/amdgpu: decouple sysfs creating of bad page node Bad page information should not be exposed by sysfs when bad page retirement is disabled, so decouple it from ras sysfs group creating, and add one guard before creating. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 63 ++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 08869e4a5374..3949470edbb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1027,6 +1027,33 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev, return scnprintf(buf, PAGE_SIZE, "feature mask: 0x%x\n", con->features); } +static void amdgpu_ras_sysfs_add_bad_page_node(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + struct attribute_group group; + struct bin_attribute *bin_attrs[] = { + &con->badpages_attr, + NULL, + }; + + con->badpages_attr = (struct bin_attribute) { + .attr = { + .name = "gpu_vram_bad_pages", + .mode = S_IRUGO, + }, + .size = 0, + .private = NULL, + .read = amdgpu_ras_sysfs_badpages_read, + }; + + group.name = RAS_FS_NAME; + group.bin_attrs = bin_attrs; + + sysfs_bin_attr_init(bin_attrs[0]); + + sysfs_update_group(&adev->dev->kobj, &group); +} + static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -1034,14 +1061,9 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) &con->features_attr.attr, NULL }; - struct bin_attribute *bin_attrs[] = { - &con->badpages_attr, - NULL - }; struct attribute_group group = { .name = RAS_FS_NAME, .attrs = attrs, - .bin_attrs = bin_attrs, }; con->features_attr = (struct device_attribute) { @@ -1052,22 +1074,20 @@ static int amdgpu_ras_sysfs_create_feature_node(struct amdgpu_device *adev) .show = amdgpu_ras_sysfs_features_read, }; - con->badpages_attr = (struct bin_attribute) { - .attr = { - .name = "gpu_vram_bad_pages", - .mode = S_IRUGO, - }, - .size = 0, - .private = NULL, - .read = amdgpu_ras_sysfs_badpages_read, - }; - sysfs_attr_init(attrs[0]); - sysfs_bin_attr_init(bin_attrs[0]); return sysfs_create_group(&adev->dev->kobj, &group); } +static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev) +{ + struct amdgpu_ras *con = amdgpu_ras_get_context(adev); + + sysfs_remove_file_from_group(&adev->dev->kobj, + &con->badpages_attr.attr, + RAS_FS_NAME); +} + static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); @@ -1075,14 +1095,9 @@ static int amdgpu_ras_sysfs_remove_feature_node(struct amdgpu_device *adev) &con->features_attr.attr, NULL }; - struct bin_attribute *bin_attrs[] = { - &con->badpages_attr, - NULL - }; struct attribute_group group = { .name = RAS_FS_NAME, .attrs = attrs, - .bin_attrs = bin_attrs, }; sysfs_remove_group(&adev->dev->kobj, &group); @@ -1151,6 +1166,9 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev) amdgpu_ras_sysfs_remove(adev, &obj->head); } + if (amdgpu_bad_page_threshold != 0) + amdgpu_ras_sysfs_remove_bad_page_node(adev); + amdgpu_ras_sysfs_remove_feature_node(adev); return 0; @@ -1278,6 +1296,9 @@ static int amdgpu_ras_fs_init(struct amdgpu_device *adev) { amdgpu_ras_sysfs_create_feature_node(adev); + if (amdgpu_bad_page_threshold != 0) + amdgpu_ras_sysfs_add_bad_page_node(adev); + return 0; } -- cgit v1.2.3 From a219ecbb83859940bd1959180bd555f28f2043a7 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 27 Jul 2020 14:56:27 +0800 Subject: drm/amdgpu: disable page reservation when amdgpu_bad_page_threshold = 0 When amdgpu_bad_page_threshold = 0, bad page reservation stuffs are skipped in either UMC ECC irq or page retirement calling of sync flood isr. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 3949470edbb0..89cb0ae9da9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1676,7 +1676,7 @@ static int amdgpu_ras_load_bad_pages(struct amdgpu_device *adev) int ret = 0; /* no bad page record, skip eeprom access */ - if (!control->num_recs) + if (!control->num_recs || (amdgpu_bad_page_threshold == 0)) return ret; bps = kcalloc(control->num_recs, sizeof(*bps), GFP_KERNEL); @@ -1780,7 +1780,8 @@ int amdgpu_ras_reserve_bad_pages(struct amdgpu_device *adev) struct amdgpu_bo *bo = NULL; int i, ret = 0; - if (!con || !con->eh_data) + /* Not reserve bad page when amdgpu_bad_page_threshold == 0. */ + if (!con || !con->eh_data || (amdgpu_bad_page_threshold == 0)) return 0; mutex_lock(&con->recovery_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c index af1b1ccf613c..262baf0f61ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c @@ -125,8 +125,9 @@ int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev, "detected in UMC block\n", err_data->ue_count); - if (err_data->err_addr_cnt && - amdgpu_ras_add_bad_pages(adev, err_data->err_addr, + if ((amdgpu_bad_page_threshold != 0) && + err_data->err_addr_cnt && + amdgpu_ras_add_bad_pages(adev, err_data->err_addr, err_data->err_addr_cnt)) dev_warn(adev->dev, "Failed to add ras bad page!\n"); -- cgit v1.2.3 From 9b856defbe355f886f99777e667506841bd267a8 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Mon, 27 Jul 2020 15:51:05 +0800 Subject: drm/amdgpu: update eeprom once specifying one bigger threshold(v3) During driver's probe, when it hits bad gpu tag in eeprom i2c init calling(the tag was set when reported bad page reaches bad page threshold in last driver's working loop), there are some strategys to deal with the cases: 1. when the module parameter amdgpu_bad_page_threshold = 0, that means page retirement feature is disabled, so just resetting the eeprom is fine. 2. When amdgpu_bad_page_threshold is not 0, and moreover, user sets one bigger valid data in order to make current boot up succeeds, correct eeprom header tag and do not break booting. 3. For other cases, driver's probe will be broken. v2: Just update eeprom header tag instead of resetting the whole table header when user sets one bigger threshold data. v3: Use dev_info/dev_err to print PCI device information, which helps in mGPU case. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 30 ++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index 7848a426c95b..e5e3ed113d63 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -216,6 +216,24 @@ static bool __validate_tbl_checksum(struct amdgpu_ras_eeprom_control *control, return true; } +static int amdgpu_ras_eeprom_correct_header_tag( + struct amdgpu_ras_eeprom_control *control, + uint32_t header) +{ + unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE]; + struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + int ret = 0; + + memset(buff, 0, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE); + + mutex_lock(&control->tbl_mutex); + hdr->header = header; + ret = __update_table_header(control, buff); + mutex_unlock(&control->tbl_mutex); + + return ret; +} + int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control) { unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; @@ -248,6 +266,7 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, struct amdgpu_device *adev = to_amdgpu_device(control); unsigned char buff[EEPROM_ADDRESS_SIZE + EEPROM_TABLE_HEADER_SIZE] = { 0 }; struct amdgpu_ras_eeprom_table_header *hdr = &control->tbl_hdr; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); struct i2c_msg msg = { .addr = 0, .flags = I2C_M_RD, @@ -287,9 +306,16 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, } else if ((hdr->header == EEPROM_TABLE_HDR_BAD) && (amdgpu_bad_page_threshold != 0)) { - *exceed_err_limit = true; - dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " + if (ras->bad_page_cnt_threshold > control->num_recs) { + dev_info(adev->dev, "Using one valid bigger bad page " + "threshold and correcting eeprom header tag.\n"); + ret = amdgpu_ras_eeprom_correct_header_tag(control, + EEPROM_TABLE_HDR_VAL); + } else { + *exceed_err_limit = true; + dev_err(adev->dev, "Exceeding the bad_page_threshold parameter, " "disabling the GPU.\n"); + } } else { DRM_INFO("Creating new EEPROM table"); -- cgit v1.2.3 From a300de40f66b87fa90703c94ffb22917f98eb902 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Mon, 27 Jul 2020 15:20:12 +0800 Subject: drm/amdgpu: introduce a new parameter to configure how many KCQ we want(v5) what: the MQD's save and restore of KCQ (kernel compute queue) cost lots of clocks during world switch which impacts a lot to multi-VF performance how: introduce a paramter to control the number of KCQ to avoid performance drop if there is no kernel compute queue needed notes: this paramter only affects gfx 8/9/10 v2: refine namings v3: choose queues for each ring to that try best to cross pipes evenly. v4: fix indentation some cleanupsin the gfx_compute_queue_acquire() v5: further fix on indentations more cleanupsin gfx_compute_queue_acquire() TODO: in the future we will let hypervisor driver to set this paramter automatically thus no need for user to configure it through modprobe in virtual machine Signed-off-by: Monk Liu Reviewed-by: Felix Kuehling Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 4 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 49 ++++++++++++------------------ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 30 +++++++++--------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 29 +++++++++--------- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 31 ++++++++++--------- 7 files changed, 76 insertions(+), 73 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index e2eed5c630fc..75631b3396a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -202,6 +202,7 @@ extern int amdgpu_si_support; #ifdef CONFIG_DRM_AMDGPU_CIK extern int amdgpu_cik_support; #endif +extern int amdgpu_num_kcq; #define AMDGPU_VM_MAX_NUM_CTX 4096 #define AMDGPU_SG_THRESHOLD (256*1024*1024) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d01d7969d47b..79b0da3e8639 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1199,6 +1199,11 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) amdgpu_gmc_tmz_set(adev); + if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { + amdgpu_num_kcq = 8; + dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid paramter provided by user\n"); + } + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index dc47549641e2..6d66705a1141 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -150,6 +150,7 @@ int amdgpu_noretry; int amdgpu_force_asic_type = -1; int amdgpu_tmz = 0; int amdgpu_reset_method = -1; /* auto */ +int amdgpu_num_kcq = -1; struct amdgpu_mgpu_info mgpu_info = { .mutex = __MUTEX_INITIALIZER(mgpu_info.mutex), @@ -776,6 +777,9 @@ module_param_named(reset_method, amdgpu_reset_method, int, 0444); MODULE_PARM_DESC(bad_page_threshold, "Bad page threshold(-1 = auto(default value), 0 = disable bad page retirement)"); module_param_named(bad_page_threshold, amdgpu_bad_page_threshold, int, 0444); +MODULE_PARM_DESC(num_kcq, "number of kernel compute queue user want to setup (8 if set to greater than 8 or less than 0, only affect gfx 8+)"); +module_param_named(num_kcq, amdgpu_num_kcq, int, 0444); + static const struct pci_device_id pciidlist[] = { #ifdef CONFIG_DRM_AMDGPU_SI {0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 8eff0173360d..0cd9de69932b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -202,40 +202,29 @@ bool amdgpu_gfx_is_high_priority_compute_queue(struct amdgpu_device *adev, void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev) { - int i, queue, pipe, mec; + int i, queue, pipe; bool multipipe_policy = amdgpu_gfx_is_multipipe_capable(adev); - - /* policy for amdgpu compute queue ownership */ - for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) { - queue = i % adev->gfx.mec.num_queue_per_pipe; - pipe = (i / adev->gfx.mec.num_queue_per_pipe) - % adev->gfx.mec.num_pipe_per_mec; - mec = (i / adev->gfx.mec.num_queue_per_pipe) - / adev->gfx.mec.num_pipe_per_mec; - - /* we've run out of HW */ - if (mec >= adev->gfx.mec.num_mec) - break; - - if (multipipe_policy) { - /* policy: amdgpu owns the first two queues of the first MEC */ - if (mec == 0 && queue < 2) - set_bit(i, adev->gfx.mec.queue_bitmap); - } else { - /* policy: amdgpu owns all queues in the first pipe */ - if (mec == 0 && pipe == 0) - set_bit(i, adev->gfx.mec.queue_bitmap); + int max_queues_per_mec = min(adev->gfx.mec.num_pipe_per_mec * + adev->gfx.mec.num_queue_per_pipe, + adev->gfx.num_compute_rings); + + if (multipipe_policy) { + /* policy: make queues evenly cross all pipes on MEC1 only */ + for (i = 0; i < max_queues_per_mec; i++) { + pipe = i % adev->gfx.mec.num_pipe_per_mec; + queue = (i / adev->gfx.mec.num_pipe_per_mec) % + adev->gfx.mec.num_queue_per_pipe; + + set_bit(pipe * adev->gfx.mec.num_queue_per_pipe + queue, + adev->gfx.mec.queue_bitmap); } + } else { + /* policy: amdgpu owns all queues in the given pipe */ + for (i = 0; i < max_queues_per_mec; ++i) + set_bit(i, adev->gfx.mec.queue_bitmap); } - /* update the number of active compute rings */ - adev->gfx.num_compute_rings = - bitmap_weight(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); - - /* If you hit this case and edited the policy, you probably just - * need to increase AMDGPU_MAX_COMPUTE_RINGS */ - if (WARN_ON(adev->gfx.num_compute_rings > AMDGPU_MAX_COMPUTE_RINGS)) - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + dev_dbg(adev->dev, "mec queue bitmap weight=%d\n", bitmap_weight(adev->gfx.mec.queue_bitmap, AMDGPU_MAX_COMPUTE_QUEUES)); } void amdgpu_gfx_graphics_queue_acquire(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index fe8ccc9be682..622f4425bf59 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4022,21 +4022,23 @@ static int gfx_v10_0_mec_init(struct amdgpu_device *adev) amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX10_MEC_HPD_SIZE; - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_GTT, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - gfx_v10_0_mec_fini(adev); - return r; - } + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_GTT, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + gfx_v10_0_mec_fini(adev); + return r; + } - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; @@ -7159,7 +7161,7 @@ static int gfx_v10_0_early_init(void *handle) break; } - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; gfx_v10_0_set_kiq_pm4_funcs(adev); gfx_v10_0_set_ring_funcs(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 8d7208959c95..7df567a6656d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -1343,21 +1343,22 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX8_MEC_HPD_SIZE; + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + return r; + } - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - return r; - } - - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } return 0; } @@ -5294,7 +5295,7 @@ static int gfx_v8_0_early_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; adev->gfx.num_gfx_rings = GFX8_NUM_GFX_RINGS; - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; adev->gfx.funcs = &gfx_v8_0_gfx_funcs; gfx_v8_0_set_ring_funcs(adev); gfx_v8_0_set_irq_funcs(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index e4e751f87092..ef07e59cd426 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -1938,22 +1938,23 @@ static int gfx_v9_0_mec_init(struct amdgpu_device *adev) /* take ownership of the relevant compute queues */ amdgpu_gfx_compute_queue_acquire(adev); mec_hpd_size = adev->gfx.num_compute_rings * GFX9_MEC_HPD_SIZE; + if (mec_hpd_size) { + r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gfx.mec.hpd_eop_obj, + &adev->gfx.mec.hpd_eop_gpu_addr, + (void **)&hpd); + if (r) { + dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); + gfx_v9_0_mec_fini(adev); + return r; + } - r = amdgpu_bo_create_reserved(adev, mec_hpd_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->gfx.mec.hpd_eop_obj, - &adev->gfx.mec.hpd_eop_gpu_addr, - (void **)&hpd); - if (r) { - dev_warn(adev->dev, "(%d) create HDP EOP bo failed\n", r); - gfx_v9_0_mec_fini(adev); - return r; - } - - memset(hpd, 0, mec_hpd_size); + memset(hpd, 0, mec_hpd_size); - amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); - amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_kunmap(adev->gfx.mec.hpd_eop_obj); + amdgpu_bo_unreserve(adev->gfx.mec.hpd_eop_obj); + } mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data; @@ -4625,7 +4626,7 @@ static int gfx_v9_0_early_init(void *handle) adev->gfx.num_gfx_rings = 0; else adev->gfx.num_gfx_rings = GFX9_NUM_GFX_RINGS; - adev->gfx.num_compute_rings = AMDGPU_MAX_COMPUTE_RINGS; + adev->gfx.num_compute_rings = amdgpu_num_kcq; gfx_v9_0_set_kiq_pm4_funcs(adev); gfx_v9_0_set_ring_funcs(adev); gfx_v9_0_set_irq_funcs(adev); -- cgit v1.2.3 From 0ad7a64d69cdbe520d0df80d100cd6b891cc12fb Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 3 Aug 2020 14:24:50 +0800 Subject: drm/amdgpu: enable RAS support for sienna cichlid enabled GECC error injection and query support Reviewed-by: Guchun Chen Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 89cb0ae9da9d..1a55f6f492fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1965,8 +1965,9 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = 0; if (amdgpu_sriov_vf(adev) || !adev->is_atom_fw || - (adev->asic_type != CHIP_VEGA20 && - adev->asic_type != CHIP_ARCTURUS)) + (adev->asic_type != CHIP_VEGA20 && + adev->asic_type != CHIP_ARCTURUS && + adev->asic_type != CHIP_SIENNA_CICHLID)) return; if (amdgpu_atomfirmware_mem_ecc_supported(adev)) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 35d21f330b0a..dd91a93de62a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -633,6 +633,10 @@ static int gmc_v10_0_late_init(void *handle) if (r) return r; + r = amdgpu_gmc_ras_late_init(adev); + if (r) + return r; + return amdgpu_irq_get(adev, &adev->gmc.vm_fault, 0); } -- cgit v1.2.3 From 4bfb74282f064f738abb22734a675326f41c230c Mon Sep 17 00:00:00 2001 From: John Clements Date: Mon, 3 Aug 2020 15:52:52 +0800 Subject: drm/amdgpu: added RAS EEPROM device support check updated RAS EEPROM init/threshold sequences to check for device support Reviewed-by: Guchun Chen Signed-off-by: John Clements Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c index e5e3ed113d63..0e64c39a2372 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c @@ -59,6 +59,15 @@ #define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev +static bool __is_ras_eeprom_supported(struct amdgpu_device *adev) +{ + if ((adev->asic_type == CHIP_VEGA20) || + (adev->asic_type == CHIP_ARCTURUS)) + return true; + + return false; +} + static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev, uint16_t *i2c_addr) { @@ -276,6 +285,9 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control, *exceed_err_limit = false; + if (!__is_ras_eeprom_supported(adev)) + return 0; + /* Verify i2c adapter is initialized */ if (!adev->pm.smu_i2c.algo) return -ENOENT; @@ -430,6 +442,9 @@ int amdgpu_ras_eeprom_check_err_threshold( *exceed_err_limit = false; + if (!__is_ras_eeprom_supported(adev)) + return 0; + /* read EEPROM table header */ mutex_lock(&control->tbl_mutex); ret = i2c_transfer(&adev->pm.smu_i2c, &msg, 1); @@ -465,7 +480,7 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control, struct amdgpu_device *adev = to_amdgpu_device(control); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - if (adev->asic_type != CHIP_VEGA20 && adev->asic_type != CHIP_ARCTURUS) + if (!__is_ras_eeprom_supported(adev)) return 0; buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE, -- cgit v1.2.3 From 734e4c97ab05db4157244284510a9fa45a9e889a Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Wed, 17 Jun 2020 15:28:04 -0400 Subject: drm/amd/display: DSC Slice height debugfs write entry [Why] We need to be able to specify slice height for any connector's DSC [How] Overwrite computed parameters in dsc_cfg, with the value needed/ Overwrites for both SST and MST connectors, but in different places, but the process is identical. Overwrites only if DSC is decided to be enabled on that connector. Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 7 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 93 ++++++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 7 ++ 4 files changed, 107 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 342663fcd44d..26217e5e800d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4670,9 +4670,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, /* Overwrite the stream flag if DSC is enabled through debugfs */ if (aconnector->dsc_settings.dsc_clock_en) stream->timing.flags.DSC = 1; + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_width) stream->timing.dsc_cfg.num_slices_h = DIV_ROUND_UP(stream->timing.h_addressable, - aconnector->dsc_settings.dsc_slice_width); + aconnector->dsc_settings.dsc_slice_width); + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height) + stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable, + aconnector->dsc_settings.dsc_slice_height); } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a06ad133a23a..1a31473d3992 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -345,6 +345,7 @@ struct amdgpu_display_manager { struct dsc_preferred_settings { bool dsc_clock_en; uint32_t dsc_slice_width; + uint32_t dsc_slice_height; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 550138012123..b4c470c75cbe 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1274,6 +1274,22 @@ done: return size; } +/* function: read DSC slice height parameter on the connector + * + * The read function: dp_dsc_slice_height_read + * returns dsc slice height used in the current configuration + * The return is an integer: 0 or other positive number + * + * Access the status with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + * 0 - means that DSC is disabled + * + * Any other number more than zero represents the + * slice height currently used by DSC in pixels + * + */ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1331,6 +1347,82 @@ static ssize_t dp_dsc_slice_height_read(struct file *f, char __user *buf, return result; } +/* function: write DSC slice height parameter + * + * The write function: dp_dsc_slice_height_write + * overwrites automatically generated DSC configuration + * of slice height. + * + * The user has to write the slice height divisible by the + * picture height. + * + * Also the user has to write height in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite slice height (example sets to 128 pixels): + * + * echo 0x80 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + * - To stop overwriting and let driver find the optimal size, + * set the height to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_slice_height + * + */ +static ssize_t dp_dsc_slice_height_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + uint8_t param_nums = 0; + long param[1] = {0}; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_slice_height = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1640,6 +1732,7 @@ static const struct file_operations dp_dsc_slice_width_debugfs_fops = { static const struct file_operations dp_dsc_slice_height_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_slice_height_read, + .write = dp_dsc_slice_height_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index b8a900e963d3..4d74780f21a4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -452,6 +452,7 @@ struct dsc_mst_fairness_params { struct drm_dp_mst_port *port; bool clock_overwrite; uint32_t slice_width_overwrite; + uint32_t slice_height_overwrite; }; struct dsc_mst_fairness_vars { @@ -490,6 +491,11 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( params[i].timing->h_addressable, params[i].slice_width_overwrite); + + if (params[i].slice_height_overwrite) + params[i].timing->dsc_cfg.num_slices_v = DIV_ROUND_UP( + params[i].timing->v_addressable, + params[i].slice_height_overwrite); } else { params[i].timing->flags.DSC = 0; } @@ -707,6 +713,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, if (params[count].clock_overwrite) debugfs_overwrite = true; params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; + params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- cgit v1.2.3 From d8a8258ec1a2b8d99bdc67d03fe62ca5cec98a14 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 20 Jul 2020 16:10:22 -0400 Subject: drm/amd/display: Update virtual stream encoder Signed-off-by: Eric Bernstein Reviewed-by: Dmytro Laktyushkin Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c index b8040da94b9d..944c0327763c 100644 --- a/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/virtual/virtual_stream_encoder.c @@ -87,6 +87,17 @@ static void virtual_enc_dp_set_odm_combine( bool odm_combine) {} +static void virtual_dig_connect_to_otg( + struct stream_encoder *enc, + int tg_inst) +{} + +static void virtual_setup_stereo_sync( + struct stream_encoder *enc, + int tg_inst, + bool enable) +{} + static const struct stream_encoder_funcs virtual_str_enc_funcs = { .dp_set_odm_combine = virtual_enc_dp_set_odm_combine, @@ -114,6 +125,8 @@ static const struct stream_encoder_funcs virtual_str_enc_funcs = { .audio_mute_control = virtual_audio_mute_control, .set_avmute = virtual_stream_encoder_set_avmute, .hdmi_reset_stream_attribute = virtual_stream_encoder_reset_hdmi_stream_attribute, + .dig_connect_to_otg = virtual_dig_connect_to_otg, + .setup_stereo_sync = virtual_setup_stereo_sync, }; bool virtual_stream_encoder_construct( -- cgit v1.2.3 From 1174eb89ccf54166a0cbbef86e6044811320a754 Mon Sep 17 00:00:00 2001 From: Eric Bernstein Date: Mon, 20 Jul 2020 19:18:43 -0400 Subject: drm/amd/display: Use parameter for call to set output mux Signed-off-by: Eric Bernstein Reviewed-by: Chris Park Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 02742cca4d84..9f8ab679616c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3102,6 +3102,9 @@ void core_link_enable_stream( struct dc *dc = pipe_ctx->stream->ctx->dc; struct dc_stream_state *stream = pipe_ctx->stream; enum dc_status status; +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + enum otg_out_mux_dest otg_out_dest = OUT_MUX_DIO; +#endif DC_LOGGER_INIT(pipe_ctx->stream->ctx->logger); if (!IS_DIAG_DC(dc->ctx->dce_environment) && @@ -3136,8 +3139,8 @@ void core_link_enable_stream( pipe_ctx->stream->link->link_state_valid = true; #if defined(CONFIG_DRM_AMD_DC_DCN3_0) - if (pipe_ctx->stream_res.tg->funcs->set_out_mux) - pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, OUT_MUX_DIO); + if (pipe_ctx->stream_res.tg->funcs->set_out_mux) + pipe_ctx->stream_res.tg->funcs->set_out_mux(pipe_ctx->stream_res.tg, otg_out_dest); #endif if (dc_is_dvi_signal(pipe_ctx->stream->signal)) -- cgit v1.2.3 From 6224220dc778e6e7b2139f6f29803d6dbdc33d95 Mon Sep 17 00:00:00 2001 From: Igor Kravchenko Date: Sun, 19 Jul 2020 20:45:28 -0400 Subject: drm/amd/display: Read VBIOS Golden Settings Tbl [Why] For ver.4.4 and higher VBIOS contains default setting table. {How] Read Golden Settings Table from VBIOS, apply Aux tuning parameters. Signed-off-by: Igor Kravchenko Reviewed-by: Aric Cyr Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser.c | 2 + drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 81 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 + drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 4 ++ drivers/gpu/drm/amd/display/dc/dc_types.h | 14 ++++ .../gpu/drm/amd/display/dc/dce/dce_link_encoder.h | 4 +- .../drm/amd/display/dc/dcn10/dcn10_link_encoder.h | 10 ++- .../drm/amd/display/dc/dcn20/dcn20_link_encoder.c | 14 +++- .../drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 5 +- drivers/gpu/drm/amd/include/atomfirmware.h | 54 ++++++++++++++- 10 files changed, 182 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c index 008d4d11339d..ad394aefa5d9 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c @@ -2834,6 +2834,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .bios_parser_destroy = bios_parser_destroy, .get_board_layout_info = bios_get_board_layout_info, + + .get_atom_dc_golden_table = NULL }; static bool bios_parser_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index b8684131151d..f8db92fed9cf 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -2079,6 +2079,85 @@ static uint16_t bios_parser_pack_data_tables( return 0; } +static struct atom_dc_golden_table_v1 *bios_get_golden_table( + struct bios_parser *bp, + uint32_t rev_major, + uint32_t rev_minor, + uint16_t *dc_golden_table_ver) +{ + struct atom_display_controller_info_v4_4 *disp_cntl_tbl_4_4 = NULL; + uint32_t dc_golden_offset = 0; + *dc_golden_table_ver = 0; + + if (!DATA_TABLES(dce_info)) + return NULL; + + /* ver.4.4 or higher */ + switch (rev_major) { + case 4: + switch (rev_minor) { + case 4: + disp_cntl_tbl_4_4 = GET_IMAGE(struct atom_display_controller_info_v4_4, + DATA_TABLES(dce_info)); + if (!disp_cntl_tbl_4_4) + return NULL; + dc_golden_offset = disp_cntl_tbl_4_4->dc_golden_table_offset; + *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver; + break; + } + break; + } + + if (!dc_golden_offset) + return NULL; + + if (*dc_golden_table_ver != 1) + return NULL; + + return GET_IMAGE(struct atom_dc_golden_table_v1, + dc_golden_offset); +} + +static enum bp_result bios_get_atom_dc_golden_table( + struct dc_bios *dcb) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + enum bp_result result = BP_RESULT_OK; + struct atom_dc_golden_table_v1 *atom_dc_golden_table = NULL; + struct atom_common_table_header *header; + struct atom_data_revision tbl_revision; + uint16_t dc_golden_table_ver = 0; + + header = GET_IMAGE(struct atom_common_table_header, + DATA_TABLES(dce_info)); + if (!header) + return BP_RESULT_UNSUPPORTED; + + get_atom_data_table_revision(header, &tbl_revision); + + atom_dc_golden_table = bios_get_golden_table(bp, + tbl_revision.major, + tbl_revision.minor, + &dc_golden_table_ver); + + if (!atom_dc_golden_table) + return BP_RESULT_UNSUPPORTED; + + dcb->golden_table.dc_golden_table_ver = dc_golden_table_ver; + dcb->golden_table.aux_dphy_rx_control0_val = atom_dc_golden_table->aux_dphy_rx_control0_val; + dcb->golden_table.aux_dphy_rx_control1_val = atom_dc_golden_table->aux_dphy_rx_control1_val; + dcb->golden_table.aux_dphy_tx_control_val = atom_dc_golden_table->aux_dphy_tx_control_val; + dcb->golden_table.dc_gpio_aux_ctrl_0_val = atom_dc_golden_table->dc_gpio_aux_ctrl_0_val; + dcb->golden_table.dc_gpio_aux_ctrl_1_val = atom_dc_golden_table->dc_gpio_aux_ctrl_1_val; + dcb->golden_table.dc_gpio_aux_ctrl_2_val = atom_dc_golden_table->dc_gpio_aux_ctrl_2_val; + dcb->golden_table.dc_gpio_aux_ctrl_3_val = atom_dc_golden_table->dc_gpio_aux_ctrl_3_val; + dcb->golden_table.dc_gpio_aux_ctrl_4_val = atom_dc_golden_table->dc_gpio_aux_ctrl_4_val; + dcb->golden_table.dc_gpio_aux_ctrl_5_val = atom_dc_golden_table->dc_gpio_aux_ctrl_5_val; + + return result; +} + + static const struct dc_vbios_funcs vbios_funcs = { .get_connectors_number = bios_parser_get_connectors_number, @@ -2128,6 +2207,8 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_board_layout_info = bios_get_board_layout_info, .pack_data_tables = bios_parser_pack_data_tables, + + .get_atom_dc_golden_table = bios_get_atom_dc_golden_table }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 9f8ab679616c..071c7b32b282 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1540,6 +1540,9 @@ static bool dc_link_construct(struct dc_link *link, } } + if (bios->funcs->get_atom_dc_golden_table) + bios->funcs->get_atom_dc_golden_table(bios); + /* * TODO check if GPIO programmed correctly * diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index 845a3054f21f..d06d07042a12 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -133,6 +133,9 @@ struct dc_vbios_funcs { uint16_t (*pack_data_tables)( struct dc_bios *dcb, void *dst); + + enum bp_result (*get_atom_dc_golden_table)( + struct dc_bios *dcb); }; struct bios_registers { @@ -154,6 +157,7 @@ struct dc_bios { struct dc_firmware_info fw_info; bool fw_info_valid; struct dc_vram_info vram_info; + struct dc_golden_table golden_table; }; #endif /* DC_BIOS_TYPES_H */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 29fe5389f973..946ba929c6f6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -890,6 +890,20 @@ struct dsc_dec_dpcd_caps { uint32_t branch_max_line_width; }; +struct dc_golden_table { + uint16_t dc_golden_table_ver; + uint32_t aux_dphy_rx_control0_val; + uint32_t aux_dphy_tx_control_val; + uint32_t aux_dphy_rx_control1_val; + uint32_t dc_gpio_aux_ctrl_0_val; + uint32_t dc_gpio_aux_ctrl_1_val; + uint32_t dc_gpio_aux_ctrl_2_val; + uint32_t dc_gpio_aux_ctrl_3_val; + uint32_t dc_gpio_aux_ctrl_4_val; + uint32_t dc_gpio_aux_ctrl_5_val; +}; + + #if defined(CONFIG_DRM_AMD_DC_DCN3_0) enum dc_gpu_mem_alloc_type { DC_MEM_ALLOC_TYPE_GART, diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h index 40ea2220330c..cb714a48b171 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h @@ -38,7 +38,8 @@ #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) #define HPD_REG_LIST(id)\ SRI(DC_HPD_CONTROL, HPD, id) @@ -135,6 +136,7 @@ struct dce110_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; + uint32_t AUX_DPHY_RX_CONTROL1; }; struct dce110_link_enc_hpd_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h index cf59ab0034dc..04dabed5f1c5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.h @@ -31,10 +31,10 @@ #define TO_DCN10_LINK_ENC(link_encoder)\ container_of(link_encoder, struct dcn10_link_encoder, base) - #define AUX_REG_LIST(id)\ SRI(AUX_CONTROL, DP_AUX, id), \ - SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id) + SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id), \ + SRI(AUX_DPHY_RX_CONTROL1, DP_AUX, id) #define HPD_REG_LIST(id)\ SRI(DC_HPD_CONTROL, HPD, id) @@ -73,6 +73,7 @@ struct dcn10_link_enc_aux_registers { uint32_t AUX_CONTROL; uint32_t AUX_DPHY_RX_CONTROL0; uint32_t AUX_DPHY_TX_CONTROL; + uint32_t AUX_DPHY_RX_CONTROL1; }; struct dcn10_link_enc_hpd_registers { @@ -443,7 +444,10 @@ struct dcn10_link_enc_registers { type AUX_TX_PRECHARGE_LEN; \ type AUX_TX_PRECHARGE_SYMBOLS; \ type AUX_MODE_DET_CHECK_DELAY;\ - type DPCS_DBG_CBUS_DIS + type DPCS_DBG_CBUS_DIS;\ + type AUX_RX_PRECHARGE_SKIP;\ + type AUX_RX_TIMEOUT_LEN;\ + type AUX_RX_TIMEOUT_LEN_MUL struct dcn10_link_enc_shift { DCN_LINK_ENCODER_REG_FIELD_LIST(uint8_t); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c index 8d209dae66e6..15c2ff264ff6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.c @@ -309,7 +309,6 @@ bool dcn20_link_encoder_is_in_alt_mode(struct link_encoder *enc) void enc2_hw_init(struct link_encoder *enc) { struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); - /* 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 @@ -333,9 +332,18 @@ void enc2_hw_init(struct link_encoder *enc) AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 AUX_RX_DETECTION_THRESHOLD [30:28] = 1 */ - AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + if (enc->ctx->dc_bios->golden_table.dc_golden_table_ver > 0) { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control0_val); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, enc->ctx->dc_bios->golden_table.aux_dphy_tx_control_val); + + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL1, enc->ctx->dc_bios->golden_table.aux_dphy_rx_control1_val); + } else { + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c4d); - AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + } //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index db09f40075c2..bf0044f7417e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -191,7 +191,10 @@ LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL0, AUX_RX_DETECTION_THRESHOLD, mask_sh), \ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_LEN, mask_sh),\ LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_TX_PRECHARGE_SYMBOLS, mask_sh),\ - LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh) + LE_SF(DP_AUX0_AUX_DPHY_TX_CONTROL, AUX_MODE_DET_CHECK_DELAY, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_PRECHARGE_SKIP, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN, mask_sh),\ + LE_SF(DP_AUX0_AUX_DPHY_RX_CONTROL1, AUX_RX_TIMEOUT_LEN_MUL, mask_sh) #define UNIPHY_DCN2_REG_LIST(id) \ SRI(CLOCK_ENABLE, SYMCLK, id), \ diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index c2544c81dfb2..3e526c394f6c 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -941,7 +941,6 @@ struct atom_display_controller_info_v4_1 uint8_t reserved3[8]; }; - struct atom_display_controller_info_v4_2 { struct atom_common_table_header table_header; @@ -976,6 +975,59 @@ struct atom_display_controller_info_v4_2 uint8_t reserved3[8]; }; +struct atom_display_controller_info_v4_4 { + struct atom_common_table_header table_header; + uint32_t display_caps; + uint32_t bootup_dispclk_10khz; + uint16_t dce_refclk_10khz; + uint16_t i2c_engine_refclk_10khz; + uint16_t dvi_ss_percentage; // in unit of 0.001% + uint16_t dvi_ss_rate_10hz; + uint16_t hdmi_ss_percentage; // in unit of 0.001% + uint16_t hdmi_ss_rate_10hz; + uint16_t dp_ss_percentage; // in unit of 0.001% + uint16_t dp_ss_rate_10hz; + uint8_t dvi_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t hdmi_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t dp_ss_mode; // enum of atom_spread_spectrum_mode + uint8_t ss_reserved; + uint8_t dfp_hardcode_mode_num; // DFP hardcode mode number defined in StandardVESA_TimingTable when EDID is not available + uint8_t dfp_hardcode_refreshrate;// DFP hardcode mode refreshrate defined in StandardVESA_TimingTable when EDID is not available + uint8_t vga_hardcode_mode_num; // VGA hardcode mode number defined in StandardVESA_TimingTable when EDID is not avablable + uint8_t vga_hardcode_refreshrate;// VGA hardcode mode number defined in StandardVESA_TimingTable when EDID is not avablable + uint16_t dpphy_refclk_10khz; + uint16_t hw_chip_id; + uint8_t dcnip_min_ver; + uint8_t dcnip_max_ver; + uint8_t max_disp_pipe_num; + uint8_t max_vbios_active_disp_pipum; + uint8_t max_ppll_num; + uint8_t max_disp_phy_num; + uint8_t max_aux_pairs; + uint8_t remotedisplayconfig; + uint32_t dispclk_pll_vco_freq; + uint32_t dp_ref_clk_freq; + uint32_t max_mclk_chg_lat; // Worst case blackout duration for a memory clock frequency (p-state) change, units of 100s of ns (0.1 us) + uint32_t max_sr_exit_lat; // Worst case memory self refresh exit time, units of 100ns of ns (0.1us) + uint32_t max_sr_enter_exit_lat; // Worst case memory self refresh entry followed by immediate exit time, units of 100ns of ns (0.1us) + uint16_t dc_golden_table_offset; // point of struct of atom_dc_golden_table_vxx + uint16_t dc_golden_table_ver; + uint32_t reserved3[3]; +}; + +struct atom_dc_golden_table_v1 +{ + uint32_t aux_dphy_rx_control0_val; + uint32_t aux_dphy_tx_control_val; + uint32_t aux_dphy_rx_control1_val; + uint32_t dc_gpio_aux_ctrl_0_val; + uint32_t dc_gpio_aux_ctrl_1_val; + uint32_t dc_gpio_aux_ctrl_2_val; + uint32_t dc_gpio_aux_ctrl_3_val; + uint32_t dc_gpio_aux_ctrl_4_val; + uint32_t dc_gpio_aux_ctrl_5_val; + uint32_t reserved[23]; +}; enum dce_info_caps_def { -- cgit v1.2.3 From a245528c598dc80fe909a5ea77372d071fd3a111 Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 26 Jun 2020 14:30:29 -0400 Subject: drm/amd/display: populate new dml variable Signed-off-by: Dmytro Laktyushkin Reviewed-by: Eric Bernstein Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 b0064087b9bb..afdd4f0d9d71 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -467,7 +467,8 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] = 1; mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0; - mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;; + mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; mode_lib->vba.DSCInputBitPerComponent[mode_lib->vba.NumberOfActivePlanes] = -- cgit v1.2.3 From 5268bf136ef08c6a30d132036de3092d8219da8c Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Fri, 19 Jun 2020 14:02:38 -0400 Subject: drm/amd/display: DSC Bit target rate debugfs write entry [Why] We need to be able to specify bits per pixel for DSC on any connector. [How] Overwrite computed DSC target rate in dsc_cfg, with requested value. Overwrites for both SST and MST connectors, but in different places, but the process is identical. Overwrites only if DSC is decided to be enabled on that connector. Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 86 ++++++++++++++++++++++ .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 9 ++- 4 files changed, 98 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 26217e5e800d..765680b62d6a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4678,6 +4678,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_slice_height) stream->timing.dsc_cfg.num_slices_v = DIV_ROUND_UP(stream->timing.v_addressable, aconnector->dsc_settings.dsc_slice_height); + + if (stream->timing.flags.DSC && aconnector->dsc_settings.dsc_bits_per_pixel) + stream->timing.dsc_cfg.bits_per_pixel = aconnector->dsc_settings.dsc_bits_per_pixel; } #endif } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1a31473d3992..a8fff3413af3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -346,6 +346,7 @@ struct dsc_preferred_settings { bool dsc_clock_en; uint32_t dsc_slice_width; uint32_t dsc_slice_height; + uint32_t dsc_bits_per_pixel; }; struct amdgpu_dm_connector { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index b4c470c75cbe..9260b27659e4 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1423,6 +1423,18 @@ done: return size; } +/* function: read DSC target rate on the connector in bits per pixel + * + * The read function: dp_dsc_bits_per_pixel_read + * returns target rate of compression in bits per pixel + * The return is an integer: 0 or other positive integer + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1480,6 +1492,79 @@ static ssize_t dp_dsc_bits_per_pixel_read(struct file *f, char __user *buf, return result; } +/* function: write DSC target rate in bits per pixel + * + * The write function: dp_dsc_bits_per_pixel_write + * overwrites automatically generated DSC configuration + * of DSC target bit rate. + * + * Also the user has to write bpp in hexidecimal + * rather than in decimal. + * + * Writing DSC settings is done with the following command: + * - To force overwrite rate (example sets to 256 bpp x 1/16): + * + * echo 0x100 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + * - To stop overwriting and let driver find the optimal rate, + * set the rate to zero: + * + * echo 0x0 > /sys/kernel/debug/dri/0/DP-X/dsc_bits_per_pixel + * + */ +static ssize_t dp_dsc_bits_per_pixel_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct pipe_ctx *pipe_ctx; + int i; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + uint8_t param_nums = 0; + long param[1] = {0}; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) { + kfree(wr_buf); + return -EINVAL; + } + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + for (i = 0; i < MAX_PIPES; i++) { + pipe_ctx = &aconnector->dc_link->dc->current_state->res_ctx.pipe_ctx[i]; + if (pipe_ctx && pipe_ctx->stream && + pipe_ctx->stream->link == aconnector->dc_link) + break; + } + + if (!pipe_ctx || !pipe_ctx->stream) + goto done; + + aconnector->dsc_settings.dsc_bits_per_pixel = param[0]; + +done: + kfree(wr_buf); + return size; +} + static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1739,6 +1824,7 @@ static const struct file_operations dp_dsc_slice_height_debugfs_fops = { static const struct file_operations dp_dsc_bits_per_pixel_debugfs_fops = { .owner = THIS_MODULE, .read = dp_dsc_bits_per_pixel_read, + .write = dp_dsc_bits_per_pixel_write, .llseek = default_llseek }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 4d74780f21a4..a222335133e0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -453,6 +453,7 @@ struct dsc_mst_fairness_params { bool clock_overwrite; uint32_t slice_width_overwrite; uint32_t slice_height_overwrite; + uint32_t bpp_overwrite; }; struct dsc_mst_fairness_vars { @@ -486,7 +487,12 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p params[i].timing, ¶ms[i].timing->dsc_cfg)) { params[i].timing->flags.DSC = 1; - params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + + if (params[i].bpp_overwrite) + params[i].timing->dsc_cfg.bits_per_pixel = params[i].bpp_overwrite; + else + params[i].timing->dsc_cfg.bits_per_pixel = vars[i].bpp_x16; + if (params[i].slice_width_overwrite) params[i].timing->dsc_cfg.num_slices_h = DIV_ROUND_UP( params[i].timing->h_addressable, @@ -714,6 +720,7 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state, debugfs_overwrite = true; params[count].slice_width_overwrite = aconnector->dsc_settings.dsc_slice_width; params[count].slice_height_overwrite = aconnector->dsc_settings.dsc_slice_height; + params[count].bpp_overwrite = aconnector->dsc_settings.dsc_bits_per_pixel; params[count].compression_possible = stream->sink->dsc_caps.dsc_dec_caps.is_dsc_supported; dc_dsc_get_policy_for_timing(params[count].timing, &dsc_policy); if (!dc_dsc_compute_bandwidth_range( -- cgit v1.2.3 From 06ff02fc1e14f9503340b1a140dde95eeaa000fe Mon Sep 17 00:00:00 2001 From: Harry Wentland Date: Tue, 30 Jun 2020 11:16:05 -0400 Subject: drm/amd/display: Fix logger context [Why&How] use correct logger context Signed-off-by: Harry Wentland Reviewed-by: Roman Li Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 ca9eedb643f2..949b61351ede 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr_internal.h @@ -71,8 +71,9 @@ enum dentist_divider_range { #define CTX \ clk_mgr->base.ctx + #define DC_LOGGER \ - clk_mgr->ctx->logger + clk_mgr->base.ctx->logger -- cgit v1.2.3 From 87353ae837c30c68b89b0d88005fefabe087859d Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Fri, 19 Jun 2020 14:07:03 -0400 Subject: drm/amd/display: Comments on how to use DSC debugfs some entries [why] Some of the DSC debugfs read enteries are missing comments explaining how to use and how to comprehend the results. Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) (limited to 'drivers/gpu') 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 9260b27659e4..9610e628baf0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1565,6 +1565,21 @@ done: return size; } +/* function: read DSC picture width parameter on the connector + * + * The read function: dp_dsc_pic_width_read + * returns dsc picture width used in the current configuration + * It is the same as h_addressable of the current + * display's timing + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_pic_width + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_pic_width_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1679,6 +1694,21 @@ static ssize_t dp_dsc_pic_height_read(struct file *f, char __user *buf, return result; } +/* function: read DSC chunk size parameter on the connector + * + * The read function: dp_dsc_chunk_size_read + * returns dsc chunk size set in the current configuration + * The value is calculated automatically by DSC code + * and depends on slice parameters and bpp target rate + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_chunk_size + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { @@ -1736,6 +1766,21 @@ static ssize_t dp_dsc_chunk_size_read(struct file *f, char __user *buf, return result; } +/* function: read DSC slice bpg offset on the connector + * + * The read function: dp_dsc_slice_bpg_offset_read + * returns dsc bpg slice offset set in the current configuration + * The value is calculated automatically by DSC code + * and depends on slice parameters and bpp target rate + * The return is an integer: 0 or other positive integer + * If 0 then DSC is disabled. + * + * Access it with the following command: + * + * cat /sys/kernel/debug/dri/0/DP-X/dsc_slice_bpg_offset + * + * 0 - means that DSC is disabled + */ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, size_t size, loff_t *pos) { -- cgit v1.2.3 From d024656757dc07e9f77d1eed854ce8f885f11856 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Thu, 23 Jul 2020 13:06:23 -0400 Subject: drm/amd/display: AMD OUI (DPCD 0x00300) skipped on some sink [Why] Sink OUI supported cap is not set so driver skips programming it. [How] Revert the change the skips OUI programming if the cap is not set Signed-off-by: Aric Cyr Reviewed-by: Anthony Koo Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers/gpu') 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 d7d2dcd49c06..9bc03f26efda 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4339,22 +4339,6 @@ void dp_set_fec_enable(struct dc_link *link, bool enable) void dpcd_set_source_specific_data(struct dc_link *link) { - uint8_t dspc = 0; - enum dc_status ret; - - ret = core_link_read_dpcd(link, DP_DOWN_STREAM_PORT_COUNT, &dspc, - sizeof(dspc)); - - if (ret != DC_OK) { - DC_LOG_ERROR("Error in DP aux read transaction," - " not writing source specific data\n"); - return; - } - - /* Return if OUI unsupported */ - if (!(dspc & DP_OUI_SUPPORT)) - return; - if (!link->dc->vendor_signature.is_valid) { struct dpcd_amd_signature amd_signature; amd_signature.AMD_IEEE_TxSignature_byte1 = 0x0; -- cgit v1.2.3 From 519d91d87f2e19727de772402ac0977633bbd13a Mon Sep 17 00:00:00 2001 From: JinZe.Xu Date: Tue, 21 Jul 2020 17:52:41 +0800 Subject: drm/amd/display: Use helper function to check for HDMI signal [How] Use dc_is_hdmi_signal to determine signal type. Signed-off-by: JinZe.Xu Reviewed-by: Charlene Liu Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 071c7b32b282..4bd6e03a7ef3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3282,7 +3282,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) dc_is_virtual_signal(pipe_ctx->stream->signal)) return; - if (pipe_ctx->stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) { + if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { core_link_set_avmute(pipe_ctx, true); } -- cgit v1.2.3 From 0914d1154f0ff03944d485f610efa3158aee4a06 Mon Sep 17 00:00:00 2001 From: George Shen Date: Fri, 17 Jul 2020 13:19:27 -0400 Subject: drm/amd/display: Change null plane state swizzle mode to 4kb_s [Why] During SetPathMode and UpdatePlanes, the plane state can be null. We default to linear swizzle mode when plane state is null. This resulted in bandwidth validation failing when trying to set 8K60 mode (which previously passed validation during rebuild timing list). [How] Change the default swizzle mode from linear to 4kb_s and update pitch accordingly. Signed-off-by: George Shen Reviewed-by: Dmytro Laktyushkin Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 2a5e7175926a..790baf552695 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -2223,7 +2223,7 @@ int dcn20_populate_dml_pipes_from_context( if (!res_ctx->pipe_ctx[i].plane_state) { pipes[pipe_cnt].pipe.src.is_hsplit = pipes[pipe_cnt].pipe.dest.odm_combine != dm_odm_combine_mode_disabled; pipes[pipe_cnt].pipe.src.source_scan = dm_horz; - pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_linear; + pipes[pipe_cnt].pipe.src.sw_mode = dm_sw_4kb_s; pipes[pipe_cnt].pipe.src.macro_tile_size = dm_64k_tile; pipes[pipe_cnt].pipe.src.viewport_width = timing->h_addressable; if (pipes[pipe_cnt].pipe.src.viewport_width > 1920) @@ -2235,7 +2235,7 @@ int dcn20_populate_dml_pipes_from_context( pipes[pipe_cnt].pipe.src.surface_width_y = pipes[pipe_cnt].pipe.src.viewport_width; pipes[pipe_cnt].pipe.src.surface_height_c = pipes[pipe_cnt].pipe.src.viewport_height; pipes[pipe_cnt].pipe.src.surface_width_c = pipes[pipe_cnt].pipe.src.viewport_width; - pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 63) / 64) * 64; /* linear sw only */ + pipes[pipe_cnt].pipe.src.data_pitch = ((pipes[pipe_cnt].pipe.src.viewport_width + 255) / 256) * 256; pipes[pipe_cnt].pipe.src.source_format = dm_444_32; pipes[pipe_cnt].pipe.dest.recout_width = pipes[pipe_cnt].pipe.src.viewport_width; /*vp_width/hratio*/ pipes[pipe_cnt].pipe.dest.recout_height = pipes[pipe_cnt].pipe.src.viewport_height; /*vp_height/vratio*/ -- cgit v1.2.3 From da83b385f3eba1d695bc8014d8a5c0a791188c16 Mon Sep 17 00:00:00 2001 From: Igor Kravchenko Date: Fri, 24 Jul 2020 11:10:40 -0400 Subject: drm/amd/display: Display goes blank after inst [why] Display goes blank after driver installation. Aux tuning parameters must be used for 2.x only. Wrong dc_golden_table offset was used. [How] Implement a new enc3_hw_init function without VBIOS constants usage to be called for 3.x Calculate dc_golden_table offset using sum of base dce_info offset and golden table offset Signed-off-by: Igor Kravchenko Reviewed-by: Aric Cyr Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 4 +- .../amd/display/dc/dcn30/dcn30_dio_link_encoder.c | 53 +++++++++++++++++++++- .../amd/display/dc/dcn30/dcn30_dio_link_encoder.h | 2 + 3 files changed, 56 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index f8db92fed9cf..078b7e344185 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -2101,7 +2101,7 @@ static struct atom_dc_golden_table_v1 *bios_get_golden_table( DATA_TABLES(dce_info)); if (!disp_cntl_tbl_4_4) return NULL; - dc_golden_offset = disp_cntl_tbl_4_4->dc_golden_table_offset; + dc_golden_offset = DATA_TABLES(dce_info) + disp_cntl_tbl_4_4->dc_golden_table_offset; *dc_golden_table_ver = disp_cntl_tbl_4_4->dc_golden_table_ver; break; } @@ -2115,7 +2115,7 @@ static struct atom_dc_golden_table_v1 *bios_get_golden_table( return NULL; return GET_IMAGE(struct atom_dc_golden_table_v1, - dc_golden_offset); + dc_golden_offset); } static enum bp_result bios_get_atom_dc_golden_table( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c index c29326e9856a..2ae159e2dd6e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.c @@ -62,7 +62,7 @@ static const struct link_encoder_funcs dcn30_link_enc_funcs = { .read_state = link_enc2_read_state, .validate_output_with_stream = dcn30_link_encoder_validate_output_with_stream, - .hw_init = enc2_hw_init, + .hw_init = enc3_hw_init, .setup = dcn10_link_encoder_setup, .enable_tmds_output = dcn10_link_encoder_enable_tmds_output, .enable_dp_output = dcn20_link_encoder_enable_dp_output, @@ -203,3 +203,54 @@ void dcn30_link_encoder_construct( enc10->base.features.flags.bits.HDMI_6GB_EN = 0; } } + +#define AUX_REG(reg)\ + (enc10->aux_regs->reg) + +#define AUX_REG_READ(reg_name) \ + dm_read_reg(CTX, AUX_REG(reg_name)) + +#define AUX_REG_WRITE(reg_name, val) \ + dm_write_reg(CTX, AUX_REG(reg_name), val) +void enc3_hw_init(struct link_encoder *enc) +{ + struct dcn10_link_encoder *enc10 = TO_DCN10_LINK_ENC(enc); + +/* + 00 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__1to2 : 1/2 + 01 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__3to4 : 3/4 + 02 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__7to8 : 7/8 + 03 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__15to16 : 15/16 + 04 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__31to32 : 31/32 + 05 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__63to64 : 63/64 + 06 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__127to128 : 127/128 + 07 - DP_AUX_DPHY_RX_DETECTION_THRESHOLD__255to256 : 255/256 +*/ + +/* + AUX_REG_UPDATE_5(AUX_DPHY_RX_CONTROL0, + AUX_RX_START_WINDOW = 1 [6:4] + AUX_RX_RECEIVE_WINDOW = 1 default is 2 [10:8] + AUX_RX_HALF_SYM_DETECT_LEN = 1 [13:12] default is 1 + AUX_RX_TRANSITION_FILTER_EN = 1 [16] default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_PHASE_DETECT [17] is 0 default is 0 + AUX_RX_ALLOW_BELOW_THRESHOLD_START [18] is 1 default is 1 + AUX_RX_ALLOW_BELOW_THRESHOLD_STOP [19] is 1 default is 1 + AUX_RX_PHASE_DETECT_LEN, [21,20] = 0x3 default is 3 + AUX_RX_DETECTION_THRESHOLD [30:28] = 1 +*/ + AUX_REG_WRITE(AUX_DPHY_RX_CONTROL0, 0x103d1110); + + AUX_REG_WRITE(AUX_DPHY_TX_CONTROL, 0x21c7a); + + //AUX_DPHY_TX_REF_CONTROL'AUX_TX_REF_DIV HW default is 0x32; + // Set AUX_TX_REF_DIV Divider to generate 2 MHz reference from refclk + // 27MHz -> 0xd + // 100MHz -> 0x32 + // 48MHz -> 0x18 + + // Set TMDS_CTL0 to 1. This is a legacy setting. + REG_UPDATE(TMDS_CTL_BITS, TMDS_CTL0, 1); + + dcn10_aux_initialize(enc10); +} diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 585d1ce63db1..8e9fd59ccde8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -73,4 +73,6 @@ void dcn30_link_encoder_construct( const struct dcn10_link_enc_shift *link_shift, const struct dcn10_link_enc_mask *link_mask); +void enc3_hw_init(struct link_encoder *enc); + #endif /* __DC_LINK_ENCODER__DCN30_H__ */ -- cgit v1.2.3 From 3d4e52d0cf24b424c668fa8ab1269725796d4ec4 Mon Sep 17 00:00:00 2001 From: Victor Lu Date: Tue, 21 Jul 2020 12:08:34 -0400 Subject: drm/amd/display: Add debugfs for forcing stream timing sync [why] There's currently no method to enable multi-stream synchronization from userspace and we don't check the VSDB bits to know whether or not specific displays should have the feature enable. [how] Add a debugfs entry that controls a new DM debug option, "force_timing_sync". This debug option will set on any newly created stream following the change to the debug option. Expose a new interface from DC that performs the timing sync and a helper to the "force_timing_sync" debugfs that iterates over the current streams and modifies the current synchornization state and grouping. Example usage to force a resync (from an X based desktop): echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync xset dpms force off && xset dpms force on Signed-off-by: Victor Lu Reviewed-by: Aurabindo Jayamohanan Pillai Acked-by: Aurabindo Pillai Acked-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 26 ++++++++++++++++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 3 ++ .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 35 ++++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +++++--- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 ++ 5 files changed, 75 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 765680b62d6a..27dfd285a944 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8034,6 +8034,13 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, goto fail; } + /* + * TODO: Check VSDB bits to decide whether this should + * be enabled or not. + */ + new_stream->triggered_crtc_reset.enabled = + dm->force_timing_sync; + dm_new_crtc_state->abm_level = dm_new_conn_state->abm_level; ret = fill_hdr_info_packet(drm_new_conn_state, @@ -9190,3 +9197,22 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) return dc_link_set_psr_allow_active(stream->link, false, true); } + +void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) +{ + struct amdgpu_device *adev = dev->dev_private; + struct dc *dc = adev->dm.dc; + int i; + + mutex_lock(&adev->dm.dc_lock); + if (dc->current_state) { + for (i = 0; i < dc->current_state->stream_count; ++i) + dc->current_state->streams[i] + ->triggered_crtc_reset.enabled = + adev->dm.force_timing_sync; + + dm_enable_per_frame_crtc_master_sync(dc->current_state); + dc_trigger_sync(dc, dc->current_state); + } + mutex_unlock(&adev->dm.dc_lock); +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index a8fff3413af3..fd863331dee1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -340,6 +340,7 @@ struct amdgpu_display_manager { * fake encoders used for DP MST. */ struct amdgpu_encoder mst_encoders[AMDGPU_DM_MAX_CRTC]; + bool force_timing_sync; }; struct dsc_preferred_settings { @@ -493,6 +494,8 @@ void dm_restore_drm_connector_state(struct drm_device *dev, void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct edid *edid); +void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); + #define MAX_COLOR_LUT_ENTRIES 4096 /* Legacy gamm LUT users such as X doesn't like large LUT sizes */ #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 9610e628baf0..ae6b1313403e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2183,6 +2183,38 @@ static const struct drm_info_list amdgpu_dm_debugfs_list[] = { {"amdgpu_mst_topology", &mst_topo}, }; +/* + * Sets the force_timing_sync debug optino from the given string. + * All connected displays will be force synchronized immediately. + * Usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync + */ +static int force_timing_sync_set(void *data, u64 val) +{ + struct amdgpu_device *adev = data; + + adev->dm.force_timing_sync = (bool)val; + + amdgpu_dm_trigger_timing_sync(adev->ddev); + + return 0; +} + +/* + * Gets the force_timing_sync debug option value into the given buffer. + * Usage: cat /sys/kernel/debug/dri/0/amdgpu_dm_force_timing_sync + */ +static int force_timing_sync_get(void *data, u64 *val) +{ + struct amdgpu_device *adev = data; + + *val = adev->dm.force_timing_sync; + + return 0; +} + +DEFINE_DEBUGFS_ATTRIBUTE(force_timing_sync_ops, force_timing_sync_get, + force_timing_sync_set, "%llu\n"); + /* * Sets the DC visual confirm debug option from the given string. * Example usage: echo 1 > /sys/kernel/debug/dri/0/amdgpu_visual_confirm @@ -2242,5 +2274,8 @@ int dtn_debugfs_init(struct amdgpu_device *adev) debugfs_create_file_unsafe("amdgpu_dm_dmub_fw_state", 0644, root, adev, &dmub_fw_state_fops); + debugfs_create_file_unsafe("amdgpu_dm_force_timing_sync", 0644, root, + adev, &force_timing_sync_ops); + return 0; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 92eb1ca1634f..5aa3b89471c3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1238,6 +1238,14 @@ bool dc_enable_stereo( return ret; } +void dc_trigger_sync(struct dc *dc, struct dc_state *context) +{ + if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { + enable_timing_multisync(dc, context); + program_timing_sync(dc, context); + } +} + /* * Applies given context to HW and copy it into current context. * It's up to the user to release the src context afterwards. @@ -1297,10 +1305,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c if (result != DC_OK) return result; - if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { - enable_timing_multisync(dc, context); - program_timing_sync(dc, context); - } + dc_trigger_sync(dc, context); /* Program all planes within new context*/ if (dc->hwss.program_front_end_for_ctx) { diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 633442bc7ef2..37743073772b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -397,6 +397,8 @@ bool dc_enable_stereo( struct dc_stream_state *streams[], uint8_t stream_count); +/* Triggers multi-stream synchronization. */ +void dc_trigger_sync(struct dc *dc, struct dc_state *context); enum surface_update_type dc_check_update_surfaces_for_stream( struct dc *dc, -- cgit v1.2.3 From 4453fbec106b5ab69389bf48a27af228a8434b97 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 22 Jul 2020 00:32:14 -0400 Subject: drm/amd/display: Separate pipe disconnect from rest of progrmaming [Why] When changing pixel formats for HDR (e.g. ARGB -> FP16) there are configurations that change from 2 pipes to 1 pipe. In these cases, it seems that disconnecting MPCC and doing a surface update at the same time(after unlocking) causes some registers to be updated slightly faster than others after unlocking (e.g. if the pixel format is updated to FP16 before the new surface address is programmed, we get corruption on the screen because the pixel formats aren't matching). We separate disconnecting MPCC from the rest of the pipe programming sequence to prevent this. [How] Move MPCC disconnect into separate operation than the rest of the pipe programming. Signed-off-by: Alvin Lee Reviewed-by: Jun Lei Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 114 +++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 7 ++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 + drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 7 files changed, 141 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5aa3b89471c3..ebbb8182228d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,6 +2300,7 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { + bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2330,6 +2331,15 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && + dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ + dc->hwss.interdependent_update_lock(dc, context, true); + mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); + } + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1..73eb4e76a0b1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1624,6 +1624,120 @@ static void dcn20_program_pipe( } } +bool dcn20_disconnect_pipes( + struct dc *dc, + struct dc_state *context) +{ + int i; + struct dce_hwseq *hws = dc->hwseq; + bool mpcc_disconnected = false; + DC_LOGGER_INIT(dc->ctx->logger); + + /* Set pipe update flags and lock pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) + dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], + &context->res_ctx.pipe_ctx[i]); + + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + /* OTG blank before disabling all front ends */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable + && !context->res_ctx.pipe_ctx[i].top_pipe + && !context->res_ctx.pipe_ctx[i].prev_odm_pipe + && context->res_ctx.pipe_ctx[i].stream) { + hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); + } + } + + /* Disconnect mpcc */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { + hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); + mpcc_disconnected = true; + } + } + } + + if (mpcc_disconnected) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + + if (!pipe_ctx || !plane_state || !pipe_ctx->stream) + continue; + + // Only update scaler and viewport here if we lose a pipe split. + // This is to prevent half the screen from being black when we + // unlock after disconnecting MPCC. + if (!(old_pipe && !pipe_ctx->top_pipe && + !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) + continue; + + if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { + if (pipe_ctx->update_flags.bits.scaler || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change || + plane_state->update_flags.bits.per_pixel_alpha_change || + pipe_ctx->stream->update_flags.bits.scaling) { + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; + ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); + /* scaler configuration */ + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + } + + if (pipe_ctx->update_flags.bits.viewport || + (context == dc->current_state && plane_state->update_flags.bits.position_change) || + (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || + (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { + + hubp->funcs->mem_program_viewport( + hubp, + &pipe_ctx->plane_res.scl_data.viewport, + &pipe_ctx->plane_res.scl_data.viewport_c); + } + } + } + } + return mpcc_disconnected; +} + +void dcn20_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *pipe_ctx; + struct timing_generator *tg; + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + tg = pipe_ctx->stream_res.tg; + + /* + * Only wait for top pipe's tg penindg bit + * Also skip if pipe is disabled. + */ + if (pipe_ctx->top_pipe || + !pipe_ctx->stream || !pipe_ctx->plane_state || + !tg->funcs->is_tg_enabled(tg)) + continue; + + /* + * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. + * For some reason waiting for OTG_UPDATE_PENDING cleared + * seems to not trigger the update right away, and if we + * lock again before VUPDATE then we don't get a separated + * operation. + */ + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + } +} + void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 83220e34c1a9..7befd35a2359 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -131,6 +131,13 @@ void dcn20_dccg_init(struct dce_hwseq *hws); int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); +bool dcn20_disconnect_pipes( + struct dc *dc, + struct dc_state *context); + +void dcn20_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context); + #ifndef TRIM_FSFT bool dcn20_optimize_timing_for_fsft(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 3dde6f26de47..55afb70d33e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index b187f71afa65..264302b27d4f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 9afee7160490..845aaf1c816c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn20_disconnect_pipes, + .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 3c986717dcd5..64c1be818b0e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,10 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); + bool (*disconnect_pipes)(struct dc *dc, + struct dc_state *context); + void (*wait_for_pending_cleared)(struct dc *dc, + struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- cgit v1.2.3 From ded750e6faaf965f7b07f8468488381dcb790c9c Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 24 Jul 2020 21:37:56 -0400 Subject: drm/amd/display: [FW Promotion] Release 0.0.27 | [Header Changes] | - Reworked the FW versioning to include hotfix | and test bits Signed-off-by: Anthony Koo Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 8b27cf0f1d51..55717ae4724d 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,11 +36,20 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x636e7b294 +#define DMUB_FW_VERSION_GIT_HASH 0xd7f4bb6ee #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 26 -#define DMUB_FW_VERSION_UCODE ((DMUB_FW_VERSION_MAJOR << 24) | (DMUB_FW_VERSION_MINOR << 16) | DMUB_FW_VERSION_REVISION) +#define DMUB_FW_VERSION_REVISION 27 +#define DMUB_FW_VERSION_TEST 0 +#define DMUB_FW_VERSION_VBIOS 0 +#define DMUB_FW_VERSION_HOTFIX 0 +#define DMUB_FW_VERSION_UCODE (((DMUB_FW_VERSION_MAJOR & 0xFF) << 24) | \ + ((DMUB_FW_VERSION_MINOR & 0xFF) << 16) | \ + ((DMUB_FW_VERSION_REVISION & 0xFF) << 8) | \ + ((DMUB_FW_VERSION_TEST & 0x1) << 7) | \ + ((DMUB_FW_VERSION_VBIOS & 0x1) << 6) | \ + (DMUB_FW_VERSION_HOTFIX & 0x3F)) + #endif //================================================================== -- cgit v1.2.3 From c4dfb54986fd79ac992c56c5a31af9469d60d5cf Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 27 Jul 2020 10:53:38 -0400 Subject: drm/amd/display: 3.2.97 Signed-off-by: Aric Cyr Acked-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ae0e27c67ef9..6d4cab948607 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.96" +#define DC_VER "3.2.97" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From 66f3db4ba62db74d0f6c5a0f872592f1a0ed7670 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 30 Jul 2020 15:21:33 -0400 Subject: drm/amdgpu/smu: rework i2c adpater registration The i2c init/fini functions just register the i2c adapter. There is no need to call them during hw init/fini. They only need to be called once per driver init/fini. The previous behavior broke runtime pm because we unregistered the i2c adapter during suspend. Tested-by: Tom St Denis Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 12 ++++++------ drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 14 -------------- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 14 -------------- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 14 -------------- 4 files changed, 6 insertions(+), 48 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 55463e7a11e2..d03b4852ed5f 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -579,6 +579,10 @@ static int smu_smc_table_sw_init(struct smu_context *smu) if (ret) return ret; + ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); + if (ret) + return ret; + return 0; } @@ -586,6 +590,8 @@ static int smu_smc_table_sw_fini(struct smu_context *smu) { int ret; + smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + ret = smu_free_memory_pool(smu); if (ret) return ret; @@ -845,10 +851,6 @@ static int smu_smc_hw_setup(struct smu_context *smu) return ret; } - ret = smu_i2c_init(smu, &adev->pm.smu_i2c); - if (ret) - return ret; - ret = smu_disable_umc_cdr_12gbps_workaround(smu); if (ret) { dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n"); @@ -1047,8 +1049,6 @@ static int smu_smc_hw_cleanup(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; - smu_i2c_fini(smu, &adev->pm.smu_i2c); - cancel_work_sync(&smu->throttling_logging_work); ret = smu_disable_thermal_alert(smu); diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index f13979687b9e..0147a5b9b06d 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2080,22 +2080,11 @@ static const struct i2c_algorithm arcturus_i2c_algo = { .functionality = arcturus_i2c_func, }; -static bool arcturus_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (arcturus_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2111,9 +2100,6 @@ static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!arcturus_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 6aaf483858a0..c33bdc6747f2 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -2457,22 +2457,11 @@ static const struct i2c_algorithm navi10_i2c_algo = { .functionality = navi10_i2c_func, }; -static bool navi10_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (navi10_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2488,9 +2477,6 @@ static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter * static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!navi10_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f64a1be94cb8..f373e2d0d31c 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -2630,22 +2630,11 @@ static const struct i2c_algorithm sienna_cichlid_i2c_algo = { .functionality = sienna_cichlid_i2c_func, }; -static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - - return control->dev.parent == &adev->pdev->dev; -} - static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); int res; - /* smu_i2c_eeprom_init may be called twice in sriov */ - if (sienna_cichlid_i2c_adapter_is_added(control)) - return 0; - control->owner = THIS_MODULE; control->class = I2C_CLASS_SPD; control->dev.parent = &adev->pdev->dev; @@ -2661,9 +2650,6 @@ static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_a static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) { - if (!sienna_cichlid_i2c_adapter_is_added(control)) - return; - i2c_del_adapter(control); } -- cgit v1.2.3 From 37912e963dadcc831dd2a766780ff0b8738773d8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 17:38:29 -0400 Subject: drm/amdgpu: handle bo size 0 in amdgpu_bo_create_kernel_at (v2) Just return early to match other bo_create functions. v2: check if the bo_ptr is NULL rather than checking the size. Reviewed-by: Christian König Reviewed-by: Felix Kuehling (v1) Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 5ac7b5561475..a3cf38d25fc1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -374,6 +374,9 @@ int amdgpu_bo_create_kernel_at(struct amdgpu_device *adev, if (r) return r; + if ((*bo_ptr) == NULL) + return 0; + /* * Remove the original mem node and create a new one at the request * position. -- cgit v1.2.3 From adb5be812251cbcae364e5016ad71c955faedbd8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 13:57:20 -0400 Subject: drm/amdgpu: use create_at for the stolen pre-OS buffer Should be functionally the same since nothing else is allocated at that point, but let's be exact. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 605d266754f6..a188216bccc2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1979,10 +1979,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel(adev, adev->gmc.stolen_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &adev->stolen_vga_memory, - NULL, &stolen_vga_buf); + r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_size, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->stolen_vga_memory, + &stolen_vga_buf); if (r) return r; -- cgit v1.2.3 From 81b54fb7a2c038e8eaae7036ad973e913463c34d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 14:10:46 -0400 Subject: drm/amdgpu: use a define for the memory size of the vga emulator Rather than open coding it everywhere. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 ++-- 6 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 75631b3396a3..5d605e473319 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -214,6 +214,8 @@ extern int amdgpu_num_kcq; #define AMDGPUFB_CONN_LIMIT 4 #define AMDGPU_BIOS_NUM_SCRATCH 16 +#define AMDGPU_VBIOS_VGA_ALLOCATION (9 * 1024 * 1024) /* reserve 8MB for vga emulator and 1 MB for FB */ + /* hard reset data */ #define AMDGPU_ASIC_RESET_DATA 0x39d5e86b diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index dd91a93de62a..943773e0c3c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -747,7 +747,7 @@ static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport; u32 pitch; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 538e7ee35cdf..4de996868d32 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -805,7 +805,7 @@ static unsigned gmc_v6_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 0f8e8aff9114..4113f2d33b75 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -970,7 +970,7 @@ static unsigned gmc_v7_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index abe64010f0d5..f29ff9afcc10 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1087,7 +1087,7 @@ static unsigned gmc_v8_0_get_vbios_fb_size(struct amdgpu_device *adev) unsigned size; if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport = RREG32(mmVIEWPORT_SIZE); size = (REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_HEIGHT) * diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c5f94bab4a01..ac15d7678d24 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1077,11 +1077,11 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) * Check related code in gmc_v9_0_sw_fini * */ if (gmc_v9_0_keep_stolen_memory(adev)) - return 9 * 1024 * 1024; + return AMDGPU_VBIOS_VGA_ALLOCATION; d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = 9 * 1024 * 1024; /* reserve 8MB for vga emulator and 1 MB for FB */ + size = AMDGPU_VBIOS_VGA_ALLOCATION; } else { u32 viewport; -- cgit v1.2.3 From fcbc92e2e1c38b3626aa871caa5124d5341f85bf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 17:46:00 -0400 Subject: drm/amdgpu: move stolen vga bo from amdgpu to amdgpu.gmc Since that is where we store the other data related to the stolen vga memory. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 ++-- 8 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5d605e473319..af51160bcf60 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -769,7 +769,6 @@ struct amdgpu_device { bool is_atom_fw; uint8_t *bios; uint32_t bios_size; - struct amdgpu_bo *stolen_vga_memory; uint32_t bios_scratch_reg_offset; uint32_t bios_scratch[AMDGPU_BIOS_NUM_SCRATCH]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 9d58c56f6cfc..ddb64be670c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -213,7 +213,8 @@ struct amdgpu_gmc { uint8_t vram_vendor; uint32_t srbm_soft_reset; bool prt_warning; - uint64_t stolen_size; + uint64_t stolen_vga_size; + struct amdgpu_bo *stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index a188216bccc2..39781127d059 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1979,9 +1979,9 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_size, + r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->stolen_vga_memory, + &adev->gmc.stolen_vga_memory, &stolen_vga_buf); if (r) return r; @@ -2043,7 +2043,7 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { void *stolen_vga_buf; /* return the VGA stolen memory (if any) back to VRAM */ - amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 943773e0c3c3..187c108f2fde 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -860,7 +860,7 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v10_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v10_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 4de996868d32..28ddb41a78c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -862,7 +862,7 @@ static int gmc_v6_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v6_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v6_0_get_vbios_fb_size(adev); r = amdgpu_bo_init(adev); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 4113f2d33b75..8b8ecbb99d84 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -1035,7 +1035,7 @@ static int gmc_v7_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v7_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v7_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index f29ff9afcc10..8e3763ec268f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1160,7 +1160,7 @@ static int gmc_v8_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v8_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v8_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index ac15d7678d24..b66c60680dba 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1243,7 +1243,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_size = gmc_v9_0_get_vbios_fb_size(adev); + adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1282,7 +1282,7 @@ static int gmc_v9_0_sw_fini(void *handle) amdgpu_vm_manager_fini(adev); if (gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_free_kernel(&adev->stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); -- cgit v1.2.3 From 5db62dc8d4f35dc11054f24ba2c86f6c3422918a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 17:55:30 -0400 Subject: drm/amdgpu: move keep stolen memory check into gmc core Rather than leaving this as a gmc v9 specific hack. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 9 ++++++++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 11 +++-------- 3 files changed, 12 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index ddb64be670c2..0cf18f01e67a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,6 +215,7 @@ struct amdgpu_gmc { bool prt_warning; uint64_t stolen_vga_size; struct amdgpu_bo *stolen_vga_memory; + bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 39781127d059..fd61769202b3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2042,8 +2042,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) void amdgpu_ttm_late_init(struct amdgpu_device *adev) { void *stolen_vga_buf; + /* return the VGA stolen memory (if any) back to VRAM */ - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + if (!adev->gmc.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); } /** @@ -2051,10 +2053,15 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) */ void amdgpu_ttm_fini(struct amdgpu_device *adev) { + void *stolen_vga_buf; + if (!adev->mman.initialized) return; amdgpu_ttm_training_reserve_vram_fini(adev); + /* return the stolen vga memory back to VRAM */ + if (adev->gmc.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index b66c60680dba..c5d2e4390fba 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -932,8 +932,7 @@ static int gmc_v9_0_late_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; int r; - if (!gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_late_init(adev); + amdgpu_bo_late_init(adev); r = amdgpu_gmc_allocate_vm_inv_eng(adev); if (r) @@ -1076,7 +1075,7 @@ static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) * TODO Remove once GART corruption is resolved * Check related code in gmc_v9_0_sw_fini * */ - if (gmc_v9_0_keep_stolen_memory(adev)) + if (adev->gmc.keep_stolen_vga_memory) return AMDGPU_VBIOS_VGA_ALLOCATION; d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); @@ -1243,6 +1242,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; + adev->gmc.keep_stolen_vga_memory = gmc_v9_0_keep_stolen_memory(adev); adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); /* Memory manager */ @@ -1275,15 +1275,10 @@ static int gmc_v9_0_sw_init(void *handle) static int gmc_v9_0_sw_fini(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - void *stolen_vga_buf; amdgpu_gmc_ras_fini(adev); amdgpu_gem_force_release(adev); amdgpu_vm_manager_fini(adev); - - if (gmc_v9_0_keep_stolen_memory(adev)) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); - amdgpu_gart_table_vram_free(adev); amdgpu_bo_fini(adev); amdgpu_gart_fini(adev); -- cgit v1.2.3 From 0635019412eb2db60fb1d34be8ed8225a0c70bd9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:05:11 -0400 Subject: drm/amdgpu: add support for extended stolen vga memory This will allow us to split the allocation for systems where we have to keep the stolen memory around to avoid S3 issues. This way we don't waste as much memory and still avoid any screen artifacts during the bios to driver transition. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 0cf18f01e67a..8f4af955d72c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,6 +215,8 @@ struct amdgpu_gmc { bool prt_warning; uint64_t stolen_vga_size; struct amdgpu_bo *stolen_vga_memory; + uint64_t stolen_extended_size; + struct amdgpu_bo *stolen_extended_memory; bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index fd61769202b3..ec975251b171 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1915,7 +1915,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) uint64_t gtt_size; int r; u64 vis_vram_limit; - void *stolen_vga_buf; + void *stolen_vga_buf, *stolen_extended_buf; mutex_init(&adev->mman.gtt_window_lock); @@ -1985,6 +1985,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) &stolen_vga_buf); if (r) return r; + r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, + adev->gmc.stolen_extended_size, + AMDGPU_GEM_DOMAIN_VRAM, + &adev->gmc.stolen_extended_memory, + &stolen_extended_buf); + if (r) + return r; DRM_INFO("amdgpu: %uM of VRAM memory ready\n", (unsigned) (adev->gmc.real_vram_size / (1024 * 1024))); @@ -2041,11 +2048,13 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) */ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { - void *stolen_vga_buf; + void *stolen_vga_buf, *stolen_extended_buf; /* return the VGA stolen memory (if any) back to VRAM */ if (!adev->gmc.keep_stolen_vga_memory) amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, + &stolen_extended_buf); } /** -- cgit v1.2.3 From dd285c5df9523117e9941f9d3c56d7ed73c4ed4d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 15:04:52 -0400 Subject: drm/amdgpu/gmc: add new helper to get the FB size used by pre-OS console This adds a new gmc callback to get the size reserved by the pre-OS console and provides a helper function for use by gmc IP drivers. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 43 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 5 ++++ 2 files changed, 48 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 21d2c8543f85..fc9e18aaa76e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -27,6 +27,7 @@ #include #include "amdgpu.h" +#include "amdgpu_gmc.h" #include "amdgpu_ras.h" #include "amdgpu_xgmi.h" @@ -431,3 +432,45 @@ void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, WREG32(reg, tmp); } } + +void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) +{ + unsigned size; + + /* + * TODO: + * Currently there is a bug where some memory client outside + * of the driver writes to first 8M of VRAM on S3 resume, + * this overrides GART which by default gets placed in first 8M and + * causes VM_FAULTS once GTT is accessed. + * Keep the stolen memory reservation until the while this is not solved. + */ + switch (adev->asic_type) { + case CHIP_VEGA10: + case CHIP_RAVEN: + case CHIP_ARCTURUS: + case CHIP_RENOIR: + adev->gmc.keep_stolen_vga_memory = true; + break; + default: + adev->gmc.keep_stolen_vga_memory = false; + break; + } + + if (!amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_DCE)) + size = 0; + else + size = amdgpu_gmc_get_vbios_fb_size(adev); + + /* set to 0 if the pre-OS buffer uses up most of vram */ + if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) + size = 0; + + if (size > AMDGPU_VBIOS_VGA_ALLOCATION) { + adev->gmc.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; + adev->gmc.stolen_extended_size = size - adev->gmc.stolen_vga_size; + } else { + adev->gmc.stolen_vga_size = size; + adev->gmc.stolen_extended_size = 0; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index 8f4af955d72c..c2a85d0b1546 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -131,6 +131,8 @@ struct amdgpu_gmc_funcs { void (*get_vm_pte)(struct amdgpu_device *adev, struct amdgpu_bo_va_mapping *mapping, uint64_t *flags); + /* get the amount of memory used by the vbios for pre-OS console */ + unsigned int (*get_vbios_fb_size)(struct amdgpu_device *adev); }; struct amdgpu_xgmi { @@ -253,6 +255,7 @@ struct amdgpu_gmc { #define amdgpu_gmc_map_mtype(adev, flags) (adev)->gmc.gmc_funcs->map_mtype((adev),(flags)) #define amdgpu_gmc_get_vm_pde(adev, level, dst, flags) (adev)->gmc.gmc_funcs->get_vm_pde((adev), (level), (dst), (flags)) #define amdgpu_gmc_get_vm_pte(adev, mapping, flags) (adev)->gmc.gmc_funcs->get_vm_pte((adev), (mapping), (flags)) +#define amdgpu_gmc_get_vbios_fb_size(adev) (adev)->gmc.gmc_funcs->get_vbios_fb_size((adev)) /** * amdgpu_gmc_vram_full_visible - Check if full VRAM is visible through the BAR @@ -307,4 +310,6 @@ extern void amdgpu_gmc_set_vm_fault_masks(struct amdgpu_device *adev, int hub_type, bool enable); +void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev); + #endif -- cgit v1.2.3 From 422fe8d27dcf180caf1e3755b9bf7c1b4de5f56a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:27:46 -0400 Subject: drm/amdgpu/gmc6: switch to using amdgpu_gmc_get_vbios_allocations The new helper centralizes the logic in one place. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 28ddb41a78c8..95a9117e9564 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -812,9 +812,6 @@ static unsigned gmc_v6_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; return size; } @@ -862,7 +859,7 @@ static int gmc_v6_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v6_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); r = amdgpu_bo_init(adev); if (r) @@ -1136,6 +1133,7 @@ static const struct amdgpu_gmc_funcs gmc_v6_0_gmc_funcs = { .set_prt = gmc_v6_0_set_prt, .get_vm_pde = gmc_v6_0_get_vm_pde, .get_vm_pte = gmc_v6_0_get_vm_pte, + .get_vbios_fb_size = gmc_v6_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v6_0_irq_funcs = { -- cgit v1.2.3 From 71755699b564bf9b03a0d036ca94164c3b5691c0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:29:20 -0400 Subject: drm/amdgpu/gmc7: switch to using amdgpu_gmc_get_vbios_allocations The new helper centralizes the logic in one place. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 8b8ecbb99d84..80c146df338a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -977,9 +977,7 @@ static unsigned gmc_v7_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; + return size; } @@ -1035,7 +1033,7 @@ static int gmc_v7_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v7_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1372,7 +1370,8 @@ static const struct amdgpu_gmc_funcs gmc_v7_0_gmc_funcs = { .emit_pasid_mapping = gmc_v7_0_emit_pasid_mapping, .set_prt = gmc_v7_0_set_prt, .get_vm_pde = gmc_v7_0_get_vm_pde, - .get_vm_pte = gmc_v7_0_get_vm_pte + .get_vm_pte = gmc_v7_0_get_vm_pte, + .get_vbios_fb_size = gmc_v7_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v7_0_irq_funcs = { -- cgit v1.2.3 From 3853626d2cf3eca3397bc5ffbd4bf2bf0f6eff8c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:29:39 -0400 Subject: drm/amdgpu/gmc8: switch to using amdgpu_gmc_get_vbios_allocations The new helper centralizes the logic in one place. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 8e3763ec268f..9ab65ca7df77 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1094,9 +1094,7 @@ static unsigned gmc_v8_0_get_vbios_fb_size(struct amdgpu_device *adev) REG_GET_FIELD(viewport, VIEWPORT_SIZE, VIEWPORT_WIDTH) * 4); } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; + return size; } @@ -1160,7 +1158,7 @@ static int gmc_v8_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v8_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); @@ -1739,7 +1737,8 @@ static const struct amdgpu_gmc_funcs gmc_v8_0_gmc_funcs = { .emit_pasid_mapping = gmc_v8_0_emit_pasid_mapping, .set_prt = gmc_v8_0_set_prt, .get_vm_pde = gmc_v8_0_get_vm_pde, - .get_vm_pte = gmc_v8_0_get_vm_pte + .get_vm_pte = gmc_v8_0_get_vm_pte, + .get_vbios_fb_size = gmc_v8_0_get_vbios_fb_size, }; static const struct amdgpu_irq_src_funcs gmc_v8_0_irq_funcs = { -- cgit v1.2.3 From 7b885f0eb4a5185c0ca73d9f82514a611e5e6258 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:29:55 -0400 Subject: drm/amdgpu/gmc9: switch to using amdgpu_gmc_get_vbios_allocations The new helper centralizes the logic in one place. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 112 ++++++++++++---------------------- 1 file changed, 38 insertions(+), 74 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index c5d2e4390fba..65488ddc34c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -827,6 +827,41 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev, *flags |= AMDGPU_PTE_SNOOPED; } +static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) +{ + u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); + unsigned size; + + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { + u32 viewport; + + switch (adev->asic_type) { + case CHIP_RAVEN: + case CHIP_RENOIR: + viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * + REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * + 4); + break; + case CHIP_VEGA10: + case CHIP_VEGA12: + case CHIP_VEGA20: + default: + viewport = RREG32_SOC15(DCE, 0, mmSCL0_VIEWPORT_SIZE); + size = (REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT) * + REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH) * + 4); + break; + } + } + + return size; +} + static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = { .flush_gpu_tlb = gmc_v9_0_flush_gpu_tlb, .flush_gpu_tlb_pasid = gmc_v9_0_flush_gpu_tlb_pasid, @@ -834,7 +869,8 @@ static const struct amdgpu_gmc_funcs gmc_v9_0_gmc_funcs = { .emit_pasid_mapping = gmc_v9_0_emit_pasid_mapping, .map_mtype = gmc_v9_0_map_mtype, .get_vm_pde = gmc_v9_0_get_vm_pde, - .get_vm_pte = gmc_v9_0_get_vm_pte + .get_vm_pte = gmc_v9_0_get_vm_pte, + .get_vbios_fb_size = gmc_v9_0_get_vbios_fb_size, }; static void gmc_v9_0_set_gmc_funcs(struct amdgpu_device *adev) @@ -902,31 +938,6 @@ static int gmc_v9_0_early_init(void *handle) return 0; } -static bool gmc_v9_0_keep_stolen_memory(struct amdgpu_device *adev) -{ - - /* - * TODO: - * Currently there is a bug where some memory client outside - * of the driver writes to first 8M of VRAM on S3 resume, - * this overrides GART which by default gets placed in first 8M and - * causes VM_FAULTS once GTT is accessed. - * Keep the stolen memory reservation until the while this is not solved. - * Also check code in gmc_v9_0_get_vbios_fb_size and gmc_v9_0_late_init - */ - switch (adev->asic_type) { - case CHIP_VEGA10: - case CHIP_RAVEN: - case CHIP_ARCTURUS: - case CHIP_RENOIR: - return true; - case CHIP_VEGA12: - case CHIP_VEGA20: - default: - return false; - } -} - static int gmc_v9_0_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -1066,52 +1077,6 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } -static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev) -{ - u32 d1vga_control; - unsigned size; - - /* - * TODO Remove once GART corruption is resolved - * Check related code in gmc_v9_0_sw_fini - * */ - if (adev->gmc.keep_stolen_vga_memory) - return AMDGPU_VBIOS_VGA_ALLOCATION; - - d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); - if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = AMDGPU_VBIOS_VGA_ALLOCATION; - } else { - u32 viewport; - - switch (adev->asic_type) { - case CHIP_RAVEN: - case CHIP_RENOIR: - viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); - size = (REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * - REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_WIDTH) * - 4); - break; - case CHIP_VEGA10: - case CHIP_VEGA12: - case CHIP_VEGA20: - default: - viewport = RREG32_SOC15(DCE, 0, mmSCL0_VIEWPORT_SIZE); - size = (REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_HEIGHT) * - REG_GET_FIELD(viewport, SCL0_VIEWPORT_SIZE, VIEWPORT_WIDTH) * - 4); - break; - } - } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) - return 0; - - return size; -} - static int gmc_v9_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -1242,8 +1207,7 @@ static int gmc_v9_0_sw_init(void *handle) if (r) return r; - adev->gmc.keep_stolen_vga_memory = gmc_v9_0_keep_stolen_memory(adev); - adev->gmc.stolen_vga_size = gmc_v9_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); -- cgit v1.2.3 From 7348c20a4e12e8f6ccf63a3deaae898bd72cd2e9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:30:14 -0400 Subject: drm/amdgpu/gmc10: switch to using amdgpu_gmc_get_vbios_allocations The new helper centralizes the logic in one place. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 57 +++++++++++++++------------------- 1 file changed, 25 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 187c108f2fde..f0f50e785dcd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -572,6 +572,28 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev, } } +static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) +{ + u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); + unsigned size; + + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { + u32 viewport; + u32 pitch; + + viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * + REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) * + 4); + } + + return size; +} + static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = { .flush_gpu_tlb = gmc_v10_0_flush_gpu_tlb, .flush_gpu_tlb_pasid = gmc_v10_0_flush_gpu_tlb_pasid, @@ -579,7 +601,8 @@ static const struct amdgpu_gmc_funcs gmc_v10_0_gmc_funcs = { .emit_pasid_mapping = gmc_v10_0_emit_pasid_mapping, .map_mtype = gmc_v10_0_map_mtype, .get_vm_pde = gmc_v10_0_get_vm_pde, - .get_vm_pte = gmc_v10_0_get_vm_pte + .get_vm_pte = gmc_v10_0_get_vm_pte, + .get_vbios_fb_size = gmc_v10_0_get_vbios_fb_size, }; static void gmc_v10_0_set_gmc_funcs(struct amdgpu_device *adev) @@ -741,36 +764,6 @@ static int gmc_v10_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } -static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev) -{ - u32 d1vga_control = RREG32_SOC15(DCE, 0, mmD1VGA_CONTROL); - unsigned size; - - if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { - size = AMDGPU_VBIOS_VGA_ALLOCATION; - } else { - u32 viewport; - u32 pitch; - - viewport = RREG32_SOC15(DCE, 0, mmHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); - pitch = RREG32_SOC15(DCE, 0, mmHUBPREQ0_DCSURF_SURFACE_PITCH); - size = (REG_GET_FIELD(viewport, - HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * - REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) * - 4); - } - /* return 0 if the pre-OS buffer uses up most of vram */ - if ((adev->gmc.real_vram_size - size) < (8 * 1024 * 1024)) { - DRM_ERROR("Warning: pre-OS buffer uses most of vram, \ - be aware of gart table overwrite\n"); - return 0; - } - - return size; -} - - - static int gmc_v10_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -860,7 +853,7 @@ static int gmc_v10_0_sw_init(void *handle) if (r) return r; - adev->gmc.stolen_vga_size = gmc_v10_0_get_vbios_fb_size(adev); + amdgpu_gmc_get_vbios_allocations(adev); /* Memory manager */ r = amdgpu_bo_init(adev); -- cgit v1.2.3 From 14b18937cb60a4970c52cd954a643ed9c09d2eaf Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 18:34:50 -0400 Subject: drm/amdgpu: drop the CPU pointers for the stolen vga bos We never use them. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ec975251b171..3df9d5a53741 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1915,7 +1915,6 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) uint64_t gtt_size; int r; u64 vis_vram_limit; - void *stolen_vga_buf, *stolen_extended_buf; mutex_init(&adev->mman.gtt_window_lock); @@ -1982,14 +1981,14 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, &adev->gmc.stolen_vga_memory, - &stolen_vga_buf); + NULL); if (r) return r; r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, adev->gmc.stolen_extended_size, AMDGPU_GEM_DOMAIN_VRAM, &adev->gmc.stolen_extended_memory, - &stolen_extended_buf); + NULL); if (r) return r; @@ -2048,13 +2047,10 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) */ void amdgpu_ttm_late_init(struct amdgpu_device *adev) { - void *stolen_vga_buf, *stolen_extended_buf; - /* return the VGA stolen memory (if any) back to VRAM */ if (!adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); - amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, - &stolen_extended_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, NULL); } /** @@ -2062,15 +2058,13 @@ void amdgpu_ttm_late_init(struct amdgpu_device *adev) */ void amdgpu_ttm_fini(struct amdgpu_device *adev) { - void *stolen_vga_buf; - if (!adev->mman.initialized) return; amdgpu_ttm_training_reserve_vram_fini(adev); /* return the stolen vga memory back to VRAM */ if (adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, &stolen_vga_buf); + amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); -- cgit v1.2.3 From 7438ae6e522f1c4df5f067fd82aaa4e82917b7a8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 28 Jul 2020 15:35:56 -0400 Subject: drm/amdgpu/gmc: disable keep_stolen_vga_memory on arcturus I suspect the only reason this was set was to avoid touching the display related registers on arcturus. Someone should double check this on arcturus with S3. Reviewed-by: Christian König Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index fc9e18aaa76e..0bd7b3797534 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -448,7 +448,6 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_VEGA10: case CHIP_RAVEN: - case CHIP_ARCTURUS: case CHIP_RENOIR: adev->gmc.keep_stolen_vga_memory = true; break; -- cgit v1.2.3 From cacbbe7c00655985aec37e5e4d02c66d7a1732c9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Jul 2020 12:53:56 -0400 Subject: drm/amdgpu: move stolen memory from gmc to mman It's more related to memory management than memory controller. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 12 ++++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 5 ----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 ++++++ 4 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 0bd7b3797534..213ef090bb0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -449,10 +449,10 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) case CHIP_VEGA10: case CHIP_RAVEN: case CHIP_RENOIR: - adev->gmc.keep_stolen_vga_memory = true; + adev->mman.keep_stolen_vga_memory = true; break; default: - adev->gmc.keep_stolen_vga_memory = false; + adev->mman.keep_stolen_vga_memory = false; break; } @@ -466,10 +466,10 @@ void amdgpu_gmc_get_vbios_allocations(struct amdgpu_device *adev) size = 0; if (size > AMDGPU_VBIOS_VGA_ALLOCATION) { - adev->gmc.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; - adev->gmc.stolen_extended_size = size - adev->gmc.stolen_vga_size; + adev->mman.stolen_vga_size = AMDGPU_VBIOS_VGA_ALLOCATION; + adev->mman.stolen_extended_size = size - adev->mman.stolen_vga_size; } else { - adev->gmc.stolen_vga_size = size; - adev->gmc.stolen_extended_size = 0; + adev->mman.stolen_vga_size = size; + adev->mman.stolen_extended_size = 0; } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h index c2a85d0b1546..d61bbde4c7d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h @@ -215,11 +215,6 @@ struct amdgpu_gmc { uint8_t vram_vendor; uint32_t srbm_soft_reset; bool prt_warning; - uint64_t stolen_vga_size; - struct amdgpu_bo *stolen_vga_memory; - uint64_t stolen_extended_size; - struct amdgpu_bo *stolen_extended_memory; - bool keep_stolen_vga_memory; uint32_t sdpif_register; /* apertures */ u64 shared_aperture_start; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3df9d5a53741..cc1a5b2876b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1978,16 +1978,16 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * This is used for VGA emulation and pre-OS scanout buffers to * avoid display artifacts while transitioning between pre-OS * and driver. */ - r = amdgpu_bo_create_kernel_at(adev, 0, adev->gmc.stolen_vga_size, + r = amdgpu_bo_create_kernel_at(adev, 0, adev->mman.stolen_vga_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->gmc.stolen_vga_memory, + &adev->mman.stolen_vga_memory, NULL); if (r) return r; - r = amdgpu_bo_create_kernel_at(adev, adev->gmc.stolen_vga_size, - adev->gmc.stolen_extended_size, + r = amdgpu_bo_create_kernel_at(adev, adev->mman.stolen_vga_size, + adev->mman.stolen_extended_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->gmc.stolen_extended_memory, + &adev->mman.stolen_extended_memory, NULL); if (r) return r; @@ -2048,9 +2048,9 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) void amdgpu_ttm_late_init(struct amdgpu_device *adev) { /* return the VGA stolen memory (if any) back to VRAM */ - if (!adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); - amdgpu_bo_free_kernel(&adev->gmc.stolen_extended_memory, NULL, NULL); + if (!adev->mman.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.stolen_extended_memory, NULL, NULL); } /** @@ -2063,8 +2063,8 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) amdgpu_ttm_training_reserve_vram_fini(adev); /* return the stolen vga memory back to VRAM */ - if (adev->gmc.keep_stolen_vga_memory) - amdgpu_bo_free_kernel(&adev->gmc.stolen_vga_memory, NULL, NULL); + if (adev->mman.keep_stolen_vga_memory) + amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 17c8d0d7bcc3..98af87f38f3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -59,6 +59,12 @@ struct amdgpu_mman { struct mutex gtt_window_lock; /* Scheduler entity for buffer moves */ struct drm_sched_entity entity; + + uint64_t stolen_vga_size; + struct amdgpu_bo *stolen_vga_memory; + uint64_t stolen_extended_size; + struct amdgpu_bo *stolen_extended_memory; + bool keep_stolen_vga_memory; }; struct amdgpu_copy_mem { -- cgit v1.2.3 From 72de33f8f7ba0f43a3117efbee6d08226ac31ecb Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Jul 2020 13:02:25 -0400 Subject: drm/amdgpu: move IP discovery data to mman It's related to the memory manager so move it there. Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 54 +++++++++++++-------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 +++++----- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 5 +++ 5 files changed, 44 insertions(+), 44 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index af51160bcf60..7464d6f9171d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -920,11 +920,6 @@ struct amdgpu_device { /* display related functionality */ struct amdgpu_display_manager dm; - /* discovery */ - uint8_t *discovery_bin; - uint32_t discovery_tmr_size; - struct amdgpu_bo *discovery_memory; - /* mes */ bool enable_mes; struct amdgpu_mes mes; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 79b0da3e8639..b72aeeb0a226 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1568,7 +1568,7 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) adev->firmware.gpu_info_fw = NULL; - if (adev->discovery_bin) { + if (adev->mman.discovery_bin) { amdgpu_discovery_get_gfx_info(adev); /* @@ -3428,7 +3428,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) sysfs_remove_files(&adev->dev->kobj, amdgpu_dev_attributes); if (IS_ENABLED(CONFIG_PERF_EVENTS)) amdgpu_pmu_fini(adev); - if (adev->discovery_bin) + if (adev->mman.discovery_bin) amdgpu_discovery_fini(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index a50ff2306504..bfb95143ba5e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -136,7 +136,7 @@ static int amdgpu_discovery_read_binary(struct amdgpu_device *adev, uint8_t *bin uint64_t pos = vram_size - DISCOVERY_TMR_OFFSET; amdgpu_device_vram_access(adev, pos, (uint32_t *)binary, - adev->discovery_tmr_size, false); + adev->mman.discovery_tmr_size, false); return 0; } @@ -168,18 +168,18 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) uint16_t checksum; int r; - adev->discovery_tmr_size = DISCOVERY_TMR_SIZE; - adev->discovery_bin = kzalloc(adev->discovery_tmr_size, GFP_KERNEL); - if (!adev->discovery_bin) + adev->mman.discovery_tmr_size = DISCOVERY_TMR_SIZE; + adev->mman.discovery_bin = kzalloc(adev->mman.discovery_tmr_size, GFP_KERNEL); + if (!adev->mman.discovery_bin) return -ENOMEM; - r = amdgpu_discovery_read_binary(adev, adev->discovery_bin); + r = amdgpu_discovery_read_binary(adev, adev->mman.discovery_bin); if (r) { DRM_ERROR("failed to read ip discovery binary\n"); goto out; } - bhdr = (struct binary_header *)adev->discovery_bin; + bhdr = (struct binary_header *)adev->mman.discovery_bin; if (le32_to_cpu(bhdr->binary_signature) != BINARY_SIGNATURE) { DRM_ERROR("invalid ip discovery binary signature\n"); @@ -192,7 +192,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) size = bhdr->binary_size - offset; checksum = bhdr->binary_checksum; - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, size, checksum)) { DRM_ERROR("invalid ip discovery binary checksum\n"); r = -EINVAL; @@ -202,7 +202,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) info = &bhdr->table_list[IP_DISCOVERY]; offset = le16_to_cpu(info->offset); checksum = le16_to_cpu(info->checksum); - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + offset); + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + offset); if (le32_to_cpu(ihdr->signature) != DISCOVERY_TABLE_SIGNATURE) { DRM_ERROR("invalid ip discovery data table signature\n"); @@ -210,7 +210,7 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) goto out; } - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, ihdr->size, checksum)) { DRM_ERROR("invalid ip discovery data table checksum\n"); r = -EINVAL; @@ -220,9 +220,9 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) info = &bhdr->table_list[GC]; offset = le16_to_cpu(info->offset); checksum = le16_to_cpu(info->checksum); - ghdr = (struct gpu_info_header *)(adev->discovery_bin + offset); + ghdr = (struct gpu_info_header *)(adev->mman.discovery_bin + offset); - if (!amdgpu_discovery_verify_checksum(adev->discovery_bin + offset, + if (!amdgpu_discovery_verify_checksum(adev->mman.discovery_bin + offset, ghdr->size, checksum)) { DRM_ERROR("invalid gc data table checksum\n"); r = -EINVAL; @@ -232,16 +232,16 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev) return 0; out: - kfree(adev->discovery_bin); - adev->discovery_bin = NULL; + kfree(adev->mman.discovery_bin); + adev->mman.discovery_bin = NULL; return r; } void amdgpu_discovery_fini(struct amdgpu_device *adev) { - kfree(adev->discovery_bin); - adev->discovery_bin = NULL; + kfree(adev->mman.discovery_bin); + adev->mman.discovery_bin = NULL; } int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) @@ -265,8 +265,8 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) return r; } - bhdr = (struct binary_header *)adev->discovery_bin; - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset)); num_dies = le16_to_cpu(ihdr->num_dies); @@ -274,7 +274,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) for (i = 0; i < num_dies; i++) { die_offset = le16_to_cpu(ihdr->die_info[i].die_offset); - dhdr = (struct die_header *)(adev->discovery_bin + die_offset); + dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset); num_ips = le16_to_cpu(dhdr->num_ips); ip_offset = die_offset + sizeof(*dhdr); @@ -288,7 +288,7 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev) le16_to_cpu(dhdr->die_id), num_ips); for (j = 0; j < num_ips; j++) { - ip = (struct ip *)(adev->discovery_bin + ip_offset); + ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); num_base_address = ip->num_base_address; DRM_DEBUG("%s(%d) #%d v%d.%d.%d:\n", @@ -337,24 +337,24 @@ int amdgpu_discovery_get_ip_version(struct amdgpu_device *adev, int hw_id, uint16_t num_ips; int i, j; - if (!adev->discovery_bin) { + if (!adev->mman.discovery_bin) { DRM_ERROR("ip discovery uninitialized\n"); return -EINVAL; } - bhdr = (struct binary_header *)adev->discovery_bin; - ihdr = (struct ip_discovery_header *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + ihdr = (struct ip_discovery_header *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[IP_DISCOVERY].offset)); num_dies = le16_to_cpu(ihdr->num_dies); for (i = 0; i < num_dies; i++) { die_offset = le16_to_cpu(ihdr->die_info[i].die_offset); - dhdr = (struct die_header *)(adev->discovery_bin + die_offset); + dhdr = (struct die_header *)(adev->mman.discovery_bin + die_offset); num_ips = le16_to_cpu(dhdr->num_ips); ip_offset = die_offset + sizeof(*dhdr); for (j = 0; j < num_ips; j++) { - ip = (struct ip *)(adev->discovery_bin + ip_offset); + ip = (struct ip *)(adev->mman.discovery_bin + ip_offset); if (le16_to_cpu(ip->hw_id) == hw_id) { if (major) @@ -377,13 +377,13 @@ int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev) struct binary_header *bhdr; struct gc_info_v1_0 *gc_info; - if (!adev->discovery_bin) { + if (!adev->mman.discovery_bin) { DRM_ERROR("ip discovery uninitialized\n"); return -EINVAL; } - bhdr = (struct binary_header *)adev->discovery_bin; - gc_info = (struct gc_info_v1_0 *)(adev->discovery_bin + + bhdr = (struct binary_header *)adev->mman.discovery_bin; + gc_info = (struct gc_info_v1_0 *)(adev->mman.discovery_bin + le16_to_cpu(bhdr->table_list[GC].offset)); adev->gfx.config.max_shader_engines = le32_to_cpu(gc_info->gc_num_se); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index cc1a5b2876b6..ea9b5b39f640 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1825,7 +1825,7 @@ static void amdgpu_ttm_training_data_block_init(struct amdgpu_device *adev) memset(ctx, 0, sizeof(*ctx)); ctx->c2p_train_data_offset = - ALIGN((adev->gmc.mc_vram_size - adev->discovery_tmr_size - SZ_1M), SZ_1M); + ALIGN((adev->gmc.mc_vram_size - adev->mman.discovery_tmr_size - SZ_1M), SZ_1M); ctx->p2c_train_data_offset = (adev->gmc.mc_vram_size - GDDR6_MEM_TRAINING_OFFSET); ctx->train_data_size = @@ -1864,10 +1864,10 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev) * Otherwise, fallback to legacy approach to check and reserve tmr block for ip * discovery data and G6 memory training data respectively */ - adev->discovery_tmr_size = + adev->mman.discovery_tmr_size = amdgpu_atomfirmware_get_fw_reserved_fb_size(adev); - if (!adev->discovery_tmr_size) - adev->discovery_tmr_size = DISCOVERY_TMR_OFFSET; + if (!adev->mman.discovery_tmr_size) + adev->mman.discovery_tmr_size = DISCOVERY_TMR_OFFSET; if (mem_train_support) { /* reserve vram for mem train according to TMR location */ @@ -1887,14 +1887,14 @@ static int amdgpu_ttm_reserve_tmr(struct amdgpu_device *adev) } ret = amdgpu_bo_create_kernel_at(adev, - adev->gmc.real_vram_size - adev->discovery_tmr_size, - adev->discovery_tmr_size, + adev->gmc.real_vram_size - adev->mman.discovery_tmr_size, + adev->mman.discovery_tmr_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->discovery_memory, + &adev->mman.discovery_memory, NULL); if (ret) { DRM_ERROR("alloc tmr failed(%d)!\n", ret); - amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL); return ret; } @@ -1968,7 +1968,7 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) * If IP discovery enabled, a block of memory should be * reserved for IP discovey. */ - if (adev->discovery_bin) { + if (adev->mman.discovery_bin) { r = amdgpu_ttm_reserve_tmr(adev); if (r) return r; @@ -2066,7 +2066,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev) if (adev->mman.keep_stolen_vga_memory) amdgpu_bo_free_kernel(&adev->mman.stolen_vga_memory, NULL, NULL); /* return the IP Discovery TMR memory back to VRAM */ - amdgpu_bo_free_kernel(&adev->discovery_memory, NULL, NULL); + amdgpu_bo_free_kernel(&adev->mman.discovery_memory, NULL, NULL); amdgpu_ttm_fw_reserve_vram_fini(adev); if (adev->mman.aper_base_kaddr) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 98af87f38f3e..6d7b83d967ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -65,6 +65,11 @@ struct amdgpu_mman { uint64_t stolen_extended_size; struct amdgpu_bo *stolen_extended_memory; bool keep_stolen_vga_memory; + + /* discovery */ + uint8_t *discovery_bin; + uint32_t discovery_tmr_size; + struct amdgpu_bo *discovery_memory; }; struct amdgpu_copy_mem { -- cgit v1.2.3 From 87ded5caeec3c61327e133baba1bce691ecd2ded Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 29 Jul 2020 13:14:17 -0400 Subject: drm/amdgpu: move vram usage by vbios to mman (v2) It's related to the memory manager so move it there. v2: inline the structure Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 12 ------------ drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 20 ++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 ++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 6 +++--- 6 files changed, 23 insertions(+), 29 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 7464d6f9171d..a5ea70697fba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -651,16 +651,6 @@ struct amdgpu_atcs { struct amdgpu_atcs_functions functions; }; -/* - * Firmware VRAM reservation - */ -struct amdgpu_fw_vram_usage { - u64 start_offset; - u64 size; - struct amdgpu_bo *reserved_bo; - void *va; -}; - /* * CGS */ @@ -944,8 +934,6 @@ struct amdgpu_device { struct delayed_work delayed_init_work; struct amdgpu_virt virt; - /* firmware VRAM reservation */ - struct amdgpu_fw_vram_usage fw_vram_usage; /* link all shadow bo */ struct list_head shadow_list; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 29f767e026e4..e33f63712b46 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1786,9 +1786,9 @@ static int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { /* Firmware request VRAM reservation for SR-IOV */ - adev->fw_vram_usage.start_offset = (start_addr & + adev->mman.fw_vram_usage_start_offset = (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; - adev->fw_vram_usage.size = size << 10; + adev->mman.fw_vram_usage_size = size << 10; /* Use the default scratch size */ usage_bytes = 0; } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index 1279053324f9..17c010d0431f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -89,9 +89,9 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { /* Firmware request VRAM reservation for SR-IOV */ - adev->fw_vram_usage.start_offset = (start_addr & + adev->mman.fw_vram_usage_start_offset = (start_addr & (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; - adev->fw_vram_usage.size = size << 10; + adev->mman.fw_vram_usage_size = size << 10; /* Use the default scratch size */ usage_bytes = 0; } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ea9b5b39f640..c7421aa32946 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1766,8 +1766,8 @@ static struct ttm_bo_driver amdgpu_bo_driver = { */ static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev) { - amdgpu_bo_free_kernel(&adev->fw_vram_usage.reserved_bo, - NULL, &adev->fw_vram_usage.va); + amdgpu_bo_free_kernel(&adev->mman.fw_vram_usage_reserved_bo, + NULL, &adev->mman.fw_vram_usage_va); } /** @@ -1781,19 +1781,19 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev) { uint64_t vram_size = adev->gmc.visible_vram_size; - adev->fw_vram_usage.va = NULL; - adev->fw_vram_usage.reserved_bo = NULL; + adev->mman.fw_vram_usage_va = NULL; + adev->mman.fw_vram_usage_reserved_bo = NULL; - if (adev->fw_vram_usage.size == 0 || - adev->fw_vram_usage.size > vram_size) + if (adev->mman.fw_vram_usage_size == 0 || + adev->mman.fw_vram_usage_size > vram_size) return 0; return amdgpu_bo_create_kernel_at(adev, - adev->fw_vram_usage.start_offset, - adev->fw_vram_usage.size, + adev->mman.fw_vram_usage_start_offset, + adev->mman.fw_vram_usage_size, AMDGPU_GEM_DOMAIN_VRAM, - &adev->fw_vram_usage.reserved_bo, - &adev->fw_vram_usage.va); + &adev->mman.fw_vram_usage_reserved_bo, + &adev->mman.fw_vram_usage_va); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 6d7b83d967ce..de37ceff0e56 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -70,6 +70,12 @@ struct amdgpu_mman { uint8_t *discovery_bin; uint32_t discovery_tmr_size; struct amdgpu_bo *discovery_memory; + + /* firmware VRAM reservation */ + u64 fw_vram_usage_start_offset; + u64 fw_vram_usage_size; + struct amdgpu_bo *fw_vram_usage_reserved_bo; + void *fw_vram_usage_va; }; struct amdgpu_copy_mem { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 5cae39d35c04..1e211544f2dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -401,7 +401,7 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev, if (bp_block_size) { bp_cnt = bp_block_size / sizeof(uint64_t); for (bp_idx = 0; bp_idx < bp_cnt; bp_idx++) { - retired_page = *(uint64_t *)(adev->fw_vram_usage.va + + retired_page = *(uint64_t *)(adev->mman.fw_vram_usage_va + bp_block_offset + bp_idx * sizeof(uint64_t)); bp.retired_page = retired_page; @@ -428,10 +428,10 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) adev->virt.fw_reserve.p_pf2vf = NULL; adev->virt.fw_reserve.p_vf2pf = NULL; - if (adev->fw_vram_usage.va != NULL) { + if (adev->mman.fw_vram_usage_va != NULL) { adev->virt.fw_reserve.p_pf2vf = (struct amd_sriov_msg_pf2vf_info_header *)( - adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); + adev->mman.fw_vram_usage_va + AMDGIM_DATAEXCHANGE_OFFSET); AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); AMDGPU_FW_VRAM_PF2VF_READ(adev, feature_flags, &adev->virt.gim_feature); -- cgit v1.2.3 From 34b0c7795bb4a618a7372547c6628ed8876d02a7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 3 Aug 2020 17:35:19 +0300 Subject: drm/amd/display: Indent an if statement The if statement wasn't indented so it's confusing. Signed-off-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 ca26714c800e..c6b737dd8425 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -71,7 +71,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) if (ASIC_REV_IS_TAHITI_P(asic_id.hw_internal_rev) || ASIC_REV_IS_PITCAIRN_PM(asic_id.hw_internal_rev) || ASIC_REV_IS_CAPEVERDE_M(asic_id.hw_internal_rev)) - dc_version = DCE_VERSION_6_0; + dc_version = DCE_VERSION_6_0; else if (ASIC_REV_IS_OLAND_M(asic_id.hw_internal_rev)) dc_version = DCE_VERSION_6_4; else -- cgit v1.2.3 From 25457a1fb76448875013625fdc10ed4e941585b4 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 4 Aug 2020 22:06:53 +0200 Subject: drm/amd/display: Constify dcn20_res_pool_funcs The only usage of dcn20_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 790baf552695..991eddd10952 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3320,7 +3320,7 @@ enum dc_status dcn20_patch_unknown_plane_state(struct dc_plane_state *plane_stat return DC_OK; } -static struct resource_funcs dcn20_res_pool_funcs = { +static const struct resource_funcs dcn20_res_pool_funcs = { .destroy = dcn20_destroy_resource_pool, .link_enc_create = dcn20_link_encoder_create, .panel_cntl_create = dcn20_panel_cntl_create, -- cgit v1.2.3 From ea22cc3353eda4b275d394c2369c8ffa87753165 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 4 Aug 2020 22:06:54 +0200 Subject: drm/amd/display: Constify dcn21_res_pool_funcs The only usage of dcn21_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index 88d41a385add..a828696668bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1754,7 +1754,7 @@ enum dc_status dcn21_patch_unknown_plane_state(struct dc_plane_state *plane_stat return result; } -static struct resource_funcs dcn21_res_pool_funcs = { +static const struct resource_funcs dcn21_res_pool_funcs = { .destroy = dcn21_destroy_resource_pool, .link_enc_create = dcn21_link_encoder_create, .panel_cntl_create = dcn21_panel_cntl_create, -- cgit v1.2.3 From cc9fc1b1444f12addc1cf6aa6e653426990f1ad2 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Tue, 4 Aug 2020 22:06:55 +0200 Subject: drm/amd/display: Constify dcn30_res_pool_funcs The only usage of dcn30_res_pool_funcs is to assign its address to a const pointer. Make it const to allow the compiler to put it in read-only memory. Signed-off-by: Rikard Falkeborn Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 653a571e366d..d474a6188445 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2412,7 +2412,7 @@ static void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw dml_init_instance(&dc->current_state->bw_ctx.dml, &dcn3_0_soc, &dcn3_0_ip, DML_PROJECT_DCN30); } -static struct resource_funcs dcn30_res_pool_funcs = { +static const struct resource_funcs dcn30_res_pool_funcs = { .destroy = dcn30_destroy_resource_pool, .link_enc_create = dcn30_link_encoder_create, .panel_cntl_create = dcn30_panel_cntl_create, -- cgit v1.2.3 From c35376137e940c3389df2726a92649c01a9844b4 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Sun, 2 Aug 2020 19:15:36 +0800 Subject: drm/amd/display: Fix wrong return value in dm_update_plane_state() On an error exit path, a negative error code should be returned instead of a positive return value. Fixes: 9e869063b0021 ("drm/amd/display: Move iteration out of dm_update_planes") Cc: Leo Li Signed-off-by: Tianjia Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') 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 27dfd285a944..7f6a91b4fe4e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8343,8 +8343,7 @@ static int dm_update_plane_state(struct dc *dc, dm_old_plane_state->dc_state, dm_state->context)) { - ret = EINVAL; - return ret; + return -EINVAL; } -- cgit v1.2.3 From b80f050ff23d48c9b191e3da7e31ee520d1b2126 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Mon, 27 Jul 2020 09:06:18 -0400 Subject: drm/amdkfd: option to disable system mem limit If multiple process share system memory through /dev/shm, KFD allocate memory should not fail if it reaches the system memory limit because one copy of physical system memory are shared by multiple process. Add module parameter no_system_mem_limit to provide user option to disable system memory limit check at runtime using sysfs or during driver module init using kernel boot argument. By default the system memory limit is on. Print out debug message to warn user if KFD allocate memory failed because system memory reaches limit. Signed-off-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 6 +++++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 9 +++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index a5ea70697fba..3e82a11577d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -188,9 +188,11 @@ extern int amdgpu_force_asic_type; #ifdef CONFIG_HSA_AMD extern int sched_policy; extern bool debug_evictions; +extern bool no_system_mem_limit; #else static const int sched_policy = KFD_SCHED_POLICY_HWS; static const bool debug_evictions; /* = false */ +static const bool no_system_mem_limit; #endif extern int amdgpu_tmz; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index a21cf84b882c..fcf72f337785 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -148,8 +148,12 @@ static int amdgpu_amdkfd_reserve_mem_limit(struct amdgpu_device *adev, spin_lock(&kfd_mem_limit.mem_limit_lock); + if (kfd_mem_limit.system_mem_used + system_mem_needed > + kfd_mem_limit.max_system_mem_limit) + pr_debug("Set no_system_mem_limit=1 if using shared memory\n"); + if ((kfd_mem_limit.system_mem_used + system_mem_needed > - kfd_mem_limit.max_system_mem_limit) || + kfd_mem_limit.max_system_mem_limit && !no_system_mem_limit) || (kfd_mem_limit.ttm_mem_used + ttm_mem_needed > kfd_mem_limit.max_ttm_mem_limit) || (adev->kfd.vram_used + vram_needed > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 6d66705a1141..5156c67ec67b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -717,6 +717,15 @@ MODULE_PARM_DESC(queue_preemption_timeout_ms, "queue preemption timeout in ms (1 bool debug_evictions; module_param(debug_evictions, bool, 0644); MODULE_PARM_DESC(debug_evictions, "enable eviction debug messages (false = default)"); + +/** + * DOC: no_system_mem_limit(bool) + * Disable system memory limit, to support multiple process shared memory + */ +bool no_system_mem_limit; +module_param(no_system_mem_limit, bool, 0644); +MODULE_PARM_DESC(no_system_mem_limit, "disable system memory limit (false = default)"); + #endif /** -- cgit v1.2.3 From 9993d8b174925a45810c45d2f5fd90d040400293 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 4 Aug 2020 16:58:30 +0800 Subject: drm/amd/powerplay: grant Arcturus softmin/max setting on latest PM firmware For Arcturus, the softmin/max settings from driver are permitted on the latest(54.26 later) SMU firmware. Thus enabling them in driver. Signed-off-by: Evan Quan Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 0147a5b9b06d..d292898120be 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -897,9 +897,10 @@ static int arcturus_force_clk_levels(struct smu_context *smu, return ret; } - if (smu_version >= 0x361200) { + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 and onwards SMU firmwares\n"); + "54.18 - 54.26(included) SMU firmwares\n"); return -EOPNOTSUPP; } @@ -1392,9 +1393,10 @@ static int arcturus_set_performance_level(struct smu_context *smu, case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - if (smu_version >= 0x361200) { + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 and onwards SMU firmwares\n"); + "54.18 - 54.26(included) SMU firmwares\n"); return -EOPNOTSUPP; } break; -- cgit v1.2.3 From c16ce56240aa654c1676f36119561162405322b1 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 5 Aug 2020 13:15:27 +0100 Subject: drm/amdgpu: fix spelling mistake "paramter" -> "parameter" There is a spelling mistake in a dev_warn message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b72aeeb0a226..16e23f053361 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1201,7 +1201,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) if (amdgpu_num_kcq > 8 || amdgpu_num_kcq < 0) { amdgpu_num_kcq = 8; - dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid paramter provided by user\n"); + dev_warn(adev->dev, "set kernel compute queue number to 8 due to invalid parameter provided by user\n"); } return 0; -- cgit v1.2.3 From 39c5a1cef84b4bc70123400d75f0fe637e1df6a6 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 23 Jul 2020 16:07:01 +0800 Subject: drm/amd/powerplay: define an universal data structure for gpu metrics (V4) Thus we can provide an interface for UMD to retrieve gpu metrics data. V2: better naming and comments V3: two structures created for dGPU and APU separately V4: add driver attached timestamp Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/include/kgd_pp_interface.h | 108 +++++++++++++++++++++++++ 1 file changed, 108 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index a7f92d0b3a90..5f38ee62c103 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -324,4 +324,112 @@ struct amd_pm_funcs { int (*set_xgmi_pstate)(void *handle, uint32_t pstate); }; +struct metrics_table_header { + uint16_t structure_size; + uint8_t format_revision; + uint8_t content_revision; +}; + +struct gpu_metrics_v1_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_edge; + uint16_t temperature_hotspot; + uint16_t temperature_mem; + uint16_t temperature_vrgfx; + uint16_t temperature_vrsoc; + uint16_t temperature_vrmem; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_umc_activity; // memory controller + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; + uint32_t energy_accumulator; + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_vclk0_frequency; + uint16_t average_dclk0_frequency; + uint16_t average_vclk1_frequency; + uint16_t average_dclk1_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_vclk0; + uint16_t current_dclk0; + uint16_t current_vclk1; + uint16_t current_dclk1; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t current_fan_speed; + + /* Link width/speed */ + uint8_t pcie_link_width; + uint8_t pcie_link_speed; // in 0.1 GT/s +}; + +struct gpu_metrics_v2_0 { + struct metrics_table_header common_header; + + /* Driver attached timestamp (in ns) */ + uint64_t system_clock_counter; + + /* Temperature */ + uint16_t temperature_gfx; // gfx temperature on APUs + uint16_t temperature_soc; // soc temperature on APUs + uint16_t temperature_core[8]; // CPU core temperature on APUs + uint16_t temperature_l3[2]; + + /* Utilization */ + uint16_t average_gfx_activity; + uint16_t average_mm_activity; // UVD or VCN + + /* Power/Energy */ + uint16_t average_socket_power; // dGPU + APU power on A + A platform + uint16_t average_cpu_power; + uint16_t average_soc_power; + uint16_t average_gfx_power; + uint16_t average_core_power[8]; // CPU core power on APUs + + /* Average clocks */ + uint16_t average_gfxclk_frequency; + uint16_t average_socclk_frequency; + uint16_t average_uclk_frequency; + uint16_t average_fclk_frequency; + uint16_t average_vclk_frequency; + uint16_t average_dclk_frequency; + + /* Current clocks */ + uint16_t current_gfxclk; + uint16_t current_socclk; + uint16_t current_uclk; + uint16_t current_fclk; + uint16_t current_vclk; + uint16_t current_dclk; + uint16_t current_coreclk[8]; // CPU core clocks + uint16_t current_l3clk[2]; + + /* Throttle status */ + uint32_t throttle_status; + + /* Fans */ + uint16_t fan_pwm; + + uint16_t padding; +}; + #endif -- cgit v1.2.3 From 25c933b1c4fcfaa65ed735e9782fdb2622f7b7e8 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 23 Jul 2020 18:03:35 +0800 Subject: drm/amd/powerplay: add new sysfs interface for retrieving gpu metrics(V2) A new interface for UMD to retrieve gpu metrics data. V2: rich the documentation Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- Documentation/gpu/amdgpu.rst | 6 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 57 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/include/kgd_pp_interface.h | 1 + drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 20 +++++++++ drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 ++ 6 files changed, 90 insertions(+) (limited to 'drivers/gpu') diff --git a/Documentation/gpu/amdgpu.rst b/Documentation/gpu/amdgpu.rst index 17112352f605..0f7679a7cf54 100644 --- a/Documentation/gpu/amdgpu.rst +++ b/Documentation/gpu/amdgpu.rst @@ -206,6 +206,12 @@ pp_power_profile_mode .. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c :doc: mem_busy_percent +gpu_metrics +~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c + :doc: gpu_metrics + GPU Product Information ======================= diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index aa27fe65cdfa..b190c0af7db1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -369,6 +369,9 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ (adev)->powerplay.pp_handle, (ppfeatures))) +#define amdgpu_dpm_get_gpu_metrics(adev, table) \ + ((adev)->powerplay.pp_funcs->get_gpu_metrics((adev)->powerplay.pp_handle, table)) + struct amdgpu_dpm { struct amdgpu_ps *ps; /* number of valid power states */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 576e3ac98365..1705e328c6fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -2120,6 +2120,59 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, return count; } +/** + * DOC: gpu_metrics + * + * The amdgpu driver provides a sysfs API for retrieving current gpu + * metrics data. The file gpu_metrics is used for this. Reading the + * file will dump all the current gpu metrics data. + * + * These data include temperature, frequency, engines utilization, + * power consume, throttler status, fan speed and cpu core statistics( + * available for APU only). That's it will give a snapshot of all sensors + * at the same time. + */ +static ssize_t amdgpu_get_gpu_metrics(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + void *gpu_metrics; + ssize_t size = 0; + int ret; + + if (amdgpu_in_reset(adev)) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + down_read(&adev->reset_sem); + if (is_support_sw_smu(adev)) + size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); + else if (adev->powerplay.pp_funcs->get_gpu_metrics) + size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); + up_read(&adev->reset_sem); + + if (size <= 0) + goto out; + + if (size >= PAGE_SIZE) + size = PAGE_SIZE - 1; + + memcpy(buf, gpu_metrics, size); + +out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(power_dpm_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), AMDGPU_DEVICE_ATTR_RW(power_dpm_force_performance_level, ATTR_FLAG_BASIC), @@ -2143,6 +2196,7 @@ static struct amdgpu_device_attr amdgpu_device_attrs[] = { AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC), AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(gpu_metrics, ATTR_FLAG_BASIC), }; static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, @@ -2192,6 +2246,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ } else if (DEVICE_ATTR_IS(pp_features)) { if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(gpu_metrics)) { + if (asic_type < CHIP_VEGA12) + *states = ATTR_STATE_UNSUPPORTED; } if (asic_type == CHIP_ARCTURUS) { diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h index 5f38ee62c103..0aec28fda058 100644 --- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h @@ -322,6 +322,7 @@ struct amd_pm_funcs { int (*asic_reset_mode_2)(void *handle); int (*set_df_cstate)(void *handle, enum pp_df_cstate state); int (*set_xgmi_pstate)(void *handle, uint32_t pstate); + ssize_t (*get_gpu_metrics)(void *handle, void **table); }; struct metrics_table_header { diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index d03b4852ed5f..f3f50b5add99 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -2516,3 +2516,23 @@ int smu_get_dpm_clock_table(struct smu_context *smu, return ret; } + +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + ssize_t size; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + size = smu->ppt_funcs->get_gpu_metrics(smu, table); + + mutex_unlock(&smu->mutex); + + return size; +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index b57b10406390..a08155b83289 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -589,6 +589,7 @@ struct pptable_funcs { void (*log_thermal_throttling_event)(struct smu_context *smu); size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); + ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); }; typedef enum { @@ -791,5 +792,7 @@ int smu_get_dpm_clock_table(struct smu_context *smu, int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); + #endif #endif -- cgit v1.2.3 From e4c9200df51033e2394c165fdafb183dbd6100ab Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 24 Jul 2020 18:39:33 +0800 Subject: drm/amd/powerplay: implement SMU V11 common APIs for retrieving link speed/width This will be shared around all SMU V11 asics. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 8 ++++ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 9 +--- drivers/gpu/drm/amd/powerplay/navi10_ppt.h | 3 -- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 8 +--- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h | 3 -- drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 53 ++++++++++++++++++++++ 6 files changed, 65 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') 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 6a42331aba8a..aeb12654257e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -264,5 +264,13 @@ int smu_v11_0_get_dpm_level_range(struct smu_context *smu, uint32_t *min_value, uint32_t *max_value); +int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu); + +int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index c33bdc6747f2..45d2d6c2481c 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -917,7 +917,6 @@ static int navi10_print_clk_levels(struct smu_context *smu, uint32_t gen_speed, lane_width; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - struct amdgpu_device *adev = smu->adev; PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; OverDriveTable_t *od_table = (OverDriveTable_t *)table_context->overdrive_table; @@ -971,12 +970,8 @@ static int navi10_print_clk_levels(struct smu_context *smu, } break; case SMU_PCIE: - gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu); + lane_width = smu_v11_0_get_current_pcie_link_width_level(smu); for (i = 0; i < NUM_LINK_LEVELS; i++) size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h index 2abb4ba01db1..84dc5a1b6830 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h @@ -49,9 +49,6 @@ #define NAVI10_VOLTAGE_SCALE (4) -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - extern void navi10_set_ppt_funcs(struct smu_context *smu); #endif diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f373e2d0d31c..05ad29fcfe68 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -960,12 +960,8 @@ static int sienna_cichlid_print_clk_levels(struct smu_context *smu, } break; case SMU_PCIE: - gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + gen_speed = smu_v11_0_get_current_pcie_link_speed(smu); + lane_width = smu_v11_0_get_current_pcie_link_width(smu); for (i = 0; i < NUM_LINK_LEVELS; i++) size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h index 8078886e4cbc..57e120c440ea 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h @@ -31,7 +31,4 @@ typedef enum { extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index 7d7de854a826..ff90e20eed5c 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -67,6 +67,19 @@ MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin"); #define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 + +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4 +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE + +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + int smu_v11_0_init_microcode(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -1918,3 +1931,43 @@ int smu_v11_0_get_dpm_level_range(struct smu_context *smu, return ret; } + +int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu) +{ + uint32_t width_level; + + width_level = smu_v11_0_get_current_pcie_link_width_level(smu); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) +{ + uint32_t speed_level; + + speed_level = smu_v11_0_get_current_pcie_link_speed_level(smu); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} -- cgit v1.2.3 From f1c378593153c93ed1db6ec8c025fa388474dd12 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 24 Jul 2020 10:42:39 +0800 Subject: drm/amd/powerplay: add Arcturus support for gpu metrics export Add Arcturus gpu metrics export interface. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 92 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 + drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 + drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 14 ++++ 4 files changed, 111 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index d292898120be..5aa0d5b03f7e 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -79,6 +79,8 @@ /* possible frequency drift (1Mhz) */ #define EPSILON 1 +#define smnPCIE_ESM_CTRL 0x111003D0 + static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), @@ -234,6 +236,13 @@ static int arcturus_tables_init(struct smu_context *smu) return -ENOMEM; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) { + kfree(smu_table->metrics_table); + return -ENOMEM; + } + return 0; } @@ -2242,6 +2251,88 @@ static void arcturus_log_thermal_throttling_event(struct smu_context *smu) kgd2kfd_smi_event_throttle(smu->adev->kfd.dev, throttler_status); } +static int arcturus_get_current_pcie_link_speed(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t esm_ctrl; + + /* TODO: confirm this on real target */ + esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL); + if ((esm_ctrl >> 15) & 0x1FFFF) + return (((esm_ctrl >> 8) & 0x3F) + 128); + + return smu_v11_0_get_current_pcie_link_speed(smu); +} + +static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + arcturus_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pptable_funcs arcturus_ppt_funcs = { /* init dpm */ .get_allowed_feature_mask = arcturus_get_allowed_feature_mask, @@ -2319,6 +2410,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .log_thermal_throttling_event = arcturus_log_thermal_throttling_event, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = arcturus_get_gpu_metrics, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index a08155b83289..ec2d2aa7f4ec 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -274,6 +274,9 @@ struct smu_table_context void *overdrive_table; void *boot_overdrive_table; + + uint32_t gpu_metrics_table_size; + void *gpu_metrics_table; }; struct smu_dpm_context { diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index aeb12654257e..f2a522176ca0 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -272,5 +272,7 @@ int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu); int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); +void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c index ff90e20eed5c..ff574ebc179e 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c @@ -417,10 +417,12 @@ int smu_v11_0_fini_smc_tables(struct smu_context *smu) struct smu_table_context *smu_table = &smu->smu_table; struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + kfree(smu_table->gpu_metrics_table); kfree(smu_table->boot_overdrive_table); kfree(smu_table->overdrive_table); kfree(smu_table->max_sustainable_clocks); kfree(smu_table->driver_pptable); + smu_table->gpu_metrics_table = NULL; smu_table->boot_overdrive_table = NULL; smu_table->overdrive_table = NULL; smu_table->max_sustainable_clocks = NULL; @@ -1971,3 +1973,15 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) return link_speed[speed_level]; } + +void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} -- cgit v1.2.3 From 14a12beab8b9d943edd3bfaac8fd31f4aa578e43 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 24 Jul 2020 17:47:03 +0800 Subject: drm/amd/powerplay: update the data structure for NV12 SmuMetrics Although it does not bring any problem for now, the coming gpu metrics interface needs to handle them differently based on the asic type. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../drm/amd/powerplay/inc/smu11_driver_if_navi10.h | 39 ++++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 18 ++++++++-- 2 files changed, 54 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h index 4b2da98afcd2..246d3951a78a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h @@ -884,6 +884,45 @@ typedef struct { uint32_t MmHubPadding[8]; // SMU internal use } SmuMetrics_t; +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureMem ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureLiquid0 ; + uint16_t TemperatureLiquid1 ; + uint16_t TemperaturePlx ; + uint16_t Padding16 ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t Padding8_2; + uint16_t CurrFanSpeed; + + uint32_t EnergyAccumulator; + uint16_t AverageVclkFrequency ; + uint16_t AverageDclkFrequency ; + uint16_t VcnActivityPercentage ; + uint16_t padding16_2; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetrics_NV12_t; + typedef struct { uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 45d2d6c2481c..fc29d290f596 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -456,13 +456,18 @@ static int navi10_tables_init(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; struct smu_table *tables = smu_table->tables; + struct amdgpu_device *adev = smu->adev; SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + if (adev->asic_type == CHIP_NAVI12) + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV12_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + else + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), @@ -473,7 +478,9 @@ static int navi10_tables_init(struct smu_context *smu) sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + smu_table->metrics_table = kzalloc(adev->asic_type == CHIP_NAVI12 ? + sizeof(SmuMetrics_NV12_t) : + sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) return -ENOMEM; smu_table->metrics_time = 0; @@ -490,6 +497,11 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, uint32_t *value) { struct smu_table_context *smu_table= &smu->smu_table; + /* + * This works for NV12 also. As although NV12 uses a different + * SmuMetrics structure from other NV1X ASICs, they share the + * same offsets for the heading parts(those members used here). + */ SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; -- cgit v1.2.3 From 6d4ff50a27749fdce0a8b8c674d9b9db13d9824d Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 24 Jul 2020 17:24:34 +0800 Subject: drm/amd/powerplay: add Navi1x support for gpu metrics export Add Navi1x gpu metrics export interface. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 93 +++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index fc29d290f596..0c5667db136b 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -482,14 +482,26 @@ static int navi10_tables_init(struct smu_context *smu) sizeof(SmuMetrics_NV12_t) : sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; } static int navi10_get_smu_metrics_data(struct smu_context *smu, @@ -2487,6 +2499,82 @@ static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter i2c_del_adapter(control); } +static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + struct amdgpu_device *adev = smu->adev; + SmuMetrics_NV12_t nv12_metrics = { 0 }; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + if (adev->asic_type == CHIP_NAVI12) + memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + if (adev->asic_type == CHIP_NAVI12) { + gpu_metrics->energy_accumulator = nv12_metrics.EnergyAccumulator; + gpu_metrics->average_vclk0_frequency = nv12_metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = nv12_metrics.AverageDclkFrequency; + gpu_metrics->average_mm_activity = nv12_metrics.VcnActivityPercentage; + } + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} static const struct pptable_funcs navi10_ppt_funcs = { .get_allowed_feature_mask = navi10_get_allowed_feature_mask, @@ -2568,6 +2656,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_power_source = smu_v11_0_set_power_source, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = navi10_get_gpu_metrics, }; void navi10_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From 8ca78a0a0e7719d1045c50e0876299c94b6454a2 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 27 Jul 2020 10:00:47 +0800 Subject: drm/amd/powerplay: add Sienna Cichlid support for gpu metrics export Add Sienna Cichlid gpu metrics export interface. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 91 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 05ad29fcfe68..f86c3cdd3b1c 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -385,14 +385,26 @@ static int sienna_cichlid_tables_init(struct smu_context *smu) smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_time = 0; + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; } static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, @@ -2649,6 +2661,80 @@ static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_ i2c_del_adapter(control); } +static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + mutex_unlock(&smu->metrics_lock); + return ret; + } + smu_table->metrics_time = jiffies; + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + if (metrics.AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs; + else + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclk0Frequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclk0Frequency; + gpu_metrics->average_vclk1_frequency = metrics.AverageVclk1Frequency; + gpu_metrics->average_dclk1_frequency = metrics.AverageDclk1Frequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK_0]; + gpu_metrics->current_vclk1 = metrics.CurrClock[PPCLK_VCLK_1]; + gpu_metrics->current_dclk1 = metrics.CurrClock[PPCLK_DCLK_1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, @@ -2726,6 +2812,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From 95868b85764aff2dcbf78d3054076df75446ad15 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 27 Jul 2020 16:24:46 +0800 Subject: drm/amd/powerplay: add Renoir support for gpu metrics export(V2) Add Renoir gpu metrics export interface. V2: use memcpy to make code more compact Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h | 2 + drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 80 ++++++++++++++++++++++++++- drivers/gpu/drm/amd/powerplay/smu_v12_0.c | 12 ++++ 3 files changed, 91 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h index 02de3b6199e5..fa2e8cb07967 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h @@ -60,5 +60,7 @@ int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_ int smu_v12_0_set_driver_table_location(struct smu_context *smu); +void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics); + #endif #endif diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 575ae4be98a2..61e8700a7bdb 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -166,18 +166,32 @@ static int renoir_init_smc_tables(struct smu_context *smu) smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); if (!smu_table->clocks_table) - return -ENOMEM; + goto err0_out; smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); if (!smu_table->metrics_table) - return -ENOMEM; + goto err1_out; smu_table->metrics_time = 0; smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); if (!smu_table->watermarks_table) - return -ENOMEM; + goto err2_out; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err3_out; return 0; + +err3_out: + kfree(smu_table->watermarks_table); +err2_out: + kfree(smu_table->metrics_table); +err1_out: + kfree(smu_table->clocks_table); +err0_out: + return -ENOMEM; } /** @@ -995,6 +1009,65 @@ static bool renoir_is_dpm_running(struct smu_context *smu) } +static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v2_0 *gpu_metrics = + (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = renoir_get_metrics_table(smu, &metrics); + if (ret) + return ret; + + smu_v12_0_init_gpu_metrics_v2_0(gpu_metrics); + + gpu_metrics->temperature_gfx = metrics.GfxTemperature; + gpu_metrics->temperature_soc = metrics.SocTemperature; + memcpy(&gpu_metrics->temperature_core[0], + &metrics.CoreTemperature[0], + sizeof(uint16_t) * 8); + gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; + gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_mm_activity = metrics.AverageUvdActivity; + + gpu_metrics->average_socket_power = metrics.CurrentSocketPower; + gpu_metrics->average_cpu_power = metrics.Power[0]; + gpu_metrics->average_soc_power = metrics.Power[1]; + memcpy(&gpu_metrics->average_core_power[0], + &metrics.CorePower[0], + sizeof(uint16_t) * 8); + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency; + gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency; + + gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK]; + gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK]; + gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK]; + gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK]; + gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK]; + gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK]; + memcpy(&gpu_metrics->current_coreclk[0], + &metrics.CoreFrequency[0], + sizeof(uint16_t) * 8); + gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; + gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->fan_pwm = metrics.FanPwm; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v2_0); +} + static const struct pptable_funcs renoir_ppt_funcs = { .set_power_state = NULL, .print_clk_levels = renoir_print_clk_levels, @@ -1029,6 +1102,7 @@ static const struct pptable_funcs renoir_ppt_funcs = { .is_dpm_running = renoir_is_dpm_running, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = renoir_get_gpu_metrics, }; void renoir_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c index 31456437bb18..660f403d5770 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c +++ b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c @@ -274,3 +274,15 @@ int smu_v12_0_set_driver_table_location(struct smu_context *smu) return ret; } + +void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v2_0); + gpu_metrics->common_header.format_revision = 2; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} -- cgit v1.2.3 From 0b01b8306789b0c07c5bf2d6f9134f8b30990932 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 11:40:07 +0800 Subject: drm/amd/powerplay: enable gpu_metrics export on legacy powerplay routines Enable gpu_metrics support on legacy powerplay routines. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 1 + 2 files changed, 20 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 7e6dcdf7df73..a6321f2063c1 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -1598,6 +1598,24 @@ static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) return 0; } +static ssize_t pp_get_gpu_metrics(void *handle, void **table) +{ + struct pp_hwmgr *hwmgr = handle; + ssize_t size; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&hwmgr->smu_lock); + size = hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); + mutex_unlock(&hwmgr->smu_lock); + + return size; +} + static const struct amd_pm_funcs pp_dpm_funcs = { .load_firmware = pp_dpm_load_fw, .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, @@ -1658,4 +1676,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .smu_i2c_bus_access = pp_smu_i2c_bus_access, .set_df_cstate = pp_set_df_cstate, .set_xgmi_pstate = pp_set_xgmi_pstate, + .get_gpu_metrics = pp_get_gpu_metrics, }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 15ed6cbdf366..1b3529efc91e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -359,6 +359,7 @@ struct pp_hwmgr_func { int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate); int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr, bool disable); + ssize_t (*get_gpu_metrics)(struct pp_hwmgr *hwmgr, void **table); }; struct pp_table_func { -- cgit v1.2.3 From e467c3a9f4ed143fd2ea3f9aef7672d3674de9f4 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 12:23:42 +0800 Subject: drm/amd/powerplay: add Vega20 support for gpu metrics export Add Vega20 gpu metrics export interface. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 123 +++++++++++++++++++-- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h | 1 + 2 files changed, 117 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index bacbe2fa1f9a..037bebda2eae 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -55,6 +55,11 @@ #define smnPCIE_LC_SPEED_CNTL 0x11140290 #define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) { struct vega20_hwmgr *data = @@ -3265,6 +3270,46 @@ static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return 0; } +static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega20_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { @@ -3277,7 +3322,6 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable; - struct amdgpu_device *adev = hwmgr->adev; struct pp_clock_levels_with_latency clocks; struct vega20_single_dpm_table *fclk_dpm_table = &(data->dpm_table.fclk_table); @@ -3371,12 +3415,10 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, break; case PP_PCIE: - current_gen_speed = (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - current_lane_width = (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; + current_gen_speed = + vega20_get_current_pcie_link_speed_level(hwmgr); + current_lane_width = + vega20_get_current_pcie_link_width_level(hwmgr); for (i = 0; i < NUM_LINK_LEVELS; i++) { if (i == 1 && data->pcie_parameters_override) { gen_speed = data->pcie_gen_level1; @@ -4218,6 +4260,72 @@ static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, return ret; } +static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega20_get_metrics_table(hwmgr, &metrics); + if (ret) + return ret; + + vega20_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega20_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega20_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pp_hwmgr_func vega20_hwmgr_funcs = { /* init/fini related */ .backend_init = vega20_hwmgr_backend_init, @@ -4288,6 +4396,7 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { .smu_i2c_bus_access = vega20_smu_i2c_bus_access, .set_df_cstate = vega20_set_df_cstate, .set_xgmi_pstate = vega20_set_xgmi_pstate, + .get_gpu_metrics = vega20_get_gpu_metrics, }; int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h index 2c3125f82b24..075c0094da9c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h @@ -527,6 +527,7 @@ struct vega20_hwmgr { unsigned long metrics_time; SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; bool pcie_parameters_override; uint32_t pcie_gen_level1; -- cgit v1.2.3 From 0fbc6533de67f49815e5bd7232cbd37fb68c6afa Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 12:39:58 +0800 Subject: drm/amd/powerplay: add Vega12 support for gpu metrics export Add Vega12 gpu metrics export interface. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 111 +++++++++++++++++++++ drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h | 1 + 2 files changed, 112 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index a678a67f1c0d..40bb0c2e4e8c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -47,6 +47,13 @@ #include "pp_thermal.h" #include "vega12_baco.h" +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 + +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); @@ -2095,6 +2102,46 @@ static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return 0; } +static int vega12_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega12_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega12_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega12_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega12_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega12_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { @@ -2682,6 +2729,69 @@ static int vega12_set_mp1_state(struct pp_hwmgr *hwmgr, return 0; } +static void vega12_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega12_get_metrics_table(hwmgr, &metrics); + if (ret) + return ret; + + vega12_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega12_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega12_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega12_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + static const struct pp_hwmgr_func vega12_hwmgr_funcs = { .backend_init = vega12_hwmgr_backend_init, .backend_fini = vega12_hwmgr_backend_fini, @@ -2739,6 +2849,7 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = { .get_ppfeature_status = vega12_get_ppfeature_status, .set_ppfeature_status = vega12_set_ppfeature_status, .set_mp1_state = vega12_set_mp1_state, + .get_gpu_metrics = vega12_get_gpu_metrics, }; int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h index 73875399666a..aa63ae41942d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h @@ -399,6 +399,7 @@ struct vega12_hwmgr { unsigned long metrics_time; SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; }; #define VEGA12_DPM2_NEAR_TDP_DEC 10 -- cgit v1.2.3 From 345fcb02d9ec4cf5eae19d063dfb27f152bde291 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 14:31:21 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Arcturus As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 74 ++++++++++++++++++---------- 1 file changed, 49 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 5aa0d5b03f7e..e3a2d7f0aba1 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -541,18 +541,16 @@ static int arcturus_freqs_in_same_level(int32_t frequency1, return (abs(frequency1 - frequency2) <= EPSILON); } -static int arcturus_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int arcturus_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -560,12 +558,50 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int arcturus_get_metrics_table(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = arcturus_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int arcturus_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = arcturus_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2273,23 +2309,11 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); + ret = arcturus_get_metrics_table(smu, + &metrics, + true); + if (ret) return ret; - } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); -- cgit v1.2.3 From 62d351632db8908e8bb5b359182b6ead54147e71 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 14:55:32 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Navi10 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 60 +++++++++++++++++++----------- 1 file changed, 38 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 0c5667db136b..8c45c472f7f2 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -504,22 +504,16 @@ err0_out: return -ENOMEM; } -static int navi10_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int navi10_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - /* - * This works for NV12 also. As although NV12 uses a different - * SmuMetrics structure from other NV1X ASICs, they share the - * same offsets for the heading parts(those members used here). - */ - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -527,12 +521,40 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int navi10_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + /* + * This works for NV12 also. As although NV12 uses a different + * SmuMetrics structure from other NV1X ASICs, they share the + * same offsets for the heading parts(those members used here). + */ + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = navi10_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2512,19 +2534,13 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); + ret = navi10_get_metrics_table_locked(smu, + &metrics, + true); if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); mutex_unlock(&smu->metrics_lock); return ret; } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); if (adev->asic_type == CHIP_NAVI12) memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); -- cgit v1.2.3 From 60ae4d67ee6d804215067f49e183214de405302b Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 15:09:57 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Sienna Cichlid As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 73 +++++++++++++++------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index f86c3cdd3b1c..2566ae5df64b 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -407,17 +407,16 @@ err0_out: return -ENOMEM; } -static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) +static int sienna_cichlid_get_metrics_table_locked(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; int ret = 0; - mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, @@ -425,12 +424,50 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, false); if (ret) { dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); return ret; } smu_table->metrics_time = jiffies; } + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + + return 0; +} + +static int sienna_cichlid_get_metrics_table(struct smu_context *smu, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = sienna_cichlid_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = sienna_cichlid_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + switch (member) { case METRICS_CURR_GFXCLK: *value = metrics->CurrClock[PPCLK_GFXCLK]; @@ -2670,23 +2707,11 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); + ret = sienna_cichlid_get_metrics_table(smu, + &metrics, + true); + if (ret) return ret; - } - smu_table->metrics_time = jiffies; - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); -- cgit v1.2.3 From 2ba38817219bfbae3cf870cb0092afb12f616fd3 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 15:02:11 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Renoir As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 61e8700a7bdb..4c1a506c3c17 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -129,13 +129,17 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = }; static int renoir_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table) + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct smu_table_context *smu_table= &smu->smu_table; int ret = 0; mutex_lock(&smu->metrics_lock); - if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { + + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)smu_table->metrics_table, false); if (ret) { @@ -146,7 +150,9 @@ static int renoir_get_metrics_table(struct smu_context *smu, smu_table->metrics_time = jiffies; } - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); + mutex_unlock(&smu->metrics_lock); return ret; @@ -375,7 +381,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, memset(&metrics, 0, sizeof(metrics)); - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -529,7 +535,7 @@ static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, int ret = 0, clk_id = 0; SmuMetrics_t metrics; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -612,7 +618,7 @@ static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -632,7 +638,7 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -1018,7 +1024,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = renoir_get_metrics_table(smu, &metrics); + ret = renoir_get_metrics_table(smu, &metrics, true); if (ret) return ret; -- cgit v1.2.3 From 740dce9517cb4f67f762131b4f62584e65b97593 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 15:24:08 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Vega20 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 31 +++++++++++++--------- 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 037bebda2eae..86d3a10379be 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -2090,22 +2090,29 @@ static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) return (mem_clk * 100); } -static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table) +static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); int ret = 0; - if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) { - ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table, - TABLE_SMU_METRICS, true); + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + HZ / 2)) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); if (ret) { pr_info("Failed to export SMU metrics table!\n"); return ret; } - memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t)); data->metrics_time = jiffies; - } else + } + + if (metrics_table) memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); return ret; @@ -2117,7 +2124,7 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, int ret = 0; SmuMetrics_t metrics_table; - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2155,7 +2162,7 @@ static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, int ret = 0; SmuMetrics_t metrics_table; - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2185,7 +2192,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, switch (idx) { case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2210,7 +2217,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2219,7 +2226,7 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table); + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -4283,7 +4290,7 @@ static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, uint32_t fan_speed_rpm; int ret; - ret = vega20_get_metrics_table(hwmgr, &metrics); + ret = vega20_get_metrics_table(hwmgr, &metrics, true); if (ret) return ret; -- cgit v1.2.3 From bf1102877751175fe6c1d68734d3c57d4af65df9 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 30 Jul 2020 15:28:40 +0800 Subject: drm/amd/powerplay: add control method to bypass metrics cache on Vega12 As for the gpu metric export, metrics cache makes no sense. It's up to user to decide how often the metrics should be retrieved. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 29 ++++++++++++++-------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 40bb0c2e4e8c..c70c30175801 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -1262,22 +1262,29 @@ static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) return (mem_clk * 100); } -static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, SmuMetrics_t *metrics_table) +static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) { struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); int ret = 0; - if (!data->metrics_time || time_after(jiffies, data->metrics_time + HZ / 2)) { - ret = smum_smc_table_manager(hwmgr, (uint8_t *)metrics_table, - TABLE_SMU_METRICS, true); + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + HZ / 2)) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); if (ret) { pr_info("Failed to export SMU metrics table!\n"); return ret; } - memcpy(&data->metrics_table, metrics_table, sizeof(SmuMetrics_t)); data->metrics_time = jiffies; - } else + } + + if (metrics_table) memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); return ret; @@ -1288,7 +1295,7 @@ static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr, uint32_t *query) SmuMetrics_t metrics_table; int ret = 0; - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1339,7 +1346,7 @@ static int vega12_get_current_activity_percent( SmuMetrics_t metrics_table; int ret = 0; - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1387,7 +1394,7 @@ static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -1396,7 +1403,7 @@ static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, *size = 4; break; case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table); + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); if (ret) return ret; @@ -2752,7 +2759,7 @@ static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, uint32_t fan_speed_rpm; int ret; - ret = vega12_get_metrics_table(hwmgr, &metrics); + ret = vega12_get_metrics_table(hwmgr, &metrics, true); if (ret) return ret; -- cgit v1.2.3 From 16c642ec3fe9a144fbe1e97dc56f13a6308f1381 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Thu, 30 Jul 2020 15:54:59 +0200 Subject: drm/amdgpu: new ids flag for tmz (v2) Allows UMD to know if TMZ is supported and enabled. This commit also bumps KMS_DRIVER_MINOR because if we don't UMD can't tell if "ids_flags & AMDGPU_IDS_FLAGS_TMZ == 0" means "tmz is not enabled" or "tmz may be enabled but the kernel doesn't report it". v2: use amdgpu_is_tmz() and reworded commit message. Signed-off-by: Pierre-Eric Pelloux-Prayer Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 2 ++ include/uapi/drm/amdgpu_drm.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 5156c67ec67b..92d0368217a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -88,9 +88,10 @@ * - 3.37.0 - L2 is invalidated before SDMA IBs, needed for correctness * - 3.38.0 - Add AMDGPU_IB_FLAG_EMIT_MEM_SYNC * - 3.39.0 - DMABUF implicit sync does a full pipeline sync + * - 3.40.0 - Add AMDGPU_IDS_FLAGS_TMZ */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 39 +#define KMS_DRIVER_MINOR 40 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index e99ad031efd4..58580a48b648 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -737,6 +737,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file dev_info.ids_flags |= AMDGPU_IDS_FLAGS_FUSION; if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) dev_info.ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION; + if (amdgpu_is_tmz(adev)) + dev_info.ids_flags |= AMDGPU_IDS_FLAGS_TMZ; vm_size = adev->vm_manager.max_pfn * AMDGPU_GPU_PAGE_SIZE; vm_size -= AMDGPU_VA_RESERVED_SIZE; diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 3218576e109d..c5ff2b275fcd 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -673,6 +673,7 @@ struct drm_amdgpu_cs_chunk_data { */ #define AMDGPU_IDS_FLAGS_FUSION 0x1 #define AMDGPU_IDS_FLAGS_PREEMPTION 0x2 +#define AMDGPU_IDS_FLAGS_TMZ 0x4 /* indicate if acceleration can be working */ #define AMDGPU_INFO_ACCEL_WORKING 0x00 -- cgit v1.2.3 From efa85f3a2b535bbc51e43a191b40f258538425b0 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Thu, 6 Aug 2020 14:41:06 +0800 Subject: drm/amd/powerplay: update driver if file for sienna_cichlid Update drive if file for sienna_cichlid. Signed-off-by: Likun Gao Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h | 6 +++--- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 aa2708fccb6d..5ef9c92f57c4 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h @@ -27,7 +27,7 @@ // *** IMPORTANT *** // SMU TEAM: Always increment the interface version if // any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x34 +#define SMU11_DRIVER_IF_VERSION 0x35 #define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 @@ -127,7 +127,7 @@ #define FEATURE_DF_CSTATE_BIT 45 #define FEATURE_2_STEP_PSTATE_BIT 46 #define FEATURE_SMNCLK_DPM_BIT 47 -#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_PERLINK_GMIDOWN_BIT 48 #define FEATURE_GFX_EDC_BIT 49 #define FEATURE_SPARE_50_BIT 50 #define FEATURE_SPARE_51_BIT 51 @@ -169,7 +169,7 @@ typedef enum { #define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 #define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 #define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCEFCLK 0x00000800 -#define DPM_OVERRIDE_DISABLE_FAST_FCLK_TIMER 0x00001000 +#define DPM_OVERRIDE_ENABLE_FAST_FCLK_TIMER 0x00001000 #define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 #define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h index f2a522176ca0..ee1506beb0ea 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -30,7 +30,7 @@ #define SMU11_DRIVER_IF_VERSION_NV10 0x36 #define SMU11_DRIVER_IF_VERSION_NV12 0x33 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 -#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x34 +#define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 /* MP Apertures */ -- cgit v1.2.3 From 707477b0861f5d7b93512024db8d39db5a65025c Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jul 2020 09:44:26 -0400 Subject: drm/amd/display: Store tiling_flags and tmz_surface on dm_plane_state [Why] Store these in advance so we can reuse them later in commit_tail without having to reserve the fbo again. These will also be used for checking for tiling changes when deciding to reset the plane or not. [How] This change should mostly be a refactor. Only commit check is affected for now and I'll drop the get_fb_info calls in prepare_planes and commit_tail after. This runs a prepass loop once we think that all planes have been added to the context and replaces the get_fb_info calls with accessing the dm_plane_state instead. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 60 +++++++++++++---------- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 2 + 2 files changed, 37 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') 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 7f6a91b4fe4e..81eeaff3acb1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3627,8 +3627,17 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state, static int get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb, uint64_t *tiling_flags, bool *tmz_surface) { - struct amdgpu_bo *rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); - int r = amdgpu_bo_reserve(rbo, false); + struct amdgpu_bo *rbo; + int r; + + if (!amdgpu_fb) { + *tiling_flags = 0; + *tmz_surface = false; + return 0; + } + + rbo = gem_to_amdgpu_bo(amdgpu_fb->base.obj[0]); + r = amdgpu_bo_reserve(rbo, false); if (unlikely(r)) { /* Don't show error message when returning -ERESTARTSYS */ @@ -4051,13 +4060,10 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, struct drm_crtc_state *crtc_state) { struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state); - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(plane_state->fb); + struct dm_plane_state *dm_plane_state = to_dm_plane_state(plane_state); struct dc_scaling_info scaling_info; struct dc_plane_info plane_info; - uint64_t tiling_flags; int ret; - bool tmz_surface = false; bool force_disable_dcc = false; ret = fill_dc_scaling_info(plane_state, &scaling_info); @@ -4069,15 +4075,12 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev, dc_plane_state->clip_rect = scaling_info.clip_rect; dc_plane_state->scaling_quality = scaling_info.scaling_quality; - ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface); - if (ret) - return ret; - force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend; - ret = fill_dc_plane_info_and_addr(adev, plane_state, tiling_flags, + ret = fill_dc_plane_info_and_addr(adev, plane_state, + dm_plane_state->tiling_flags, &plane_info, &dc_plane_state->address, - tmz_surface, + dm_plane_state->tmz_surface, force_disable_dcc); if (ret) return ret; @@ -5675,6 +5678,10 @@ dm_drm_plane_duplicate_state(struct drm_plane *plane) dc_plane_state_retain(dm_plane_state->dc_state); } + /* Framebuffer hasn't been updated yet, so retain old flags. */ + dm_plane_state->tiling_flags = old_dm_plane_state->tiling_flags; + dm_plane_state->tmz_surface = old_dm_plane_state->tmz_surface; + return &dm_plane_state->base; } @@ -8482,13 +8489,9 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, continue; for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { - const struct amdgpu_framebuffer *amdgpu_fb = - to_amdgpu_framebuffer(new_plane_state->fb); struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane]; struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane]; struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane]; - uint64_t tiling_flags; - bool tmz_surface = false; new_plane_crtc = new_plane_state->crtc; new_dm_plane_state = to_dm_plane_state(new_plane_state); @@ -8535,16 +8538,12 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, bundle->surface_updates[num_plane].scaling_info = scaling_info; - if (amdgpu_fb) { - ret = get_fb_info(amdgpu_fb, &tiling_flags, &tmz_surface); - if (ret) - goto cleanup; - + if (new_plane_state->fb) { ret = fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, tiling_flags, - plane_info, - &flip_addr->address, tmz_surface, - false); + dm->adev, new_plane_state, + new_dm_plane_state->tiling_flags, + plane_info, &flip_addr->address, + new_dm_plane_state->tmz_surface, false); if (ret) goto cleanup; @@ -8758,6 +8757,17 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, } } + /* Prepass for updating tiling flags on new planes. */ + for_each_new_plane_in_state(state, plane, new_plane_state, i) { + struct dm_plane_state *new_dm_plane_state = to_dm_plane_state(new_plane_state); + struct amdgpu_framebuffer *new_afb = to_amdgpu_framebuffer(new_plane_state->fb); + + ret = get_fb_info(new_afb, &new_dm_plane_state->tiling_flags, + &new_dm_plane_state->tmz_surface); + if (ret) + goto fail; + } + /* Remove exiting planes if they are modified */ for_each_oldnew_plane_in_state_reverse(state, plane, old_plane_state, new_plane_state, i) { ret = dm_update_plane_state(dc, state, plane, diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index fd863331dee1..a7856ae2e5f5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -412,6 +412,8 @@ struct dc_plane_state; struct dm_plane_state { struct drm_plane_state base; struct dc_plane_state *dc_state; + uint64_t tiling_flags; + bool tmz_surface; }; struct dm_crtc_state { -- cgit v1.2.3 From 9a81cc60796b9f86cf19245e68562750541bb575 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jul 2020 09:59:53 -0400 Subject: drm/amd/display: Reset plane when tiling flags change [Why] Enabling or disable DCC or switching between tiled and linear formats can require bandwidth updates. They're currently skipping all DC validation by being treated as purely surface updates. [How] Treat tiling_flag changes (which encode DCC state) as a condition for resetting the plane. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') 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 81eeaff3acb1..89083210855d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8258,6 +8258,8 @@ static bool should_reset_plane(struct drm_atomic_state *state, * TODO: Come up with a more elegant solution for this. */ for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) { + struct dm_plane_state *old_dm_plane_state, *new_dm_plane_state; + if (other->type == DRM_PLANE_TYPE_CURSOR) continue; @@ -8268,9 +8270,20 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (old_other_state->crtc != new_other_state->crtc) return true; - /* TODO: Remove this once we can handle fast format changes. */ - if (old_other_state->fb && new_other_state->fb && - old_other_state->fb->format != new_other_state->fb->format) + /* Framebuffer checks fall at the end. */ + if (!old_other_state->fb || !new_other_state->fb) + continue; + + /* Pixel format changes can require bandwidth updates. */ + if (old_other_state->fb->format != new_other_state->fb->format) + return true; + + old_dm_plane_state = to_dm_plane_state(old_other_state); + new_dm_plane_state = to_dm_plane_state(new_other_state); + + /* Tiling and DCC changes also require bandwidth updates. */ + if (old_dm_plane_state->tiling_flags != + new_dm_plane_state->tiling_flags) return true; } -- cgit v1.2.3 From cf322b49c9e8fe41e5c9d0b5e57eee84085da553 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jul 2020 10:03:10 -0400 Subject: drm/amd/display: Avoid using unvalidated tiling_flags and tmz_surface in prepare_planes [Why] We're racing with userspace as the flags could potentially change from when we acquired and validated them in commit_check. [How] We unfortunately can't drop this function in its entirety from prepare_planes since we don't know the afb->address at commit_check time yet. So instead of querying new tiling_flags and tmz_surface use the ones from the plane_state directly. While we're at it, also update the force_disable_dcc option based on the state from atomic check. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 36 ++++++++++++----------- 1 file changed, 19 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') 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 89083210855d..03534ff0c895 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5716,14 +5716,8 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, struct list_head list; struct ttm_validate_buffer tv; struct ww_acquire_ctx ticket; - uint64_t tiling_flags; uint32_t domain; int r; - bool tmz_surface = false; - bool force_disable_dcc = false; - - dm_plane_state_old = to_dm_plane_state(plane->state); - dm_plane_state_new = to_dm_plane_state(new_state); if (!new_state->fb) { DRM_DEBUG_DRIVER("No FB bound\n"); @@ -5767,27 +5761,35 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane, return r; } - amdgpu_bo_get_tiling_flags(rbo, &tiling_flags); - - tmz_surface = amdgpu_bo_encrypted(rbo); - ttm_eu_backoff_reservation(&ticket, &list); afb->address = amdgpu_bo_gpu_offset(rbo); amdgpu_bo_ref(rbo); + /** + * We don't do surface updates on planes that have been newly created, + * but we also don't have the afb->address during atomic check. + * + * Fill in buffer attributes depending on the address here, but only on + * newly created planes since they're not being used by DC yet and this + * won't modify global state. + */ + dm_plane_state_old = to_dm_plane_state(plane->state); + dm_plane_state_new = to_dm_plane_state(new_state); + if (dm_plane_state_new->dc_state && - dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { - struct dc_plane_state *plane_state = dm_plane_state_new->dc_state; + dm_plane_state_old->dc_state != dm_plane_state_new->dc_state) { + struct dc_plane_state *plane_state = + dm_plane_state_new->dc_state; + bool force_disable_dcc = !plane_state->dcc.enable; - force_disable_dcc = adev->asic_type == CHIP_RAVEN && adev->in_suspend; fill_plane_buffer_attributes( adev, afb, plane_state->format, plane_state->rotation, - tiling_flags, &plane_state->tiling_info, - &plane_state->plane_size, &plane_state->dcc, - &plane_state->address, tmz_surface, - force_disable_dcc); + dm_plane_state_new->tiling_flags, + &plane_state->tiling_info, &plane_state->plane_size, + &plane_state->dcc, &plane_state->address, + dm_plane_state_new->tmz_surface, force_disable_dcc); } return 0; -- cgit v1.2.3 From 8ce5d8425d39eb9197e30bcffc5afbaa7079b723 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Thu, 6 Aug 2020 15:48:10 -0400 Subject: drm/amd/display: Use validated tiling_flags and tmz_surface in commit_tail [Why] So we're not racing with userspace or deadlocking DM. [How] These flags are now stored on dm_plane_state itself and acquried and validated during commit_check, so just use those instead. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') 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 03534ff0c895..c3ac47b835d6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7012,8 +7012,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, long r; unsigned long flags; struct amdgpu_bo *abo; - uint64_t tiling_flags; - bool tmz_surface = false; uint32_t target_vblank, last_flip_vblank; bool vrr_active = amdgpu_dm_vrr_active(acrtc_state); bool pflip_present = false; @@ -7097,21 +7095,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (unlikely(r <= 0)) DRM_ERROR("Waiting for fences timed out!"); - /* - * We cannot reserve buffers here, which means the normal flag - * access functions don't work. Paper over this with READ_ONCE, - * but maybe the flags are invariant enough that not even that - * would be needed. - */ - tiling_flags = READ_ONCE(abo->tiling_flags); - tmz_surface = READ_ONCE(abo->flags) & AMDGPU_GEM_CREATE_ENCRYPTED; - fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, tiling_flags, + dm->adev, new_plane_state, + dm_new_plane_state->tiling_flags, &bundle->plane_infos[planes_count], &bundle->flip_addrs[planes_count].address, - tmz_surface, - false); + dm_new_plane_state->tmz_surface, false); DRM_DEBUG_DRIVER("plane: id=%d dcc_en=%d\n", new_plane_state->plane->index, -- cgit v1.2.3 From dc4cb30deec713888d31ec6d81c8ca34605089d5 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jul 2020 10:48:21 -0400 Subject: drm/amd/display: Reset plane for anything that's not a FAST update [Why] MEDIUM or FULL updates can require global validation or affect bandwidth. By treating these all simply as surface updates we aren't actually passing this through DC global validation. [How] There's currently no way to pass surface updates through DC global validation, nor do I think it's a good idea to change the interface to accept these. DC global validation itself is currently stateless, and we can move our update type checking to be stateless as well by duplicating DC surface checks in DM based on DRM properties. We wanted to rely on DC automatically determining this since DC knows best, but DM is ultimately what fills in everything into DC plane state so it does need to know as well. There are basically only three paths that we exercise in DM today: 1) Cursor (async update) 2) Pageflip (fast update) 3) Full pipe programming (medium/full updates) Which means that anything that's more than a pageflip really needs to go down path #3. So this change duplicates all the surface update checks based on DRM state instead inside of should_reset_plane(). Next step is dropping dm_determine_update_type_for_commit and we no longer require the old DC state at all for global validation. Optimization can come later so we don't reset DC planes at all for MEDIUM udpates and avoid validation, but we might require some extra checks in DM to achieve this. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 25 +++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/gpu') 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 c3ac47b835d6..0b23c4220020 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8261,6 +8261,31 @@ static bool should_reset_plane(struct drm_atomic_state *state, if (old_other_state->crtc != new_other_state->crtc) return true; + /* Src/dst size and scaling updates. */ + if (old_other_state->src_w != new_other_state->src_w || + old_other_state->src_h != new_other_state->src_h || + old_other_state->crtc_w != new_other_state->crtc_w || + old_other_state->crtc_h != new_other_state->crtc_h) + return true; + + /* Rotation / mirroring updates. */ + if (old_other_state->rotation != new_other_state->rotation) + return true; + + /* Blending updates. */ + if (old_other_state->pixel_blend_mode != + new_other_state->pixel_blend_mode) + return true; + + /* Alpha updates. */ + if (old_other_state->alpha != new_other_state->alpha) + return true; + + /* Colorspace changes. */ + if (old_other_state->color_range != new_other_state->color_range || + old_other_state->color_encoding != new_other_state->color_encoding) + return true; + /* Framebuffer checks fall at the end. */ if (!old_other_state->fb || !new_other_state->fb) continue; -- cgit v1.2.3 From f6d7c7faf0ee69569bc2ad309f48ab76785d2972 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Tue, 28 Jul 2020 11:08:02 -0400 Subject: drm/amd/display: Drop dm_determine_update_type_for_commit [Why] This was added in the past to solve the issue of not knowing when to stall for medium and full updates in DM. Since DC is ultimately decides what requires bandwidth changes we wanted to make use of it directly to determine this. The problem is that we can't actually pass any of the stream or surface updates into DC global validation, so we don't actually check if the new configuration is valid - we just validate the old existing config instead and stall for outstanding commits to finish. There's also the problem of grabbing the DRM private object for pageflips which can lead to page faults in the case where commits execute out of order and free a DRM private object state that was still required for commit tail. [How] Now that we reset the plane in DM with the same conditions DC checks we can have planes go through DC validation and we know when we need to check and stall based on whether the stream or planes changed. We mark lock_and_validation_needed whenever we've done this, so just go back to using that instead of dm_determine_update_type_for_commit. Since we'll skip resetting the plane for a pageflip we will no longer grab the DRM private object for pageflips as well, avoiding the page fault issued caused by pageflipping under load with commits executing out of order. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 199 ++-------------------- 1 file changed, 17 insertions(+), 182 deletions(-) (limited to 'drivers/gpu') 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 0b23c4220020..8f27bebf4633 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8466,161 +8466,6 @@ static int dm_update_plane_state(struct dc *dc, return ret; } -static int -dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, - struct drm_atomic_state *state, - enum surface_update_type *out_type) -{ - struct dc *dc = dm->dc; - struct dm_atomic_state *dm_state = NULL, *old_dm_state = NULL; - int i, j, num_plane, ret = 0; - struct drm_plane_state *old_plane_state, *new_plane_state; - struct dm_plane_state *new_dm_plane_state, *old_dm_plane_state; - struct drm_crtc *new_plane_crtc; - struct drm_plane *plane; - - struct drm_crtc *crtc; - struct drm_crtc_state *new_crtc_state, *old_crtc_state; - struct dm_crtc_state *new_dm_crtc_state, *old_dm_crtc_state; - struct dc_stream_status *status = NULL; - enum surface_update_type update_type = UPDATE_TYPE_FAST; - struct surface_info_bundle { - struct dc_surface_update surface_updates[MAX_SURFACES]; - struct dc_plane_info plane_infos[MAX_SURFACES]; - struct dc_scaling_info scaling_infos[MAX_SURFACES]; - struct dc_flip_addrs flip_addrs[MAX_SURFACES]; - struct dc_stream_update stream_update; - } *bundle; - - bundle = kzalloc(sizeof(*bundle), GFP_KERNEL); - - if (!bundle) { - DRM_ERROR("Failed to allocate update bundle\n"); - /* Set type to FULL to avoid crashing in DC*/ - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - - memset(bundle, 0, sizeof(struct surface_info_bundle)); - - new_dm_crtc_state = to_dm_crtc_state(new_crtc_state); - old_dm_crtc_state = to_dm_crtc_state(old_crtc_state); - num_plane = 0; - - if (new_dm_crtc_state->stream != old_dm_crtc_state->stream) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - if (!new_dm_crtc_state->stream) - continue; - - for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, j) { - struct dc_plane_info *plane_info = &bundle->plane_infos[num_plane]; - struct dc_flip_addrs *flip_addr = &bundle->flip_addrs[num_plane]; - struct dc_scaling_info *scaling_info = &bundle->scaling_infos[num_plane]; - - new_plane_crtc = new_plane_state->crtc; - new_dm_plane_state = to_dm_plane_state(new_plane_state); - old_dm_plane_state = to_dm_plane_state(old_plane_state); - - if (plane->type == DRM_PLANE_TYPE_CURSOR) - continue; - - if (new_dm_plane_state->dc_state != old_dm_plane_state->dc_state) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - - if (crtc != new_plane_crtc) - continue; - - bundle->surface_updates[num_plane].surface = - new_dm_plane_state->dc_state; - - if (new_crtc_state->mode_changed) { - bundle->stream_update.dst = new_dm_crtc_state->stream->dst; - bundle->stream_update.src = new_dm_crtc_state->stream->src; - } - - if (new_crtc_state->color_mgmt_changed) { - bundle->surface_updates[num_plane].gamma = - new_dm_plane_state->dc_state->gamma_correction; - bundle->surface_updates[num_plane].in_transfer_func = - new_dm_plane_state->dc_state->in_transfer_func; - bundle->surface_updates[num_plane].gamut_remap_matrix = - &new_dm_plane_state->dc_state->gamut_remap_matrix; - bundle->stream_update.gamut_remap = - &new_dm_crtc_state->stream->gamut_remap_matrix; - bundle->stream_update.output_csc_transform = - &new_dm_crtc_state->stream->csc_color_matrix; - bundle->stream_update.out_transfer_func = - new_dm_crtc_state->stream->out_transfer_func; - } - - ret = fill_dc_scaling_info(new_plane_state, - scaling_info); - if (ret) - goto cleanup; - - bundle->surface_updates[num_plane].scaling_info = scaling_info; - - if (new_plane_state->fb) { - ret = fill_dc_plane_info_and_addr( - dm->adev, new_plane_state, - new_dm_plane_state->tiling_flags, - plane_info, &flip_addr->address, - new_dm_plane_state->tmz_surface, false); - if (ret) - goto cleanup; - - bundle->surface_updates[num_plane].plane_info = plane_info; - bundle->surface_updates[num_plane].flip_addr = flip_addr; - } - - num_plane++; - } - - if (num_plane == 0) - continue; - - ret = dm_atomic_get_state(state, &dm_state); - if (ret) - goto cleanup; - - old_dm_state = dm_atomic_get_old_state(state); - if (!old_dm_state) { - ret = -EINVAL; - goto cleanup; - } - - status = dc_stream_get_status_from_state(old_dm_state->context, - new_dm_crtc_state->stream); - bundle->stream_update.stream = new_dm_crtc_state->stream; - /* - * TODO: DC modifies the surface during this call so we need - * to lock here - find a way to do this without locking. - */ - mutex_lock(&dm->dc_lock); - update_type = dc_check_update_surfaces_for_stream( - dc, bundle->surface_updates, num_plane, - &bundle->stream_update, status); - mutex_unlock(&dm->dc_lock); - - if (update_type > UPDATE_TYPE_MED) { - update_type = UPDATE_TYPE_FULL; - goto cleanup; - } - } - -cleanup: - kfree(bundle); - - *out_type = update_type; - return ret; -} #if defined(CONFIG_DRM_AMD_DC_DCN) static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) { @@ -8661,8 +8506,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm * acquired. For full updates case which removes/adds/updates streams on one * CRTC while flipping on another CRTC, acquiring global lock will guarantee * that any such full update commit will wait for completion of any outstanding - * flip using DRMs synchronization events. See - * dm_determine_update_type_for_commit() + * flip using DRMs synchronization events. * * Note that DM adds the affected connectors for all CRTCs in state, when that * might not seem necessary. This is because DC stream creation requires the @@ -8683,15 +8527,8 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_plane *plane; struct drm_plane_state *old_plane_state, *new_plane_state; - enum surface_update_type update_type = UPDATE_TYPE_FAST; - enum surface_update_type overall_update_type = UPDATE_TYPE_FAST; enum dc_status status; int ret, i; - - /* - * This bool will be set for true for any modeset/reset - * or plane update which implies non fast surface update. - */ bool lock_and_validation_needed = false; ret = drm_atomic_helper_check_modeset(dev, state); @@ -8885,27 +8722,23 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (!is_scaling_state_different(dm_new_con_state, dm_old_con_state)) continue; - overall_update_type = UPDATE_TYPE_FULL; lock_and_validation_needed = true; } - ret = dm_determine_update_type_for_commit(&adev->dm, state, &update_type); - if (ret) - goto fail; - - if (overall_update_type < update_type) - overall_update_type = update_type; - - /* - * lock_and_validation_needed was an old way to determine if we need to set - * the global lock. Leaving it in to check if we broke any corner cases - * lock_and_validation_needed true = UPDATE_TYPE_FULL or UPDATE_TYPE_MED - * lock_and_validation_needed false = UPDATE_TYPE_FAST + /** + * Streams and planes are reset when there are changes that affect + * bandwidth. Anything that affects bandwidth needs to go through + * DC global validation to ensure that the configuration can be applied + * to hardware. + * + * We have to currently stall out here in atomic_check for outstanding + * commits to finish in this case because our IRQ handlers reference + * DRM state directly - we can end up disabling interrupts too early + * if we don't. + * + * TODO: Remove this stall and drop DM state private objects. */ - if (lock_and_validation_needed && overall_update_type <= UPDATE_TYPE_FAST) - WARN(1, "Global lock should be Set, overall_update_type should be UPDATE_TYPE_MED or UPDATE_TYPE_FULL"); - - if (overall_update_type > UPDATE_TYPE_FAST) { + if (lock_and_validation_needed) { ret = dm_atomic_get_state(state, &dm_state); if (ret) goto fail; @@ -8987,7 +8820,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, struct dm_crtc_state *dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); - dm_new_crtc_state->update_type = (int)overall_update_type; + dm_new_crtc_state->update_type = lock_and_validation_needed ? + UPDATE_TYPE_FULL : + UPDATE_TYPE_FAST; } /* Must be success */ -- cgit v1.2.3 From 8b6ec999b198b59ae61e86e70f5e9df73fe4754f Mon Sep 17 00:00:00 2001 From: Qi Liu Date: Tue, 21 Jul 2020 18:16:47 +0800 Subject: drm/virtio: fix missing dma_fence_put() in virtio_gpu_execbuffer_ioctl() We should put the reference count of the fence after calling virtio_gpu_cmd_submit(). So add the missing dma_fence_put(). Fixes: 2cd7b6f08bc4 ("drm/virtio: add in/out fence support for explicit synchronization") Co-developed-by: Xin He Signed-off-by: Xin He Signed-off-by: Qi Liu Reviewed-by: Muchun Song Link: http://patchwork.freedesktop.org/patch/msgid/20200721101647.42653-1-hexin.op@bytedance.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 5df722072ba0..19c5bc01eb79 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -179,6 +179,7 @@ static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, vfpriv->ctx_id, buflist, out_fence); + dma_fence_put(&out_fence->f); virtio_gpu_notify(vgdev); return 0; -- cgit v1.2.3 From 836b194d65782aaec4485a07d2aab52d3f698505 Mon Sep 17 00:00:00 2001 From: Xin He Date: Wed, 22 Jul 2020 13:18:51 +0800 Subject: drm/virtio: fix memory leak in virtio_gpu_cleanup_object() Before setting shmem->pages to NULL, kfree() should be called. Signed-off-by: Xin He Reviewed-by: Qi Liu Link: http://patchwork.freedesktop.org/patch/msgid/20200722051851.72662-1-hexin.op@bytedance.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_object.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index 6ccbd01cd888..703b5cd51751 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -79,6 +79,7 @@ void virtio_gpu_cleanup_object(struct virtio_gpu_object *bo) } sg_free_table(shmem->pages); + kfree(shmem->pages); shmem->pages = NULL; drm_gem_shmem_unpin(&bo->base.base); } -- cgit v1.2.3 From ca6fd7a66843b6ef64179d0a4ce943affbb6c057 Mon Sep 17 00:00:00 2001 From: Likun Gao Date: Thu, 6 Aug 2020 17:37:28 +0800 Subject: drm/amdgpu: use mode1 reset by default for sienna_cichlid Swith default gpu reset method for sienna_cichlid to MODE1 reset. Signed-off-by: Likun Gao Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 74d02d270d34..da8024c2826e 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -362,10 +362,15 @@ nv_asic_reset_method(struct amdgpu_device *adev) dev_warn(adev->dev, "Specified reset method:%d isn't supported, using AUTO instead.\n", amdgpu_reset_method); - if (smu_baco_is_support(smu)) - return AMD_RESET_METHOD_BACO; - else + switch (adev->asic_type) { + case CHIP_SIENNA_CICHLID: return AMD_RESET_METHOD_MODE1; + default: + if (smu_baco_is_support(smu)) + return AMD_RESET_METHOD_BACO; + else + return AMD_RESET_METHOD_MODE1; + } } static int nv_asic_reset(struct amdgpu_device *adev) -- cgit v1.2.3 From ad1cac262ed2c344ec93e145c5307480cecfbc2f Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 3 Aug 2020 11:15:14 +0800 Subject: drm/amd/powerplay: update swSMU VCN/JPEG PG logics Add lock protections and avoid unnecessary actions if the PG state is already the same as required. Signed-off-by: Evan Quan Tested-by: Matt Coffin Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 57 +++++++++++++++++++++- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 4 -- drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 6 ++- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 8 --- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 8 --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 9 ---- drivers/gpu/drm/amd/powerplay/smu_internal.h | 2 - 7 files changed, 60 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f3f50b5add99..1b64ca9ecccb 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -133,6 +133,56 @@ int smu_get_dpm_freq_range(struct smu_context *smu, return ret; } +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_vcn_enable) + return 0; + + mutex_lock(&power_gate->vcn_gate_lock); + + if (atomic_read(&power_gate->vcn_gated) ^ enable) + goto out; + + ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->vcn_gated, !enable); + +out: + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_jpeg_enable) + return 0; + + mutex_lock(&power_gate->jpeg_gate_lock); + + if (atomic_read(&power_gate->jpeg_gated) ^ enable) + goto out; + + ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->jpeg_gated, !enable); + +out: + mutex_unlock(&power_gate->jpeg_gate_lock); + + return ret; +} + /** * smu_dpm_set_power_gate - power gate/ungate the specific IP block * @@ -650,6 +700,11 @@ static int smu_sw_init(void *handle) smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); + atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); + mutex_init(&smu->smu_power.power_gate.vcn_gate_lock); + mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock); + smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; @@ -1974,7 +2029,7 @@ int smu_read_sensor(struct smu_context *smu, *size = 4; break; case AMDGPU_PP_SENSOR_VCN_POWER_STATE: - *(uint32_t *)data = smu->smu_power.power_gate.vcn_gated ? 0 : 1; + *(uint32_t *)data = atomic_read(&smu->smu_power.power_gate.vcn_gated) ? 0: 1; *size = 4; break; case AMDGPU_PP_SENSOR_MIN_FAN_RPM: diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index e3a2d7f0aba1..e59e6fb6f0a8 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -1896,8 +1896,6 @@ static bool arcturus_is_dpm_running(struct smu_context *smu) static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -1908,7 +1906,6 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) return ret; } } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0); @@ -1917,7 +1914,6 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) return ret; } } - power_gate->vcn_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index ec2d2aa7f4ec..23c2279bd500 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -295,8 +295,10 @@ struct smu_dpm_context { struct smu_power_gate { bool uvd_gated; bool vce_gated; - bool vcn_gated; - bool jpeg_gated; + atomic_t vcn_gated; + atomic_t jpeg_gated; + struct mutex vcn_gate_lock; + struct mutex jpeg_gate_lock; }; struct smu_power_context { diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 8c45c472f7f2..82659b781f05 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -831,8 +831,6 @@ static int navi10_set_default_dpm_table(struct smu_context *smu) static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -842,14 +840,12 @@ static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } - power_gate->vcn_gated = true; } return ret; @@ -857,8 +853,6 @@ static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -867,14 +861,12 @@ static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 4c1a506c3c17..8a8e6033f71f 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -479,8 +479,6 @@ static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -490,14 +488,12 @@ static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); if (ret) return ret; } - power_gate->vcn_gated = true; } return ret; @@ -505,8 +501,6 @@ static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -515,14 +509,12 @@ static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 2566ae5df64b..bb756b4c284e 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -815,10 +815,7 @@ static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu) static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; struct amdgpu_device *adev = smu->adev; - int ret = 0; if (enable) { @@ -834,7 +831,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl return ret; } } - power_gate->vcn_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); @@ -847,7 +843,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl return ret; } } - power_gate->vcn_gated = true; } return ret; @@ -855,8 +850,6 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) { - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; int ret = 0; if (enable) { @@ -865,14 +858,12 @@ static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enab if (ret) return ret; } - power_gate->jpeg_gated = false; } else { if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); if (ret) return ret; } - power_gate->jpeg_gated = true; } return ret; diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index d0deaefd3feb..f1d8f247e589 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -77,8 +77,6 @@ #define smu_get_dal_power_level(smu, clocks) smu_ppt_funcs(get_dal_power_level, 0, smu, clocks) #define smu_get_perf_level(smu, designation, level) smu_ppt_funcs(get_perf_level, 0, smu, designation, level) #define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks) -#define smu_dpm_set_vcn_enable(smu, enable) smu_ppt_funcs(dpm_set_vcn_enable, 0, smu, enable) -#define smu_dpm_set_jpeg_enable(smu, enable) smu_ppt_funcs(dpm_set_jpeg_enable, 0, smu, enable) #define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges) #define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) #define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) -- cgit v1.2.3 From 520f5e425a69417540b7563c266f773752dcea44 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 5 Aug 2020 17:24:41 +0800 Subject: drm/amd/powerplay: put VCN/JPEG into PG ungate state before dpm table setup(V3) As VCN related dpm table setup needs VCN be in PG ungate state. Same logics applies to JPEG. V2: fix paste typo V3: code cosmetic Signed-off-by: Evan Quan Tested-by: Matt Coffin Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 85 ++++++++++++++++++++++++---- drivers/gpu/drm/amd/powerplay/smu_internal.h | 1 - 2 files changed, 73 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 1b64ca9ecccb..1ffacc712e53 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -133,8 +133,8 @@ int smu_get_dpm_freq_range(struct smu_context *smu, return ret; } -static int smu_dpm_set_vcn_enable(struct smu_context *smu, - bool enable) +static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -143,23 +143,34 @@ static int smu_dpm_set_vcn_enable(struct smu_context *smu, if (!smu->ppt_funcs->dpm_set_vcn_enable) return 0; - mutex_lock(&power_gate->vcn_gate_lock); - if (atomic_read(&power_gate->vcn_gated) ^ enable) - goto out; + return 0; ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); if (!ret) atomic_set(&power_gate->vcn_gated, !enable); -out: + return ret; +} + +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->vcn_gate_lock); + + ret = smu_dpm_set_vcn_enable_locked(smu, enable); + mutex_unlock(&power_gate->vcn_gate_lock); return ret; } -static int smu_dpm_set_jpeg_enable(struct smu_context *smu, - bool enable) +static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, + bool enable) { struct smu_power_context *smu_power = &smu->smu_power; struct smu_power_gate *power_gate = &smu_power->power_gate; @@ -168,16 +179,27 @@ static int smu_dpm_set_jpeg_enable(struct smu_context *smu, if (!smu->ppt_funcs->dpm_set_jpeg_enable) return 0; - mutex_lock(&power_gate->jpeg_gate_lock); - if (atomic_read(&power_gate->jpeg_gated) ^ enable) - goto out; + return 0; ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); if (!ret) atomic_set(&power_gate->jpeg_gated, !enable); -out: + return ret; +} + +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->jpeg_gate_lock); + + ret = smu_dpm_set_jpeg_enable_locked(smu, enable); + mutex_unlock(&power_gate->jpeg_gate_lock); return ret; @@ -403,6 +425,45 @@ static int smu_early_init(void *handle) return smu_set_funcs(adev); } +static int smu_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int vcn_gate, jpeg_gate; + int ret = 0; + + if (!smu->ppt_funcs->set_default_dpm_table) + return 0; + + mutex_lock(&power_gate->vcn_gate_lock); + mutex_lock(&power_gate->jpeg_gate_lock); + + vcn_gate = atomic_read(&power_gate->vcn_gated); + jpeg_gate = atomic_read(&power_gate->jpeg_gated); + + ret = smu_dpm_set_vcn_enable_locked(smu, true); + if (ret) + goto err0_out; + + ret = smu_dpm_set_jpeg_enable_locked(smu, true); + if (ret) + goto err1_out; + + ret = smu->ppt_funcs->set_default_dpm_table(smu); + if (ret) + dev_err(smu->adev->dev, + "Failed to setup default dpm clock tables!\n"); + + smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate); +err1_out: + smu_dpm_set_vcn_enable_locked(smu, !vcn_gate); +err0_out: + mutex_unlock(&power_gate->jpeg_gate_lock); + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + static int smu_late_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h index f1d8f247e589..264073d4e263 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ b/drivers/gpu/drm/amd/powerplay/smu_internal.h @@ -60,7 +60,6 @@ #define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) #define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) #define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) -#define smu_set_default_dpm_table(smu) smu_ppt_funcs(set_default_dpm_table, 0, smu) #define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) #define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu) #define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu) -- cgit v1.2.3 From 94561899ddb0f89d7fd3fb58ee3ed6961ef048ad Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Tue, 4 Aug 2020 12:32:13 +0800 Subject: drm/amdgpu: unlock mutex on error Make sure to unlock the mutex when error happen v2: 1. correct syntax error in the commit comments 2. remove change-Id Acked-by: Nirmoy Das Reviewed-by: Luben Tuikov Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 92790db5edc0..9738dccb1c2c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -632,13 +632,14 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, } ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); + + up_read(&adev->reset_sem); + if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; } - up_read(&adev->reset_sem); - ret = dma_fence_wait(f, false); err_ib_sched: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 4e017f379eb6..67a756f4337b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -545,7 +545,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) } ret = amdgpu_xgmi_update_topology(hive, tmp_adev); if (ret) - goto exit; + goto exit_unlock; } /* get latest topology info for each device from psp */ @@ -558,7 +558,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) tmp_adev->gmc.xgmi.node_id, tmp_adev->gmc.xgmi.hive_id, ret); /* To do : continue with some node failed or disable the whole hive */ - goto exit; + goto exit_unlock; } } } @@ -566,7 +566,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) if (!ret) ret = amdgpu_xgmi_sysfs_add_dev_info(adev, hive); - +exit_unlock: mutex_unlock(&hive->hive_lock); exit: if (!ret) -- cgit v1.2.3 From 82c2454761298a2fdaade6a253a7b034b9cfa15d Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman Date: Thu, 6 Aug 2020 22:52:20 +0530 Subject: drm/amdgpu: Fix bug where DPM is not enabled after hibernate and resume Reproducing bug report here: After hibernating and resuming, DPM is not enabled. This remains the case even if you test hibernate using the steps here: https://www.kernel.org/doc/html/latest/power/basic-pm-debugging.html I debugged the problem, and figured out that in the file hardwaremanager.c, in the function, phm_enable_dynamic_state_management(), the check 'if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr) && !amdgpu_passthrough(adev) && adev->in_suspend)' returns true for the hibernate case, and false for the suspend case. This means that for the hibernate case, the AMDGPU driver doesn't enable DPM (even though it should) and simply returns from that function. In the suspend case, it goes ahead and enables DPM, even though it doesn't need to. I debugged further, and found out that in the case of suspend, for the CIK/Hawaii GPUs, smum_is_dpm_running(hwmgr) returns false, while in the case of hibernate, smum_is_dpm_running(hwmgr) returns true. For CIK, the ci_is_dpm_running() function calls the ci_is_smc_ram_running() function, which is ultimately used to determine if DPM is currently enabled or not, and this seems to provide the wrong answer. I've changed the ci_is_dpm_running() function to instead use the same method that some other AMD GPU chips do (e.g Fiji), which seems to read the voltage controller. I've tested on my R9 390 and it seems to work correctly for both suspend and hibernate use cases, and has been stable so far. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=208839 Signed-off-by: Sandeep Raghuraman Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index 02159ca29fa2..c18169aa59ce 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -2725,7 +2725,10 @@ static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) { - return ci_is_smc_ram_running(hwmgr); + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, + VOLTAGE_CONTROLLER_ON)) + ? true : false; } static int ci_smu_init(struct pp_hwmgr *hwmgr) -- cgit v1.2.3 From 5068ed578e34450a285fca3f9d830361b44267ad Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 9 Aug 2020 22:34:06 +0200 Subject: drm: amdgpu: Use the correct size when allocating memory When '*sgt' is allocated, we must allocated 'sizeof(**sgt)' bytes instead of 'sizeof(*sg)'. The sizeof(*sg) is bigger than sizeof(**sgt) so this wastes memory but it won't lead to corruption. Fixes: f44ffd677fb3 ("drm/amdgpu: add support for exporting VRAM using DMA-buf v3") Reviewed-by: Christian König Signed-off-by: Christophe JAILLET Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 97ad8ffe6c6c..be6a7ec22de4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -463,7 +463,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, unsigned int pages; int i, r; - *sgt = kmalloc(sizeof(*sg), GFP_KERNEL); + *sgt = kmalloc(sizeof(**sgt), GFP_KERNEL); if (!*sgt) return -ENOMEM; -- cgit v1.2.3 From 5218992251e62cedd16ff4466717ca09b7ad4b18 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 7 Aug 2020 18:22:27 -0400 Subject: Revert "drm/amdkfd: Fix spurious debug exception on gfx10" This reverts commit ea368183ae900e376b66d3f23da22acde48e385a. Needed due to conflicts when reverting "drm/amdkfd: Unify gfx9/gfx10 context save area layouts". Signed-off-by: Felix Kuehling 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, 90 insertions(+), 95 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index a5cf735daf48..7290a30f26ca 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -911,7 +911,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf820152, + 0xbf85fff8, 0xbf820150, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1024,63 +1024,62 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xba80f801, - 0x00000000, 0xbf8a0000, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0x80788478, 0xf4211cfa, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, + 0xf4211cfa, 0xf0000000, + 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef814, 0xf4211bba, - 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef815, - 0xbefc036f, 0xbefe0370, - 0xbeff0371, 0x876f7bff, - 0x000003ff, 0xb9ef4803, - 0xb9f9f816, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e2a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0x806eff6e, - 0x00000200, 0x806e746e, - 0x826f8075, 0x876fff6f, - 0x0000ffff, 0xf4091c37, - 0xfa000050, 0xf4091d37, - 0xfa000060, 0xf4011e77, - 0xfa000074, 0xbf8cc07f, - 0x876fff6d, 0xfc000000, - 0x906f9a6f, 0x8f6f906f, - 0xbeee0380, 0x886e6f6e, - 0x876fff6d, 0x02000000, - 0x906f996f, 0x8f6f8f6f, + 0xb9eef815, 0xbefc036f, + 0xbefe0370, 0xbeff0371, + 0x876f7bff, 0x000003ff, + 0xb9ef4803, 0xb9f9f816, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e2a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0x806eff6e, 0x00000200, + 0x806e746e, 0x826f8075, + 0x876fff6f, 0x0000ffff, + 0xf4091c37, 0xfa000050, + 0xf4091d37, 0xfa000060, + 0xf4011e77, 0xfa000074, + 0xbf8cc07f, 0x876fff6d, + 0xfc000000, 0x906f9a6f, + 0x8f6f906f, 0xbeee0380, 0x886e6f6e, 0x876fff6d, - 0x01000000, 0x906f986f, - 0x8f6f996f, 0x886e6f6e, - 0x876fff7a, 0x00800000, - 0x906f976f, 0xb9eef807, - 0x876dff6d, 0x0000ffff, - 0x87fe7e7e, 0x87ea6a6a, - 0xb9faf802, 0xbe80226c, + 0x02000000, 0x906f996f, + 0x8f6f8f6f, 0x886e6f6e, + 0x876fff6d, 0x01000000, + 0x906f986f, 0x8f6f996f, + 0x886e6f6e, 0x876fff7a, + 0x00800000, 0x906f976f, + 0xb9eef807, 0x876dff6d, + 0x0000ffff, 0x87fe7e7e, + 0x87ea6a6a, 0xb9faf802, + 0xbf8a0000, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, @@ -1809,7 +1808,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xe0704000, 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013d, + 0xbf85fff8, 0xbf82013b, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, @@ -1922,52 +1921,51 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbe863106, 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xba80f801, - 0x00000000, 0xbf8a0000, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xbf84fff0, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0x80788478, 0xf4211cfa, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0x80788478, + 0xf4211cfa, 0xf0000000, + 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef814, 0xf4211bba, - 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef815, - 0xbefc036f, 0xbefe0370, - 0xbeff0371, 0x876f7bff, - 0x000003ff, 0xb9ef4803, - 0x876f7bff, 0xfffff800, - 0x906f8b6f, 0xb9efa2c3, - 0xb9f3f801, 0xb96e2a05, - 0x806e816e, 0xbf0d9972, - 0xbf850002, 0x8f6e896e, - 0xbf820001, 0x8f6e8a6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, + 0xb9eef815, 0xbefc036f, + 0xbefe0370, 0xbeff0371, + 0x876f7bff, 0x000003ff, + 0xb9ef4803, 0x876f7bff, + 0xfffff800, 0x906f8b6f, + 0xb9efa2c3, 0xb9f3f801, + 0xb96e2a05, 0x806e816e, + 0xbf0d9972, 0xbf850002, + 0x8f6e896e, 0xbf820001, + 0x8f6e8a6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbf8a0000, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 0f8e06a2ea8d..4569db452160 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -895,11 +895,6 @@ L_RESTORE_SGPR: s_cmp_eq_u32 m0, 0 //scc = (m0 < s_sgpr_save_num) ? 1 : 0 s_cbranch_scc0 L_RESTORE_SGPR_LOOP - // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. - // Clear DEBUG_EN before and restore MODE after the barrier. - s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 - s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG - /* restore HW registers */ L_RESTORE_HWREG: // HWREG SR memory offset : size(VGPR)+size(SVGPR)+size(SGPR) @@ -983,6 +978,8 @@ L_RESTORE_HWREG: s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu + s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG + s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: -- cgit v1.2.3 From c342d7c579f2c9f4e84552d53881acd1cf15eb14 Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Fri, 7 Aug 2020 18:23:56 -0400 Subject: Revert "drm/amdkfd: Unify gfx9/gfx10 context save area layouts" This reverts commit 0a5baee415000a3e18730ac98e19d046c3cebbe6. The change introduced a regression on some chips. Reverting until a proper solution can be found. Signed-off-by: Felix Kuehling 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, 464 insertions(+), 468 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 7290a30f26ca..577d901fdb63 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -680,7 +680,7 @@ static const uint32_t cwsr_trap_gfx9_hex[] = { }; static const uint32_t cwsr_trap_nv1x_hex[] = { - 0xbf820001, 0xbf8201ce, + 0xbf820001, 0xbf8201cd, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -794,256 +794,255 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbefc037e, 0xbefe037c, 0xbefc0370, 0xf4611efa, 0xf8000000, 0x80708470, - 0xbefc037e, 0x80708470, - 0xb971f801, 0xbefe037c, - 0xbefc0370, 0xf4611c7a, - 0xf8000000, 0x80708470, - 0xbefc037e, 0xb971f814, + 0xbefc037e, 0xb971f801, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, 0xbefc037e, - 0xb971f815, 0xbefe037c, + 0xb971f814, 0xbefe037c, 0xbefc0370, 0xf4611c7a, 0xf8000000, 0x80708470, - 0xbefc037e, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0xbef603ff, - 0x01000000, 0xbefb0374, - 0x80747074, 0x82758075, - 0xbefc0380, 0xbf800000, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xbe8c2f0c, 0xbe8e2f0e, - 0xf469003a, 0xfa000000, - 0xf469013a, 0xfa000010, - 0xf469023a, 0xfa000020, - 0xf469033a, 0xfa000030, - 0x8074c074, 0x82758075, - 0x807c907c, 0xbf0aff7c, - 0x00000060, 0xbf85ffea, - 0xbe802f00, 0xbe822f02, - 0xbe842f04, 0xbe862f06, - 0xbe882f08, 0xbe8a2f0a, - 0xf469003a, 0xfa000000, - 0xf469013a, 0xfa000010, - 0xf469023a, 0xfa000020, - 0x8074b074, 0x82758075, - 0xbef4037b, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb97b4306, - 0x877bc17b, 0xbf840044, - 0xbf8a0000, 0x877aff73, - 0x04000000, 0xbf840040, - 0x8f7b867b, 0x8f7b827b, - 0xbef6037b, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef603ff, - 0x01000000, 0xd7650000, - 0x000100c1, 0xd7660000, - 0x000200c1, 0x16000084, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850012, 0xbe8303ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7c, 0xbf85fff4, - 0xbf820011, 0xbe8303ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7c, 0xbf85fff4, + 0xbefc037e, 0xb971f815, + 0xbefe037c, 0xbefc0370, + 0xf4611c7a, 0xf8000000, + 0x80708470, 0xbefc037e, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0xbef603ff, 0x01000000, + 0xbefb0374, 0x80747074, + 0x82758075, 0xbefc0380, + 0xbf800000, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xbe8c2f0c, + 0xbe8e2f0e, 0xf469003a, + 0xfa000000, 0xf469013a, + 0xfa000010, 0xf469023a, + 0xfa000020, 0xf469033a, + 0xfa000030, 0x8074c074, + 0x82758075, 0x807c907c, + 0xbf0aff7c, 0x00000060, + 0xbf85ffea, 0xbe802f00, + 0xbe822f02, 0xbe842f04, + 0xbe862f06, 0xbe882f08, + 0xbe8a2f0a, 0xf469003a, + 0xfa000000, 0xf469013a, + 0xfa000010, 0xf469023a, + 0xfa000020, 0x8074b074, + 0x82758075, 0xbef4037b, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850004, 0xbef003ff, - 0x00000200, 0xbeff0380, - 0xbf820003, 0xbef003ff, - 0x00000400, 0xbeff03c1, - 0xb97b2a05, 0x807b817b, - 0x8f7b827b, 0x907c9973, + 0xbf850002, 0xbeff0380, + 0xbf820001, 0xbeff03c1, + 0xb97b4306, 0x877bc17b, + 0xbf840044, 0xbf8a0000, + 0x877aff73, 0x04000000, + 0xbf840040, 0x8f7b867b, + 0x8f7b827b, 0xbef6037b, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef603ff, 0x01000000, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x16000084, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850017, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0704000, 0x705d0000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000200, 0xbf0a7b7c, - 0xbf85ffef, 0xbf820025, + 0xbefc0380, 0xbf850012, + 0xbe8303ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff4, 0xbf820011, + 0xbe8303ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7c, + 0xbf85fff4, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850004, + 0xbef003ff, 0x00000200, + 0xbeff0380, 0xbf820003, + 0xbef003ff, 0x00000400, + 0xbeff03c1, 0xb97b2a05, + 0x807b817b, 0x8f7b827b, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850017, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840020, 0x7e008700, + 0xbf840037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, + 0x705d0000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7c, 0xbf85ffef, - 0xb97b1e06, 0x877bc17b, - 0xbf84000c, 0x8f7b837b, - 0x807b7c7b, 0xbefe03c1, - 0xbeff0380, 0x7e008700, + 0xbf820025, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840020, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0704000, 0x705d0000, - 0x807c817c, 0x8070ff70, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf820150, - 0xbef4037e, 0x8775ff7f, - 0x0000ffff, 0x8875ff75, - 0x00040000, 0xbef60380, - 0xbef703ff, 0x10807fac, - 0x876eff7f, 0x08000000, - 0x906e836e, 0x88776e77, - 0x876eff7f, 0x70000000, - 0x906e816e, 0x88776e77, - 0xb97202dc, 0x8f729972, - 0x8872727f, 0x876eff7f, - 0x04000000, 0xbf840034, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000400, 0xbf0a7b7c, + 0xbf85ffef, 0xb97b1e06, + 0x877bc17b, 0xbf84000c, + 0x8f7b837b, 0x807b7c7b, + 0xbefe03c1, 0xbeff0380, + 0x7e008700, 0xe0704000, + 0x705d0000, 0x807c817c, + 0x8070ff70, 0x00000080, + 0xbf0a7b7c, 0xbf85fff8, + 0xbf82014f, 0xbef4037e, + 0x8775ff7f, 0x0000ffff, + 0x8875ff75, 0x00040000, + 0xbef60380, 0xbef703ff, + 0x10807fac, 0x876eff7f, + 0x08000000, 0x906e836e, + 0x88776e77, 0x876eff7f, + 0x70000000, 0x906e816e, + 0x88776e77, 0xb97202dc, + 0x8f729972, 0x8872727f, + 0x876eff7f, 0x04000000, + 0xbf840034, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f4306, + 0x876fc16f, 0xbf840029, + 0x8f6f866f, 0x8f6f826f, + 0xbef6036f, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x8078ff78, + 0x00000080, 0xbef603ff, + 0x01000000, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbefc0380, 0xbf850009, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff8, + 0xbf820008, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000100, 0x8078ff78, + 0x00000100, 0xbf0a6f7c, + 0xbf85fff8, 0xbef80380, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f4306, 0x876fc16f, - 0xbf840029, 0x8f6f866f, - 0x8f6f826f, 0xbef6036f, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0x8078ff78, 0x00000080, - 0xbef603ff, 0x01000000, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850009, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff8, 0xbf820008, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000100, - 0x8078ff78, 0x00000100, - 0xbf0a6f7c, 0xbf85fff8, - 0xbef80380, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f2a05, - 0x806f816f, 0x8f6f826f, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850021, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000200, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304080, 0x785d0100, - 0xe0304100, 0x785d0200, - 0xe0304180, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000200, - 0xbf0a6f7c, 0xbf85ffee, - 0xe0304000, 0x6e5d0000, - 0xe0304080, 0x6e5d0100, - 0xe0304100, 0x6e5d0200, - 0xe0304180, 0x6e5d0300, - 0xbf820032, 0xbef603ff, + 0xb96f2a05, 0x806f816f, + 0x8f6f826f, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbf850021, 0xbef603ff, 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000400, + 0x8078ff78, 0x00000200, 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304100, - 0x785d0100, 0xe0304200, - 0x785d0200, 0xe0304300, + 0x785d0000, 0xe0304080, + 0x785d0100, 0xe0304100, + 0x785d0200, 0xe0304180, 0x785d0300, 0xbf8c3f70, 0x7e008500, 0x7e028501, 0x7e048502, 0x7e068503, 0x807c847c, 0x8078ff78, - 0x00000400, 0xbf0a6f7c, - 0xbf85ffee, 0xb96f1e06, - 0x876fc16f, 0xbf84000e, - 0x8f6f836f, 0x806f7c6f, - 0xbefe03c1, 0xbeff0380, + 0x00000200, 0xbf0a6f7c, + 0xbf85ffee, 0xe0304000, + 0x6e5d0000, 0xe0304080, + 0x6e5d0100, 0xe0304100, + 0x6e5d0200, 0xe0304180, + 0x6e5d0300, 0xbf820032, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000400, 0xbefc0384, 0xe0304000, 0x785d0000, + 0xe0304100, 0x785d0100, + 0xe0304200, 0x785d0200, + 0xe0304300, 0x785d0300, 0xbf8c3f70, 0x7e008500, - 0x807c817c, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff7, 0xbeff03c1, - 0xe0304000, 0x6e5d0000, - 0xe0304100, 0x6e5d0100, - 0xe0304200, 0x6e5d0200, - 0xe0304300, 0x6e5d0300, - 0xbf8c3f70, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef603ff, - 0x01000000, 0xbefc03ff, - 0x0000006c, 0x80f89078, - 0xf429003a, 0xf0000000, - 0xbf8cc07f, 0x80fc847c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0x80f8a078, - 0xf42d003a, 0xf0000000, - 0xbf8cc07f, 0x80fc887c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0x80f8c078, - 0xf431003a, 0xf0000000, - 0xbf8cc07f, 0x80fc907c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0xbe883108, - 0xbe8a310a, 0xbe8c310c, - 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000400, + 0xbf0a6f7c, 0xbf85ffee, + 0xb96f1e06, 0x876fc16f, + 0xbf84000e, 0x8f6f836f, + 0x806f7c6f, 0xbefe03c1, + 0xbeff0380, 0xe0304000, + 0x785d0000, 0xbf8c3f70, + 0x7e008500, 0x807c817c, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff7, + 0xbeff03c1, 0xe0304000, + 0x6e5d0000, 0xe0304100, + 0x6e5d0100, 0xe0304200, + 0x6e5d0200, 0xe0304300, + 0x6e5d0300, 0xbf8c3f70, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, + 0xbef603ff, 0x01000000, + 0xbefc03ff, 0x0000006c, + 0x80f89078, 0xf429003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc847c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0x80f8a078, 0xf42d003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc887c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0x80f8c078, 0xf431003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc907c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0xbe883108, 0xbe8a310a, + 0xbe8c310c, 0xbe8e310e, + 0xbf06807c, 0xbf84fff0, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, @@ -1576,7 +1575,7 @@ static const uint32_t cwsr_trap_arcturus_hex[] = { }; static const uint32_t cwsr_trap_gfx10_hex[] = { - 0xbf820001, 0xbf8201d0, + 0xbf820001, 0xbf8201cf, 0xb0804004, 0xb978f802, 0x8a788678, 0xb96ef801, 0x876eff6e, 0x00000800, @@ -1658,289 +1657,288 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xd7610002, 0x0000f87a, 0x807c817c, 0xd7610002, 0x0000f87b, 0x807c817c, - 0x80708470, 0xb971f801, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xb971f814, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xb971f815, - 0xd7610002, 0x0000f871, - 0x807c817c, 0xbeff0380, - 0xe0704000, 0x705d0200, - 0xb9702a05, 0x80708170, - 0xbf0d9973, 0xbf850002, - 0x8f708970, 0xbf820001, - 0x8f708a70, 0xb97a1e06, - 0x8f7a8a7a, 0x80707a70, - 0xbef603ff, 0x01000000, - 0xbef90380, 0xbefc0380, - 0xbf800000, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xbe8c2f0c, - 0xbe8e2f0e, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0xb971f801, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xb971f814, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xb971f815, 0xd7610002, + 0x0000f871, 0x807c817c, + 0xbeff0380, 0xe0704000, + 0x705d0200, 0xb9702a05, + 0x80708170, 0xbf0d9973, + 0xbf850002, 0x8f708970, + 0xbf820001, 0x8f708a70, + 0xb97a1e06, 0x8f7a8a7a, + 0x80707a70, 0xbef603ff, + 0x01000000, 0xbef90380, + 0xbefc0380, 0xbf800000, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xbe8c2f0c, 0xbe8e2f0e, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, 0x80798179, 0xd7610002, - 0x0000f20c, 0x80798179, - 0xd7610002, 0x0000f20d, + 0x0000f20b, 0x80798179, + 0xd7610002, 0x0000f20c, 0x80798179, 0xd7610002, - 0x0000f20e, 0x80798179, - 0xd7610002, 0x0000f20f, - 0x80798179, 0xbf06a079, - 0xbf840006, 0xe0704000, - 0x705d0200, 0x8070ff70, - 0x00000080, 0xbef90380, - 0x7e040280, 0x807c907c, - 0xbf0aff7c, 0x00000060, - 0xbf85ffbc, 0xbe802f00, - 0xbe822f02, 0xbe842f04, - 0xbe862f06, 0xbe882f08, - 0xbe8a2f0a, 0xd7610002, - 0x0000f200, 0x80798179, - 0xd7610002, 0x0000f201, + 0x0000f20d, 0x80798179, + 0xd7610002, 0x0000f20e, 0x80798179, 0xd7610002, - 0x0000f202, 0x80798179, - 0xd7610002, 0x0000f203, + 0x0000f20f, 0x80798179, + 0xbf06a079, 0xbf840006, + 0xe0704000, 0x705d0200, + 0x8070ff70, 0x00000080, + 0xbef90380, 0x7e040280, + 0x807c907c, 0xbf0aff7c, + 0x00000060, 0xbf85ffbc, + 0xbe802f00, 0xbe822f02, + 0xbe842f04, 0xbe862f06, + 0xbe882f08, 0xbe8a2f0a, + 0xd7610002, 0x0000f200, 0x80798179, 0xd7610002, - 0x0000f204, 0x80798179, - 0xd7610002, 0x0000f205, + 0x0000f201, 0x80798179, + 0xd7610002, 0x0000f202, 0x80798179, 0xd7610002, - 0x0000f206, 0x80798179, - 0xd7610002, 0x0000f207, + 0x0000f203, 0x80798179, + 0xd7610002, 0x0000f204, 0x80798179, 0xd7610002, - 0x0000f208, 0x80798179, - 0xd7610002, 0x0000f209, + 0x0000f205, 0x80798179, + 0xd7610002, 0x0000f206, 0x80798179, 0xd7610002, - 0x0000f20a, 0x80798179, - 0xd7610002, 0x0000f20b, - 0x80798179, 0xe0704000, - 0x705d0200, 0xbefe03c1, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb97b4306, - 0x877bc17b, 0xbf840044, - 0xbf8a0000, 0x877aff73, - 0x04000000, 0xbf840040, - 0x8f7b867b, 0x8f7b827b, - 0xbef6037b, 0xb9702a05, - 0x80708170, 0xbf0d9973, - 0xbf850002, 0x8f708970, - 0xbf820001, 0x8f708a70, - 0xb97a1e06, 0x8f7a8a7a, - 0x80707a70, 0x8070ff70, - 0x00000200, 0x8070ff70, - 0x00000080, 0xbef603ff, - 0x01000000, 0xd7650000, - 0x000100c1, 0xd7660000, - 0x000200c1, 0x16000084, - 0x907c9973, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850012, 0xbe8303ff, - 0x00000080, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000080, - 0xbf0a7b7c, 0xbf85fff4, - 0xbf820011, 0xbe8303ff, - 0x00000100, 0xbf800000, - 0xbf800000, 0xbf800000, - 0xd8d80000, 0x01000000, - 0xbf8c0000, 0xe0704000, - 0x705d0100, 0x807c037c, - 0x80700370, 0xd5250000, - 0x0001ff00, 0x00000100, - 0xbf0a7b7c, 0xbf85fff4, + 0x0000f207, 0x80798179, + 0xd7610002, 0x0000f208, + 0x80798179, 0xd7610002, + 0x0000f209, 0x80798179, + 0xd7610002, 0x0000f20a, + 0x80798179, 0xd7610002, + 0x0000f20b, 0x80798179, + 0xe0704000, 0x705d0200, 0xbefe03c1, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850004, 0xbef003ff, - 0x00000200, 0xbeff0380, - 0xbf820003, 0xbef003ff, - 0x00000400, 0xbeff03c1, - 0xb97b2a05, 0x807b817b, - 0x8f7b827b, 0x907c9973, + 0xbf850002, 0xbeff0380, + 0xbf820001, 0xbeff03c1, + 0xb97b4306, 0x877bc17b, + 0xbf840044, 0xbf8a0000, + 0x877aff73, 0x04000000, + 0xbf840040, 0x8f7b867b, + 0x8f7b827b, 0xbef6037b, + 0xb9702a05, 0x80708170, + 0xbf0d9973, 0xbf850002, + 0x8f708970, 0xbf820001, + 0x8f708a70, 0xb97a1e06, + 0x8f7a8a7a, 0x80707a70, + 0x8070ff70, 0x00000200, + 0x8070ff70, 0x00000080, + 0xbef603ff, 0x01000000, + 0xd7650000, 0x000100c1, + 0xd7660000, 0x000200c1, + 0x16000084, 0x907c9973, 0x877c817c, 0xbf06817c, - 0xbf850017, 0xbef603ff, - 0x01000000, 0xbefc0384, - 0xbf0a7b7c, 0xbf840037, - 0x7e008700, 0x7e028701, - 0x7e048702, 0x7e068703, - 0xe0704000, 0x705d0000, - 0xe0704080, 0x705d0100, - 0xe0704100, 0x705d0200, - 0xe0704180, 0x705d0300, - 0x807c847c, 0x8070ff70, - 0x00000200, 0xbf0a7b7c, - 0xbf85ffef, 0xbf820025, + 0xbefc0380, 0xbf850012, + 0xbe8303ff, 0x00000080, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000080, 0xbf0a7b7c, + 0xbf85fff4, 0xbf820011, + 0xbe8303ff, 0x00000100, + 0xbf800000, 0xbf800000, + 0xbf800000, 0xd8d80000, + 0x01000000, 0xbf8c0000, + 0xe0704000, 0x705d0100, + 0x807c037c, 0x80700370, + 0xd5250000, 0x0001ff00, + 0x00000100, 0xbf0a7b7c, + 0xbf85fff4, 0xbefe03c1, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850004, + 0xbef003ff, 0x00000200, + 0xbeff0380, 0xbf820003, + 0xbef003ff, 0x00000400, + 0xbeff03c1, 0xb97b2a05, + 0x807b817b, 0x8f7b827b, + 0x907c9973, 0x877c817c, + 0xbf06817c, 0xbf850017, 0xbef603ff, 0x01000000, 0xbefc0384, 0xbf0a7b7c, - 0xbf840020, 0x7e008700, + 0xbf840037, 0x7e008700, 0x7e028701, 0x7e048702, 0x7e068703, 0xe0704000, - 0x705d0000, 0xe0704100, - 0x705d0100, 0xe0704200, - 0x705d0200, 0xe0704300, + 0x705d0000, 0xe0704080, + 0x705d0100, 0xe0704100, + 0x705d0200, 0xe0704180, 0x705d0300, 0x807c847c, - 0x8070ff70, 0x00000400, + 0x8070ff70, 0x00000200, 0xbf0a7b7c, 0xbf85ffef, - 0xb97b1e06, 0x877bc17b, - 0xbf84000c, 0x8f7b837b, - 0x807b7c7b, 0xbefe03c1, - 0xbeff0380, 0x7e008700, + 0xbf820025, 0xbef603ff, + 0x01000000, 0xbefc0384, + 0xbf0a7b7c, 0xbf840020, + 0x7e008700, 0x7e028701, + 0x7e048702, 0x7e068703, 0xe0704000, 0x705d0000, - 0x807c817c, 0x8070ff70, - 0x00000080, 0xbf0a7b7c, - 0xbf85fff8, 0xbf82013b, - 0xbef4037e, 0x8775ff7f, - 0x0000ffff, 0x8875ff75, - 0x00040000, 0xbef60380, - 0xbef703ff, 0x10807fac, - 0x876eff7f, 0x08000000, - 0x906e836e, 0x88776e77, - 0x876eff7f, 0x70000000, - 0x906e816e, 0x88776e77, - 0xb97202dc, 0x8f729972, - 0x8872727f, 0x876eff7f, - 0x04000000, 0xbf840034, + 0xe0704100, 0x705d0100, + 0xe0704200, 0x705d0200, + 0xe0704300, 0x705d0300, + 0x807c847c, 0x8070ff70, + 0x00000400, 0xbf0a7b7c, + 0xbf85ffef, 0xb97b1e06, + 0x877bc17b, 0xbf84000c, + 0x8f7b837b, 0x807b7c7b, + 0xbefe03c1, 0xbeff0380, + 0x7e008700, 0xe0704000, + 0x705d0000, 0x807c817c, + 0x8070ff70, 0x00000080, + 0xbf0a7b7c, 0xbf85fff8, + 0xbf82013a, 0xbef4037e, + 0x8775ff7f, 0x0000ffff, + 0x8875ff75, 0x00040000, + 0xbef60380, 0xbef703ff, + 0x10807fac, 0x876eff7f, + 0x08000000, 0x906e836e, + 0x88776e77, 0x876eff7f, + 0x70000000, 0x906e816e, + 0x88776e77, 0xb97202dc, + 0x8f729972, 0x8872727f, + 0x876eff7f, 0x04000000, + 0xbf840034, 0xbefe03c1, + 0x907c9972, 0x877c817c, + 0xbf06817c, 0xbf850002, + 0xbeff0380, 0xbf820001, + 0xbeff03c1, 0xb96f4306, + 0x876fc16f, 0xbf840029, + 0x8f6f866f, 0x8f6f826f, + 0xbef6036f, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0x8078ff78, + 0x00000080, 0xbef603ff, + 0x01000000, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbefc0380, 0xbf850009, + 0xe0310000, 0x781d0000, + 0x807cff7c, 0x00000080, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff8, + 0xbf820008, 0xe0310000, + 0x781d0000, 0x807cff7c, + 0x00000100, 0x8078ff78, + 0x00000100, 0xbf0a6f7c, + 0xbf85fff8, 0xbef80380, 0xbefe03c1, 0x907c9972, 0x877c817c, 0xbf06817c, 0xbf850002, 0xbeff0380, 0xbf820001, 0xbeff03c1, - 0xb96f4306, 0x876fc16f, - 0xbf840029, 0x8f6f866f, - 0x8f6f826f, 0xbef6036f, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0x8078ff78, 0x00000080, - 0xbef603ff, 0x01000000, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbefc0380, - 0xbf850009, 0xe0310000, - 0x781d0000, 0x807cff7c, - 0x00000080, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff8, 0xbf820008, - 0xe0310000, 0x781d0000, - 0x807cff7c, 0x00000100, - 0x8078ff78, 0x00000100, - 0xbf0a6f7c, 0xbf85fff8, - 0xbef80380, 0xbefe03c1, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850002, - 0xbeff0380, 0xbf820001, - 0xbeff03c1, 0xb96f2a05, - 0x806f816f, 0x8f6f826f, - 0x907c9972, 0x877c817c, - 0xbf06817c, 0xbf850021, - 0xbef603ff, 0x01000000, - 0xbeee0378, 0x8078ff78, - 0x00000200, 0xbefc0384, - 0xe0304000, 0x785d0000, - 0xe0304080, 0x785d0100, - 0xe0304100, 0x785d0200, - 0xe0304180, 0x785d0300, - 0xbf8c3f70, 0x7e008500, - 0x7e028501, 0x7e048502, - 0x7e068503, 0x807c847c, - 0x8078ff78, 0x00000200, - 0xbf0a6f7c, 0xbf85ffee, - 0xe0304000, 0x6e5d0000, - 0xe0304080, 0x6e5d0100, - 0xe0304100, 0x6e5d0200, - 0xe0304180, 0x6e5d0300, - 0xbf820032, 0xbef603ff, + 0xb96f2a05, 0x806f816f, + 0x8f6f826f, 0x907c9972, + 0x877c817c, 0xbf06817c, + 0xbf850021, 0xbef603ff, 0x01000000, 0xbeee0378, - 0x8078ff78, 0x00000400, + 0x8078ff78, 0x00000200, 0xbefc0384, 0xe0304000, - 0x785d0000, 0xe0304100, - 0x785d0100, 0xe0304200, - 0x785d0200, 0xe0304300, + 0x785d0000, 0xe0304080, + 0x785d0100, 0xe0304100, + 0x785d0200, 0xe0304180, 0x785d0300, 0xbf8c3f70, 0x7e008500, 0x7e028501, 0x7e048502, 0x7e068503, 0x807c847c, 0x8078ff78, - 0x00000400, 0xbf0a6f7c, - 0xbf85ffee, 0xb96f1e06, - 0x876fc16f, 0xbf84000e, - 0x8f6f836f, 0x806f7c6f, - 0xbefe03c1, 0xbeff0380, + 0x00000200, 0xbf0a6f7c, + 0xbf85ffee, 0xe0304000, + 0x6e5d0000, 0xe0304080, + 0x6e5d0100, 0xe0304100, + 0x6e5d0200, 0xe0304180, + 0x6e5d0300, 0xbf820032, + 0xbef603ff, 0x01000000, + 0xbeee0378, 0x8078ff78, + 0x00000400, 0xbefc0384, 0xe0304000, 0x785d0000, + 0xe0304100, 0x785d0100, + 0xe0304200, 0x785d0200, + 0xe0304300, 0x785d0300, 0xbf8c3f70, 0x7e008500, - 0x807c817c, 0x8078ff78, - 0x00000080, 0xbf0a6f7c, - 0xbf85fff7, 0xbeff03c1, - 0xe0304000, 0x6e5d0000, - 0xe0304100, 0x6e5d0100, - 0xe0304200, 0x6e5d0200, - 0xe0304300, 0x6e5d0300, - 0xbf8c3f70, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0x80f8ff78, - 0x00000050, 0xbef603ff, - 0x01000000, 0xbefc03ff, - 0x0000006c, 0x80f89078, - 0xf429003a, 0xf0000000, - 0xbf8cc07f, 0x80fc847c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0x80f8a078, - 0xf42d003a, 0xf0000000, - 0xbf8cc07f, 0x80fc887c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0x80f8c078, - 0xf431003a, 0xf0000000, - 0xbf8cc07f, 0x80fc907c, - 0xbf800000, 0xbe803100, - 0xbe823102, 0xbe843104, - 0xbe863106, 0xbe883108, - 0xbe8a310a, 0xbe8c310c, - 0xbe8e310e, 0xbf06807c, - 0xbf84fff0, 0xb9782a05, - 0x80788178, 0xbf0d9972, - 0xbf850002, 0x8f788978, - 0xbf820001, 0x8f788a78, - 0xb96e1e06, 0x8f6e8a6e, - 0x80786e78, 0x8078ff78, - 0x00000200, 0xbef603ff, - 0x01000000, 0xf4211bfa, + 0x7e028501, 0x7e048502, + 0x7e068503, 0x807c847c, + 0x8078ff78, 0x00000400, + 0xbf0a6f7c, 0xbf85ffee, + 0xb96f1e06, 0x876fc16f, + 0xbf84000e, 0x8f6f836f, + 0x806f7c6f, 0xbefe03c1, + 0xbeff0380, 0xe0304000, + 0x785d0000, 0xbf8c3f70, + 0x7e008500, 0x807c817c, + 0x8078ff78, 0x00000080, + 0xbf0a6f7c, 0xbf85fff7, + 0xbeff03c1, 0xe0304000, + 0x6e5d0000, 0xe0304100, + 0x6e5d0100, 0xe0304200, + 0x6e5d0200, 0xe0304300, + 0x6e5d0300, 0xbf8c3f70, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0x80f8ff78, 0x00000050, + 0xbef603ff, 0x01000000, + 0xbefc03ff, 0x0000006c, + 0x80f89078, 0xf429003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc847c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0x80f8a078, 0xf42d003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc887c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0x80f8c078, 0xf431003a, + 0xf0000000, 0xbf8cc07f, + 0x80fc907c, 0xbf800000, + 0xbe803100, 0xbe823102, + 0xbe843104, 0xbe863106, + 0xbe883108, 0xbe8a310a, + 0xbe8c310c, 0xbe8e310e, + 0xbf06807c, 0xbf84fff0, + 0xb9782a05, 0x80788178, + 0xbf0d9972, 0xbf850002, + 0x8f788978, 0xbf820001, + 0x8f788a78, 0xb96e1e06, + 0x8f6e8a6e, 0x80786e78, + 0x8078ff78, 0x00000200, + 0xbef603ff, 0x01000000, + 0xf4211bfa, 0xf0000000, + 0x80788478, 0xf4211b3a, 0xf0000000, 0x80788478, - 0xf4211b3a, 0xf0000000, - 0x80788478, 0xf4211b7a, + 0xf4211b7a, 0xf0000000, + 0x80788478, 0xf4211c3a, 0xf0000000, 0x80788478, - 0xf4211c3a, 0xf0000000, - 0x80788478, 0xf4211c7a, + 0xf4211c7a, 0xf0000000, + 0x80788478, 0xf4211eba, 0xf0000000, 0x80788478, - 0xf4211eba, 0xf0000000, - 0x80788478, 0xf4211efa, + 0xf4211efa, 0xf0000000, + 0x80788478, 0xf4211e7a, 0xf0000000, 0x80788478, - 0xf4211e7a, 0xf0000000, - 0x80788478, 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, 0xf4211bba, 0xf0000000, 0x80788478, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 4569db452160..5b220f2a7501 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -407,7 +407,6 @@ L_SAVE_HWREG: // Not used on Sienna_Cichlid but keep layout same for debugger. write_hwreg_to_mem(s_save_xnack_mask, s_save_buf_rsrc0, s_save_mem_offset) - s_add_u32 s_save_mem_offset, s_save_mem_offset, 4 s_getreg_b32 s_save_m0, hwreg(HW_REG_MODE) write_hwreg_to_mem(s_save_m0, s_save_buf_rsrc0, s_save_mem_offset) @@ -913,7 +912,6 @@ L_RESTORE_HWREG: read_hwreg_from_mem(s_restore_status, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_trapsts, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_xnack_mask, s_restore_buf_rsrc0, s_restore_mem_offset) - s_add_u32 s_restore_mem_offset, s_restore_mem_offset, 4 read_hwreg_from_mem(s_restore_mode, s_restore_buf_rsrc0, s_restore_mem_offset) read_hwreg_from_mem(s_restore_flat_scratch, s_restore_buf_rsrc0, s_restore_mem_offset) s_waitcnt lgkmcnt(0) -- cgit v1.2.3 From b60646a20c9f61e364c86cc88f50f547361cceb3 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 | 174 +++++++++++---------- .../gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm | 7 +- 2 files changed, 93 insertions(+), 88 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h index 577d901fdb63..affbca7c0050 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler.h @@ -911,7 +911,7 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, 0xbf85fff8, - 0xbf82014f, 0xbef4037e, + 0xbf820151, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, 0xbef703ff, @@ -1024,61 +1024,62 @@ static const uint32_t cwsr_trap_nv1x_hex[] = { 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xba80f801, 0x00000000, + 0xbf8a0000, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0xb9f9f816, - 0x876f7bff, 0xfffff800, - 0x906f8b6f, 0xb9efa2c3, - 0xb9f3f801, 0xb96e2a05, - 0x806e816e, 0xbf0d9972, - 0xbf850002, 0x8f6e896e, - 0xbf820001, 0x8f6e8a6e, - 0x806eff6e, 0x00000200, - 0x806e746e, 0x826f8075, - 0x876fff6f, 0x0000ffff, - 0xf4091c37, 0xfa000050, - 0xf4091d37, 0xfa000060, - 0xf4011e77, 0xfa000074, - 0xbf8cc07f, 0x876fff6d, - 0xfc000000, 0x906f9a6f, - 0x8f6f906f, 0xbeee0380, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0xb9f9f816, 0x876f7bff, + 0xfffff800, 0x906f8b6f, + 0xb9efa2c3, 0xb9f3f801, + 0xb96e2a05, 0x806e816e, + 0xbf0d9972, 0xbf850002, + 0x8f6e896e, 0xbf820001, + 0x8f6e8a6e, 0x806eff6e, + 0x00000200, 0x806e746e, + 0x826f8075, 0x876fff6f, + 0x0000ffff, 0xf4091c37, + 0xfa000050, 0xf4091d37, + 0xfa000060, 0xf4011e77, + 0xfa000074, 0xbf8cc07f, + 0x876fff6d, 0xfc000000, + 0x906f9a6f, 0x8f6f906f, + 0xbeee0380, 0x886e6f6e, + 0x876fff6d, 0x02000000, + 0x906f996f, 0x8f6f8f6f, 0x886e6f6e, 0x876fff6d, - 0x02000000, 0x906f996f, - 0x8f6f8f6f, 0x886e6f6e, - 0x876fff6d, 0x01000000, - 0x906f986f, 0x8f6f996f, - 0x886e6f6e, 0x876fff7a, - 0x00800000, 0x906f976f, - 0xb9eef807, 0x876dff6d, - 0x0000ffff, 0x87fe7e7e, - 0x87ea6a6a, 0xb9faf802, - 0xbf8a0000, 0xbe80226c, + 0x01000000, 0x906f986f, + 0x8f6f996f, 0x886e6f6e, + 0x876fff7a, 0x00800000, + 0x906f976f, 0xb9eef807, + 0x876dff6d, 0x0000ffff, + 0x87fe7e7e, 0x87ea6a6a, + 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, @@ -1807,7 +1808,7 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0x705d0000, 0x807c817c, 0x8070ff70, 0x00000080, 0xbf0a7b7c, 0xbf85fff8, - 0xbf82013a, 0xbef4037e, + 0xbf82013c, 0xbef4037e, 0x8775ff7f, 0x0000ffff, 0x8875ff75, 0x00040000, 0xbef60380, 0xbef703ff, @@ -1920,50 +1921,51 @@ static const uint32_t cwsr_trap_gfx10_hex[] = { 0xbe883108, 0xbe8a310a, 0xbe8c310c, 0xbe8e310e, 0xbf06807c, 0xbf84fff0, - 0xb9782a05, 0x80788178, - 0xbf0d9972, 0xbf850002, - 0x8f788978, 0xbf820001, - 0x8f788a78, 0xb96e1e06, - 0x8f6e8a6e, 0x80786e78, - 0x8078ff78, 0x00000200, - 0xbef603ff, 0x01000000, - 0xf4211bfa, 0xf0000000, - 0x80788478, 0xf4211b3a, + 0xba80f801, 0x00000000, + 0xbf8a0000, 0xb9782a05, + 0x80788178, 0xbf0d9972, + 0xbf850002, 0x8f788978, + 0xbf820001, 0x8f788a78, + 0xb96e1e06, 0x8f6e8a6e, + 0x80786e78, 0x8078ff78, + 0x00000200, 0xbef603ff, + 0x01000000, 0xf4211bfa, 0xf0000000, 0x80788478, - 0xf4211b7a, 0xf0000000, - 0x80788478, 0xf4211c3a, + 0xf4211b3a, 0xf0000000, + 0x80788478, 0xf4211b7a, 0xf0000000, 0x80788478, - 0xf4211c7a, 0xf0000000, - 0x80788478, 0xf4211eba, + 0xf4211c3a, 0xf0000000, + 0x80788478, 0xf4211c7a, 0xf0000000, 0x80788478, - 0xf4211efa, 0xf0000000, - 0x80788478, 0xf4211e7a, + 0xf4211eba, 0xf0000000, + 0x80788478, 0xf4211efa, 0xf0000000, 0x80788478, - 0xf4211cfa, 0xf0000000, - 0x80788478, 0xf4211bba, + 0xf4211e7a, 0xf0000000, + 0x80788478, 0xf4211cfa, 0xf0000000, 0x80788478, - 0xbf8cc07f, 0xb9eef814, 0xf4211bba, 0xf0000000, 0x80788478, 0xbf8cc07f, - 0xb9eef815, 0xbefc036f, - 0xbefe0370, 0xbeff0371, - 0x876f7bff, 0x000003ff, - 0xb9ef4803, 0x876f7bff, - 0xfffff800, 0x906f8b6f, - 0xb9efa2c3, 0xb9f3f801, - 0xb96e2a05, 0x806e816e, - 0xbf0d9972, 0xbf850002, - 0x8f6e896e, 0xbf820001, - 0x8f6e8a6e, 0x806eff6e, - 0x00000200, 0x806e746e, - 0x826f8075, 0x876fff6f, - 0x0000ffff, 0xf4091c37, - 0xfa000050, 0xf4091d37, - 0xfa000060, 0xf4011e77, - 0xfa000074, 0xbf8cc07f, - 0x876dff6d, 0x0000ffff, - 0x87fe7e7e, 0x87ea6a6a, - 0xb9faf802, 0xbf8a0000, + 0xb9eef814, 0xf4211bba, + 0xf0000000, 0x80788478, + 0xbf8cc07f, 0xb9eef815, + 0xbefc036f, 0xbefe0370, + 0xbeff0371, 0x876f7bff, + 0x000003ff, 0xb9ef4803, + 0x876f7bff, 0xfffff800, + 0x906f8b6f, 0xb9efa2c3, + 0xb9f3f801, 0xb96e2a05, + 0x806e816e, 0xbf0d9972, + 0xbf850002, 0x8f6e896e, + 0xbf820001, 0x8f6e8a6e, + 0x806eff6e, 0x00000200, + 0x806e746e, 0x826f8075, + 0x876fff6f, 0x0000ffff, + 0xf4091c37, 0xfa000050, + 0xf4091d37, 0xfa000060, + 0xf4011e77, 0xfa000074, + 0xbf8cc07f, 0x876dff6d, + 0x0000ffff, 0x87fe7e7e, + 0x87ea6a6a, 0xb9faf802, 0xbe80226c, 0xbf810000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, 0xbf9f0000, diff --git a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm index 5b220f2a7501..5081f91190b8 100644 --- a/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm +++ b/drivers/gpu/drm/amd/amdkfd/cwsr_trap_handler_gfx10.asm @@ -894,6 +894,11 @@ L_RESTORE_SGPR: s_cmp_eq_u32 m0, 0 //scc = (m0 < s_sgpr_save_num) ? 1 : 0 s_cbranch_scc0 L_RESTORE_SGPR_LOOP + // s_barrier with MODE.DEBUG_EN=1, STATUS.PRIV=1 incorrectly asserts debug exception. + // Clear DEBUG_EN before and restore MODE after the barrier. + s_setreg_imm32_b32 hwreg(HW_REG_MODE), 0 + s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG + /* restore HW registers */ L_RESTORE_HWREG: // HWREG SR memory offset : size(VGPR)+size(SVGPR)+size(SGPR) @@ -976,8 +981,6 @@ L_RESTORE_HWREG: s_and_b64 vcc, vcc, vcc // Restore STATUS.VCCZ, not writable by s_setreg_b32 s_setreg_b32 hwreg(HW_REG_STATUS), s_restore_status // SCC is included, which is changed by previous salu - s_barrier //barrier to ensure the readiness of LDS before access attemps from any other wave in the same TG - s_rfe_b64 s_restore_pc_lo //Return to the main shader program and resume execution L_END_PGM: -- cgit v1.2.3 From 1d4473261966bef70ff65ebb303bae98949b8f8a Mon Sep 17 00:00:00 2001 From: Liu ChengZhe Date: Thu, 6 Aug 2020 14:54:08 +0800 Subject: drm/amdgpu: Skip some registers config for SRIOV Some registers are not accessible to virtual function setup, so skip their initialization when in VF-SRIOV mode. v2: move SRIOV VF check into specify functions; modify commit description and comment. Signed-off-by: Liu ChengZhe Reviewed-by: Luben Tuikov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 1f6112b7fa49..80c906a0383f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -182,6 +182,12 @@ static void gfxhub_v2_1_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -237,6 +243,12 @@ static void gfxhub_v2_1_enable_system_domain(struct amdgpu_device *adev) static void gfxhub_v2_1_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32, @@ -373,6 +385,13 @@ void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index d83912901f73..8acb3b625afe 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -181,6 +181,12 @@ static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -236,6 +242,12 @@ static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev) static void mmhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); @@ -365,6 +377,13 @@ void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); -- cgit v1.2.3 From 7358462f7de98f95550f27abf805d4d5c95e2a5c Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 7 Aug 2020 15:03:40 +0800 Subject: drm/amd/powerplay: correct Vega20 cached smu feature state Correct the cached smu feature state on pp_features sysfs setting. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 86d3a10379be..303e764af11a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -984,10 +984,7 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) { struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - int ret = 0; + int i, ret = 0; PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, @@ -995,17 +992,8 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) "[DisableAllSMUFeatures] Failed to disable all smu features!", return ret); - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[DisableAllSMUFeatures] Failed to get enabled smc features!", - return ret); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? - true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - } + for (i = 0; i < GNLD_FEATURES_MAX; i++) + data->smu_features[i].enabled = 0; return 0; } @@ -3242,10 +3230,11 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) { - uint64_t features_enabled; - uint64_t features_to_enable; - uint64_t features_to_disable; - int ret = 0; + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint64_t features_enabled, features_to_enable, features_to_disable; + int i, ret = 0; + bool enabled; if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) return -EINVAL; @@ -3274,6 +3263,17 @@ static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return ret; } + /* Update the cached feature enablement state */ + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? + true : false; + data->smu_features[i].enabled = enabled; + } + return 0; } -- cgit v1.2.3 From 8d0717f422255513ae1afab2ea0b75ba9f1512a9 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 7 Aug 2020 17:01:47 +0800 Subject: drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading The UVD/VCE PG state is managed by UVD and VCE IP. It's error-prone to assume the bootup state in SMU based on the dpm status. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 303e764af11a..c9f402edc0d6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -1645,12 +1645,6 @@ static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) data->uvd_power_gated = true; data->vce_power_gated = true; - - if (data->smu_features[GNLD_DPM_UVD].enabled) - data->uvd_power_gated = false; - - if (data->smu_features[GNLD_DPM_VCE].enabled) - data->vce_power_gated = false; } static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -- cgit v1.2.3 From 5a58abf5ed4f63e0d8c6f542da1d9e2dd8dea1bc Mon Sep 17 00:00:00 2001 From: shiwu.zhang Date: Fri, 7 Aug 2020 16:43:59 +0800 Subject: drm/amdgpu: update gc golden register for arcturus Update golden setting to improve performance on HPC and ML apps Signed-off-by: shiwu.zhang Tested-by: gang.long Reviewed-by: guchun.chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index ef07e59cd426..93c63ff3b35e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -691,6 +691,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_4_1_arct[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_5_ARCT, 0x3ff, 0x135), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_CONFIG, 0xffffffff, 0x011A0000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_FIFO_SIZES, 0xffffffff, 0x00000f00), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_UTCL1_CNTL1, 0x30000000, 0x30000000) }; static const struct soc15_reg_rlcg rlcg_access_gc_9_0[] = { -- cgit v1.2.3 From bcca6298069435fa7f23ab98f4cb635fcbd3bc20 Mon Sep 17 00:00:00 2001 From: Monk Liu Date: Mon, 10 Aug 2020 14:12:06 +0800 Subject: drm/amdgpu: fix reload KMD hang on GFX10 KIQ GFX10 KIQ will hang if we try below steps: modprobe amdgpu rmmod amdgpu modprobe amdgpu sched_hw_submission=4 Due to KIQ is always living there even after KMD unloaded thus when doing the realod KIQ will crash upon its register being programed by different values with the previous loading (the config like HQD addr, ring size, is easily changed if we alter the sched_hw_submission) the fix is we must inactive KIQ first before touching any of its registgers Signed-off-by: Monk Liu Reviewed-by: Emily Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 622f4425bf59..0702c94fcca3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6435,6 +6435,10 @@ static int gfx_v10_0_kiq_init_register(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int j; + /* inactivate the queue */ + if (amdgpu_sriov_vf(adev)) + WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, 0); + /* disable wptr polling */ WREG32_FIELD15(GC, 0, CP_PQ_WPTR_POLL_CNTL, EN, 0); -- cgit v1.2.3 From fe04afad4ee144557fbf7196c5746cfe57fbdf47 Mon Sep 17 00:00:00 2001 From: Joshua Aberback Date: Thu, 16 Jul 2020 12:39:27 -0400 Subject: drm/amd/display: Adjust static-ness of resource functions [Why] Register definitions are asic-specific, so functions that use registers of a particular asic should be static, to be exposed in asic-specific function pointer structures. [How] - make register-definition-using functions static - make some functions non-static, for future use - remove duplicate function definition Signed-off-by: Joshua Aberback Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn20/dcn20_resource.h | 1 - .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 27 ++++++++++++---------- .../gpu/drm/amd/display/dc/dcn30/dcn30_resource.h | 3 +++ 3 files changed, 18 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h index 2c1959845c29..cdd39ee9761d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.h @@ -95,7 +95,6 @@ struct display_stream_compressor *dcn20_dsc_create( struct dc_context *ctx, uint32_t inst); void dcn20_dsc_destroy(struct display_stream_compressor **dsc); -void dcn20_patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb); void dcn20_cap_soc_clocks( struct _vcs_dpi_soc_bounding_box_st *bb, struct pp_smu_nv_clock_table max_clocks); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index d474a6188445..aa3ea6c79c27 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -871,7 +871,7 @@ void dcn30_dpp_destroy(struct dpp **dpp) *dpp = NULL; } -struct dpp *dcn30_dpp_create( +static struct dpp *dcn30_dpp_create( struct dc_context *ctx, uint32_t inst) { @@ -889,7 +889,8 @@ struct dpp *dcn30_dpp_create( kfree(dpp); return NULL; } -struct output_pixel_processor *dcn30_opp_create( + +static struct output_pixel_processor *dcn30_opp_create( struct dc_context *ctx, uint32_t inst) { struct dcn20_opp *opp = @@ -905,7 +906,7 @@ struct output_pixel_processor *dcn30_opp_create( return &opp->base; } -struct dce_aux *dcn30_aux_engine_create( +static struct dce_aux *dcn30_aux_engine_create( struct dc_context *ctx, uint32_t inst) { @@ -924,6 +925,7 @@ struct dce_aux *dcn30_aux_engine_create( return &aux_engine->base; } + #define i2c_inst_regs(id) { I2C_HW_ENGINE_COMMON_REG_LIST(id) } static const struct dce_i2c_registers i2c_hw_regs[] = { @@ -943,7 +945,7 @@ static const struct dce_i2c_mask i2c_masks = { I2C_COMMON_MASK_SH_LIST_DCN2(_MASK) }; -struct dce_i2c_hw *dcn30_i2c_hw_create( +static struct dce_i2c_hw *dcn30_i2c_hw_create( struct dc_context *ctx, uint32_t inst) { @@ -958,6 +960,7 @@ struct dce_i2c_hw *dcn30_i2c_hw_create( return dce_i2c_hw; } + static struct mpc *dcn30_mpc_create( struct dc_context *ctx, int num_mpcc, @@ -1008,7 +1011,7 @@ struct hubbub *dcn30_hubbub_create(struct dc_context *ctx) return &hubbub3->base; } -struct timing_generator *dcn30_timing_generator_create( +static struct timing_generator *dcn30_timing_generator_create( struct dc_context *ctx, uint32_t instance) { @@ -1042,7 +1045,7 @@ static const struct encoder_feature_support link_enc_feature = { .flags.bits.IS_TPS4_CAPABLE = true }; -struct link_encoder *dcn30_link_encoder_create( +static struct link_encoder *dcn30_link_encoder_create( const struct encoder_init_data *enc_init_data) { struct dcn20_link_encoder *enc20 = @@ -1063,7 +1066,7 @@ struct link_encoder *dcn30_link_encoder_create( return &enc20->enc10.base; } -struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) +static struct panel_cntl *dcn30_panel_cntl_create(const struct panel_cntl_init_data *init_data) { struct dce_panel_cntl *panel_cntl = kzalloc(sizeof(struct dce_panel_cntl), GFP_KERNEL); @@ -1311,7 +1314,7 @@ static void dcn30_resource_destruct(struct dcn30_resource_pool *pool) dcn_dccg_destroy(&pool->base.dccg); } -struct hubp *dcn30_hubp_create( +static struct hubp *dcn30_hubp_create( struct dc_context *ctx, uint32_t inst) { @@ -1330,7 +1333,7 @@ struct hubp *dcn30_hubp_create( return NULL; } -bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) +static bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) { int i; uint32_t pipe_count = pool->res_cap->num_dwb; @@ -1355,7 +1358,7 @@ bool dcn30_dwbc_create(struct dc_context *ctx, struct resource_pool *pool) return true; } -bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) +static bool dcn30_mmhubbub_create(struct dc_context *ctx, struct resource_pool *pool) { int i; uint32_t pipe_count = pool->res_cap->num_dwb; @@ -2292,7 +2295,7 @@ static void get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts, (dcn3_0_soc.return_bus_width_bytes * (dcn3_0_soc.max_avg_sdp_bw_use_normal_percent / 100)); } -static void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) { unsigned int i, j; unsigned int num_states = 0; @@ -2683,7 +2686,7 @@ static bool dcn30_resource_construct( if (!resource_construct(num_virtual_links, dc, &pool->base, (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment) ? &res_create_funcs : &res_create_maximus_funcs))) - goto create_fail; + goto create_fail; /* HW Sequencer and Plane caps */ dcn30_hw_sequencer_construct(dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h index 4b4a4d81c1e3..c9d5f94092a0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.h @@ -79,4 +79,7 @@ enum dc_status dcn30_add_stream_to_ctx( struct dc *dc, struct dc_state *new_ctx, struct dc_stream_state *dc_stream); + +void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + #endif /* _DCN30_RESOURCE_H_ */ -- cgit v1.2.3 From 5396fa590df764775e83c9014330bc4112a75f63 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 27 Jul 2020 21:21:16 -0400 Subject: drm/amd/display: Fix incorrect backlight register offset for DCN [Why] Typo in backlight refactor inctroduced wrong register offset. [How] Change DCE to DCN register map for PWRSEQ_REF_DIV Cc: stable@vger.kernel.org Signed-off-by: Aric Cyr Reviewed-by: Ashley Thomas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 70ec691e14d2..99c68ca9c7e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -49,7 +49,7 @@ #define DCN_PANEL_CNTL_REG_LIST()\ DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \ DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ - DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ + DCN_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ SR(BL_PWM_CNTL), \ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ -- cgit v1.2.3 From ffe0fcbb20d61ccf670e17a89b0dc06be141cce0 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 29 Jul 2020 17:49:14 -0400 Subject: drm/amd/display: Revert regression [Why] Caused pipe split regression Signed-off-by: Alvin Lee Reviewed-by: Aric Cyr Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 -- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 114 --------------------- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h | 7 -- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 - drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 - drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 - drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 - 7 files changed, 141 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ebbb8182228d..5aa3b89471c3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,7 +2300,6 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { - bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2331,15 +2330,6 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } - if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && - dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ - dc->hwss.interdependent_update_lock(dc, context, true); - mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); - dc->hwss.interdependent_update_lock(dc, context, false); - if (mpcc_disconnected) - dc->hwss.wait_for_pending_cleared(dc, context); - } - for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 73eb4e76a0b1..66180b4332f1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1624,120 +1624,6 @@ static void dcn20_program_pipe( } } -bool dcn20_disconnect_pipes( - struct dc *dc, - struct dc_state *context) -{ - int i; - struct dce_hwseq *hws = dc->hwseq; - bool mpcc_disconnected = false; - DC_LOGGER_INIT(dc->ctx->logger); - - /* Set pipe update flags and lock pipes */ - for (i = 0; i < dc->res_pool->pipe_count; i++) - dcn20_detect_pipe_changes(&dc->current_state->res_ctx.pipe_ctx[i], - &context->res_ctx.pipe_ctx[i]); - - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - /* OTG blank before disabling all front ends */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable - && !context->res_ctx.pipe_ctx[i].top_pipe - && !context->res_ctx.pipe_ctx[i].prev_odm_pipe - && context->res_ctx.pipe_ctx[i].stream) { - hws->funcs.blank_pixel_data(dc, &context->res_ctx.pipe_ctx[i], true); - } - } - - /* Disconnect mpcc */ - for (i = 0; i < dc->res_pool->pipe_count; i++) { - if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable) { - hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); - DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); - mpcc_disconnected = true; - } - } - } - - if (mpcc_disconnected) { - for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; - struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; - struct dc_plane_state *plane_state = pipe_ctx->plane_state; - struct hubp *hubp = pipe_ctx->plane_res.hubp; - - if (!pipe_ctx || !plane_state || !pipe_ctx->stream) - continue; - - // Only update scaler and viewport here if we lose a pipe split. - // This is to prevent half the screen from being black when we - // unlock after disconnecting MPCC. - if (!(old_pipe && !pipe_ctx->top_pipe && - !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) - continue; - - if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { - if (pipe_ctx->update_flags.bits.scaler || - plane_state->update_flags.bits.scaling_change || - plane_state->update_flags.bits.position_change || - plane_state->update_flags.bits.per_pixel_alpha_change || - pipe_ctx->stream->update_flags.bits.scaling) { - - pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; - ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); - /* scaler configuration */ - pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( - pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); - } - - if (pipe_ctx->update_flags.bits.viewport || - (context == dc->current_state && plane_state->update_flags.bits.position_change) || - (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || - (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { - - hubp->funcs->mem_program_viewport( - hubp, - &pipe_ctx->plane_res.scl_data.viewport, - &pipe_ctx->plane_res.scl_data.viewport_c); - } - } - } - } - return mpcc_disconnected; -} - -void dcn20_wait_for_pending_cleared(struct dc *dc, - struct dc_state *context) -{ - struct pipe_ctx *pipe_ctx; - struct timing_generator *tg; - int i; - - for (i = 0; i < dc->res_pool->pipe_count; i++) { - pipe_ctx = &context->res_ctx.pipe_ctx[i]; - tg = pipe_ctx->stream_res.tg; - - /* - * Only wait for top pipe's tg penindg bit - * Also skip if pipe is disabled. - */ - if (pipe_ctx->top_pipe || - !pipe_ctx->stream || !pipe_ctx->plane_state || - !tg->funcs->is_tg_enabled(tg)) - continue; - - /* - * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. - * For some reason waiting for OTG_UPDATE_PENDING cleared - * seems to not trigger the update right away, and if we - * lock again before VUPDATE then we don't get a separated - * operation. - */ - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); - pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); - } -} - void dcn20_program_front_end_for_ctx( struct dc *dc, struct dc_state *context) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h index 7befd35a2359..83220e34c1a9 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.h @@ -131,13 +131,6 @@ void dcn20_dccg_init(struct dce_hwseq *hws); int dcn20_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config); -bool dcn20_disconnect_pipes( - struct dc *dc, - struct dc_state *context); - -void dcn20_wait_for_pending_cleared(struct dc *dc, - struct dc_state *context); - #ifndef TRIM_FSFT bool dcn20_optimize_timing_for_fsft(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 55afb70d33e5..3dde6f26de47 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,8 +34,6 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index 264302b27d4f..b187f71afa65 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,8 +35,6 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 845aaf1c816c..9afee7160490 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,8 +35,6 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, - .disconnect_pipes = dcn20_disconnect_pipes, - .wait_for_pending_cleared = dcn20_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 64c1be818b0e..3c986717dcd5 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,10 +67,6 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); - bool (*disconnect_pipes)(struct dc *dc, - struct dc_state *context); - void (*wait_for_pending_cleared)(struct dc *dc, - struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- cgit v1.2.3 From c0c96fc9c2ca845c2d79006c543e337a31969ac2 Mon Sep 17 00:00:00 2001 From: Xiaodong Yan Date: Tue, 28 Jul 2020 18:12:45 +0800 Subject: drm/amd/display: mpcc black color should not be impacted by pixel encoding format [Why] The format in MPCC should be 444 [How] do not modify the mpcc black color according to pixel encoding format Signed-off-by: Xiaodong Yan Reviewed-by: Eric Yang Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers/gpu') 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 a643927e272b..57cd52789606 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2368,14 +2368,6 @@ void dcn10_update_mpcc(struct dc *dc, struct pipe_ctx *pipe_ctx) &blnd_cfg.black_color); } - /* - * The way 420 is packed, 2 channels carry Y component, 1 channel - * alternate between Cb and Cr, so both channels need the pixel - * value for Y - */ - if (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) - blnd_cfg.black_color.color_r_cr = blnd_cfg.black_color.color_g_y; - if (per_pixel_alpha) blnd_cfg.alpha_mode = MPCC_ALPHA_BLEND_MODE_PER_PIXEL_ALPHA; else -- cgit v1.2.3 From 575da8db31572d1d8de572d0b6ffb113624c2f8f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 29 Jul 2020 17:33:27 -0400 Subject: drm/amd/display: Fix LFC multiplier changing erratically [Why] 1. There is a calculation that is using frame_time_in_us instead of last_render_time_in_us to calculate whether choosing an LFC multiplier would cause the inserted frame duration to be outside of range. 2. We do not handle unsigned integer subtraction correctly and it underflows to a really large value, which causes some logic errors. [How] 1. Fix logic to calculate 'within range' using last_render_time_in_us 2. Split out delta_from_mid_point_delta_in_us calculation to ensure we don't underflow and wrap around Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 36 +++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 81820f3d6b3b..d988533d4af5 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -324,22 +324,44 @@ static void apply_below_the_range(struct core_freesync *core_freesync, /* Choose number of frames to insert based on how close it * can get to the mid point of the variable range. + * - Delta for CEIL: delta_from_mid_point_in_us_1 + * - Delta for FLOOR: delta_from_mid_point_in_us_2 */ - if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us && - (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 || - mid_point_frames_floor < 2)) { + if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { + /* Check for out of range. + * If using CEIL produces a value that is out of range, + * then we are forced to use FLOOR. + */ + frames_to_insert = mid_point_frames_floor; + } else if (mid_point_frames_floor < 2) { + /* Check if FLOOR would result in non-LFC. In this case + * choose to use CEIL + */ + frames_to_insert = mid_point_frames_ceil; + } else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + /* If choosing CEIL results in a frame duration that is + * closer to the mid point of the range. + * Choose CEIL + */ frames_to_insert = mid_point_frames_ceil; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - - delta_from_mid_point_in_us_1; } else { + /* If choosing FLOOR results in a frame duration that is + * closer to the mid point of the range. + * Choose FLOOR + */ frames_to_insert = mid_point_frames_floor; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - - delta_from_mid_point_in_us_2; } /* Prefer current frame multiplier when BTR is enabled unless it drifts * too far from the midpoint */ + if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - + delta_from_mid_point_in_us_1; + } else { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - + delta_from_mid_point_in_us_2; + } if (in_out_vrr->btr.frames_to_insert != 0 && delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) { if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < -- cgit v1.2.3 From 073e7cd56d04110792a7a16b344d8b462178cadb Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 29 Jul 2020 17:43:10 -0400 Subject: drm/amd/display: Switch to immediate mode for updating infopackets [Why] Using FRAME_UPDATE will result in infopacket to be potentially updated one frame late. In commit stream scenarios for previously active stream, some stale infopacket data from previous config might be erroneously sent out on initial frame after stream is re-enabled. [How] Switch to using IMMEDIATE_UPDATE mode Signed-off-by: Anthony Koo Reviewed-by: Ashley Thomas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 16 ++++++++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 07b2f9399671..842abb4c475b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -121,35 +121,35 @@ void enc1_update_generic_info_packet( switch (packet_index) { case 0: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC0_FRAME_UPDATE, 1); + AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); break; case 1: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC1_FRAME_UPDATE, 1); + AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); break; case 2: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC2_FRAME_UPDATE, 1); + AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); break; case 3: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC3_FRAME_UPDATE, 1); + AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); break; case 4: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_FRAME_UPDATE, 1); + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); break; case 5: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC5_FRAME_UPDATE, 1); + AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); break; case 6: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC6_FRAME_UPDATE, 1); + AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); break; case 7: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_FRAME_UPDATE, 1); + AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index ed385b1477be..30eae7459d50 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -281,7 +281,14 @@ struct dcn10_stream_enc_registers { SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ @@ -345,7 +352,14 @@ struct dcn10_stream_enc_registers { type AFMT_GENERIC2_FRAME_UPDATE;\ type AFMT_GENERIC3_FRAME_UPDATE;\ type AFMT_GENERIC4_FRAME_UPDATE;\ + type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ type AFMT_GENERIC5_FRAME_UPDATE;\ type AFMT_GENERIC6_FRAME_UPDATE;\ type AFMT_GENERIC7_FRAME_UPDATE;\ -- cgit v1.2.3 From 81b437f57e35a6caa3a4304e6fff0eba0a9f3266 Mon Sep 17 00:00:00 2001 From: Alvin Lee Date: Wed, 29 Jul 2020 23:08:59 -0400 Subject: drm/amd/display: Disconnect pipe separetely when disable pipe split [Why] When changing pixel formats for HDR (e.g. ARGB -> FP16) there are configurations that change from 2 pipes to 1 pipe. In these cases, it seems that disconnecting MPCC and doing a surface update at the same time(after unlocking) causes some registers to be updated slightly faster than others after unlocking (e.g. if the pixel format is updated to FP16 before the new surface address is programmed, we get corruption on the screen because the pixel formats aren't matching). We separate disconnecting MPCC from the rest of the pipe programming sequence to prevent this. [How] Move MPCC disconnect into separate operation than the rest of the pipe programming. Signed-off-by: Alvin Lee Reviewed-by: Aric Cyr Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 146 +++++++++++++++++++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h | 6 + drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c | 2 + drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c | 2 + drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c | 2 + drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c | 2 + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 4 + 8 files changed, 174 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5aa3b89471c3..ebbb8182228d 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2300,6 +2300,7 @@ static void commit_planes_for_stream(struct dc *dc, enum surface_update_type update_type, struct dc_state *context) { + bool mpcc_disconnected = false; int i, j; struct pipe_ctx *top_pipe_to_program = NULL; @@ -2330,6 +2331,15 @@ static void commit_planes_for_stream(struct dc *dc, context_clock_trace(dc, context); } + if (update_type != UPDATE_TYPE_FAST && dc->hwss.interdependent_update_lock && + dc->hwss.disconnect_pipes && dc->hwss.wait_for_pending_cleared){ + dc->hwss.interdependent_update_lock(dc, context, true); + mpcc_disconnected = dc->hwss.disconnect_pipes(dc, context); + dc->hwss.interdependent_update_lock(dc, context, false); + if (mpcc_disconnected) + dc->hwss.wait_for_pending_cleared(dc, context); + } + for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 57cd52789606..95e9d05f884b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2752,6 +2752,152 @@ static struct pipe_ctx *dcn10_find_top_pipe_for_stream( return NULL; } +bool dcn10_disconnect_pipes( + struct dc *dc, + struct dc_state *context) +{ + bool found_stream = false; + int i, j; + struct dce_hwseq *hws = dc->hwseq; + struct dc_state *old_ctx = dc->current_state; + bool mpcc_disconnected = false; + struct pipe_ctx *old_pipe; + struct pipe_ctx *new_pipe; + DC_LOGGER_INIT(dc->ctx->logger); + + /* Set pipe update flags and lock pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + new_pipe = &context->res_ctx.pipe_ctx[i]; + new_pipe->update_flags.raw = 0; + + if (!old_pipe->plane_state && !new_pipe->plane_state) + continue; + + if (old_pipe->plane_state && !new_pipe->plane_state) + new_pipe->update_flags.bits.disable = 1; + + /* Check for scl update */ + if (memcmp(&old_pipe->plane_res.scl_data, &new_pipe->plane_res.scl_data, sizeof(struct scaler_data))) + new_pipe->update_flags.bits.scaler = 1; + + /* Check for vp update */ + if (memcmp(&old_pipe->plane_res.scl_data.viewport, &new_pipe->plane_res.scl_data.viewport, sizeof(struct rect)) + || memcmp(&old_pipe->plane_res.scl_data.viewport_c, + &new_pipe->plane_res.scl_data.viewport_c, sizeof(struct rect))) + new_pipe->update_flags.bits.viewport = 1; + + } + + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + /* Disconnect mpcc here only if losing pipe split*/ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable && + old_ctx->res_ctx.pipe_ctx[i].top_pipe) { + + /* Find the top pipe in the new ctx for the bottom pipe that we + * want to remove by comparing the streams. If both pipes are being + * disabled then do it in the regular pipe programming sequence + */ + for (j = 0; j < dc->res_pool->pipe_count; j++) { + if (old_ctx->res_ctx.pipe_ctx[i].top_pipe->stream == context->res_ctx.pipe_ctx[j].stream && + !context->res_ctx.pipe_ctx[j].top_pipe && + !context->res_ctx.pipe_ctx[j].update_flags.bits.disable) { + found_stream = true; + break; + } + } + + // Disconnect if the top pipe lost it's pipe split + if (found_stream && !context->res_ctx.pipe_ctx[j].bottom_pipe) { + hws->funcs.plane_atomic_disconnect(dc, &dc->current_state->res_ctx.pipe_ctx[i]); + DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); + mpcc_disconnected = true; + } + } + found_stream = false; + } + } + + if (mpcc_disconnected) { + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; + struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i]; + struct dc_plane_state *plane_state = pipe_ctx->plane_state; + struct hubp *hubp = pipe_ctx->plane_res.hubp; + + if (!pipe_ctx || !plane_state || !pipe_ctx->stream) + continue; + + // Only update scaler and viewport here if we lose a pipe split. + // This is to prevent half the screen from being black when we + // unlock after disconnecting MPCC. + if (!(old_pipe && !pipe_ctx->top_pipe && + !pipe_ctx->bottom_pipe && old_pipe->bottom_pipe)) + continue; + + if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw) { + if (pipe_ctx->update_flags.bits.scaler || + plane_state->update_flags.bits.scaling_change || + plane_state->update_flags.bits.position_change || + plane_state->update_flags.bits.per_pixel_alpha_change || + pipe_ctx->stream->update_flags.bits.scaling) { + + pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->plane_state->per_pixel_alpha; + ASSERT(pipe_ctx->plane_res.scl_data.lb_params.depth == LB_PIXEL_DEPTH_30BPP); + /* scaler configuration */ + pipe_ctx->plane_res.dpp->funcs->dpp_set_scaler( + pipe_ctx->plane_res.dpp, &pipe_ctx->plane_res.scl_data); + } + + if (pipe_ctx->update_flags.bits.viewport || + (context == dc->current_state && plane_state->update_flags.bits.position_change) || + (context == dc->current_state && plane_state->update_flags.bits.scaling_change) || + (context == dc->current_state && pipe_ctx->stream->update_flags.bits.scaling)) { + + hubp->funcs->mem_program_viewport( + hubp, + &pipe_ctx->plane_res.scl_data.viewport, + &pipe_ctx->plane_res.scl_data.viewport_c); + } + } + } + } + return mpcc_disconnected; +} + +void dcn10_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *pipe_ctx; + struct timing_generator *tg; + int i; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe_ctx = &context->res_ctx.pipe_ctx[i]; + tg = pipe_ctx->stream_res.tg; + + /* + * Only wait for top pipe's tg penindg bit + * Also skip if pipe is disabled. + */ + if (pipe_ctx->top_pipe || + !pipe_ctx->stream || !pipe_ctx->plane_state || + !tg->funcs->is_tg_enabled(tg)) + continue; + + /* + * Wait for VBLANK then VACTIVE to ensure we get VUPDATE. + * For some reason waiting for OTG_UPDATE_PENDING cleared + * seems to not trigger the update right away, and if we + * lock again before VUPDATE then we don't get a separated + * operation. + */ + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); + pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); + } +} + void dcn10_apply_ctx_for_surface( struct dc *dc, const struct dc_stream_state *stream, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h index 6d891166da8a..e5691e499023 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.h @@ -194,6 +194,12 @@ void dcn10_get_surface_visual_confirm_color( void dcn10_get_hdr_visual_confirm_color( struct pipe_ctx *pipe_ctx, struct tg_color *color); +bool dcn10_disconnect_pipes( + struct dc *dc, + struct dc_state *context); + +void dcn10_wait_for_pending_cleared(struct dc *dc, + struct dc_state *context); void dcn10_set_hdr_multiplier(struct pipe_ctx *pipe_ctx); void dcn10_verify_allow_pstate_change_high(struct dc *dc); diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c index 5c98b71c1d47..a1d1559bb5d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = dcn10_apply_ctx_for_surface, .post_unlock_program_front_end = dcn10_post_unlock_program_front_end, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .update_plane_addr = dcn10_update_plane_addr, .update_dchub = dcn10_update_dchub, .update_pending_status = dcn10_update_pending_status, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c index 3dde6f26de47..966e1790b9bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_init.c @@ -34,6 +34,8 @@ static const struct hw_sequencer_funcs dcn20_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c index b187f71afa65..2ba880c3943c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn21_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c index 9afee7160490..19daa456e3bf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_init.c @@ -35,6 +35,8 @@ static const struct hw_sequencer_funcs dcn30_funcs = { .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, + .disconnect_pipes = dcn10_disconnect_pipes, + .wait_for_pending_cleared = dcn10_wait_for_pending_cleared, .post_unlock_program_front_end = dcn20_post_unlock_program_front_end, .update_plane_addr = dcn20_update_plane_addr, .update_dchub = dcn10_update_dchub, diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h index 3c986717dcd5..64c1be818b0e 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h @@ -67,6 +67,10 @@ struct hw_sequencer_funcs { int num_planes, struct dc_state *context); void (*program_front_end_for_ctx)(struct dc *dc, struct dc_state *context); + bool (*disconnect_pipes)(struct dc *dc, + struct dc_state *context); + void (*wait_for_pending_cleared)(struct dc *dc, + struct dc_state *context); void (*post_unlock_program_front_end)(struct dc *dc, struct dc_state *context); void (*update_plane_addr)(const struct dc *dc, -- cgit v1.2.3 From 57321eae08d67c6cce0030b37812b64417569f12 Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Tue, 28 Jul 2020 15:10:35 +0800 Subject: drm/amd/display: Fix EDID parsing after resume from suspend [Why] Resuming from suspend, CEA blocks from EDID are not parsed and no video modes can support YUV420. When this happens, output bpc cannot go over 8-bit with 4K modes on HDMI. [How] In amdgpu_dm_update_connector_after_detect(), drm_add_edid_modes() is called after drm_connector_update_edid_property() to fully parse EDID and update display info. Cc: stable@vger.kernel.org Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') 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 8f27bebf4633..68b88c97014b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2202,6 +2202,7 @@ void amdgpu_dm_update_connector_after_detect( drm_connector_update_edid_property(connector, aconnector->edid); + drm_add_edid_modes(connector, aconnector->edid); if (aconnector->dc_link->aux_mode) drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, -- cgit v1.2.3 From 8db2d634ed29eeaed56fdbeaf63da7ae9e65280b Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Thu, 30 Jul 2020 16:31:29 -0400 Subject: drm/amd/display: Blank stream before destroying HDCP session [Why] Stream disable sequence incorretly destroys HDCP session while stream is not blanked and while audio is not muted. This sequence causes a flash of corruption during mode change and an audio click. [How] Change sequence to blank stream before destroying HDCP session. Audio will also be muted by blanking the stream. Cc: stable@vger.kernel.org Signed-off-by: Jaehyun Chung Reviewed-by: Alvin Lee Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4bd6e03a7ef3..117d8aaf2a9b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,12 +3286,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } + dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif - dc->hwss.blank_stream(pipe_ctx); - if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- cgit v1.2.3 From fbd7cda0e61e25a5714d7b3b4dd3524271bc2245 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Sat, 8 Aug 2020 22:42:35 +0200 Subject: drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal GFP_KERNEL may and will sleep, and this is being executed in a non-preemptible context; this will mess things up since it's called inbetween DC_FP_START/END, and rescheduling will result in the DC_FP_END later being called in a different context (or just crashing if any floating point/vector registers/instructions are used after the call is resumed in a different context). Signed-off-by: Daniel Kolesa Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 991eddd10952..c31d1f30e505 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3141,7 +3141,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co int vlevel = 0; int pipe_split_from[MAX_PIPES]; int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); DC_LOGGER_INIT(dc->ctx->logger); BW_VAL_TRACE_COUNT(); -- cgit v1.2.3 From c38d444e44badc557cf29fdfdfb823604890ccfa Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Sat, 8 Aug 2020 22:44:58 +0200 Subject: drm/amd/display: add DCN support for aarch64 This adds ARM64 support into the DCN. This mainly enables support for Navi graphics cards. The dcn10 changes haven't been tested, since I don't have the relevant hardware available, but there is no way to conditionally disable them, so I've done them anyway. Signed-off-by: Daniel Kolesa Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/Kconfig | 2 +- drivers/gpu/drm/amd/display/dc/calcs/Makefile | 7 ++ drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile | 7 ++ drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 7 ++ .../gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 81 +++++++++++++--------- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 4 ++ drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 4 ++ drivers/gpu/drm/amd/display/dc/dml/Makefile | 13 ++++ drivers/gpu/drm/amd/display/dc/dsc/Makefile | 5 ++ drivers/gpu/drm/amd/display/dc/os_types.h | 4 ++ 10 files changed, 102 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 77569097a480..f24abf428534 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -6,7 +6,7 @@ config DRM_AMD_DC bool "AMD DC - Enable new display engine" default y select SND_HDA_COMPONENT if SND_HDA_CORE - select DRM_AMD_DC_DCN if (X86 || PPC64) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS) + select DRM_AMD_DC_DCN if (X86 || PPC64 || (ARM64 && KERNEL_MODE_NEON)) && !(KCOV_INSTRUMENT_ALL && KCOV_ENABLE_COMPARISONS) help Choose this option if you want to use the new display engine support for AMDGPU. This adds required support for Vega and diff --git a/drivers/gpu/drm/amd/display/dc/calcs/Makefile b/drivers/gpu/drm/amd/display/dc/calcs/Makefile index 4674aca8f206..64f515d74410 100644 --- a/drivers/gpu/drm/amd/display/dc/calcs/Makefile +++ b/drivers/gpu/drm/amd/display/dc/calcs/Makefile @@ -33,6 +33,10 @@ ifdef CONFIG_PPC64 calcs_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +calcs_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -53,6 +57,9 @@ endif CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_ccflags) CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_ccflags) CFLAGS_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_ccflags) -Wno-tautological-compare +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calcs.o := $(calcs_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_auto.o := $(calcs_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/calcs/dcn_calc_math.o := $(calcs_rcflags) BW_CALCS = dce_calcs.o bw_fixed.o custom_float.o diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile index 52b1ce775a1e..1a495759a034 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/Makefile @@ -104,6 +104,13 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := $(call cc-option,-mno-gnu-attribute) endif +# prevent build errors: +# ...: '-mgeneral-regs-only' is incompatible with the use of floating-point types +# this file is unused on arm64, just like on ppc64 +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/clk_mgr/dcn21/rn_clk_mgr.o := -mgeneral-regs-only +endif + AMD_DAL_CLK_MGR_DCN21 = $(addprefix $(AMDDALPATH)/dc/clk_mgr/dcn21/,$(CLK_MGR_DCN21)) AMD_DISPLAY_FILES += $(AMD_DAL_CLK_MGR_DCN21) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile index 62ad1a11bff9..733e6e6e43bd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn10/Makefile @@ -31,4 +31,11 @@ DCN10 = dcn10_init.o dcn10_resource.o dcn10_ipp.o dcn10_hw_sequencer.o \ AMD_DAL_DCN10 = $(addprefix $(AMDDALPATH)/dc/dcn10/,$(DCN10)) +# fix: +# ...: '-mgeneral-regs-only' is incompatible with the use of floating-point types +# aarch64 does not support soft-float, so use hard-float and handle this in code +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn10/dcn10_resource.o := -mgeneral-regs-only +endif + AMD_DISPLAY_FILES += $(AMD_DAL_DCN10) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 17d5cb422025..07571f84e0f8 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1331,6 +1331,47 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx) return value; } +/* + * Some architectures don't support soft-float (e.g. aarch64), on those + * this function has to be called with hardfloat enabled, make sure not + * to inline it so whatever fp stuff is done stays inside + */ +static noinline void dcn10_resource_construct_fp( + struct dc *dc) +{ + if (dc->ctx->dce_version == DCN_VERSION_1_01) { + struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; + struct dcn_ip_params *dcn_ip = dc->dcn_ip; + struct display_mode_lib *dml = &dc->dml; + + dml->ip.max_num_dpp = 3; + /* TODO how to handle 23.84? */ + dcn_soc->dram_clock_change_latency = 23; + dcn_ip->max_num_dpp = 3; + } + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc->urgent_latency = 3; + dc->debug.disable_dmcu = true; + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; + } + + + dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; + ASSERT(dc->dcn_soc->number_of_channels < 3); + if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ + dc->dcn_soc->number_of_channels = 2; + + if (dc->dcn_soc->number_of_channels == 1) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; + dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; + dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; + if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { + dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; + } + } +} + static bool dcn10_resource_construct( uint8_t num_virtual_links, struct dc *dc, @@ -1482,37 +1523,15 @@ static bool dcn10_resource_construct( memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults)); memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults)); - if (dc->ctx->dce_version == DCN_VERSION_1_01) { - struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc; - struct dcn_ip_params *dcn_ip = dc->dcn_ip; - struct display_mode_lib *dml = &dc->dml; - - dml->ip.max_num_dpp = 3; - /* TODO how to handle 23.84? */ - dcn_soc->dram_clock_change_latency = 23; - dcn_ip->max_num_dpp = 3; - } - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->urgent_latency = 3; - dc->debug.disable_dmcu = true; - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f; - } - - - dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width; - ASSERT(dc->dcn_soc->number_of_channels < 3); - if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/ - dc->dcn_soc->number_of_channels = 2; - - if (dc->dcn_soc->number_of_channels == 1) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f; - dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f; - dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f; - if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) { - dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f; - } - } +#if defined(CONFIG_ARM64) + /* Aarch64 does not support -msoft-float/-mfloat-abi=soft */ + DC_FP_START(); + dcn10_resource_construct_fp(dc); + DC_FP_END(); +#else + /* Other architectures we build for build this with soft-float */ + dcn10_resource_construct_fp(dc); +#endif pool->base.pp_smu = dcn10_pp_smu_create(ctx); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile index 5fcaf78334ff..624cb1341ef1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn20/Makefile @@ -17,6 +17,10 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn20/dcn20_resource.o := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile index 07684d3e375a..51a2f3d4c194 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn21/Makefile @@ -13,6 +13,10 @@ ifdef CONFIG_PPC64 CFLAGS_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dcn21/dcn21_resource.o := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 417331438c30..dbc7e2abe379 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -33,6 +33,10 @@ ifdef CONFIG_PPC64 dml_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +dml_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -60,6 +64,13 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20v2.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn21/display_mode_vba_21.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn21/display_rq_dlg_calc_21.o := $(dml_rcflags) endif ifdef CONFIG_DRM_AMD_DC_DCN3_0 CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) -Wframe-larger-than=2048 @@ -67,6 +78,8 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) endif CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_rcflags) DML = display_mode_lib.o display_rq_dlg_helpers.o dml1_display_rq_dlg_calc.o \ diff --git a/drivers/gpu/drm/amd/display/dc/dsc/Makefile b/drivers/gpu/drm/amd/display/dc/dsc/Makefile index ea29cf95d470..f2624a1156e5 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dsc/Makefile @@ -10,6 +10,10 @@ ifdef CONFIG_PPC64 dsc_ccflags := -mhard-float -maltivec endif +ifdef CONFIG_ARM64 +dsc_rcflags := -mgeneral-regs-only +endif + ifdef CONFIG_CC_IS_GCC ifeq ($(call cc-ifversion, -lt, 0701, y), y) IS_OLD_GCC = 1 @@ -28,6 +32,7 @@ endif endif CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags) +CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags) DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o diff --git a/drivers/gpu/drm/amd/display/dc/os_types.h b/drivers/gpu/drm/amd/display/dc/os_types.h index c3bbfe397e8d..330acaaed79a 100644 --- a/drivers/gpu/drm/amd/display/dc/os_types.h +++ b/drivers/gpu/drm/amd/display/dc/os_types.h @@ -55,6 +55,10 @@ #include #define DC_FP_START() kernel_fpu_begin() #define DC_FP_END() kernel_fpu_end() +#elif defined(CONFIG_ARM64) +#include +#define DC_FP_START() kernel_neon_begin() +#define DC_FP_END() kernel_neon_end() #elif defined(CONFIG_PPC64) #include #include -- cgit v1.2.3 From 200b86f9891b87ff1709e1dca4efe9d2ee06154d Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Aug 2020 11:55:32 -0400 Subject: drm/amdgpu/display: drop unused function This is not longer used as of the latest rework of this code so drop it to avoid a unused function warning. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'drivers/gpu') 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 68b88c97014b..031b7eb55356 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2827,24 +2827,6 @@ dm_atomic_get_new_state(struct drm_atomic_state *state) return NULL; } -static struct dm_atomic_state * -dm_atomic_get_old_state(struct drm_atomic_state *state) -{ - struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_display_manager *dm = &adev->dm; - struct drm_private_obj *obj; - struct drm_private_state *old_obj_state; - int i; - - for_each_old_private_obj_in_state(state, obj, old_obj_state, i) { - if (obj->funcs == dm->atomic_obj.funcs) - return to_dm_atomic_state(old_obj_state); - } - - return NULL; -} - static struct drm_private_state * dm_atomic_duplicate_state(struct drm_private_obj *obj) { -- cgit v1.2.3 From d6e6dfb287443b4197afde4632784ba640944648 Mon Sep 17 00:00:00 2001 From: Qinglang Miao Date: Mon, 10 Aug 2020 20:59:19 +0800 Subject: drm/amd/display: convert to use le16_add_cpu() Convert cpu_to_le16(le16_to_cpu(E1) + E2) to use le16_add_cpu(). Signed-off-by: Qinglang Miao Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/command_table.c | 4 +--- drivers/gpu/drm/amd/display/dc/bios/command_table2.c | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table.c b/drivers/gpu/drm/amd/display/dc/bios/command_table.c index 5815983caaf8..070459e3e407 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table.c @@ -1877,9 +1877,7 @@ static enum bp_result set_crtc_using_dtd_timing_v3( * but it is 4 either from Edid data (spec CEA 861) * or CEA timing table. */ - params.usV_SyncOffset = - cpu_to_le16(le16_to_cpu(params.usV_SyncOffset) + 1); - + le16_add_cpu(¶ms.usV_SyncOffset, 1); } } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index bed91572f82a..e8f52eb8ef0d 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -569,10 +569,7 @@ static enum bp_result set_crtc_using_dtd_timing_v3( * but it is 4 either from Edid data (spec CEA 861) * or CEA timing table. */ - params.v_syncoffset = - cpu_to_le16(le16_to_cpu(params.v_syncoffset) + - 1); - + le16_add_cpu(¶ms.v_syncoffset, 1); } } -- cgit v1.2.3 From 78484d7c747e30468b35bd5f19edf602f50162a7 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 9 Aug 2020 22:34:06 +0200 Subject: drm: amdgpu: Use the correct size when allocating memory When '*sgt' is allocated, we must allocated 'sizeof(**sgt)' bytes instead of 'sizeof(*sg)'. The sizeof(*sg) is bigger than sizeof(**sgt) so this wastes memory but it won't lead to corruption. Fixes: f44ffd677fb3 ("drm/amdgpu: add support for exporting VRAM using DMA-buf v3") Reviewed-by: Christian König Signed-off-by: Christophe JAILLET Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 134cc36e30c5..0739e259bf91 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -462,7 +462,7 @@ int amdgpu_vram_mgr_alloc_sgt(struct amdgpu_device *adev, unsigned int pages; int i, r; - *sgt = kmalloc(sizeof(*sg), GFP_KERNEL); + *sgt = kmalloc(sizeof(**sgt), GFP_KERNEL); if (!*sgt) return -ENOMEM; -- cgit v1.2.3 From d5bbb4761c9ffbe8e3a547b74ec26fb6ce31bf32 Mon Sep 17 00:00:00 2001 From: Liu ChengZhe Date: Thu, 6 Aug 2020 14:54:08 +0800 Subject: drm/amdgpu: Skip some registers config for SRIOV Some registers are not accessible to virtual function setup, so skip their initialization when in VF-SRIOV mode. v2: move SRIOV VF check into specify functions; modify commit description and comment. Signed-off-by: Liu ChengZhe Reviewed-by: Luben Tuikov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 19 +++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index fa0bca3e1f73..5d2505956f84 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -135,6 +135,12 @@ static void gfxhub_v2_1_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -190,6 +196,12 @@ static void gfxhub_v2_1_enable_system_domain(struct amdgpu_device *adev) static void gfxhub_v2_1_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); WREG32_SOC15(GC, 0, mmGCVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_HI32, @@ -326,6 +338,13 @@ void gfxhub_v2_1_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(GC, 0, mmGCVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, GCVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 757fa8e83f5b..c79fc54bc3c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -134,6 +134,12 @@ static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev) { uint32_t tmp; + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + /* Setup L2 cache */ tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL, ENABLE_L2_CACHE, 1); @@ -189,6 +195,12 @@ static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev) static void mmhub_v2_0_disable_identity_aperture(struct amdgpu_device *adev) { + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CONTEXT1_IDENTITY_APERTURE_LOW_ADDR_LO32, 0xFFFFFFFF); @@ -318,6 +330,13 @@ void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; + + /* These registers are not accessible to VF-SRIOV. + * The PF will program them instead. + */ + if (amdgpu_sriov_vf(adev)) + return; + tmp = RREG32_SOC15(MMHUB, 0, mmMMVM_L2_PROTECTION_FAULT_CNTL); tmp = REG_SET_FIELD(tmp, MMVM_L2_PROTECTION_FAULT_CNTL, RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, value); -- cgit v1.2.3 From 266d81d9eed30f4994d76a2b237c63ece062eefe Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 7 Aug 2020 15:03:40 +0800 Subject: drm/amd/powerplay: correct Vega20 cached smu feature state Correct the cached smu feature state on pp_features sysfs setting. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 38 +++++++++++----------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index 3b8839641770..e9676ebdba63 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -979,10 +979,7 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) { struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - int ret = 0; + int i, ret = 0; PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, @@ -990,17 +987,8 @@ static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) "[DisableAllSMUFeatures] Failed to disable all smu features!", return ret); - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[DisableAllSMUFeatures] Failed to get enabled smc features!", - return ret); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? - true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - } + for (i = 0; i < GNLD_FEATURES_MAX; i++) + data->smu_features[i].enabled = 0; return 0; } @@ -3230,10 +3218,11 @@ static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) { - uint64_t features_enabled; - uint64_t features_to_enable; - uint64_t features_to_disable; - int ret = 0; + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint64_t features_enabled, features_to_enable, features_to_disable; + int i, ret = 0; + bool enabled; if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) return -EINVAL; @@ -3262,6 +3251,17 @@ static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfe return ret; } + /* Update the cached feature enablement state */ + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? + true : false; + data->smu_features[i].enabled = enabled; + } + return 0; } -- cgit v1.2.3 From 2c5b8080d810d98e3e59617680218499b17c84a1 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 7 Aug 2020 17:01:47 +0800 Subject: drm/amd/powerplay: correct UVD/VCE PG state on custom pptable uploading The UVD/VCE PG state is managed by UVD and VCE IP. It's error-prone to assume the bootup state in SMU based on the dpm status. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index e9676ebdba63..ea70d736f6a8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -1640,12 +1640,6 @@ static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) data->uvd_power_gated = true; data->vce_power_gated = true; - - if (data->smu_features[GNLD_DPM_UVD].enabled) - data->uvd_power_gated = false; - - if (data->smu_features[GNLD_DPM_VCE].enabled) - data->vce_power_gated = false; } static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -- cgit v1.2.3 From 97a9b60fa3bf29d29d0fc253a98096c02fb8106e Mon Sep 17 00:00:00 2001 From: shiwu.zhang Date: Fri, 7 Aug 2020 16:43:59 +0800 Subject: drm/amdgpu: update gc golden register for arcturus Update golden setting to improve performance on HPC and ML apps Signed-off-by: shiwu.zhang Tested-by: gang.long Reviewed-by: guchun.chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index cb9d60a4e05e..b95f22262a90 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -691,6 +691,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_4_1_arct[] = SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_5_ARCT, 0x3ff, 0x135), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_CONFIG, 0xffffffff, 0x011A0000), SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_FIFO_SIZES, 0xffffffff, 0x00000f00), + SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_UTCL1_CNTL1, 0x30000000, 0x30000000) }; static const struct soc15_reg_rlcg rlcg_access_gc_9_0[] = { -- cgit v1.2.3 From a49f6727e14caff32419cc3002b9ae9cafb750d7 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 27 Jul 2020 21:21:16 -0400 Subject: drm/amd/display: Fix incorrect backlight register offset for DCN [Why] Typo in backlight refactor inctroduced wrong register offset. [How] Change DCE to DCN register map for PWRSEQ_REF_DIV Cc: stable@vger.kernel.org Signed-off-by: Aric Cyr Reviewed-by: Ashley Thomas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h index 70ec691e14d2..99c68ca9c7e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.h @@ -49,7 +49,7 @@ #define DCN_PANEL_CNTL_REG_LIST()\ DCN_PANEL_CNTL_SR(PWRSEQ_CNTL, LVTMA), \ DCN_PANEL_CNTL_SR(PWRSEQ_STATE, LVTMA), \ - DCE_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ + DCN_PANEL_CNTL_SR(PWRSEQ_REF_DIV, LVTMA), \ SR(BL_PWM_CNTL), \ SR(BL_PWM_CNTL2), \ SR(BL_PWM_PERIOD_CNTL), \ -- cgit v1.2.3 From e4ed4dbbc8383d42a197da8fe7ca6434b0f14def Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 29 Jul 2020 17:33:27 -0400 Subject: drm/amd/display: Fix LFC multiplier changing erratically [Why] 1. There is a calculation that is using frame_time_in_us instead of last_render_time_in_us to calculate whether choosing an LFC multiplier would cause the inserted frame duration to be outside of range. 2. We do not handle unsigned integer subtraction correctly and it underflows to a really large value, which causes some logic errors. [How] 1. Fix logic to calculate 'within range' using last_render_time_in_us 2. Split out delta_from_mid_point_delta_in_us calculation to ensure we don't underflow and wrap around Signed-off-by: Anthony Koo Reviewed-by: Aric Cyr Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../drm/amd/display/modules/freesync/freesync.c | 36 +++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index 81820f3d6b3b..d988533d4af5 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -324,22 +324,44 @@ static void apply_below_the_range(struct core_freesync *core_freesync, /* Choose number of frames to insert based on how close it * can get to the mid point of the variable range. + * - Delta for CEIL: delta_from_mid_point_in_us_1 + * - Delta for FLOOR: delta_from_mid_point_in_us_2 */ - if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us && - (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 || - mid_point_frames_floor < 2)) { + if ((last_render_time_in_us / mid_point_frames_ceil) < in_out_vrr->min_duration_in_us) { + /* Check for out of range. + * If using CEIL produces a value that is out of range, + * then we are forced to use FLOOR. + */ + frames_to_insert = mid_point_frames_floor; + } else if (mid_point_frames_floor < 2) { + /* Check if FLOOR would result in non-LFC. In this case + * choose to use CEIL + */ + frames_to_insert = mid_point_frames_ceil; + } else if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + /* If choosing CEIL results in a frame duration that is + * closer to the mid point of the range. + * Choose CEIL + */ frames_to_insert = mid_point_frames_ceil; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - - delta_from_mid_point_in_us_1; } else { + /* If choosing FLOOR results in a frame duration that is + * closer to the mid point of the range. + * Choose FLOOR + */ frames_to_insert = mid_point_frames_floor; - delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - - delta_from_mid_point_in_us_2; } /* Prefer current frame multiplier when BTR is enabled unless it drifts * too far from the midpoint */ + if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 - + delta_from_mid_point_in_us_1; + } else { + delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_1 - + delta_from_mid_point_in_us_2; + } if (in_out_vrr->btr.frames_to_insert != 0 && delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) { if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) < -- cgit v1.2.3 From abba907c7a20032c2d504fd5afe3af7d440a09d0 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Wed, 29 Jul 2020 17:43:10 -0400 Subject: drm/amd/display: Switch to immediate mode for updating infopackets [Why] Using FRAME_UPDATE will result in infopacket to be potentially updated one frame late. In commit stream scenarios for previously active stream, some stale infopacket data from previous config might be erroneously sent out on initial frame after stream is re-enabled. [How] Switch to using IMMEDIATE_UPDATE mode Signed-off-by: Anthony Koo Reviewed-by: Ashley Thomas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c | 16 ++++++++-------- .../gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c index 07b2f9399671..842abb4c475b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c @@ -121,35 +121,35 @@ void enc1_update_generic_info_packet( switch (packet_index) { case 0: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC0_FRAME_UPDATE, 1); + AFMT_GENERIC0_IMMEDIATE_UPDATE, 1); break; case 1: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC1_FRAME_UPDATE, 1); + AFMT_GENERIC1_IMMEDIATE_UPDATE, 1); break; case 2: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC2_FRAME_UPDATE, 1); + AFMT_GENERIC2_IMMEDIATE_UPDATE, 1); break; case 3: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC3_FRAME_UPDATE, 1); + AFMT_GENERIC3_IMMEDIATE_UPDATE, 1); break; case 4: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC4_FRAME_UPDATE, 1); + AFMT_GENERIC4_IMMEDIATE_UPDATE, 1); break; case 5: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC5_FRAME_UPDATE, 1); + AFMT_GENERIC5_IMMEDIATE_UPDATE, 1); break; case 6: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC6_FRAME_UPDATE, 1); + AFMT_GENERIC6_IMMEDIATE_UPDATE, 1); break; case 7: REG_UPDATE(AFMT_VBI_PACKET_CONTROL1, - AFMT_GENERIC7_FRAME_UPDATE, 1); + AFMT_GENERIC7_IMMEDIATE_UPDATE, 1); break; default: break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h index ed385b1477be..30eae7459d50 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.h @@ -281,7 +281,14 @@ struct dcn10_stream_enc_registers { SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_FRAME_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC0_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC1_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC2_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC3_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC4_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_IMMEDIATE_UPDATE, mask_sh),\ + SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_IMMEDIATE_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC5_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC6_FRAME_UPDATE, mask_sh),\ SE_SF(DIG0_AFMT_VBI_PACKET_CONTROL1, AFMT_GENERIC7_FRAME_UPDATE, mask_sh),\ @@ -345,7 +352,14 @@ struct dcn10_stream_enc_registers { type AFMT_GENERIC2_FRAME_UPDATE;\ type AFMT_GENERIC3_FRAME_UPDATE;\ type AFMT_GENERIC4_FRAME_UPDATE;\ + type AFMT_GENERIC0_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC1_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC2_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC3_IMMEDIATE_UPDATE;\ type AFMT_GENERIC4_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC5_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC6_IMMEDIATE_UPDATE;\ + type AFMT_GENERIC7_IMMEDIATE_UPDATE;\ type AFMT_GENERIC5_FRAME_UPDATE;\ type AFMT_GENERIC6_FRAME_UPDATE;\ type AFMT_GENERIC7_FRAME_UPDATE;\ -- cgit v1.2.3 From b24bdc37d03a0478189e20a50286092840f414fa Mon Sep 17 00:00:00 2001 From: Stylon Wang Date: Tue, 28 Jul 2020 15:10:35 +0800 Subject: drm/amd/display: Fix EDID parsing after resume from suspend [Why] Resuming from suspend, CEA blocks from EDID are not parsed and no video modes can support YUV420. When this happens, output bpc cannot go over 8-bit with 4K modes on HDMI. [How] In amdgpu_dm_update_connector_after_detect(), drm_add_edid_modes() is called after drm_connector_update_edid_property() to fully parse EDID and update display info. Cc: stable@vger.kernel.org Signed-off-by: Stylon Wang Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') 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 e6833a2d01f8..39444619d9b5 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2196,6 +2196,7 @@ void amdgpu_dm_update_connector_after_detect( drm_connector_update_edid_property(connector, aconnector->edid); + drm_add_edid_modes(connector, aconnector->edid); if (aconnector->dc_link->aux_mode) drm_dp_cec_set_edid(&aconnector->dm_dp_aux.aux, -- cgit v1.2.3 From 79940e4d10df9c737a394630968471c632246ee0 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Thu, 30 Jul 2020 16:31:29 -0400 Subject: drm/amd/display: Blank stream before destroying HDCP session [Why] Stream disable sequence incorretly destroys HDCP session while stream is not blanked and while audio is not muted. This sequence causes a flash of corruption during mode change and an audio click. [How] Change sequence to blank stream before destroying HDCP session. Audio will also be muted by blanking the stream. Cc: stable@vger.kernel.org Signed-off-by: Jaehyun Chung Reviewed-by: Alvin Lee Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 4bd6e03a7ef3..117d8aaf2a9b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,12 +3286,11 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } + dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif - dc->hwss.blank_stream(pipe_ctx); - if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- cgit v1.2.3 From f41ed88cbd6f025f7a683a11a74f901555fba11c Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Sat, 8 Aug 2020 22:42:35 +0200 Subject: drm/amdgpu/display: use GFP_ATOMIC in dcn20_validate_bandwidth_internal GFP_KERNEL may and will sleep, and this is being executed in a non-preemptible context; this will mess things up since it's called inbetween DC_FP_START/END, and rescheduling will result in the DC_FP_END later being called in a different context (or just crashing if any floating point/vector registers/instructions are used after the call is resumed in a different context). Signed-off-by: Daniel Kolesa Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 790baf552695..9140b3fc767a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3141,7 +3141,7 @@ static bool dcn20_validate_bandwidth_internal(struct dc *dc, struct dc_state *co int vlevel = 0; int pipe_split_from[MAX_PIPES]; int pipe_cnt = 0; - display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_KERNEL); + display_e2e_pipe_params_st *pipes = kzalloc(dc->res_pool->pipe_count * sizeof(display_e2e_pipe_params_st), GFP_ATOMIC); DC_LOGGER_INIT(dc->ctx->logger); BW_VAL_TRACE_COUNT(); -- cgit v1.2.3 From 0cf0ee983b14af5e2160fa677b2eeb4c5dbb03ad Mon Sep 17 00:00:00 2001 From: Arunpravin Date: Thu, 6 Aug 2020 14:34:33 +0530 Subject: drm/amdgpu: Enable P2P dmabuf over XGMI Access the exported P2P dmabuf over XGMI, if available. Otherwise, fall back to the existing PCIe method. Reviewed-by: Christian König Signed-off-by: Arunpravin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 34 +++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h | 2 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 19 +++++++++++++--- 3 files changed, 52 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 43d8ed7dbd00..b3a62d5ba4e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -35,6 +35,7 @@ #include "amdgpu_display.h" #include "amdgpu_gem.h" #include "amdgpu_dma_buf.h" +#include "amdgpu_xgmi.h" #include #include #include @@ -595,3 +596,36 @@ struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, obj->import_attach = attach; return obj; } + +/** + * amdgpu_dmabuf_is_xgmi_accessible - Check if xgmi available for P2P transfer + * + * @adev: amdgpu_device pointer of the importer + * @bo: amdgpu buffer object + * + * Returns: + * True if dmabuf accessible over xgmi, false otherwise. + */ +bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct amdgpu_bo *bo) +{ + struct drm_gem_object *obj = &bo->tbo.base; + struct drm_gem_object *gobj; + + if (obj->import_attach) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + + if (dma_buf->ops != &amdgpu_dmabuf_ops) + /* No XGMI with non AMD GPUs */ + return false; + + gobj = dma_buf->priv; + bo = gem_to_amdgpu_bo(gobj); + } + + if (amdgpu_xgmi_same_hive(adev, amdgpu_ttm_adev(bo->tbo.bdev)) && + (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)) + return true; + + return false; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index ec447a7b6b28..2c5c84a06bb9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -29,6 +29,8 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, int flags); struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); +bool amdgpu_dmabuf_is_xgmi_accessible(struct amdgpu_device *adev, + struct amdgpu_bo *bo); void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 71e005cf2952..771c27478bb1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "amdgpu.h" @@ -35,6 +36,7 @@ #include "amdgpu_amdkfd.h" #include "amdgpu_gmc.h" #include "amdgpu_xgmi.h" +#include "amdgpu_dma_buf.h" /** * DOC: GPUVM @@ -1778,15 +1780,24 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, nodes = NULL; resv = vm->root.base.bo->tbo.base.resv; } else { + struct drm_gem_object *obj = &bo->tbo.base; struct ttm_dma_tt *ttm; + resv = bo->tbo.base.resv; + if (obj->import_attach && bo_va->is_xgmi) { + struct dma_buf *dma_buf = obj->import_attach->dmabuf; + struct drm_gem_object *gobj = dma_buf->priv; + struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj); + + if (abo->tbo.mem.mem_type == TTM_PL_VRAM) + bo = gem_to_amdgpu_bo(gobj); + } mem = &bo->tbo.mem; nodes = mem->mm_node; if (mem->mem_type == TTM_PL_TT) { ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); pages_addr = ttm->dma_address; } - resv = bo->tbo.base.resv; } if (bo) { @@ -2132,8 +2143,10 @@ struct amdgpu_bo_va *amdgpu_vm_bo_add(struct amdgpu_device *adev, INIT_LIST_HEAD(&bo_va->valids); INIT_LIST_HEAD(&bo_va->invalids); - if (bo && amdgpu_xgmi_same_hive(adev, amdgpu_ttm_adev(bo->tbo.bdev)) && - (bo->preferred_domains & AMDGPU_GEM_DOMAIN_VRAM)) { + if (!bo) + return bo_va; + + if (amdgpu_dmabuf_is_xgmi_accessible(adev, bo)) { bo_va->is_xgmi = true; /* Power up XGMI if it can be potentially used */ amdgpu_xgmi_set_pstate(adev, AMDGPU_XGMI_PSTATE_MAX_VEGA20); -- cgit v1.2.3 From f75e94d86829e92a758a26fc5bbdb4c9eba86260 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Tue, 4 Aug 2020 15:00:53 +0800 Subject: drm/amdgpu: bypass querying ras error count registers Once ras recovery is issued by ras sync flood interrupt or ras controller interrupt, add this guard to bypass or execute ras error count register harvest of all IPs. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Reviewed-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 22 ++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 3 +++ drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c | 48 ++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 1a55f6f492fd..fbe464c68e5b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1547,17 +1547,19 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) struct list_head device_list, *device_list_handle = NULL; struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, false); - /* Build list of devices to query RAS related errors */ - if (hive && adev->gmc.xgmi.num_physical_nodes > 1) - device_list_handle = &hive->device_list; - else { - INIT_LIST_HEAD(&device_list); - list_add_tail(&adev->gmc.xgmi.head, &device_list); - device_list_handle = &device_list; - } + if (!ras->disable_ras_err_cnt_harvest) { + /* Build list of devices to query RAS related errors */ + if (hive && adev->gmc.xgmi.num_physical_nodes > 1) { + device_list_handle = &hive->device_list; + } else { + INIT_LIST_HEAD(&device_list); + list_add_tail(&adev->gmc.xgmi.head, &device_list); + device_list_handle = &device_list; + } - list_for_each_entry(remote_adev, device_list_handle, gmc.xgmi.head) { - amdgpu_ras_log_on_err_counter(remote_adev); + list_for_each_entry(remote_adev, + device_list_handle, gmc.xgmi.head) + amdgpu_ras_log_on_err_counter(remote_adev); } if (amdgpu_device_should_recover_gpu(ras->adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 70a6fca73617..6b8d7bb83bb3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -343,6 +343,9 @@ struct amdgpu_ras { /* bad page count threshold */ uint32_t bad_page_cnt_threshold; + + /* disable ras error count harvest in recovery */ + bool disable_ras_err_cnt_harvest; }; struct ras_fs_data { diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c index e629156173d3..eadc9526d33f 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_4.c @@ -302,6 +302,7 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device uint32_t bif_doorbell_intr_cntl; struct ras_manager *obj = amdgpu_ras_find_obj(adev, adev->nbio.ras_if); struct ras_err_data err_data = {0, 0, 0, NULL}; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); bif_doorbell_intr_cntl = RREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL); if (REG_GET_FIELD(bif_doorbell_intr_cntl, @@ -312,28 +313,31 @@ static void nbio_v7_4_handle_ras_controller_intr_no_bifring(struct amdgpu_device RAS_CNTLR_INTERRUPT_CLEAR, 1); WREG32_SOC15(NBIO, 0, mmBIF_DOORBELL_INT_CNTL, bif_doorbell_intr_cntl); - /* - * clear error status after ras_controller_intr according to - * hw team and count ue number for query - */ - nbio_v7_4_query_ras_error_count(adev, &err_data); - - /* logging on error counter and printing for awareness */ - obj->err_data.ue_count += err_data.ue_count; - obj->err_data.ce_count += err_data.ce_count; - - if (err_data.ce_count) - dev_info(adev->dev, "%ld correctable hardware " - "errors detected in %s block, " - "no user action is needed.\n", - obj->err_data.ce_count, - adev->nbio.ras_if->name); - - if (err_data.ue_count) - dev_info(adev->dev, "%ld uncorrectable hardware " - "errors detected in %s block\n", - obj->err_data.ue_count, - adev->nbio.ras_if->name); + if (!ras->disable_ras_err_cnt_harvest) { + /* + * clear error status after ras_controller_intr + * according to hw team and count ue number + * for query + */ + nbio_v7_4_query_ras_error_count(adev, &err_data); + + /* logging on error cnt and printing for awareness */ + obj->err_data.ue_count += err_data.ue_count; + obj->err_data.ce_count += err_data.ce_count; + + if (err_data.ce_count) + dev_info(adev->dev, "%ld correctable hardware " + "errors detected in %s block, " + "no user action is needed.\n", + obj->err_data.ce_count, + adev->nbio.ras_if->name); + + if (err_data.ue_count) + dev_info(adev->dev, "%ld uncorrectable hardware " + "errors detected in %s block\n", + obj->err_data.ue_count, + adev->nbio.ras_if->name); + } dev_info(adev->dev, "RAS controller interrupt triggered " "by NBIF error\n"); -- cgit v1.2.3 From 66459e1db2f8b6f7cdfe0d091345b56d12348d0d Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Tue, 4 Aug 2020 15:05:01 +0800 Subject: drm/amdgpu: add debugfs node to toggle ras error cnt harvest Before ras recovery is issued, user could operate this debugfs node to enable/disable the harvest of all RAS IPs' ras error count registers, which will help keep hardware's registers' status instead of cleaning up them. Signed-off-by: Guchun Chen Reviewed-by: Hawking Zhang Reviewed-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fbe464c68e5b..2d1fad1abf7a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1215,6 +1215,13 @@ static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) */ debugfs_create_bool("auto_reboot", S_IWUGO | S_IRUGO, con->dir, &con->reboot); + + /* + * User could set this not to clean up hardware's error count register + * of RAS IPs during ras recovery. + */ + debugfs_create_bool("disable_ras_err_cnt_harvest", 0644, + con->dir, &con->disable_ras_err_cnt_harvest); } void amdgpu_ras_debugfs_create(struct amdgpu_device *adev, -- cgit v1.2.3 From d58fe3cf11a86e59183c8b91c50ae2cde24a2128 Mon Sep 17 00:00:00 2001 From: Tianci.Yin Date: Fri, 19 Jun 2020 16:01:11 +0800 Subject: drm/amdgpu: add interface amdgpu_gfx_init_spm_golden for Navi1x On Navi1x, the SPM golden settings are lost after GFXOFF enter/exit, so reconfiguration is needed. Make the configuration code as an interface for future use. Reviewed-by: Hawking Zhang Reviewed-by: Luben Tuikov Reviewed-by: Feifei Xu Signed-off-by: Tianci.Yin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 2 ++ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 34 ++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index 1e7a2b0997c5..a611e78dd4ba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -216,6 +216,7 @@ struct amdgpu_gfx_funcs { int (*ras_error_inject)(struct amdgpu_device *adev, void *inject_if); int (*query_ras_error_count) (struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count) (struct amdgpu_device *adev); + void (*init_spm_golden)(struct amdgpu_device *adev); }; struct sq_work { @@ -324,6 +325,7 @@ struct amdgpu_gfx { #define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev)) #define amdgpu_gfx_select_se_sh(adev, se, sh, instance) (adev)->gfx.funcs->select_se_sh((adev), (se), (sh), (instance)) #define amdgpu_gfx_select_me_pipe_q(adev, me, pipe, q, vmid) (adev)->gfx.funcs->select_me_pipe_q((adev), (me), (pipe), (q), (vmid)) +#define amdgpu_gfx_init_spm_golden(adev) (adev)->gfx.funcs->init_spm_golden((adev)) /** * amdgpu_gfx_create_bitmask - create a bitmask diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 0702c94fcca3..d851fe80eaf4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3307,6 +3307,29 @@ static void gfx_v10_0_set_kiq_pm4_funcs(struct amdgpu_device *adev) adev->gfx.kiq.pmf = &gfx_v10_0_kiq_pm4_funcs; } +static void gfx_v10_0_init_spm_golden_registers(struct amdgpu_device *adev) +{ + switch (adev->asic_type) { + case CHIP_NAVI10: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_0_nv10, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_0_nv10)); + break; + case CHIP_NAVI14: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_1_nv14, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_nv14)); + break; + case CHIP_NAVI12: + soc15_program_register_sequence(adev, + golden_settings_gc_rlc_spm_10_1_2_nv12, + (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_2_nv12)); + break; + default: + break; + } +} + static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) { switch (adev->asic_type) { @@ -3317,9 +3340,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_0_nv10, (const u32)ARRAY_SIZE(golden_settings_gc_10_0_nv10)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_0_nv10, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_0_nv10)); break; case CHIP_NAVI14: soc15_program_register_sequence(adev, @@ -3328,9 +3348,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_1_nv14, (const u32)ARRAY_SIZE(golden_settings_gc_10_1_nv14)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_1_nv14, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_nv14)); break; case CHIP_NAVI12: soc15_program_register_sequence(adev, @@ -3339,9 +3356,6 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) soc15_program_register_sequence(adev, golden_settings_gc_10_1_2_nv12, (const u32)ARRAY_SIZE(golden_settings_gc_10_1_2_nv12)); - soc15_program_register_sequence(adev, - golden_settings_gc_rlc_spm_10_1_2_nv12, - (const u32)ARRAY_SIZE(golden_settings_gc_rlc_spm_10_1_2_nv12)); break; case CHIP_SIENNA_CICHLID: soc15_program_register_sequence(adev, @@ -3360,6 +3374,7 @@ static void gfx_v10_0_init_golden_registers(struct amdgpu_device *adev) default: break; } + gfx_v10_0_init_spm_golden_registers(adev); } static void gfx_v10_0_scratch_init(struct amdgpu_device *adev) @@ -4149,6 +4164,7 @@ static const struct amdgpu_gfx_funcs gfx_v10_0_gfx_funcs = { .read_wave_sgprs = &gfx_v10_0_read_wave_sgprs, .read_wave_vgprs = &gfx_v10_0_read_wave_vgprs, .select_me_pipe_q = &gfx_v10_0_select_me_pipe_q, + .init_spm_golden = &gfx_v10_0_init_spm_golden_registers, }; static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev) -- cgit v1.2.3 From 425a78f43b34a6bebc5c2746eb09a3b45a45a286 Mon Sep 17 00:00:00 2001 From: Tianci.Yin Date: Mon, 20 Jul 2020 15:47:37 +0800 Subject: drm/amdgpu: reconfigure spm golden settings on Navi1x after GFXOFF exit(v3) On Navi1x, the SPM golden settings are lost after GFXOFF enter/exit, so reconfigure the golden settings after GFXOFF exit. Reviewed-by: Hawking Zhang Signed-off-by: Tianci.Yin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 0cd9de69932b..8ccd17d02cc6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -560,8 +560,14 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable) if (enable && !adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) { schedule_delayed_work(&adev->gfx.gfx_off_delay_work, GFX_OFF_DELAY_ENABLE); } else if (!enable && adev->gfx.gfx_off_state) { - if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) + if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) { adev->gfx.gfx_off_state = false; + + if (adev->gfx.funcs->init_spm_golden) { + dev_dbg(adev->dev, "GFXOFF is disabled, re-init SPM golden settings\n"); + amdgpu_gfx_init_spm_golden(adev); + } + } } mutex_unlock(&adev->gfx.gfx_off_mutex); -- cgit v1.2.3 From a189d0ae0cd68643204cbe9b11e824414b2b06c9 Mon Sep 17 00:00:00 2001 From: Wenhui Sheng Date: Thu, 23 Jul 2020 10:57:06 +0800 Subject: drm/amdgpu: add RAP TA header file The RAP TA contains tests used to verify if RAP(Register Access Policy), or otherwise known as Security Policy is applied correctly by PSP BL&TOS. The RAP test is a measure to ensure that we reduce the avenue of complexity and mistakes when dealing with RAP in post-si execution, where debugging failures related to RAP is quite difficult and expensive. v2: add introduction for RAP TA Signed-off-by: Wenhui Sheng Reviewed-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/ta_rap_if.h | 84 ++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 drivers/gpu/drm/amd/amdgpu/ta_rap_if.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h b/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h new file mode 100644 index 000000000000..f14833fae07c --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/ta_rap_if.h @@ -0,0 +1,84 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _TA_RAP_IF_H +#define _TA_RAP_IF_H + +/* Responses have bit 31 set */ +#define RSP_ID_MASK (1U << 31) +#define RSP_ID(cmdId) (((uint32_t)(cmdId)) | RSP_ID_MASK) + +enum ta_rap_status { + TA_RAP_STATUS__SUCCESS = 1, + TA_RAP_STATUS__ERROR_GENERIC_FAILURE = 2, + TA_RAP_STATUS__ERROR_CMD_NOT_SUPPORTED = 3, + TA_RAP_STATUS__ERROR_INVALID_VALIDATION_METHOD = 4, + TA_RAP_STATUS__ERROR_NULL_POINTER = 5, + TA_RAP_STATUS__ERROR_NOT_INITIALIZED = 6, + TA_RAP_STATUS__ERROR_VALIDATION_FAILED = 7, + TA_RAP_STATUS__ERROR_ASIC_NOT_SUPPORTED = 8, + TA_RAP_STATUS__ERROR_OPERATION_NOT_PERMISSABLE = 9, + TA_RAP_STATUS__ERROR_ALREADY_INIT = 10, +}; + +enum ta_rap_cmd { + TA_CMD_RAP__INITIALIZE = 1, + TA_CMD_RAP__VALIDATE_L0 = 2, +}; + +enum ta_rap_validation_method { + METHOD_A = 1, +}; + +struct ta_rap_cmd_input_data { + uint8_t reserved[8]; +}; + +struct ta_rap_cmd_output_data { + uint32_t last_subsection; + uint32_t num_total_validate; + uint32_t num_valid; + uint32_t last_validate_addr; + uint32_t last_validate_val; + uint32_t last_validate_val_exptd; +}; + +union ta_rap_cmd_input { + struct ta_rap_cmd_input_data input; +}; + +union ta_rap_cmd_output { + struct ta_rap_cmd_output_data output; +}; + +struct ta_rap_shared_memory { + uint32_t cmd_id; + uint32_t validation_method_id; + uint32_t resp_id; + enum ta_rap_status rap_status; + union ta_rap_cmd_input rap_in_message; + union ta_rap_cmd_output rap_out_message; + uint8_t reserved[64]; +}; + +#endif // #define _TA_RAP_IF_H -- cgit v1.2.3 From 8602692b6f73d2ea0312cccea5416b270d0f7247 Mon Sep 17 00:00:00 2001 From: Wenhui Sheng Date: Fri, 17 Jul 2020 16:55:20 +0800 Subject: drm/amdgpu: enable RAP TA load Enable the RAP TA loading path and add RAP test trigger interface. v2: fix potential mem leak issue Signed-off-by: Wenhui Sheng Reviewed-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 183 ++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h | 17 +++ drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h | 1 + 3 files changed, 201 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c68369731b20..116a89990f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1430,6 +1430,168 @@ static int psp_dtm_terminate(struct psp_context *psp) } // DTM end +// RAP start +static int psp_rap_init_shared_buf(struct psp_context *psp) +{ + int ret; + + /* + * Allocate 16k memory aligned to 4k from Frame Buffer (local + * physical) for rap ta <-> Driver + */ + ret = amdgpu_bo_create_kernel(psp->adev, PSP_RAP_SHARED_MEM_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, + &psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + return ret; +} + +static int psp_rap_load(struct psp_context *psp) +{ + int ret; + struct psp_gfx_cmd_resp *cmd; + + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + memset(psp->fw_pri_buf, 0, PSP_1_MEG); + memcpy(psp->fw_pri_buf, psp->ta_rap_start_addr, psp->ta_rap_ucode_size); + + psp_prep_ta_load_cmd_buf(cmd, + psp->fw_pri_mc_addr, + psp->ta_rap_ucode_size, + psp->rap_context.rap_shared_mc_addr, + PSP_RAP_SHARED_MEM_SIZE); + + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + + if (!ret) { + psp->rap_context.rap_initialized = true; + psp->rap_context.session_id = cmd->resp.session_id; + mutex_init(&psp->rap_context.mutex); + } + + kfree(cmd); + + return ret; +} + +static int psp_rap_unload(struct psp_context *psp) +{ + int ret; + struct psp_gfx_cmd_resp *cmd; + + cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + psp_prep_ta_unload_cmd_buf(cmd, psp->rap_context.session_id); + + ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr); + + kfree(cmd); + + return ret; +} + +static int psp_rap_initialize(struct psp_context *psp) +{ + int ret; + + /* + * TODO: bypass the initialize in sriov for now + */ + if (amdgpu_sriov_vf(psp->adev)) + return 0; + + if (!psp->adev->psp.ta_rap_ucode_size || + !psp->adev->psp.ta_rap_start_addr) { + dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n"); + return 0; + } + + if (!psp->rap_context.rap_initialized) { + ret = psp_rap_init_shared_buf(psp); + if (ret) + return ret; + } + + ret = psp_rap_load(psp); + if (ret) + return ret; + + ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE); + if (ret != TA_RAP_STATUS__SUCCESS) { + psp_rap_unload(psp); + + amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + psp->rap_context.rap_initialized = false; + + dev_warn(psp->adev->dev, "RAP TA initialize fail.\n"); + return -EINVAL; + } + + return 0; +} + +static int psp_rap_terminate(struct psp_context *psp) +{ + int ret; + + if (!psp->rap_context.rap_initialized) + return 0; + + ret = psp_rap_unload(psp); + + psp->rap_context.rap_initialized = false; + + /* free rap shared memory */ + amdgpu_bo_free_kernel(&psp->rap_context.rap_shared_bo, + &psp->rap_context.rap_shared_mc_addr, + &psp->rap_context.rap_shared_buf); + + return ret; +} + +int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id) +{ + struct ta_rap_shared_memory *rap_cmd; + int ret; + + if (!psp->rap_context.rap_initialized) + return -EINVAL; + + if (ta_cmd_id != TA_CMD_RAP__INITIALIZE && + ta_cmd_id != TA_CMD_RAP__VALIDATE_L0) + return -EINVAL; + + mutex_lock(&psp->rap_context.mutex); + + rap_cmd = (struct ta_rap_shared_memory *) + psp->rap_context.rap_shared_buf; + memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory)); + + rap_cmd->cmd_id = ta_cmd_id; + rap_cmd->validation_method_id = METHOD_A; + + ret = psp_ta_invoke(psp, rap_cmd->cmd_id, psp->rap_context.session_id); + if (ret) { + mutex_unlock(&psp->rap_context.mutex); + return ret; + } + + mutex_unlock(&psp->rap_context.mutex); + + return rap_cmd->rap_status; +} +// RAP end + static int psp_hw_start(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; @@ -1892,6 +2054,11 @@ skip_memalloc: if (ret) dev_err(psp->adev->dev, "DTM: Failed to initialize DTM\n"); + + ret = psp_rap_initialize(psp); + if (ret) + dev_err(psp->adev->dev, + "RAP: Failed to initialize RAP\n"); } return 0; @@ -1942,6 +2109,7 @@ static int psp_hw_fini(void *handle) if (psp->adev->psp.ta_fw) { psp_ras_terminate(psp); + psp_rap_terminate(psp); psp_dtm_terminate(psp); psp_hdcp_terminate(psp); } @@ -2000,6 +2168,11 @@ static int psp_suspend(void *handle) DRM_ERROR("Failed to terminate dtm ta\n"); return ret; } + ret = psp_rap_terminate(psp); + if (ret) { + DRM_ERROR("Failed to terminate rap ta\n"); + return ret; + } } ret = psp_asd_unload(psp); @@ -2078,6 +2251,11 @@ static int psp_resume(void *handle) if (ret) dev_err(psp->adev->dev, "DTM: Failed to initialize DTM\n"); + + ret = psp_rap_initialize(psp); + if (ret) + dev_err(psp->adev->dev, + "RAP: Failed to initialize RAP\n"); } mutex_unlock(&adev->firmware.mutex); @@ -2343,6 +2521,11 @@ int parse_ta_bin_descriptor(struct psp_context *psp, psp->ta_dtm_ucode_size = le32_to_cpu(desc->size_bytes); psp->ta_dtm_start_addr = ucode_start_addr; break; + case TA_FW_TYPE_PSP_RAP: + psp->ta_rap_ucode_version = le32_to_cpu(desc->fw_version); + psp->ta_rap_ucode_size = le32_to_cpu(desc->size_bytes); + psp->ta_rap_start_addr = ucode_start_addr; + break; default: dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type); break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h index 623888bf30cb..919d2fb7427b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h @@ -29,6 +29,7 @@ #include "psp_gfx_if.h" #include "ta_xgmi_if.h" #include "ta_ras_if.h" +#include "ta_rap_if.h" #define PSP_FENCE_BUFFER_SIZE 0x1000 #define PSP_CMD_BUFFER_SIZE 0x1000 @@ -38,6 +39,7 @@ #define PSP_TMR_SIZE 0x400000 #define PSP_HDCP_SHARED_MEM_SIZE 0x4000 #define PSP_DTM_SHARED_MEM_SIZE 0x4000 +#define PSP_RAP_SHARED_MEM_SIZE 0x4000 #define PSP_SHARED_MEM_SIZE 0x4000 struct psp_context; @@ -159,6 +161,15 @@ struct psp_dtm_context { struct mutex mutex; }; +struct psp_rap_context { + bool rap_initialized; + uint32_t session_id; + struct amdgpu_bo *rap_shared_bo; + uint64_t rap_shared_mc_addr; + void *rap_shared_buf; + struct mutex mutex; +}; + #define MEM_TRAIN_SYSTEM_SIGNATURE 0x54534942 #define GDDR6_MEM_TRAINING_DATA_SIZE_IN_BYTES 0x1000 #define GDDR6_MEM_TRAINING_OFFSET 0x8000 @@ -277,11 +288,16 @@ struct psp_context uint32_t ta_dtm_ucode_size; uint8_t *ta_dtm_start_addr; + uint32_t ta_rap_ucode_version; + uint32_t ta_rap_ucode_size; + uint8_t *ta_rap_start_addr; + struct psp_asd_context asd_context; struct psp_xgmi_context xgmi_context; struct psp_ras_context ras; struct psp_hdcp_context hdcp_context; struct psp_dtm_context dtm_context; + struct psp_rap_context rap_context; struct mutex mutex; struct psp_memory_training_context mem_train_ctx; }; @@ -357,6 +373,7 @@ int psp_ras_trigger_error(struct psp_context *psp, int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id); +int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id); int psp_rlc_autoload_start(struct psp_context *psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h index 12a8bc8fca0b..3c23c6293ff9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h @@ -131,6 +131,7 @@ enum ta_fw_type { TA_FW_TYPE_PSP_RAS, TA_FW_TYPE_PSP_HDCP, TA_FW_TYPE_PSP_DTM, + TA_FW_TYPE_PSP_RAP, }; struct ta_fw_bin_desc { -- cgit v1.2.3 From a4322e1881bed80ddb904482f0b2e948fa7fd47e Mon Sep 17 00:00:00 2001 From: Wenhui Sheng Date: Tue, 11 Aug 2020 11:02:03 +0800 Subject: drm/amdgpu: add debugfs interface for RAP test After amdgpu driver loading successfully, we can use RAP debugfs interface /dri/xxx/rap_test to trigger RAP test. Currently only L0 validate test is supported. v2: refine amdgpu_rap.h Signed-off-by: Wenhui Sheng Reviewed-by: Guchun Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c | 127 ++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h | 30 +++++++ 4 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 0ba396e9d7e4..dec1927ca75d 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -55,7 +55,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_vf_error.o amdgpu_sched.o amdgpu_debugfs.o amdgpu_ids.o \ amdgpu_gmc.o amdgpu_mmhub.o amdgpu_xgmi.o amdgpu_csa.o amdgpu_ras.o amdgpu_vm_cpu.o \ amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.o \ - amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o + amdgpu_umc.o smu_v11_0_i2c.o amdgpu_fru_eeprom.o amdgpu_rap.o amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 3a4b31b1c4f2..0af249a1e35b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -34,6 +34,7 @@ #include "amdgpu_pm.h" #include "amdgpu_dm_debugfs.h" #include "amdgpu_ras.h" +#include "amdgpu_rap.h" /** * amdgpu_debugfs_add_files - Add simple debugfs entries @@ -1623,6 +1624,8 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) amdgpu_debugfs_autodump_init(adev); + amdgpu_rap_debugfs_init(adev); + return amdgpu_debugfs_add_files(adev, amdgpu_debugfs_list, ARRAY_SIZE(amdgpu_debugfs_list)); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c new file mode 100644 index 000000000000..87cbc9011b2d --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c @@ -0,0 +1,127 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + */ +#include +#include + +#include "amdgpu.h" +#include "amdgpu_rap.h" + +/** + * DOC: AMDGPU RAP debugfs test interface + * + * how to use? + * echo opcode > /dri/xxx/rap_test + * + * opcode: + * currently, only 2 is supported by Linux host driver, + * opcode 2 stands for TA_CMD_RAP__VALIDATE_L0, used to + * trigger L0 policy validation, you can refer more detail + * from header file ta_rap_if.h + * + */ +static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; + struct ta_rap_shared_memory *rap_shared_mem; + struct ta_rap_cmd_output_data *rap_cmd_output; + struct drm_device *dev = adev->ddev; + uint32_t op; + int ret; + + if (*pos || size != 2) + return -EINVAL; + + ret = kstrtouint_from_user(buf, size, *pos, &op); + if (ret) + return ret; + + ret = pm_runtime_get_sync(dev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(dev->dev); + return ret; + } + + /* make sure gfx core is on, RAP TA cann't handle + * GFX OFF case currently. + */ + amdgpu_gfx_off_ctrl(adev, false); + + switch (op) { + case 2: + ret = psp_rap_invoke(&adev->psp, op); + + if (ret == TA_RAP_STATUS__SUCCESS) { + dev_info(adev->dev, "RAP L0 validate test success.\n"); + } else { + rap_shared_mem = (struct ta_rap_shared_memory *) + adev->psp.rap_context.rap_shared_buf; + rap_cmd_output = &(rap_shared_mem->rap_out_message.output); + + dev_info(adev->dev, "RAP test failed, the output is:\n"); + dev_info(adev->dev, "\tlast_subsection: 0x%08x.\n", + rap_cmd_output->last_subsection); + dev_info(adev->dev, "\tnum_total_validate: 0x%08x.\n", + rap_cmd_output->num_total_validate); + dev_info(adev->dev, "\tnum_valid: 0x%08x.\n", + rap_cmd_output->num_valid); + dev_info(adev->dev, "\tlast_validate_addr: 0x%08x.\n", + rap_cmd_output->last_validate_addr); + dev_info(adev->dev, "\tlast_validate_val: 0x%08x.\n", + rap_cmd_output->last_validate_val); + dev_info(adev->dev, "\tlast_validate_val_exptd: 0x%08x.\n", + rap_cmd_output->last_validate_val_exptd); + } + break; + default: + dev_info(adev->dev, "Unsupported op id: %d, ", op); + dev_info(adev->dev, "Only support op 2(L0 validate test).\n"); + } + + amdgpu_gfx_off_ctrl(adev, true); + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + + return size; +} + +static const struct file_operations amdgpu_rap_debugfs_ops = { + .owner = THIS_MODULE, + .read = NULL, + .write = amdgpu_rap_debugfs_write, + .llseek = default_llseek +}; + +void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + struct drm_minor *minor = adev->ddev->primary; + + if (!adev->psp.rap_context.rap_initialized) + return; + + debugfs_create_file("rap_test", S_IWUSR, minor->debugfs_root, + adev, &amdgpu_rap_debugfs_ops); +#endif +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h new file mode 100644 index 000000000000..ec6d7632d3a0 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.h @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * + */ +#ifndef _AMDGPU_RAP_H +#define _AMDGPU_RAP_H + +#include "amdgpu.h" + +void amdgpu_rap_debugfs_init(struct amdgpu_device *adev); +#endif -- cgit v1.2.3 From 72e14ebf9fc09e33b28b70f00a2ed9821c198633 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Thu, 6 Aug 2020 14:48:15 +0800 Subject: drm/amdgpu: annotate a false positive recursive locking [ 584.110304] ============================================ [ 584.110590] WARNING: possible recursive locking detected [ 584.110876] 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 Tainted: G OE [ 584.111164] -------------------------------------------- [ 584.111456] kworker/38:1/553 is trying to acquire lock: [ 584.111721] ffff9b15ff0a47a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.112112] but task is already holding lock: [ 584.112673] ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.113068] other info that might help us debug this: [ 584.113689] Possible unsafe locking scenario: [ 584.114350] CPU0 [ 584.114685] ---- [ 584.115014] lock(&adev->reset_sem); [ 584.115349] lock(&adev->reset_sem); [ 584.115678] *** DEADLOCK *** [ 584.116624] May be due to missing lock nesting notation [ 584.117284] 4 locks held by kworker/38:1/553: [ 584.117616] #0: ffff9ad635c1d348 ((wq_completion)events){+.+.}, at: process_one_work+0x21f/0x630 [ 584.117967] #1: ffffac708e1c3e58 ((work_completion)(&con->recovery_work)){+.+.}, at: process_one_work+0x21f/0x630 [ 584.118358] #2: ffffffffc1c2a5d0 (&tmp->hive_lock){+.+.}, at: amdgpu_device_gpu_recover+0xae/0x1030 [amdgpu] [ 584.118786] #3: ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.119222] stack backtrace: [ 584.119990] CPU: 38 PID: 553 Comm: kworker/38:1 Kdump: loaded Tainted: G OE 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 [ 584.120782] Hardware name: Supermicro SYS-7049GP-TRT/X11DPG-QT, BIOS 3.1 05/23/2019 [ 584.121223] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 584.121638] Call Trace: [ 584.122050] dump_stack+0x98/0xd5 [ 584.122499] __lock_acquire+0x1139/0x16e0 [ 584.122931] ? trace_hardirqs_on+0x3b/0xf0 [ 584.123358] ? cancel_delayed_work+0xa6/0xc0 [ 584.123771] lock_acquire+0xb8/0x1c0 [ 584.124197] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.124599] down_write+0x49/0x120 [ 584.125032] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125472] amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125910] ? amdgpu_ras_error_query+0x1b8/0x2a0 [amdgpu] [ 584.126367] amdgpu_ras_do_recovery+0x159/0x190 [amdgpu] [ 584.126789] process_one_work+0x29e/0x630 [ 584.127208] worker_thread+0x3c/0x3f0 [ 584.127621] ? __kthread_parkme+0x61/0x90 [ 584.128014] kthread+0x12f/0x150 [ 584.128402] ? process_one_work+0x630/0x630 [ 584.128790] ? kthread_park+0x90/0x90 [ 584.129174] ret_from_fork+0x3a/0x50 Each adev has owned lock_class_key to avoid false positive recursive locking. v2: 1. register adev->lock_key into lockdep, otherwise lockdep will report the below warning [ 1216.705820] BUG: key ffff890183b647d0 has not been registered! [ 1216.705924] ------------[ cut here ]------------ [ 1216.705972] DEBUG_LOCKS_WARN_ON(1) [ 1216.705997] WARNING: CPU: 20 PID: 541 at kernel/locking/lockdep.c:3743 lockdep_init_map+0x150/0x210 v3: change to use down_write_nest_lock to annotate the false dead-lock warning. Reviewed-by: Daniel Vetter Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 16e23f053361..fe8878761c29 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4178,12 +4178,16 @@ end: return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) { if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - down_write(&adev->reset_sem); + if (hive) { + down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); + } else { + down_write(&adev->reset_sem); + } atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4345,7 +4349,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev)) { + if (!amdgpu_device_lock_adev(tmp_adev, hive)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; -- cgit v1.2.3 From 2f53072434525eccdd4a4cab3837096c1a3df357 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Tue, 11 Aug 2020 16:10:19 +0200 Subject: drm/amdgpu: pass NULL pointer instead of 0 Fixes: c030f2e4166c3f55 ("drm/amdgpu: add amdgpu_ras.c to support ras (v2)") Signed-off-by: Nirmoy Das Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 2d1fad1abf7a..cd1403f83dcf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1570,7 +1570,7 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) } if (amdgpu_device_should_recover_gpu(ras->adev)) - amdgpu_device_gpu_recover(ras->adev, 0); + amdgpu_device_gpu_recover(ras->adev, NULL); atomic_set(&ras->in_recovery, 0); } -- cgit v1.2.3 From 9fb1506eb671aa1640a8bd60f0121b94041a1f6a Mon Sep 17 00:00:00 2001 From: Oak Zeng Date: Thu, 6 Aug 2020 22:17:35 -0500 Subject: drm/amdgpu: Use function pointer for some mmhub functions Add more function pointers to amdgpu_mmhub_funcs. ASIC specific implementation of most mmhub functions are called from a general function pointer, instead of calling different function for different ASIC. Simplify the code by deleting duplicate functions Signed-off-by: Oak Zeng Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 21 ++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h | 13 ++++++ drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 19 ++++++--- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 48 ++++++---------------- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 27 ++++++++---- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h | 14 ------- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 25 +++++++---- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h | 11 +---- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c | 24 +++++++---- drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h | 12 ------ 12 files changed, 100 insertions(+), 121 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index 35d4a5ab0228..a2cb31737378 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -283,22 +283,6 @@ static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, return 0; } -static void kgd_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, - uint64_t page_table_base) -{ - struct amdgpu_device *adev = get_amdgpu_device(kgd); - - if (!amdgpu_amdkfd_is_kfd_vmid(adev, vmid)) { - pr_err("trying to set page table base for wrong VMID %u\n", - vmid); - return; - } - - mmhub_v9_4_setup_vm_pt_regs(adev, vmid, page_table_base); - - gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); -} - const struct kfd2kgd_calls arcturus_kfd2kgd = { .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings, .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping, @@ -317,7 +301,8 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { .wave_control_execute = kgd_gfx_v9_wave_control_execute, .address_watch_get_offset = kgd_gfx_v9_address_watch_get_offset, .get_atc_vmid_pasid_mapping_info = - kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, - .set_vm_context_page_table_base = kgd_set_vm_context_page_table_base, + kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, + .set_vm_context_page_table_base = + kgd_gfx_v9_set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 73728181b88f..d5d997fe6aa4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -677,7 +677,7 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd, return 0; } -static void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, +void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_device *adev = get_amdgpu_device(kgd); @@ -688,7 +688,7 @@ static void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, return; } - mmhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); + adev->mmhub.funcs->setup_vm_pt_regs(adev, vmid, page_table_base); gfxhub_v1_0_setup_vm_pt_regs(adev, vmid, page_table_base); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h index aedf67d57449..f098e88d3a0d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.h @@ -60,3 +60,6 @@ uint32_t kgd_gfx_v9_address_watch_get_offset(struct kgd_dev *kgd, bool kgd_gfx_v9_get_atc_vmid_pasid_mapping_info(struct kgd_dev *kgd, uint8_t vmid, uint16_t *p_pasid); + +void kgd_gfx_v9_set_vm_context_page_table_base(struct kgd_dev *kgd, + uint32_t vmid, uint64_t page_table_base); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h index e89fb35fec71..0c43d7fe893c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mmhub.h @@ -27,6 +27,19 @@ struct amdgpu_mmhub_funcs { void (*query_ras_error_count)(struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count)(struct amdgpu_device *adev); + u64 (*get_fb_location)(struct amdgpu_device *adev); + void (*init)(struct amdgpu_device *adev); + int (*gart_enable)(struct amdgpu_device *adev); + void (*set_fault_enable_default)(struct amdgpu_device *adev, + bool value); + void (*gart_disable)(struct amdgpu_device *adev); + int (*set_clockgating)(struct amdgpu_device *adev, + enum amd_clockgating_state state); + void (*get_clockgating)(struct amdgpu_device *adev, u32 *flags); + void (*setup_vm_pt_regs)(struct amdgpu_device *adev, uint32_t vmid, + uint64_t page_table_base); + void (*update_power_gating)(struct amdgpu_device *adev, + bool enable); }; struct amdgpu_mmhub { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index f0f50e785dcd..9d3b1245a339 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -627,10 +627,17 @@ static void gmc_v10_0_set_umc_funcs(struct amdgpu_device *adev) } } + +static void gmc_v10_0_set_mmhub_funcs(struct amdgpu_device *adev) +{ + adev->mmhub.funcs = &mmhub_v2_0_funcs; +} + static int gmc_v10_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; + gmc_v10_0_set_mmhub_funcs(adev); gmc_v10_0_set_gmc_funcs(adev); gmc_v10_0_set_irq_funcs(adev); gmc_v10_0_set_umc_funcs(adev); @@ -775,7 +782,7 @@ static int gmc_v10_0_sw_init(void *handle) else gfxhub_v2_0_init(adev); - mmhub_v2_0_init(adev); + adev->mmhub.funcs->init(adev); spin_lock_init(&adev->gmc.invalidate_lock); @@ -944,7 +951,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - r = mmhub_v2_0_gart_enable(adev); + r = adev->mmhub.funcs->gart_enable(adev); if (r) return r; @@ -966,7 +973,7 @@ static int gmc_v10_0_gart_enable(struct amdgpu_device *adev) gfxhub_v2_1_set_fault_enable_default(adev, value); else gfxhub_v2_0_set_fault_enable_default(adev, value); - mmhub_v2_0_set_fault_enable_default(adev, value); + adev->mmhub.funcs->set_fault_enable_default(adev, value); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_MMHUB_0, 0); gmc_v10_0_flush_gpu_tlb(adev, 0, AMDGPU_GFXHUB_0, 0); @@ -1011,7 +1018,7 @@ static void gmc_v10_0_gart_disable(struct amdgpu_device *adev) gfxhub_v2_1_gart_disable(adev); else gfxhub_v2_0_gart_disable(adev); - mmhub_v2_0_gart_disable(adev); + adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } @@ -1078,7 +1085,7 @@ static int gmc_v10_0_set_clockgating_state(void *handle, int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - r = mmhub_v2_0_set_clockgating(adev, state); + r = adev->mmhub.funcs->set_clockgating(adev, state); if (r) return r; @@ -1093,7 +1100,7 @@ static void gmc_v10_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - mmhub_v2_0_get_clockgating(adev, flags); + adev->mmhub.funcs->get_clockgating(adev, flags); if (adev->asic_type == CHIP_SIENNA_CICHLID || adev->asic_type == CHIP_NAVY_FLOUNDER) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 65488ddc34c3..773ee11b3d17 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -908,13 +908,11 @@ static void gmc_v9_0_set_umc_funcs(struct amdgpu_device *adev) static void gmc_v9_0_set_mmhub_funcs(struct amdgpu_device *adev) { switch (adev->asic_type) { - case CHIP_VEGA20: - adev->mmhub.funcs = &mmhub_v1_0_funcs; - break; case CHIP_ARCTURUS: adev->mmhub.funcs = &mmhub_v9_4_funcs; break; default: + adev->mmhub.funcs = &mmhub_v1_0_funcs; break; } } @@ -980,10 +978,8 @@ static void gmc_v9_0_vram_gtt_location(struct amdgpu_device *adev, { u64 base = 0; - if (adev->asic_type == CHIP_ARCTURUS) - base = mmhub_v9_4_get_fb_location(adev); - else if (!amdgpu_sriov_vf(adev)) - base = mmhub_v1_0_get_fb_location(adev); + if (!amdgpu_sriov_vf(adev)) + base = adev->mmhub.funcs->get_fb_location(adev); /* add the xgmi offset of the physical node */ base += adev->gmc.xgmi.physical_node_id * adev->gmc.xgmi.node_segment_size; @@ -1083,10 +1079,8 @@ static int gmc_v9_0_sw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; gfxhub_v1_0_init(adev); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_init(adev); - else - mmhub_v1_0_init(adev); + + adev->mmhub.funcs->init(adev); spin_lock_init(&adev->gmc.invalidate_lock); @@ -1313,10 +1307,7 @@ static int gmc_v9_0_gart_enable(struct amdgpu_device *adev) if (r) return r; - if (adev->asic_type == CHIP_ARCTURUS) - r = mmhub_v9_4_gart_enable(adev); - else - r = mmhub_v1_0_gart_enable(adev); + r = adev->mmhub.funcs->gart_enable(adev); if (r) return r; @@ -1351,11 +1342,10 @@ static int gmc_v9_0_hw_init(void *handle) golden_settings_vega10_hdp, ARRAY_SIZE(golden_settings_vega10_hdp)); + if (adev->mmhub.funcs->update_power_gating) + adev->mmhub.funcs->update_power_gating(adev, true); + switch (adev->asic_type) { - case CHIP_RAVEN: - /* TODO for renoir */ - mmhub_v1_0_update_power_gating(adev, true); - break; case CHIP_ARCTURUS: WREG32_FIELD15(HDP, 0, HDP_MMHUB_CNTL, HDP_MMHUB_GCC, 1); break; @@ -1381,10 +1371,7 @@ static int gmc_v9_0_hw_init(void *handle) if (!amdgpu_sriov_vf(adev)) { gfxhub_v1_0_set_fault_enable_default(adev, value); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_set_fault_enable_default(adev, value); - else - mmhub_v1_0_set_fault_enable_default(adev, value); + adev->mmhub.funcs->set_fault_enable_default(adev, value); } for (i = 0; i < adev->num_vmhubs; ++i) gmc_v9_0_flush_gpu_tlb(adev, 0, i, 0); @@ -1421,10 +1408,7 @@ static void gmc_v9_0_save_registers(struct amdgpu_device *adev) static void gmc_v9_0_gart_disable(struct amdgpu_device *adev) { gfxhub_v1_0_gart_disable(adev); - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_gart_disable(adev); - else - mmhub_v1_0_gart_disable(adev); + adev->mmhub.funcs->gart_disable(adev); amdgpu_gart_table_vram_unpin(adev); } @@ -1497,10 +1481,7 @@ static int gmc_v9_0_set_clockgating_state(void *handle, { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_set_clockgating(adev, state); - else - mmhub_v1_0_set_clockgating(adev, state); + adev->mmhub.funcs->set_clockgating(adev, state); athub_v1_0_set_clockgating(adev, state); @@ -1511,10 +1492,7 @@ static void gmc_v9_0_get_clockgating_state(void *handle, u32 *flags) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->asic_type == CHIP_ARCTURUS) - mmhub_v9_4_get_clockgating(adev, flags); - else - mmhub_v1_0_get_clockgating(adev, flags); + adev->mmhub.funcs->get_clockgating(adev, flags); athub_v1_0_get_clockgating(adev, flags); } diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index dffcb93ecee5..e24d6e533be3 100755 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -34,7 +34,7 @@ #define mmDAGB0_CNTL_MISC2_RV 0x008f #define mmDAGB0_CNTL_MISC2_RV_BASE_IDX 0 -u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) +static u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) { u64 base = RREG32_SOC15(MMHUB, 0, mmMC_VM_FB_LOCATION_BASE); u64 top = RREG32_SOC15(MMHUB, 0, mmMC_VM_FB_LOCATION_TOP); @@ -51,7 +51,7 @@ u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev) return base; } -void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -297,7 +297,7 @@ static void mmhub_v1_0_program_invalidation(struct amdgpu_device *adev) } } -void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, +static void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, bool enable) { if (amdgpu_sriov_vf(adev)) @@ -310,7 +310,7 @@ void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, } } -int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) +static int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) { if (amdgpu_sriov_vf(adev)) { /* @@ -338,7 +338,7 @@ int mmhub_v1_0_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) +static void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -373,7 +373,7 @@ void mmhub_v1_0_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -415,7 +415,7 @@ void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) WREG32_SOC15(MMHUB, 0, mmVM_L2_PROTECTION_FAULT_CNTL, tmp); } -void mmhub_v1_0_init(struct amdgpu_device *adev) +static void mmhub_v1_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -525,7 +525,7 @@ static void mmhub_v1_0_update_medium_grain_light_sleep(struct amdgpu_device *ade WREG32_SOC15(MMHUB, 0, mmATC_L2_MISC_CG, data); } -int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -549,7 +549,7 @@ int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -781,4 +781,13 @@ const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs = { .ras_late_init = amdgpu_mmhub_ras_late_init, .query_ras_error_count = mmhub_v1_0_query_ras_error_count, .reset_ras_error_count = mmhub_v1_0_reset_ras_error_count, + .get_fb_location = mmhub_v1_0_get_fb_location, + .init = mmhub_v1_0_init, + .gart_enable = mmhub_v1_0_gart_enable, + .set_fault_enable_default = mmhub_v1_0_set_fault_enable_default, + .gart_disable = mmhub_v1_0_gart_disable, + .set_clockgating = mmhub_v1_0_set_clockgating, + .get_clockgating = mmhub_v1_0_get_clockgating, + .setup_vm_pt_regs = mmhub_v1_0_setup_vm_pt_regs, + .update_power_gating = mmhub_v1_0_update_power_gating, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h index c43319e8f945..d77f5b65a618 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.h @@ -25,18 +25,4 @@ extern const struct amdgpu_mmhub_funcs mmhub_v1_0_funcs; -u64 mmhub_v1_0_get_fb_location(struct amdgpu_device *adev); -int mmhub_v1_0_gart_enable(struct amdgpu_device *adev); -void mmhub_v1_0_gart_disable(struct amdgpu_device *adev); -void mmhub_v1_0_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v1_0_init(struct amdgpu_device *adev); -int mmhub_v1_0_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v1_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, - bool enable); -void mmhub_v1_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); - #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 8acb3b625afe..5baf899417d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -83,7 +83,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, MMVM_L2_PROTECTION_FAULT_STATUS, RW)); } -void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -327,7 +327,7 @@ static void mmhub_v2_0_program_invalidation(struct amdgpu_device *adev) } } -int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) +static int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) { /* GART Enable. */ mmhub_v2_0_init_gart_aperture_regs(adev); @@ -343,7 +343,7 @@ int mmhub_v2_0_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) +static void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -374,7 +374,7 @@ void mmhub_v2_0_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; @@ -422,7 +422,7 @@ static const struct amdgpu_vmhub_funcs mmhub_v2_0_vmhub_funcs = { .get_invalidate_req = mmhub_v2_0_get_invalidate_req, }; -void mmhub_v2_0_init(struct amdgpu_device *adev) +static void mmhub_v2_0_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; @@ -552,7 +552,7 @@ static void mmhub_v2_0_update_medium_grain_light_sleep(struct amdgpu_device *ade } } -int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -576,7 +576,7 @@ int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -609,3 +609,14 @@ void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags) if (data & MM_ATC_L2_MISC_CG__MEM_LS_ENABLE_MASK) *flags |= AMD_CG_SUPPORT_MC_LS; } + +const struct amdgpu_mmhub_funcs mmhub_v2_0_funcs = { + .ras_late_init = amdgpu_mmhub_ras_late_init, + .init = mmhub_v2_0_init, + .gart_enable = mmhub_v2_0_gart_enable, + .set_fault_enable_default = mmhub_v2_0_set_fault_enable_default, + .gart_disable = mmhub_v2_0_gart_disable, + .set_clockgating = mmhub_v2_0_set_clockgating, + .get_clockgating = mmhub_v2_0_get_clockgating, + .setup_vm_pt_regs = mmhub_v2_0_setup_vm_pt_regs, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h index 3ea4344f0315..f80f461d67da 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.h @@ -23,15 +23,6 @@ #ifndef __MMHUB_V2_0_H__ #define __MMHUB_V2_0_H__ -int mmhub_v2_0_gart_enable(struct amdgpu_device *adev); -void mmhub_v2_0_gart_disable(struct amdgpu_device *adev); -void mmhub_v2_0_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v2_0_init(struct amdgpu_device *adev); -int mmhub_v2_0_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v2_0_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); +extern const struct amdgpu_mmhub_funcs mmhub_v2_0_funcs; #endif diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c index 9979f54fef57..6c6ad529c65c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c @@ -36,7 +36,7 @@ #define MMHUB_NUM_INSTANCES 2 #define MMHUB_INSTANCE_REGISTER_OFFSET 0x3000 -u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev) +static u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev) { /* The base should be same b/t 2 mmhubs on Acrturus. Read one here. */ u64 base = RREG32_SOC15(MMHUB, 0, mmVMSHAREDVC0_MC_VM_FB_LOCATION_BASE); @@ -97,7 +97,7 @@ static void mmhub_v9_4_init_gart_aperture_regs(struct amdgpu_device *adev, (u32)(adev->gmc.gart_end >> 44)); } -void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, +static void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, uint64_t page_table_base) { int i; @@ -375,7 +375,7 @@ static void mmhub_v9_4_program_invalidation(struct amdgpu_device *adev, } } -int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) +static int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) { int i; @@ -397,7 +397,7 @@ int mmhub_v9_4_gart_enable(struct amdgpu_device *adev) return 0; } -void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) +static void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0]; u32 tmp; @@ -442,7 +442,7 @@ void mmhub_v9_4_gart_disable(struct amdgpu_device *adev) * @adev: amdgpu_device pointer * @value: true redirects VM faults to the default page */ -void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) +static void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) { u32 tmp; int i; @@ -500,7 +500,7 @@ void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, bool value) } } -void mmhub_v9_4_init(struct amdgpu_device *adev) +static void mmhub_v9_4_init(struct amdgpu_device *adev) { struct amdgpu_vmhub *hub[MMHUB_NUM_INSTANCES] = {&adev->vmhub[AMDGPU_MMHUB_0], &adev->vmhub[AMDGPU_MMHUB_1]}; @@ -630,7 +630,7 @@ static void mmhub_v9_4_update_medium_grain_light_sleep(struct amdgpu_device *ade } } -int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, +static int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, enum amd_clockgating_state state) { if (amdgpu_sriov_vf(adev)) @@ -650,7 +650,7 @@ int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, return 0; } -void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags) +static void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags) { int data, data1; @@ -1628,4 +1628,12 @@ const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs = { .ras_late_init = amdgpu_mmhub_ras_late_init, .query_ras_error_count = mmhub_v9_4_query_ras_error_count, .reset_ras_error_count = mmhub_v9_4_reset_ras_error_count, + .get_fb_location = mmhub_v9_4_get_fb_location, + .init = mmhub_v9_4_init, + .gart_enable = mmhub_v9_4_gart_enable, + .set_fault_enable_default = mmhub_v9_4_set_fault_enable_default, + .gart_disable = mmhub_v9_4_gart_disable, + .set_clockgating = mmhub_v9_4_set_clockgating, + .get_clockgating = mmhub_v9_4_get_clockgating, + .setup_vm_pt_regs = mmhub_v9_4_setup_vm_pt_regs, }; diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h index 1b979773776c..92404a8f66f3 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.h @@ -25,16 +25,4 @@ extern const struct amdgpu_mmhub_funcs mmhub_v9_4_funcs; -u64 mmhub_v9_4_get_fb_location(struct amdgpu_device *adev); -int mmhub_v9_4_gart_enable(struct amdgpu_device *adev); -void mmhub_v9_4_gart_disable(struct amdgpu_device *adev); -void mmhub_v9_4_set_fault_enable_default(struct amdgpu_device *adev, - bool value); -void mmhub_v9_4_init(struct amdgpu_device *adev); -int mmhub_v9_4_set_clockgating(struct amdgpu_device *adev, - enum amd_clockgating_state state); -void mmhub_v9_4_get_clockgating(struct amdgpu_device *adev, u32 *flags); -void mmhub_v9_4_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, - uint64_t page_table_base); - #endif -- cgit v1.2.3 From a9c75edcbe7cca5c2edb87fa765efac7558523c0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 6 Aug 2020 15:38:25 +0800 Subject: drm/amd/powerplay: update the metrics table cache interval as 1ms To make the setting same as Arcturus/Navi1x/Sienna_Cichlid. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 2 +- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 2 +- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index c70c30175801..f0680dd58508 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -1272,7 +1272,7 @@ static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, if (bypass_cache || !data->metrics_time || - time_after(jiffies, data->metrics_time + HZ / 2)) { + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&data->metrics_table), TABLE_SMU_METRICS, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index c9f402edc0d6..da84012b7fd5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -2082,7 +2082,7 @@ static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, if (bypass_cache || !data->metrics_time || - time_after(jiffies, data->metrics_time + HZ / 2)) { + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&data->metrics_table), TABLE_SMU_METRICS, diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index 8a8e6033f71f..c50c4547fea9 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -139,7 +139,7 @@ static int renoir_get_metrics_table(struct smu_context *smu, if (bypass_cache || !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) { + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, (void *)smu_table->metrics_table, false); if (ret) { -- cgit v1.2.3 From fceafc9b7b393698ac9aadb5c3b64b1ba1f61e1e Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 6 Aug 2020 16:49:19 +0800 Subject: drm/amd/powerplay: maximum the code sharing around metrics table retrieving Instead of having one copy in each ASIC. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 55 +++------------------- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 41 +++------------- drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 40 ++-------------- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 55 +++------------------- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 45 ++++++++++++++++++ drivers/gpu/drm/amd/powerplay/smu_cmn.h | 8 ++++ 6 files changed, 77 insertions(+), 167 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index e59e6fb6f0a8..8b1025dc54fd 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -541,49 +541,6 @@ static int arcturus_freqs_in_same_level(int32_t frequency1, return (abs(frequency1 - frequency2) <= EPSILON); } -static int arcturus_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - -static int arcturus_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = arcturus_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int arcturus_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -594,9 +551,9 @@ static int arcturus_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = arcturus_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2305,9 +2262,9 @@ static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = arcturus_get_metrics_table(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 82659b781f05..42a60769c52f 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -504,34 +504,6 @@ err0_out: return -ENOMEM; } -static int navi10_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - static int navi10_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -547,9 +519,9 @@ static int navi10_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = navi10_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2526,14 +2498,15 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = navi10_get_metrics_table_locked(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + true); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; } + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); if (adev->asic_type == CHIP_NAVI12) memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c index c50c4547fea9..186929c31e9e 100644 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c @@ -128,36 +128,6 @@ static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), }; -static int renoir_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, SMU_TABLE_SMU_METRICS, 0, - (void *)smu_table->metrics_table, false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - mutex_unlock(&smu->metrics_lock); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int renoir_init_smc_tables(struct smu_context *smu) { struct smu_table_context *smu_table = &smu->smu_table; @@ -381,7 +351,7 @@ static int renoir_print_clk_levels(struct smu_context *smu, memset(&metrics, 0, sizeof(metrics)); - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -527,7 +497,7 @@ static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, int ret = 0, clk_id = 0; SmuMetrics_t metrics; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -610,7 +580,7 @@ static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -630,7 +600,7 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, if (!value) return -EINVAL; - ret = renoir_get_metrics_table(smu, &metrics, false); + ret = smu_cmn_get_metrics_table(smu, &metrics, false); if (ret) return ret; @@ -1016,7 +986,7 @@ static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = renoir_get_metrics_table(smu, &metrics, true); + ret = smu_cmn_get_metrics_table(smu, &metrics, true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index bb756b4c284e..c5935f0a065b 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -407,49 +407,6 @@ err0_out: return -ENOMEM; } -static int sienna_cichlid_get_metrics_table_locked(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t)); - - return 0; -} - -static int sienna_cichlid_get_metrics_table(struct smu_context *smu, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = sienna_cichlid_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} - static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, MetricsMember_t member, uint32_t *value) @@ -460,9 +417,9 @@ static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, mutex_lock(&smu->metrics_lock); - ret = sienna_cichlid_get_metrics_table_locked(smu, - NULL, - false); + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); if (ret) { mutex_unlock(&smu->metrics_lock); return ret; @@ -2698,9 +2655,9 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, SmuMetrics_t metrics; int ret = 0; - ret = sienna_cichlid_get_metrics_table(smu, - &metrics, - true); + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); if (ret) return ret; diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index 5c23c44c33bd..968b734baac0 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -631,3 +631,48 @@ int smu_cmn_write_pptable(struct smu_context *smu) pptable, true); } + +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + struct smu_table_context *smu_table= &smu->smu_table; + uint32_t table_size = + smu_table->tables[SMU_TABLE_SMU_METRICS].size; + int ret = 0; + + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + return ret; + } + smu_table->metrics_time = jiffies; + } + + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, table_size); + + return 0; +} + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/powerplay/smu_cmn.h index 98face8c5fd6..6d00ad740c27 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.h +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.h @@ -79,5 +79,13 @@ int smu_cmn_write_watermarks_table(struct smu_context *smu); int smu_cmn_write_pptable(struct smu_context *smu); +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + #endif #endif -- cgit v1.2.3 From c048e4cd607ae637eac5e7c81e8aa5b9f0d43a6a Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 10 Aug 2020 13:27:56 +0800 Subject: drm/amd/powerplay: bump NAVI12 driver if version To fit the latest SMU firmware. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') 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 ee1506beb0ea..65363d56e3cc 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h @@ -28,7 +28,7 @@ #define SMU11_DRIVER_IF_VERSION_INV 0xFFFFFFFF #define SMU11_DRIVER_IF_VERSION_ARCT 0x17 #define SMU11_DRIVER_IF_VERSION_NV10 0x36 -#define SMU11_DRIVER_IF_VERSION_NV12 0x33 +#define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 #define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 -- cgit v1.2.3 From ba4e049e63b607ac2e0c070b1406826390d5047e Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Wed, 12 Aug 2020 15:57:32 +0800 Subject: drm/amdgpu: disable gfxoff for navy_flounder gfxoff is temporarily disabled for navy_flounder, since at present the feature has broken some basic amdgpu test. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index d851fe80eaf4..de6e6de41867 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3610,6 +3610,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; + case CHIP_NAVY_FLOUNDER: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + break; default: break; } -- cgit v1.2.3 From e1a84641d478f7f35a8189f447da107c473ef0d0 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 6 Aug 2020 23:41:47 +0800 Subject: drm/amdgpu: fix uninit-value in arcturus_log_thermal_throttling_event() when function arcturus_get_smu_metrics_data() call failed, it will cause the variable "throttler_status" isn't initialized before use. warning: powerplay/arcturus_ppt.c:2268:24: warning: ‘throttler_status’ may be used uninitialized in this function [-Wmaybe-uninitialized] 2268 | if (throttler_status & logging_label[throttler_idx].feature_mask) { Signed-off-by: Kevin Wang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 8b1025dc54fd..81f43fea4d52 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2208,14 +2208,17 @@ static const struct throttling_logging_label { }; static void arcturus_log_thermal_throttling_event(struct smu_context *smu) { + int ret; int throttler_idx, throtting_events = 0, buf_idx = 0; struct amdgpu_device *adev = smu->adev; uint32_t throttler_status; char log_buf[256]; - arcturus_get_smu_metrics_data(smu, - METRICS_THROTTLER_STATUS, - &throttler_status); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_THROTTLER_STATUS, + &throttler_status); + if (ret) + return; memset(log_buf, 0, sizeof(log_buf)); for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label); -- cgit v1.2.3 From f10bb940d8d2774fedc63c4dfb975e4310a261cd Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 11:53:47 +0800 Subject: drm/amd/powerplay: optimize the interface for mgpu fan boost enablement Cover the implementation details from outside(of power). Also preparing for expanding this to swSMU. Signed-off-by: Evan Quan Acked-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +--- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 13 +++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 6 ++---- 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index fe8878761c29..bb7f0c8611f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2228,9 +2228,7 @@ static int amdgpu_device_enable_mgpu_fan_boost(void) gpu_ins = &(mgpu_info.gpu_ins[i]); adev = gpu_ins->adev; if (!(adev->flags & AMD_IS_APU) && - !gpu_ins->mgpu_fan_enabled && - adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->enable_mgpu_fan_boost) { + !gpu_ins->mgpu_fan_enabled) { ret = amdgpu_dpm_enable_mgpu_fan_boost(adev); if (ret) break; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 2082c0acd216..27417f873a36 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1216,3 +1216,16 @@ int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) return 0; } + +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = 0; + + if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index b190c0af7db1..cc16b5a3ac44 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -357,10 +357,6 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ (adev)->powerplay.pp_handle, type, parameter, size)) -#define amdgpu_dpm_enable_mgpu_fan_boost(adev) \ - ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\ - (adev)->powerplay.pp_handle)) - #define amdgpu_dpm_get_ppfeature_status(adev, buf) \ ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ (adev)->powerplay.pp_handle, (buf))) @@ -548,4 +544,6 @@ int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); + #endif -- cgit v1.2.3 From 9f979a49e23f4b87d038708e06ea6d320e198e71 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 12:08:56 +0800 Subject: drm/amd/powerplay: enable swSMU mgpu fan boost support Enable mgpu fan boost feature on swSMU routines. Signed-off-by: Evan Quan Acked-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 5 ++++- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 3 +++ 3 files changed, 24 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 27417f873a36..240c440cbe00 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1222,9 +1222,12 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) void *pp_handle = adev->powerplay.pp_handle; const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + struct smu_context *smu = &adev->smu; int ret = 0; - if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + if (is_support_sw_smu(adev)) + ret = smu_enable_mgpu_fan_boost(smu); + else if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); return ret; diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index 1ffacc712e53..f87a73cb7ec5 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -2652,3 +2652,20 @@ ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, return size; } + +int smu_enable_mgpu_fan_boost(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->enable_mgpu_fan_boost) + ret = smu->ppt_funcs->enable_mgpu_fan_boost(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h index 23c2279bd500..bbe4a343e9f1 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h @@ -595,6 +595,7 @@ struct pptable_funcs { size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); + int (*enable_mgpu_fan_boost)(struct smu_context *smu); }; typedef enum { @@ -799,5 +800,7 @@ int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); +int smu_enable_mgpu_fan_boost(struct smu_context *smu); + #endif #endif -- cgit v1.2.3 From 94a670d5ac45b9449581d7133287cc297774f944 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 12:29:16 +0800 Subject: drm/amd/powerplay: enable Navi1X mgpu fan boost feature(V2) Support Navi1X mgpu fan boost enablement. V2: rich the comment and correct the revision id check Signed-off-by: Evan Quan Acked-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- .../gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h | 4 +++- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h index 406bfd187ce8..fa0174dc7e0e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h @@ -123,7 +123,9 @@ #define PPSMC_MSG_DALDisableDummyPstateChange 0x49 #define PPSMC_MSG_DALEnableDummyPstateChange 0x4A -#define PPSMC_Message_Count 0x4B +#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x4C + +#define PPSMC_Message_Count 0x4D typedef uint32_t PPSMC_Result; typedef uint32_t PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 42a60769c52f..4b4d461899df 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -138,6 +138,7 @@ static struct cmn2asic_msg_mapping navi10_message_map[SMU_MSG_MAX_COUNT] = { MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0), MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), }; static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { @@ -2557,6 +2558,26 @@ static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_0); } +static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t param = 0; + + /* Navi12 does not support this */ + if (adev->asic_type == CHIP_NAVI12) + return 0; + + /* Workaround for WS SKU */ + if (adev->pdev->device == 0x7312 && + adev->pdev->revision == 0) + param = 0xD188; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + param, + NULL); +} + static const struct pptable_funcs navi10_ppt_funcs = { .get_allowed_feature_mask = navi10_get_allowed_feature_mask, .set_default_dpm_table = navi10_set_default_dpm_table, @@ -2638,6 +2659,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = navi10_get_gpu_metrics, + .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, }; void navi10_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From 05f39286ce11b98376e0d179aff0d537c257e772 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 12:37:03 +0800 Subject: drm/amd/powerplay: enable Sienna Cichlid mgpu fan boost feature Support Sienna Cichlid mgpu fan boost enablement. Signed-off-by: Evan Quan Acked-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index c5935f0a065b..407a11c2826b 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -124,6 +124,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(BacoAudioD3PME, PPSMC_MSG_BacoAudioD3PME, 0), MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), MSG_MAP(Mode1Reset, PPSMC_MSG_Mode1Reset, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), }; static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { @@ -2709,6 +2710,14 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, return sizeof(struct gpu_metrics_v1_0); } +static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + 0, + NULL); +} + static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, @@ -2786,6 +2795,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, + .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From f1403342ebdfcff3c3cf57ae476f19d3078f2767 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 12 Aug 2020 17:48:26 +0200 Subject: drm/amdgpu: revert "fix system hang issue during GPU reset" The whole approach wasn't thought through till the end. We already had a reset lock like this in the past and it caused the same problems like this one. Completely revert the patch for now and add individual trylock protection to the hardware access functions as necessary. This reverts commit df9c8d1aa278c435c30a69b8f2418b4a52fcb929. Signed-off-by: Christian König Acked-by: Alex Deucher 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 | 57 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 - drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 353 ++++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 3 +- drivers/gpu/drm/amd/amdgpu/atom.c | 1 - drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 13 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 13 +- .../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, 184 insertions(+), 469 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3e82a11577d9..08f80ca3b296 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,9 +949,9 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate; - atomic_t in_gpu_reset; + bool in_gpu_reset; enum pp_mp1_state mp1_state; - struct rw_semaphore reset_sem; + struct mutex lock_reset; struct amdgpu_doorbell_index doorbell_index; struct mutex notifier_lock; @@ -1266,9 +1266,4 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) return adev->gmc.tmz_enabled; } -static inline bool amdgpu_in_reset(struct amdgpu_device *adev) -{ - return atomic_read(&adev->in_gpu_reset) ? true : false; -} - #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 9738dccb1c2c..0effc1d46824 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -244,14 +244,11 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, if (cp_mqd_gfx9) bp.flags |= AMDGPU_GEM_CREATE_CP_MQD_GFX9; - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - r = amdgpu_bo_create(adev, &bp, &bo); if (r) { dev_err(adev->dev, "failed to allocate BO for amdkfd (%d)\n", r); - goto err; + return r; } /* map the buffer */ @@ -286,7 +283,6 @@ int amdgpu_amdkfd_alloc_gtt_mem(struct kgd_dev *kgd, size_t size, amdgpu_bo_unreserve(bo); - up_read(&adev->reset_sem); return 0; allocate_mem_kmap_bo_failed: @@ -295,25 +291,19 @@ 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, @@ -345,14 +335,9 @@ int amdgpu_amdkfd_alloc_gws(struct kgd_dev *kgd, size_t size, void amdgpu_amdkfd_free_gws(struct kgd_dev *kgd, void *mem_obj) { - struct amdgpu_device *adev = (struct amdgpu_device *)kgd; struct amdgpu_bo *bo = (struct amdgpu_bo *)mem_obj; - down_read(&adev->reset_sem); - amdgpu_bo_unref(&bo); - - up_read(&adev->reset_sem); } uint32_t amdgpu_amdkfd_get_fw_version(struct kgd_dev *kgd, @@ -626,15 +611,8 @@ int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, /* This works for NO_HWS. TODO: need to handle without knowing VMID */ job->vmid = vmid; - if (!down_read_trylock(&adev->reset_sem)) { - ret = -EIO; - goto err_ib_sched; - } - ret = amdgpu_ib_schedule(ring, 1, ib, job, &f); - up_read(&adev->reset_sem); - if (ret) { DRM_ERROR("amdgpu: failed to schedule IB.\n"); goto err_ib_sched; @@ -670,9 +648,6 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) { struct amdgpu_device *adev = (struct amdgpu_device *)kgd; - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - if (adev->family == AMDGPU_FAMILY_AI) { int i; @@ -682,8 +657,6 @@ int amdgpu_amdkfd_flush_gpu_tlb_vmid(struct kgd_dev *kgd, uint16_t vmid) amdgpu_gmc_flush_gpu_tlb(adev, vmid, AMDGPU_GFXHUB_0, 0); } - up_read(&adev->reset_sem); - return 0; } @@ -692,18 +665,11 @@ int amdgpu_amdkfd_flush_gpu_tlb_pasid(struct kgd_dev *kgd, uint16_t pasid) struct amdgpu_device *adev = (struct amdgpu_device *)kgd; const uint32_t flush_type = 0; bool all_hub = false; - int ret = -EIO; if (adev->family == AMDGPU_FAMILY_AI) all_hub = true; - if (down_read_trylock(&adev->reset_sem)) { - ret = amdgpu_gmc_flush_gpu_tlb_pasid(adev, - pasid, flush_type, all_hub); - up_read(&adev->reset_sem); - } - - return ret; + return amdgpu_gmc_flush_gpu_tlb_pasid(adev, pasid, flush_type, all_hub); } bool amdgpu_amdkfd_have_atomics_support(struct kgd_dev *kgd) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index b0dcc800251e..bf927f432506 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -542,7 +542,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v10_compute_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; #if 0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index 275f20399373..744366c7ee85 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -423,7 +423,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, unsigned long flags, end_jiffies; int retry; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index 4997189d8b36..feab4cc6e836 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -419,7 +419,7 @@ static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, int retry; struct vi_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index d5d997fe6aa4..e4c274bd35c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -539,7 +539,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v9_mqd *m = get_mqd(mqd); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index fcf72f337785..62cb510e2cc4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1194,9 +1194,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( return -EINVAL; } - if (!down_read_trylock(&adev->reset_sem)) - return -EIO; - *mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL); if (!*mem) { ret = -ENOMEM; @@ -1263,7 +1260,6 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( if (offset) *offset = amdgpu_bo_mmap_offset(bo); - up_read(&adev->reset_sem); return 0; allocate_init_user_pages_failed: @@ -1281,9 +1277,6 @@ 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 a3b150304dae..a512ccbc4dea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1292,8 +1292,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) parser.adev = adev; parser.filp = filp; - down_read(&adev->reset_sem); - r = amdgpu_cs_parser_init(&parser, data); if (r) { DRM_ERROR("Failed to initialize parser %d!\n", r); @@ -1333,8 +1331,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) out: amdgpu_cs_parser_fini(&parser, r, reserved_buffers); - up_read(&adev->reset_sem); - return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index d85d13f7a043..8842c55d4490 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -358,8 +358,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, if (atomic_read(&ctx->guilty)) out->state.flags |= AMDGPU_CTX_QUERY2_FLAGS_GUILTY; - down_read(&adev->reset_sem); - /*query ue count*/ ras_counter = amdgpu_ras_query_error_count(adev, false); /*ras counter is monotonic increasing*/ @@ -375,8 +373,6 @@ static int amdgpu_ctx_query2(struct amdgpu_device *adev, ctx->ras_counter_ce = ras_counter; } - up_read(&adev->reset_sem); - mutex_unlock(&mgr->lock); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 0af249a1e35b..35fed75a4397 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -101,14 +101,14 @@ static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) file->private_data = adev; - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); if (adev->autodump.dumping.done) { reinit_completion(&adev->autodump.dumping); ret = 0; } else { ret = -EBUSY; } - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); return ret; } @@ -127,7 +127,7 @@ static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_ poll_wait(file, &adev->autodump.gpu_hang, poll_table); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return POLLIN | POLLRDNORM | POLLWRNORM; return 0; @@ -1242,7 +1242,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) } /* Avoid accidently unparking the sched thread during GPU reset */ - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -1269,7 +1269,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) kthread_unpark(ring->sched.thread); } - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1459,7 +1459,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) return -ENOMEM; /* Avoid accidently unparking the sched thread during GPU reset */ - down_read(&adev->reset_sem); + mutex_lock(&adev->lock_reset); /* stop the scheduler */ kthread_park(ring->sched.thread); @@ -1500,7 +1500,7 @@ failure: /* restart the scheduler */ kthread_unpark(ring->sched.thread); - up_read(&adev->reset_sem); + mutex_unlock(&adev->lock_reset); ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index bb7f0c8611f9..415e1a32b98c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1940,7 +1940,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) if (adev->ip_blocks[i].status.hw == true) break; - if (amdgpu_in_reset(adev) || adev->in_suspend) { + if (adev->in_gpu_reset || adev->in_suspend) { r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { DRM_ERROR("resume of IP block <%s> failed %d\n", @@ -2117,7 +2117,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev) AMDGPU_RESET_MAGIC_NUM)) return true; - if (!amdgpu_in_reset(adev)) + if (!adev->in_gpu_reset) return false; /* @@ -3053,8 +3053,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->mn_lock); mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); - init_rwsem(&adev->reset_sem); - atomic_set(&adev->in_gpu_reset, 0); + mutex_init(&adev->lock_reset); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4082,11 +4081,8 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (need_full_reset) { /* post card */ - if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) { - dev_warn(tmp_adev->dev, "asic atom init failed!"); - r = -EAGAIN; - goto out; - } + if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) + DRM_WARN("asic atom init failed!"); if (!r) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); @@ -4176,18 +4172,16 @@ end: return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, struct amdgpu_hive_info *hive) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, bool trylock) { - if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) - return false; - - if (hive) { - down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); - } else { - down_write(&adev->reset_sem); - } + if (trylock) { + if (!mutex_trylock(&adev->lock_reset)) + return false; + } else + mutex_lock(&adev->lock_reset); atomic_inc(&adev->gpu_reset_counter); + adev->in_gpu_reset = true; switch (amdgpu_asic_reset_method(adev)) { case AMD_RESET_METHOD_MODE1: adev->mp1_state = PP_MP1_STATE_SHUTDOWN; @@ -4207,8 +4201,8 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) { amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; - atomic_set(&adev->in_gpu_reset, 0); - up_write(&adev->reset_sem); + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); } static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) @@ -4318,14 +4312,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, false); - if (hive) { - if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { - DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", - job ? job->base.id : -1, hive->hive_id); - return 0; - } - mutex_lock(&hive->hive_lock); + hive = amdgpu_get_xgmi_hive(adev, true); + if (hive && !mutex_trylock(&hive->reset_lock)) { + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", + job ? job->base.id : -1, hive->hive_id); + mutex_unlock(&hive->hive_lock); + return 0; } /* @@ -4347,11 +4339,11 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev, hive)) { + if (!amdgpu_device_lock_adev(tmp_adev, !hive)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); - r = 0; - goto skip_recovery; + mutex_unlock(&hive->hive_lock); + return 0; } /* @@ -4484,9 +4476,8 @@ skip_sched_resume: amdgpu_device_unlock_adev(tmp_adev); } -skip_recovery: if (hive) { - atomic_set(&hive->in_reset, 0); + mutex_unlock(&hive->reset_lock); mutex_unlock(&hive->hive_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 73cc68ab53d0..7f9e50247413 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -671,8 +671,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, bo_va = NULL; } - down_read(&adev->reset_sem); - switch (args->operation) { case AMDGPU_VA_OP_MAP: va_flags = amdgpu_gem_va_map_flags(adev, args->flags); @@ -702,8 +700,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, amdgpu_gem_va_update_vm(adev, &fpriv->vm, bo_va, args->operation); - up_read(&adev->reset_sem); - error_backoff: ttm_eu_backoff_reservation(&ticket, &list); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 8ccd17d02cc6..a819360a4b6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -719,7 +719,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_read; might_sleep(); @@ -777,7 +777,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_write; might_sleep(); @@ -796,5 +796,5 @@ failed_undo: amdgpu_ring_undo(ring); spin_unlock_irqrestore(&kiq->ring_lock, flags); failed_kiq_write: - dev_warn(adev->dev, "failed to write reg:%x\n", reg); + pr_err("failed to write reg:%x\n", reg); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 75d37dfb51aa..937029ad5271 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -220,17 +220,17 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job) trace_amdgpu_sched_run_job(job); - if (down_read_trylock(&ring->adev->reset_sem)) { + if (job->vram_lost_counter != atomic_read(&ring->adev->vram_lost_counter)) + dma_fence_set_error(finished, -ECANCELED);/* skip IB as well if VRAM lost */ + + if (finished->error < 0) { + DRM_INFO("Skip scheduling IBs!\n"); + } else { r = amdgpu_ib_schedule(ring, job->num_ibs, job->ibs, job, - &fence); - up_read(&ring->adev->reset_sem); + &fence); if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); - } else { - dma_fence_set_error(finished, -ECANCELED); - DRM_INFO("Skip scheduling IBs!\n"); } - /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 58580a48b648..7619f1c3084d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1087,8 +1087,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, if (!fpriv) return; - down_read(&adev->reset_sem); - pm_runtime_get_sync(dev->dev); if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL) @@ -1127,8 +1125,6 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); - - up_read(&adev->reset_sem); } /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 1705e328c6fc..65ad174bb976 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -163,7 +163,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, enum amd_pm_state_type pm; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -172,8 +172,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { if (adev->smu.ppt_funcs->get_current_power_state) pm = smu_get_current_power_state(&adev->smu); @@ -185,8 +183,6 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, pm = adev->pm.dpm.user_state; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -205,7 +201,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strncmp("battery", buf, strlen("battery")) == 0) @@ -223,8 +219,6 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { mutex_lock(&adev->pm.mutex); adev->pm.dpm.user_state = state; @@ -238,9 +232,6 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, amdgpu_pm_compute_clocks(adev); } - - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -316,7 +307,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level = 0xff; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -325,8 +316,6 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -334,8 +323,6 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, else level = adev->pm.dpm.forced_level; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -362,7 +349,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level current_level = 0xff; int ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strncmp("low", buf, strlen("low")) == 0) { @@ -393,8 +380,6 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) current_level = smu_get_performance_level(&adev->smu); else if (adev->powerplay.pp_funcs->get_performance_level) @@ -403,8 +388,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (current_level == level) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = count; - goto pro_end; + return count; } if (adev->asic_type == CHIP_RAVEN) { @@ -425,8 +409,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pr_err("Currently not in any profile mode!\n"); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } if (is_support_sw_smu(adev)) { @@ -434,8 +417,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } else if (adev->powerplay.pp_funcs->force_performance_level) { mutex_lock(&adev->pm.mutex); @@ -443,16 +425,14 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } ret = amdgpu_dpm_force_performance_level(adev, level); if (ret) { mutex_unlock(&adev->pm.mutex); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } else { adev->pm.dpm.forced_level = level; } @@ -461,9 +441,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); -pro_end: - up_read(&adev->reset_sem); - return ret; + return count; } static ssize_t amdgpu_get_pp_num_states(struct device *dev, @@ -475,7 +453,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len, ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -519,7 +497,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0, ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -560,7 +538,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->pp_force_state_enabled) @@ -580,7 +558,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, unsigned long idx; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (strlen(buf) == 1) @@ -606,7 +584,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, return ret; } - down_read(&adev->reset_sem); /* only set user selected power states */ if (state != POWER_STATE_TYPE_INTERNAL_BOOT && state != POWER_STATE_TYPE_DEFAULT) { @@ -614,8 +591,6 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, AMD_PP_TASK_ENABLE_USER_STATE, &state); adev->pp_force_state_enabled = true; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); } @@ -643,7 +618,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size, ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -687,7 +662,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -696,21 +671,16 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_table(&adev->smu, (void *)buf, count); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return ret; } } else if (adev->powerplay.pp_funcs->set_pp_table) amdgpu_dpm_set_pp_table(adev, buf, count); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -845,7 +815,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, const char delimiter[3] = {' ', '\n', '\0'}; uint32_t type; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (count > 127) @@ -889,10 +859,6 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, return ret; } - ret = count; - - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { ret = smu_od_edit_dpm_table(&adev->smu, type, parameter, parameter_size); @@ -900,8 +866,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } else { if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { @@ -910,8 +875,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } @@ -922,22 +886,18 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, NULL); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = count; - goto pro_end; + return count; } else { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - ret = -EINVAL; - goto pro_end; + return -EINVAL; } } } pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); -pro_end: - up_read(&adev->reset_sem); - return ret; + return count; } static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, @@ -949,7 +909,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1003,7 +963,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtou64(buf, 0, &featuremask); @@ -1018,13 +978,11 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, return ret; } - down_read(&adev->reset_sem); if (is_support_sw_smu(adev)) { ret = smu_sys_set_pp_feature_mask(&adev->smu, featuremask); if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } } else if (adev->powerplay.pp_funcs->set_ppfeature_status) { @@ -1032,12 +990,9 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, if (ret) { pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1053,7 +1008,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1062,8 +1017,6 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_sys_get_pp_feature_mask(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_ppfeature_status) @@ -1071,8 +1024,6 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1118,7 +1069,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1127,8 +1078,6 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1136,8 +1085,6 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1190,7 +1137,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1203,15 +1150,11 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1230,7 +1173,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1239,8 +1182,6 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_MCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1248,8 +1189,6 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1266,7 +1205,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, uint32_t mask = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1279,15 +1218,11 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_MCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1306,7 +1241,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1315,8 +1250,6 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_SOCCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1324,8 +1257,6 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1342,7 +1273,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1355,8 +1286,6 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_SOCCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1364,8 +1293,6 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1384,7 +1311,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1393,8 +1320,6 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_FCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1402,8 +1327,6 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1420,7 +1343,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1433,8 +1356,6 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_FCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1442,8 +1363,6 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1462,7 +1381,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1471,8 +1390,6 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_DCEFCLK, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1480,8 +1397,6 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1498,7 +1413,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1511,8 +1426,6 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_DCEFCLK, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1520,8 +1433,6 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1540,7 +1451,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1549,8 +1460,6 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_print_clk_levels(&adev->smu, SMU_PCIE, buf); else if (adev->powerplay.pp_funcs->print_clock_levels) @@ -1558,8 +1467,6 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1576,7 +1483,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, int ret; uint32_t mask = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1589,8 +1496,6 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_force_clk_levels(&adev->smu, SMU_PCIE, mask); else if (adev->powerplay.pp_funcs->force_clock_level) @@ -1598,8 +1503,6 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, else ret = 0; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1618,7 +1521,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, uint32_t value = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1627,15 +1530,11 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_SCLK); else if (adev->powerplay.pp_funcs->get_sclk_od) value = amdgpu_dpm_get_sclk_od(adev); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1652,7 +1551,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, int ret; long int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1666,8 +1565,6 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value); } else { @@ -1682,8 +1579,6 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1699,7 +1594,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, uint32_t value = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1708,15 +1603,11 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) value = smu_get_od_percentage(&(adev->smu), SMU_OD_MCLK); else if (adev->powerplay.pp_funcs->get_mclk_od) value = amdgpu_dpm_get_mclk_od(adev); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1733,7 +1624,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, int ret; long int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1747,8 +1638,6 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value); } else { @@ -1763,8 +1652,6 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, } } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1800,7 +1687,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, ssize_t size; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1809,8 +1696,6 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) size = smu_get_power_profile_mode(&adev->smu, buf); else if (adev->powerplay.pp_funcs->get_power_profile_mode) @@ -1818,8 +1703,6 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, else size = snprintf(buf, PAGE_SIZE, "\n"); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1844,7 +1727,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; tmp[0] = *(buf); @@ -1878,15 +1761,11 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) ret = smu_set_power_profile_mode(&adev->smu, parameter, parameter_size, true); else if (adev->powerplay.pp_funcs->set_power_profile_mode) ret = amdgpu_dpm_set_power_profile_mode(adev, parameter, parameter_size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1912,7 +1791,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1921,11 +1800,9 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, return r; } - down_read(&adev->reset_sem); /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1952,7 +1829,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1961,14 +1838,10 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, return r; } - down_read(&adev->reset_sem); - /* read the IP busy sensor */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -1999,7 +1872,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, uint64_t count0 = 0, count1 = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->flags & AMD_IS_APU) @@ -2014,12 +1887,8 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, return ret; } - down_read(&adev->reset_sem); - amdgpu_asic_get_pcie_usage(adev, &count0, &count1); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(ddev->dev); pm_runtime_put_autosuspend(ddev->dev); @@ -2044,7 +1913,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (adev->unique_id) @@ -2142,7 +2011,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, ssize_t size = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -2151,12 +2020,10 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, return ret; } - down_read(&adev->reset_sem); if (is_support_sw_smu(adev)) size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); else if (adev->powerplay.pp_funcs->get_gpu_metrics) size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); - up_read(&adev->reset_sem); if (size <= 0) goto out; @@ -2368,7 +2235,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, int channel = to_sensor_dev_attr(attr)->index; int r, temp = 0, size = sizeof(temp); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (channel >= PP_TEMP_MAX) @@ -2380,8 +2247,6 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, return r; } - down_read(&adev->reset_sem); - switch (channel) { case PP_TEMP_JUNCTION: /* get current junction temperature */ @@ -2403,8 +2268,6 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, break; } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2508,7 +2371,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2517,23 +2380,18 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2549,7 +2407,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err, ret; int value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2562,23 +2420,18 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, value); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, value); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2608,7 +2461,7 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, u32 value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2617,15 +2470,11 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - up_read(&adev->reset_sem); - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); pm_runtime_mark_last_busy(adev->ddev->dev); @@ -2666,7 +2515,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, int err; u32 speed = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2675,8 +2524,6 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_percent(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_percent) @@ -2684,8 +2531,6 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2705,7 +2550,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, int err; u32 speed = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2714,8 +2559,6 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &speed); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2723,8 +2566,6 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2743,7 +2584,7 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, u32 size = sizeof(min_rpm); int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2752,13 +2593,9 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, return r; } - down_read(&adev->reset_sem); - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, (void *)&min_rpm, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2777,7 +2614,7 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, u32 size = sizeof(max_rpm); int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2786,13 +2623,9 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, return r; } - down_read(&adev->reset_sem); - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, (void *)&max_rpm, &size); - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2810,7 +2643,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, int err; u32 rpm = 0; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2819,8 +2652,6 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_get_fan_speed_rpm(&adev->smu, &rpm); else if (adev->powerplay.pp_funcs->get_fan_speed_rpm) @@ -2828,8 +2659,6 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2848,7 +2677,7 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, u32 value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2857,15 +2686,11 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) pwm_mode = smu_get_fan_control_mode(&adev->smu); else pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - up_read(&adev->reset_sem); - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2879,8 +2704,6 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_set_fan_speed_rpm(&adev->smu, value); else if (adev->powerplay.pp_funcs->set_fan_speed_rpm) @@ -2888,8 +2711,6 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2907,7 +2728,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2916,23 +2737,18 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, return ret; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2949,7 +2765,7 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, int value; u32 pwm_mode; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2969,22 +2785,17 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_set_fan_control_mode(&adev->smu, pwm_mode); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); - up_read(&adev->reset_sem); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -2999,7 +2810,7 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, u32 vddgfx; int r, size = sizeof(vddgfx); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3008,11 +2819,9 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&vddgfx, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3038,7 +2847,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, u32 vddnb; int r, size = sizeof(vddnb); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; /* only APUs have vddnb */ @@ -3051,11 +2860,9 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&vddnb, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3082,7 +2889,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, int r, size = sizeof(u32); unsigned uw; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3091,11 +2898,9 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the voltage */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3125,7 +2930,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ssize_t size; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3134,8 +2939,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, return r; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, true); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -3146,8 +2949,6 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3163,7 +2964,7 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ssize_t size; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3172,8 +2973,6 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, return r; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) { smu_get_power_limit(&adev->smu, &limit, false); size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); @@ -3184,8 +2983,6 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3202,7 +2999,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, int err; u32 value; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; if (amdgpu_sriov_vf(adev)) @@ -3221,8 +3018,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, return err; } - down_read(&adev->reset_sem); - if (is_support_sw_smu(adev)) err = smu_set_power_limit(&adev->smu, value); else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_power_limit) @@ -3230,8 +3025,6 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, else err = -EINVAL; - up_read(&adev->reset_sem); - pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3249,7 +3042,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, uint32_t sclk; int r, size = sizeof(sclk); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3258,11 +3051,9 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&sclk, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -3288,7 +3079,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, uint32_t mclk; int r, size = sizeof(mclk); - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3297,11 +3088,9 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, return r; } - down_read(&adev->reset_sem); /* get the sclk */ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&mclk, &size); - up_read(&adev->reset_sem); pm_runtime_mark_last_busy(adev->ddev->dev); pm_runtime_put_autosuspend(adev->ddev->dev); @@ -4188,7 +3977,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) u32 flags = 0; int r; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EPERM; r = pm_runtime_get_sync(dev->dev); @@ -4204,7 +3993,6 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) return 0; } - down_read(&adev->reset_sem); if (!is_support_sw_smu(adev) && adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { mutex_lock(&adev->pm.mutex); @@ -4217,13 +4005,10 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) } else { r = amdgpu_debugfs_pm_info_pp(m, adev); } - up_read(&adev->reset_sem); if (r) goto out; - down_read(&adev->reset_sem); amdgpu_device_ip_get_clockgating_state(adev, &flags); - up_read(&adev->reset_sem); seq_printf(m, "Clock Gating Flags Mask: 0x%x\n", flags); amdgpu_parse_cg_state(m, flags); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 116a89990f39..aa1e77c60c0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1869,7 +1869,7 @@ static int psp_load_smu_fw(struct psp_context *psp) return 0; - if (amdgpu_in_reset(adev) && ras && ras->supported) { + if (adev->in_gpu_reset && ras && ras->supported) { ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); if (ret) { DRM_WARN("Failed to set MP1 state prepare for reload\n"); @@ -1984,7 +1984,7 @@ static int psp_load_fw(struct amdgpu_device *adev) int ret; struct psp_context *psp = &adev->psp; - if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { + if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ goto skip_memalloc; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index cd1403f83dcf..f09082578865 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2079,7 +2079,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, amdgpu_ras_request_reset_on_boot(adev, ras_block->block); return 0; - } else if (adev->in_suspend || amdgpu_in_reset(adev)) { + } else if (adev->in_suspend || adev->in_gpu_reset) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -2088,7 +2088,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, } /* in resume phase, no need to create ras fs node */ - if (adev->in_suspend || amdgpu_in_reset(adev)) + if (adev->in_suspend || adev->in_gpu_reset) return 0; if (ih_info->cb) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index c7421aa32946..2d502e98fad0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2098,7 +2098,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) uint64_t size; int r; - if (!adev->mman.initialized || amdgpu_in_reset(adev) || + if (!adev->mman.initialized || adev->in_gpu_reset || adev->mman.buffer_funcs_enabled == enable) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 039245c98ff8..183743c5fb7b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -628,8 +628,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ - if (!amdgpu_sriov_vf(adev) && - (amdgpu_in_reset(adev) || adev->in_suspend)) + if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index 1e211544f2dc..ae720a6dc5a0 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: - dev_warn(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1); + pr_err("failed to write reg %x wait reg %x\n", reg0, reg1); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index b2046c3a404d..f826945989c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -325,9 +325,9 @@ static inline bool is_virtual_machine(void) #define amdgpu_sriov_is_pp_one_vf(adev) \ ((adev)->virt.gim_feature & AMDGIM_FEATURE_PP_ONE_VF) #define amdgpu_sriov_is_debug(adev) \ - ((!amdgpu_in_reset(adev)) && adev->virt.tdr_debug) + ((!adev->in_gpu_reset) && adev->virt.tdr_debug) #define amdgpu_sriov_is_normal(adev) \ - ((!amdgpu_in_reset(adev)) && (!adev->virt.tdr_debug)) + ((!adev->in_gpu_reset) && (!adev->virt.tdr_debug)) bool amdgpu_virt_mmio_blocked(struct amdgpu_device *adev); void amdgpu_virt_init_setting(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 67a756f4337b..cd6e6eb7d966 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -372,7 +372,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo tmp->hive_id = adev->gmc.xgmi.hive_id; INIT_LIST_HEAD(&tmp->device_list); mutex_init(&tmp->hive_lock); - atomic_set(&tmp->in_reset, 0); + mutex_init(&tmp->reset_lock); task_barrier_init(&tmp->tb); if (lock) @@ -397,7 +397,6 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) hive->hi_req_gpu : adev; bool is_hi_req = pstate == AMDGPU_XGMI_PSTATE_MAX_VEGA20; bool init_low = hive->pstate == AMDGPU_XGMI_PSTATE_UNKNOWN; - bool locked; /* fw bug so temporarily disable pstate switching */ return 0; @@ -405,9 +404,7 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) if (!hive || adev->asic_type != CHIP_VEGA20) return 0; - locked = atomic_read(&hive->in_reset) ? false : true; - if (locked) - mutex_lock(&hive->hive_lock); + mutex_lock(&hive->hive_lock); if (is_hi_req) hive->hi_req_count++; @@ -442,8 +439,7 @@ int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) adev : NULL; } out: - if (locked) - mutex_unlock(&hive->hive_lock); + mutex_unlock(&hive->hive_lock); return ret; } @@ -598,6 +594,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) if(!(--hive->number_devices)){ amdgpu_xgmi_sysfs_destroy(adev, hive); mutex_destroy(&hive->hive_lock); + mutex_destroy(&hive->reset_lock); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 61720cd4a1ee..6999eab16a72 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -30,8 +30,7 @@ struct amdgpu_hive_info { uint64_t hive_id; struct list_head device_list; int number_devices; - struct mutex hive_lock; - atomic_t in_reset; + struct mutex hive_lock, reset_lock; struct kobject *kobj; struct device_attribute dev_attr; struct amdgpu_device *adev; diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c index 8341bd965202..4cfc786699c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/atom.c +++ b/drivers/gpu/drm/amd/amdgpu/atom.c @@ -755,7 +755,6 @@ static void atom_op_jump(atom_exec_context *ctx, int *ptr, int arg) /* jiffies wrap around we will just wait a little longer */ ctx->last_jump_jiffies = jiffies; } - schedule(); } else { ctx->last_jump = ctx->start + target; ctx->last_jump_jiffies = jiffies; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index de6e6de41867..e87d43537013 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6201,7 +6201,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) struct v10_gfx_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.gfx_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6213,7 +6213,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (amdgpu_in_reset(adev)) { + } else if (adev->in_gpu_reset) { /* reset mqd with the backup copy */ if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6566,7 +6566,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v10_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6602,7 +6602,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6612,7 +6612,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 7df567a6656d..14fd04b699da 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4633,7 +4633,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4670,7 +4670,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4682,7 +4682,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 93c63ff3b35e..2c5bb282cc01 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3686,7 +3686,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3724,7 +3724,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -3736,7 +3736,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); - } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ + } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3930,7 +3930,7 @@ static int gfx_v9_0_hw_fini(void *handle) /* Use deinitialize sequence from CAIL when unbinding device from driver, * otherwise KIQ is hanging when binding back */ - if (!amdgpu_in_reset(adev) && !adev->in_suspend) { + if (!adev->in_gpu_reset && !adev->in_suspend) { mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, adev->gfx.kiq.ring.me, adev->gfx.kiq.ring.pipe, @@ -4088,7 +4088,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) + if (r < 1 && (adev->in_gpu_reset || in_interrupt())) goto failed_kiq_read; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 9d3b1245a339..ec8c0af39553 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,7 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + !adev->in_gpu_reset) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -312,7 +312,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready || - amdgpu_in_reset(adev) || + adev->in_gpu_reset || ring->sched.ready == false) { gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0); mutex_unlock(&adev->mman.gtt_window_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 80c146df338a..3ce5c1d2fdf2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -434,7 +434,7 @@ static int gmc_v7_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 9ab65ca7df77..3e6615f9d39c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -635,7 +635,7 @@ static int gmc_v8_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, int vmid; unsigned int tmp; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; for (vmid = 1; vmid < 16; vmid++) { diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 773ee11b3d17..6a780b674018 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -501,7 +501,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + !adev->in_gpu_reset) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -596,7 +596,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; - if (amdgpu_in_reset(adev)) + if (adev->in_gpu_reset) return -EIO; if (ring->sched.ready) { @@ -633,8 +633,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - dev_info(adev->dev, - "wait for kiq fence error: %ld\n", r); + DRM_ERROR("wait for kiq fence error: %ld.\n", r); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index fe31cbeccfe9..5fd67e1cc2a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -238,16 +238,20 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; + int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the reset_sem to allow "amdgpu_job_timedout" + * we can unlock the lock_reset to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - down_read(&adev->reset_sem); + locked = mutex_trylock(&adev->lock_reset); + if (locked) + adev->in_gpu_reset = true; + do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -257,7 +261,10 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - up_read(&adev->reset_sem); + if (locked) { + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); + } /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 6f55172e8337..ce2bf1fb79ed 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -259,16 +259,20 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; + int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. * - * we can unlock the reset_sem to allow "amdgpu_job_timedout" + * we can unlock the lock_reset to allow "amdgpu_job_timedout" * to run gpu_recover() after FLR_NOTIFICATION_CMPL received * which means host side had finished this VF's FLR. */ - down_read(&adev->reset_sem); + locked = mutex_trylock(&adev->lock_reset); + if (locked) + adev->in_gpu_reset = true; + do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) goto flr_done; @@ -278,7 +282,10 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - up_read(&adev->reset_sem); + if (locked) { + adev->in_gpu_reset = false; + mutex_unlock(&adev->lock_reset); + } /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 7ad1537820b5..e0e60b0d0669 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -304,17 +304,15 @@ static void deallocate_vmid(struct device_queue_manager *dqm, struct qcm_process_device *qpd, struct queue *q) { - if (!dqm->is_resetting) { - /* On GFX v7, CP doesn't flush TC at dequeue */ - if (q->device->device_info->asic_family == CHIP_HAWAII) - if (flush_texture_cache_nocpsch(q->device, qpd)) - pr_err("Failed to flush TC\n"); + /* On GFX v7, CP doesn't flush TC at dequeue */ + if (q->device->device_info->asic_family == CHIP_HAWAII) + if (flush_texture_cache_nocpsch(q->device, qpd)) + pr_err("Failed to flush TC\n"); - kfd_flush_tlb(qpd_to_pdd(qpd)); + kfd_flush_tlb(qpd_to_pdd(qpd)); - /* Release the vmid mapping */ - set_pasid_vmid_mapping(dqm, 0, qpd->vmid); - } + /* Release the vmid mapping */ + set_pasid_vmid_mapping(dqm, 0, qpd->vmid); dqm->vmid_pasid[qpd->vmid] = 0; qpd->vmid = 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ee2258404c8f..40695d52e9a8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1551,10 +1551,6 @@ int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process, void kfd_flush_tlb(struct kfd_process_device *pdd) { struct kfd_dev *dev = pdd->dev; - struct device_queue_manager *dqm = dev->dqm; - - if (dqm->is_resetting) - return; if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { /* Nothing to flush until a VMID is assigned, which diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 031b7eb55356..653b4a0d51d8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1658,7 +1658,7 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - if (amdgpu_in_reset(adev)) { + if (adev->in_gpu_reset) { mutex_lock(&dm->dc_lock); dm->cached_dc_state = dc_copy_state(dm->dc->current_state); @@ -1844,7 +1844,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j; - if (amdgpu_in_reset(adev)) { + if (adev->in_gpu_reset) { dc_state = dm->cached_dc_state; r = dm_dmub_hw_init(adev); diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c index f87a73cb7ec5..7d17c4f1b489 100644 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c @@ -1110,7 +1110,7 @@ static int smu_disable_dpms(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; bool use_baco = !smu->is_apu && - ((amdgpu_in_reset(adev) && + ((adev->in_gpu_reset && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index da84012b7fd5..c7216362b68d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -489,7 +489,7 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; - bool use_baco = (amdgpu_in_reset(adev) && + bool use_baco = (adev->in_gpu_reset && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || (adev->in_runpm && amdgpu_asic_supports_baco(adev)); -- cgit v1.2.3 From 2e2f5dd51421648098bb4621719181b963d2d961 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 13 Aug 2020 14:35:35 +0800 Subject: drm/amdgpu: fix NULL pointer access issue when unloading driver When unloading driver by "modprobe -r amdgpu", one NULL pointer dereference bug occurs in ras debugfs releasing. The cause is the duplicated debugfs_remove, as drm debugfs_root dir has been cleaned up already by drm_minor_unregister. BUG: kernel NULL pointer dereference, address: 00000000000000a0 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 11 PID: 1526 Comm: modprobe Tainted: G OE 5.6.0-guchchen #1 Hardware name: System manufacturer System Product Name/TUF Z370-PLUS GAMING II, BIOS 0411 09/21/2018 RIP: 0010:down_write+0x15/0x40 Code: eb de e8 7e 17 72 ff cc cc cc cc cc cc cc cc cc cc cc cc cc cc 0f 1f 44 00 00 53 48 89 fb e8 92 d8 ff ff 31 c0 ba 01 00 00 00 48 0f b1 13 75 0f 65 48 8b 04 25 c0 8b 01 00 48 89 43 08 5b c3 RSP: 0018:ffffb1590386fcd0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00000000000000a0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffffffff85b2fcc2 RDI: 00000000000000a0 RBP: ffffb1590386fd30 R08: ffffffff85b2fcc2 R09: 000000000002b3c0 R10: ffff97a330618c40 R11: 00000000000005f6 R12: ffff97a3481beb40 R13: 00000000000000a0 R14: ffff97a3481beb40 R15: 0000000000000000 FS: 00007fb11a717540(0000) GS:ffff97a376cc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000a0 CR3: 00000004066d6006 CR4: 00000000003606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: simple_recursive_removal+0x63/0x370 ? debugfs_remove+0x60/0x60 debugfs_remove+0x40/0x60 amdgpu_ras_fini+0x82/0x230 [amdgpu] ? __kernfs_remove.part.17+0x101/0x1f0 ? kernfs_name_hash+0x12/0x80 amdgpu_device_fini+0x1c0/0x580 [amdgpu] amdgpu_driver_unload_kms+0x3e/0x70 [amdgpu] amdgpu_pci_remove+0x36/0x60 [amdgpu] pci_device_remove+0x3b/0xb0 device_release_driver_internal+0xe5/0x1c0 driver_detach+0x46/0x90 bus_remove_driver+0x58/0xd0 pci_unregister_driver+0x29/0x90 amdgpu_exit+0x11/0x25 [amdgpu] __x64_sys_delete_module+0x13d/0x210 do_syscall_64+0x5f/0x250 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Guchun Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index f09082578865..e437530fa808 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1278,7 +1278,6 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, if (!obj || !obj->ent) return; - debugfs_remove(obj->ent); obj->ent = NULL; put_obj(obj); } @@ -1292,7 +1291,6 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) amdgpu_ras_debugfs_remove(adev, &obj->head); } - debugfs_remove_recursive(con->dir); con->dir = NULL; } /* debugfs end */ -- cgit v1.2.3 From ae2bf61ff39e78ce926de37d22dc7d5159c610cd Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 13 Aug 2020 15:00:56 +0800 Subject: drm/amdgpu: guard ras debugfs creation/removal based on CONFIG_DEBUG_FS It can avoid potential build warn/error when CONFIG_DEBUG_FS is not set. Signed-off-by: Guchun Chen Reviewed-by: Tao Zhou Reviewed-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index e437530fa808..866373c95cae 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1246,6 +1246,7 @@ void amdgpu_ras_debugfs_create(struct amdgpu_device *adev, void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev) { +#if defined(CONFIG_DEBUG_FS) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_manager *obj; struct ras_fs_if fs_info; @@ -1268,6 +1269,7 @@ void amdgpu_ras_debugfs_create_all(struct amdgpu_device *adev) amdgpu_ras_debugfs_create(adev, &fs_info); } } +#endif } void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, @@ -1284,6 +1286,7 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) { +#if defined(CONFIG_DEBUG_FS) struct amdgpu_ras *con = amdgpu_ras_get_context(adev); struct ras_manager *obj, *tmp; @@ -1292,6 +1295,7 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) } con->dir = NULL; +#endif } /* debugfs end */ -- cgit v1.2.3 From bc8f830035304b3ba91d4dda2480f868f66fe230 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 14 Aug 2020 12:15:44 +0800 Subject: drm/amd/powerplay: suppress the kernel test robot warning Suppress the warning below: In file included from drivers/gpu/drm/amd/amdgpu/../powerplay/smu_cmn.c: >> drivers/gpu/drm/amd/powerplay/smu_cmn.c:485:9: warning: Identical condition 'ret', second condition is always false [identicalConditionAfterEarlyExit] return ret; ^ drivers/gpu/drm/amd/powerplay/smu_cmn.c:477:6: note: first condition if (ret) ^ drivers/gpu/drm/amd/powerplay/smu_cmn.c:485:9: note: second condition return ret; ^ Signed-off-by: Evan Quan Reported-by: kernel test robot Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/smu_cmn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c index 968b734baac0..a58ea08cd115 100644 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ b/drivers/gpu/drm/amd/powerplay/smu_cmn.c @@ -604,7 +604,7 @@ int smu_cmn_update_table(struct smu_context *smu, memcpy(table_data, table->cpu_addr, table_size); } - return ret; + return 0; } int smu_cmn_write_watermarks_table(struct smu_context *smu) -- cgit v1.2.3 From 171090dbc0d5e11b2c3207bdd6b4910255e7e61b Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 14 Aug 2020 16:34:15 +0800 Subject: drm/amd/pm: drop redundant MEM_TYPE_* macros As these are already defined in amdgpu_atombios.h. Otherwise, we may hit "redefined" compile warning. Signed-off-by: Evan Quan Reviewed-by: Feifei Xu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h index 3ee54f182943..76ed2e413594 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h @@ -26,15 +26,6 @@ #include "hwmgr.h" -#define MEM_TYPE_GDDR5 0x50 -#define MEM_TYPE_GDDR4 0x40 -#define MEM_TYPE_GDDR3 0x30 -#define MEM_TYPE_DDR2 0x20 -#define MEM_TYPE_GDDR1 0x10 -#define MEM_TYPE_DDR3 0xb0 -#define MEM_TYPE_MASK 0xF0 - - /* As returned from PowerConnectorDetectionTable. */ #define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80 #define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40 -- cgit v1.2.3 From b89e9eb681653868e3ecb0287f1cf65aaec853da Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 13:11:24 +0800 Subject: drm/amd/powerplay: optimize amdgpu_dpm_set_clockgating_by_smu() implementation Cover the implementation details from outside(of power part). Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 7 +++---- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 21 +++++++-------------- drivers/gpu/drm/amd/amdgpu/vi.c | 21 +++++++-------------- 4 files changed, 32 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 240c440cbe00..5e9baca556a4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1232,3 +1232,18 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) return ret; } + +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = 0; + + if (pp_funcs && pp_funcs->set_clockgating_by_smu) + ret = pp_funcs->set_clockgating_by_smu(pp_handle, + msg_id); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index cc16b5a3ac44..672b73ad08c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -341,10 +341,6 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ (adev)->powerplay.pp_handle, request)) -#define amdgpu_dpm_set_clockgating_by_smu(adev, msg_id) \ - ((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\ - (adev)->powerplay.pp_handle, msg_id)) - #define amdgpu_dpm_get_power_profile_mode(adev, buf) \ ((adev)->powerplay.pp_funcs->get_power_profile_mode(\ (adev)->powerplay.pp_handle, buf)) @@ -546,4 +542,7 @@ int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 14fd04b699da..003982f8eb7f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5880,8 +5880,7 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -5902,8 +5901,7 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; @@ -5932,8 +5930,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) { @@ -5952,8 +5949,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_3D, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -5974,8 +5970,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) { @@ -5990,8 +5985,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_RLC, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) { @@ -6005,8 +5999,7 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CP, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index f6f2ed0830b1..b4e4a7a19d19 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1507,8 +1507,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_MC, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_SDMA_MGCG)) { @@ -1526,8 +1525,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_SDMA, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_MGCG)) { @@ -1545,8 +1543,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_HDP, pp_support_state, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } @@ -1560,8 +1557,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_LS, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG) { if (state == AMD_CG_STATE_UNGATE) @@ -1573,8 +1569,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_CG, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_DRM_LS) { @@ -1588,8 +1583,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_DRM, PP_STATE_SUPPORT_LS, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG) { @@ -1603,8 +1597,7 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_ROM, PP_STATE_SUPPORT_CG, pp_state); - if (adev->powerplay.pp_funcs->set_clockgating_by_smu) - amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; } -- cgit v1.2.3 From 70bdb6ed222053bb0e4694f255a685cc3f4981e0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 12 Aug 2020 13:19:25 +0800 Subject: drm/amd/powerplay: drop unnecessary pp_funcs checker It's redundant. Also, the callers should not care about the implementation details. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | 11 +++-------- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 5 ++--- drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 3 +-- 3 files changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 12247a32f9ef..d3e51d361179 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -136,9 +136,7 @@ static int acp_poweroff(struct generic_pm_domain *genpd) * 2. power off the acp tiles * 3. check and enter ulv state */ - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); } return 0; } @@ -157,8 +155,7 @@ static int acp_poweron(struct generic_pm_domain *genpd) * 2. turn on acp clock * 3. power on acp tiles */ - if (adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, false); } return 0; } @@ -529,9 +526,7 @@ static int acp_set_powergating_state(void *handle, struct amdgpu_device *adev = (struct amdgpu_device *)handle; bool enable = (state == AMD_PG_STATE_GATE); - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 003982f8eb7f..3b7127202420 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -5343,10 +5343,9 @@ static int gfx_v8_0_late_init(void *handle) static void gfx_v8_0_enable_gfx_static_mg_power_gating(struct amdgpu_device *adev, bool enable) { - if (((adev->asic_type == CHIP_POLARIS11) || + if ((adev->asic_type == CHIP_POLARIS11) || (adev->asic_type == CHIP_POLARIS12) || - (adev->asic_type == CHIP_VEGAM)) && - adev->powerplay.pp_funcs->set_powergating_by_smu) + (adev->asic_type == CHIP_VEGAM)) /* Send msg to SMU via Powerplay */ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, enable); diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index e24d6e533be3..45a902b1acb7 100755 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -304,8 +304,7 @@ static void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, return; if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_powergating_by_smu) - amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); + amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); } } -- cgit v1.2.3 From 20d3c28ce4e28ac4df9d139054aecb65ee5a9ee4 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 13 Aug 2020 11:51:11 +0800 Subject: drm/amd/powerplay: optimize i2c bus access implementation The caller needs not care about the internal details how the powerplay API implemented. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 15 +++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 3 +++ drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c | 15 ++------------- 3 files changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 5e9baca556a4..3465fddff666 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -1247,3 +1247,18 @@ int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, return ret; } + +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = -EOPNOTSUPP; + + if (pp_funcs && pp_funcs->smu_i2c_bus_access) + ret = pp_funcs->smu_i2c_bus_access(pp_handle, + acquire); + + return ret; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 672b73ad08c2..5a2344f839f2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -545,4 +545,7 @@ int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, uint32_t msg_id); +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c index d55bf64770c4..7fb240c4990c 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c @@ -508,14 +508,9 @@ static bool smu_v11_0_i2c_bus_lock(struct i2c_adapter *control) struct amdgpu_device *adev = to_amdgpu_device(control); /* Send PPSMC_MSG_RequestI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access) - goto Fail; - - - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle, true)) + if (!amdgpu_dpm_smu_i2c_bus_access(adev, true)) return true; -Fail: return false; } @@ -523,16 +518,10 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control) { struct amdgpu_device *adev = to_amdgpu_device(control); - /* Send PPSMC_MSG_RequestI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access) - goto Fail; - /* Send PPSMC_MSG_ReleaseI2CBus */ - if (!adev->powerplay.pp_funcs->smu_i2c_bus_access(adev->powerplay.pp_handle, - false)) + if (!amdgpu_dpm_smu_i2c_bus_access(adev, false)) return true; -Fail: return false; } -- cgit v1.2.3 From e9372d23715d6802fd6d3763cb19c5a0c07ad641 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 13 Aug 2020 13:37:52 +0800 Subject: drm/amd/powerplay: put those exposed power interfaces in amdgpu_dpm.c As other power interfaces. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 425 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 14 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 423 ------------------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h | 8 - 4 files changed, 439 insertions(+), 431 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index 3465fddff666..e480b54f6545 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c @@ -28,6 +28,11 @@ #include "amdgpu_dpm.h" #include "atom.h" #include "amd_pcie.h" +#include "amdgpu_display.h" +#include "hwmgr.h" +#include + +#define WIDTH_4K 3840 void amdgpu_dpm_print_class_info(u32 class, u32 class2) { @@ -1262,3 +1267,423 @@ int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, return ret; } + +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) +{ + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + if (power_supply_is_system_supplied() > 0) + adev->pm.ac_power = true; + else + adev->pm.ac_power = false; + if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->enable_bapm) + amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); + mutex_unlock(&adev->pm.mutex); + + if (is_support_sw_smu(adev)) + smu_set_ac_dc(&adev->smu); + } +} + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + + if (!data || !size) + return -EINVAL; + + if (is_support_sw_smu(adev)) + ret = smu_read_sensor(&adev->smu, sensor, data, size); + else { + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) + ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, + sensor, data, size); + else + ret = -EINVAL; + } + + return ret; +} + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work) +{ + struct amdgpu_device *adev = + container_of(work, struct amdgpu_device, + pm.dpm.thermal.work); + /* switch to the thermal state */ + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + int temp, size = sizeof(temp); + + if (!adev->pm.dpm_enabled) + return; + + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, + (void *)&temp, &size)) { + if (temp < adev->pm.dpm.thermal.min_temp) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } else { + if (adev->pm.dpm.thermal.high_to_low) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } + mutex_lock(&adev->pm.mutex); + if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) + adev->pm.dpm.thermal_active = true; + else + adev->pm.dpm.thermal_active = false; + adev->pm.dpm.state = dpm_state; + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); +} + +static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type dpm_state) +{ + int i; + struct amdgpu_ps *ps; + u32 ui_class; + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? + true : false; + + /* check if the vblank period is too short to adjust the mclk */ + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { + if (amdgpu_dpm_vblank_too_short(adev)) + single_display = false; + } + + /* certain older asics have a separare 3D performance state, + * so try that first if the user selected performance + */ + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; + /* balanced states don't exist at the moment */ + if (dpm_state == POWER_STATE_TYPE_BALANCED) + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + +restart_search: + /* Pick the best power state based on current conditions */ + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + ps = &adev->pm.dpm.ps[i]; + ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; + switch (dpm_state) { + /* user states */ + case POWER_STATE_TYPE_BATTERY: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_BALANCED: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_PERFORMANCE: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + /* internal states */ + case POWER_STATE_TYPE_INTERNAL_UVD: + if (adev->pm.dpm.uvd_ps) + return adev->pm.dpm.uvd_ps; + else + break; + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_BOOT: + return adev->pm.dpm.boot_ps; + case POWER_STATE_TYPE_INTERNAL_THERMAL: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ACPI: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ULV: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_3DPERF: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + return ps; + break; + default: + break; + } + } + /* use a fallback state if we didn't match */ + switch (dpm_state) { + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (adev->pm.dpm.uvd_ps) { + return adev->pm.dpm.uvd_ps; + } else { + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + } + case POWER_STATE_TYPE_INTERNAL_THERMAL: + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_ACPI: + dpm_state = POWER_STATE_TYPE_BATTERY; + goto restart_search; + case POWER_STATE_TYPE_BATTERY: + case POWER_STATE_TYPE_BALANCED: + case POWER_STATE_TYPE_INTERNAL_3DPERF: + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + default: + break; + } + + return NULL; +} + +static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) +{ + struct amdgpu_ps *ps; + enum amd_pm_state_type dpm_state; + int ret; + bool equal = false; + + /* if dpm init failed */ + if (!adev->pm.dpm_enabled) + return; + + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { + /* add other state override checks here */ + if ((!adev->pm.dpm.thermal_active) && + (!adev->pm.dpm.uvd_active)) + adev->pm.dpm.state = adev->pm.dpm.user_state; + } + dpm_state = adev->pm.dpm.state; + + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); + if (ps) + adev->pm.dpm.requested_ps = ps; + else + return; + + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + printk("switching from power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); + printk("switching to power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); + } + + /* update whether vce is active */ + ps->vce_active = adev->pm.dpm.vce_active; + if (adev->powerplay.pp_funcs->display_configuration_changed) + amdgpu_dpm_display_configuration_changed(adev); + + ret = amdgpu_dpm_pre_set_power_state(adev); + if (ret) + return; + + if (adev->powerplay.pp_funcs->check_state_equal) { + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) + equal = false; + } + + if (equal) + return; + + amdgpu_dpm_set_power_state(adev); + amdgpu_dpm_post_set_power_state(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; + + if (adev->powerplay.pp_funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) { + enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; + /* force low perf level for thermal */ + amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + /* save the user's level */ + adev->pm.dpm.forced_level = level; + } else { + /* otherwise, user selected level */ + amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + } + } +} + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) +{ + int i = 0; + + if (!adev->pm.dpm_enabled) + return; + + if (adev->mode_info.num_crtc) + amdgpu_display_bandwidth_update(adev); + + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->sched.ready) + amdgpu_fence_wait_empty(ring); + } + + if (is_support_sw_smu(adev)) { + struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; + smu_handle_task(&adev->smu, + smu_dpm->dpm_level, + AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, + true); + } else { + if (adev->powerplay.pp_funcs->dispatch_tasks) { + if (!amdgpu_device_has_dc_support(adev)) { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; + adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); + adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ + if (adev->pm.pm_display_cfg.vrefresh > 120) + adev->pm.pm_display_cfg.min_vblank_time = 0; + if (adev->powerplay.pp_funcs->display_configuration_change) + adev->powerplay.pp_funcs->display_configuration_change( + adev->powerplay.pp_handle, + &adev->pm.pm_display_cfg); + mutex_unlock(&adev->pm.mutex); + } + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); + } else { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + amdgpu_dpm_change_power_state_locked(adev); + mutex_unlock(&adev->pm.mutex); + } + } +} + +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + } else { + adev->pm.dpm.uvd_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); + if (ret) + DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + + /* enable/disable Low Memory PState for UVD (4k videos) */ + if (adev->asic_type == CHIP_STONEY && + adev->uvd.decode_image_width >= WIDTH_4K) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if (hwmgr && hwmgr->hwmgr_func && + hwmgr->hwmgr_func->update_nbdpm_pstate) + hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, + !enable, + true); + } + } +} + +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; + } else { + adev->pm.dpm.vce_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); + if (ret) + DRM_ERROR("Dpm %s vce failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + } +} + +void amdgpu_pm_print_power_states(struct amdgpu_device *adev) +{ + int i; + + if (adev->powerplay.pp_funcs->print_power_state == NULL) + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) + amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); + +} + +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); + if (ret) + DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", + enable ? "enable" : "disable", ret); +} + +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) +{ + int r; + + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { + r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); + if (r) { + pr_err("smu firmware loading failed\n"); + return r; + } + *smu_version = adev->pm.fw_version; + } + return 0; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index 5a2344f839f2..dff4a5f99bb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -548,4 +548,18 @@ int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, bool acquire); +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size); + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work); + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); +void amdgpu_pm_print_power_states(struct amdgpu_device *adev); +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 65ad174bb976..5fc6a9a13096 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -29,17 +29,14 @@ #include "amdgpu_drv.h" #include "amdgpu_pm.h" #include "amdgpu_dpm.h" -#include "amdgpu_display.h" #include "amdgpu_smu.h" #include "atom.h" -#include #include #include #include #include #include #include "hwmgr.h" -#define WIDTH_4K 3840 static const struct cg_flag_name clocks[] = { {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, @@ -81,45 +78,6 @@ static const struct hwmon_temp_label { {PP_TEMP_MEM, "mem"}, }; -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) -{ - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - if (power_supply_is_system_supplied() > 0) - adev->pm.ac_power = true; - else - adev->pm.ac_power = false; - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->enable_bapm) - amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); - mutex_unlock(&adev->pm.mutex); - - if (is_support_sw_smu(adev)) - smu_set_ac_dc(&adev->smu); - } -} - -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if (!data || !size) - return -EINVAL; - - if (is_support_sw_smu(adev)) - ret = smu_read_sensor(&adev->smu, sensor, data, size); - else { - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) - ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, - sensor, data, size); - else - ret = -EINVAL; - } - - return ret; -} - /** * DOC: power_dpm_state * @@ -3425,338 +3383,6 @@ static const struct attribute_group *hwmon_groups[] = { NULL }; -void amdgpu_dpm_thermal_work_handler(struct work_struct *work) -{ - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, - pm.dpm.thermal.work); - /* switch to the thermal state */ - enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; - int temp, size = sizeof(temp); - - if (!adev->pm.dpm_enabled) - return; - - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, - (void *)&temp, &size)) { - if (temp < adev->pm.dpm.thermal.min_temp) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } else { - if (adev->pm.dpm.thermal.high_to_low) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } - mutex_lock(&adev->pm.mutex); - if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) - adev->pm.dpm.thermal_active = true; - else - adev->pm.dpm.thermal_active = false; - adev->pm.dpm.state = dpm_state; - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); -} - -static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amd_pm_state_type dpm_state) -{ - int i; - struct amdgpu_ps *ps; - u32 ui_class; - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? - true : false; - - /* check if the vblank period is too short to adjust the mclk */ - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { - if (amdgpu_dpm_vblank_too_short(adev)) - single_display = false; - } - - /* certain older asics have a separare 3D performance state, - * so try that first if the user selected performance - */ - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; - /* balanced states don't exist at the moment */ - if (dpm_state == POWER_STATE_TYPE_BALANCED) - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - -restart_search: - /* Pick the best power state based on current conditions */ - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - ps = &adev->pm.dpm.ps[i]; - ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; - switch (dpm_state) { - /* user states */ - case POWER_STATE_TYPE_BATTERY: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_BALANCED: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_PERFORMANCE: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - /* internal states */ - case POWER_STATE_TYPE_INTERNAL_UVD: - if (adev->pm.dpm.uvd_ps) - return adev->pm.dpm.uvd_ps; - else - break; - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_BOOT: - return adev->pm.dpm.boot_ps; - case POWER_STATE_TYPE_INTERNAL_THERMAL: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ACPI: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ULV: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_3DPERF: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - return ps; - break; - default: - break; - } - } - /* use a fallback state if we didn't match */ - switch (dpm_state) { - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (adev->pm.dpm.uvd_ps) { - return adev->pm.dpm.uvd_ps; - } else { - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - } - case POWER_STATE_TYPE_INTERNAL_THERMAL: - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_ACPI: - dpm_state = POWER_STATE_TYPE_BATTERY; - goto restart_search; - case POWER_STATE_TYPE_BATTERY: - case POWER_STATE_TYPE_BALANCED: - case POWER_STATE_TYPE_INTERNAL_3DPERF: - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - default: - break; - } - - return NULL; -} - -static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) -{ - struct amdgpu_ps *ps; - enum amd_pm_state_type dpm_state; - int ret; - bool equal = false; - - /* if dpm init failed */ - if (!adev->pm.dpm_enabled) - return; - - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { - /* add other state override checks here */ - if ((!adev->pm.dpm.thermal_active) && - (!adev->pm.dpm.uvd_active)) - adev->pm.dpm.state = adev->pm.dpm.user_state; - } - dpm_state = adev->pm.dpm.state; - - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); - if (ps) - adev->pm.dpm.requested_ps = ps; - else - return; - - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { - printk("switching from power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); - printk("switching to power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); - } - - /* update whether vce is active */ - ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) - amdgpu_dpm_display_configuration_changed(adev); - - ret = amdgpu_dpm_pre_set_power_state(adev); - if (ret) - return; - - if (adev->powerplay.pp_funcs->check_state_equal) { - if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) - equal = false; - } - - if (equal) - return; - - amdgpu_dpm_set_power_state(adev); - amdgpu_dpm_post_set_power_state(adev); - - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - - if (adev->powerplay.pp_funcs->force_performance_level) { - if (adev->pm.dpm.thermal_active) { - enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; - /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); - /* save the user's level */ - adev->pm.dpm.forced_level = level; - } else { - /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); - } - } -} - -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; - } else { - adev->pm.dpm.uvd_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); - if (ret) - DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - - /* enable/disable Low Memory PState for UVD (4k videos) */ - if (adev->asic_type == CHIP_STONEY && - adev->uvd.decode_image_width >= WIDTH_4K) { - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->hwmgr_func && - hwmgr->hwmgr_func->update_nbdpm_pstate) - hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, - !enable, - true); - } - } -} - -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; - } else { - adev->pm.dpm.vce_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); - if (ret) - DRM_ERROR("Dpm %s vce failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - } -} - -void amdgpu_pm_print_power_states(struct amdgpu_device *adev) -{ - int i; - - if (adev->powerplay.pp_funcs->print_power_state == NULL) - return; - - for (i = 0; i < adev->pm.dpm.num_ps; i++) - amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - -} - -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); - if (ret) - DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", - enable ? "enable" : "disable", ret); -} - -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) -{ - int r; - - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { - r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); - if (r) { - pr_err("smu firmware loading failed\n"); - return r; - } - *smu_version = adev->pm.fw_version; - } - return 0; -} - int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) { int ret; @@ -3817,55 +3443,6 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) amdgpu_device_attr_remove_groups(adev, &adev->pm.pm_attr_list); } -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) -{ - int i = 0; - - if (!adev->pm.dpm_enabled) - return; - - if (adev->mode_info.num_crtc) - amdgpu_display_bandwidth_update(adev); - - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->sched.ready) - amdgpu_fence_wait_empty(ring); - } - - if (is_support_sw_smu(adev)) { - struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; - smu_handle_task(&adev->smu, - smu_dpm->dpm_level, - AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, - true); - } else { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - if (!amdgpu_device_has_dc_support(adev)) { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; - adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); - adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ - if (adev->pm.pm_display_cfg.vrefresh > 120) - adev->pm.pm_display_cfg.min_vblank_time = 0; - if (adev->powerplay.pp_funcs->display_configuration_change) - adev->powerplay.pp_funcs->display_configuration_change( - adev->powerplay.pp_handle, - &adev->pm.pm_display_cfg); - mutex_unlock(&adev->pm.mutex); - } - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); - } else { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - amdgpu_dpm_change_power_state_locked(adev); - mutex_unlock(&adev->pm.mutex); - } - } -} - /* * Debugfs info */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h index d9ae2b49a402..45a22e101d15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h @@ -79,18 +79,10 @@ struct amdgpu_device_attr_entry { amdgpu_get_##_name, NULL, \ _flags, ##__VA_ARGS__) -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); int amdgpu_pm_sysfs_init(struct amdgpu_device *adev); int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev); void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev); void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev); -void amdgpu_pm_print_power_states(struct amdgpu_device *adev); -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); -void amdgpu_dpm_thermal_work_handler(struct work_struct *work); -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); -- cgit v1.2.3 From e098bc9612c2b60f94920461d71c92962a916e73 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Thu, 13 Aug 2020 16:39:25 +0800 Subject: drm/amd/pm: optimize the power related source code layout The target is to provide a clear entry point(for power routines). Also this can help to maintain a clear view about the frameworks used on different ASICs. Hopefully all these can make power part more friendly to play with. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | 1689 ---- drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h | 565 -- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | 3613 --------- drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h | 89 - drivers/gpu/drm/amd/amdgpu/cik_dpm.h | 29 - drivers/gpu/drm/amd/amdgpu/kv_dpm.c | 3382 -------- drivers/gpu/drm/amd/amdgpu/kv_dpm.h | 229 - drivers/gpu/drm/amd/amdgpu/kv_smc.c | 218 - drivers/gpu/drm/amd/amdgpu/ppsmc.h | 200 - drivers/gpu/drm/amd/amdgpu/r600_dpm.h | 127 - drivers/gpu/drm/amd/amdgpu/si_dpm.c | 8079 -------------------- drivers/gpu/drm/amd/amdgpu/si_dpm.h | 1015 --- drivers/gpu/drm/amd/amdgpu/si_smc.c | 273 - drivers/gpu/drm/amd/amdgpu/sislands_smc.h | 423 - drivers/gpu/drm/amd/pm/Makefile | 46 + drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 1689 ++++ drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3613 +++++++++ drivers/gpu/drm/amd/pm/inc/amd_powerplay.h | 35 + drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 565 ++ drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h | 89 + drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 806 ++ drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h | 127 + drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h | 186 + drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h | 412 + drivers/gpu/drm/amd/pm/inc/hardwaremanager.h | 469 ++ drivers/gpu/drm/amd/pm/inc/hwmgr.h | 824 ++ drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h | 1793 +++++ drivers/gpu/drm/amd/pm/inc/power_state.h | 196 + drivers/gpu/drm/amd/pm/inc/pp_debug.h | 62 + drivers/gpu/drm/amd/pm/inc/pp_endian.h | 38 + drivers/gpu/drm/amd/pm/inc/pp_thermal.h | 44 + drivers/gpu/drm/amd/pm/inc/ppinterrupt.h | 46 + drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h | 94 + drivers/gpu/drm/amd/pm/inc/smu10.h | 190 + drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h | 116 + drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h | 893 +++ .../gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h | 931 +++ .../gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h | 1126 +++ .../amd/pm/inc/smu11_driver_if_sienna_cichlid.h | 1242 +++ drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h | 232 + drivers/gpu/drm/amd/pm/inc/smu7.h | 189 + drivers/gpu/drm/amd/pm/inc/smu71.h | 510 ++ drivers/gpu/drm/amd/pm/inc/smu71_discrete.h | 631 ++ drivers/gpu/drm/amd/pm/inc/smu72.h | 687 ++ drivers/gpu/drm/amd/pm/inc/smu72_discrete.h | 783 ++ drivers/gpu/drm/amd/pm/inc/smu73.h | 720 ++ drivers/gpu/drm/amd/pm/inc/smu73_discrete.h | 799 ++ drivers/gpu/drm/amd/pm/inc/smu74.h | 833 ++ drivers/gpu/drm/amd/pm/inc/smu74_discrete.h | 849 ++ drivers/gpu/drm/amd/pm/inc/smu75.h | 760 ++ drivers/gpu/drm/amd/pm/inc/smu75_discrete.h | 886 +++ drivers/gpu/drm/amd/pm/inc/smu7_common.h | 54 + drivers/gpu/drm/amd/pm/inc/smu7_discrete.h | 515 ++ drivers/gpu/drm/amd/pm/inc/smu7_fusion.h | 300 + drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h | 421 + drivers/gpu/drm/amd/pm/inc/smu8.h | 72 + drivers/gpu/drm/amd/pm/inc/smu8_fusion.h | 135 + drivers/gpu/drm/amd/pm/inc/smu9.h | 148 + drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h | 486 ++ drivers/gpu/drm/amd/pm/inc/smu_types.h | 274 + drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h | 169 + drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h | 101 + drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 278 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h | 139 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h | 196 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h | 136 + drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h | 167 + drivers/gpu/drm/amd/pm/inc/smu_v12_0.h | 66 + drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h | 106 + drivers/gpu/drm/amd/pm/inc/smumgr.h | 116 + drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h | 420 + drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h | 144 + drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h | 767 ++ drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h | 123 + drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h | 131 + drivers/gpu/drm/amd/pm/powerplay/Makefile | 39 + drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c | 1680 ++++ drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h | 29 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile | 44 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c | 195 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h | 29 + .../gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c | 120 + .../gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h | 63 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c | 196 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h | 29 + .../drm/amd/pm/powerplay/hwmgr/hardwaremanager.c | 544 ++ drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c | 564 ++ drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h | 116 + .../gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c | 222 + .../gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h | 29 + .../gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c | 1288 ++++ .../gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h | 46 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c | 296 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h | 40 + .../gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c | 1562 ++++ .../gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h | 328 + .../gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c | 710 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h | 244 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h | 555 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c | 64 + .../gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h | 31 + .../gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h | 436 ++ .../amd/pm/powerplay/hwmgr/process_pptables_v1_0.c | 1337 ++++ .../amd/pm/powerplay/hwmgr/process_pptables_v1_0.h | 35 + .../drm/amd/pm/powerplay/hwmgr/processpptables.c | 1732 +++++ .../drm/amd/pm/powerplay/hwmgr/processpptables.h | 50 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 1404 ++++ .../gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h | 321 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h | 43 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c | 91 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h | 32 + .../amd/pm/powerplay/hwmgr/smu7_clockpowergating.c | 437 ++ .../amd/pm/powerplay/hwmgr/smu7_clockpowergating.h | 38 + .../drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h | 55 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 5215 +++++++++++++ .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h | 368 + .../drm/amd/pm/powerplay/hwmgr/smu7_powertune.c | 1239 +++ .../drm/amd/pm/powerplay/hwmgr/smu7_powertune.h | 62 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c | 471 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h | 58 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c | 2049 +++++ .../gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h | 311 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c | 66 + drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h | 31 + .../gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c | 767 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h | 228 + .../gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c | 231 + .../gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h | 29 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c | 121 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h | 29 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 5482 +++++++++++++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h | 446 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h | 43 + .../drm/amd/pm/powerplay/hwmgr/vega10_powertune.c | 1392 ++++ .../drm/amd/pm/powerplay/hwmgr/vega10_powertune.h | 82 + .../drm/amd/pm/powerplay/hwmgr/vega10_pptable.h | 445 ++ .../pm/powerplay/hwmgr/vega10_processpptables.c | 1398 ++++ .../pm/powerplay/hwmgr/vega10_processpptables.h | 63 + .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 657 ++ .../drm/amd/pm/powerplay/hwmgr/vega10_thermal.h | 80 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c | 119 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h | 29 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c | 2868 +++++++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h | 458 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h | 41 + .../drm/amd/pm/powerplay/hwmgr/vega12_pptable.h | 109 + .../pm/powerplay/hwmgr/vega12_processpptables.c | 402 + .../pm/powerplay/hwmgr/vega12_processpptables.h | 58 + .../drm/amd/pm/powerplay/hwmgr/vega12_thermal.c | 316 + .../drm/amd/pm/powerplay/hwmgr/vega12_thermal.h | 66 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c | 122 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h | 33 + .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 4409 +++++++++++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h | 590 ++ .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h | 36 + .../drm/amd/pm/powerplay/hwmgr/vega20_powertune.c | 72 + .../drm/amd/pm/powerplay/hwmgr/vega20_powertune.h | 32 + .../drm/amd/pm/powerplay/hwmgr/vega20_pptable.h | 142 + .../pm/powerplay/hwmgr/vega20_processpptables.c | 972 +++ .../pm/powerplay/hwmgr/vega20_processpptables.h | 31 + .../drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 357 + .../drm/amd/pm/powerplay/hwmgr/vega20_thermal.h | 71 + drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c | 3382 ++++++++ drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h | 229 + drivers/gpu/drm/amd/pm/powerplay/kv_smc.c | 218 + drivers/gpu/drm/amd/pm/powerplay/ppsmc.h | 200 + drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h | 127 + drivers/gpu/drm/amd/pm/powerplay/si_dpm.c | 8079 ++++++++++++++++++++ drivers/gpu/drm/amd/pm/powerplay/si_dpm.h | 1015 +++ drivers/gpu/drm/amd/pm/powerplay/si_smc.c | 273 + drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h | 423 + drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile | 33 + .../gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 2965 +++++++ .../gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h | 76 + .../gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c | 2673 +++++++ .../gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h | 49 + .../drm/amd/pm/powerplay/smumgr/iceland_smumgr.c | 2686 +++++++ .../drm/amd/pm/powerplay/smumgr/iceland_smumgr.h | 70 + .../drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c | 2590 +++++++ .../drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h | 66 + .../gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c | 322 + .../gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h | 50 + .../gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c | 601 ++ .../gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h | 83 + .../gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c | 910 +++ .../gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h | 99 + .../gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c | 180 + .../gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h | 32 + drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c | 247 + .../gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c | 3268 ++++++++ .../gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h | 74 + .../drm/amd/pm/powerplay/smumgr/vega10_smumgr.c | 396 + .../drm/amd/pm/powerplay/smumgr/vega10_smumgr.h | 51 + .../drm/amd/pm/powerplay/smumgr/vega12_smumgr.c | 416 + .../drm/amd/pm/powerplay/smumgr/vega12_smumgr.h | 57 + .../drm/amd/pm/powerplay/smumgr/vega20_smumgr.c | 646 ++ .../drm/amd/pm/powerplay/smumgr/vega20_smumgr.h | 63 + .../gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c | 2302 ++++++ .../gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h | 75 + drivers/gpu/drm/amd/pm/swsmu/Makefile | 36 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2671 +++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile | 33 + drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 2405 ++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h | 72 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 2674 +++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h | 54 + .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 2810 +++++++ .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h | 34 + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 1987 +++++ drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile | 31 + drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 1085 +++ drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h | 33 + drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c | 288 + drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c | 678 ++ drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h | 91 + drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 97 + drivers/gpu/drm/amd/powerplay/Makefile | 44 - drivers/gpu/drm/amd/powerplay/amd_powerplay.c | 1680 ---- drivers/gpu/drm/amd/powerplay/amdgpu_smu.c | 2671 ------- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 2405 ------ drivers/gpu/drm/amd/powerplay/arcturus_ppt.h | 72 - drivers/gpu/drm/amd/powerplay/hwmgr/Makefile | 44 - drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c | 195 - drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h | 29 - drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c | 120 - drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h | 63 - drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c | 196 - drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h | 29 - .../gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c | 544 -- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c | 564 -- drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h | 116 - drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c | 222 - drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h | 29 - .../gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c | 1288 ---- .../gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h | 46 - drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c | 296 - drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h | 40 - drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c | 1562 ---- drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h | 328 - drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c | 710 -- drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h | 244 - drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h | 555 -- drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c | 64 - drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h | 31 - drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h | 436 -- .../amd/powerplay/hwmgr/process_pptables_v1_0.c | 1337 ---- .../amd/powerplay/hwmgr/process_pptables_v1_0.h | 35 - .../gpu/drm/amd/powerplay/hwmgr/processpptables.c | 1732 ----- .../gpu/drm/amd/powerplay/hwmgr/processpptables.h | 50 - drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 1404 ---- drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h | 321 - drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h | 43 - drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c | 91 - drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h | 32 - .../amd/powerplay/hwmgr/smu7_clockpowergating.c | 437 -- .../amd/powerplay/hwmgr/smu7_clockpowergating.h | 38 - .../drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h | 55 - drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 5215 ------------- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h | 368 - .../gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c | 1239 --- .../gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h | 62 - drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c | 471 -- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h | 58 - drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c | 2049 ----- drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h | 311 - drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.c | 66 - drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h | 31 - drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c | 767 -- drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h | 228 - drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c | 231 - drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h | 29 - drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c | 121 - drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h | 29 - drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | 5482 ------------- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h | 446 -- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h | 43 - .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c | 1392 ---- .../gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h | 82 - .../gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h | 445 -- .../amd/powerplay/hwmgr/vega10_processpptables.c | 1398 ---- .../amd/powerplay/hwmgr/vega10_processpptables.h | 63 - .../gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 657 -- .../gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h | 80 - drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c | 119 - drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h | 29 - drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | 2868 ------- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h | 458 -- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h | 41 - .../gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h | 109 - .../amd/powerplay/hwmgr/vega12_processpptables.c | 402 - .../amd/powerplay/hwmgr/vega12_processpptables.h | 58 - .../gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c | 316 - .../gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h | 66 - drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c | 122 - drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h | 33 - drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | 4409 ----------- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h | 590 -- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h | 36 - .../gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c | 72 - .../gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h | 32 - .../gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h | 142 - .../amd/powerplay/hwmgr/vega20_processpptables.c | 972 --- .../amd/powerplay/hwmgr/vega20_processpptables.h | 31 - .../gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c | 357 - .../gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h | 71 - drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h | 35 - drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h | 806 -- drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h | 127 - drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h | 186 - drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h | 412 - .../gpu/drm/amd/powerplay/inc/hardwaremanager.h | 469 -- drivers/gpu/drm/amd/powerplay/inc/hwmgr.h | 824 -- .../gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h | 1793 ----- drivers/gpu/drm/amd/powerplay/inc/power_state.h | 196 - drivers/gpu/drm/amd/powerplay/inc/pp_debug.h | 62 - drivers/gpu/drm/amd/powerplay/inc/pp_endian.h | 38 - drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h | 44 - drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h | 46 - drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h | 94 - drivers/gpu/drm/amd/powerplay/inc/smu10.h | 190 - .../gpu/drm/amd/powerplay/inc/smu10_driver_if.h | 116 - .../gpu/drm/amd/powerplay/inc/smu11_driver_if.h | 893 --- .../amd/powerplay/inc/smu11_driver_if_arcturus.h | 931 --- .../drm/amd/powerplay/inc/smu11_driver_if_navi10.h | 1126 --- .../powerplay/inc/smu11_driver_if_sienna_cichlid.h | 1242 --- .../gpu/drm/amd/powerplay/inc/smu12_driver_if.h | 232 - drivers/gpu/drm/amd/powerplay/inc/smu7.h | 189 - drivers/gpu/drm/amd/powerplay/inc/smu71.h | 510 -- drivers/gpu/drm/amd/powerplay/inc/smu71_discrete.h | 631 -- drivers/gpu/drm/amd/powerplay/inc/smu72.h | 687 -- drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h | 783 -- drivers/gpu/drm/amd/powerplay/inc/smu73.h | 720 -- drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h | 799 -- drivers/gpu/drm/amd/powerplay/inc/smu74.h | 833 -- drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h | 849 -- drivers/gpu/drm/amd/powerplay/inc/smu75.h | 760 -- drivers/gpu/drm/amd/powerplay/inc/smu75_discrete.h | 886 --- drivers/gpu/drm/amd/powerplay/inc/smu7_common.h | 54 - drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h | 515 -- drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h | 300 - drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h | 421 - drivers/gpu/drm/amd/powerplay/inc/smu8.h | 72 - drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h | 135 - drivers/gpu/drm/amd/powerplay/inc/smu9.h | 148 - drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h | 486 -- drivers/gpu/drm/amd/powerplay/inc/smu_types.h | 274 - .../gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h | 169 - .../gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h | 101 - drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h | 278 - .../gpu/drm/amd/powerplay/inc/smu_v11_0_7_ppsmc.h | 139 - .../drm/amd/powerplay/inc/smu_v11_0_7_pptable.h | 196 - .../gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h | 136 - .../gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h | 167 - drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h | 66 - .../gpu/drm/amd/powerplay/inc/smu_v12_0_ppsmc.h | 106 - drivers/gpu/drm/amd/powerplay/inc/smumgr.h | 116 - drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h | 420 - drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h | 144 - .../drm/amd/powerplay/inc/vega12/smu9_driver_if.h | 767 -- drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h | 123 - drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h | 131 - drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 2674 ------- drivers/gpu/drm/amd/powerplay/navi10_ppt.h | 54 - drivers/gpu/drm/amd/powerplay/renoir_ppt.c | 1085 --- drivers/gpu/drm/amd/powerplay/renoir_ppt.h | 33 - drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 2810 ------- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h | 34 - drivers/gpu/drm/amd/powerplay/smu_cmn.c | 678 -- drivers/gpu/drm/amd/powerplay/smu_cmn.h | 91 - drivers/gpu/drm/amd/powerplay/smu_internal.h | 97 - drivers/gpu/drm/amd/powerplay/smu_v11_0.c | 1987 ----- drivers/gpu/drm/amd/powerplay/smu_v12_0.c | 288 - drivers/gpu/drm/amd/powerplay/smumgr/Makefile | 33 - drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 2965 ------- drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h | 76 - drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c | 2673 ------- drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h | 49 - .../gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c | 2686 ------- .../gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h | 70 - .../drm/amd/powerplay/smumgr/polaris10_smumgr.c | 2590 ------- .../drm/amd/powerplay/smumgr/polaris10_smumgr.h | 66 - .../gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c | 322 - .../gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h | 50 - drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c | 601 -- drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h | 83 - drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | 910 --- drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h | 99 - drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c | 180 - drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h | 32 - drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c | 247 - .../gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c | 3268 -------- .../gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h | 74 - .../gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c | 396 - .../gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h | 51 - .../gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c | 416 - .../gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h | 57 - .../gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c | 646 -- .../gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h | 63 - .../gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c | 2302 ------ .../gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h | 75 - 401 files changed, 126855 insertions(+), 126718 deletions(-) delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/cik_dpm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/kv_dpm.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/kv_dpm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/kv_smc.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/ppsmc.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/r600_dpm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/si_dpm.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/si_dpm.h delete mode 100644 drivers/gpu/drm/amd/amdgpu/si_smc.c delete mode 100644 drivers/gpu/drm/amd/amdgpu/sislands_smc.h create mode 100644 drivers/gpu/drm/amd/pm/Makefile create mode 100644 drivers/gpu/drm/amd/pm/amdgpu_dpm.c create mode 100644 drivers/gpu/drm/amd/pm/amdgpu_pm.c create mode 100644 drivers/gpu/drm/amd/pm/inc/amd_powerplay.h create mode 100644 drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h create mode 100644 drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h create mode 100644 drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h create mode 100644 drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/hardwaremanager.h create mode 100644 drivers/gpu/drm/amd/pm/inc/hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h create mode 100644 drivers/gpu/drm/amd/pm/inc/power_state.h create mode 100644 drivers/gpu/drm/amd/pm/inc/pp_debug.h create mode 100644 drivers/gpu/drm/amd/pm/inc/pp_endian.h create mode 100644 drivers/gpu/drm/amd/pm/inc/pp_thermal.h create mode 100644 drivers/gpu/drm/amd/pm/inc/ppinterrupt.h create mode 100644 drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu10.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu7.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu71.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu71_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu72.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu72_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu73.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu73_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu74.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu74_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu75.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu75_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu7_common.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu7_discrete.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu7_fusion.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu7_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu8.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu8_fusion.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu9.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu9_driver_if.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_types.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_cz.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_ucode_xfer_vi.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v11_0.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v11_0_7_pptable.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v11_0_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v11_0_pptable.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v12_0.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smu_v12_0_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h create mode 100644 drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/Makefile create mode 100644 drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/kv_smc.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/ppsmc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/si_dpm.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/si_dpm.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/si_smc.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c create mode 100644 drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/Makefile create mode 100644 drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h create mode 100644 drivers/gpu/drm/amd/pm/swsmu/smu_internal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/Makefile delete mode 100644 drivers/gpu/drm/amd/powerplay/amd_powerplay.c delete mode 100644 drivers/gpu/drm/amd/powerplay/amdgpu_smu.c delete mode 100644 drivers/gpu/drm/amd/powerplay/arcturus_ppt.c delete mode 100644 drivers/gpu/drm/amd/powerplay/arcturus_ppt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/Makefile delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c delete mode 100644 drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/hwmgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/power_state.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/pp_debug.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/pp_endian.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu10.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu7.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu71.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu71_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu72.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu73.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu74.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu74_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu75.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu75_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu7_common.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu7_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu8.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu9.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_types.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_7_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v11_0_pptable.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v12_0.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smu_v12_0_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h delete mode 100644 drivers/gpu/drm/amd/powerplay/navi10_ppt.c delete mode 100644 drivers/gpu/drm/amd/powerplay/navi10_ppt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/renoir_ppt.c delete mode 100644 drivers/gpu/drm/amd/powerplay/renoir_ppt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c delete mode 100644 drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smu_cmn.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smu_cmn.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smu_internal.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smu_v11_0.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smu_v12_0.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/Makefile delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c delete mode 100644 drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index dec1927ca75d..39976c7b100c 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -30,7 +30,7 @@ FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME) ccflags-y := -I$(FULL_AMD_PATH)/include/asic_reg \ -I$(FULL_AMD_PATH)/include \ -I$(FULL_AMD_PATH)/amdgpu \ - -I$(FULL_AMD_PATH)/powerplay/inc \ + -I$(FULL_AMD_PATH)/pm/inc \ -I$(FULL_AMD_PATH)/acp/include \ -I$(FULL_AMD_DISPLAY_PATH) \ -I$(FULL_AMD_DISPLAY_PATH)/include \ @@ -47,7 +47,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_encoders.o amdgpu_display.o amdgpu_i2c.o \ amdgpu_fb.o amdgpu_gem.o amdgpu_ring.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o amdgpu_test.o \ - amdgpu_pm.o atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ + atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ amdgpu_dma_buf.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ @@ -60,10 +60,10 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu-$(CONFIG_PERF_EVENTS) += amdgpu_pmu.o # add asic specific block -amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o \ dce_v8_0.o gfx_v7_0.o cik_sdma.o uvd_v4_2.o vce_v2_0.o -amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o si_dpm.o si_smc.o \ +amdgpu-$(CONFIG_DRM_AMDGPU_SI)+= si.o gmc_v6_0.o gfx_v6_0.o si_ih.o si_dma.o dce_v6_0.o \ uvd_v3_1.o amdgpu-y += \ @@ -105,10 +105,6 @@ amdgpu-y += \ psp_v11_0.o \ psp_v12_0.o -# add SMC block -amdgpu-y += \ - amdgpu_dpm.o - # add DCE block amdgpu-y += \ dce_v10_0.o \ @@ -212,7 +208,7 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_mn.o -include $(FULL_AMD_PATH)/powerplay/Makefile +include $(FULL_AMD_PATH)/pm/Makefile amdgpu-y += $(AMD_POWERPLAY_FILES) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c deleted file mode 100644 index e480b54f6545..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ /dev/null @@ -1,1689 +0,0 @@ -/* - * Copyright 2011 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Alex Deucher - */ - -#include "amdgpu.h" -#include "amdgpu_atombios.h" -#include "amdgpu_i2c.h" -#include "amdgpu_dpm.h" -#include "atom.h" -#include "amd_pcie.h" -#include "amdgpu_display.h" -#include "hwmgr.h" -#include - -#define WIDTH_4K 3840 - -void amdgpu_dpm_print_class_info(u32 class, u32 class2) -{ - const char *s; - - switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { - case ATOM_PPLIB_CLASSIFICATION_UI_NONE: - default: - s = "none"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: - s = "battery"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: - s = "balanced"; - break; - case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: - s = "performance"; - break; - } - printk("\tui class: %s\n", s); - printk("\tinternal class:"); - if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && - (class2 == 0)) - pr_cont(" none"); - else { - if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) - pr_cont(" boot"); - if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - pr_cont(" thermal"); - if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - pr_cont(" limited_pwr"); - if (class & ATOM_PPLIB_CLASSIFICATION_REST) - pr_cont(" rest"); - if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) - pr_cont(" forced"); - if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - pr_cont(" 3d_perf"); - if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) - pr_cont(" ovrdrv"); - if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - pr_cont(" uvd"); - if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) - pr_cont(" 3d_low"); - if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) - pr_cont(" acpi"); - if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - pr_cont(" uvd_hd2"); - if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - pr_cont(" uvd_hd"); - if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - pr_cont(" uvd_sd"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - pr_cont(" limited_pwr2"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - pr_cont(" ulv"); - if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - pr_cont(" uvd_mvc"); - } - pr_cont("\n"); -} - -void amdgpu_dpm_print_cap_info(u32 caps) -{ - printk("\tcaps:"); - if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) - pr_cont(" single_disp"); - if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) - pr_cont(" video"); - if (caps & ATOM_PPLIB_DISALLOW_ON_DC) - pr_cont(" no_dc"); - pr_cont("\n"); -} - -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - printk("\tstatus:"); - if (rps == adev->pm.dpm.current_ps) - pr_cont(" c"); - if (rps == adev->pm.dpm.requested_ps) - pr_cont(" r"); - if (rps == adev->pm.dpm.boot_ps) - pr_cont(" b"); - pr_cont("\n"); -} - -void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) -{ - struct drm_device *ddev = adev->ddev; - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - - adev->pm.dpm.new_active_crtcs = 0; - adev->pm.dpm.new_active_crtc_count = 0; - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (amdgpu_crtc->enabled) { - adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); - adev->pm.dpm.new_active_crtc_count++; - } - } - } -} - - -u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) -{ - struct drm_device *dev = adev->ddev; - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - u32 vblank_in_pixels; - u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ - - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { - vblank_in_pixels = - amdgpu_crtc->hw_mode.crtc_htotal * - (amdgpu_crtc->hw_mode.crtc_vblank_end - - amdgpu_crtc->hw_mode.crtc_vdisplay + - (amdgpu_crtc->v_border * 2)); - - vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock; - break; - } - } - } - - return vblank_time_us; -} - -u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) -{ - struct drm_device *dev = adev->ddev; - struct drm_crtc *crtc; - struct amdgpu_crtc *amdgpu_crtc; - u32 vrefresh = 0; - - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { - vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); - break; - } - } - } - - return vrefresh; -} - -bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor) -{ - switch (sensor) { - case THERMAL_TYPE_RV6XX: - case THERMAL_TYPE_RV770: - case THERMAL_TYPE_EVERGREEN: - case THERMAL_TYPE_SUMO: - case THERMAL_TYPE_NI: - case THERMAL_TYPE_SI: - case THERMAL_TYPE_CI: - case THERMAL_TYPE_KV: - return true; - case THERMAL_TYPE_ADT7473_WITH_INTERNAL: - case THERMAL_TYPE_EMC2103_WITH_INTERNAL: - return false; /* need special handling */ - case THERMAL_TYPE_NONE: - case THERMAL_TYPE_EXTERNAL: - case THERMAL_TYPE_EXTERNAL_GPIO: - default: - return false; - } -} - -union power_info { - struct _ATOM_POWERPLAY_INFO info; - struct _ATOM_POWERPLAY_INFO_V2 info_2; - struct _ATOM_POWERPLAY_INFO_V3 info_3; - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; - struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; - struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; -}; - -union fan_info { - struct _ATOM_PPLIB_FANTABLE fan; - struct _ATOM_PPLIB_FANTABLE2 fan2; - struct _ATOM_PPLIB_FANTABLE3 fan3; -}; - -static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, - ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) -{ - u32 size = atom_table->ucNumEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - int i; - ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; - - amdgpu_table->entries = kzalloc(size, GFP_KERNEL); - if (!amdgpu_table->entries) - return -ENOMEM; - - entry = &atom_table->entries[0]; - for (i = 0; i < atom_table->ucNumEntries; i++) { - amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | - (entry->ucClockHigh << 16); - amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); - } - amdgpu_table->count = atom_table->ucNumEntries; - - return 0; -} - -int amdgpu_get_platform_caps(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - union power_info *power_info; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); - adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); - adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); - - return 0; -} - -/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 - -int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - union power_info *power_info; - union fan_info *fan_info; - ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - int ret, i; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - /* fan table */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { - if (power_info->pplib3.usFanTableOffset) { - fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib3.usFanTableOffset)); - adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; - adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); - adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); - adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); - adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); - adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); - adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); - if (fan_info->fan.ucFanTableFormat >= 2) - adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); - else - adev->pm.dpm.fan.t_max = 10900; - adev->pm.dpm.fan.cycle_delay = 100000; - if (fan_info->fan.ucFanTableFormat >= 3) { - adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; - adev->pm.dpm.fan.default_max_fan_pwm = - le16_to_cpu(fan_info->fan3.usFanPWMMax); - adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; - adev->pm.dpm.fan.fan_output_sensitivity = - le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); - } - adev->pm.dpm.fan.ucode_fan_control = true; - } - } - - /* clock dependancy tables, shedding tables */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { - if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); - ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, - dep_table); - if (ret) { - amdgpu_free_extended_power_table(adev); - return ret; - } - } - if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { - ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = - (ATOM_PPLIB_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); - if (clk_v->ucNumEntries) { - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = - le16_to_cpu(clk_v->entries[0].usSclkLow) | - (clk_v->entries[0].ucSclkHigh << 16); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = - le16_to_cpu(clk_v->entries[0].usMclkLow) | - (clk_v->entries[0].ucMclkHigh << 16); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = - le16_to_cpu(clk_v->entries[0].usVddc); - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = - le16_to_cpu(clk_v->entries[0].usVddci); - } - } - if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { - ATOM_PPLIB_PhaseSheddingLimits_Table *psl = - (ATOM_PPLIB_PhaseSheddingLimits_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); - ATOM_PPLIB_PhaseSheddingLimits_Record *entry; - - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = - kcalloc(psl->ucNumEntries, - sizeof(struct amdgpu_phase_shedding_limits_entry), - GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - - entry = &psl->entries[0]; - for (i = 0; i < psl->ucNumEntries; i++) { - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = - le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = - le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); - adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); - } - adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = - psl->ucNumEntries; - } - } - - /* cac data */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { - adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); - adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); - adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; - adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); - if (adev->pm.dpm.tdp_od_limit) - adev->pm.dpm.power_control = true; - else - adev->pm.dpm.power_control = false; - adev->pm.dpm.tdp_adjustment = 0; - adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); - adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); - adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); - if (power_info->pplib5.usCACLeakageTableOffset) { - ATOM_PPLIB_CAC_Leakage_Table *cac_table = - (ATOM_PPLIB_CAC_Leakage_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); - ATOM_PPLIB_CAC_Leakage_Record *entry; - u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); - adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - entry = &cac_table->entries[0]; - for (i = 0; i < cac_table->ucNumEntries; i++) { - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = - le16_to_cpu(entry->usVddc1); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = - le16_to_cpu(entry->usVddc2); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = - le16_to_cpu(entry->usVddc3); - } else { - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = - le16_to_cpu(entry->usVddc); - adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = - le32_to_cpu(entry->ulLeakageValue); - } - entry = (ATOM_PPLIB_CAC_Leakage_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); - } - adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; - } - } - - /* ext tables */ - if (le16_to_cpu(power_info->pplib.usTableSize) >= - sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { - ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && - ext_hdr->usVCETableOffset) { - VCEClockInfoArray *array = (VCEClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1); - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = - (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + - 1 + array->ucNumEntries * sizeof(VCEClockInfo)); - ATOM_PPLIB_VCE_State_Table *states = - (ATOM_PPLIB_VCE_State_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + - 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + - 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); - ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; - ATOM_PPLIB_VCE_State_Record *state_entry; - VCEClockInfo *vce_clk; - u32 size = limits->numEntries * - sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - state_entry = &states->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - vce_clk = (VCEClockInfo *) - ((u8 *)&array->entries[0] + - (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); - adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); - } - adev->pm.dpm.num_of_vce_states = - states->numEntries > AMD_MAX_VCE_LEVELS ? - AMD_MAX_VCE_LEVELS : states->numEntries; - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { - vce_clk = (VCEClockInfo *) - ((u8 *)&array->entries[0] + - (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); - adev->pm.dpm.vce_states[i].evclk = - le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); - adev->pm.dpm.vce_states[i].ecclk = - le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); - adev->pm.dpm.vce_states[i].clk_idx = - state_entry->ucClockInfoIndex & 0x3f; - adev->pm.dpm.vce_states[i].pstate = - (state_entry->ucClockInfoIndex & 0xc0) >> 6; - state_entry = (ATOM_PPLIB_VCE_State_Record *) - ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && - ext_hdr->usUVDTableOffset) { - UVDClockInfoArray *array = (UVDClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = - (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + - 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); - ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - UVDClockInfo *uvd_clk = (UVDClockInfo *) - ((u8 *)&array->entries[0] + - (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = - le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = - le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); - adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && - ext_hdr->usSAMUTableOffset) { - ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = - (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); - ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = - le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); - adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && - ext_hdr->usPPMTableOffset) { - ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPPMTableOffset)); - adev->pm.dpm.dyn_state.ppm_table = - kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.ppm_table) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; - adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = - le16_to_cpu(ppm->usCpuCoreNumber); - adev->pm.dpm.dyn_state.ppm_table->platform_tdp = - le32_to_cpu(ppm->ulPlatformTDP); - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = - le32_to_cpu(ppm->ulSmallACPlatformTDP); - adev->pm.dpm.dyn_state.ppm_table->platform_tdc = - le32_to_cpu(ppm->ulPlatformTDC); - adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = - le32_to_cpu(ppm->ulSmallACPlatformTDC); - adev->pm.dpm.dyn_state.ppm_table->apu_tdp = - le32_to_cpu(ppm->ulApuTDP); - adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = - le32_to_cpu(ppm->ulDGpuTDP); - adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = - le32_to_cpu(ppm->ulDGpuUlvPower); - adev->pm.dpm.dyn_state.ppm_table->tj_max = - le32_to_cpu(ppm->ulTjmax); - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && - ext_hdr->usACPTableOffset) { - ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = - (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usACPTableOffset) + 1); - ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; - u32 size = limits->numEntries * - sizeof(struct amdgpu_clock_voltage_dependency_entry); - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = - kzalloc(size, GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = - limits->numEntries; - entry = &limits->entries[0]; - for (i = 0; i < limits->numEntries; i++) { - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = - le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); - adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = - le16_to_cpu(entry->usVoltage); - entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) - ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); - } - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && - ext_hdr->usPowerTuneTableOffset) { - u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - ATOM_PowerTune_Table *pt; - adev->pm.dpm.dyn_state.cac_tdp_table = - kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.cac_tdp_table) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - if (rev > 0) { - ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = - ppt->usMaximumPowerDeliveryLimit; - pt = &ppt->power_tune_table; - } else { - ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); - adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; - pt = &ppt->power_tune_table; - } - adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); - adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = - le16_to_cpu(pt->usConfigurableTDP); - adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); - adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = - le16_to_cpu(pt->usBatteryPowerLimit); - adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = - le16_to_cpu(pt->usSmallPowerLimit); - adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = - le16_to_cpu(pt->usLowCACLeakage); - adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = - le16_to_cpu(pt->usHighCACLeakage); - } - if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && - ext_hdr->usSclkVddgfxTableOffset) { - dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); - ret = amdgpu_parse_clk_voltage_dep_table( - &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, - dep_table); - if (ret) { - kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); - return ret; - } - } - } - - return 0; -} - -void amdgpu_free_extended_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; - - kfree(dyn_state->vddc_dependency_on_sclk.entries); - kfree(dyn_state->vddci_dependency_on_mclk.entries); - kfree(dyn_state->vddc_dependency_on_mclk.entries); - kfree(dyn_state->mvdd_dependency_on_mclk.entries); - kfree(dyn_state->cac_leakage_table.entries); - kfree(dyn_state->phase_shedding_limits_table.entries); - kfree(dyn_state->ppm_table); - kfree(dyn_state->cac_tdp_table); - kfree(dyn_state->vce_clock_voltage_dependency_table.entries); - kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); - kfree(dyn_state->samu_clock_voltage_dependency_table.entries); - kfree(dyn_state->acp_clock_voltage_dependency_table.entries); - kfree(dyn_state->vddgfx_dependency_on_sclk.entries); -} - -static const char *pp_lib_thermal_controller_names[] = { - "NONE", - "lm63", - "adm1032", - "adm1030", - "max6649", - "lm64", - "f75375", - "RV6xx", - "RV770", - "adt7473", - "NONE", - "External GPIO", - "Evergreen", - "emc2103", - "Sumo", - "Northern Islands", - "Southern Islands", - "lm96163", - "Sea Islands", - "Kaveri/Kabini", -}; - -void amdgpu_add_thermal_controller(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - ATOM_PPLIB_POWERPLAYTABLE *power_table; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - ATOM_PPLIB_THERMALCONTROLLER *controller; - struct amdgpu_i2c_bus_rec i2c_bus; - u16 data_offset; - u8 frev, crev; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return; - power_table = (ATOM_PPLIB_POWERPLAYTABLE *) - (mode_info->atom_context->bios + data_offset); - controller = &power_table->sThermalController; - - /* add the i2c bus for thermal/fan chip */ - if (controller->ucType > 0) { - if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) - adev->pm.no_fan = true; - adev->pm.fan_pulses_per_revolution = - controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - if (adev->pm.fan_pulses_per_revolution) { - adev->pm.fan_min_rpm = controller->ucFanMinRPM; - adev->pm.fan_max_rpm = controller->ucFanMaxRPM; - } - if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_RV770; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_NI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_SI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_CI; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { - DRM_INFO("Internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_KV; - } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { - DRM_INFO("External GPIO thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; - } else if (controller->ucType == - ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { - DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; - } else if (controller->ucType == - ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { - DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; - } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { - DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", - pp_lib_thermal_controller_names[controller->ucType], - controller->ucI2cAddress >> 1, - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; - i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); - adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); - if (adev->pm.i2c_bus) { - struct i2c_board_info info = { }; - const char *name = pp_lib_thermal_controller_names[controller->ucType]; - info.addr = controller->ucI2cAddress >> 1; - strlcpy(info.type, name, sizeof(info.type)); - i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); - } - } else { - DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", - controller->ucType, - controller->ucI2cAddress >> 1, - (controller->ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); - } - } -} - -enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, - u32 sys_mask, - enum amdgpu_pcie_gen asic_gen, - enum amdgpu_pcie_gen default_gen) -{ - switch (asic_gen) { - case AMDGPU_PCIE_GEN1: - return AMDGPU_PCIE_GEN1; - case AMDGPU_PCIE_GEN2: - return AMDGPU_PCIE_GEN2; - case AMDGPU_PCIE_GEN3: - return AMDGPU_PCIE_GEN3; - default: - if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) && - (default_gen == AMDGPU_PCIE_GEN3)) - return AMDGPU_PCIE_GEN3; - else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) && - (default_gen == AMDGPU_PCIE_GEN2)) - return AMDGPU_PCIE_GEN2; - else - return AMDGPU_PCIE_GEN1; - } - return AMDGPU_PCIE_GEN1; -} - -struct amd_vce_state* -amdgpu_get_vce_clock_state(void *handle, u32 idx) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (idx < adev->pm.dpm.num_of_vce_states) - return &adev->pm.dpm.vce_states[idx]; - - return NULL; -} - -int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) -{ - uint32_t clk_freq; - int ret = 0; - if (is_support_sw_smu(adev)) { - ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK, - low ? &clk_freq : NULL, - !low ? &clk_freq : NULL); - if (ret) - return 0; - return clk_freq * 100; - - } else { - return (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low)); - } -} - -int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low) -{ - uint32_t clk_freq; - int ret = 0; - if (is_support_sw_smu(adev)) { - ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK, - low ? &clk_freq : NULL, - !low ? &clk_freq : NULL); - if (ret) - return 0; - return clk_freq * 100; - - } else { - return (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low)); - } -} - -int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) -{ - int ret = 0; - bool swsmu = is_support_sw_smu(adev); - - switch (block_type) { - case AMD_IP_BLOCK_TYPE_UVD: - case AMD_IP_BLOCK_TYPE_VCE: - if (swsmu) { - ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); - } else if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) { - /* - * TODO: need a better lock mechanism - * - * Here adev->pm.mutex lock protection is enforced on - * UVD and VCE cases only. Since for other cases, there - * may be already lock protection in amdgpu_pm.c. - * This is a quick fix for the deadlock issue below. - * NFO: task ocltst:2028 blocked for more than 120 seconds. - * Tainted: G OE 5.0.0-37-generic #40~18.04.1-Ubuntu - * echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. - * cltst D 0 2028 2026 0x00000000 - * all Trace: - * __schedule+0x2c0/0x870 - * schedule+0x2c/0x70 - * schedule_preempt_disabled+0xe/0x10 - * __mutex_lock.isra.9+0x26d/0x4e0 - * __mutex_lock_slowpath+0x13/0x20 - * ? __mutex_lock_slowpath+0x13/0x20 - * mutex_lock+0x2f/0x40 - * amdgpu_dpm_set_powergating_by_smu+0x64/0xe0 [amdgpu] - * gfx_v8_0_enable_gfx_static_mg_power_gating+0x3c/0x70 [amdgpu] - * gfx_v8_0_set_powergating_state+0x66/0x260 [amdgpu] - * amdgpu_device_ip_set_powergating_state+0x62/0xb0 [amdgpu] - * pp_dpm_force_performance_level+0xe7/0x100 [amdgpu] - * amdgpu_set_dpm_forced_performance_level+0x129/0x330 [amdgpu] - */ - mutex_lock(&adev->pm.mutex); - ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( - (adev)->powerplay.pp_handle, block_type, gate)); - mutex_unlock(&adev->pm.mutex); - } - break; - case AMD_IP_BLOCK_TYPE_GFX: - case AMD_IP_BLOCK_TYPE_VCN: - case AMD_IP_BLOCK_TYPE_SDMA: - if (swsmu) - ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); - else if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( - (adev)->powerplay.pp_handle, block_type, gate)); - break; - case AMD_IP_BLOCK_TYPE_JPEG: - if (swsmu) - ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); - break; - case AMD_IP_BLOCK_TYPE_GMC: - case AMD_IP_BLOCK_TYPE_ACP: - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_powergating_by_smu) - ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( - (adev)->powerplay.pp_handle, block_type, gate)); - break; - default: - break; - } - - return ret; -} - -int amdgpu_dpm_baco_enter(struct amdgpu_device *adev) -{ - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - int ret = 0; - - if (is_support_sw_smu(adev)) { - ret = smu_baco_enter(smu); - } else { - if (!pp_funcs || !pp_funcs->set_asic_baco_state) - return -ENOENT; - - /* enter BACO state */ - ret = pp_funcs->set_asic_baco_state(pp_handle, 1); - } - - return ret; -} - -int amdgpu_dpm_baco_exit(struct amdgpu_device *adev) -{ - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - int ret = 0; - - if (is_support_sw_smu(adev)) { - ret = smu_baco_exit(smu); - } else { - if (!pp_funcs || !pp_funcs->set_asic_baco_state) - return -ENOENT; - - /* exit BACO state */ - ret = pp_funcs->set_asic_baco_state(pp_handle, 0); - } - - return ret; -} - -int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, - enum pp_mp1_state mp1_state) -{ - int ret = 0; - - if (is_support_sw_smu(adev)) { - ret = smu_set_mp1_state(&adev->smu, mp1_state); - } else if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_mp1_state) { - ret = adev->powerplay.pp_funcs->set_mp1_state( - adev->powerplay.pp_handle, - mp1_state); - } - - return ret; -} - -bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) -{ - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - bool baco_cap; - - if (is_support_sw_smu(adev)) { - return smu_baco_is_support(smu); - } else { - if (!pp_funcs || !pp_funcs->get_asic_baco_capability) - return false; - - if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap)) - return false; - - return baco_cap ? true : false; - } -} - -int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) -{ - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev)) { - return smu_mode2_reset(smu); - } else { - if (!pp_funcs || !pp_funcs->asic_reset_mode_2) - return -ENOENT; - - return pp_funcs->asic_reset_mode_2(pp_handle); - } -} - -int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) -{ - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - int ret = 0; - - dev_info(adev->dev, "GPU BACO reset\n"); - - if (is_support_sw_smu(adev)) { - ret = smu_baco_enter(smu); - if (ret) - return ret; - - ret = smu_baco_exit(smu); - if (ret) - return ret; - } else { - if (!pp_funcs - || !pp_funcs->set_asic_baco_state) - return -ENOENT; - - /* enter BACO state */ - ret = pp_funcs->set_asic_baco_state(pp_handle, 1); - if (ret) - return ret; - - /* exit BACO state */ - ret = pp_funcs->set_asic_baco_state(pp_handle, 0); - if (ret) - return ret; - } - - return 0; -} - -bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) -{ - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev)) - return smu_mode1_reset_is_support(smu); - - return false; -} - -int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) -{ - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev)) - return smu_mode1_reset(smu); - - return -EOPNOTSUPP; -} - -int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, - enum PP_SMC_POWER_PROFILE type, - bool en) -{ - int ret = 0; - - if (is_support_sw_smu(adev)) - ret = smu_switch_power_profile(&adev->smu, type, en); - else if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->switch_power_profile) - ret = adev->powerplay.pp_funcs->switch_power_profile( - adev->powerplay.pp_handle, type, en); - - return ret; -} - -int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, - uint32_t pstate) -{ - int ret = 0; - - if (is_support_sw_smu(adev)) - ret = smu_set_xgmi_pstate(&adev->smu, pstate); - else if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->set_xgmi_pstate) - ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, - pstate); - - return ret; -} - -int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, - uint32_t cstate) -{ - int ret = 0; - const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; - void *pp_handle = adev->powerplay.pp_handle; - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev)) - ret = smu_set_df_cstate(smu, cstate); - else if (pp_funcs && - pp_funcs->set_df_cstate) - ret = pp_funcs->set_df_cstate(pp_handle, cstate); - - return ret; -} - -int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) -{ - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev)) - return smu_allow_xgmi_power_down(smu, en); - - return 0; -} - -int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) -{ - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = - adev->powerplay.pp_funcs; - struct smu_context *smu = &adev->smu; - int ret = 0; - - if (is_support_sw_smu(adev)) - ret = smu_enable_mgpu_fan_boost(smu); - else if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) - ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); - - return ret; -} - -int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, - uint32_t msg_id) -{ - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = - adev->powerplay.pp_funcs; - int ret = 0; - - if (pp_funcs && pp_funcs->set_clockgating_by_smu) - ret = pp_funcs->set_clockgating_by_smu(pp_handle, - msg_id); - - return ret; -} - -int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, - bool acquire) -{ - void *pp_handle = adev->powerplay.pp_handle; - const struct amd_pm_funcs *pp_funcs = - adev->powerplay.pp_funcs; - int ret = -EOPNOTSUPP; - - if (pp_funcs && pp_funcs->smu_i2c_bus_access) - ret = pp_funcs->smu_i2c_bus_access(pp_handle, - acquire); - - return ret; -} - -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) -{ - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - if (power_supply_is_system_supplied() > 0) - adev->pm.ac_power = true; - else - adev->pm.ac_power = false; - if (adev->powerplay.pp_funcs && - adev->powerplay.pp_funcs->enable_bapm) - amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); - mutex_unlock(&adev->pm.mutex); - - if (is_support_sw_smu(adev)) - smu_set_ac_dc(&adev->smu); - } -} - -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if (!data || !size) - return -EINVAL; - - if (is_support_sw_smu(adev)) - ret = smu_read_sensor(&adev->smu, sensor, data, size); - else { - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) - ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, - sensor, data, size); - else - ret = -EINVAL; - } - - return ret; -} - -void amdgpu_dpm_thermal_work_handler(struct work_struct *work) -{ - struct amdgpu_device *adev = - container_of(work, struct amdgpu_device, - pm.dpm.thermal.work); - /* switch to the thermal state */ - enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; - int temp, size = sizeof(temp); - - if (!adev->pm.dpm_enabled) - return; - - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, - (void *)&temp, &size)) { - if (temp < adev->pm.dpm.thermal.min_temp) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } else { - if (adev->pm.dpm.thermal.high_to_low) - /* switch back the user state */ - dpm_state = adev->pm.dpm.user_state; - } - mutex_lock(&adev->pm.mutex); - if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) - adev->pm.dpm.thermal_active = true; - else - adev->pm.dpm.thermal_active = false; - adev->pm.dpm.state = dpm_state; - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); -} - -static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amd_pm_state_type dpm_state) -{ - int i; - struct amdgpu_ps *ps; - u32 ui_class; - bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? - true : false; - - /* check if the vblank period is too short to adjust the mclk */ - if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { - if (amdgpu_dpm_vblank_too_short(adev)) - single_display = false; - } - - /* certain older asics have a separare 3D performance state, - * so try that first if the user selected performance - */ - if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) - dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; - /* balanced states don't exist at the moment */ - if (dpm_state == POWER_STATE_TYPE_BALANCED) - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - -restart_search: - /* Pick the best power state based on current conditions */ - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - ps = &adev->pm.dpm.ps[i]; - ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; - switch (dpm_state) { - /* user states */ - case POWER_STATE_TYPE_BATTERY: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_BALANCED: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - case POWER_STATE_TYPE_PERFORMANCE: - if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { - if (single_display) - return ps; - } else - return ps; - } - break; - /* internal states */ - case POWER_STATE_TYPE_INTERNAL_UVD: - if (adev->pm.dpm.uvd_ps) - return adev->pm.dpm.uvd_ps; - else - break; - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_BOOT: - return adev->pm.dpm.boot_ps; - case POWER_STATE_TYPE_INTERNAL_THERMAL: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ACPI: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_ULV: - if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - return ps; - break; - case POWER_STATE_TYPE_INTERNAL_3DPERF: - if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - return ps; - break; - default: - break; - } - } - /* use a fallback state if we didn't match */ - switch (dpm_state) { - case POWER_STATE_TYPE_INTERNAL_UVD_SD: - dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_UVD_HD: - case POWER_STATE_TYPE_INTERNAL_UVD_HD2: - case POWER_STATE_TYPE_INTERNAL_UVD_MVC: - if (adev->pm.dpm.uvd_ps) { - return adev->pm.dpm.uvd_ps; - } else { - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - } - case POWER_STATE_TYPE_INTERNAL_THERMAL: - dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; - goto restart_search; - case POWER_STATE_TYPE_INTERNAL_ACPI: - dpm_state = POWER_STATE_TYPE_BATTERY; - goto restart_search; - case POWER_STATE_TYPE_BATTERY: - case POWER_STATE_TYPE_BALANCED: - case POWER_STATE_TYPE_INTERNAL_3DPERF: - dpm_state = POWER_STATE_TYPE_PERFORMANCE; - goto restart_search; - default: - break; - } - - return NULL; -} - -static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) -{ - struct amdgpu_ps *ps; - enum amd_pm_state_type dpm_state; - int ret; - bool equal = false; - - /* if dpm init failed */ - if (!adev->pm.dpm_enabled) - return; - - if (adev->pm.dpm.user_state != adev->pm.dpm.state) { - /* add other state override checks here */ - if ((!adev->pm.dpm.thermal_active) && - (!adev->pm.dpm.uvd_active)) - adev->pm.dpm.state = adev->pm.dpm.user_state; - } - dpm_state = adev->pm.dpm.state; - - ps = amdgpu_dpm_pick_power_state(adev, dpm_state); - if (ps) - adev->pm.dpm.requested_ps = ps; - else - return; - - if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { - printk("switching from power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); - printk("switching to power state:\n"); - amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); - } - - /* update whether vce is active */ - ps->vce_active = adev->pm.dpm.vce_active; - if (adev->powerplay.pp_funcs->display_configuration_changed) - amdgpu_dpm_display_configuration_changed(adev); - - ret = amdgpu_dpm_pre_set_power_state(adev); - if (ret) - return; - - if (adev->powerplay.pp_funcs->check_state_equal) { - if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) - equal = false; - } - - if (equal) - return; - - amdgpu_dpm_set_power_state(adev); - amdgpu_dpm_post_set_power_state(adev); - - adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; - adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; - - if (adev->powerplay.pp_funcs->force_performance_level) { - if (adev->pm.dpm.thermal_active) { - enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; - /* force low perf level for thermal */ - amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); - /* save the user's level */ - adev->pm.dpm.forced_level = level; - } else { - /* otherwise, user selected level */ - amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); - } - } -} - -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) -{ - int i = 0; - - if (!adev->pm.dpm_enabled) - return; - - if (adev->mode_info.num_crtc) - amdgpu_display_bandwidth_update(adev); - - for (i = 0; i < AMDGPU_MAX_RINGS; i++) { - struct amdgpu_ring *ring = adev->rings[i]; - if (ring && ring->sched.ready) - amdgpu_fence_wait_empty(ring); - } - - if (is_support_sw_smu(adev)) { - struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; - smu_handle_task(&adev->smu, - smu_dpm->dpm_level, - AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, - true); - } else { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - if (!amdgpu_device_has_dc_support(adev)) { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; - adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); - adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ - if (adev->pm.pm_display_cfg.vrefresh > 120) - adev->pm.pm_display_cfg.min_vblank_time = 0; - if (adev->powerplay.pp_funcs->display_configuration_change) - adev->powerplay.pp_funcs->display_configuration_change( - adev->powerplay.pp_handle, - &adev->pm.pm_display_cfg); - mutex_unlock(&adev->pm.mutex); - } - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); - } else { - mutex_lock(&adev->pm.mutex); - amdgpu_dpm_get_active_displays(adev); - amdgpu_dpm_change_power_state_locked(adev); - mutex_unlock(&adev->pm.mutex); - } - } -} - -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; - } else { - adev->pm.dpm.uvd_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); - if (ret) - DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - - /* enable/disable Low Memory PState for UVD (4k videos) */ - if (adev->asic_type == CHIP_STONEY && - adev->uvd.decode_image_width >= WIDTH_4K) { - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->hwmgr_func && - hwmgr->hwmgr_func->update_nbdpm_pstate) - hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, - !enable, - true); - } - } -} - -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - if (adev->family == AMDGPU_FAMILY_SI) { - mutex_lock(&adev->pm.mutex); - if (enable) { - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; - } else { - adev->pm.dpm.vce_active = false; - } - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } else { - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); - if (ret) - DRM_ERROR("Dpm %s vce failed, ret = %d. \n", - enable ? "enable" : "disable", ret); - } -} - -void amdgpu_pm_print_power_states(struct amdgpu_device *adev) -{ - int i; - - if (adev->powerplay.pp_funcs->print_power_state == NULL) - return; - - for (i = 0; i < adev->pm.dpm.num_ps; i++) - amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - -} - -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) -{ - int ret = 0; - - ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); - if (ret) - DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", - enable ? "enable" : "disable", ret); -} - -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) -{ - int r; - - if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { - r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); - if (r) { - pr_err("smu firmware loading failed\n"); - return r; - } - *smu_version = adev->pm.fw_version; - } - return 0; -} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h deleted file mode 100644 index dff4a5f99bb0..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __AMDGPU_DPM_H__ -#define __AMDGPU_DPM_H__ - -enum amdgpu_int_thermal_type { - THERMAL_TYPE_NONE, - THERMAL_TYPE_EXTERNAL, - THERMAL_TYPE_EXTERNAL_GPIO, - THERMAL_TYPE_RV6XX, - THERMAL_TYPE_RV770, - THERMAL_TYPE_ADT7473_WITH_INTERNAL, - THERMAL_TYPE_EVERGREEN, - THERMAL_TYPE_SUMO, - THERMAL_TYPE_NI, - THERMAL_TYPE_SI, - THERMAL_TYPE_EMC2103_WITH_INTERNAL, - THERMAL_TYPE_CI, - THERMAL_TYPE_KV, -}; - -enum amdgpu_dpm_auto_throttle_src { - AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, - AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL -}; - -enum amdgpu_dpm_event_src { - AMDGPU_DPM_EVENT_SRC_ANALOG = 0, - AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1, - AMDGPU_DPM_EVENT_SRC_DIGITAL = 2, - AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, - AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 -}; - -struct amdgpu_ps { - u32 caps; /* vbios flags */ - u32 class; /* vbios flags */ - u32 class2; /* vbios flags */ - /* UVD clocks */ - u32 vclk; - u32 dclk; - /* VCE clocks */ - u32 evclk; - u32 ecclk; - bool vce_active; - enum amd_vce_level vce_level; - /* asic priv */ - void *ps_priv; -}; - -struct amdgpu_dpm_thermal { - /* thermal interrupt work */ - struct work_struct work; - /* low temperature threshold */ - int min_temp; - /* high temperature threshold */ - int max_temp; - /* edge max emergency(shutdown) temp */ - int max_edge_emergency_temp; - /* hotspot low temperature threshold */ - int min_hotspot_temp; - /* hotspot high temperature critical threshold */ - int max_hotspot_crit_temp; - /* hotspot max emergency(shutdown) temp */ - int max_hotspot_emergency_temp; - /* memory low temperature threshold */ - int min_mem_temp; - /* memory high temperature critical threshold */ - int max_mem_crit_temp; - /* memory max emergency(shutdown) temp */ - int max_mem_emergency_temp; - /* was last interrupt low to high or high to low */ - bool high_to_low; - /* interrupt source */ - struct amdgpu_irq_src irq; -}; - -enum amdgpu_clk_action -{ - AMDGPU_SCLK_UP = 1, - AMDGPU_SCLK_DOWN -}; - -struct amdgpu_blacklist_clocks -{ - u32 sclk; - u32 mclk; - enum amdgpu_clk_action action; -}; - -struct amdgpu_clock_and_voltage_limits { - u32 sclk; - u32 mclk; - u16 vddc; - u16 vddci; -}; - -struct amdgpu_clock_array { - u32 count; - u32 *values; -}; - -struct amdgpu_clock_voltage_dependency_entry { - u32 clk; - u16 v; -}; - -struct amdgpu_clock_voltage_dependency_table { - u32 count; - struct amdgpu_clock_voltage_dependency_entry *entries; -}; - -union amdgpu_cac_leakage_entry { - struct { - u16 vddc; - u32 leakage; - }; - struct { - u16 vddc1; - u16 vddc2; - u16 vddc3; - }; -}; - -struct amdgpu_cac_leakage_table { - u32 count; - union amdgpu_cac_leakage_entry *entries; -}; - -struct amdgpu_phase_shedding_limits_entry { - u16 voltage; - u32 sclk; - u32 mclk; -}; - -struct amdgpu_phase_shedding_limits_table { - u32 count; - struct amdgpu_phase_shedding_limits_entry *entries; -}; - -struct amdgpu_uvd_clock_voltage_dependency_entry { - u32 vclk; - u32 dclk; - u16 v; -}; - -struct amdgpu_uvd_clock_voltage_dependency_table { - u8 count; - struct amdgpu_uvd_clock_voltage_dependency_entry *entries; -}; - -struct amdgpu_vce_clock_voltage_dependency_entry { - u32 ecclk; - u32 evclk; - u16 v; -}; - -struct amdgpu_vce_clock_voltage_dependency_table { - u8 count; - struct amdgpu_vce_clock_voltage_dependency_entry *entries; -}; - -struct amdgpu_ppm_table { - u8 ppm_design; - u16 cpu_core_number; - u32 platform_tdp; - u32 small_ac_platform_tdp; - u32 platform_tdc; - u32 small_ac_platform_tdc; - u32 apu_tdp; - u32 dgpu_tdp; - u32 dgpu_ulv_power; - u32 tj_max; -}; - -struct amdgpu_cac_tdp_table { - u16 tdp; - u16 configurable_tdp; - u16 tdc; - u16 battery_power_limit; - u16 small_power_limit; - u16 low_cac_leakage; - u16 high_cac_leakage; - u16 maximum_power_delivery_limit; -}; - -struct amdgpu_dpm_dynamic_state { - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk; - struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk; - struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk; - struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; - struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk; - struct amdgpu_clock_array valid_sclk_values; - struct amdgpu_clock_array valid_mclk_values; - struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc; - struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac; - u32 mclk_sclk_ratio; - u32 sclk_mclk_delta; - u16 vddc_vddci_delta; - u16 min_vddc_for_pcie_gen2; - struct amdgpu_cac_leakage_table cac_leakage_table; - struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table; - struct amdgpu_ppm_table *ppm_table; - struct amdgpu_cac_tdp_table *cac_tdp_table; -}; - -struct amdgpu_dpm_fan { - u16 t_min; - u16 t_med; - u16 t_high; - u16 pwm_min; - u16 pwm_med; - u16 pwm_high; - u8 t_hyst; - u32 cycle_delay; - u16 t_max; - u8 control_mode; - u16 default_max_fan_pwm; - u16 default_fan_output_sensitivity; - u16 fan_output_sensitivity; - bool ucode_fan_control; -}; - -enum amdgpu_pcie_gen { - AMDGPU_PCIE_GEN1 = 0, - AMDGPU_PCIE_GEN2 = 1, - AMDGPU_PCIE_GEN3 = 2, - AMDGPU_PCIE_GEN_INVALID = 0xffff -}; - -#define amdgpu_dpm_pre_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_post_set_power_state(adev) \ - ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_display_configuration_changed(adev) \ - ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_print_power_state(adev, ps) \ - ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) - -#define amdgpu_dpm_vblank_too_short(adev) \ - ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_enable_bapm(adev, e) \ - ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) - -#define amdgpu_dpm_set_fan_control_mode(adev, m) \ - ((adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m))) - -#define amdgpu_dpm_get_fan_control_mode(adev) \ - ((adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ - ((adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s))) - -#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ - ((adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s))) - -#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \ - ((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) - -#define amdgpu_dpm_set_fan_speed_rpm(adev, s) \ - ((adev)->powerplay.pp_funcs->set_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) - -#define amdgpu_dpm_force_performance_level(adev, l) \ - ((adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l))) - -#define amdgpu_dpm_get_current_power_state(adev) \ - ((adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_get_pp_num_states(adev, data) \ - ((adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)) - -#define amdgpu_dpm_get_pp_table(adev, table) \ - ((adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)) - -#define amdgpu_dpm_set_pp_table(adev, buf, size) \ - ((adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)) - -#define amdgpu_dpm_print_clock_levels(adev, type, buf) \ - ((adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)) - -#define amdgpu_dpm_force_clock_level(adev, type, level) \ - ((adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)) - -#define amdgpu_dpm_get_sclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_sclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)) - -#define amdgpu_dpm_get_mclk_od(adev) \ - ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_set_mclk_od(adev, value) \ - ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) - -#define amdgpu_dpm_dispatch_task(adev, task_id, user_state) \ - ((adev)->powerplay.pp_funcs->dispatch_tasks)((adev)->powerplay.pp_handle, (task_id), (user_state)) - -#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ - ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) - -#define amdgpu_dpm_get_vce_clock_state(adev, i) \ - ((adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i))) - -#define amdgpu_dpm_get_performance_level(adev) \ - ((adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)) - -#define amdgpu_dpm_reset_power_profile_state(adev, request) \ - ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ - (adev)->powerplay.pp_handle, request)) - -#define amdgpu_dpm_get_power_profile_mode(adev, buf) \ - ((adev)->powerplay.pp_funcs->get_power_profile_mode(\ - (adev)->powerplay.pp_handle, buf)) - -#define amdgpu_dpm_set_power_profile_mode(adev, parameter, size) \ - ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ - (adev)->powerplay.pp_handle, parameter, size)) - -#define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ - ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ - (adev)->powerplay.pp_handle, type, parameter, size)) - -#define amdgpu_dpm_get_ppfeature_status(adev, buf) \ - ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ - (adev)->powerplay.pp_handle, (buf))) - -#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \ - ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ - (adev)->powerplay.pp_handle, (ppfeatures))) - -#define amdgpu_dpm_get_gpu_metrics(adev, table) \ - ((adev)->powerplay.pp_funcs->get_gpu_metrics((adev)->powerplay.pp_handle, table)) - -struct amdgpu_dpm { - struct amdgpu_ps *ps; - /* number of valid power states */ - int num_ps; - /* current power state that is active */ - struct amdgpu_ps *current_ps; - /* requested power state */ - struct amdgpu_ps *requested_ps; - /* boot up power state */ - struct amdgpu_ps *boot_ps; - /* default uvd power state */ - struct amdgpu_ps *uvd_ps; - /* vce requirements */ - u32 num_of_vce_states; - struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; - enum amd_vce_level vce_level; - enum amd_pm_state_type state; - enum amd_pm_state_type user_state; - enum amd_pm_state_type last_state; - enum amd_pm_state_type last_user_state; - u32 platform_caps; - u32 voltage_response_time; - u32 backbias_response_time; - void *priv; - u32 new_active_crtcs; - int new_active_crtc_count; - u32 current_active_crtcs; - int current_active_crtc_count; - struct amdgpu_dpm_dynamic_state dyn_state; - struct amdgpu_dpm_fan fan; - u32 tdp_limit; - u32 near_tdp_limit; - u32 near_tdp_limit_adjusted; - u32 sq_ramping_threshold; - u32 cac_leakage; - u16 tdp_od_limit; - u32 tdp_adjustment; - u16 load_line_slope; - bool power_control; - /* special states active */ - bool thermal_active; - bool uvd_active; - bool vce_active; - /* thermal handling */ - struct amdgpu_dpm_thermal thermal; - /* forced levels */ - enum amd_dpm_forced_level forced_level; -}; - -struct amdgpu_pm { - struct mutex mutex; - u32 current_sclk; - u32 current_mclk; - u32 default_sclk; - u32 default_mclk; - struct amdgpu_i2c_chan *i2c_bus; - bool bus_locked; - /* internal thermal controller on rv6xx+ */ - enum amdgpu_int_thermal_type int_thermal_type; - struct device *int_hwmon_dev; - /* fan control parameters */ - bool no_fan; - u8 fan_pulses_per_revolution; - u8 fan_min_rpm; - u8 fan_max_rpm; - /* dpm */ - bool dpm_enabled; - bool sysfs_initialized; - struct amdgpu_dpm dpm; - const struct firmware *fw; /* SMC firmware */ - uint32_t fw_version; - uint32_t pcie_gen_mask; - uint32_t pcie_mlw_mask; - struct amd_pp_display_configuration pm_display_cfg;/* set by dc */ - uint32_t smu_prv_buffer_size; - struct amdgpu_bo *smu_prv_buffer; - bool ac_power; - /* powerplay feature */ - uint32_t pp_feature; - - /* Used for I2C access to various EEPROMs on relevant ASICs */ - struct i2c_adapter smu_i2c; - struct list_head pm_attr_list; -}; - -#define R600_SSTU_DFLT 0 -#define R600_SST_DFLT 0x00C8 - -/* XXX are these ok? */ -#define R600_TEMP_RANGE_MIN (90 * 1000) -#define R600_TEMP_RANGE_MAX (120 * 1000) - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -enum amdgpu_td { - AMDGPU_TD_AUTO, - AMDGPU_TD_UP, - AMDGPU_TD_DOWN, -}; - -enum amdgpu_display_watermark { - AMDGPU_DISPLAY_WATERMARK_LOW = 0, - AMDGPU_DISPLAY_WATERMARK_HIGH = 1, -}; - -enum amdgpu_display_gap -{ - AMDGPU_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, - AMDGPU_PM_DISPLAY_GAP_VBLANK = 1, - AMDGPU_PM_DISPLAY_GAP_WATERMARK = 2, - AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, -}; - -void amdgpu_dpm_print_class_info(u32 class, u32 class2); -void amdgpu_dpm_print_cap_info(u32 caps); -void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, - struct amdgpu_ps *rps); -u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); -u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev); -void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev); -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size); - -bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor); - -int amdgpu_get_platform_caps(struct amdgpu_device *adev); - -int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); -void amdgpu_free_extended_power_table(struct amdgpu_device *adev); - -void amdgpu_add_thermal_controller(struct amdgpu_device *adev); - -enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, - u32 sys_mask, - enum amdgpu_pcie_gen asic_gen, - enum amdgpu_pcie_gen default_gen); - -struct amd_vce_state* -amdgpu_get_vce_clock_state(void *handle, u32 idx); - -int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, - uint32_t block_type, bool gate); - -extern int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low); - -extern int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low); - -int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, - uint32_t pstate); - -int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, - enum PP_SMC_POWER_PROFILE type, - bool en); - -int amdgpu_dpm_baco_reset(struct amdgpu_device *adev); - -int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev); - -bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev); - -bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev); -int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev); - -int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, - enum pp_mp1_state mp1_state); - -int amdgpu_dpm_baco_exit(struct amdgpu_device *adev); - -int amdgpu_dpm_baco_enter(struct amdgpu_device *adev); - -int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, - uint32_t cstate); - -int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); - -int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); - -int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, - uint32_t msg_id); - -int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, - bool acquire); - -void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); - -int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, - void *data, uint32_t *size); - -void amdgpu_dpm_thermal_work_handler(struct work_struct *work); - -void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); -void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); -void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); -void amdgpu_pm_print_power_states(struct amdgpu_device *adev); -int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c deleted file mode 100644 index 5fc6a9a13096..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ /dev/null @@ -1,3613 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Rafał Miłecki - * Alex Deucher - */ - -#include - -#include "amdgpu.h" -#include "amdgpu_drv.h" -#include "amdgpu_pm.h" -#include "amdgpu_dpm.h" -#include "amdgpu_smu.h" -#include "atom.h" -#include -#include -#include -#include -#include -#include "hwmgr.h" - -static const struct cg_flag_name clocks[] = { - {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"}, - {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"}, - {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"}, - {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"}, - {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"}, - {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"}, - {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"}, - {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, - {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"}, - {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"}, - {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"}, - {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"}, - - {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, - {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, - {0, NULL}, -}; - -static const struct hwmon_temp_label { - enum PP_HWMON_TEMP channel; - const char *label; -} temp_label[] = { - {PP_TEMP_EDGE, "edge"}, - {PP_TEMP_JUNCTION, "junction"}, - {PP_TEMP_MEM, "mem"}, -}; - -/** - * DOC: power_dpm_state - * - * The power_dpm_state file is a legacy interface and is only provided for - * backwards compatibility. The amdgpu driver provides a sysfs API for adjusting - * certain power related parameters. The file power_dpm_state is used for this. - * It accepts the following arguments: - * - * - battery - * - * - balanced - * - * - performance - * - * battery - * - * On older GPUs, the vbios provided a special power state for battery - * operation. Selecting battery switched to this state. This is no - * longer provided on newer GPUs so the option does nothing in that case. - * - * balanced - * - * On older GPUs, the vbios provided a special power state for balanced - * operation. Selecting balanced switched to this state. This is no - * longer provided on newer GPUs so the option does nothing in that case. - * - * performance - * - * On older GPUs, the vbios provided a special power state for performance - * operation. Selecting performance switched to this state. This is no - * longer provided on newer GPUs so the option does nothing in that case. - * - */ - -static ssize_t amdgpu_get_power_dpm_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - enum amd_pm_state_type pm; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - if (adev->smu.ppt_funcs->get_current_power_state) - pm = smu_get_current_power_state(&adev->smu); - else - pm = adev->pm.dpm.user_state; - } else if (adev->powerplay.pp_funcs->get_current_power_state) { - pm = amdgpu_dpm_get_current_power_state(adev); - } else { - pm = adev->pm.dpm.user_state; - } - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return snprintf(buf, PAGE_SIZE, "%s\n", - (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : - (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); -} - -static ssize_t amdgpu_set_power_dpm_state(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - enum amd_pm_state_type state; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - if (strncmp("battery", buf, strlen("battery")) == 0) - state = POWER_STATE_TYPE_BATTERY; - else if (strncmp("balanced", buf, strlen("balanced")) == 0) - state = POWER_STATE_TYPE_BALANCED; - else if (strncmp("performance", buf, strlen("performance")) == 0) - state = POWER_STATE_TYPE_PERFORMANCE; - else - return -EINVAL; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); - } else if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state); - } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.user_state = state; - mutex_unlock(&adev->pm.mutex); - - amdgpu_pm_compute_clocks(adev); - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - - -/** - * DOC: power_dpm_force_performance_level - * - * The amdgpu driver provides a sysfs API for adjusting certain power - * related parameters. The file power_dpm_force_performance_level is - * used for this. It accepts the following arguments: - * - * - auto - * - * - low - * - * - high - * - * - manual - * - * - profile_standard - * - * - profile_min_sclk - * - * - profile_min_mclk - * - * - profile_peak - * - * auto - * - * When auto is selected, the driver will attempt to dynamically select - * the optimal power profile for current conditions in the driver. - * - * low - * - * When low is selected, the clocks are forced to the lowest power state. - * - * high - * - * When high is selected, the clocks are forced to the highest power state. - * - * manual - * - * When manual is selected, the user can manually adjust which power states - * are enabled for each clock domain via the sysfs pp_dpm_mclk, pp_dpm_sclk, - * and pp_dpm_pcie files and adjust the power state transition heuristics - * via the pp_power_profile_mode sysfs file. - * - * profile_standard - * profile_min_sclk - * profile_min_mclk - * profile_peak - * - * When the profiling modes are selected, clock and power gating are - * disabled and the clocks are set for different profiling cases. This - * mode is recommended for profiling specific work loads where you do - * not want clock or power gating for clock fluctuation to interfere - * with your results. profile_standard sets the clocks to a fixed clock - * level which varies from asic to asic. profile_min_sclk forces the sclk - * to the lowest level. profile_min_mclk forces the mclk to the lowest level. - * profile_peak sets all clocks (mclk, sclk, pcie) to the highest levels. - * - */ - -static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - enum amd_dpm_forced_level level = 0xff; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) - level = smu_get_performance_level(&adev->smu); - else if (adev->powerplay.pp_funcs->get_performance_level) - level = amdgpu_dpm_get_performance_level(adev); - else - level = adev->pm.dpm.forced_level; - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return snprintf(buf, PAGE_SIZE, "%s\n", - (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : - (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : - (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" : - (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : - (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) ? "profile_standard" : - (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) ? "profile_min_sclk" : - (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) ? "profile_min_mclk" : - (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) ? "profile_peak" : - "unknown"); -} - -static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - enum amd_dpm_forced_level level; - enum amd_dpm_forced_level current_level = 0xff; - int ret = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - if (strncmp("low", buf, strlen("low")) == 0) { - level = AMD_DPM_FORCED_LEVEL_LOW; - } else if (strncmp("high", buf, strlen("high")) == 0) { - level = AMD_DPM_FORCED_LEVEL_HIGH; - } else if (strncmp("auto", buf, strlen("auto")) == 0) { - level = AMD_DPM_FORCED_LEVEL_AUTO; - } else if (strncmp("manual", buf, strlen("manual")) == 0) { - level = AMD_DPM_FORCED_LEVEL_MANUAL; - } else if (strncmp("profile_exit", buf, strlen("profile_exit")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILE_EXIT; - } else if (strncmp("profile_standard", buf, strlen("profile_standard")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD; - } else if (strncmp("profile_min_sclk", buf, strlen("profile_min_sclk")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK; - } else if (strncmp("profile_min_mclk", buf, strlen("profile_min_mclk")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK; - } else if (strncmp("profile_peak", buf, strlen("profile_peak")) == 0) { - level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - } else { - return -EINVAL; - } - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) - current_level = smu_get_performance_level(&adev->smu); - else if (adev->powerplay.pp_funcs->get_performance_level) - current_level = amdgpu_dpm_get_performance_level(adev); - - if (current_level == level) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } - - if (adev->asic_type == CHIP_RAVEN) { - if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { - if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, false); - else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL) - amdgpu_gfx_off_ctrl(adev, true); - } - } - - /* profile_exit setting is valid only when current mode is in profile mode */ - if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) && - (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { - pr_err("Currently not in any profile mode!\n"); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - - if (is_support_sw_smu(adev)) { - ret = smu_force_performance_level(&adev->smu, level); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } else if (adev->powerplay.pp_funcs->force_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->pm.dpm.thermal_active) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - ret = amdgpu_dpm_force_performance_level(adev, level); - if (ret) { - mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } else { - adev->pm.dpm.forced_level = level; - } - mutex_unlock(&adev->pm.mutex); - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -static ssize_t amdgpu_get_pp_num_states(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - struct pp_states_info data; - int i, buf_len, ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - ret = smu_get_power_num_states(&adev->smu, &data); - if (ret) - return ret; - } else if (adev->powerplay.pp_funcs->get_pp_num_states) { - amdgpu_dpm_get_pp_num_states(adev, &data); - } else { - memset(&data, 0, sizeof(data)); - } - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums); - for (i = 0; i < data.nums; i++) - buf_len += snprintf(buf + buf_len, PAGE_SIZE, "%d %s\n", i, - (data.states[i] == POWER_STATE_TYPE_INTERNAL_BOOT) ? "boot" : - (data.states[i] == POWER_STATE_TYPE_BATTERY) ? "battery" : - (data.states[i] == POWER_STATE_TYPE_BALANCED) ? "balanced" : - (data.states[i] == POWER_STATE_TYPE_PERFORMANCE) ? "performance" : "default"); - - return buf_len; -} - -static ssize_t amdgpu_get_pp_cur_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - struct pp_states_info data; - struct smu_context *smu = &adev->smu; - enum amd_pm_state_type pm = 0; - int i = 0, ret = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - pm = smu_get_current_power_state(smu); - ret = smu_get_power_num_states(smu, &data); - if (ret) - return ret; - } else if (adev->powerplay.pp_funcs->get_current_power_state - && adev->powerplay.pp_funcs->get_pp_num_states) { - pm = amdgpu_dpm_get_current_power_state(adev); - amdgpu_dpm_get_pp_num_states(adev, &data); - } - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - for (i = 0; i < data.nums; i++) { - if (pm == data.states[i]) - break; - } - - if (i == data.nums) - i = -EINVAL; - - return snprintf(buf, PAGE_SIZE, "%d\n", i); -} - -static ssize_t amdgpu_get_pp_force_state(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - - if (adev->in_gpu_reset) - return -EPERM; - - if (adev->pp_force_state_enabled) - return amdgpu_get_pp_cur_state(dev, attr, buf); - else - return snprintf(buf, PAGE_SIZE, "\n"); -} - -static ssize_t amdgpu_set_pp_force_state(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - enum amd_pm_state_type state = 0; - unsigned long idx; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - if (strlen(buf) == 1) - adev->pp_force_state_enabled = false; - else if (is_support_sw_smu(adev)) - adev->pp_force_state_enabled = false; - else if (adev->powerplay.pp_funcs->dispatch_tasks && - adev->powerplay.pp_funcs->get_pp_num_states) { - struct pp_states_info data; - - ret = kstrtoul(buf, 0, &idx); - if (ret || idx >= ARRAY_SIZE(data.states)) - return -EINVAL; - - idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); - - amdgpu_dpm_get_pp_num_states(adev, &data); - state = data.states[idx]; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - /* only set user selected power states */ - if (state != POWER_STATE_TYPE_INTERNAL_BOOT && - state != POWER_STATE_TYPE_DEFAULT) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_ENABLE_USER_STATE, &state); - adev->pp_force_state_enabled = true; - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - } - - return count; -} - -/** - * DOC: pp_table - * - * The amdgpu driver provides a sysfs API for uploading new powerplay - * tables. The file pp_table is used for this. Reading the file - * will dump the current power play table. Writing to the file - * will attempt to upload a new powerplay table and re-initialize - * powerplay using that new table. - * - */ - -static ssize_t amdgpu_get_pp_table(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - char *table = NULL; - int size, ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - size = smu_sys_get_pp_table(&adev->smu, (void **)&table); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - if (size < 0) - return size; - } else if (adev->powerplay.pp_funcs->get_pp_table) { - size = amdgpu_dpm_get_pp_table(adev, &table); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - if (size < 0) - return size; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return 0; - } - - if (size >= PAGE_SIZE) - size = PAGE_SIZE - 1; - - memcpy(buf, table, size); - - return size; -} - -static ssize_t amdgpu_set_pp_table(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - return ret; - } - } else if (adev->powerplay.pp_funcs->set_pp_table) - amdgpu_dpm_set_pp_table(adev, buf, count); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -/** - * DOC: pp_od_clk_voltage - * - * The amdgpu driver provides a sysfs API for adjusting the clocks and voltages - * 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: - * - * - a list of engine clock levels and voltages labeled OD_SCLK - * - * - a list of memory clock levels and voltages labeled OD_MCLK - * - * - a list of valid ranges for sclk, mclk, and voltage labeled OD_RANGE - * - * To manually adjust these settings, first select manual using - * power_dpm_force_performance_level. Enter a new value for each - * level by writing a string that contains "s/m level clock voltage" to - * the file. E.g., "s 1 500 820" will update sclk level 1 to be 500 MHz - * at 820 mV; "m 0 350 810" will update mclk level 0 to be 350 MHz at - * 810 mV. When you have edited all of the states as needed, write - * "c" (commit) to the file to commit your changes. If you want to reset to the - * default power levels, write "r" (reset) to the file to reset them. - * - * - * < For Vega20 and newer ASICs > - * - * Reading the file will display: - * - * - minimum and maximum engine clock labeled OD_SCLK - * - * - maximum memory clock labeled OD_MCLK - * - * - three points labeled OD_VDDC_CURVE. - * They can be used to calibrate the sclk voltage curve. - * - * - a list of valid ranges for sclk, mclk, and voltage curve points - * labeled OD_RANGE - * - * To manually adjust these settings: - * - * - First select manual using power_dpm_force_performance_level - * - * - For clock frequency setting, enter a new value by writing a - * string that contains "s/m index clock" to the file. The index - * should be 0 if to set minimum clock. And 1 if to set maximum - * clock. E.g., "s 0 500" will update minimum sclk to be 500 MHz. - * "m 1 800" will update maximum mclk to be 800Mhz. - * - * For sclk voltage curve, enter the new values by writing a - * string that contains "vc point clock voltage" to the file. The - * points are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will - * update point1 with clock set as 300Mhz and voltage as - * 600mV. "vc 2 1000 1000" will update point3 with clock set - * as 1000Mhz and voltage 1000mV. - * - * - When you have edited all of the states as needed, write "c" (commit) - * to the file to commit your changes - * - * - If you want to reset to the default power levels, write "r" (reset) - * to the file to reset them - * - */ - -static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t parameter_size = 0; - long parameter[64]; - char buf_cpy[128]; - char *tmp_str; - char *sub_str; - const char delimiter[3] = {' ', '\n', '\0'}; - uint32_t type; - - if (adev->in_gpu_reset) - return -EPERM; - - if (count > 127) - return -EINVAL; - - if (*buf == 's') - type = PP_OD_EDIT_SCLK_VDDC_TABLE; - else if (*buf == 'm') - type = PP_OD_EDIT_MCLK_VDDC_TABLE; - else if(*buf == 'r') - type = PP_OD_RESTORE_DEFAULT_TABLE; - else if (*buf == 'c') - type = PP_OD_COMMIT_DPM_TABLE; - else if (!strncmp(buf, "vc", 2)) - type = PP_OD_EDIT_VDDC_CURVE; - else - return -EINVAL; - - memcpy(buf_cpy, buf, count+1); - - tmp_str = buf_cpy; - - if (type == PP_OD_EDIT_VDDC_CURVE) - tmp_str++; - while (isspace(*++tmp_str)); - - while (tmp_str[0]) { - sub_str = strsep(&tmp_str, delimiter); - ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); - if (ret) - return -EINVAL; - parameter_size++; - - while (isspace(*tmp_str)) - tmp_str++; - } - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - ret = smu_od_edit_dpm_table(&adev->smu, type, - parameter, parameter_size); - - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } else { - if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { - ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, - parameter, parameter_size); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } - - if (type == PP_OD_COMMIT_DPM_TABLE) { - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, - AMD_PP_TASK_READJUST_POWER_STATE, - NULL); - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return count; - } else { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - size = smu_print_clk_levels(&adev->smu, SMU_OD_SCLK, buf); - size += smu_print_clk_levels(&adev->smu, SMU_OD_MCLK, buf+size); - size += smu_print_clk_levels(&adev->smu, SMU_OD_VDDC_CURVE, buf+size); - size += smu_print_clk_levels(&adev->smu, SMU_OD_RANGE, buf+size); - } else if (adev->powerplay.pp_funcs->print_clock_levels) { - size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); - size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); - size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); - } else { - size = snprintf(buf, PAGE_SIZE, "\n"); - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -/** - * DOC: pp_features - * - * The amdgpu driver provides a sysfs API for adjusting what powerplay - * features to be enabled. The file pp_features is used for this. And - * this is only available for Vega10 and later dGPUs. - * - * Reading back the file will show you the followings: - * - Current ppfeature masks - * - List of the all supported powerplay features with their naming, - * bitmasks and enablement status('Y'/'N' means "enabled"/"disabled"). - * - * To manually enable or disable a specific feature, just set or clear - * the corresponding bit from original ppfeature masks and input the - * new ppfeature masks. - */ -static ssize_t amdgpu_set_pp_features(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint64_t featuremask; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = kstrtou64(buf, 0, &featuremask); - if (ret) - return -EINVAL; - - pr_debug("featuremask = 0x%llx\n", featuremask); - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - return -EINVAL; - } - } else if (adev->powerplay.pp_funcs->set_ppfeature_status) { - ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); - if (ret) { - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - return -EINVAL; - } - } - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -static ssize_t amdgpu_get_pp_features(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_get_ppfeature_status(adev, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -/** - * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie - * - * The amdgpu driver provides a sysfs API for adjusting what power levels - * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk, - * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for - * this. - * - * pp_dpm_socclk and pp_dpm_dcefclk interfaces are only available for - * Vega10 and later ASICs. - * pp_dpm_fclk interface is only available for Vega20 and later ASICs. - * - * Reading back the files will show you the available power levels within - * the power state and the clock information for those levels. - * - * To manually adjust these states, first select manual using - * power_dpm_force_performance_level. - * Secondly, enter a new value for each level by inputing a string that - * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie" - * E.g., - * - * .. code-block:: bash - * - * echo "4 5 6" > pp_dpm_sclk - * - * will enable sclk levels 4, 5, and 6. - * - * NOTE: change to the dcefclk max dpm level is not supported now - */ - -static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -/* - * Worst case: 32 bits individually specified, in octal at 12 characters - * per line (+1 for \n). - */ -#define AMDGPU_MASK_BUF_MAX (32 * 13) - -static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) -{ - int ret; - long level; - char *sub_str = NULL; - char *tmp; - char buf_cpy[AMDGPU_MASK_BUF_MAX + 1]; - const char delimiter[3] = {' ', '\n', '\0'}; - size_t bytes; - - *mask = 0; - - bytes = min(count, sizeof(buf_cpy) - 1); - memcpy(buf_cpy, buf, bytes); - buf_cpy[bytes] = '\0'; - tmp = buf_cpy; - while (tmp[0]) { - sub_str = strsep(&tmp, delimiter); - if (strlen(sub_str)) { - ret = kstrtol(sub_str, 0, &level); - if (ret) - return -EINVAL; - *mask |= 1 << level; - } else - break; - } - - return 0; -} - -static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t mask = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint32_t mask = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t mask = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask); - else - ret = 0; - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t mask = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask); - else - ret = 0; - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t mask = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask); - else - ret = 0; - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - uint32_t mask = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = amdgpu_read_mask(buf, count, &mask); - if (ret) - return ret; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - ret = amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); - else - ret = 0; - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (ret) - return -EINVAL; - - return count; -} - -static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint32_t value = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - long int value; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = kstrtol(buf, 0, &value); - - if (ret) - return -EINVAL; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value); - } else { - if (adev->powerplay.pp_funcs->set_sclk_od) - amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint32_t value = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int ret; - long int value; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = kstrtol(buf, 0, &value); - - if (ret) - return -EINVAL; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) { - value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value); - } else { - if (adev->powerplay.pp_funcs->set_mclk_od) - amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - - if (adev->powerplay.pp_funcs->dispatch_tasks) { - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - } else { - adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; - amdgpu_pm_compute_clocks(adev); - } - } - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return count; -} - -/** - * DOC: pp_power_profile_mode - * - * The amdgpu driver provides a sysfs API for adjusting the heuristics - * related to switching between power levels in a power state. The file - * pp_power_profile_mode is used for this. - * - * Reading this file outputs a list of all of the predefined power profiles - * and the relevant heuristics settings for that profile. - * - * To select a profile or create a custom profile, first select manual using - * power_dpm_force_performance_level. Writing the number of a predefined - * profile to pp_power_profile_mode will enable those heuristics. To - * create a custom set of heuristics, write a string of numbers to the file - * starting with the number of the custom profile along with a setting - * for each heuristic parameter. Due to differences across asic families - * the heuristic parameters vary from family to family. - * - */ - -static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - ssize_t size; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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) - size = amdgpu_dpm_get_power_profile_mode(adev, buf); - else - size = snprintf(buf, PAGE_SIZE, "\n"); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - - -static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - int ret; - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint32_t parameter_size = 0; - long parameter[64]; - char *sub_str, buf_cpy[128]; - char *tmp_str; - uint32_t i = 0; - char tmp[2]; - long int profile_mode = 0; - const char delimiter[3] = {' ', '\n', '\0'}; - - if (adev->in_gpu_reset) - return -EPERM; - - tmp[0] = *(buf); - tmp[1] = '\0'; - ret = kstrtol(tmp, 0, &profile_mode); - if (ret) - return -EINVAL; - - if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { - if (count < 2 || count > 127) - return -EINVAL; - while (isspace(*++buf)) - i++; - memcpy(buf_cpy, buf, count-i); - tmp_str = buf_cpy; - while (tmp_str[0]) { - sub_str = strsep(&tmp_str, delimiter); - ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); - if (ret) - return -EINVAL; - parameter_size++; - while (isspace(*tmp_str)) - tmp_str++; - } - } - parameter[parameter_size] = profile_mode; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - 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); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (!ret) - return count; - - return -EINVAL; -} - -/** - * DOC: gpu_busy_percent - * - * The amdgpu driver provides a sysfs API for reading how busy the GPU - * is as a percentage. The file gpu_busy_percent is used for this. - * The SMU firmware computes a percentage of load based on the - * aggregate activity level in the IP cores. - */ -static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int r, value, size = sizeof(value); - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return r; - } - - /* read the IP busy sensor */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, - (void *)&value, &size); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -/** - * DOC: mem_busy_percent - * - * The amdgpu driver provides a sysfs API for reading how busy the VRAM - * is as a percentage. The file mem_busy_percent is used for this. - * The SMU firmware computes a percentage of load based on the - * aggregate activity level in the IP cores. - */ -static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - int r, value, size = sizeof(value); - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return r; - } - - /* read the IP busy sensor */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, - (void *)&value, &size); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -/** - * DOC: pcie_bw - * - * The amdgpu driver provides a sysfs API for estimating how much data - * has been received and sent by the GPU in the last second through PCIe. - * The file pcie_bw is used for this. - * The Perf counters count the number of received and sent messages and return - * those values, as well as the maximum payload size of a PCIe packet (mps). - * Note that it is not possible to easily and quickly obtain the size of each - * packet transmitted, so we output the max payload size (mps) to allow for - * quick estimation of the PCIe bandwidth usage - */ -static ssize_t amdgpu_get_pcie_bw(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - uint64_t count0 = 0, count1 = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - if (adev->flags & AMD_IS_APU) - return -ENODATA; - - if (!adev->asic_funcs->get_pcie_usage) - return -ENODATA; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - amdgpu_asic_get_pcie_usage(adev, &count0, &count1); - - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n", - count0, count1, pcie_get_mps(adev->pdev)); -} - -/** - * DOC: unique_id - * - * The amdgpu driver provides a sysfs API for providing a unique ID for the GPU - * The file unique_id is used for this. - * This will provide a Unique ID that will persist from machine to machine - * - * NOTE: This will only work for GFX9 and newer. This file will be absent - * on unsupported ASICs (GFX8 and older) - */ -static ssize_t amdgpu_get_unique_id(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - - if (adev->in_gpu_reset) - return -EPERM; - - if (adev->unique_id) - return snprintf(buf, PAGE_SIZE, "%016llx\n", adev->unique_id); - - return 0; -} - -/** - * DOC: thermal_throttling_logging - * - * Thermal throttling pulls down the clock frequency and thus the performance. - * It's an useful mechanism to protect the chip from overheating. Since it - * impacts performance, the user controls whether it is enabled and if so, - * the log frequency. - * - * Reading back the file shows you the status(enabled or disabled) and - * the interval(in seconds) between each thermal logging. - * - * Writing an integer to the file, sets a new logging interval, in seconds. - * The value should be between 1 and 3600. If the value is less than 1, - * thermal logging is disabled. Values greater than 3600 are ignored. - */ -static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - - return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", - adev->ddev->unique, - atomic_read(&adev->throttling_logging_enabled) ? "enabled" : "disabled", - adev->throttling_logging_rs.interval / HZ + 1); -} - -static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - long throttling_logging_interval; - unsigned long flags; - int ret = 0; - - ret = kstrtol(buf, 0, &throttling_logging_interval); - if (ret) - return ret; - - if (throttling_logging_interval > 3600) - return -EINVAL; - - if (throttling_logging_interval > 0) { - raw_spin_lock_irqsave(&adev->throttling_logging_rs.lock, flags); - /* - * Reset the ratelimit timer internals. - * This can effectively restart the timer. - */ - adev->throttling_logging_rs.interval = - (throttling_logging_interval - 1) * HZ; - adev->throttling_logging_rs.begin = 0; - adev->throttling_logging_rs.printed = 0; - adev->throttling_logging_rs.missed = 0; - raw_spin_unlock_irqrestore(&adev->throttling_logging_rs.lock, flags); - - atomic_set(&adev->throttling_logging_enabled, 1); - } else { - atomic_set(&adev->throttling_logging_enabled, 0); - } - - return count; -} - -/** - * DOC: gpu_metrics - * - * The amdgpu driver provides a sysfs API for retrieving current gpu - * metrics data. The file gpu_metrics is used for this. Reading the - * file will dump all the current gpu metrics data. - * - * These data include temperature, frequency, engines utilization, - * power consume, throttler status, fan speed and cpu core statistics( - * available for APU only). That's it will give a snapshot of all sensors - * at the same time. - */ -static ssize_t amdgpu_get_gpu_metrics(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; - void *gpu_metrics; - ssize_t size = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(ddev->dev); - return ret; - } - - if (is_support_sw_smu(adev)) - size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); - else if (adev->powerplay.pp_funcs->get_gpu_metrics) - size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); - - if (size <= 0) - goto out; - - if (size >= PAGE_SIZE) - size = PAGE_SIZE - 1; - - memcpy(buf, gpu_metrics, size); - -out: - pm_runtime_mark_last_busy(ddev->dev); - pm_runtime_put_autosuspend(ddev->dev); - - return size; -} - -static struct amdgpu_device_attr amdgpu_device_attrs[] = { - AMDGPU_DEVICE_ATTR_RW(power_dpm_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(power_dpm_force_performance_level, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(pp_num_states, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(pp_cur_state, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_force_state, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_table, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_sclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_socclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_mclk_od, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_power_profile_mode, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_od_clk_voltage, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(gpu_busy_percent, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(mem_busy_percent, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(pcie_bw, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging, ATTR_FLAG_BASIC), - AMDGPU_DEVICE_ATTR_RO(gpu_metrics, ATTR_FLAG_BASIC), -}; - -static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, - uint32_t mask, enum amdgpu_device_attr_states *states) -{ - struct device_attribute *dev_attr = &attr->dev_attr; - const char *attr_name = dev_attr->attr.name; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - enum amd_asic_type asic_type = adev->asic_type; - - if (!(attr->flags & mask)) { - *states = ATTR_STATE_UNSUPPORTED; - return 0; - } - -#define DEVICE_ATTR_IS(_name) (!strcmp(attr_name, #_name)) - - if (DEVICE_ATTR_IS(pp_dpm_socclk)) { - if (asic_type < CHIP_VEGA10) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { - if (asic_type < CHIP_VEGA10 || asic_type == CHIP_ARCTURUS) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { - if (asic_type < CHIP_VEGA20) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_dpm_pcie)) { - if (asic_type == CHIP_ARCTURUS) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { - *states = ATTR_STATE_UNSUPPORTED; - if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || - (!is_support_sw_smu(adev) && hwmgr->od_enabled)) - *states = ATTR_STATE_SUPPORTED; - } else if (DEVICE_ATTR_IS(mem_busy_percent)) { - if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pcie_bw)) { - /* PCIe Perf counters won't work on APU nodes */ - if (adev->flags & AMD_IS_APU) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(unique_id)) { - if (asic_type != CHIP_VEGA10 && - asic_type != CHIP_VEGA20 && - asic_type != CHIP_ARCTURUS) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(pp_features)) { - if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) - *states = ATTR_STATE_UNSUPPORTED; - } else if (DEVICE_ATTR_IS(gpu_metrics)) { - if (asic_type < CHIP_VEGA12) - *states = ATTR_STATE_UNSUPPORTED; - } - - if (asic_type == CHIP_ARCTURUS) { - /* Arcturus does not support standalone mclk/socclk/fclk level setting */ - if (DEVICE_ATTR_IS(pp_dpm_mclk) || - DEVICE_ATTR_IS(pp_dpm_socclk) || - DEVICE_ATTR_IS(pp_dpm_fclk)) { - dev_attr->attr.mode &= ~S_IWUGO; - dev_attr->store = NULL; - } - } - -#undef DEVICE_ATTR_IS - - return 0; -} - - -static int amdgpu_device_attr_create(struct amdgpu_device *adev, - struct amdgpu_device_attr *attr, - uint32_t mask, struct list_head *attr_list) -{ - int ret = 0; - struct device_attribute *dev_attr = &attr->dev_attr; - const char *name = dev_attr->attr.name; - enum amdgpu_device_attr_states attr_states = ATTR_STATE_SUPPORTED; - struct amdgpu_device_attr_entry *attr_entry; - - int (*attr_update)(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, - uint32_t mask, enum amdgpu_device_attr_states *states) = default_attr_update; - - BUG_ON(!attr); - - attr_update = attr->attr_update ? attr_update : default_attr_update; - - ret = attr_update(adev, attr, mask, &attr_states); - if (ret) { - dev_err(adev->dev, "failed to update device file %s, ret = %d\n", - name, ret); - return ret; - } - - if (attr_states == ATTR_STATE_UNSUPPORTED) - return 0; - - ret = device_create_file(adev->dev, dev_attr); - if (ret) { - dev_err(adev->dev, "failed to create device file %s, ret = %d\n", - name, ret); - } - - attr_entry = kmalloc(sizeof(*attr_entry), GFP_KERNEL); - if (!attr_entry) - return -ENOMEM; - - attr_entry->attr = attr; - INIT_LIST_HEAD(&attr_entry->entry); - - list_add_tail(&attr_entry->entry, attr_list); - - return ret; -} - -static void amdgpu_device_attr_remove(struct amdgpu_device *adev, struct amdgpu_device_attr *attr) -{ - struct device_attribute *dev_attr = &attr->dev_attr; - - device_remove_file(adev->dev, dev_attr); -} - -static void amdgpu_device_attr_remove_groups(struct amdgpu_device *adev, - struct list_head *attr_list); - -static int amdgpu_device_attr_create_groups(struct amdgpu_device *adev, - struct amdgpu_device_attr *attrs, - uint32_t counts, - uint32_t mask, - struct list_head *attr_list) -{ - int ret = 0; - uint32_t i = 0; - - for (i = 0; i < counts; i++) { - ret = amdgpu_device_attr_create(adev, &attrs[i], mask, attr_list); - if (ret) - goto failed; - } - - return 0; - -failed: - amdgpu_device_attr_remove_groups(adev, attr_list); - - return ret; -} - -static void amdgpu_device_attr_remove_groups(struct amdgpu_device *adev, - struct list_head *attr_list) -{ - struct amdgpu_device_attr_entry *entry, *entry_tmp; - - if (list_empty(attr_list)) - return ; - - list_for_each_entry_safe(entry, entry_tmp, attr_list, entry) { - amdgpu_device_attr_remove(adev, entry->attr); - list_del(&entry->entry); - kfree(entry); - } -} - -static ssize_t amdgpu_hwmon_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int channel = to_sensor_dev_attr(attr)->index; - int r, temp = 0, size = sizeof(temp); - - if (adev->in_gpu_reset) - return -EPERM; - - if (channel >= PP_TEMP_MAX) - return -EINVAL; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - switch (channel) { - case PP_TEMP_JUNCTION: - /* get current junction temperature */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_HOTSPOT_TEMP, - (void *)&temp, &size); - break; - case PP_TEMP_EDGE: - /* get current edge temperature */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_EDGE_TEMP, - (void *)&temp, &size); - break; - case PP_TEMP_MEM: - /* get current memory temperature */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_TEMP, - (void *)&temp, &size); - break; - default: - r = -EINVAL; - break; - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp); -} - -static ssize_t amdgpu_hwmon_show_temp_thresh(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int hyst = to_sensor_dev_attr(attr)->index; - int temp; - - if (hyst) - temp = adev->pm.dpm.thermal.min_temp; - else - temp = adev->pm.dpm.thermal.max_temp; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp); -} - -static ssize_t amdgpu_hwmon_show_hotspot_temp_thresh(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int hyst = to_sensor_dev_attr(attr)->index; - int temp; - - if (hyst) - temp = adev->pm.dpm.thermal.min_hotspot_temp; - else - temp = adev->pm.dpm.thermal.max_hotspot_crit_temp; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp); -} - -static ssize_t amdgpu_hwmon_show_mem_temp_thresh(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int hyst = to_sensor_dev_attr(attr)->index; - int temp; - - if (hyst) - temp = adev->pm.dpm.thermal.min_mem_temp; - else - temp = adev->pm.dpm.thermal.max_mem_crit_temp; - - return snprintf(buf, PAGE_SIZE, "%d\n", temp); -} - -static ssize_t amdgpu_hwmon_show_temp_label(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int channel = to_sensor_dev_attr(attr)->index; - - if (channel >= PP_TEMP_MAX) - return -EINVAL; - - return snprintf(buf, PAGE_SIZE, "%s\n", temp_label[channel].label); -} - -static ssize_t amdgpu_hwmon_show_temp_emergency(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int channel = to_sensor_dev_attr(attr)->index; - int temp = 0; - - if (channel >= PP_TEMP_MAX) - return -EINVAL; - - switch (channel) { - case PP_TEMP_JUNCTION: - temp = adev->pm.dpm.thermal.max_hotspot_emergency_temp; - break; - case PP_TEMP_EDGE: - temp = adev->pm.dpm.thermal.max_edge_emergency_temp; - break; - case PP_TEMP_MEM: - temp = adev->pm.dpm.thermal.max_mem_emergency_temp; - break; - } - - return snprintf(buf, PAGE_SIZE, "%d\n", temp); -} - -static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 pwm_mode = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(adev->ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return ret; - } - - 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); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return sprintf(buf, "%i\n", pwm_mode); -} - -static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err, ret; - int value; - - if (adev->in_gpu_reset) - return -EPERM; - - err = kstrtoint(buf, 10, &value); - if (err) - return err; - - ret = pm_runtime_get_sync(adev->ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return ret; - } - - 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); - return -EINVAL; - } - - amdgpu_dpm_set_fan_control_mode(adev, value); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return count; -} - -static ssize_t amdgpu_hwmon_get_pwm1_min(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%i\n", 0); -} - -static ssize_t amdgpu_hwmon_get_pwm1_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%i\n", 255); -} - -static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 value; - u32 pwm_mode; - - if (adev->in_gpu_reset) - return -EPERM; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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); - - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pr_info("manual fan speed control should be enabled first\n"); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - return -EINVAL; - } - - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - value = (value * 100) / 255; - - if (is_support_sw_smu(adev)) - err = smu_set_fan_speed_percent(&adev->smu, value); - else if (adev->powerplay.pp_funcs->set_fan_speed_percent) - err = amdgpu_dpm_set_fan_speed_percent(adev, value); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - return count; -} - -static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 speed = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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) - err = amdgpu_dpm_get_fan_speed_percent(adev, &speed); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - speed = (speed * 255) / 100; - - return sprintf(buf, "%i\n", speed); -} - -static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 speed = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - return sprintf(buf, "%i\n", speed); -} - -static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 min_rpm = 0; - u32 size = sizeof(min_rpm); - int r; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, - (void *)&min_rpm, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", min_rpm); -} - -static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 max_rpm = 0; - u32 size = sizeof(max_rpm); - int r; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, - (void *)&max_rpm, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", max_rpm); -} - -static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 rpm = 0; - - if (adev->in_gpu_reset) - return -EPERM; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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) - err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - return sprintf(buf, "%i\n", rpm); -} - -static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 value; - u32 pwm_mode; - - if (adev->in_gpu_reset) - return -EPERM; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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); - - if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - return -ENODATA; - } - - err = kstrtou32(buf, 10, &value); - if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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) - err = amdgpu_dpm_set_fan_speed_rpm(adev, value); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - return count; -} - -static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 pwm_mode = 0; - int ret; - - if (adev->in_gpu_reset) - return -EPERM; - - ret = pm_runtime_get_sync(adev->ddev->dev); - if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return ret; - } - - 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); - return -EINVAL; - } - - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); -} - -static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - int value; - u32 pwm_mode; - - if (adev->in_gpu_reset) - return -EPERM; - - err = kstrtoint(buf, 10, &value); - if (err) - return err; - - if (value == 0) - pwm_mode = AMD_FAN_CTRL_AUTO; - else if (value == 1) - pwm_mode = AMD_FAN_CTRL_MANUAL; - else - return -EINVAL; - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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); - return -EINVAL; - } - amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return count; -} - -static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 vddgfx; - int r, size = sizeof(vddgfx); - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - /* get the voltage */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, - (void *)&vddgfx, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", vddgfx); -} - -static ssize_t amdgpu_hwmon_show_vddgfx_label(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "vddgfx\n"); -} - -static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 vddnb; - int r, size = sizeof(vddnb); - - if (adev->in_gpu_reset) - return -EPERM; - - /* only APUs have vddnb */ - if (!(adev->flags & AMD_IS_APU)) - return -EINVAL; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - /* get the voltage */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, - (void *)&vddnb, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%d\n", vddnb); -} - -static ssize_t amdgpu_hwmon_show_vddnb_label(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "vddnb\n"); -} - -static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - u32 query = 0; - int r, size = sizeof(u32); - unsigned uw; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - /* get the voltage */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, - (void *)&query, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - /* convert to microwatts */ - uw = (query >> 8) * 1000000 + (query & 0xff) * 1000; - - return snprintf(buf, PAGE_SIZE, "%u\n", uw); -} - -static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "%i\n", 0); -} - -static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - uint32_t limit = 0; - ssize_t size; - int r; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - if (is_support_sw_smu(adev)) { - smu_get_power_limit(&adev->smu, &limit, true); - size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); - } else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) { - adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, true); - size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); - } else { - size = snprintf(buf, PAGE_SIZE, "\n"); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return size; -} - -static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - uint32_t limit = 0; - ssize_t size; - int r; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - if (is_support_sw_smu(adev)) { - smu_get_power_limit(&adev->smu, &limit, false); - size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); - } else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) { - adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, false); - size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); - } else { - size = snprintf(buf, PAGE_SIZE, "\n"); - } - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - return size; -} - - -static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - int err; - u32 value; - - if (adev->in_gpu_reset) - return -EPERM; - - if (amdgpu_sriov_vf(adev)) - return -EINVAL; - - err = kstrtou32(buf, 10, &value); - if (err) - return err; - - value = value / 1000000; /* convert to Watt */ - - - err = pm_runtime_get_sync(adev->ddev->dev); - if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return err; - } - - 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) - err = adev->powerplay.pp_funcs->set_power_limit(adev->powerplay.pp_handle, value); - else - err = -EINVAL; - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (err) - return err; - - return count; -} - -static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - uint32_t sclk; - int r, size = sizeof(sclk); - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - /* get the sclk */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, - (void *)&sclk, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%u\n", sclk * 10 * 1000); -} - -static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "sclk\n"); -} - -static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct amdgpu_device *adev = dev_get_drvdata(dev); - uint32_t mclk; - int r, size = sizeof(mclk); - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(adev->ddev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); - return r; - } - - /* get the sclk */ - r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, - (void *)&mclk, &size); - - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); - - if (r) - return r; - - return snprintf(buf, PAGE_SIZE, "%u\n", mclk * 10 * 1000); -} - -static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "mclk\n"); -} - -/** - * DOC: hwmon - * - * The amdgpu driver exposes the following sensor interfaces: - * - * - GPU temperature (via the on-die sensor) - * - * - GPU voltage - * - * - Northbridge voltage (APUs only) - * - * - GPU power - * - * - GPU fan - * - * - GPU gfx/compute engine clock - * - * - GPU memory clock (dGPU only) - * - * hwmon interfaces for GPU temperature: - * - * - temp[1-3]_input: the on die GPU temperature in millidegrees Celsius - * - temp2_input and temp3_input are supported on SOC15 dGPUs only - * - * - temp[1-3]_label: temperature channel label - * - temp2_label and temp3_label are supported on SOC15 dGPUs only - * - * - temp[1-3]_crit: temperature critical max value in millidegrees Celsius - * - temp2_crit and temp3_crit are supported on SOC15 dGPUs only - * - * - temp[1-3]_crit_hyst: temperature hysteresis for critical limit in millidegrees Celsius - * - temp2_crit_hyst and temp3_crit_hyst are supported on SOC15 dGPUs only - * - * - temp[1-3]_emergency: temperature emergency max value(asic shutdown) in millidegrees Celsius - * - these are supported on SOC15 dGPUs only - * - * hwmon interfaces for GPU voltage: - * - * - in0_input: the voltage on the GPU in millivolts - * - * - in1_input: the voltage on the Northbridge in millivolts - * - * hwmon interfaces for GPU power: - * - * - power1_average: average power used by the GPU in microWatts - * - * - power1_cap_min: minimum cap supported in microWatts - * - * - power1_cap_max: maximum cap supported in microWatts - * - * - power1_cap: selected power cap in microWatts - * - * hwmon interfaces for GPU fan: - * - * - pwm1: pulse width modulation fan level (0-255) - * - * - pwm1_enable: pulse width modulation fan control method (0: no fan speed control, 1: manual fan speed control using pwm interface, 2: automatic fan speed control) - * - * - pwm1_min: pulse width modulation fan control minimum level (0) - * - * - pwm1_max: pulse width modulation fan control maximum level (255) - * - * - fan1_min: an minimum value Unit: revolution/min (RPM) - * - * - fan1_max: an maxmum value Unit: revolution/max (RPM) - * - * - fan1_input: fan speed in RPM - * - * - fan[1-\*]_target: Desired fan speed Unit: revolution/min (RPM) - * - * - fan[1-\*]_enable: Enable or disable the sensors.1: Enable 0: Disable - * - * hwmon interfaces for GPU clocks: - * - * - freq1_input: the gfx/compute clock in hertz - * - * - freq2_input: the memory clock in hertz - * - * You can use hwmon tools like sensors to view this information on your system. - * - */ - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_EDGE); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_EDGE); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_JUNCTION); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, amdgpu_hwmon_show_hotspot_temp_thresh, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, amdgpu_hwmon_show_hotspot_temp_thresh, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_JUNCTION); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_MEM); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, amdgpu_hwmon_show_mem_temp_thresh, NULL, 0); -static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, amdgpu_hwmon_show_mem_temp_thresh, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_MEM); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_EDGE); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_JUNCTION); -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_MEM); -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, amdgpu_hwmon_set_pwm1, 0); -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0); -static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, amdgpu_hwmon_get_fan1_min, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, amdgpu_hwmon_get_fan1_max, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_target, amdgpu_hwmon_set_fan1_target, 0); -static SENSOR_DEVICE_ATTR(fan1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_enable, amdgpu_hwmon_set_fan1_enable, 0); -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0); -static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, amdgpu_hwmon_show_vddnb_label, NULL, 0); -static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, NULL, 0); -static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0); -static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0); -static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); -static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0); -static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0); -static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0); -static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label, NULL, 0); - -static struct attribute *hwmon_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_emergency.dev_attr.attr, - &sensor_dev_attr_temp2_emergency.dev_attr.attr, - &sensor_dev_attr_temp3_emergency.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_min.dev_attr.attr, - &sensor_dev_attr_pwm1_max.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_max.dev_attr.attr, - &sensor_dev_attr_fan1_target.dev_attr.attr, - &sensor_dev_attr_fan1_enable.dev_attr.attr, - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_label.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_label.dev_attr.attr, - &sensor_dev_attr_power1_average.dev_attr.attr, - &sensor_dev_attr_power1_cap_max.dev_attr.attr, - &sensor_dev_attr_power1_cap_min.dev_attr.attr, - &sensor_dev_attr_power1_cap.dev_attr.attr, - &sensor_dev_attr_freq1_input.dev_attr.attr, - &sensor_dev_attr_freq1_label.dev_attr.attr, - &sensor_dev_attr_freq2_input.dev_attr.attr, - &sensor_dev_attr_freq2_label.dev_attr.attr, - NULL -}; - -static umode_t hwmon_attributes_visible(struct kobject *kobj, - struct attribute *attr, int index) -{ - struct device *dev = kobj_to_dev(kobj); - struct amdgpu_device *adev = dev_get_drvdata(dev); - umode_t effective_mode = attr->mode; - - /* under multi-vf mode, the hwmon attributes are all not supported */ - if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) - return 0; - - /* there is no fan under pp one vf mode */ - if (amdgpu_sriov_is_pp_one_vf(adev) && - (attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - - /* Skip fan attributes if fan is not present */ - if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - - /* Skip fan attributes on APU */ - if ((adev->flags & AMD_IS_APU) && - (attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - - /* Skip crit temp on APU */ - if ((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ) && - (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || - attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) - return 0; - - /* Skip limit attributes if DPM is not enabled */ - if (!adev->pm.dpm_enabled && - (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || - attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr || - attr == &sensor_dev_attr_pwm1.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_input.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr || - attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_target.dev_attr.attr || - attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) - return 0; - - if (!is_support_sw_smu(adev)) { - /* mask fan attributes if we have no bindings for this asic to expose */ - if ((!adev->powerplay.pp_funcs->get_fan_speed_percent && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ - (!adev->powerplay.pp_funcs->get_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ - effective_mode &= ~S_IRUGO; - - if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && - attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ - (!adev->powerplay.pp_funcs->set_fan_control_mode && - attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ - effective_mode &= ~S_IWUSR; - } - - if (((adev->flags & AMD_IS_APU) || - adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ - adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ - (attr == &sensor_dev_attr_power1_average.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| - attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) - return 0; - - if (!is_support_sw_smu(adev)) { - /* hide max/min values if we can't both query and manage the fan */ - if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && - !adev->powerplay.pp_funcs->get_fan_speed_percent) && - (!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || - attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) - return 0; - - if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm && - !adev->powerplay.pp_funcs->get_fan_speed_rpm) && - (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || - attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) - return 0; - } - - if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ - adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ - (attr == &sensor_dev_attr_in0_input.dev_attr.attr || - attr == &sensor_dev_attr_in0_label.dev_attr.attr)) - return 0; - - /* only APUs have vddnb */ - if (!(adev->flags & AMD_IS_APU) && - (attr == &sensor_dev_attr_in1_input.dev_attr.attr || - attr == &sensor_dev_attr_in1_label.dev_attr.attr)) - return 0; - - /* no mclk on APUs */ - if ((adev->flags & AMD_IS_APU) && - (attr == &sensor_dev_attr_freq2_input.dev_attr.attr || - attr == &sensor_dev_attr_freq2_label.dev_attr.attr)) - return 0; - - /* only SOC15 dGPUs support hotspot and mem temperatures */ - if (((adev->flags & AMD_IS_APU) || - adev->asic_type < CHIP_VEGA10) && - (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr || - attr == &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr || - attr == &sensor_dev_attr_temp3_crit.dev_attr.attr || - attr == &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr || - attr == &sensor_dev_attr_temp1_emergency.dev_attr.attr || - attr == &sensor_dev_attr_temp2_emergency.dev_attr.attr || - attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr || - attr == &sensor_dev_attr_temp2_input.dev_attr.attr || - attr == &sensor_dev_attr_temp3_input.dev_attr.attr || - attr == &sensor_dev_attr_temp2_label.dev_attr.attr || - attr == &sensor_dev_attr_temp3_label.dev_attr.attr)) - return 0; - - return effective_mode; -} - -static const struct attribute_group hwmon_attrgroup = { - .attrs = hwmon_attributes, - .is_visible = hwmon_attributes_visible, -}; - -static const struct attribute_group *hwmon_groups[] = { - &hwmon_attrgroup, - NULL -}; - -int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) -{ - int ret; - uint32_t mask = 0; - - if (adev->pm.sysfs_initialized) - return 0; - - if (adev->pm.dpm_enabled == 0) - return 0; - - INIT_LIST_HEAD(&adev->pm.pm_attr_list); - - adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, - DRIVER_NAME, adev, - hwmon_groups); - if (IS_ERR(adev->pm.int_hwmon_dev)) { - ret = PTR_ERR(adev->pm.int_hwmon_dev); - dev_err(adev->dev, - "Unable to register hwmon device: %d\n", ret); - return ret; - } - - switch (amdgpu_virt_get_sriov_vf_mode(adev)) { - case SRIOV_VF_MODE_ONE_VF: - mask = ATTR_FLAG_ONEVF; - break; - case SRIOV_VF_MODE_MULTI_VF: - mask = 0; - break; - case SRIOV_VF_MODE_BARE_METAL: - default: - mask = ATTR_FLAG_MASK_ALL; - break; - } - - ret = amdgpu_device_attr_create_groups(adev, - amdgpu_device_attrs, - ARRAY_SIZE(amdgpu_device_attrs), - mask, - &adev->pm.pm_attr_list); - if (ret) - return ret; - - adev->pm.sysfs_initialized = true; - - return 0; -} - -void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) -{ - if (adev->pm.dpm_enabled == 0) - return; - - if (adev->pm.int_hwmon_dev) - hwmon_device_unregister(adev->pm.int_hwmon_dev); - - amdgpu_device_attr_remove_groups(adev, &adev->pm.pm_attr_list); -} - -/* - * Debugfs info - */ -#if defined(CONFIG_DEBUG_FS) - -static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) -{ - uint32_t value; - uint64_t value64; - uint32_t query = 0; - int size; - - /* GPU Clocks */ - size = sizeof(value); - seq_printf(m, "GFX Clocks and Power:\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (MCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (SCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (PSTATE_SCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (PSTATE_MCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&value, &size)) - seq_printf(m, "\t%u mV (VDDGFX)\n", value); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size)) - seq_printf(m, "\t%u mV (VDDNB)\n", value); - size = sizeof(uint32_t); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size)) - seq_printf(m, "\t%u.%u W (average GPU)\n", query >> 8, query & 0xff); - size = sizeof(value); - seq_printf(m, "\n"); - - /* GPU Temp */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&value, &size)) - seq_printf(m, "GPU Temperature: %u C\n", value/1000); - - /* GPU Load */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size)) - seq_printf(m, "GPU Load: %u %%\n", value); - /* MEM Load */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size)) - seq_printf(m, "MEM Load: %u %%\n", value); - - seq_printf(m, "\n"); - - /* SMC feature mask */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size)) - seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64); - - if (adev->asic_type > CHIP_VEGA20) { - /* VCN clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) { - if (!value) { - seq_printf(m, "VCN: Disabled\n"); - } else { - seq_printf(m, "VCN: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (DCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (VCLK)\n", value/100); - } - } - seq_printf(m, "\n"); - } else { - /* UVD clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) { - if (!value) { - seq_printf(m, "UVD: Disabled\n"); - } else { - seq_printf(m, "UVD: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (DCLK)\n", value/100); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (VCLK)\n", value/100); - } - } - seq_printf(m, "\n"); - - /* VCE clocks */ - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) { - if (!value) { - seq_printf(m, "VCE: Disabled\n"); - } else { - seq_printf(m, "VCE: Enabled\n"); - if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size)) - seq_printf(m, "\t%u MHz (ECCLK)\n", value/100); - } - } - } - - return 0; -} - -static void amdgpu_parse_cg_state(struct seq_file *m, u32 flags) -{ - int i; - - for (i = 0; clocks[i].flag; i++) - seq_printf(m, "\t%s: %s\n", clocks[i].name, - (flags & clocks[i].flag) ? "On" : "Off"); -} - -static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; - u32 flags = 0; - int r; - - if (adev->in_gpu_reset) - return -EPERM; - - r = pm_runtime_get_sync(dev->dev); - if (r < 0) { - pm_runtime_put_autosuspend(dev->dev); - return r; - } - - if (!adev->pm.dpm_enabled) { - seq_printf(m, "dpm not enabled\n"); - pm_runtime_mark_last_busy(dev->dev); - pm_runtime_put_autosuspend(dev->dev); - return 0; - } - - if (!is_support_sw_smu(adev) && - adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { - mutex_lock(&adev->pm.mutex); - if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) - adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); - else - seq_printf(m, "Debugfs support not implemented for this asic\n"); - mutex_unlock(&adev->pm.mutex); - r = 0; - } else { - r = amdgpu_debugfs_pm_info_pp(m, adev); - } - if (r) - goto out; - - amdgpu_device_ip_get_clockgating_state(adev, &flags); - - 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); - - return r; -} - -static const struct drm_info_list amdgpu_pm_info_list[] = { - {"amdgpu_pm_info", amdgpu_debugfs_pm_info, 0, NULL}, -}; -#endif - -int amdgpu_debugfs_pm_init(struct amdgpu_device *adev) -{ -#if defined(CONFIG_DEBUG_FS) - return amdgpu_debugfs_add_files(adev, amdgpu_pm_info_list, ARRAY_SIZE(amdgpu_pm_info_list)); -#else - return 0; -#endif -} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h deleted file mode 100644 index 45a22e101d15..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef __AMDGPU_PM_H__ -#define __AMDGPU_PM_H__ - -struct cg_flag_name -{ - u32 flag; - const char *name; -}; - -enum amdgpu_device_attr_flags { - ATTR_FLAG_BASIC = (1 << 0), - ATTR_FLAG_ONEVF = (1 << 16), -}; - -#define ATTR_FLAG_TYPE_MASK (0x0000ffff) -#define ATTR_FLAG_MODE_MASK (0xffff0000) -#define ATTR_FLAG_MASK_ALL (0xffffffff) - -enum amdgpu_device_attr_states { - ATTR_STATE_UNSUPPORTED = 0, - ATTR_STATE_SUPPORTED, -}; - -struct amdgpu_device_attr { - struct device_attribute dev_attr; - enum amdgpu_device_attr_flags flags; - int (*attr_update)(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, - uint32_t mask, enum amdgpu_device_attr_states *states); - -}; - -struct amdgpu_device_attr_entry { - struct list_head entry; - struct amdgpu_device_attr *attr; -}; - -#define to_amdgpu_device_attr(_dev_attr) \ - container_of(_dev_attr, struct amdgpu_device_attr, dev_attr) - -#define __AMDGPU_DEVICE_ATTR(_name, _mode, _show, _store, _flags, ...) \ - { .dev_attr = __ATTR(_name, _mode, _show, _store), \ - .flags = _flags, \ - ##__VA_ARGS__, } - -#define AMDGPU_DEVICE_ATTR(_name, _mode, _flags, ...) \ - __AMDGPU_DEVICE_ATTR(_name, _mode, \ - amdgpu_get_##_name, amdgpu_set_##_name, \ - _flags, ##__VA_ARGS__) - -#define AMDGPU_DEVICE_ATTR_RW(_name, _flags, ...) \ - AMDGPU_DEVICE_ATTR(_name, S_IRUGO | S_IWUSR, \ - _flags, ##__VA_ARGS__) - -#define AMDGPU_DEVICE_ATTR_RO(_name, _flags, ...) \ - __AMDGPU_DEVICE_ATTR(_name, S_IRUGO, \ - amdgpu_get_##_name, NULL, \ - _flags, ##__VA_ARGS__) - -int amdgpu_pm_sysfs_init(struct amdgpu_device *adev); -int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev); -void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev); -void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev); - -int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/cik_dpm.h b/drivers/gpu/drm/amd/amdgpu/cik_dpm.h deleted file mode 100644 index 2fcc4b60153c..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/cik_dpm.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2014 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 __CIK_DPM_H__ -#define __CIK_DPM_H__ - -extern const struct amdgpu_ip_block_version kv_smu_ip_block; - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c deleted file mode 100644 index 4b3faaccecb9..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ /dev/null @@ -1,3382 +0,0 @@ -/* - * Copyright 2013 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 "amdgpu.h" -#include "amdgpu_pm.h" -#include "cikd.h" -#include "atom.h" -#include "amdgpu_atombios.h" -#include "amdgpu_dpm.h" -#include "kv_dpm.h" -#include "gfx_v7_0.h" -#include - -#include "smu/smu_7_0_0_d.h" -#include "smu/smu_7_0_0_sh_mask.h" - -#include "gca/gfx_7_2_d.h" -#include "gca/gfx_7_2_sh_mask.h" - -#define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define KV_MINIMUM_ENGINE_CLOCK 800 -#define SMC_RAM_END 0x40000 - -static const struct amd_pm_funcs kv_dpm_funcs; - -static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev); -static int kv_enable_nb_dpm(struct amdgpu_device *adev, - bool enable); -static void kv_init_graphics_levels(struct amdgpu_device *adev); -static int kv_calculate_ds_divider(struct amdgpu_device *adev); -static int kv_calculate_nbps_level_settings(struct amdgpu_device *adev); -static int kv_calculate_dpm_settings(struct amdgpu_device *adev); -static void kv_enable_new_levels(struct amdgpu_device *adev); -static void kv_program_nbps_index_settings(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps); -static int kv_set_enabled_level(struct amdgpu_device *adev, u32 level); -static int kv_set_enabled_levels(struct amdgpu_device *adev); -static int kv_force_dpm_highest(struct amdgpu_device *adev); -static int kv_force_dpm_lowest(struct amdgpu_device *adev); -static void kv_apply_state_adjust_rules(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps, - struct amdgpu_ps *old_rps); -static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, - int min_temp, int max_temp); -static int kv_init_fps_limits(struct amdgpu_device *adev); - -static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate); -static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate); - - -static u32 kv_convert_vid2_to_vid7(struct amdgpu_device *adev, - struct sumo_vid_mapping_table *vid_mapping_table, - u32 vid_2bit) -{ - struct amdgpu_clock_voltage_dependency_table *vddc_sclk_table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - u32 i; - - if (vddc_sclk_table && vddc_sclk_table->count) { - if (vid_2bit < vddc_sclk_table->count) - return vddc_sclk_table->entries[vid_2bit].v; - else - return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v; - } else { - for (i = 0; i < vid_mapping_table->num_entries; i++) { - if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) - return vid_mapping_table->entries[i].vid_7bit; - } - return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; - } -} - -static u32 kv_convert_vid7_to_vid2(struct amdgpu_device *adev, - struct sumo_vid_mapping_table *vid_mapping_table, - u32 vid_7bit) -{ - struct amdgpu_clock_voltage_dependency_table *vddc_sclk_table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - u32 i; - - if (vddc_sclk_table && vddc_sclk_table->count) { - for (i = 0; i < vddc_sclk_table->count; i++) { - if (vddc_sclk_table->entries[i].v == vid_7bit) - return i; - } - return vddc_sclk_table->count - 1; - } else { - for (i = 0; i < vid_mapping_table->num_entries; i++) { - if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) - return vid_mapping_table->entries[i].vid_2bit; - } - - return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; - } -} - -static void sumo_take_smu_control(struct amdgpu_device *adev, bool enable) -{ -/* This bit selects who handles display phy powergating. - * Clear the bit to let atom handle it. - * Set it to let the driver handle it. - * For now we just let atom handle it. - */ -#if 0 - u32 v = RREG32(mmDOUT_SCRATCH3); - - if (enable) - v |= 0x4; - else - v &= 0xFFFFFFFB; - - WREG32(mmDOUT_SCRATCH3, v); -#endif -} - -static void sumo_construct_sclk_voltage_mapping_table(struct amdgpu_device *adev, - struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table, - ATOM_AVAILABLE_SCLK_LIST *table) -{ - u32 i; - u32 n = 0; - u32 prev_sclk = 0; - - for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { - if (table[i].ulSupportedSCLK > prev_sclk) { - sclk_voltage_mapping_table->entries[n].sclk_frequency = - table[i].ulSupportedSCLK; - sclk_voltage_mapping_table->entries[n].vid_2bit = - table[i].usVoltageIndex; - prev_sclk = table[i].ulSupportedSCLK; - n++; - } - } - - sclk_voltage_mapping_table->num_max_dpm_entries = n; -} - -static void sumo_construct_vid_mapping_table(struct amdgpu_device *adev, - struct sumo_vid_mapping_table *vid_mapping_table, - ATOM_AVAILABLE_SCLK_LIST *table) -{ - u32 i, j; - - for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { - if (table[i].ulSupportedSCLK != 0) { - vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = - table[i].usVoltageID; - vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = - table[i].usVoltageIndex; - } - } - - for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { - if (vid_mapping_table->entries[i].vid_7bit == 0) { - for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) { - if (vid_mapping_table->entries[j].vid_7bit != 0) { - vid_mapping_table->entries[i] = - vid_mapping_table->entries[j]; - vid_mapping_table->entries[j].vid_7bit = 0; - break; - } - } - - if (j == SUMO_MAX_NUMBER_VOLTAGES) - break; - } - } - - vid_mapping_table->num_entries = i; -} - -#if 0 -static const struct kv_lcac_config_values sx_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 1, 4, 1 }, - { 2, 5, 1 }, - { 3, 4, 2 }, - { 4, 1, 1 }, - { 5, 5, 2 }, - { 6, 6, 1 }, - { 7, 9, 2 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_values mc0_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_values mc1_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_values mc2_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_values mc3_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_values cpl_local_cac_cfg_kv[] = -{ - { 0, 4, 1 }, - { 1, 4, 1 }, - { 2, 5, 1 }, - { 3, 4, 1 }, - { 4, 1, 1 }, - { 5, 5, 1 }, - { 6, 6, 1 }, - { 7, 9, 1 }, - { 8, 4, 1 }, - { 9, 2, 1 }, - { 10, 3, 1 }, - { 11, 6, 1 }, - { 12, 8, 2 }, - { 13, 1, 1 }, - { 14, 2, 1 }, - { 15, 3, 1 }, - { 16, 1, 1 }, - { 17, 4, 1 }, - { 18, 3, 1 }, - { 19, 1, 1 }, - { 20, 8, 1 }, - { 21, 5, 1 }, - { 22, 1, 1 }, - { 23, 1, 1 }, - { 24, 4, 1 }, - { 27, 6, 1 }, - { 28, 1, 1 }, - { 0xffffffff } -}; - -static const struct kv_lcac_config_reg sx0_cac_config_reg[] = -{ - { 0xc0400d00, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; - -static const struct kv_lcac_config_reg mc0_cac_config_reg[] = -{ - { 0xc0400d30, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; - -static const struct kv_lcac_config_reg mc1_cac_config_reg[] = -{ - { 0xc0400d3c, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; - -static const struct kv_lcac_config_reg mc2_cac_config_reg[] = -{ - { 0xc0400d48, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; - -static const struct kv_lcac_config_reg mc3_cac_config_reg[] = -{ - { 0xc0400d54, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; - -static const struct kv_lcac_config_reg cpl_cac_config_reg[] = -{ - { 0xc0400d80, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } -}; -#endif - -static const struct kv_pt_config_reg didt_config_kv[] = -{ - { 0x10, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x10, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x10, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x10, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x11, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x11, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x11, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x11, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x12, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x12, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x12, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x12, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x2, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, - { 0x2, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, - { 0x2, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, - { 0x1, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x1, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x0, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x30, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x30, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x30, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x30, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x31, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x31, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x31, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x31, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x32, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x32, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x32, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x32, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x22, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, - { 0x22, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, - { 0x22, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, - { 0x21, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x21, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x20, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x50, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x50, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x50, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x50, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x51, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x51, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x51, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x51, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x52, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x52, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x52, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x52, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x42, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, - { 0x42, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, - { 0x42, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, - { 0x41, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x41, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x40, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x70, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x70, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x70, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x70, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x71, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x71, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x71, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x71, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x72, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x72, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x72, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x72, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0x62, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, - { 0x62, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, - { 0x62, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, - { 0x61, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x61, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, - { 0x60, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, - { 0xFFFFFFFF } -}; - -static struct kv_ps *kv_get_ps(struct amdgpu_ps *rps) -{ - struct kv_ps *ps = rps->ps_priv; - - return ps; -} - -static struct kv_power_info *kv_get_pi(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = adev->pm.dpm.priv; - - return pi; -} - -#if 0 -static void kv_program_local_cac_table(struct amdgpu_device *adev, - const struct kv_lcac_config_values *local_cac_table, - const struct kv_lcac_config_reg *local_cac_reg) -{ - u32 i, count, data; - const struct kv_lcac_config_values *values = local_cac_table; - - while (values->block_id != 0xffffffff) { - count = values->signal_id; - for (i = 0; i < count; i++) { - data = ((values->block_id << local_cac_reg->block_shift) & - local_cac_reg->block_mask); - data |= ((i << local_cac_reg->signal_shift) & - local_cac_reg->signal_mask); - data |= ((values->t << local_cac_reg->t_shift) & - local_cac_reg->t_mask); - data |= ((1 << local_cac_reg->enable_shift) & - local_cac_reg->enable_mask); - WREG32_SMC(local_cac_reg->cntl, data); - } - values++; - } -} -#endif - -static int kv_program_pt_config_registers(struct amdgpu_device *adev, - const struct kv_pt_config_reg *cac_config_regs) -{ - const struct kv_pt_config_reg *config_regs = cac_config_regs; - u32 data; - u32 cache = 0; - - if (config_regs == NULL) - return -EINVAL; - - while (config_regs->offset != 0xFFFFFFFF) { - if (config_regs->type == KV_CONFIGREG_CACHE) { - cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); - } else { - switch (config_regs->type) { - case KV_CONFIGREG_SMC_IND: - data = RREG32_SMC(config_regs->offset); - break; - case KV_CONFIGREG_DIDT_IND: - data = RREG32_DIDT(config_regs->offset); - break; - default: - data = RREG32(config_regs->offset); - break; - } - - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - data |= cache; - cache = 0; - - switch (config_regs->type) { - case KV_CONFIGREG_SMC_IND: - WREG32_SMC(config_regs->offset, data); - break; - case KV_CONFIGREG_DIDT_IND: - WREG32_DIDT(config_regs->offset, data); - break; - default: - WREG32(config_regs->offset, data); - break; - } - } - config_regs++; - } - - return 0; -} - -static void kv_do_enable_didt(struct amdgpu_device *adev, bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 data; - - if (pi->caps_sq_ramping) { - data = RREG32_DIDT(ixDIDT_SQ_CTRL0); - if (enable) - data |= DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_SQ_CTRL0, data); - } - - if (pi->caps_db_ramping) { - data = RREG32_DIDT(ixDIDT_DB_CTRL0); - if (enable) - data |= DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_DB_CTRL0, data); - } - - if (pi->caps_td_ramping) { - data = RREG32_DIDT(ixDIDT_TD_CTRL0); - if (enable) - data |= DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_TD_CTRL0, data); - } - - if (pi->caps_tcp_ramping) { - data = RREG32_DIDT(ixDIDT_TCP_CTRL0); - if (enable) - data |= DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - else - data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; - WREG32_DIDT(ixDIDT_TCP_CTRL0, data); - } -} - -static int kv_enable_didt(struct amdgpu_device *adev, bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - if (pi->caps_sq_ramping || - pi->caps_db_ramping || - pi->caps_td_ramping || - pi->caps_tcp_ramping) { - amdgpu_gfx_rlc_enter_safe_mode(adev); - - if (enable) { - ret = kv_program_pt_config_registers(adev, didt_config_kv); - if (ret) { - amdgpu_gfx_rlc_exit_safe_mode(adev); - return ret; - } - } - - kv_do_enable_didt(adev, enable); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - } - - return 0; -} - -#if 0 -static void kv_initialize_hardware_cac_manager(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - if (pi->caps_cac) { - WREG32_SMC(ixLCAC_SX0_OVR_SEL, 0); - WREG32_SMC(ixLCAC_SX0_OVR_VAL, 0); - kv_program_local_cac_table(adev, sx_local_cac_cfg_kv, sx0_cac_config_reg); - - WREG32_SMC(ixLCAC_MC0_OVR_SEL, 0); - WREG32_SMC(ixLCAC_MC0_OVR_VAL, 0); - kv_program_local_cac_table(adev, mc0_local_cac_cfg_kv, mc0_cac_config_reg); - - WREG32_SMC(ixLCAC_MC1_OVR_SEL, 0); - WREG32_SMC(ixLCAC_MC1_OVR_VAL, 0); - kv_program_local_cac_table(adev, mc1_local_cac_cfg_kv, mc1_cac_config_reg); - - WREG32_SMC(ixLCAC_MC2_OVR_SEL, 0); - WREG32_SMC(ixLCAC_MC2_OVR_VAL, 0); - kv_program_local_cac_table(adev, mc2_local_cac_cfg_kv, mc2_cac_config_reg); - - WREG32_SMC(ixLCAC_MC3_OVR_SEL, 0); - WREG32_SMC(ixLCAC_MC3_OVR_VAL, 0); - kv_program_local_cac_table(adev, mc3_local_cac_cfg_kv, mc3_cac_config_reg); - - WREG32_SMC(ixLCAC_CPL_OVR_SEL, 0); - WREG32_SMC(ixLCAC_CPL_OVR_VAL, 0); - kv_program_local_cac_table(adev, cpl_local_cac_cfg_kv, cpl_cac_config_reg); - } -} -#endif - -static int kv_enable_smc_cac(struct amdgpu_device *adev, bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret = 0; - - if (pi->caps_cac) { - if (enable) { - ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableCac); - if (ret) - pi->cac_enabled = false; - else - pi->cac_enabled = true; - } else if (pi->cac_enabled) { - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableCac); - pi->cac_enabled = false; - } - } - - return ret; -} - -static int kv_process_firmware_header(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 tmp; - int ret; - - ret = amdgpu_kv_read_smc_sram_dword(adev, SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, DpmTable), - &tmp, pi->sram_end); - - if (ret == 0) - pi->dpm_table_start = tmp; - - ret = amdgpu_kv_read_smc_sram_dword(adev, SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, SoftRegisters), - &tmp, pi->sram_end); - - if (ret == 0) - pi->soft_regs_start = tmp; - - return ret; -} - -static int kv_enable_dpm_voltage_scaling(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - pi->graphics_voltage_change_enable = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsVoltageChangeEnable), - &pi->graphics_voltage_change_enable, - sizeof(u8), pi->sram_end); - - return ret; -} - -static int kv_set_dpm_interval(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - pi->graphics_interval = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsInterval), - &pi->graphics_interval, - sizeof(u8), pi->sram_end); - - return ret; -} - -static int kv_set_dpm_boot_state(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsBootLevel), - &pi->graphics_boot_level, - sizeof(u8), pi->sram_end); - - return ret; -} - -static void kv_program_vc(struct amdgpu_device *adev) -{ - WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0x3FFFC100); -} - -static void kv_clear_vc(struct amdgpu_device *adev) -{ - WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0); -} - -static int kv_set_divider_value(struct amdgpu_device *adev, - u32 index, u32 sclk) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct atom_clock_dividers dividers; - int ret; - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - sclk, false, ÷rs); - if (ret) - return ret; - - pi->graphics_level[index].SclkDid = (u8)dividers.post_div; - pi->graphics_level[index].SclkFrequency = cpu_to_be32(sclk); - - return 0; -} - -static u16 kv_convert_8bit_index_to_voltage(struct amdgpu_device *adev, - u16 voltage) -{ - return 6200 - (voltage * 25); -} - -static u16 kv_convert_2bit_index_to_voltage(struct amdgpu_device *adev, - u32 vid_2bit) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 vid_8bit = kv_convert_vid2_to_vid7(adev, - &pi->sys_info.vid_mapping_table, - vid_2bit); - - return kv_convert_8bit_index_to_voltage(adev, (u16)vid_8bit); -} - - -static int kv_set_vid(struct amdgpu_device *adev, u32 index, u32 vid) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->graphics_level[index].VoltageDownH = (u8)pi->voltage_drop_t; - pi->graphics_level[index].MinVddNb = - cpu_to_be32(kv_convert_2bit_index_to_voltage(adev, vid)); - - return 0; -} - -static int kv_set_at(struct amdgpu_device *adev, u32 index, u32 at) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->graphics_level[index].AT = cpu_to_be16((u16)at); - - return 0; -} - -static void kv_dpm_power_level_enable(struct amdgpu_device *adev, - u32 index, bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->graphics_level[index].EnabledForActivity = enable ? 1 : 0; -} - -static void kv_start_dpm(struct amdgpu_device *adev) -{ - u32 tmp = RREG32_SMC(ixGENERAL_PWRMGT); - - tmp |= GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK; - WREG32_SMC(ixGENERAL_PWRMGT, tmp); - - amdgpu_kv_smc_dpm_enable(adev, true); -} - -static void kv_stop_dpm(struct amdgpu_device *adev) -{ - amdgpu_kv_smc_dpm_enable(adev, false); -} - -static void kv_start_am(struct amdgpu_device *adev) -{ - u32 sclk_pwrmgt_cntl = RREG32_SMC(ixSCLK_PWRMGT_CNTL); - - sclk_pwrmgt_cntl &= ~(SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | - SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK); - sclk_pwrmgt_cntl |= SCLK_PWRMGT_CNTL__DYNAMIC_PM_EN_MASK; - - WREG32_SMC(ixSCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); -} - -static void kv_reset_am(struct amdgpu_device *adev) -{ - u32 sclk_pwrmgt_cntl = RREG32_SMC(ixSCLK_PWRMGT_CNTL); - - sclk_pwrmgt_cntl |= (SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | - SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK); - - WREG32_SMC(ixSCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); -} - -static int kv_freeze_sclk_dpm(struct amdgpu_device *adev, bool freeze) -{ - return amdgpu_kv_notify_message_to_smu(adev, freeze ? - PPSMC_MSG_SCLKDPM_FreezeLevel : PPSMC_MSG_SCLKDPM_UnfreezeLevel); -} - -static int kv_force_lowest_valid(struct amdgpu_device *adev) -{ - return kv_force_dpm_lowest(adev); -} - -static int kv_unforce_levels(struct amdgpu_device *adev) -{ - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) - return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NoForcedLevel); - else - return kv_set_enabled_levels(adev); -} - -static int kv_update_sclk_t(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 low_sclk_interrupt_t = 0; - int ret = 0; - - if (pi->caps_sclk_throttle_low_notification) { - low_sclk_interrupt_t = cpu_to_be32(pi->low_sclk_interrupt_t); - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, LowSclkInterruptT), - (u8 *)&low_sclk_interrupt_t, - sizeof(u32), pi->sram_end); - } - return ret; -} - -static int kv_program_bootup_state(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - - if (table && table->count) { - for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { - if (table->entries[i].clk == pi->boot_pl.sclk) - break; - } - - pi->graphics_boot_level = (u8)i; - kv_dpm_power_level_enable(adev, i, true); - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - - if (table->num_max_dpm_entries == 0) - return -EINVAL; - - for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { - if (table->entries[i].sclk_frequency == pi->boot_pl.sclk) - break; - } - - pi->graphics_boot_level = (u8)i; - kv_dpm_power_level_enable(adev, i, true); - } - return 0; -} - -static int kv_enable_auto_thermal_throttling(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - pi->graphics_therm_throttle_enable = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsThermThrottleEnable), - &pi->graphics_therm_throttle_enable, - sizeof(u8), pi->sram_end); - - return ret; -} - -static int kv_upload_dpm_settings(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsLevel), - (u8 *)&pi->graphics_level, - sizeof(SMU7_Fusion_GraphicsLevel) * SMU7_MAX_LEVELS_GRAPHICS, - pi->sram_end); - - if (ret) - return ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsDpmLevelCount), - &pi->graphics_dpm_level_count, - sizeof(u8), pi->sram_end); - - return ret; -} - -static u32 kv_get_clock_difference(u32 a, u32 b) -{ - return (a >= b) ? a - b : b - a; -} - -static u32 kv_get_clk_bypass(struct amdgpu_device *adev, u32 clk) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 value; - - if (pi->caps_enable_dfs_bypass) { - if (kv_get_clock_difference(clk, 40000) < 200) - value = 3; - else if (kv_get_clock_difference(clk, 30000) < 200) - value = 2; - else if (kv_get_clock_difference(clk, 20000) < 200) - value = 7; - else if (kv_get_clock_difference(clk, 15000) < 200) - value = 6; - else if (kv_get_clock_difference(clk, 10000) < 200) - value = 8; - else - value = 0; - } else { - value = 0; - } - - return value; -} - -static int kv_populate_uvd_table(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_uvd_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; - struct atom_clock_dividers dividers; - int ret; - u32 i; - - if (table == NULL || table->count == 0) - return 0; - - pi->uvd_level_count = 0; - for (i = 0; i < table->count; i++) { - if (pi->high_voltage_t && - (pi->high_voltage_t < table->entries[i].v)) - break; - - pi->uvd_level[i].VclkFrequency = cpu_to_be32(table->entries[i].vclk); - pi->uvd_level[i].DclkFrequency = cpu_to_be32(table->entries[i].dclk); - pi->uvd_level[i].MinVddNb = cpu_to_be16(table->entries[i].v); - - pi->uvd_level[i].VClkBypassCntl = - (u8)kv_get_clk_bypass(adev, table->entries[i].vclk); - pi->uvd_level[i].DClkBypassCntl = - (u8)kv_get_clk_bypass(adev, table->entries[i].dclk); - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - table->entries[i].vclk, false, ÷rs); - if (ret) - return ret; - pi->uvd_level[i].VclkDivider = (u8)dividers.post_div; - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - table->entries[i].dclk, false, ÷rs); - if (ret) - return ret; - pi->uvd_level[i].DclkDivider = (u8)dividers.post_div; - - pi->uvd_level_count++; - } - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, UvdLevelCount), - (u8 *)&pi->uvd_level_count, - sizeof(u8), pi->sram_end); - if (ret) - return ret; - - pi->uvd_interval = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, UVDInterval), - &pi->uvd_interval, - sizeof(u8), pi->sram_end); - if (ret) - return ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, UvdLevel), - (u8 *)&pi->uvd_level, - sizeof(SMU7_Fusion_UvdLevel) * SMU7_MAX_LEVELS_UVD, - pi->sram_end); - - return ret; - -} - -static int kv_populate_vce_table(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - u32 i; - struct amdgpu_vce_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; - struct atom_clock_dividers dividers; - - if (table == NULL || table->count == 0) - return 0; - - pi->vce_level_count = 0; - for (i = 0; i < table->count; i++) { - if (pi->high_voltage_t && - pi->high_voltage_t < table->entries[i].v) - break; - - pi->vce_level[i].Frequency = cpu_to_be32(table->entries[i].evclk); - pi->vce_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); - - pi->vce_level[i].ClkBypassCntl = - (u8)kv_get_clk_bypass(adev, table->entries[i].evclk); - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - table->entries[i].evclk, false, ÷rs); - if (ret) - return ret; - pi->vce_level[i].Divider = (u8)dividers.post_div; - - pi->vce_level_count++; - } - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, VceLevelCount), - (u8 *)&pi->vce_level_count, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - pi->vce_interval = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, VCEInterval), - (u8 *)&pi->vce_interval, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, VceLevel), - (u8 *)&pi->vce_level, - sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_VCE, - pi->sram_end); - - return ret; -} - -static int kv_populate_samu_table(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; - struct atom_clock_dividers dividers; - int ret; - u32 i; - - if (table == NULL || table->count == 0) - return 0; - - pi->samu_level_count = 0; - for (i = 0; i < table->count; i++) { - if (pi->high_voltage_t && - pi->high_voltage_t < table->entries[i].v) - break; - - pi->samu_level[i].Frequency = cpu_to_be32(table->entries[i].clk); - pi->samu_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); - - pi->samu_level[i].ClkBypassCntl = - (u8)kv_get_clk_bypass(adev, table->entries[i].clk); - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - table->entries[i].clk, false, ÷rs); - if (ret) - return ret; - pi->samu_level[i].Divider = (u8)dividers.post_div; - - pi->samu_level_count++; - } - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, SamuLevelCount), - (u8 *)&pi->samu_level_count, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - pi->samu_interval = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, SAMUInterval), - (u8 *)&pi->samu_interval, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, SamuLevel), - (u8 *)&pi->samu_level, - sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_SAMU, - pi->sram_end); - if (ret) - return ret; - - return ret; -} - - -static int kv_populate_acp_table(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; - struct atom_clock_dividers dividers; - int ret; - u32 i; - - if (table == NULL || table->count == 0) - return 0; - - pi->acp_level_count = 0; - for (i = 0; i < table->count; i++) { - pi->acp_level[i].Frequency = cpu_to_be32(table->entries[i].clk); - pi->acp_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - table->entries[i].clk, false, ÷rs); - if (ret) - return ret; - pi->acp_level[i].Divider = (u8)dividers.post_div; - - pi->acp_level_count++; - } - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, AcpLevelCount), - (u8 *)&pi->acp_level_count, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - pi->acp_interval = 1; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, ACPInterval), - (u8 *)&pi->acp_interval, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, AcpLevel), - (u8 *)&pi->acp_level, - sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_ACP, - pi->sram_end); - if (ret) - return ret; - - return ret; -} - -static void kv_calculate_dfs_bypass_settings(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - - if (table && table->count) { - for (i = 0; i < pi->graphics_dpm_level_count; i++) { - if (pi->caps_enable_dfs_bypass) { - if (kv_get_clock_difference(table->entries[i].clk, 40000) < 200) - pi->graphics_level[i].ClkBypassCntl = 3; - else if (kv_get_clock_difference(table->entries[i].clk, 30000) < 200) - pi->graphics_level[i].ClkBypassCntl = 2; - else if (kv_get_clock_difference(table->entries[i].clk, 26600) < 200) - pi->graphics_level[i].ClkBypassCntl = 7; - else if (kv_get_clock_difference(table->entries[i].clk , 20000) < 200) - pi->graphics_level[i].ClkBypassCntl = 6; - else if (kv_get_clock_difference(table->entries[i].clk , 10000) < 200) - pi->graphics_level[i].ClkBypassCntl = 8; - else - pi->graphics_level[i].ClkBypassCntl = 0; - } else { - pi->graphics_level[i].ClkBypassCntl = 0; - } - } - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - for (i = 0; i < pi->graphics_dpm_level_count; i++) { - if (pi->caps_enable_dfs_bypass) { - if (kv_get_clock_difference(table->entries[i].sclk_frequency, 40000) < 200) - pi->graphics_level[i].ClkBypassCntl = 3; - else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 30000) < 200) - pi->graphics_level[i].ClkBypassCntl = 2; - else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 26600) < 200) - pi->graphics_level[i].ClkBypassCntl = 7; - else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 20000) < 200) - pi->graphics_level[i].ClkBypassCntl = 6; - else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 10000) < 200) - pi->graphics_level[i].ClkBypassCntl = 8; - else - pi->graphics_level[i].ClkBypassCntl = 0; - } else { - pi->graphics_level[i].ClkBypassCntl = 0; - } - } - } -} - -static int kv_enable_ulv(struct amdgpu_device *adev, bool enable) -{ - return amdgpu_kv_notify_message_to_smu(adev, enable ? - PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); -} - -static void kv_reset_acp_boot_level(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->acp_boot_level = 0xff; -} - -static void kv_update_current_ps(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct kv_ps *new_ps = kv_get_ps(rps); - struct kv_power_info *pi = kv_get_pi(adev); - - pi->current_rps = *rps; - pi->current_ps = *new_ps; - pi->current_rps.ps_priv = &pi->current_ps; - adev->pm.dpm.current_ps = &pi->current_rps; -} - -static void kv_update_requested_ps(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct kv_ps *new_ps = kv_get_ps(rps); - struct kv_power_info *pi = kv_get_pi(adev); - - pi->requested_rps = *rps; - pi->requested_ps = *new_ps; - pi->requested_rps.ps_priv = &pi->requested_ps; - adev->pm.dpm.requested_ps = &pi->requested_rps; -} - -static void kv_dpm_enable_bapm(void *handle, bool enable) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - if (pi->bapm_enable) { - ret = amdgpu_kv_smc_bapm_enable(adev, enable); - if (ret) - DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); - } -} - -static int kv_dpm_enable(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - ret = kv_process_firmware_header(adev); - if (ret) { - DRM_ERROR("kv_process_firmware_header failed\n"); - return ret; - } - kv_init_fps_limits(adev); - kv_init_graphics_levels(adev); - ret = kv_program_bootup_state(adev); - if (ret) { - DRM_ERROR("kv_program_bootup_state failed\n"); - return ret; - } - kv_calculate_dfs_bypass_settings(adev); - ret = kv_upload_dpm_settings(adev); - if (ret) { - DRM_ERROR("kv_upload_dpm_settings failed\n"); - return ret; - } - ret = kv_populate_uvd_table(adev); - if (ret) { - DRM_ERROR("kv_populate_uvd_table failed\n"); - return ret; - } - ret = kv_populate_vce_table(adev); - if (ret) { - DRM_ERROR("kv_populate_vce_table failed\n"); - return ret; - } - ret = kv_populate_samu_table(adev); - if (ret) { - DRM_ERROR("kv_populate_samu_table failed\n"); - return ret; - } - ret = kv_populate_acp_table(adev); - if (ret) { - DRM_ERROR("kv_populate_acp_table failed\n"); - return ret; - } - kv_program_vc(adev); -#if 0 - kv_initialize_hardware_cac_manager(adev); -#endif - kv_start_am(adev); - if (pi->enable_auto_thermal_throttling) { - ret = kv_enable_auto_thermal_throttling(adev); - if (ret) { - DRM_ERROR("kv_enable_auto_thermal_throttling failed\n"); - return ret; - } - } - ret = kv_enable_dpm_voltage_scaling(adev); - if (ret) { - DRM_ERROR("kv_enable_dpm_voltage_scaling failed\n"); - return ret; - } - ret = kv_set_dpm_interval(adev); - if (ret) { - DRM_ERROR("kv_set_dpm_interval failed\n"); - return ret; - } - ret = kv_set_dpm_boot_state(adev); - if (ret) { - DRM_ERROR("kv_set_dpm_boot_state failed\n"); - return ret; - } - ret = kv_enable_ulv(adev, true); - if (ret) { - DRM_ERROR("kv_enable_ulv failed\n"); - return ret; - } - kv_start_dpm(adev); - ret = kv_enable_didt(adev, true); - if (ret) { - DRM_ERROR("kv_enable_didt failed\n"); - return ret; - } - ret = kv_enable_smc_cac(adev, true); - if (ret) { - DRM_ERROR("kv_enable_smc_cac failed\n"); - return ret; - } - - kv_reset_acp_boot_level(adev); - - ret = amdgpu_kv_smc_bapm_enable(adev, false); - if (ret) { - DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); - return ret; - } - - if (adev->irq.installed && - amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { - ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX); - if (ret) { - DRM_ERROR("kv_set_thermal_temperature_range failed\n"); - return ret; - } - amdgpu_irq_get(adev, &adev->pm.dpm.thermal.irq, - AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); - amdgpu_irq_get(adev, &adev->pm.dpm.thermal.irq, - AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); - } - - return ret; -} - -static void kv_dpm_disable(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, - AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); - amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, - AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); - - amdgpu_kv_smc_bapm_enable(adev, false); - - if (adev->asic_type == CHIP_MULLINS) - kv_enable_nb_dpm(adev, false); - - /* powerup blocks */ - kv_dpm_powergate_acp(adev, false); - kv_dpm_powergate_samu(adev, false); - if (pi->caps_vce_pg) /* power on the VCE block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); - if (pi->caps_uvd_pg) /* power on the UVD block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); - - kv_enable_smc_cac(adev, false); - kv_enable_didt(adev, false); - kv_clear_vc(adev); - kv_stop_dpm(adev); - kv_enable_ulv(adev, false); - kv_reset_am(adev); - - kv_update_current_ps(adev, adev->pm.dpm.boot_ps); -} - -#if 0 -static int kv_write_smc_soft_register(struct amdgpu_device *adev, - u16 reg_offset, u32 value) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - return amdgpu_kv_copy_bytes_to_smc(adev, pi->soft_regs_start + reg_offset, - (u8 *)&value, sizeof(u16), pi->sram_end); -} - -static int kv_read_smc_soft_register(struct amdgpu_device *adev, - u16 reg_offset, u32 *value) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - return amdgpu_kv_read_smc_sram_dword(adev, pi->soft_regs_start + reg_offset, - value, pi->sram_end); -} -#endif - -static void kv_init_sclk_t(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->low_sclk_interrupt_t = 0; -} - -static int kv_init_fps_limits(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret = 0; - - if (pi->caps_fps) { - u16 tmp; - - tmp = 45; - pi->fps_high_t = cpu_to_be16(tmp); - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, FpsHighT), - (u8 *)&pi->fps_high_t, - sizeof(u16), pi->sram_end); - - tmp = 30; - pi->fps_low_t = cpu_to_be16(tmp); - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, FpsLowT), - (u8 *)&pi->fps_low_t, - sizeof(u16), pi->sram_end); - - } - return ret; -} - -static void kv_init_powergate_state(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->uvd_power_gated = false; - pi->vce_power_gated = false; - pi->samu_power_gated = false; - pi->acp_power_gated = false; - -} - -static int kv_enable_uvd_dpm(struct amdgpu_device *adev, bool enable) -{ - return amdgpu_kv_notify_message_to_smu(adev, enable ? - PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); -} - -static int kv_enable_vce_dpm(struct amdgpu_device *adev, bool enable) -{ - return amdgpu_kv_notify_message_to_smu(adev, enable ? - PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); -} - -static int kv_enable_samu_dpm(struct amdgpu_device *adev, bool enable) -{ - return amdgpu_kv_notify_message_to_smu(adev, enable ? - PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable); -} - -static int kv_enable_acp_dpm(struct amdgpu_device *adev, bool enable) -{ - return amdgpu_kv_notify_message_to_smu(adev, enable ? - PPSMC_MSG_ACPDPM_Enable : PPSMC_MSG_ACPDPM_Disable); -} - -static int kv_update_uvd_dpm(struct amdgpu_device *adev, bool gate) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_uvd_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; - int ret; - u32 mask; - - if (!gate) { - if (table->count) - pi->uvd_boot_level = table->count - 1; - else - pi->uvd_boot_level = 0; - - if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) { - mask = 1 << pi->uvd_boot_level; - } else { - mask = 0x1f; - } - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, UvdBootLevel), - (uint8_t *)&pi->uvd_boot_level, - sizeof(u8), pi->sram_end); - if (ret) - return ret; - - amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_UVDDPM_SetEnabledMask, - mask); - } - - return kv_enable_uvd_dpm(adev, !gate); -} - -static u8 kv_get_vce_boot_level(struct amdgpu_device *adev, u32 evclk) -{ - u8 i; - struct amdgpu_vce_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; - - for (i = 0; i < table->count; i++) { - if (table->entries[i].evclk >= evclk) - break; - } - - return i; -} - -static int kv_update_vce_dpm(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - struct amdgpu_ps *amdgpu_current_state) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_vce_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; - int ret; - - if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) { - if (pi->caps_stable_p_state) - pi->vce_boot_level = table->count - 1; - else - pi->vce_boot_level = kv_get_vce_boot_level(adev, amdgpu_new_state->evclk); - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, VceBootLevel), - (u8 *)&pi->vce_boot_level, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - if (pi->caps_stable_p_state) - amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (1 << pi->vce_boot_level)); - kv_enable_vce_dpm(adev, true); - } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) { - kv_enable_vce_dpm(adev, false); - } - - return 0; -} - -static int kv_update_samu_dpm(struct amdgpu_device *adev, bool gate) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; - int ret; - - if (!gate) { - if (pi->caps_stable_p_state) - pi->samu_boot_level = table->count - 1; - else - pi->samu_boot_level = 0; - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, SamuBootLevel), - (u8 *)&pi->samu_boot_level, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - if (pi->caps_stable_p_state) - amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_SAMUDPM_SetEnabledMask, - (1 << pi->samu_boot_level)); - } - - return kv_enable_samu_dpm(adev, !gate); -} - -static u8 kv_get_acp_boot_level(struct amdgpu_device *adev) -{ - u8 i; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; - - for (i = 0; i < table->count; i++) { - if (table->entries[i].clk >= 0) /* XXX */ - break; - } - - if (i >= table->count) - i = table->count - 1; - - return i; -} - -static void kv_update_acp_boot_level(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u8 acp_boot_level; - - if (!pi->caps_stable_p_state) { - acp_boot_level = kv_get_acp_boot_level(adev); - if (acp_boot_level != pi->acp_boot_level) { - pi->acp_boot_level = acp_boot_level; - amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_ACPDPM_SetEnabledMask, - (1 << pi->acp_boot_level)); - } - } -} - -static int kv_update_acp_dpm(struct amdgpu_device *adev, bool gate) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; - int ret; - - if (!gate) { - if (pi->caps_stable_p_state) - pi->acp_boot_level = table->count - 1; - else - pi->acp_boot_level = kv_get_acp_boot_level(adev); - - ret = amdgpu_kv_copy_bytes_to_smc(adev, - pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, AcpBootLevel), - (u8 *)&pi->acp_boot_level, - sizeof(u8), - pi->sram_end); - if (ret) - return ret; - - if (pi->caps_stable_p_state) - amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_ACPDPM_SetEnabledMask, - (1 << pi->acp_boot_level)); - } - - return kv_enable_acp_dpm(adev, !gate); -} - -static void kv_dpm_powergate_uvd(void *handle, bool gate) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - pi->uvd_power_gated = gate; - - if (gate) { - /* stop the UVD block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_GATE); - kv_update_uvd_dpm(adev, gate); - if (pi->caps_uvd_pg) - /* power off the UVD block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerOFF); - } else { - if (pi->caps_uvd_pg) - /* power on the UVD block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); - /* re-init the UVD block */ - kv_update_uvd_dpm(adev, gate); - - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_UNGATE); - } -} - -static void kv_dpm_powergate_vce(void *handle, bool gate) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - int ret; - - pi->vce_power_gated = gate; - - if (gate) { - /* stop the VCE block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - kv_enable_vce_dpm(adev, false); - if (pi->caps_vce_pg) /* power off the VCE block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); - } else { - if (pi->caps_vce_pg) /* power on the VCE block */ - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); - kv_enable_vce_dpm(adev, true); - /* re-init the VCE block */ - ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); - } -} - - -static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - if (pi->samu_power_gated == gate) - return; - - pi->samu_power_gated = gate; - - if (gate) { - kv_update_samu_dpm(adev, true); - if (pi->caps_samu_pg) - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SAMPowerOFF); - } else { - if (pi->caps_samu_pg) - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SAMPowerON); - kv_update_samu_dpm(adev, false); - } -} - -static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - if (pi->acp_power_gated == gate) - return; - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) - return; - - pi->acp_power_gated = gate; - - if (gate) { - kv_update_acp_dpm(adev, true); - if (pi->caps_acp_pg) - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_ACPPowerOFF); - } else { - if (pi->caps_acp_pg) - amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_ACPPowerON); - kv_update_acp_dpm(adev, false); - } -} - -static void kv_set_valid_clock_range(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps) -{ - struct kv_ps *new_ps = kv_get_ps(new_rps); - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - - if (table && table->count) { - for (i = 0; i < pi->graphics_dpm_level_count; i++) { - if ((table->entries[i].clk >= new_ps->levels[0].sclk) || - (i == (pi->graphics_dpm_level_count - 1))) { - pi->lowest_valid = i; - break; - } - } - - for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { - if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk) - break; - } - pi->highest_valid = i; - - if (pi->lowest_valid > pi->highest_valid) { - if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > - (table->entries[pi->lowest_valid].clk - new_ps->levels[new_ps->num_levels - 1].sclk)) - pi->highest_valid = pi->lowest_valid; - else - pi->lowest_valid = pi->highest_valid; - } - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - - for (i = 0; i < (int)pi->graphics_dpm_level_count; i++) { - if (table->entries[i].sclk_frequency >= new_ps->levels[0].sclk || - i == (int)(pi->graphics_dpm_level_count - 1)) { - pi->lowest_valid = i; - break; - } - } - - for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { - if (table->entries[i].sclk_frequency <= - new_ps->levels[new_ps->num_levels - 1].sclk) - break; - } - pi->highest_valid = i; - - if (pi->lowest_valid > pi->highest_valid) { - if ((new_ps->levels[0].sclk - - table->entries[pi->highest_valid].sclk_frequency) > - (table->entries[pi->lowest_valid].sclk_frequency - - new_ps->levels[new_ps->num_levels -1].sclk)) - pi->highest_valid = pi->lowest_valid; - else - pi->lowest_valid = pi->highest_valid; - } - } -} - -static int kv_update_dfs_bypass_settings(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps) -{ - struct kv_ps *new_ps = kv_get_ps(new_rps); - struct kv_power_info *pi = kv_get_pi(adev); - int ret = 0; - u8 clk_bypass_cntl; - - if (pi->caps_enable_dfs_bypass) { - clk_bypass_cntl = new_ps->need_dfs_bypass ? - pi->graphics_level[pi->graphics_boot_level].ClkBypassCntl : 0; - ret = amdgpu_kv_copy_bytes_to_smc(adev, - (pi->dpm_table_start + - offsetof(SMU7_Fusion_DpmTable, GraphicsLevel) + - (pi->graphics_boot_level * sizeof(SMU7_Fusion_GraphicsLevel)) + - offsetof(SMU7_Fusion_GraphicsLevel, ClkBypassCntl)), - &clk_bypass_cntl, - sizeof(u8), pi->sram_end); - } - - return ret; -} - -static int kv_enable_nb_dpm(struct amdgpu_device *adev, - bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - int ret = 0; - - if (enable) { - if (pi->enable_nb_dpm && !pi->nb_dpm_enabled) { - ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NBDPM_Enable); - if (ret == 0) - pi->nb_dpm_enabled = true; - } - } else { - if (pi->enable_nb_dpm && pi->nb_dpm_enabled) { - ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NBDPM_Disable); - if (ret == 0) - pi->nb_dpm_enabled = false; - } - } - - return ret; -} - -static int kv_dpm_force_performance_level(void *handle, - enum amd_dpm_forced_level level) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (level == AMD_DPM_FORCED_LEVEL_HIGH) { - ret = kv_force_dpm_highest(adev); - if (ret) - return ret; - } else if (level == AMD_DPM_FORCED_LEVEL_LOW) { - ret = kv_force_dpm_lowest(adev); - if (ret) - return ret; - } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) { - ret = kv_unforce_levels(adev); - if (ret) - return ret; - } - - adev->pm.dpm.forced_level = level; - - return 0; -} - -static int kv_dpm_pre_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; - struct amdgpu_ps *new_ps = &requested_ps; - - kv_update_requested_ps(adev, new_ps); - - kv_apply_state_adjust_rules(adev, - &pi->requested_rps, - &pi->current_rps); - - return 0; -} - -static int kv_dpm_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_ps *new_ps = &pi->requested_rps; - struct amdgpu_ps *old_ps = &pi->current_rps; - int ret; - - if (pi->bapm_enable) { - ret = amdgpu_kv_smc_bapm_enable(adev, adev->pm.ac_power); - if (ret) { - DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); - return ret; - } - } - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { - if (pi->enable_dpm) { - kv_set_valid_clock_range(adev, new_ps); - kv_update_dfs_bypass_settings(adev, new_ps); - ret = kv_calculate_ds_divider(adev); - if (ret) { - DRM_ERROR("kv_calculate_ds_divider failed\n"); - return ret; - } - kv_calculate_nbps_level_settings(adev); - kv_calculate_dpm_settings(adev); - kv_force_lowest_valid(adev); - kv_enable_new_levels(adev); - kv_upload_dpm_settings(adev); - kv_program_nbps_index_settings(adev, new_ps); - kv_unforce_levels(adev); - kv_set_enabled_levels(adev); - kv_force_lowest_valid(adev); - kv_unforce_levels(adev); - - ret = kv_update_vce_dpm(adev, new_ps, old_ps); - if (ret) { - DRM_ERROR("kv_update_vce_dpm failed\n"); - return ret; - } - kv_update_sclk_t(adev); - if (adev->asic_type == CHIP_MULLINS) - kv_enable_nb_dpm(adev, true); - } - } else { - if (pi->enable_dpm) { - kv_set_valid_clock_range(adev, new_ps); - kv_update_dfs_bypass_settings(adev, new_ps); - ret = kv_calculate_ds_divider(adev); - if (ret) { - DRM_ERROR("kv_calculate_ds_divider failed\n"); - return ret; - } - kv_calculate_nbps_level_settings(adev); - kv_calculate_dpm_settings(adev); - kv_freeze_sclk_dpm(adev, true); - kv_upload_dpm_settings(adev); - kv_program_nbps_index_settings(adev, new_ps); - kv_freeze_sclk_dpm(adev, false); - kv_set_enabled_levels(adev); - ret = kv_update_vce_dpm(adev, new_ps, old_ps); - if (ret) { - DRM_ERROR("kv_update_vce_dpm failed\n"); - return ret; - } - kv_update_acp_boot_level(adev); - kv_update_sclk_t(adev); - kv_enable_nb_dpm(adev, true); - } - } - - return 0; -} - -static void kv_dpm_post_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_ps *new_ps = &pi->requested_rps; - - kv_update_current_ps(adev, new_ps); -} - -static void kv_dpm_setup_asic(struct amdgpu_device *adev) -{ - sumo_take_smu_control(adev, true); - kv_init_powergate_state(adev); - kv_init_sclk_t(adev); -} - -#if 0 -static void kv_dpm_reset_asic(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { - kv_force_lowest_valid(adev); - kv_init_graphics_levels(adev); - kv_program_bootup_state(adev); - kv_upload_dpm_settings(adev); - kv_force_lowest_valid(adev); - kv_unforce_levels(adev); - } else { - kv_init_graphics_levels(adev); - kv_program_bootup_state(adev); - kv_freeze_sclk_dpm(adev, true); - kv_upload_dpm_settings(adev); - kv_freeze_sclk_dpm(adev, false); - kv_set_enabled_level(adev, pi->graphics_boot_level); - } -} -#endif - -static void kv_construct_max_power_limits_table(struct amdgpu_device *adev, - struct amdgpu_clock_and_voltage_limits *table) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - if (pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries > 0) { - int idx = pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1; - table->sclk = - pi->sys_info.sclk_voltage_mapping_table.entries[idx].sclk_frequency; - table->vddc = - kv_convert_2bit_index_to_voltage(adev, - pi->sys_info.sclk_voltage_mapping_table.entries[idx].vid_2bit); - } - - table->mclk = pi->sys_info.nbp_memory_clock[0]; -} - -static void kv_patch_voltage_values(struct amdgpu_device *adev) -{ - int i; - struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = - &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; - struct amdgpu_vce_clock_voltage_dependency_table *vce_table = - &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table *samu_table = - &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; - struct amdgpu_clock_voltage_dependency_table *acp_table = - &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; - - if (uvd_table->count) { - for (i = 0; i < uvd_table->count; i++) - uvd_table->entries[i].v = - kv_convert_8bit_index_to_voltage(adev, - uvd_table->entries[i].v); - } - - if (vce_table->count) { - for (i = 0; i < vce_table->count; i++) - vce_table->entries[i].v = - kv_convert_8bit_index_to_voltage(adev, - vce_table->entries[i].v); - } - - if (samu_table->count) { - for (i = 0; i < samu_table->count; i++) - samu_table->entries[i].v = - kv_convert_8bit_index_to_voltage(adev, - samu_table->entries[i].v); - } - - if (acp_table->count) { - for (i = 0; i < acp_table->count; i++) - acp_table->entries[i].v = - kv_convert_8bit_index_to_voltage(adev, - acp_table->entries[i].v); - } - -} - -static void kv_construct_boot_state(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->boot_pl.sclk = pi->sys_info.bootup_sclk; - pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; - pi->boot_pl.ds_divider_index = 0; - pi->boot_pl.ss_divider_index = 0; - pi->boot_pl.allow_gnb_slow = 1; - pi->boot_pl.force_nbp_state = 0; - pi->boot_pl.display_wm = 0; - pi->boot_pl.vce_wm = 0; -} - -static int kv_force_dpm_highest(struct amdgpu_device *adev) -{ - int ret; - u32 enable_mask, i; - - ret = amdgpu_kv_dpm_get_enable_mask(adev, &enable_mask); - if (ret) - return ret; - - for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) { - if (enable_mask & (1 << i)) - break; - } - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) - return amdgpu_kv_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DPM_ForceState, i); - else - return kv_set_enabled_level(adev, i); -} - -static int kv_force_dpm_lowest(struct amdgpu_device *adev) -{ - int ret; - u32 enable_mask, i; - - ret = amdgpu_kv_dpm_get_enable_mask(adev, &enable_mask); - if (ret) - return ret; - - for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { - if (enable_mask & (1 << i)) - break; - } - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) - return amdgpu_kv_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DPM_ForceState, i); - else - return kv_set_enabled_level(adev, i); -} - -static u8 kv_get_sleep_divider_id_from_clock(struct amdgpu_device *adev, - u32 sclk, u32 min_sclk_in_sr) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - u32 temp; - u32 min = max(min_sclk_in_sr, (u32)KV_MINIMUM_ENGINE_CLOCK); - - if (sclk < min) - return 0; - - if (!pi->caps_sclk_ds) - return 0; - - for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) { - temp = sclk >> i; - if (temp >= min) - break; - } - - return (u8)i; -} - -static int kv_get_high_voltage_limit(struct amdgpu_device *adev, int *limit) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - int i; - - if (table && table->count) { - for (i = table->count - 1; i >= 0; i--) { - if (pi->high_voltage_t && - (kv_convert_8bit_index_to_voltage(adev, table->entries[i].v) <= - pi->high_voltage_t)) { - *limit = i; - return 0; - } - } - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - - for (i = table->num_max_dpm_entries - 1; i >= 0; i--) { - if (pi->high_voltage_t && - (kv_convert_2bit_index_to_voltage(adev, table->entries[i].vid_2bit) <= - pi->high_voltage_t)) { - *limit = i; - return 0; - } - } - } - - *limit = 0; - return 0; -} - -static void kv_apply_state_adjust_rules(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps, - struct amdgpu_ps *old_rps) -{ - struct kv_ps *ps = kv_get_ps(new_rps); - struct kv_power_info *pi = kv_get_pi(adev); - u32 min_sclk = 10000; /* ??? */ - u32 sclk, mclk = 0; - int i, limit; - bool force_high; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - u32 stable_p_state_sclk = 0; - struct amdgpu_clock_and_voltage_limits *max_limits = - &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; - - if (new_rps->vce_active) { - new_rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; - new_rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; - } else { - new_rps->evclk = 0; - new_rps->ecclk = 0; - } - - mclk = max_limits->mclk; - sclk = min_sclk; - - if (pi->caps_stable_p_state) { - stable_p_state_sclk = (max_limits->sclk * 75) / 100; - - for (i = table->count - 1; i >= 0; i--) { - if (stable_p_state_sclk >= table->entries[i].clk) { - stable_p_state_sclk = table->entries[i].clk; - break; - } - } - - if (i > 0) - stable_p_state_sclk = table->entries[0].clk; - - sclk = stable_p_state_sclk; - } - - if (new_rps->vce_active) { - if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) - sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; - } - - ps->need_dfs_bypass = true; - - for (i = 0; i < ps->num_levels; i++) { - if (ps->levels[i].sclk < sclk) - ps->levels[i].sclk = sclk; - } - - if (table && table->count) { - for (i = 0; i < ps->num_levels; i++) { - if (pi->high_voltage_t && - (pi->high_voltage_t < - kv_convert_8bit_index_to_voltage(adev, ps->levels[i].vddc_index))) { - kv_get_high_voltage_limit(adev, &limit); - ps->levels[i].sclk = table->entries[limit].clk; - } - } - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - - for (i = 0; i < ps->num_levels; i++) { - if (pi->high_voltage_t && - (pi->high_voltage_t < - kv_convert_8bit_index_to_voltage(adev, ps->levels[i].vddc_index))) { - kv_get_high_voltage_limit(adev, &limit); - ps->levels[i].sclk = table->entries[limit].sclk_frequency; - } - } - } - - if (pi->caps_stable_p_state) { - for (i = 0; i < ps->num_levels; i++) { - ps->levels[i].sclk = stable_p_state_sclk; - } - } - - pi->video_start = new_rps->dclk || new_rps->vclk || - new_rps->evclk || new_rps->ecclk; - - if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == - ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) - pi->battery_state = true; - else - pi->battery_state = false; - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { - ps->dpm0_pg_nb_ps_lo = 0x1; - ps->dpm0_pg_nb_ps_hi = 0x0; - ps->dpmx_nb_ps_lo = 0x1; - ps->dpmx_nb_ps_hi = 0x0; - } else { - ps->dpm0_pg_nb_ps_lo = 0x3; - ps->dpm0_pg_nb_ps_hi = 0x0; - ps->dpmx_nb_ps_lo = 0x3; - ps->dpmx_nb_ps_hi = 0x0; - - if (pi->sys_info.nb_dpm_enable) { - force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || - pi->video_start || (adev->pm.dpm.new_active_crtc_count >= 3) || - pi->disable_nb_ps3_in_battery; - ps->dpm0_pg_nb_ps_lo = force_high ? 0x2 : 0x3; - ps->dpm0_pg_nb_ps_hi = 0x2; - ps->dpmx_nb_ps_lo = force_high ? 0x2 : 0x3; - ps->dpmx_nb_ps_hi = 0x2; - } - } -} - -static void kv_dpm_power_level_enabled_for_throttle(struct amdgpu_device *adev, - u32 index, bool enable) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - pi->graphics_level[index].EnabledForThrottle = enable ? 1 : 0; -} - -static int kv_calculate_ds_divider(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 sclk_in_sr = 10000; /* ??? */ - u32 i; - - if (pi->lowest_valid > pi->highest_valid) - return -EINVAL; - - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { - pi->graphics_level[i].DeepSleepDivId = - kv_get_sleep_divider_id_from_clock(adev, - be32_to_cpu(pi->graphics_level[i].SclkFrequency), - sclk_in_sr); - } - return 0; -} - -static int kv_calculate_nbps_level_settings(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - bool force_high; - struct amdgpu_clock_and_voltage_limits *max_limits = - &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; - u32 mclk = max_limits->mclk; - - if (pi->lowest_valid > pi->highest_valid) - return -EINVAL; - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { - pi->graphics_level[i].GnbSlow = 1; - pi->graphics_level[i].ForceNbPs1 = 0; - pi->graphics_level[i].UpH = 0; - } - - if (!pi->sys_info.nb_dpm_enable) - return 0; - - force_high = ((mclk >= pi->sys_info.nbp_memory_clock[3]) || - (adev->pm.dpm.new_active_crtc_count >= 3) || pi->video_start); - - if (force_high) { - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) - pi->graphics_level[i].GnbSlow = 0; - } else { - if (pi->battery_state) - pi->graphics_level[0].ForceNbPs1 = 1; - - pi->graphics_level[1].GnbSlow = 0; - pi->graphics_level[2].GnbSlow = 0; - pi->graphics_level[3].GnbSlow = 0; - pi->graphics_level[4].GnbSlow = 0; - } - } else { - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { - pi->graphics_level[i].GnbSlow = 1; - pi->graphics_level[i].ForceNbPs1 = 0; - pi->graphics_level[i].UpH = 0; - } - - if (pi->sys_info.nb_dpm_enable && pi->battery_state) { - pi->graphics_level[pi->lowest_valid].UpH = 0x28; - pi->graphics_level[pi->lowest_valid].GnbSlow = 0; - if (pi->lowest_valid != pi->highest_valid) - pi->graphics_level[pi->lowest_valid].ForceNbPs1 = 1; - } - } - return 0; -} - -static int kv_calculate_dpm_settings(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - - if (pi->lowest_valid > pi->highest_valid) - return -EINVAL; - - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) - pi->graphics_level[i].DisplayWatermark = (i == pi->highest_valid) ? 1 : 0; - - return 0; -} - -static void kv_init_graphics_levels(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - struct amdgpu_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; - - if (table && table->count) { - u32 vid_2bit; - - pi->graphics_dpm_level_count = 0; - for (i = 0; i < table->count; i++) { - if (pi->high_voltage_t && - (pi->high_voltage_t < - kv_convert_8bit_index_to_voltage(adev, table->entries[i].v))) - break; - - kv_set_divider_value(adev, i, table->entries[i].clk); - vid_2bit = kv_convert_vid7_to_vid2(adev, - &pi->sys_info.vid_mapping_table, - table->entries[i].v); - kv_set_vid(adev, i, vid_2bit); - kv_set_at(adev, i, pi->at[i]); - kv_dpm_power_level_enabled_for_throttle(adev, i, true); - pi->graphics_dpm_level_count++; - } - } else { - struct sumo_sclk_voltage_mapping_table *table = - &pi->sys_info.sclk_voltage_mapping_table; - - pi->graphics_dpm_level_count = 0; - for (i = 0; i < table->num_max_dpm_entries; i++) { - if (pi->high_voltage_t && - pi->high_voltage_t < - kv_convert_2bit_index_to_voltage(adev, table->entries[i].vid_2bit)) - break; - - kv_set_divider_value(adev, i, table->entries[i].sclk_frequency); - kv_set_vid(adev, i, table->entries[i].vid_2bit); - kv_set_at(adev, i, pi->at[i]); - kv_dpm_power_level_enabled_for_throttle(adev, i, true); - pi->graphics_dpm_level_count++; - } - } - - for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) - kv_dpm_power_level_enable(adev, i, false); -} - -static void kv_enable_new_levels(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i; - - for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { - if (i >= pi->lowest_valid && i <= pi->highest_valid) - kv_dpm_power_level_enable(adev, i, true); - } -} - -static int kv_set_enabled_level(struct amdgpu_device *adev, u32 level) -{ - u32 new_mask = (1 << level); - - return amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - new_mask); -} - -static int kv_set_enabled_levels(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - u32 i, new_mask = 0; - - for (i = pi->lowest_valid; i <= pi->highest_valid; i++) - new_mask |= (1 << i); - - return amdgpu_kv_send_msg_to_smc_with_parameter(adev, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - new_mask); -} - -static void kv_program_nbps_index_settings(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps) -{ - struct kv_ps *new_ps = kv_get_ps(new_rps); - struct kv_power_info *pi = kv_get_pi(adev); - u32 nbdpmconfig1; - - if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) - return; - - if (pi->sys_info.nb_dpm_enable) { - nbdpmconfig1 = RREG32_SMC(ixNB_DPM_CONFIG_1); - nbdpmconfig1 &= ~(NB_DPM_CONFIG_1__Dpm0PgNbPsLo_MASK | - NB_DPM_CONFIG_1__Dpm0PgNbPsHi_MASK | - NB_DPM_CONFIG_1__DpmXNbPsLo_MASK | - NB_DPM_CONFIG_1__DpmXNbPsHi_MASK); - nbdpmconfig1 |= (new_ps->dpm0_pg_nb_ps_lo << NB_DPM_CONFIG_1__Dpm0PgNbPsLo__SHIFT) | - (new_ps->dpm0_pg_nb_ps_hi << NB_DPM_CONFIG_1__Dpm0PgNbPsHi__SHIFT) | - (new_ps->dpmx_nb_ps_lo << NB_DPM_CONFIG_1__DpmXNbPsLo__SHIFT) | - (new_ps->dpmx_nb_ps_hi << NB_DPM_CONFIG_1__DpmXNbPsHi__SHIFT); - WREG32_SMC(ixNB_DPM_CONFIG_1, nbdpmconfig1); - } -} - -static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, - int min_temp, int max_temp) -{ - int low_temp = 0 * 1000; - int high_temp = 255 * 1000; - u32 tmp; - - if (low_temp < min_temp) - low_temp = min_temp; - if (high_temp > max_temp) - high_temp = max_temp; - if (high_temp < low_temp) { - DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); - return -EINVAL; - } - - tmp = RREG32_SMC(ixCG_THERMAL_INT_CTRL); - tmp &= ~(CG_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK | - CG_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK); - tmp |= ((49 + (high_temp / 1000)) << CG_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT) | - ((49 + (low_temp / 1000)) << CG_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT); - WREG32_SMC(ixCG_THERMAL_INT_CTRL, tmp); - - adev->pm.dpm.thermal.min_temp = low_temp; - adev->pm.dpm.thermal.max_temp = high_temp; - - return 0; -} - -union igp_info { - struct _ATOM_INTEGRATED_SYSTEM_INFO info; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; - struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; -}; - -static int kv_parse_sys_info_table(struct amdgpu_device *adev) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct amdgpu_mode_info *mode_info = &adev->mode_info; - int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); - union igp_info *igp_info; - u8 frev, crev; - u16 data_offset; - int i; - - if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) { - igp_info = (union igp_info *)(mode_info->atom_context->bios + - data_offset); - - if (crev != 8) { - DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); - return -EINVAL; - } - pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_8.ulBootUpEngineClock); - pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_8.ulBootUpUMAClock); - pi->sys_info.bootup_nb_voltage_index = - le16_to_cpu(igp_info->info_8.usBootUpNBVoltage); - if (igp_info->info_8.ucHtcTmpLmt == 0) - pi->sys_info.htc_tmp_lmt = 203; - else - pi->sys_info.htc_tmp_lmt = igp_info->info_8.ucHtcTmpLmt; - if (igp_info->info_8.ucHtcHystLmt == 0) - pi->sys_info.htc_hyst_lmt = 5; - else - pi->sys_info.htc_hyst_lmt = igp_info->info_8.ucHtcHystLmt; - if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { - DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); - } - - if (le32_to_cpu(igp_info->info_8.ulSystemConfig) & (1 << 3)) - pi->sys_info.nb_dpm_enable = true; - else - pi->sys_info.nb_dpm_enable = false; - - for (i = 0; i < KV_NUM_NBPSTATES; i++) { - pi->sys_info.nbp_memory_clock[i] = - le32_to_cpu(igp_info->info_8.ulNbpStateMemclkFreq[i]); - pi->sys_info.nbp_n_clock[i] = - le32_to_cpu(igp_info->info_8.ulNbpStateNClkFreq[i]); - } - if (le32_to_cpu(igp_info->info_8.ulGPUCapInfo) & - SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) - pi->caps_enable_dfs_bypass = true; - - sumo_construct_sclk_voltage_mapping_table(adev, - &pi->sys_info.sclk_voltage_mapping_table, - igp_info->info_8.sAvail_SCLK); - - sumo_construct_vid_mapping_table(adev, - &pi->sys_info.vid_mapping_table, - igp_info->info_8.sAvail_SCLK); - - kv_construct_max_power_limits_table(adev, - &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac); - } - return 0; -} - -union power_info { - struct _ATOM_POWERPLAY_INFO info; - struct _ATOM_POWERPLAY_INFO_V2 info_2; - struct _ATOM_POWERPLAY_INFO_V3 info_3; - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; -}; - -union pplib_clock_info { - struct _ATOM_PPLIB_R600_CLOCK_INFO r600; - struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; - struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; - struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; -}; - -union pplib_power_state { - struct _ATOM_PPLIB_STATE v1; - struct _ATOM_PPLIB_STATE_V2 v2; -}; - -static void kv_patch_boot_state(struct amdgpu_device *adev, - struct kv_ps *ps) -{ - struct kv_power_info *pi = kv_get_pi(adev); - - ps->num_levels = 1; - ps->levels[0] = pi->boot_pl; -} - -static void kv_parse_pplib_non_clock_info(struct amdgpu_device *adev, - struct amdgpu_ps *rps, - struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, - u8 table_rev) -{ - struct kv_ps *ps = kv_get_ps(rps); - - rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); - rps->class = le16_to_cpu(non_clock_info->usClassification); - rps->class2 = le16_to_cpu(non_clock_info->usClassification2); - - if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { - rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); - rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); - } else { - rps->vclk = 0; - rps->dclk = 0; - } - - if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { - adev->pm.dpm.boot_ps = rps; - kv_patch_boot_state(adev, ps); - } - if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - adev->pm.dpm.uvd_ps = rps; -} - -static void kv_parse_pplib_clock_info(struct amdgpu_device *adev, - struct amdgpu_ps *rps, int index, - union pplib_clock_info *clock_info) -{ - struct kv_power_info *pi = kv_get_pi(adev); - struct kv_ps *ps = kv_get_ps(rps); - struct kv_pl *pl = &ps->levels[index]; - u32 sclk; - - sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); - sclk |= clock_info->sumo.ucEngineClockHigh << 16; - pl->sclk = sclk; - pl->vddc_index = clock_info->sumo.vddcIndex; - - ps->num_levels = index + 1; - - if (pi->caps_sclk_ds) { - pl->ds_divider_index = 5; - pl->ss_divider_index = 5; - } -} - -static int kv_parse_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; - union pplib_power_state *power_state; - int i, j, k, non_clock_array_index, clock_array_index; - union pplib_clock_info *clock_info; - struct _StateArray *state_array; - struct _ClockInfoArray *clock_info_array; - struct _NonClockInfoArray *non_clock_info_array; - union power_info *power_info; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - u8 *power_state_offset; - struct kv_ps *ps; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - amdgpu_add_thermal_controller(adev); - - state_array = (struct _StateArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usStateArrayOffset)); - clock_info_array = (struct _ClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); - non_clock_info_array = (struct _NonClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - - adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, - sizeof(struct amdgpu_ps), - GFP_KERNEL); - if (!adev->pm.dpm.ps) - return -ENOMEM; - power_state_offset = (u8 *)state_array->states; - for (i = 0; i < state_array->ucNumEntries; i++) { - u8 *idx; - power_state = (union pplib_power_state *)power_state_offset; - non_clock_array_index = power_state->v2.nonClockInfoIndex; - non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) - &non_clock_info_array->nonClockInfo[non_clock_array_index]; - ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL); - if (ps == NULL) { - kfree(adev->pm.dpm.ps); - return -ENOMEM; - } - adev->pm.dpm.ps[i].ps_priv = ps; - k = 0; - idx = (u8 *)&power_state->v2.clockInfoIndex[0]; - for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { - clock_array_index = idx[j]; - if (clock_array_index >= clock_info_array->ucNumEntries) - continue; - if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) - break; - clock_info = (union pplib_clock_info *) - ((u8 *)&clock_info_array->clockInfo[0] + - (clock_array_index * clock_info_array->ucEntrySize)); - kv_parse_pplib_clock_info(adev, - &adev->pm.dpm.ps[i], k, - clock_info); - k++; - } - kv_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], - non_clock_info, - non_clock_info_array->ucEntrySize); - power_state_offset += 2 + power_state->v2.ucNumDPMLevels; - } - adev->pm.dpm.num_ps = state_array->ucNumEntries; - - /* fill in the vce power states */ - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { - u32 sclk; - clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; - clock_info = (union pplib_clock_info *) - &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; - sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); - sclk |= clock_info->sumo.ucEngineClockHigh << 16; - adev->pm.dpm.vce_states[i].sclk = sclk; - adev->pm.dpm.vce_states[i].mclk = 0; - } - - return 0; -} - -static int kv_dpm_init(struct amdgpu_device *adev) -{ - struct kv_power_info *pi; - int ret, i; - - pi = kzalloc(sizeof(struct kv_power_info), GFP_KERNEL); - if (pi == NULL) - return -ENOMEM; - adev->pm.dpm.priv = pi; - - ret = amdgpu_get_platform_caps(adev); - if (ret) - return ret; - - ret = amdgpu_parse_extended_power_table(adev); - if (ret) - return ret; - - for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) - pi->at[i] = TRINITY_AT_DFLT; - - pi->sram_end = SMC_RAM_END; - - pi->enable_nb_dpm = true; - - pi->caps_power_containment = true; - pi->caps_cac = true; - pi->enable_didt = false; - if (pi->enable_didt) { - pi->caps_sq_ramping = true; - pi->caps_db_ramping = true; - pi->caps_td_ramping = true; - pi->caps_tcp_ramping = true; - } - - if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) - pi->caps_sclk_ds = true; - else - pi->caps_sclk_ds = false; - - pi->enable_auto_thermal_throttling = true; - pi->disable_nb_ps3_in_battery = false; - if (amdgpu_bapm == 0) - pi->bapm_enable = false; - else - pi->bapm_enable = true; - pi->voltage_drop_t = 0; - pi->caps_sclk_throttle_low_notification = false; - pi->caps_fps = false; /* true? */ - pi->caps_uvd_pg = (adev->pg_flags & AMD_PG_SUPPORT_UVD) ? true : false; - pi->caps_uvd_dpm = true; - pi->caps_vce_pg = (adev->pg_flags & AMD_PG_SUPPORT_VCE) ? true : false; - pi->caps_samu_pg = (adev->pg_flags & AMD_PG_SUPPORT_SAMU) ? true : false; - pi->caps_acp_pg = (adev->pg_flags & AMD_PG_SUPPORT_ACP) ? true : false; - pi->caps_stable_p_state = false; - - ret = kv_parse_sys_info_table(adev); - if (ret) - return ret; - - kv_patch_voltage_values(adev); - kv_construct_boot_state(adev); - - ret = kv_parse_power_table(adev); - if (ret) - return ret; - - pi->enable_dpm = true; - - return 0; -} - -static void -kv_dpm_debugfs_print_current_performance_level(void *handle, - struct seq_file *m) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - u32 current_index = - (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; - u32 sclk, tmp; - u16 vddc; - - if (current_index >= SMU__NUM_SCLK_DPM_STATE) { - seq_printf(m, "invalid dpm profile %d\n", current_index); - } else { - sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency); - tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) & - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> - SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT; - vddc = kv_convert_8bit_index_to_voltage(adev, (u16)tmp); - seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); - seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); - seq_printf(m, "power level %d sclk: %u vddc: %u\n", - current_index, sclk, vddc); - } -} - -static void -kv_dpm_print_power_state(void *handle, void *request_ps) -{ - int i; - struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; - struct kv_ps *ps = kv_get_ps(rps); - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - amdgpu_dpm_print_class_info(rps->class, rps->class2); - amdgpu_dpm_print_cap_info(rps->caps); - printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); - for (i = 0; i < ps->num_levels; i++) { - struct kv_pl *pl = &ps->levels[i]; - printk("\t\tpower level %d sclk: %u vddc: %u\n", - i, pl->sclk, - kv_convert_8bit_index_to_voltage(adev, pl->vddc_index)); - } - amdgpu_dpm_print_ps_status(adev, rps); -} - -static void kv_dpm_fini(struct amdgpu_device *adev) -{ - int i; - - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - kfree(adev->pm.dpm.ps[i].ps_priv); - } - kfree(adev->pm.dpm.ps); - kfree(adev->pm.dpm.priv); - amdgpu_free_extended_power_table(adev); -} - -static void kv_dpm_display_configuration_changed(void *handle) -{ - -} - -static u32 kv_dpm_get_sclk(void *handle, bool low) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - struct kv_ps *requested_state = kv_get_ps(&pi->requested_rps); - - if (low) - return requested_state->levels[0].sclk; - else - return requested_state->levels[requested_state->num_levels - 1].sclk; -} - -static u32 kv_dpm_get_mclk(void *handle, bool low) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - - return pi->sys_info.bootup_uma_clk; -} - -/* get temperature in millidegrees */ -static int kv_dpm_get_temp(void *handle) -{ - u32 temp; - int actual_temp = 0; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - temp = RREG32_SMC(0xC0300E0C); - - if (temp) - actual_temp = (temp / 8) - 49; - else - actual_temp = 0; - - actual_temp = actual_temp * 1000; - - return actual_temp; -} - -static int kv_dpm_early_init(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - adev->powerplay.pp_funcs = &kv_dpm_funcs; - adev->powerplay.pp_handle = adev; - kv_dpm_set_irq_funcs(adev); - - return 0; -} - -static int kv_dpm_late_init(void *handle) -{ - /* powerdown unused blocks for now */ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (!adev->pm.dpm_enabled) - return 0; - - kv_dpm_powergate_acp(adev, true); - kv_dpm_powergate_samu(adev, true); - - return 0; -} - -static int kv_dpm_sw_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, - &adev->pm.dpm.thermal.irq); - if (ret) - return ret; - - ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, - &adev->pm.dpm.thermal.irq); - if (ret) - return ret; - - /* default to balanced state */ - adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; - adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; - adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO; - adev->pm.default_sclk = adev->clock.default_sclk; - adev->pm.default_mclk = adev->clock.default_mclk; - adev->pm.current_sclk = adev->clock.default_sclk; - adev->pm.current_mclk = adev->clock.default_mclk; - adev->pm.int_thermal_type = THERMAL_TYPE_NONE; - - if (amdgpu_dpm == 0) - return 0; - - INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); - mutex_lock(&adev->pm.mutex); - ret = kv_dpm_init(adev); - if (ret) - goto dpm_failed; - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - if (amdgpu_dpm == 1) - amdgpu_pm_print_power_states(adev); - mutex_unlock(&adev->pm.mutex); - DRM_INFO("amdgpu: dpm initialized\n"); - - return 0; - -dpm_failed: - kv_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); - DRM_ERROR("amdgpu: dpm initialization failed\n"); - return ret; -} - -static int kv_dpm_sw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - flush_work(&adev->pm.dpm.thermal.work); - - mutex_lock(&adev->pm.mutex); - kv_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); - - return 0; -} - -static int kv_dpm_hw_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (!amdgpu_dpm) - return 0; - - mutex_lock(&adev->pm.mutex); - kv_dpm_setup_asic(adev); - ret = kv_dpm_enable(adev); - if (ret) - adev->pm.dpm_enabled = false; - else - adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); - return ret; -} - -static int kv_dpm_hw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - kv_dpm_disable(adev); - mutex_unlock(&adev->pm.mutex); - } - - return 0; -} - -static int kv_dpm_suspend(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - /* disable dpm */ - kv_dpm_disable(adev); - /* reset the power state */ - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - mutex_unlock(&adev->pm.mutex); - } - return 0; -} - -static int kv_dpm_resume(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - /* asic init will reset to the boot state */ - mutex_lock(&adev->pm.mutex); - kv_dpm_setup_asic(adev); - ret = kv_dpm_enable(adev); - if (ret) - adev->pm.dpm_enabled = false; - else - adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); - if (adev->pm.dpm_enabled) - amdgpu_pm_compute_clocks(adev); - } - return 0; -} - -static bool kv_dpm_is_idle(void *handle) -{ - return true; -} - -static int kv_dpm_wait_for_idle(void *handle) -{ - return 0; -} - - -static int kv_dpm_soft_reset(void *handle) -{ - return 0; -} - -static int kv_dpm_set_interrupt_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *src, - unsigned type, - enum amdgpu_interrupt_state state) -{ - u32 cg_thermal_int; - - switch (type) { - case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH: - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); - cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; - WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); - break; - case AMDGPU_IRQ_STATE_ENABLE: - cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); - cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; - WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); - break; - default: - break; - } - break; - - case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW: - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); - cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; - WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); - break; - case AMDGPU_IRQ_STATE_ENABLE: - cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); - cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; - WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); - break; - default: - break; - } - break; - - default: - break; - } - return 0; -} - -static int kv_dpm_process_interrupt(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - bool queue_thermal = false; - - if (entry == NULL) - return -EINVAL; - - switch (entry->src_id) { - case 230: /* thermal low to high */ - DRM_DEBUG("IH: thermal low to high\n"); - adev->pm.dpm.thermal.high_to_low = false; - queue_thermal = true; - break; - case 231: /* thermal high to low */ - DRM_DEBUG("IH: thermal high to low\n"); - adev->pm.dpm.thermal.high_to_low = true; - queue_thermal = true; - break; - default: - break; - } - - if (queue_thermal) - schedule_work(&adev->pm.dpm.thermal.work); - - return 0; -} - -static int kv_dpm_set_clockgating_state(void *handle, - enum amd_clockgating_state state) -{ - return 0; -} - -static int kv_dpm_set_powergating_state(void *handle, - enum amd_powergating_state state) -{ - return 0; -} - -static inline bool kv_are_power_levels_equal(const struct kv_pl *kv_cpl1, - const struct kv_pl *kv_cpl2) -{ - return ((kv_cpl1->sclk == kv_cpl2->sclk) && - (kv_cpl1->vddc_index == kv_cpl2->vddc_index) && - (kv_cpl1->ds_divider_index == kv_cpl2->ds_divider_index) && - (kv_cpl1->force_nbp_state == kv_cpl2->force_nbp_state)); -} - -static int kv_check_state_equal(void *handle, - void *current_ps, - void *request_ps, - bool *equal) -{ - struct kv_ps *kv_cps; - struct kv_ps *kv_rps; - int i; - struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; - struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) - return -EINVAL; - - kv_cps = kv_get_ps(cps); - kv_rps = kv_get_ps(rps); - - if (kv_cps == NULL) { - *equal = false; - return 0; - } - - if (kv_cps->num_levels != kv_rps->num_levels) { - *equal = false; - return 0; - } - - for (i = 0; i < kv_cps->num_levels; i++) { - if (!kv_are_power_levels_equal(&(kv_cps->levels[i]), - &(kv_rps->levels[i]))) { - *equal = false; - return 0; - } - } - - /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ - *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); - *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); - - return 0; -} - -static int kv_dpm_read_sensor(void *handle, int idx, - void *value, int *size) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct kv_power_info *pi = kv_get_pi(adev); - uint32_t sclk; - u32 pl_index = - (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> - TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; - - /* size must be at least 4 bytes for all sensors */ - if (*size < 4) - return -EINVAL; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - if (pl_index < SMU__NUM_SCLK_DPM_STATE) { - sclk = be32_to_cpu( - pi->graphics_level[pl_index].SclkFrequency); - *((uint32_t *)value) = sclk; - *size = 4; - return 0; - } - return -EINVAL; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = kv_dpm_get_temp(adev); - *size = 4; - return 0; - default: - return -EINVAL; - } -} - -static int kv_set_powergating_by_smu(void *handle, - uint32_t block_type, bool gate) -{ - switch (block_type) { - case AMD_IP_BLOCK_TYPE_UVD: - kv_dpm_powergate_uvd(handle, gate); - break; - case AMD_IP_BLOCK_TYPE_VCE: - kv_dpm_powergate_vce(handle, gate); - break; - default: - break; - } - return 0; -} - -static const struct amd_ip_funcs kv_dpm_ip_funcs = { - .name = "kv_dpm", - .early_init = kv_dpm_early_init, - .late_init = kv_dpm_late_init, - .sw_init = kv_dpm_sw_init, - .sw_fini = kv_dpm_sw_fini, - .hw_init = kv_dpm_hw_init, - .hw_fini = kv_dpm_hw_fini, - .suspend = kv_dpm_suspend, - .resume = kv_dpm_resume, - .is_idle = kv_dpm_is_idle, - .wait_for_idle = kv_dpm_wait_for_idle, - .soft_reset = kv_dpm_soft_reset, - .set_clockgating_state = kv_dpm_set_clockgating_state, - .set_powergating_state = kv_dpm_set_powergating_state, -}; - -const struct amdgpu_ip_block_version kv_smu_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &kv_dpm_ip_funcs, -}; - -static const struct amd_pm_funcs kv_dpm_funcs = { - .pre_set_power_state = &kv_dpm_pre_set_power_state, - .set_power_state = &kv_dpm_set_power_state, - .post_set_power_state = &kv_dpm_post_set_power_state, - .display_configuration_changed = &kv_dpm_display_configuration_changed, - .get_sclk = &kv_dpm_get_sclk, - .get_mclk = &kv_dpm_get_mclk, - .print_power_state = &kv_dpm_print_power_state, - .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, - .force_performance_level = &kv_dpm_force_performance_level, - .set_powergating_by_smu = kv_set_powergating_by_smu, - .enable_bapm = &kv_dpm_enable_bapm, - .get_vce_clock_state = amdgpu_get_vce_clock_state, - .check_state_equal = kv_check_state_equal, - .read_sensor = &kv_dpm_read_sensor, -}; - -static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { - .set = kv_dpm_set_interrupt_state, - .process = kv_dpm_process_interrupt, -}; - -static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev) -{ - adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; - adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs; -} diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.h b/drivers/gpu/drm/amd/amdgpu/kv_dpm.h deleted file mode 100644 index 6df0ed41317c..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright 2013 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 __KV_DPM_H__ -#define __KV_DPM_H__ - -#define SMU__NUM_SCLK_DPM_STATE 8 -#define SMU__NUM_MCLK_DPM_LEVELS 4 -#define SMU__NUM_LCLK_DPM_LEVELS 8 -#define SMU__NUM_PCIE_DPM_LEVELS 0 /* ??? */ -#include "smu7_fusion.h" -#include "ppsmc.h" - -#define SUMO_MAX_HARDWARE_POWERLEVELS 5 - -#define SUMO_MAX_NUMBER_VOLTAGES 4 - -struct sumo_vid_mapping_entry { - u16 vid_2bit; - u16 vid_7bit; -}; - -struct sumo_vid_mapping_table { - u32 num_entries; - struct sumo_vid_mapping_entry entries[SUMO_MAX_NUMBER_VOLTAGES]; -}; - -struct sumo_sclk_voltage_mapping_entry { - u32 sclk_frequency; - u16 vid_2bit; - u16 rsv; -}; - -struct sumo_sclk_voltage_mapping_table { - u32 num_max_dpm_entries; - struct sumo_sclk_voltage_mapping_entry entries[SUMO_MAX_HARDWARE_POWERLEVELS]; -}; - -#define TRINITY_AT_DFLT 30 - -#define KV_NUM_NBPSTATES 4 - -enum kv_pt_config_reg_type { - KV_CONFIGREG_MMR = 0, - KV_CONFIGREG_SMC_IND, - KV_CONFIGREG_DIDT_IND, - KV_CONFIGREG_CACHE, - KV_CONFIGREG_MAX -}; - -struct kv_pt_config_reg { - u32 offset; - u32 mask; - u32 shift; - u32 value; - enum kv_pt_config_reg_type type; -}; - -struct kv_lcac_config_values { - u32 block_id; - u32 signal_id; - u32 t; -}; - -struct kv_lcac_config_reg { - u32 cntl; - u32 block_mask; - u32 block_shift; - u32 signal_mask; - u32 signal_shift; - u32 t_mask; - u32 t_shift; - u32 enable_mask; - u32 enable_shift; -}; - -struct kv_pl { - u32 sclk; - u8 vddc_index; - u8 ds_divider_index; - u8 ss_divider_index; - u8 allow_gnb_slow; - u8 force_nbp_state; - u8 display_wm; - u8 vce_wm; -}; - -struct kv_ps { - struct kv_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS]; - u32 num_levels; - bool need_dfs_bypass; - u8 dpm0_pg_nb_ps_lo; - u8 dpm0_pg_nb_ps_hi; - u8 dpmx_nb_ps_lo; - u8 dpmx_nb_ps_hi; -}; - -struct kv_sys_info { - u32 bootup_uma_clk; - u32 bootup_sclk; - u32 dentist_vco_freq; - u32 nb_dpm_enable; - u32 nbp_memory_clock[KV_NUM_NBPSTATES]; - u32 nbp_n_clock[KV_NUM_NBPSTATES]; - u16 bootup_nb_voltage_index; - u8 htc_tmp_lmt; - u8 htc_hyst_lmt; - struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table; - struct sumo_vid_mapping_table vid_mapping_table; - u32 uma_channel_number; -}; - -struct kv_power_info { - u32 at[SUMO_MAX_HARDWARE_POWERLEVELS]; - u32 voltage_drop_t; - struct kv_sys_info sys_info; - struct kv_pl boot_pl; - bool enable_nb_ps_policy; - bool disable_nb_ps3_in_battery; - bool video_start; - bool battery_state; - u32 lowest_valid; - u32 highest_valid; - u16 high_voltage_t; - bool cac_enabled; - bool bapm_enable; - /* smc offsets */ - u32 sram_end; - u32 dpm_table_start; - u32 soft_regs_start; - /* dpm SMU tables */ - u8 graphics_dpm_level_count; - u8 uvd_level_count; - u8 vce_level_count; - u8 acp_level_count; - u8 samu_level_count; - u16 fps_high_t; - SMU7_Fusion_GraphicsLevel graphics_level[SMU__NUM_SCLK_DPM_STATE]; - SMU7_Fusion_ACPILevel acpi_level; - SMU7_Fusion_UvdLevel uvd_level[SMU7_MAX_LEVELS_UVD]; - SMU7_Fusion_ExtClkLevel vce_level[SMU7_MAX_LEVELS_VCE]; - SMU7_Fusion_ExtClkLevel acp_level[SMU7_MAX_LEVELS_ACP]; - SMU7_Fusion_ExtClkLevel samu_level[SMU7_MAX_LEVELS_SAMU]; - u8 uvd_boot_level; - u8 vce_boot_level; - u8 acp_boot_level; - u8 samu_boot_level; - u8 uvd_interval; - u8 vce_interval; - u8 acp_interval; - u8 samu_interval; - u8 graphics_boot_level; - u8 graphics_interval; - u8 graphics_therm_throttle_enable; - u8 graphics_voltage_change_enable; - u8 graphics_clk_slow_enable; - u8 graphics_clk_slow_divider; - u8 fps_low_t; - u32 low_sclk_interrupt_t; - bool uvd_power_gated; - bool vce_power_gated; - bool acp_power_gated; - bool samu_power_gated; - bool nb_dpm_enabled; - /* flags */ - bool enable_didt; - bool enable_dpm; - bool enable_auto_thermal_throttling; - bool enable_nb_dpm; - /* caps */ - bool caps_cac; - bool caps_power_containment; - bool caps_sq_ramping; - bool caps_db_ramping; - bool caps_td_ramping; - bool caps_tcp_ramping; - bool caps_sclk_throttle_low_notification; - bool caps_fps; - bool caps_uvd_dpm; - bool caps_uvd_pg; - bool caps_vce_pg; - bool caps_samu_pg; - bool caps_acp_pg; - bool caps_stable_p_state; - bool caps_enable_dfs_bypass; - bool caps_sclk_ds; - struct amdgpu_ps current_rps; - struct kv_ps current_ps; - struct amdgpu_ps requested_rps; - struct kv_ps requested_ps; -}; - -/* XXX are these ok? */ -#define KV_TEMP_RANGE_MIN (90 * 1000) -#define KV_TEMP_RANGE_MAX (120 * 1000) - -/* kv_smc.c */ -int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id); -int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask); -int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, - PPSMC_Msg msg, u32 parameter); -int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit); -int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable); -int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable); -int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit); - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/kv_smc.c b/drivers/gpu/drm/amd/amdgpu/kv_smc.c deleted file mode 100644 index 2d9ab6b8be66..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/kv_smc.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright 2013 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Alex Deucher - */ - -#include "amdgpu.h" -#include "cikd.h" -#include "kv_dpm.h" - -#include "smu/smu_7_0_0_d.h" -#include "smu/smu_7_0_0_sh_mask.h" - -int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id) -{ - u32 i; - u32 tmp = 0; - - WREG32(mmSMC_MESSAGE_0, id & SMC_MESSAGE_0__SMC_MSG_MASK); - - for (i = 0; i < adev->usec_timeout; i++) { - if ((RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK) != 0) - break; - udelay(1); - } - tmp = RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK; - - if (tmp != 1) { - if (tmp == 0xFF) - return -EINVAL; - else if (tmp == 0xFE) - return -EINVAL; - } - - return 0; -} - -int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask) -{ - int ret; - - ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SCLKDPM_GetEnabledMask); - - if (ret == 0) - *enable_mask = RREG32_SMC(ixSMC_SYSCON_MSG_ARG_0); - - return ret; -} - -int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, - PPSMC_Msg msg, u32 parameter) -{ - - WREG32(mmSMC_MSG_ARG_0, parameter); - - return amdgpu_kv_notify_message_to_smu(adev, msg); -} - -static int kv_set_smc_sram_address(struct amdgpu_device *adev, - u32 smc_address, u32 limit) -{ - if (smc_address & 3) - return -EINVAL; - if ((smc_address + 3) > limit) - return -EINVAL; - - WREG32(mmSMC_IND_INDEX_0, smc_address); - WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, - ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK); - - return 0; -} - -int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit) -{ - int ret; - - ret = kv_set_smc_sram_address(adev, smc_address, limit); - if (ret) - return ret; - - *value = RREG32(mmSMC_IND_DATA_0); - return 0; -} - -int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable) -{ - if (enable) - return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Enable); - else - return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Disable); -} - -int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable) -{ - if (enable) - return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableBAPM); - else - return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableBAPM); -} - -int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit) -{ - int ret; - u32 data, original_data, addr, extra_shift, t_byte, count, mask; - - if ((smc_start_address + byte_count) > limit) - return -EINVAL; - - addr = smc_start_address; - t_byte = addr & 3; - - /* RMW for the initial bytes */ - if (t_byte != 0) { - addr -= t_byte; - - ret = kv_set_smc_sram_address(adev, addr, limit); - if (ret) - return ret; - - original_data = RREG32(mmSMC_IND_DATA_0); - - data = 0; - mask = 0; - count = 4; - while (count > 0) { - if (t_byte > 0) { - mask = (mask << 8) | 0xff; - t_byte--; - } else if (byte_count > 0) { - data = (data << 8) + *src++; - byte_count--; - mask <<= 8; - } else { - data <<= 8; - mask = (mask << 8) | 0xff; - } - count--; - } - - data |= original_data & mask; - - ret = kv_set_smc_sram_address(adev, addr, limit); - if (ret) - return ret; - - WREG32(mmSMC_IND_DATA_0, data); - - addr += 4; - } - - while (byte_count >= 4) { - /* SMC address space is BE */ - data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; - - ret = kv_set_smc_sram_address(adev, addr, limit); - if (ret) - return ret; - - WREG32(mmSMC_IND_DATA_0, data); - - src += 4; - byte_count -= 4; - addr += 4; - } - - /* RMW for the final bytes */ - if (byte_count > 0) { - data = 0; - - ret = kv_set_smc_sram_address(adev, addr, limit); - if (ret) - return ret; - - original_data = RREG32(mmSMC_IND_DATA_0); - - extra_shift = 8 * (4 - byte_count); - - while (byte_count > 0) { - /* SMC address space is BE */ - data = (data << 8) + *src++; - byte_count--; - } - - data <<= extra_shift; - - data |= (original_data & ~((~0UL) << extra_shift)); - - ret = kv_set_smc_sram_address(adev, addr, limit); - if (ret) - return ret; - - WREG32(mmSMC_IND_DATA_0, data); - } - return 0; -} - diff --git a/drivers/gpu/drm/amd/amdgpu/ppsmc.h b/drivers/gpu/drm/amd/amdgpu/ppsmc.h deleted file mode 100644 index 8463245f424f..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/ppsmc.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright 2011 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 PP_SMC_H -#define PP_SMC_H - -#pragma pack(push, 1) - -#define PPSMC_SWSTATE_FLAG_DC 0x01 -#define PPSMC_SWSTATE_FLAG_UVD 0x02 -#define PPSMC_SWSTATE_FLAG_VCE 0x04 -#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 - -#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff - -#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -#define PPSMC_SYSTEMFLAG_GDDR5 0x04 -#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO 0x40 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 -#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x02 - -#define PPSMC_DISPLAY_WATERMARK_LOW 0 -#define PPSMC_DISPLAY_WATERMARK_HIGH 1 - -#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -#define PPSMC_STATEFLAG_POWERBOOST 0x02 -#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 - -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -#define PPSMC_Result_OK ((uint8_t)0x01) -#define PPSMC_Result_Failed ((uint8_t)0xFF) - -typedef uint8_t PPSMC_Result; - -#define PPSMC_MSG_Halt ((uint8_t)0x10) -#define PPSMC_MSG_Resume ((uint8_t)0x11) -#define PPSMC_MSG_ZeroLevelsDisabled ((uint8_t)0x13) -#define PPSMC_MSG_OneLevelsDisabled ((uint8_t)0x14) -#define PPSMC_MSG_TwoLevelsDisabled ((uint8_t)0x15) -#define PPSMC_MSG_EnableThermalInterrupt ((uint8_t)0x16) -#define PPSMC_MSG_RunningOnAC ((uint8_t)0x17) -#define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20) -#define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40) -#define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41) -#define PPSMC_MSG_ForceHigh ((uint8_t)0x42) -#define PPSMC_MSG_ForceMediumOrHigh ((uint8_t)0x43) -#define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51) -#define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52) -#define PPSMC_MSG_EnableCac ((uint8_t)0x53) -#define PPSMC_MSG_DisableCac ((uint8_t)0x54) -#define PPSMC_TDPClampingActive ((uint8_t)0x59) -#define PPSMC_TDPClampingInactive ((uint8_t)0x5A) -#define PPSMC_StartFanControl ((uint8_t)0x5B) -#define PPSMC_StopFanControl ((uint8_t)0x5C) -#define PPSMC_MSG_NoDisplay ((uint8_t)0x5D) -#define PPSMC_NoDisplay ((uint8_t)0x5D) -#define PPSMC_MSG_HasDisplay ((uint8_t)0x5E) -#define PPSMC_HasDisplay ((uint8_t)0x5E) -#define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60) -#define PPSMC_MSG_UVDPowerON ((uint8_t)0x61) -#define PPSMC_MSG_EnableULV ((uint8_t)0x62) -#define PPSMC_MSG_DisableULV ((uint8_t)0x63) -#define PPSMC_MSG_EnterULV ((uint8_t)0x64) -#define PPSMC_MSG_ExitULV ((uint8_t)0x65) -#define PPSMC_CACLongTermAvgEnable ((uint8_t)0x6E) -#define PPSMC_CACLongTermAvgDisable ((uint8_t)0x6F) -#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint8_t)0x7A) -#define PPSMC_FlushDataCache ((uint8_t)0x80) -#define PPSMC_MSG_SetEnabledLevels ((uint8_t)0x82) -#define PPSMC_MSG_SetForcedLevels ((uint8_t)0x83) -#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84) -#define PPSMC_MSG_EnableDTE ((uint8_t)0x87) -#define PPSMC_MSG_DisableDTE ((uint8_t)0x88) -#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint8_t)0x96) -#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint8_t)0x97) -#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) - -/* CI/KV/KB */ -#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) -#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) -#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) -#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) -#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) -#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) -#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) -#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) -#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) -#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) -#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) -#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) -#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) -#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) -#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) -#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) -#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) -#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) -#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) -#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) -#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) -#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) -#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) -#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) -#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150) -#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151) -#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154) -#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155) -#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156) -#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157) -#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158) -#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159) -#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a) -#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b) -#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) -#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) -#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) -#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) -#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) -#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) -#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) -#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) -#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) -#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) -#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) -#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) -#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) -#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) -#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) -#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) -#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) -#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) - -#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) -#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) - -#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) -#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) - -/* TN */ -#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102) -#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104) -#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108) -#define PPSMC_MSG_Voltage_Cntl_Enable ((uint32_t) 0x109) -#define PPSMC_MSG_Thermal_Cntl_Enable ((uint32_t) 0x10a) -#define PPSMC_MSG_VCEPowerOFF ((uint32_t) 0x10e) -#define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f) -#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112) -#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d) -#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e) -#define PPSMC_MSG_EnableBAPM ((uint32_t) 0x120) -#define PPSMC_MSG_DisableBAPM ((uint32_t) 0x121) -#define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124) - -#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) -#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) -#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) -#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) -#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) - -typedef uint16_t PPSMC_Msg; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/r600_dpm.h b/drivers/gpu/drm/amd/amdgpu/r600_dpm.h deleted file mode 100644 index 055321f61ca7..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/r600_dpm.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2011 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 __R600_DPM_H__ -#define __R600_DPM_H__ - -#define R600_ASI_DFLT 10000 -#define R600_BSP_DFLT 0x41EB -#define R600_BSU_DFLT 0x2 -#define R600_AH_DFLT 5 -#define R600_RLP_DFLT 25 -#define R600_RMP_DFLT 65 -#define R600_LHP_DFLT 40 -#define R600_LMP_DFLT 15 -#define R600_TD_DFLT 0 -#define R600_UTC_DFLT_00 0x24 -#define R600_UTC_DFLT_01 0x22 -#define R600_UTC_DFLT_02 0x22 -#define R600_UTC_DFLT_03 0x22 -#define R600_UTC_DFLT_04 0x22 -#define R600_UTC_DFLT_05 0x22 -#define R600_UTC_DFLT_06 0x22 -#define R600_UTC_DFLT_07 0x22 -#define R600_UTC_DFLT_08 0x22 -#define R600_UTC_DFLT_09 0x22 -#define R600_UTC_DFLT_10 0x22 -#define R600_UTC_DFLT_11 0x22 -#define R600_UTC_DFLT_12 0x22 -#define R600_UTC_DFLT_13 0x22 -#define R600_UTC_DFLT_14 0x22 -#define R600_DTC_DFLT_00 0x24 -#define R600_DTC_DFLT_01 0x22 -#define R600_DTC_DFLT_02 0x22 -#define R600_DTC_DFLT_03 0x22 -#define R600_DTC_DFLT_04 0x22 -#define R600_DTC_DFLT_05 0x22 -#define R600_DTC_DFLT_06 0x22 -#define R600_DTC_DFLT_07 0x22 -#define R600_DTC_DFLT_08 0x22 -#define R600_DTC_DFLT_09 0x22 -#define R600_DTC_DFLT_10 0x22 -#define R600_DTC_DFLT_11 0x22 -#define R600_DTC_DFLT_12 0x22 -#define R600_DTC_DFLT_13 0x22 -#define R600_DTC_DFLT_14 0x22 -#define R600_VRC_DFLT 0x0000C003 -#define R600_VOLTAGERESPONSETIME_DFLT 1000 -#define R600_BACKBIASRESPONSETIME_DFLT 1000 -#define R600_VRU_DFLT 0x3 -#define R600_SPLLSTEPTIME_DFLT 0x1000 -#define R600_SPLLSTEPUNIT_DFLT 0x3 -#define R600_TPU_DFLT 0 -#define R600_TPC_DFLT 0x200 -#define R600_SSTU_DFLT 0 -#define R600_SST_DFLT 0x00C8 -#define R600_GICST_DFLT 0x200 -#define R600_FCT_DFLT 0x0400 -#define R600_FCTU_DFLT 0 -#define R600_CTXCGTT3DRPHC_DFLT 0x20 -#define R600_CTXCGTT3DRSDC_DFLT 0x40 -#define R600_VDDC3DOORPHC_DFLT 0x100 -#define R600_VDDC3DOORSDC_DFLT 0x7 -#define R600_VDDC3DOORSU_DFLT 0 -#define R600_MPLLLOCKTIME_DFLT 100 -#define R600_MPLLRESETTIME_DFLT 150 -#define R600_VCOSTEPPCT_DFLT 20 -#define R600_ENDINGVCOSTEPPCT_DFLT 5 -#define R600_REFERENCEDIVIDER_DFLT 4 - -#define R600_PM_NUMBER_OF_TC 15 -#define R600_PM_NUMBER_OF_SCLKS 20 -#define R600_PM_NUMBER_OF_MCLKS 4 -#define R600_PM_NUMBER_OF_VOLTAGE_LEVELS 4 -#define R600_PM_NUMBER_OF_ACTIVITY_LEVELS 3 - -/* XXX are these ok? */ -#define R600_TEMP_RANGE_MIN (90 * 1000) -#define R600_TEMP_RANGE_MAX (120 * 1000) - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -enum r600_power_level { - R600_POWER_LEVEL_LOW = 0, - R600_POWER_LEVEL_MEDIUM = 1, - R600_POWER_LEVEL_HIGH = 2, - R600_POWER_LEVEL_CTXSW = 3, -}; - -enum r600_td { - R600_TD_AUTO, - R600_TD_UP, - R600_TD_DOWN, -}; - -enum r600_display_watermark { - R600_DISPLAY_WATERMARK_LOW = 0, - R600_DISPLAY_WATERMARK_HIGH = 1, -}; - -enum r600_display_gap -{ - R600_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, - R600_PM_DISPLAY_GAP_VBLANK = 1, - R600_PM_DISPLAY_GAP_WATERMARK = 2, - R600_PM_DISPLAY_GAP_IGNORE = 3, -}; -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c deleted file mode 100644 index ea914b256ebd..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ /dev/null @@ -1,8079 +0,0 @@ -/* - * Copyright 2013 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 -#include - -#include "amdgpu.h" -#include "amdgpu_pm.h" -#include "amdgpu_dpm.h" -#include "amdgpu_atombios.h" -#include "amd_pcie.h" -#include "sid.h" -#include "r600_dpm.h" -#include "si_dpm.h" -#include "atom.h" -#include "../include/pptable.h" -#include -#include -#include - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -#define SMC_RAM_END 0x20000 - -#define SCLK_MIN_DEEPSLEEP_FREQ 1350 - - -/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 - -#define BIOS_SCRATCH_4 0x5cd - -MODULE_FIRMWARE("amdgpu/tahiti_smc.bin"); -MODULE_FIRMWARE("amdgpu/pitcairn_smc.bin"); -MODULE_FIRMWARE("amdgpu/pitcairn_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/verde_smc.bin"); -MODULE_FIRMWARE("amdgpu/verde_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/oland_smc.bin"); -MODULE_FIRMWARE("amdgpu/oland_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/hainan_smc.bin"); -MODULE_FIRMWARE("amdgpu/hainan_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/banks_k_2_smc.bin"); - -static const struct amd_pm_funcs si_dpm_funcs; - -union power_info { - struct _ATOM_POWERPLAY_INFO info; - struct _ATOM_POWERPLAY_INFO_V2 info_2; - struct _ATOM_POWERPLAY_INFO_V3 info_3; - struct _ATOM_PPLIB_POWERPLAYTABLE pplib; - struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; - struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; - struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; - struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; -}; - -union fan_info { - struct _ATOM_PPLIB_FANTABLE fan; - struct _ATOM_PPLIB_FANTABLE2 fan2; - struct _ATOM_PPLIB_FANTABLE3 fan3; -}; - -union pplib_clock_info { - struct _ATOM_PPLIB_R600_CLOCK_INFO r600; - struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; - struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; - struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; - struct _ATOM_PPLIB_SI_CLOCK_INFO si; -}; - -static const u32 r600_utc[R600_PM_NUMBER_OF_TC] = -{ - R600_UTC_DFLT_00, - R600_UTC_DFLT_01, - R600_UTC_DFLT_02, - R600_UTC_DFLT_03, - R600_UTC_DFLT_04, - R600_UTC_DFLT_05, - R600_UTC_DFLT_06, - R600_UTC_DFLT_07, - R600_UTC_DFLT_08, - R600_UTC_DFLT_09, - R600_UTC_DFLT_10, - R600_UTC_DFLT_11, - R600_UTC_DFLT_12, - R600_UTC_DFLT_13, - R600_UTC_DFLT_14, -}; - -static const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = -{ - R600_DTC_DFLT_00, - R600_DTC_DFLT_01, - R600_DTC_DFLT_02, - R600_DTC_DFLT_03, - R600_DTC_DFLT_04, - R600_DTC_DFLT_05, - R600_DTC_DFLT_06, - R600_DTC_DFLT_07, - R600_DTC_DFLT_08, - R600_DTC_DFLT_09, - R600_DTC_DFLT_10, - R600_DTC_DFLT_11, - R600_DTC_DFLT_12, - R600_DTC_DFLT_13, - R600_DTC_DFLT_14, -}; - -static const struct si_cac_config_reg cac_weights_tahiti[] = -{ - { 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg lcac_tahiti[] = -{ - { 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, - { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } - -}; - -static const struct si_cac_config_reg cac_override_tahiti[] = -{ - { 0xFFFFFFFF } -}; - -static const struct si_powertune_data powertune_data_tahiti = -{ - ((1 << 16) | 27027), - 6, - 0, - 4, - 95, - { - 0UL, - 0UL, - 4521550UL, - 309631529UL, - -1270850L, - 4513710L, - 40 - }, - 595000000UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static const struct si_dte_data dte_data_tahiti = -{ - { 1159409, 0, 0, 0, 0 }, - { 777, 0, 0, 0, 0 }, - 2, - 54000, - 127000, - 25, - 2, - 10, - 13, - { 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 }, - { 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 }, - { 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 }, - 85, - false -}; - -static const struct si_dte_data dte_data_tahiti_pro = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_new_zealand = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 }, - { 0x29B, 0x3E9, 0x537, 0x7D2, 0 }, - 0x5, - 0xAFC8, - 0x69, - 0x32, - 1, - 0, - 0x10, - { 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 }, - 85, - true -}; - -static const struct si_dte_data dte_data_aruba_pro = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_malta = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_cac_config_reg cac_weights_pitcairn[] = -{ - { 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg lcac_pitcairn[] = -{ - { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_override_pitcairn[] = -{ - { 0xFFFFFFFF } -}; - -static const struct si_powertune_data powertune_data_pitcairn = -{ - ((1 << 16) | 27027), - 5, - 0, - 6, - 100, - { - 51600000UL, - 1800000UL, - 7194395UL, - 309631529UL, - -1270850L, - 4513710L, - 100 - }, - 117830498UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static const struct si_dte_data dte_data_pitcairn = -{ - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - 0, - false -}; - -static const struct si_dte_data dte_data_curacao_xt = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_curacao_pro = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_neptune_xt = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 45000, - 100, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_cac_config_reg cac_weights_chelsea_pro[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_chelsea_xt[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_heathrow[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_cape_verde_pro[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_cape_verde[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg lcac_cape_verde[] = -{ - { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_override_cape_verde[] = -{ - { 0xFFFFFFFF } -}; - -static const struct si_powertune_data powertune_data_cape_verde = -{ - ((1 << 16) | 0x6993), - 5, - 0, - 7, - 105, - { - 0UL, - 0UL, - 7194395UL, - 309631529UL, - -1270850L, - 4513710L, - 100 - }, - 117830498UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static const struct si_dte_data dte_data_cape_verde = -{ - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - 0, - false -}; - -static const struct si_dte_data dte_data_venus_xtx = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 }, - 5, - 55000, - 0x69, - 0xA, - 1, - 0, - 0x3, - { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_venus_xt = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 }, - 5, - 55000, - 0x69, - 0xA, - 1, - 0, - 0x3, - { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_venus_pro = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 }, - 5, - 55000, - 0x69, - 0xA, - 1, - 0, - 0x3, - { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - { 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_cac_config_reg cac_weights_oland[] = -{ - { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_mars_pro[] = -{ - { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_mars_xt[] = -{ - { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_oland_pro[] = -{ - { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_weights_oland_xt[] = -{ - { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg lcac_oland[] = -{ - { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg lcac_mars_pro[] = -{ - { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, - { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, - { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_cac_config_reg cac_override_oland[] = -{ - { 0xFFFFFFFF } -}; - -static const struct si_powertune_data powertune_data_oland = -{ - ((1 << 16) | 0x6993), - 5, - 0, - 7, - 105, - { - 0UL, - 0UL, - 7194395UL, - 309631529UL, - -1270850L, - 4513710L, - 100 - }, - 117830498UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static const struct si_powertune_data powertune_data_mars_pro = -{ - ((1 << 16) | 0x6993), - 5, - 0, - 7, - 105, - { - 0UL, - 0UL, - 7194395UL, - 309631529UL, - -1270850L, - 4513710L, - 100 - }, - 117830498UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static const struct si_dte_data dte_data_oland = -{ - { 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0 }, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - 0, - false -}; - -static const struct si_dte_data dte_data_mars_pro = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 55000, - 105, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - -static const struct si_dte_data dte_data_sun_xt = -{ - { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, - { 0x0, 0x0, 0x0, 0x0, 0x0 }, - 5, - 55000, - 105, - 0xA, - 1, - 0, - 0x10, - { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, - { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, - { 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - 90, - true -}; - - -static const struct si_cac_config_reg cac_weights_hainan[] = -{ - { 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND }, - { 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND }, - { 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND }, - { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND }, - { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND }, - { 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND }, - { 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND }, - { 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND }, - { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND }, - { 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND }, - { 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND }, - { 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND }, - { 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND }, - { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND }, - { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND }, - { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND }, - { 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, - { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND }, - { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, - { 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND }, - { 0xFFFFFFFF } -}; - -static const struct si_powertune_data powertune_data_hainan = -{ - ((1 << 16) | 0x6993), - 5, - 0, - 9, - 105, - { - 0UL, - 0UL, - 7194395UL, - 309631529UL, - -1270850L, - 4513710L, - 100 - }, - 117830498UL, - 12, - { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 - }, - true -}; - -static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev); -static struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev); -static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev); -static struct si_ps *si_get_ps(struct amdgpu_ps *rps); - -static int si_populate_voltage_value(struct amdgpu_device *adev, - const struct atom_voltage_table *table, - u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage); -static int si_get_std_voltage_value(struct amdgpu_device *adev, - SISLANDS_SMC_VOLTAGE_VALUE *voltage, - u16 *std_voltage); -static int si_write_smc_soft_register(struct amdgpu_device *adev, - u16 reg_offset, u32 value); -static int si_convert_power_level_to_smc(struct amdgpu_device *adev, - struct rv7xx_pl *pl, - SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level); -static int si_calculate_sclk_params(struct amdgpu_device *adev, - u32 engine_clock, - SISLANDS_SMC_SCLK_VALUE *sclk); - -static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev); -static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev); -static void si_dpm_set_irq_funcs(struct amdgpu_device *adev); - -static struct si_power_info *si_get_pi(struct amdgpu_device *adev) -{ - struct si_power_info *pi = adev->pm.dpm.priv; - return pi; -} - -static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff, - u16 v, s32 t, u32 ileakage, u32 *leakage) -{ - s64 kt, kv, leakage_w, i_leakage, vddc; - s64 temperature, t_slope, t_intercept, av, bv, t_ref; - s64 tmp; - - i_leakage = div64_s64(drm_int2fixp(ileakage), 100); - vddc = div64_s64(drm_int2fixp(v), 1000); - temperature = div64_s64(drm_int2fixp(t), 1000); - - t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000); - t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000); - av = div64_s64(drm_int2fixp(coeff->av), 100000000); - bv = div64_s64(drm_int2fixp(coeff->bv), 100000000); - t_ref = drm_int2fixp(coeff->t_ref); - - tmp = drm_fixp_mul(t_slope, vddc) + t_intercept; - kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature)); - kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref))); - kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc))); - - leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); - - *leakage = drm_fixp2int(leakage_w * 1000); -} - -static void si_calculate_leakage_for_v_and_t(struct amdgpu_device *adev, - const struct ni_leakage_coeffients *coeff, - u16 v, - s32 t, - u32 i_leakage, - u32 *leakage) -{ - si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage); -} - -static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff, - const u32 fixed_kt, u16 v, - u32 ileakage, u32 *leakage) -{ - s64 kt, kv, leakage_w, i_leakage, vddc; - - i_leakage = div64_s64(drm_int2fixp(ileakage), 100); - vddc = div64_s64(drm_int2fixp(v), 1000); - - kt = div64_s64(drm_int2fixp(fixed_kt), 100000000); - kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000), - drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc))); - - leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); - - *leakage = drm_fixp2int(leakage_w * 1000); -} - -static void si_calculate_leakage_for_v(struct amdgpu_device *adev, - const struct ni_leakage_coeffients *coeff, - const u32 fixed_kt, - u16 v, - u32 i_leakage, - u32 *leakage) -{ - si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage); -} - - -static void si_update_dte_from_pl2(struct amdgpu_device *adev, - struct si_dte_data *dte_data) -{ - u32 p_limit1 = adev->pm.dpm.tdp_limit; - u32 p_limit2 = adev->pm.dpm.near_tdp_limit; - u32 k = dte_data->k; - u32 t_max = dte_data->max_t; - u32 t_split[5] = { 10, 15, 20, 25, 30 }; - u32 t_0 = dte_data->t0; - u32 i; - - if (p_limit2 != 0 && p_limit2 <= p_limit1) { - dte_data->tdep_count = 3; - - for (i = 0; i < k; i++) { - dte_data->r[i] = - (t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) / - (p_limit2 * (u32)100); - } - - dte_data->tdep_r[1] = dte_data->r[4] * 2; - - for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) { - dte_data->tdep_r[i] = dte_data->r[4]; - } - } else { - DRM_ERROR("Invalid PL2! DTE will not be updated.\n"); - } -} - -static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = adev->pm.dpm.priv; - - return pi; -} - -static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) -{ - struct ni_power_info *pi = adev->pm.dpm.priv; - - return pi; -} - -static struct si_ps *si_get_ps(struct amdgpu_ps *aps) -{ - struct si_ps *ps = aps->ps_priv; - - return ps; -} - -static void si_initialize_powertune_defaults(struct amdgpu_device *adev) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - bool update_dte_from_pl2 = false; - - if (adev->asic_type == CHIP_TAHITI) { - si_pi->cac_weights = cac_weights_tahiti; - si_pi->lcac_config = lcac_tahiti; - si_pi->cac_override = cac_override_tahiti; - si_pi->powertune_data = &powertune_data_tahiti; - si_pi->dte_data = dte_data_tahiti; - - switch (adev->pdev->device) { - case 0x6798: - si_pi->dte_data.enable_dte_by_default = true; - break; - case 0x6799: - si_pi->dte_data = dte_data_new_zealand; - break; - case 0x6790: - case 0x6791: - case 0x6792: - case 0x679E: - si_pi->dte_data = dte_data_aruba_pro; - update_dte_from_pl2 = true; - break; - case 0x679B: - si_pi->dte_data = dte_data_malta; - update_dte_from_pl2 = true; - break; - case 0x679A: - si_pi->dte_data = dte_data_tahiti_pro; - update_dte_from_pl2 = true; - break; - default: - if (si_pi->dte_data.enable_dte_by_default == true) - DRM_ERROR("DTE is not enabled!\n"); - break; - } - } else if (adev->asic_type == CHIP_PITCAIRN) { - si_pi->cac_weights = cac_weights_pitcairn; - si_pi->lcac_config = lcac_pitcairn; - si_pi->cac_override = cac_override_pitcairn; - si_pi->powertune_data = &powertune_data_pitcairn; - - switch (adev->pdev->device) { - case 0x6810: - case 0x6818: - si_pi->dte_data = dte_data_curacao_xt; - update_dte_from_pl2 = true; - break; - case 0x6819: - case 0x6811: - si_pi->dte_data = dte_data_curacao_pro; - update_dte_from_pl2 = true; - break; - case 0x6800: - case 0x6806: - si_pi->dte_data = dte_data_neptune_xt; - update_dte_from_pl2 = true; - break; - default: - si_pi->dte_data = dte_data_pitcairn; - break; - } - } else if (adev->asic_type == CHIP_VERDE) { - si_pi->lcac_config = lcac_cape_verde; - si_pi->cac_override = cac_override_cape_verde; - si_pi->powertune_data = &powertune_data_cape_verde; - - switch (adev->pdev->device) { - case 0x683B: - case 0x683F: - case 0x6829: - case 0x6835: - si_pi->cac_weights = cac_weights_cape_verde_pro; - si_pi->dte_data = dte_data_cape_verde; - break; - case 0x682C: - si_pi->cac_weights = cac_weights_cape_verde_pro; - si_pi->dte_data = dte_data_sun_xt; - update_dte_from_pl2 = true; - break; - case 0x6825: - case 0x6827: - si_pi->cac_weights = cac_weights_heathrow; - si_pi->dte_data = dte_data_cape_verde; - break; - case 0x6824: - case 0x682D: - si_pi->cac_weights = cac_weights_chelsea_xt; - si_pi->dte_data = dte_data_cape_verde; - break; - case 0x682F: - si_pi->cac_weights = cac_weights_chelsea_pro; - si_pi->dte_data = dte_data_cape_verde; - break; - case 0x6820: - si_pi->cac_weights = cac_weights_heathrow; - si_pi->dte_data = dte_data_venus_xtx; - break; - case 0x6821: - si_pi->cac_weights = cac_weights_heathrow; - si_pi->dte_data = dte_data_venus_xt; - break; - case 0x6823: - case 0x682B: - case 0x6822: - case 0x682A: - si_pi->cac_weights = cac_weights_chelsea_pro; - si_pi->dte_data = dte_data_venus_pro; - break; - default: - si_pi->cac_weights = cac_weights_cape_verde; - si_pi->dte_data = dte_data_cape_verde; - break; - } - } else if (adev->asic_type == CHIP_OLAND) { - si_pi->lcac_config = lcac_mars_pro; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_mars_pro; - si_pi->dte_data = dte_data_mars_pro; - - switch (adev->pdev->device) { - case 0x6601: - case 0x6621: - case 0x6603: - case 0x6605: - si_pi->cac_weights = cac_weights_mars_pro; - update_dte_from_pl2 = true; - break; - case 0x6600: - case 0x6606: - case 0x6620: - case 0x6604: - si_pi->cac_weights = cac_weights_mars_xt; - update_dte_from_pl2 = true; - break; - case 0x6611: - case 0x6613: - case 0x6608: - si_pi->cac_weights = cac_weights_oland_pro; - update_dte_from_pl2 = true; - break; - case 0x6610: - si_pi->cac_weights = cac_weights_oland_xt; - update_dte_from_pl2 = true; - break; - default: - si_pi->cac_weights = cac_weights_oland; - si_pi->lcac_config = lcac_oland; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_oland; - si_pi->dte_data = dte_data_oland; - break; - } - } else if (adev->asic_type == CHIP_HAINAN) { - si_pi->cac_weights = cac_weights_hainan; - si_pi->lcac_config = lcac_oland; - si_pi->cac_override = cac_override_oland; - si_pi->powertune_data = &powertune_data_hainan; - si_pi->dte_data = dte_data_sun_xt; - update_dte_from_pl2 = true; - } else { - DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n"); - return; - } - - ni_pi->enable_power_containment = false; - ni_pi->enable_cac = false; - ni_pi->enable_sq_ramping = false; - si_pi->enable_dte = false; - - if (si_pi->powertune_data->enable_powertune_by_default) { - ni_pi->enable_power_containment = true; - ni_pi->enable_cac = true; - if (si_pi->dte_data.enable_dte_by_default) { - si_pi->enable_dte = true; - if (update_dte_from_pl2) - si_update_dte_from_pl2(adev, &si_pi->dte_data); - - } - ni_pi->enable_sq_ramping = true; - } - - ni_pi->driver_calculate_cac_leakage = true; - ni_pi->cac_configuration_required = true; - - if (ni_pi->cac_configuration_required) { - ni_pi->support_cac_long_term_average = true; - si_pi->dyn_powertune_data.l2_lta_window_size = - si_pi->powertune_data->l2_lta_window_size_default; - si_pi->dyn_powertune_data.lts_truncate = - si_pi->powertune_data->lts_truncate_default; - } else { - ni_pi->support_cac_long_term_average = false; - si_pi->dyn_powertune_data.l2_lta_window_size = 0; - si_pi->dyn_powertune_data.lts_truncate = 0; - } - - si_pi->dyn_powertune_data.disable_uvd_powertune = false; -} - -static u32 si_get_smc_power_scaling_factor(struct amdgpu_device *adev) -{ - return 1; -} - -static u32 si_calculate_cac_wintime(struct amdgpu_device *adev) -{ - u32 xclk; - u32 wintime; - u32 cac_window; - u32 cac_window_size; - - xclk = amdgpu_asic_get_xclk(adev); - - if (xclk == 0) - return 0; - - cac_window = RREG32(CG_CAC_CTRL) & CAC_WINDOW_MASK; - cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF); - - wintime = (cac_window_size * 100) / xclk; - - return wintime; -} - -static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor) -{ - return power_in_watts; -} - -static int si_calculate_adjusted_tdp_limits(struct amdgpu_device *adev, - bool adjust_polarity, - u32 tdp_adjustment, - u32 *tdp_limit, - u32 *near_tdp_limit) -{ - u32 adjustment_delta, max_tdp_limit; - - if (tdp_adjustment > (u32)adev->pm.dpm.tdp_od_limit) - return -EINVAL; - - max_tdp_limit = ((100 + 100) * adev->pm.dpm.tdp_limit) / 100; - - if (adjust_polarity) { - *tdp_limit = ((100 + tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; - *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - adev->pm.dpm.tdp_limit); - } else { - *tdp_limit = ((100 - tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; - adjustment_delta = adev->pm.dpm.tdp_limit - *tdp_limit; - if (adjustment_delta < adev->pm.dpm.near_tdp_limit_adjusted) - *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta; - else - *near_tdp_limit = 0; - } - - if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit)) - return -EINVAL; - if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit)) - return -EINVAL; - - return 0; -} - -static int si_populate_smc_tdp_limits(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - - if (ni_pi->enable_power_containment) { - SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; - PP_SIslands_PAPMParameters *papm_parm; - struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table; - u32 scaling_factor = si_get_smc_power_scaling_factor(adev); - u32 tdp_limit; - u32 near_tdp_limit; - int ret; - - if (scaling_factor == 0) - return -EINVAL; - - memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); - - ret = si_calculate_adjusted_tdp_limits(adev, - false, /* ??? */ - adev->pm.dpm.tdp_adjustment, - &tdp_limit, - &near_tdp_limit); - if (ret) - return ret; - - smc_table->dpm2Params.TDPLimit = - cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000); - smc_table->dpm2Params.NearTDPLimit = - cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000); - smc_table->dpm2Params.SafePowerLimit = - cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); - - ret = amdgpu_si_copy_bytes_to_smc(adev, - (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + - offsetof(PP_SIslands_DPM2Parameters, TDPLimit)), - (u8 *)(&(smc_table->dpm2Params.TDPLimit)), - sizeof(u32) * 3, - si_pi->sram_end); - if (ret) - return ret; - - if (si_pi->enable_ppm) { - papm_parm = &si_pi->papm_parm; - memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters)); - papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp); - papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max); - papm_parm->dGPU_T_Warning = cpu_to_be32(95); - papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5); - papm_parm->PlatformPowerLimit = 0xffffffff; - papm_parm->NearTDPLimitPAPM = 0xffffffff; - - ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start, - (u8 *)papm_parm, - sizeof(PP_SIslands_PAPMParameters), - si_pi->sram_end); - if (ret) - return ret; - } - } - return 0; -} - -static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - - if (ni_pi->enable_power_containment) { - SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; - u32 scaling_factor = si_get_smc_power_scaling_factor(adev); - int ret; - - memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); - - smc_table->dpm2Params.NearTDPLimit = - cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000); - smc_table->dpm2Params.SafePowerLimit = - cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); - - ret = amdgpu_si_copy_bytes_to_smc(adev, - (si_pi->state_table_start + - offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + - offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)), - (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)), - sizeof(u32) * 2, - si_pi->sram_end); - if (ret) - return ret; - } - - return 0; -} - -static u16 si_calculate_power_efficiency_ratio(struct amdgpu_device *adev, - const u16 prev_std_vddc, - const u16 curr_std_vddc) -{ - u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN; - u64 prev_vddc = (u64)prev_std_vddc; - u64 curr_vddc = (u64)curr_std_vddc; - u64 pwr_efficiency_ratio, n, d; - - if ((prev_vddc == 0) || (curr_vddc == 0)) - return 0; - - n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000); - d = prev_vddc * prev_vddc; - pwr_efficiency_ratio = div64_u64(n, d); - - if (pwr_efficiency_ratio > (u64)0xFFFF) - return 0; - - return (u16)pwr_efficiency_ratio; -} - -static bool si_should_disable_uvd_powertune(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - if (si_pi->dyn_powertune_data.disable_uvd_powertune && - amdgpu_state->vclk && amdgpu_state->dclk) - return true; - - return false; -} - -struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev) -{ - struct evergreen_power_info *pi = adev->pm.dpm.priv; - - return pi; -} - -static int si_populate_power_containment_values(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SISLANDS_SMC_SWSTATE *smc_state) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_ps *state = si_get_ps(amdgpu_state); - SISLANDS_SMC_VOLTAGE_VALUE vddc; - u32 prev_sclk; - u32 max_sclk; - u32 min_sclk; - u16 prev_std_vddc; - u16 curr_std_vddc; - int i; - u16 pwr_efficiency_ratio; - u8 max_ps_percent; - bool disable_uvd_power_tune; - int ret; - - if (ni_pi->enable_power_containment == false) - return 0; - - if (state->performance_level_count == 0) - return -EINVAL; - - if (smc_state->levelCount != state->performance_level_count) - return -EINVAL; - - disable_uvd_power_tune = si_should_disable_uvd_powertune(adev, amdgpu_state); - - smc_state->levels[0].dpm2.MaxPS = 0; - smc_state->levels[0].dpm2.NearTDPDec = 0; - smc_state->levels[0].dpm2.AboveSafeInc = 0; - smc_state->levels[0].dpm2.BelowSafeInc = 0; - smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0; - - for (i = 1; i < state->performance_level_count; i++) { - prev_sclk = state->performance_levels[i-1].sclk; - max_sclk = state->performance_levels[i].sclk; - if (i == 1) - max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M; - else - max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H; - - if (prev_sclk > max_sclk) - return -EINVAL; - - if ((max_ps_percent == 0) || - (prev_sclk == max_sclk) || - disable_uvd_power_tune) - min_sclk = max_sclk; - else if (i == 1) - min_sclk = prev_sclk; - else - min_sclk = (prev_sclk * (u32)max_ps_percent) / 100; - - if (min_sclk < state->performance_levels[0].sclk) - min_sclk = state->performance_levels[0].sclk; - - if (min_sclk == 0) - return -EINVAL; - - ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, - state->performance_levels[i-1].vddc, &vddc); - if (ret) - return ret; - - ret = si_get_std_voltage_value(adev, &vddc, &prev_std_vddc); - if (ret) - return ret; - - ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, - state->performance_levels[i].vddc, &vddc); - if (ret) - return ret; - - ret = si_get_std_voltage_value(adev, &vddc, &curr_std_vddc); - if (ret) - return ret; - - pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(adev, - prev_std_vddc, curr_std_vddc); - - smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk); - smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC; - smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC; - smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC; - smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio); - } - - return 0; -} - -static int si_populate_sq_ramping_values(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SISLANDS_SMC_SWSTATE *smc_state) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_ps *state = si_get_ps(amdgpu_state); - u32 sq_power_throttle, sq_power_throttle2; - bool enable_sq_ramping = ni_pi->enable_sq_ramping; - int i; - - if (state->performance_level_count == 0) - return -EINVAL; - - if (smc_state->levelCount != state->performance_level_count) - return -EINVAL; - - if (adev->pm.dpm.sq_ramping_threshold == 0) - return -EINVAL; - - if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT)) - enable_sq_ramping = false; - - if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT)) - enable_sq_ramping = false; - - if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT)) - enable_sq_ramping = false; - - if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) - enable_sq_ramping = false; - - if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) - enable_sq_ramping = false; - - for (i = 0; i < state->performance_level_count; i++) { - sq_power_throttle = 0; - sq_power_throttle2 = 0; - - if ((state->performance_levels[i].sclk >= adev->pm.dpm.sq_ramping_threshold) && - enable_sq_ramping) { - sq_power_throttle |= MAX_POWER(SISLANDS_DPM2_SQ_RAMP_MAX_POWER); - sq_power_throttle |= MIN_POWER(SISLANDS_DPM2_SQ_RAMP_MIN_POWER); - sq_power_throttle2 |= MAX_POWER_DELTA(SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA); - sq_power_throttle2 |= STI_SIZE(SISLANDS_DPM2_SQ_RAMP_STI_SIZE); - sq_power_throttle2 |= LTI_RATIO(SISLANDS_DPM2_SQ_RAMP_LTI_RATIO); - } else { - sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK; - sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; - } - - smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle); - smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2); - } - - return 0; -} - -static int si_enable_power_containment(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - bool enable) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - PPSMC_Result smc_result; - int ret = 0; - - if (ni_pi->enable_power_containment) { - if (enable) { - if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingActive); - if (smc_result != PPSMC_Result_OK) { - ret = -EINVAL; - ni_pi->pc_enabled = false; - } else { - ni_pi->pc_enabled = true; - } - } - } else { - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive); - if (smc_result != PPSMC_Result_OK) - ret = -EINVAL; - ni_pi->pc_enabled = false; - } - } - - return ret; -} - -static int si_initialize_smc_dte_tables(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - int ret = 0; - struct si_dte_data *dte_data = &si_pi->dte_data; - Smc_SIslands_DTE_Configuration *dte_tables = NULL; - u32 table_size; - u8 tdep_count; - u32 i; - - if (dte_data == NULL) - si_pi->enable_dte = false; - - if (si_pi->enable_dte == false) - return 0; - - if (dte_data->k <= 0) - return -EINVAL; - - dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL); - if (dte_tables == NULL) { - si_pi->enable_dte = false; - return -ENOMEM; - } - - table_size = dte_data->k; - - if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES) - table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES; - - tdep_count = dte_data->tdep_count; - if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE) - tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; - - dte_tables->K = cpu_to_be32(table_size); - dte_tables->T0 = cpu_to_be32(dte_data->t0); - dte_tables->MaxT = cpu_to_be32(dte_data->max_t); - dte_tables->WindowSize = dte_data->window_size; - dte_tables->temp_select = dte_data->temp_select; - dte_tables->DTE_mode = dte_data->dte_mode; - dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold); - - if (tdep_count > 0) - table_size--; - - for (i = 0; i < table_size; i++) { - dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]); - dte_tables->R[i] = cpu_to_be32(dte_data->r[i]); - } - - dte_tables->Tdep_count = tdep_count; - - for (i = 0; i < (u32)tdep_count; i++) { - dte_tables->T_limits[i] = dte_data->t_limits[i]; - dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]); - dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]); - } - - ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->dte_table_start, - (u8 *)dte_tables, - sizeof(Smc_SIslands_DTE_Configuration), - si_pi->sram_end); - kfree(dte_tables); - - return ret; -} - -static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev, - u16 *max, u16 *min) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct amdgpu_cac_leakage_table *table = - &adev->pm.dpm.dyn_state.cac_leakage_table; - u32 i; - u32 v0_loadline; - - if (table == NULL) - return -EINVAL; - - *max = 0; - *min = 0xFFFF; - - for (i = 0; i < table->count; i++) { - if (table->entries[i].vddc > *max) - *max = table->entries[i].vddc; - if (table->entries[i].vddc < *min) - *min = table->entries[i].vddc; - } - - if (si_pi->powertune_data->lkge_lut_v0_percent > 100) - return -EINVAL; - - v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100; - - if (v0_loadline > 0xFFFFUL) - return -EINVAL; - - *min = (u16)v0_loadline; - - if ((*min > *max) || (*max == 0) || (*min == 0)) - return -EINVAL; - - return 0; -} - -static u16 si_get_cac_std_voltage_step(u16 max, u16 min) -{ - return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) / - SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; -} - -static int si_init_dte_leakage_table(struct amdgpu_device *adev, - PP_SIslands_CacConfig *cac_tables, - u16 vddc_max, u16 vddc_min, u16 vddc_step, - u16 t0, u16 t_step) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 leakage; - unsigned int i, j; - s32 t; - u32 smc_leakage; - u32 scaling_factor; - u16 voltage; - - scaling_factor = si_get_smc_power_scaling_factor(adev); - - for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) { - t = (1000 * (i * t_step + t0)); - - for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { - voltage = vddc_max - (vddc_step * j); - - si_calculate_leakage_for_v_and_t(adev, - &si_pi->powertune_data->leakage_coefficients, - voltage, - t, - si_pi->dyn_powertune_data.cac_leakage, - &leakage); - - smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; - - if (smc_leakage > 0xFFFF) - smc_leakage = 0xFFFF; - - cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = - cpu_to_be16((u16)smc_leakage); - } - } - return 0; -} - -static int si_init_simplified_leakage_table(struct amdgpu_device *adev, - PP_SIslands_CacConfig *cac_tables, - u16 vddc_max, u16 vddc_min, u16 vddc_step) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 leakage; - unsigned int i, j; - u32 smc_leakage; - u32 scaling_factor; - u16 voltage; - - scaling_factor = si_get_smc_power_scaling_factor(adev); - - for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { - voltage = vddc_max - (vddc_step * j); - - si_calculate_leakage_for_v(adev, - &si_pi->powertune_data->leakage_coefficients, - si_pi->powertune_data->fixed_kt, - voltage, - si_pi->dyn_powertune_data.cac_leakage, - &leakage); - - smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; - - if (smc_leakage > 0xFFFF) - smc_leakage = 0xFFFF; - - for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) - cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = - cpu_to_be16((u16)smc_leakage); - } - return 0; -} - -static int si_initialize_smc_cac_tables(struct amdgpu_device *adev) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - PP_SIslands_CacConfig *cac_tables = NULL; - u16 vddc_max, vddc_min, vddc_step; - u16 t0, t_step; - u32 load_line_slope, reg; - int ret = 0; - u32 ticks_per_us = amdgpu_asic_get_xclk(adev) / 100; - - if (ni_pi->enable_cac == false) - return 0; - - cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL); - if (!cac_tables) - return -ENOMEM; - - reg = RREG32(CG_CAC_CTRL) & ~CAC_WINDOW_MASK; - reg |= CAC_WINDOW(si_pi->powertune_data->cac_window); - WREG32(CG_CAC_CTRL, reg); - - si_pi->dyn_powertune_data.cac_leakage = adev->pm.dpm.cac_leakage; - si_pi->dyn_powertune_data.dc_pwr_value = - si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0]; - si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(adev); - si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default; - - si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000; - - ret = si_get_cac_std_voltage_max_min(adev, &vddc_max, &vddc_min); - if (ret) - goto done_free; - - vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min); - vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)); - t_step = 4; - t0 = 60; - - if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage) - ret = si_init_dte_leakage_table(adev, cac_tables, - vddc_max, vddc_min, vddc_step, - t0, t_step); - else - ret = si_init_simplified_leakage_table(adev, cac_tables, - vddc_max, vddc_min, vddc_step); - if (ret) - goto done_free; - - load_line_slope = ((u32)adev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100; - - cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size); - cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate; - cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n; - cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min); - cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step); - cac_tables->R_LL = cpu_to_be32(load_line_slope); - cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime); - cac_tables->calculation_repeats = cpu_to_be32(2); - cac_tables->dc_cac = cpu_to_be32(0); - cac_tables->log2_PG_LKG_SCALE = 12; - cac_tables->cac_temp = si_pi->powertune_data->operating_temp; - cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0); - cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step); - - ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->cac_table_start, - (u8 *)cac_tables, - sizeof(PP_SIslands_CacConfig), - si_pi->sram_end); - - if (ret) - goto done_free; - - ret = si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us); - -done_free: - if (ret) { - ni_pi->enable_cac = false; - ni_pi->enable_power_containment = false; - } - - kfree(cac_tables); - - return ret; -} - -static int si_program_cac_config_registers(struct amdgpu_device *adev, - const struct si_cac_config_reg *cac_config_regs) -{ - const struct si_cac_config_reg *config_regs = cac_config_regs; - u32 data = 0, offset; - - if (!config_regs) - return -EINVAL; - - while (config_regs->offset != 0xFFFFFFFF) { - switch (config_regs->type) { - case SISLANDS_CACCONFIG_CGIND: - offset = SMC_CG_IND_START + config_regs->offset; - if (offset < SMC_CG_IND_END) - data = RREG32_SMC(offset); - break; - default: - data = RREG32(config_regs->offset); - break; - } - - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - - switch (config_regs->type) { - case SISLANDS_CACCONFIG_CGIND: - offset = SMC_CG_IND_START + config_regs->offset; - if (offset < SMC_CG_IND_END) - WREG32_SMC(offset, data); - break; - default: - WREG32(config_regs->offset, data); - break; - } - config_regs++; - } - return 0; -} - -static int si_initialize_hardware_cac_manager(struct amdgpu_device *adev) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - int ret; - - if ((ni_pi->enable_cac == false) || - (ni_pi->cac_configuration_required == false)) - return 0; - - ret = si_program_cac_config_registers(adev, si_pi->lcac_config); - if (ret) - return ret; - ret = si_program_cac_config_registers(adev, si_pi->cac_override); - if (ret) - return ret; - ret = si_program_cac_config_registers(adev, si_pi->cac_weights); - if (ret) - return ret; - - return 0; -} - -static int si_enable_smc_cac(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - bool enable) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - PPSMC_Result smc_result; - int ret = 0; - - if (ni_pi->enable_cac) { - if (enable) { - if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { - if (ni_pi->support_cac_long_term_average) { - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable); - if (smc_result != PPSMC_Result_OK) - ni_pi->support_cac_long_term_average = false; - } - - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); - if (smc_result != PPSMC_Result_OK) { - ret = -EINVAL; - ni_pi->cac_enabled = false; - } else { - ni_pi->cac_enabled = true; - } - - if (si_pi->enable_dte) { - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); - if (smc_result != PPSMC_Result_OK) - ret = -EINVAL; - } - } - } else if (ni_pi->cac_enabled) { - if (si_pi->enable_dte) - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); - - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); - - ni_pi->cac_enabled = false; - - if (ni_pi->support_cac_long_term_average) - smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable); - } - } - return ret; -} - -static int si_init_smc_spll_table(struct amdgpu_device *adev) -{ - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - SMC_SISLANDS_SPLL_DIV_TABLE *spll_table; - SISLANDS_SMC_SCLK_VALUE sclk_params; - u32 fb_div, p_div; - u32 clk_s, clk_v; - u32 sclk = 0; - int ret = 0; - u32 tmp; - int i; - - if (si_pi->spll_table_start == 0) - return -EINVAL; - - spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL); - if (spll_table == NULL) - return -ENOMEM; - - for (i = 0; i < 256; i++) { - ret = si_calculate_sclk_params(adev, sclk, &sclk_params); - if (ret) - break; - p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT; - fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT; - clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT; - clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT; - - fb_div &= ~0x00001FFF; - fb_div >>= 1; - clk_v >>= 6; - - if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT)) - ret = -EINVAL; - if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) - ret = -EINVAL; - if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) - ret = -EINVAL; - if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT)) - ret = -EINVAL; - - if (ret) - break; - - tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) | - ((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK); - spll_table->freq[i] = cpu_to_be32(tmp); - - tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) | - ((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK); - spll_table->ss[i] = cpu_to_be32(tmp); - - sclk += 512; - } - - - if (!ret) - ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->spll_table_start, - (u8 *)spll_table, - sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), - si_pi->sram_end); - - if (ret) - ni_pi->enable_power_containment = false; - - kfree(spll_table); - - return ret; -} - -static u16 si_get_lower_of_leakage_and_vce_voltage(struct amdgpu_device *adev, - u16 vce_voltage) -{ - u16 highest_leakage = 0; - struct si_power_info *si_pi = si_get_pi(adev); - int i; - - for (i = 0; i < si_pi->leakage_voltage.count; i++){ - if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage) - highest_leakage = si_pi->leakage_voltage.entries[i].voltage; - } - - if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage)) - return highest_leakage; - - return vce_voltage; -} - -static int si_get_vce_clock_voltage(struct amdgpu_device *adev, - u32 evclk, u32 ecclk, u16 *voltage) -{ - u32 i; - int ret = -EINVAL; - struct amdgpu_vce_clock_voltage_dependency_table *table = - &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; - - if (((evclk == 0) && (ecclk == 0)) || - (table && (table->count == 0))) { - *voltage = 0; - return 0; - } - - for (i = 0; i < table->count; i++) { - if ((evclk <= table->entries[i].evclk) && - (ecclk <= table->entries[i].ecclk)) { - *voltage = table->entries[i].v; - ret = 0; - break; - } - } - - /* if no match return the highest voltage */ - if (ret) - *voltage = table->entries[table->count - 1].v; - - *voltage = si_get_lower_of_leakage_and_vce_voltage(adev, *voltage); - - return ret; -} - -static bool si_dpm_vblank_too_short(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); - /* we never hit the non-gddr5 limit so disable it */ - u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; - - if (vblank_time < switch_limit) - return true; - else - return false; - -} - -static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev, - u32 arb_freq_src, u32 arb_freq_dest) -{ - u32 mc_arb_dram_timing; - u32 mc_arb_dram_timing2; - u32 burst_time; - u32 mc_cg_config; - - switch (arb_freq_src) { - case MC_CG_ARB_FREQ_F0: - mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING); - mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); - burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT; - break; - case MC_CG_ARB_FREQ_F1: - mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_1); - mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1); - burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT; - break; - case MC_CG_ARB_FREQ_F2: - mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_2); - mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2); - burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT; - break; - case MC_CG_ARB_FREQ_F3: - mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_3); - mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3); - burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT; - break; - default: - return -EINVAL; - } - - switch (arb_freq_dest) { - case MC_CG_ARB_FREQ_F0: - WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing); - WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); - WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK); - break; - case MC_CG_ARB_FREQ_F1: - WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); - WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); - WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK); - break; - case MC_CG_ARB_FREQ_F2: - WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing); - WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2); - WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK); - break; - case MC_CG_ARB_FREQ_F3: - WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing); - WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2); - WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK); - break; - default: - return -EINVAL; - } - - mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F; - WREG32(MC_CG_CONFIG, mc_cg_config); - WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK); - - return 0; -} - -static void ni_update_current_ps(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct si_ps *new_ps = si_get_ps(rps); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); - - eg_pi->current_rps = *rps; - ni_pi->current_ps = *new_ps; - eg_pi->current_rps.ps_priv = &ni_pi->current_ps; - adev->pm.dpm.current_ps = &eg_pi->current_rps; -} - -static void ni_update_requested_ps(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct si_ps *new_ps = si_get_ps(rps); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); - - eg_pi->requested_rps = *rps; - ni_pi->requested_ps = *new_ps; - eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps; - adev->pm.dpm.requested_ps = &eg_pi->requested_rps; -} - -static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev, - struct amdgpu_ps *new_ps, - struct amdgpu_ps *old_ps) -{ - struct si_ps *new_state = si_get_ps(new_ps); - struct si_ps *current_state = si_get_ps(old_ps); - - if ((new_ps->vclk == old_ps->vclk) && - (new_ps->dclk == old_ps->dclk)) - return; - - if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >= - current_state->performance_levels[current_state->performance_level_count - 1].sclk) - return; - - amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); -} - -static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev, - struct amdgpu_ps *new_ps, - struct amdgpu_ps *old_ps) -{ - struct si_ps *new_state = si_get_ps(new_ps); - struct si_ps *current_state = si_get_ps(old_ps); - - if ((new_ps->vclk == old_ps->vclk) && - (new_ps->dclk == old_ps->dclk)) - return; - - if (new_state->performance_levels[new_state->performance_level_count - 1].sclk < - current_state->performance_levels[current_state->performance_level_count - 1].sclk) - return; - - amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); -} - -static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage) -{ - unsigned int i; - - for (i = 0; i < table->count; i++) - if (voltage <= table->entries[i].value) - return table->entries[i].value; - - return table->entries[table->count - 1].value; -} - -static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks, - u32 max_clock, u32 requested_clock) -{ - unsigned int i; - - if ((clocks == NULL) || (clocks->count == 0)) - return (requested_clock < max_clock) ? requested_clock : max_clock; - - for (i = 0; i < clocks->count; i++) { - if (clocks->values[i] >= requested_clock) - return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock; - } - - return (clocks->values[clocks->count - 1] < max_clock) ? - clocks->values[clocks->count - 1] : max_clock; -} - -static u32 btc_get_valid_mclk(struct amdgpu_device *adev, - u32 max_mclk, u32 requested_mclk) -{ - return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values, - max_mclk, requested_mclk); -} - -static u32 btc_get_valid_sclk(struct amdgpu_device *adev, - u32 max_sclk, u32 requested_sclk) -{ - return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values, - max_sclk, requested_sclk); -} - -static void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, - u32 *max_clock) -{ - u32 i, clock = 0; - - if ((table == NULL) || (table->count == 0)) { - *max_clock = clock; - return; - } - - for (i = 0; i < table->count; i++) { - if (clock < table->entries[i].clk) - clock = table->entries[i].clk; - } - *max_clock = clock; -} - -static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table, - u32 clock, u16 max_voltage, u16 *voltage) -{ - u32 i; - - if ((table == NULL) || (table->count == 0)) - return; - - for (i= 0; i < table->count; i++) { - if (clock <= table->entries[i].clk) { - if (*voltage < table->entries[i].v) - *voltage = (u16)((table->entries[i].v < max_voltage) ? - table->entries[i].v : max_voltage); - return; - } - } - - *voltage = (*voltage > max_voltage) ? *voltage : max_voltage; -} - -static void btc_adjust_clock_combinations(struct amdgpu_device *adev, - const struct amdgpu_clock_and_voltage_limits *max_limits, - struct rv7xx_pl *pl) -{ - - if ((pl->mclk == 0) || (pl->sclk == 0)) - return; - - if (pl->mclk == pl->sclk) - return; - - if (pl->mclk > pl->sclk) { - if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio) - pl->sclk = btc_get_valid_sclk(adev, - max_limits->sclk, - (pl->mclk + - (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) / - adev->pm.dpm.dyn_state.mclk_sclk_ratio); - } else { - if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta) - pl->mclk = btc_get_valid_mclk(adev, - max_limits->mclk, - pl->sclk - - adev->pm.dpm.dyn_state.sclk_mclk_delta); - } -} - -static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev, - u16 max_vddc, u16 max_vddci, - u16 *vddc, u16 *vddci) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - u16 new_voltage; - - if ((0 == *vddc) || (0 == *vddci)) - return; - - if (*vddc > *vddci) { - if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { - new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table, - (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta)); - *vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci; - } - } else { - if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { - new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table, - (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta)); - *vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc; - } - } -} - -static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, - u32 *p, u32 *u) -{ - u32 b_c = 0; - u32 i_c; - u32 tmp; - - i_c = (i * r_c) / 100; - tmp = i_c >> p_b; - - while (tmp) { - b_c++; - tmp >>= 1; - } - - *u = (b_c + 1) / 2; - *p = i_c / (1 << (2 * (*u))); -} - -static int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th) -{ - u32 k, a, ah, al; - u32 t1; - - if ((fl == 0) || (fh == 0) || (fl > fh)) - return -EINVAL; - - k = (100 * fh) / fl; - t1 = (t * (k - 100)); - a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100)); - a = (a + 5) / 10; - ah = ((a * t) + 5000) / 10000; - al = a - ah; - - *th = t - ah; - *tl = t + al; - - return 0; -} - -static bool r600_is_uvd_state(u32 class, u32 class2) -{ - if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - return true; - if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - return true; - if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - return true; - if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - return true; - if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - return true; - return false; -} - -static u8 rv770_get_memory_module_index(struct amdgpu_device *adev) -{ - return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff); -} - -static void rv770_get_max_vddc(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - u16 vddc; - - if (amdgpu_atombios_get_max_vddc(adev, 0, 0, &vddc)) - pi->max_vddc = 0; - else - pi->max_vddc = vddc; -} - -static void rv770_get_engine_memory_ss(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct amdgpu_atom_ss ss; - - pi->sclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, - ASIC_INTERNAL_ENGINE_SS, 0); - pi->mclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, - ASIC_INTERNAL_MEMORY_SS, 0); - - if (pi->sclk_ss || pi->mclk_ss) - pi->dynamic_ss = true; - else - pi->dynamic_ss = false; -} - - -static void si_apply_state_adjust_rules(struct amdgpu_device *adev, - struct amdgpu_ps *rps) -{ - struct si_ps *ps = si_get_ps(rps); - struct amdgpu_clock_and_voltage_limits *max_limits; - bool disable_mclk_switching = false; - bool disable_sclk_switching = false; - u32 mclk, sclk; - u16 vddc, vddci, min_vce_voltage = 0; - u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; - u32 max_sclk = 0, max_mclk = 0; - int i; - - if (adev->asic_type == CHIP_HAINAN) { - if ((adev->pdev->revision == 0x81) || - (adev->pdev->revision == 0xC3) || - (adev->pdev->device == 0x6664) || - (adev->pdev->device == 0x6665) || - (adev->pdev->device == 0x6667)) { - max_sclk = 75000; - } - if ((adev->pdev->revision == 0xC3) || - (adev->pdev->device == 0x6665)) { - max_sclk = 60000; - max_mclk = 80000; - } - } else if (adev->asic_type == CHIP_OLAND) { - if ((adev->pdev->revision == 0xC7) || - (adev->pdev->revision == 0x80) || - (adev->pdev->revision == 0x81) || - (adev->pdev->revision == 0x83) || - (adev->pdev->revision == 0x87) || - (adev->pdev->device == 0x6604) || - (adev->pdev->device == 0x6605)) { - max_sclk = 75000; - } - } - - if (rps->vce_active) { - rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; - rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; - si_get_vce_clock_voltage(adev, rps->evclk, rps->ecclk, - &min_vce_voltage); - } else { - rps->evclk = 0; - rps->ecclk = 0; - } - - if ((adev->pm.dpm.new_active_crtc_count > 1) || - si_dpm_vblank_too_short(adev)) - disable_mclk_switching = true; - - if (rps->vclk || rps->dclk) { - disable_mclk_switching = true; - disable_sclk_switching = true; - } - - if (adev->pm.ac_power) - max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; - else - max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc; - - for (i = ps->performance_level_count - 2; i >= 0; i--) { - if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc) - ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc; - } - if (adev->pm.ac_power == false) { - for (i = 0; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].mclk > max_limits->mclk) - ps->performance_levels[i].mclk = max_limits->mclk; - if (ps->performance_levels[i].sclk > max_limits->sclk) - ps->performance_levels[i].sclk = max_limits->sclk; - if (ps->performance_levels[i].vddc > max_limits->vddc) - ps->performance_levels[i].vddc = max_limits->vddc; - if (ps->performance_levels[i].vddci > max_limits->vddci) - ps->performance_levels[i].vddci = max_limits->vddci; - } - } - - /* limit clocks to max supported clocks based on voltage dependency tables */ - btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - &max_sclk_vddc); - btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &max_mclk_vddci); - btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &max_mclk_vddc); - - for (i = 0; i < ps->performance_level_count; i++) { - if (max_sclk_vddc) { - if (ps->performance_levels[i].sclk > max_sclk_vddc) - ps->performance_levels[i].sclk = max_sclk_vddc; - } - if (max_mclk_vddci) { - if (ps->performance_levels[i].mclk > max_mclk_vddci) - ps->performance_levels[i].mclk = max_mclk_vddci; - } - if (max_mclk_vddc) { - if (ps->performance_levels[i].mclk > max_mclk_vddc) - ps->performance_levels[i].mclk = max_mclk_vddc; - } - if (max_mclk) { - if (ps->performance_levels[i].mclk > max_mclk) - ps->performance_levels[i].mclk = max_mclk; - } - if (max_sclk) { - if (ps->performance_levels[i].sclk > max_sclk) - ps->performance_levels[i].sclk = max_sclk; - } - } - - /* XXX validate the min clocks required for display */ - - if (disable_mclk_switching) { - mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; - vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; - } else { - mclk = ps->performance_levels[0].mclk; - vddci = ps->performance_levels[0].vddci; - } - - if (disable_sclk_switching) { - sclk = ps->performance_levels[ps->performance_level_count - 1].sclk; - vddc = ps->performance_levels[ps->performance_level_count - 1].vddc; - } else { - sclk = ps->performance_levels[0].sclk; - vddc = ps->performance_levels[0].vddc; - } - - if (rps->vce_active) { - if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) - sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; - if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk) - mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk; - } - - /* adjusted low state */ - ps->performance_levels[0].sclk = sclk; - ps->performance_levels[0].mclk = mclk; - ps->performance_levels[0].vddc = vddc; - ps->performance_levels[0].vddci = vddci; - - if (disable_sclk_switching) { - sclk = ps->performance_levels[0].sclk; - for (i = 1; i < ps->performance_level_count; i++) { - if (sclk < ps->performance_levels[i].sclk) - sclk = ps->performance_levels[i].sclk; - } - for (i = 0; i < ps->performance_level_count; i++) { - ps->performance_levels[i].sclk = sclk; - ps->performance_levels[i].vddc = vddc; - } - } else { - for (i = 1; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk) - ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk; - if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc) - ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; - } - } - - if (disable_mclk_switching) { - mclk = ps->performance_levels[0].mclk; - for (i = 1; i < ps->performance_level_count; i++) { - if (mclk < ps->performance_levels[i].mclk) - mclk = ps->performance_levels[i].mclk; - } - for (i = 0; i < ps->performance_level_count; i++) { - ps->performance_levels[i].mclk = mclk; - ps->performance_levels[i].vddci = vddci; - } - } else { - for (i = 1; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk) - ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk; - if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci) - ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci; - } - } - - for (i = 0; i < ps->performance_level_count; i++) - btc_adjust_clock_combinations(adev, max_limits, - &ps->performance_levels[i]); - - for (i = 0; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].vddc < min_vce_voltage) - ps->performance_levels[i].vddc = min_vce_voltage; - btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, - ps->performance_levels[i].sclk, - max_limits->vddc, &ps->performance_levels[i].vddc); - btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - ps->performance_levels[i].mclk, - max_limits->vddci, &ps->performance_levels[i].vddci); - btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - ps->performance_levels[i].mclk, - max_limits->vddc, &ps->performance_levels[i].vddc); - btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, - adev->clock.current_dispclk, - max_limits->vddc, &ps->performance_levels[i].vddc); - } - - for (i = 0; i < ps->performance_level_count; i++) { - btc_apply_voltage_delta_rules(adev, - max_limits->vddc, max_limits->vddci, - &ps->performance_levels[i].vddc, - &ps->performance_levels[i].vddci); - } - - ps->dc_compatible = true; - for (i = 0; i < ps->performance_level_count; i++) { - if (ps->performance_levels[i].vddc > adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) - ps->dc_compatible = false; - } -} - -#if 0 -static int si_read_smc_soft_register(struct amdgpu_device *adev, - u16 reg_offset, u32 *value) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - return amdgpu_si_read_smc_sram_dword(adev, - si_pi->soft_regs_start + reg_offset, value, - si_pi->sram_end); -} -#endif - -static int si_write_smc_soft_register(struct amdgpu_device *adev, - u16 reg_offset, u32 value) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - return amdgpu_si_write_smc_sram_dword(adev, - si_pi->soft_regs_start + reg_offset, - value, si_pi->sram_end); -} - -static bool si_is_special_1gb_platform(struct amdgpu_device *adev) -{ - bool ret = false; - u32 tmp, width, row, column, bank, density; - bool is_memory_gddr5, is_special; - - tmp = RREG32(MC_SEQ_MISC0); - is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT)); - is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT)) - & (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT)); - - WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb); - width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32; - - tmp = RREG32(MC_ARB_RAMCFG); - row = ((tmp & NOOFROWS_MASK) >> NOOFROWS_SHIFT) + 10; - column = ((tmp & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) + 8; - bank = ((tmp & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + 2; - - density = (1 << (row + column - 20 + bank)) * width; - - if ((adev->pdev->device == 0x6819) && - is_memory_gddr5 && is_special && (density == 0x400)) - ret = true; - - return ret; -} - -static void si_get_leakage_vddc(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u16 vddc, count = 0; - int i, ret; - - for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) { - ret = amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(adev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i); - - if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) { - si_pi->leakage_voltage.entries[count].voltage = vddc; - si_pi->leakage_voltage.entries[count].leakage_index = - SISLANDS_LEAKAGE_INDEX0 + i; - count++; - } - } - si_pi->leakage_voltage.count = count; -} - -static int si_get_leakage_voltage_from_leakage_index(struct amdgpu_device *adev, - u32 index, u16 *leakage_voltage) -{ - struct si_power_info *si_pi = si_get_pi(adev); - int i; - - if (leakage_voltage == NULL) - return -EINVAL; - - if ((index & 0xff00) != 0xff00) - return -EINVAL; - - if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1) - return -EINVAL; - - if (index < SISLANDS_LEAKAGE_INDEX0) - return -EINVAL; - - for (i = 0; i < si_pi->leakage_voltage.count; i++) { - if (si_pi->leakage_voltage.entries[i].leakage_index == index) { - *leakage_voltage = si_pi->leakage_voltage.entries[i].voltage; - return 0; - } - } - return -EAGAIN; -} - -static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - bool want_thermal_protection; - enum amdgpu_dpm_event_src dpm_event_src; - - switch (sources) { - case 0: - default: - want_thermal_protection = false; - break; - case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL): - want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL; - break; - case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL): - want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_EXTERNAL; - break; - case ((1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | - (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL)): - want_thermal_protection = true; - dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; - break; - } - - if (want_thermal_protection) { - WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK); - if (pi->thermal_protection) - WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); - } else { - WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); - } -} - -static void si_enable_auto_throttle_source(struct amdgpu_device *adev, - enum amdgpu_dpm_auto_throttle_src source, - bool enable) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - - if (enable) { - if (!(pi->active_auto_throttle_sources & (1 << source))) { - pi->active_auto_throttle_sources |= 1 << source; - si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); - } - } else { - if (pi->active_auto_throttle_sources & (1 << source)) { - pi->active_auto_throttle_sources &= ~(1 << source); - si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); - } - } -} - -static void si_start_dpm(struct amdgpu_device *adev) -{ - WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); -} - -static void si_stop_dpm(struct amdgpu_device *adev) -{ - WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); -} - -static void si_enable_sclk_control(struct amdgpu_device *adev, bool enable) -{ - if (enable) - WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); - else - WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); - -} - -#if 0 -static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev, - u32 thermal_level) -{ - PPSMC_Result ret; - - if (thermal_level == 0) { - ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); - if (ret == PPSMC_Result_OK) - return 0; - else - return -EINVAL; - } - return 0; -} - -static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev) -{ - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true); -} -#endif - -#if 0 -static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power) -{ - if (ac_power) - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ? - 0 : -EINVAL; - - return 0; -} -#endif - -static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, - PPSMC_Msg msg, u32 parameter) -{ - WREG32(SMC_SCRATCH0, parameter); - return amdgpu_si_send_msg_to_smc(adev, msg); -} - -static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev) -{ - if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK) - return -EINVAL; - - return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static int si_dpm_force_performance_level(void *handle, - enum amd_dpm_forced_level level) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct amdgpu_ps *rps = adev->pm.dpm.current_ps; - struct si_ps *ps = si_get_ps(rps); - u32 levels = ps->performance_level_count; - - if (level == AMD_DPM_FORCED_LEVEL_HIGH) { - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) - return -EINVAL; - - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK) - return -EINVAL; - } else if (level == AMD_DPM_FORCED_LEVEL_LOW) { - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) - return -EINVAL; - - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK) - return -EINVAL; - } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) { - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) - return -EINVAL; - - if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) - return -EINVAL; - } - - adev->pm.dpm.forced_level = level; - - return 0; -} - -#if 0 -static int si_set_boot_state(struct amdgpu_device *adev) -{ - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} -#endif - -static int si_set_sw_state(struct amdgpu_device *adev) -{ - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static int si_halt_smc(struct amdgpu_device *adev) -{ - if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK) - return -EINVAL; - - return (amdgpu_si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static int si_resume_smc(struct amdgpu_device *adev) -{ - if (amdgpu_si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK) - return -EINVAL; - - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static void si_dpm_start_smc(struct amdgpu_device *adev) -{ - amdgpu_si_program_jump_on_start(adev); - amdgpu_si_start_smc(adev); - amdgpu_si_smc_clock(adev, true); -} - -static void si_dpm_stop_smc(struct amdgpu_device *adev) -{ - amdgpu_si_reset_smc(adev); - amdgpu_si_smc_clock(adev, false); -} - -static int si_process_firmware_header(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - int ret; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_stateTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->state_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_softRegisters, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->soft_regs_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->mc_reg_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_fanTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->fan_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->arb_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->cac_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->dte_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_spllTable, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->spll_table_start = tmp; - - ret = amdgpu_si_read_smc_sram_dword(adev, - SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + - SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - si_pi->papm_cfg_table_start = tmp; - - return ret; -} - -static void si_read_clock_registers(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - si_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL); - si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2); - si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3); - si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4); - si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM); - si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2); - si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL); - si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL); - si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL); - si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL); - si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL); - si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1); - si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2); - si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1); - si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2); -} - -static void si_enable_thermal_protection(struct amdgpu_device *adev, - bool enable) -{ - if (enable) - WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); - else - WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); -} - -static void si_enable_acpi_power_management(struct amdgpu_device *adev) -{ - WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); -} - -#if 0 -static int si_enter_ulp_state(struct amdgpu_device *adev) -{ - WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower); - - udelay(25000); - - return 0; -} - -static int si_exit_ulp_state(struct amdgpu_device *adev) -{ - int i; - - WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower); - - udelay(7000); - - for (i = 0; i < adev->usec_timeout; i++) { - if (RREG32(SMC_RESP_0) == 1) - break; - udelay(1000); - } - - return 0; -} -#endif - -static int si_notify_smc_display_change(struct amdgpu_device *adev, - bool has_display) -{ - PPSMC_Msg msg = has_display ? - PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay; - - return (amdgpu_si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static void si_program_response_times(struct amdgpu_device *adev) -{ - u32 voltage_response_time, acpi_delay_time, vbi_time_out; - u32 vddc_dly, acpi_dly, vbi_dly; - u32 reference_clock; - - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1); - - voltage_response_time = (u32)adev->pm.dpm.voltage_response_time; - - if (voltage_response_time == 0) - voltage_response_time = 1000; - - acpi_delay_time = 15000; - vbi_time_out = 100000; - - reference_clock = amdgpu_asic_get_xclk(adev); - - vddc_dly = (voltage_response_time * reference_clock) / 100; - acpi_dly = (acpi_delay_time * reference_clock) / 100; - vbi_dly = (vbi_time_out * reference_clock) / 100; - - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_vreg, vddc_dly); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_acpi, acpi_dly); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA); -} - -static void si_program_ds_registers(struct amdgpu_device *adev) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - u32 tmp; - - /* DEEP_SLEEP_CLK_SEL field should be 0x10 on tahiti A0 */ - if (adev->asic_type == CHIP_TAHITI && adev->rev_id == 0x0) - tmp = 0x10; - else - tmp = 0x1; - - if (eg_pi->sclk_deep_sleep) { - WREG32_P(MISC_CLK_CNTL, DEEP_SLEEP_CLK_SEL(tmp), ~DEEP_SLEEP_CLK_SEL_MASK); - WREG32_P(CG_SPLL_AUTOSCALE_CNTL, AUTOSCALE_ON_SS_CLEAR, - ~AUTOSCALE_ON_SS_CLEAR); - } -} - -static void si_program_display_gap(struct amdgpu_device *adev) -{ - u32 tmp, pipe; - int i; - - tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK); - if (adev->pm.dpm.new_active_crtc_count > 0) - tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); - else - tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE); - - if (adev->pm.dpm.new_active_crtc_count > 1) - tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); - else - tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE); - - WREG32(CG_DISPLAY_GAP_CNTL, tmp); - - tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG); - pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT; - - if ((adev->pm.dpm.new_active_crtc_count > 0) && - (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) { - /* find the first active crtc */ - for (i = 0; i < adev->mode_info.num_crtc; i++) { - if (adev->pm.dpm.new_active_crtcs & (1 << i)) - break; - } - if (i == adev->mode_info.num_crtc) - pipe = 0; - else - pipe = i; - - tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK; - tmp |= DCCG_DISP1_SLOW_SELECT(pipe); - WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp); - } - - /* Setting this to false forces the performance state to low if the crtcs are disabled. - * This can be a problem on PowerXpress systems or if you want to use the card - * for offscreen rendering or compute if there are no crtcs enabled. - */ - si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > 0); -} - -static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - - if (enable) { - if (pi->sclk_ss) - WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN); - } else { - WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN); - WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN); - } -} - -static void si_setup_bsp(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - u32 xclk = amdgpu_asic_get_xclk(adev); - - r600_calculate_u_and_p(pi->asi, - xclk, - 16, - &pi->bsp, - &pi->bsu); - - r600_calculate_u_and_p(pi->pasi, - xclk, - 16, - &pi->pbsp, - &pi->pbsu); - - - pi->dsp = BSP(pi->bsp) | BSU(pi->bsu); - pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu); - - WREG32(CG_BSP, pi->dsp); -} - -static void si_program_git(struct amdgpu_device *adev) -{ - WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK); -} - -static void si_program_tp(struct amdgpu_device *adev) -{ - int i; - enum r600_td td = R600_TD_DFLT; - - for (i = 0; i < R600_PM_NUMBER_OF_TC; i++) - WREG32(CG_FFCT_0 + i, (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i]))); - - if (td == R600_TD_AUTO) - WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); - else - WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); - - if (td == R600_TD_UP) - WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); - - if (td == R600_TD_DOWN) - WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); -} - -static void si_program_tpp(struct amdgpu_device *adev) -{ - WREG32(CG_TPC, R600_TPC_DFLT); -} - -static void si_program_sstp(struct amdgpu_device *adev) -{ - WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT))); -} - -static void si_enable_display_gap(struct amdgpu_device *adev) -{ - u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); - - tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK); - tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) | - DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE)); - - tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); - tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) | - DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE)); - WREG32(CG_DISPLAY_GAP_CNTL, tmp); -} - -static void si_program_vc(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - - WREG32(CG_FTV, pi->vrc); -} - -static void si_clear_vc(struct amdgpu_device *adev) -{ - WREG32(CG_FTV, 0); -} - -static u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) -{ - u8 mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1); - return mc_para_index; -} - -static u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) -{ - u8 mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (u8)((memory_clock - 60000) / 5000); - } - return mc_para_index; -} - -static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - bool strobe_mode = false; - u8 result = 0; - - if (mclk <= pi->mclk_strobe_mode_threshold) - strobe_mode = true; - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) - result = si_get_mclk_frequency_ratio(mclk, strobe_mode); - else - result = si_get_ddr3_mclk_frequency_ratio(mclk); - - if (strobe_mode) - result |= SISLANDS_SMC_STROBE_ENABLE; - - return result; -} - -static int si_upload_firmware(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - amdgpu_si_reset_smc(adev); - amdgpu_si_smc_clock(adev, false); - - return amdgpu_si_load_smc_ucode(adev, si_pi->sram_end); -} - -static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev, - const struct atom_voltage_table *table, - const struct amdgpu_phase_shedding_limits_table *limits) -{ - u32 data, num_bits, num_levels; - - if ((table == NULL) || (limits == NULL)) - return false; - - data = table->mask_low; - - num_bits = hweight32(data); - - if (num_bits == 0) - return false; - - num_levels = (1 << num_bits); - - if (table->count != num_levels) - return false; - - if (limits->count != (num_levels - 1)) - return false; - - return true; -} - -static void si_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev, - u32 max_voltage_steps, - struct atom_voltage_table *voltage_table) -{ - unsigned int i, diff; - - if (voltage_table->count <= max_voltage_steps) - return; - - diff = voltage_table->count - max_voltage_steps; - - for (i= 0; i < max_voltage_steps; i++) - voltage_table->entries[i] = voltage_table->entries[i + diff]; - - voltage_table->count = max_voltage_steps; -} - -static int si_get_svi2_voltage_table(struct amdgpu_device *adev, - struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table, - struct atom_voltage_table *voltage_table) -{ - u32 i; - - if (voltage_dependency_table == NULL) - return -EINVAL; - - voltage_table->mask_low = 0; - voltage_table->phase_delay = 0; - - voltage_table->count = voltage_dependency_table->count; - for (i = 0; i < voltage_table->count; i++) { - voltage_table->entries[i].value = voltage_dependency_table->entries[i].v; - voltage_table->entries[i].smio_low = 0; - } - - return 0; -} - -static int si_construct_voltage_tables(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - int ret; - - if (pi->voltage_control) { - ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, - VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table); - if (ret) - return ret; - - if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(adev, - SISLANDS_MAX_NO_VREG_STEPS, - &eg_pi->vddc_voltage_table); - } else if (si_pi->voltage_control_svi2) { - ret = si_get_svi2_voltage_table(adev, - &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, - &eg_pi->vddc_voltage_table); - if (ret) - return ret; - } else { - return -EINVAL; - } - - if (eg_pi->vddci_control) { - ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI, - VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table); - if (ret) - return ret; - - if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(adev, - SISLANDS_MAX_NO_VREG_STEPS, - &eg_pi->vddci_voltage_table); - } - if (si_pi->vddci_control_svi2) { - ret = si_get_svi2_voltage_table(adev, - &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, - &eg_pi->vddci_voltage_table); - if (ret) - return ret; - } - - if (pi->mvdd_control) { - ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC, - VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table); - - if (ret) { - pi->mvdd_control = false; - return ret; - } - - if (si_pi->mvdd_voltage_table.count == 0) { - pi->mvdd_control = false; - return -EINVAL; - } - - if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) - si_trim_voltage_table_to_fit_state_table(adev, - SISLANDS_MAX_NO_VREG_STEPS, - &si_pi->mvdd_voltage_table); - } - - if (si_pi->vddc_phase_shed_control) { - ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, - VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table); - if (ret) - si_pi->vddc_phase_shed_control = false; - - if ((si_pi->vddc_phase_shed_table.count == 0) || - (si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS)) - si_pi->vddc_phase_shed_control = false; - } - - return 0; -} - -static void si_populate_smc_voltage_table(struct amdgpu_device *adev, - const struct atom_voltage_table *voltage_table, - SISLANDS_SMC_STATETABLE *table) -{ - unsigned int i; - - for (i = 0; i < voltage_table->count; i++) - table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low); -} - -static int si_populate_smc_voltage_tables(struct amdgpu_device *adev, - SISLANDS_SMC_STATETABLE *table) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - u8 i; - - if (si_pi->voltage_control_svi2) { - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc, - si_pi->svc_gpio_id); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd, - si_pi->svd_gpio_id); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type, - 2); - } else { - if (eg_pi->vddc_voltage_table.count) { - si_populate_smc_voltage_table(adev, &eg_pi->vddc_voltage_table, table); - table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = - cpu_to_be32(eg_pi->vddc_voltage_table.mask_low); - - for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) { - if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) { - table->maxVDDCIndexInPPTable = i; - break; - } - } - } - - if (eg_pi->vddci_voltage_table.count) { - si_populate_smc_voltage_table(adev, &eg_pi->vddci_voltage_table, table); - - table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] = - cpu_to_be32(eg_pi->vddci_voltage_table.mask_low); - } - - - if (si_pi->mvdd_voltage_table.count) { - si_populate_smc_voltage_table(adev, &si_pi->mvdd_voltage_table, table); - - table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] = - cpu_to_be32(si_pi->mvdd_voltage_table.mask_low); - } - - if (si_pi->vddc_phase_shed_control) { - if (si_validate_phase_shedding_tables(adev, &si_pi->vddc_phase_shed_table, - &adev->pm.dpm.dyn_state.phase_shedding_limits_table)) { - si_populate_smc_voltage_table(adev, &si_pi->vddc_phase_shed_table, table); - - table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] = - cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low); - - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_phase_shedding_delay, - (u32)si_pi->vddc_phase_shed_table.phase_delay); - } else { - si_pi->vddc_phase_shed_control = false; - } - } - } - - return 0; -} - -static int si_populate_voltage_value(struct amdgpu_device *adev, - const struct atom_voltage_table *table, - u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage) -{ - unsigned int i; - - for (i = 0; i < table->count; i++) { - if (value <= table->entries[i].value) { - voltage->index = (u8)i; - voltage->value = cpu_to_be16(table->entries[i].value); - break; - } - } - - if (i >= table->count) - return -EINVAL; - - return 0; -} - -static int si_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk, - SISLANDS_SMC_VOLTAGE_VALUE *voltage) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - - if (pi->mvdd_control) { - if (mclk <= pi->mvdd_split_frequency) - voltage->index = 0; - else - voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1; - - voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value); - } - return 0; -} - -static int si_get_std_voltage_value(struct amdgpu_device *adev, - SISLANDS_SMC_VOLTAGE_VALUE *voltage, - u16 *std_voltage) -{ - u16 v_index; - bool voltage_found = false; - *std_voltage = be16_to_cpu(voltage->value); - - if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) { - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) { - if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL) - return -EINVAL; - - for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { - if (be16_to_cpu(voltage->value) == - (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { - voltage_found = true; - if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) - *std_voltage = - adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; - else - *std_voltage = - adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; - break; - } - } - - if (!voltage_found) { - for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { - if (be16_to_cpu(voltage->value) <= - (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { - voltage_found = true; - if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) - *std_voltage = - adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; - else - *std_voltage = - adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; - break; - } - } - } - } else { - if ((u32)voltage->index < adev->pm.dpm.dyn_state.cac_leakage_table.count) - *std_voltage = adev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc; - } - } - - return 0; -} - -static int si_populate_std_voltage_value(struct amdgpu_device *adev, - u16 value, u8 index, - SISLANDS_SMC_VOLTAGE_VALUE *voltage) -{ - voltage->index = index; - voltage->value = cpu_to_be16(value); - - return 0; -} - -static int si_populate_phase_shedding_value(struct amdgpu_device *adev, - const struct amdgpu_phase_shedding_limits_table *limits, - u16 voltage, u32 sclk, u32 mclk, - SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage) -{ - unsigned int i; - - for (i = 0; i < limits->count; i++) { - if ((voltage <= limits->entries[i].voltage) && - (sclk <= limits->entries[i].sclk) && - (mclk <= limits->entries[i].mclk)) - break; - } - - smc_voltage->phase_settings = (u8)i; - - return 0; -} - -static int si_init_arb_table_index(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - int ret; - - ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - tmp &= 0x00FFFFFF; - tmp |= MC_CG_ARB_FREQ_F1 << 24; - - return amdgpu_si_write_smc_sram_dword(adev, si_pi->arb_table_start, - tmp, si_pi->sram_end); -} - -static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev) -{ - return ni_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); -} - -static int si_reset_to_default(struct amdgpu_device *adev) -{ - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ? - 0 : -EINVAL; -} - -static int si_force_switch_to_arb_f0(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - int ret; - - ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, - &tmp, si_pi->sram_end); - if (ret) - return ret; - - tmp = (tmp >> 24) & 0xff; - - if (tmp == MC_CG_ARB_FREQ_F0) - return 0; - - return ni_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0); -} - -static u32 si_calculate_memory_refresh_rate(struct amdgpu_device *adev, - u32 engine_clock) -{ - u32 dram_rows; - u32 dram_refresh_rate; - u32 mc_arb_rfsh_rate; - u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT; - - if (tmp >= 4) - dram_rows = 16384; - else - dram_rows = 1 << (tmp + 10); - - dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3); - mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64; - - return mc_arb_rfsh_rate; -} - -static int si_populate_memory_timing_parameters(struct amdgpu_device *adev, - struct rv7xx_pl *pl, - SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs) -{ - u32 dram_timing; - u32 dram_timing2; - u32 burst_time; - - arb_regs->mc_arb_rfsh_rate = - (u8)si_calculate_memory_refresh_rate(adev, pl->sclk); - - amdgpu_atombios_set_engine_dram_timings(adev, - pl->sclk, - pl->mclk); - - dram_timing = RREG32(MC_ARB_DRAM_TIMING); - dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); - burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK; - - arb_regs->mc_arb_dram_timing = cpu_to_be32(dram_timing); - arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2); - arb_regs->mc_arb_burst_time = (u8)burst_time; - - return 0; -} - -static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - unsigned int first_arb_set) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ps *state = si_get_ps(amdgpu_state); - SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; - int i, ret = 0; - - for (i = 0; i < state->performance_level_count; i++) { - ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs); - if (ret) - break; - ret = amdgpu_si_copy_bytes_to_smc(adev, - si_pi->arb_table_start + - offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i), - (u8 *)&arb_regs, - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), - si_pi->sram_end); - if (ret) - break; - } - - return ret; -} - -static int si_program_memory_timing_parameters(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state) -{ - return si_do_program_memory_timing_parameters(adev, amdgpu_new_state, - SISLANDS_DRIVER_STATE_ARB_INDEX); -} - -static int si_populate_initial_mvdd_value(struct amdgpu_device *adev, - struct SISLANDS_SMC_VOLTAGE_VALUE *voltage) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - - if (pi->mvdd_control) - return si_populate_voltage_value(adev, &si_pi->mvdd_voltage_table, - si_pi->mvdd_bootup_value, voltage); - - return 0; -} - -static int si_populate_smc_initial_state(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_initial_state, - SISLANDS_SMC_STATETABLE *table) -{ - struct si_ps *initial_state = si_get_ps(amdgpu_initial_state); - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - u32 reg; - int ret; - - table->initialState.levels[0].mclk.vDLL_CNTL = - cpu_to_be32(si_pi->clock_registers.dll_cntl); - table->initialState.levels[0].mclk.vMCLK_PWRMGT_CNTL = - cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl); - table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = - cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl); - table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = - cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl); - table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL = - cpu_to_be32(si_pi->clock_registers.mpll_func_cntl); - table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = - cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1); - table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = - cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2); - table->initialState.levels[0].mclk.vMPLL_SS = - cpu_to_be32(si_pi->clock_registers.mpll_ss1); - table->initialState.levels[0].mclk.vMPLL_SS2 = - cpu_to_be32(si_pi->clock_registers.mpll_ss2); - - table->initialState.levels[0].mclk.mclk_value = - cpu_to_be32(initial_state->performance_levels[0].mclk); - - table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = - cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl); - table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = - cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2); - table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = - cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3); - table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = - cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4); - table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = - cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum); - table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = - cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2); - - table->initialState.levels[0].sclk.sclk_value = - cpu_to_be32(initial_state->performance_levels[0].sclk); - - table->initialState.levels[0].arbRefreshState = - SISLANDS_INITIAL_STATE_ARB_INDEX; - - table->initialState.levels[0].ACIndex = 0; - - ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, - initial_state->performance_levels[0].vddc, - &table->initialState.levels[0].vddc); - - if (!ret) { - u16 std_vddc; - - ret = si_get_std_voltage_value(adev, - &table->initialState.levels[0].vddc, - &std_vddc); - if (!ret) - si_populate_std_voltage_value(adev, std_vddc, - table->initialState.levels[0].vddc.index, - &table->initialState.levels[0].std_vddc); - } - - if (eg_pi->vddci_control) - si_populate_voltage_value(adev, - &eg_pi->vddci_voltage_table, - initial_state->performance_levels[0].vddci, - &table->initialState.levels[0].vddci); - - if (si_pi->vddc_phase_shed_control) - si_populate_phase_shedding_value(adev, - &adev->pm.dpm.dyn_state.phase_shedding_limits_table, - initial_state->performance_levels[0].vddc, - initial_state->performance_levels[0].sclk, - initial_state->performance_levels[0].mclk, - &table->initialState.levels[0].vddc); - - si_populate_initial_mvdd_value(adev, &table->initialState.levels[0].mvdd); - - reg = CG_R(0xffff) | CG_L(0); - table->initialState.levels[0].aT = cpu_to_be32(reg); - table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); - table->initialState.levels[0].gen2PCIE = (u8)si_pi->boot_pcie_gen; - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { - table->initialState.levels[0].strobeMode = - si_get_strobe_mode_settings(adev, - initial_state->performance_levels[0].mclk); - - if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold) - table->initialState.levels[0].mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG; - else - table->initialState.levels[0].mcFlags = 0; - } - - table->initialState.levelCount = 1; - - table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; - - table->initialState.levels[0].dpm2.MaxPS = 0; - table->initialState.levels[0].dpm2.NearTDPDec = 0; - table->initialState.levels[0].dpm2.AboveSafeInc = 0; - table->initialState.levels[0].dpm2.BelowSafeInc = 0; - table->initialState.levels[0].dpm2.PwrEfficiencyRatio = 0; - - reg = MIN_POWER_MASK | MAX_POWER_MASK; - table->initialState.levels[0].SQPowerThrottle = cpu_to_be32(reg); - - reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; - table->initialState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); - - return 0; -} - -static int si_populate_smc_acpi_state(struct amdgpu_device *adev, - SISLANDS_SMC_STATETABLE *table) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; - u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; - u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; - u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; - u32 dll_cntl = si_pi->clock_registers.dll_cntl; - u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; - u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; - u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; - u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; - u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; - u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; - u32 reg; - int ret; - - table->ACPIState = table->initialState; - - table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (pi->acpi_vddc) { - ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, - pi->acpi_vddc, &table->ACPIState.levels[0].vddc); - if (!ret) { - u16 std_vddc; - - ret = si_get_std_voltage_value(adev, - &table->ACPIState.levels[0].vddc, &std_vddc); - if (!ret) - si_populate_std_voltage_value(adev, std_vddc, - table->ACPIState.levels[0].vddc.index, - &table->ACPIState.levels[0].std_vddc); - } - table->ACPIState.levels[0].gen2PCIE = si_pi->acpi_pcie_gen; - - if (si_pi->vddc_phase_shed_control) { - si_populate_phase_shedding_value(adev, - &adev->pm.dpm.dyn_state.phase_shedding_limits_table, - pi->acpi_vddc, - 0, - 0, - &table->ACPIState.levels[0].vddc); - } - } else { - ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, - pi->min_vddc_in_table, &table->ACPIState.levels[0].vddc); - if (!ret) { - u16 std_vddc; - - ret = si_get_std_voltage_value(adev, - &table->ACPIState.levels[0].vddc, &std_vddc); - - if (!ret) - si_populate_std_voltage_value(adev, std_vddc, - table->ACPIState.levels[0].vddc.index, - &table->ACPIState.levels[0].std_vddc); - } - table->ACPIState.levels[0].gen2PCIE = - (u8)amdgpu_get_pcie_gen_support(adev, - si_pi->sys_pcie_mask, - si_pi->boot_pcie_gen, - AMDGPU_PCIE_GEN1); - - if (si_pi->vddc_phase_shed_control) - si_populate_phase_shedding_value(adev, - &adev->pm.dpm.dyn_state.phase_shedding_limits_table, - pi->min_vddc_in_table, - 0, - 0, - &table->ACPIState.levels[0].vddc); - } - - if (pi->acpi_vddc) { - if (eg_pi->acpi_vddci) - si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, - eg_pi->acpi_vddci, - &table->ACPIState.levels[0].vddci); - } - - mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET; - mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); - - dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS); - - spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; - spll_func_cntl_2 |= SCLK_MUX_SEL(4); - - table->ACPIState.levels[0].mclk.vDLL_CNTL = - cpu_to_be32(dll_cntl); - table->ACPIState.levels[0].mclk.vMCLK_PWRMGT_CNTL = - cpu_to_be32(mclk_pwrmgt_cntl); - table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = - cpu_to_be32(mpll_ad_func_cntl); - table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = - cpu_to_be32(mpll_dq_func_cntl); - table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL = - cpu_to_be32(mpll_func_cntl); - table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = - cpu_to_be32(mpll_func_cntl_1); - table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = - cpu_to_be32(mpll_func_cntl_2); - table->ACPIState.levels[0].mclk.vMPLL_SS = - cpu_to_be32(si_pi->clock_registers.mpll_ss1); - table->ACPIState.levels[0].mclk.vMPLL_SS2 = - cpu_to_be32(si_pi->clock_registers.mpll_ss2); - - table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = - cpu_to_be32(spll_func_cntl); - table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = - cpu_to_be32(spll_func_cntl_2); - table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = - cpu_to_be32(spll_func_cntl_3); - table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = - cpu_to_be32(spll_func_cntl_4); - - table->ACPIState.levels[0].mclk.mclk_value = 0; - table->ACPIState.levels[0].sclk.sclk_value = 0; - - si_populate_mvdd_value(adev, 0, &table->ACPIState.levels[0].mvdd); - - if (eg_pi->dynamic_ac_timing) - table->ACPIState.levels[0].ACIndex = 0; - - table->ACPIState.levels[0].dpm2.MaxPS = 0; - table->ACPIState.levels[0].dpm2.NearTDPDec = 0; - table->ACPIState.levels[0].dpm2.AboveSafeInc = 0; - table->ACPIState.levels[0].dpm2.BelowSafeInc = 0; - table->ACPIState.levels[0].dpm2.PwrEfficiencyRatio = 0; - - reg = MIN_POWER_MASK | MAX_POWER_MASK; - table->ACPIState.levels[0].SQPowerThrottle = cpu_to_be32(reg); - - reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; - table->ACPIState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); - - return 0; -} - -static int si_populate_ulv_state(struct amdgpu_device *adev, - SISLANDS_SMC_SWSTATE *state) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ulv_param *ulv = &si_pi->ulv; - u32 sclk_in_sr = 1350; /* ??? */ - int ret; - - ret = si_convert_power_level_to_smc(adev, &ulv->pl, - &state->levels[0]); - if (!ret) { - if (eg_pi->sclk_deep_sleep) { - if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) - state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; - else - state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; - } - if (ulv->one_pcie_lane_in_ulv) - state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1; - state->levels[0].arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX); - state->levels[0].ACIndex = 1; - state->levels[0].std_vddc = state->levels[0].vddc; - state->levelCount = 1; - - state->flags |= PPSMC_SWSTATE_FLAG_DC; - } - - return ret; -} - -static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ulv_param *ulv = &si_pi->ulv; - SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; - int ret; - - ret = si_populate_memory_timing_parameters(adev, &ulv->pl, - &arb_regs); - if (ret) - return ret; - - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay, - ulv->volt_change_delay); - - ret = amdgpu_si_copy_bytes_to_smc(adev, - si_pi->arb_table_start + - offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX, - (u8 *)&arb_regs, - sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), - si_pi->sram_end); - - return ret; -} - -static void si_get_mvdd_configuration(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - - pi->mvdd_split_frequency = 30000; -} - -static int si_init_smc_table(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps; - const struct si_ulv_param *ulv = &si_pi->ulv; - SISLANDS_SMC_STATETABLE *table = &si_pi->smc_statetable; - int ret; - u32 lane_width; - u32 vr_hot_gpio; - - si_populate_smc_voltage_tables(adev, table); - - switch (adev->pm.int_thermal_type) { - case THERMAL_TYPE_SI: - case THERMAL_TYPE_EMC2103_WITH_INTERNAL: - table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL; - break; - case THERMAL_TYPE_NONE: - table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE; - break; - default: - table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL; - break; - } - - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) - table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) { - if ((adev->pdev->device != 0x6818) && (adev->pdev->device != 0x6819)) - table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT; - } - - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC) - table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) - table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY) - table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH; - - if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) { - table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO; - vr_hot_gpio = adev->pm.dpm.backbias_response_time; - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_vr_hot_gpio, - vr_hot_gpio); - } - - ret = si_populate_smc_initial_state(adev, amdgpu_boot_state, table); - if (ret) - return ret; - - ret = si_populate_smc_acpi_state(adev, table); - if (ret) - return ret; - - table->driverState = table->initialState; - - ret = si_do_program_memory_timing_parameters(adev, amdgpu_boot_state, - SISLANDS_INITIAL_STATE_ARB_INDEX); - if (ret) - return ret; - - if (ulv->supported && ulv->pl.vddc) { - ret = si_populate_ulv_state(adev, &table->ULVState); - if (ret) - return ret; - - ret = si_program_ulv_memory_timing_parameters(adev); - if (ret) - return ret; - - WREG32(CG_ULV_CONTROL, ulv->cg_ulv_control); - WREG32(CG_ULV_PARAMETER, ulv->cg_ulv_parameter); - - lane_width = amdgpu_get_pcie_lanes(adev); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); - } else { - table->ULVState = table->initialState; - } - - return amdgpu_si_copy_bytes_to_smc(adev, si_pi->state_table_start, - (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE), - si_pi->sram_end); -} - -static int si_calculate_sclk_params(struct amdgpu_device *adev, - u32 engine_clock, - SISLANDS_SMC_SCLK_VALUE *sclk) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - struct atom_clock_dividers dividers; - u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; - u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; - u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; - u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; - u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum; - u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2; - u64 tmp; - u32 reference_clock = adev->clock.spll.reference_freq; - u32 reference_divider; - u32 fbdiv; - int ret; - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - engine_clock, false, ÷rs); - if (ret) - return ret; - - reference_divider = 1 + dividers.ref_div; - - tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384; - do_div(tmp, reference_clock); - fbdiv = (u32) tmp; - - spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK); - spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); - spll_func_cntl |= SPLL_PDIV_A(dividers.post_div); - - spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; - spll_func_cntl_2 |= SCLK_MUX_SEL(2); - - spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; - spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); - spll_func_cntl_3 |= SPLL_DITHEN; - - if (pi->sclk_ss) { - struct amdgpu_atom_ss ss; - u32 vco_freq = engine_clock * dividers.post_div; - - if (amdgpu_atombios_get_asic_ss_info(adev, &ss, - ASIC_INTERNAL_ENGINE_SS, vco_freq)) { - u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); - u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000); - - cg_spll_spread_spectrum &= ~CLK_S_MASK; - cg_spll_spread_spectrum |= CLK_S(clk_s); - cg_spll_spread_spectrum |= SSEN; - - cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; - cg_spll_spread_spectrum_2 |= CLK_V(clk_v); - } - } - - sclk->sclk_value = engine_clock; - sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl; - sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2; - sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3; - sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4; - sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum; - sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2; - - return 0; -} - -static int si_populate_sclk_value(struct amdgpu_device *adev, - u32 engine_clock, - SISLANDS_SMC_SCLK_VALUE *sclk) -{ - SISLANDS_SMC_SCLK_VALUE sclk_tmp; - int ret; - - ret = si_calculate_sclk_params(adev, engine_clock, &sclk_tmp); - if (!ret) { - sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value); - sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL); - sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2); - sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3); - sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4); - sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM); - sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2); - } - - return ret; -} - -static int si_populate_mclk_value(struct amdgpu_device *adev, - u32 engine_clock, - u32 memory_clock, - SISLANDS_SMC_MCLK_VALUE *mclk, - bool strobe_mode, - bool dll_state_on) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - u32 dll_cntl = si_pi->clock_registers.dll_cntl; - u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; - u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; - u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; - u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; - u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; - u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; - u32 mpll_ss1 = si_pi->clock_registers.mpll_ss1; - u32 mpll_ss2 = si_pi->clock_registers.mpll_ss2; - struct atom_mpll_param mpll_param; - int ret; - - ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param); - if (ret) - return ret; - - mpll_func_cntl &= ~BWCTRL_MASK; - mpll_func_cntl |= BWCTRL(mpll_param.bwcntl); - - mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK); - mpll_func_cntl_1 |= CLKF(mpll_param.clkf) | - CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode); - - mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK; - mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div); - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { - mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK); - mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) | - YCLK_POST_DIV(mpll_param.post_div); - } - - if (pi->mclk_ss) { - struct amdgpu_atom_ss ss; - u32 freq_nom; - u32 tmp; - u32 reference_clock = adev->clock.mpll.reference_freq; - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) - freq_nom = memory_clock * 4; - else - freq_nom = memory_clock * 2; - - tmp = freq_nom / reference_clock; - tmp = tmp * tmp; - if (amdgpu_atombios_get_asic_ss_info(adev, &ss, - ASIC_INTERNAL_MEMORY_SS, freq_nom)) { - u32 clks = reference_clock * 5 / ss.rate; - u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom); - - mpll_ss1 &= ~CLKV_MASK; - mpll_ss1 |= CLKV(clkv); - - mpll_ss2 &= ~CLKS_MASK; - mpll_ss2 |= CLKS(clks); - } - } - - mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK; - mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed); - - if (dll_state_on) - mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB; - else - mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); - - mclk->mclk_value = cpu_to_be32(memory_clock); - mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); - mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1); - mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2); - mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); - mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); - mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); - mclk->vDLL_CNTL = cpu_to_be32(dll_cntl); - mclk->vMPLL_SS = cpu_to_be32(mpll_ss1); - mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2); - - return 0; -} - -static void si_populate_smc_sp(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SISLANDS_SMC_SWSTATE *smc_state) -{ - struct si_ps *ps = si_get_ps(amdgpu_state); - struct rv7xx_power_info *pi = rv770_get_pi(adev); - int i; - - for (i = 0; i < ps->performance_level_count - 1; i++) - smc_state->levels[i].bSP = cpu_to_be32(pi->dsp); - - smc_state->levels[ps->performance_level_count - 1].bSP = - cpu_to_be32(pi->psp); -} - -static int si_convert_power_level_to_smc(struct amdgpu_device *adev, - struct rv7xx_pl *pl, - SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - int ret; - bool dll_state_on; - u16 std_vddc; - bool gmc_pg = false; - - if (eg_pi->pcie_performance_request && - (si_pi->force_pcie_gen != AMDGPU_PCIE_GEN_INVALID)) - level->gen2PCIE = (u8)si_pi->force_pcie_gen; - else - level->gen2PCIE = (u8)pl->pcie_gen; - - ret = si_populate_sclk_value(adev, pl->sclk, &level->sclk); - if (ret) - return ret; - - level->mcFlags = 0; - - if (pi->mclk_stutter_mode_threshold && - (pl->mclk <= pi->mclk_stutter_mode_threshold) && - !eg_pi->uvd_enabled && - (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) && - (adev->pm.dpm.new_active_crtc_count <= 2)) { - level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN; - - if (gmc_pg) - level->mcFlags |= SISLANDS_SMC_MC_PG_EN; - } - - if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { - if (pl->mclk > pi->mclk_edc_enable_threshold) - level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG; - - if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold) - level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG; - - level->strobeMode = si_get_strobe_mode_settings(adev, pl->mclk); - - if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) { - if (si_get_mclk_frequency_ratio(pl->mclk, true) >= - ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf)) - dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; - else - dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false; - } else { - dll_state_on = false; - } - } else { - level->strobeMode = si_get_strobe_mode_settings(adev, - pl->mclk); - - dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; - } - - ret = si_populate_mclk_value(adev, - pl->sclk, - pl->mclk, - &level->mclk, - (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on); - if (ret) - return ret; - - ret = si_populate_voltage_value(adev, - &eg_pi->vddc_voltage_table, - pl->vddc, &level->vddc); - if (ret) - return ret; - - - ret = si_get_std_voltage_value(adev, &level->vddc, &std_vddc); - if (ret) - return ret; - - ret = si_populate_std_voltage_value(adev, std_vddc, - level->vddc.index, &level->std_vddc); - if (ret) - return ret; - - if (eg_pi->vddci_control) { - ret = si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, - pl->vddci, &level->vddci); - if (ret) - return ret; - } - - if (si_pi->vddc_phase_shed_control) { - ret = si_populate_phase_shedding_value(adev, - &adev->pm.dpm.dyn_state.phase_shedding_limits_table, - pl->vddc, - pl->sclk, - pl->mclk, - &level->vddc); - if (ret) - return ret; - } - - level->MaxPoweredUpCU = si_pi->max_cu; - - ret = si_populate_mvdd_value(adev, pl->mclk, &level->mvdd); - - return ret; -} - -static int si_populate_smc_t(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SISLANDS_SMC_SWSTATE *smc_state) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct si_ps *state = si_get_ps(amdgpu_state); - u32 a_t; - u32 t_l, t_h; - u32 high_bsp; - int i, ret; - - if (state->performance_level_count >= 9) - return -EINVAL; - - if (state->performance_level_count < 2) { - a_t = CG_R(0xffff) | CG_L(0); - smc_state->levels[0].aT = cpu_to_be32(a_t); - return 0; - } - - smc_state->levels[0].aT = cpu_to_be32(0); - - for (i = 0; i <= state->performance_level_count - 2; i++) { - ret = r600_calculate_at( - (50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1), - 100 * R600_AH_DFLT, - state->performance_levels[i + 1].sclk, - state->performance_levels[i].sclk, - &t_l, - &t_h); - - if (ret) { - t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT; - t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT; - } - - a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK; - a_t |= CG_R(t_l * pi->bsp / 20000); - smc_state->levels[i].aT = cpu_to_be32(a_t); - - high_bsp = (i == state->performance_level_count - 2) ? - pi->pbsp : pi->bsp; - a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000); - smc_state->levels[i + 1].aT = cpu_to_be32(a_t); - } - - return 0; -} - -static int si_disable_ulv(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ulv_param *ulv = &si_pi->ulv; - - if (ulv->supported) - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ? - 0 : -EINVAL; - - return 0; -} - -static bool si_is_state_ulv_compatible(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) -{ - const struct si_power_info *si_pi = si_get_pi(adev); - const struct si_ulv_param *ulv = &si_pi->ulv; - const struct si_ps *state = si_get_ps(amdgpu_state); - int i; - - if (state->performance_levels[0].mclk != ulv->pl.mclk) - return false; - - /* XXX validate against display requirements! */ - - for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) { - if (adev->clock.current_dispclk <= - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) { - if (ulv->pl.vddc < - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v) - return false; - } - } - - if ((amdgpu_state->vclk != 0) || (amdgpu_state->dclk != 0)) - return false; - - return true; -} - -static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state) -{ - const struct si_power_info *si_pi = si_get_pi(adev); - const struct si_ulv_param *ulv = &si_pi->ulv; - - if (ulv->supported) { - if (si_is_state_ulv_compatible(adev, amdgpu_new_state)) - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ? - 0 : -EINVAL; - } - return 0; -} - -static int si_convert_power_state_to_smc(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SISLANDS_SMC_SWSTATE *smc_state) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct ni_power_info *ni_pi = ni_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ps *state = si_get_ps(amdgpu_state); - int i, ret; - u32 threshold; - u32 sclk_in_sr = 1350; /* ??? */ - - if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS) - return -EINVAL; - - threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100; - - if (amdgpu_state->vclk && amdgpu_state->dclk) { - eg_pi->uvd_enabled = true; - if (eg_pi->smu_uvd_hs) - smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD; - } else { - eg_pi->uvd_enabled = false; - } - - if (state->dc_compatible) - smc_state->flags |= PPSMC_SWSTATE_FLAG_DC; - - smc_state->levelCount = 0; - for (i = 0; i < state->performance_level_count; i++) { - if (eg_pi->sclk_deep_sleep) { - if ((i == 0) || si_pi->sclk_deep_sleep_above_low) { - if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) - smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; - else - smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; - } - } - - ret = si_convert_power_level_to_smc(adev, &state->performance_levels[i], - &smc_state->levels[i]); - smc_state->levels[i].arbRefreshState = - (u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i); - - if (ret) - return ret; - - if (ni_pi->enable_power_containment) - smc_state->levels[i].displayWatermark = - (state->performance_levels[i].sclk < threshold) ? - PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; - else - smc_state->levels[i].displayWatermark = (i < 2) ? - PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; - - if (eg_pi->dynamic_ac_timing) - smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i; - else - smc_state->levels[i].ACIndex = 0; - - smc_state->levelCount++; - } - - si_write_smc_soft_register(adev, - SI_SMC_SOFT_REGISTER_watermark_threshold, - threshold / 512); - - si_populate_smc_sp(adev, amdgpu_state, smc_state); - - ret = si_populate_power_containment_values(adev, amdgpu_state, smc_state); - if (ret) - ni_pi->enable_power_containment = false; - - ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state); - if (ret) - ni_pi->enable_sq_ramping = false; - - return si_populate_smc_t(adev, amdgpu_state, smc_state); -} - -static int si_upload_sw_state(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ps *new_state = si_get_ps(amdgpu_new_state); - int ret; - u32 address = si_pi->state_table_start + - offsetof(SISLANDS_SMC_STATETABLE, driverState); - u32 state_size = sizeof(SISLANDS_SMC_SWSTATE) + - ((new_state->performance_level_count - 1) * - sizeof(SISLANDS_SMC_HW_PERFORMANCE_LEVEL)); - SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState; - - memset(smc_state, 0, state_size); - - ret = si_convert_power_state_to_smc(adev, amdgpu_new_state, smc_state); - if (ret) - return ret; - - return amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, - state_size, si_pi->sram_end); -} - -static int si_upload_ulv_state(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ulv_param *ulv = &si_pi->ulv; - int ret = 0; - - if (ulv->supported && ulv->pl.vddc) { - u32 address = si_pi->state_table_start + - offsetof(SISLANDS_SMC_STATETABLE, ULVState); - SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.ULVState; - u32 state_size = sizeof(SISLANDS_SMC_SWSTATE); - - memset(smc_state, 0, state_size); - - ret = si_populate_ulv_state(adev, smc_state); - if (!ret) - ret = amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, - state_size, si_pi->sram_end); - } - - return ret; -} - -static int si_upload_smc_data(struct amdgpu_device *adev) -{ - struct amdgpu_crtc *amdgpu_crtc = NULL; - int i; - - if (adev->pm.dpm.new_active_crtc_count == 0) - return 0; - - for (i = 0; i < adev->mode_info.num_crtc; i++) { - if (adev->pm.dpm.new_active_crtcs & (1 << i)) { - amdgpu_crtc = adev->mode_info.crtcs[i]; - break; - } - } - - if (amdgpu_crtc == NULL) - return 0; - - if (amdgpu_crtc->line_time <= 0) - return 0; - - if (si_write_smc_soft_register(adev, - SI_SMC_SOFT_REGISTER_crtc_index, - amdgpu_crtc->crtc_id) != PPSMC_Result_OK) - return 0; - - if (si_write_smc_soft_register(adev, - SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min, - amdgpu_crtc->wm_high / amdgpu_crtc->line_time) != PPSMC_Result_OK) - return 0; - - if (si_write_smc_soft_register(adev, - SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max, - amdgpu_crtc->wm_low / amdgpu_crtc->line_time) != PPSMC_Result_OK) - return 0; - - return 0; -} - -static int si_set_mc_special_registers(struct amdgpu_device *adev, - struct si_mc_reg_table *table) -{ - u8 i, j, k; - u32 temp_reg; - - for (i = 0, j = table->last; i < table->last; i++) { - if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) - return -EINVAL; - switch (table->mc_reg_address[i].s1) { - case MC_SEQ_MISC1: - temp_reg = RREG32(MC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - j++; - - if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) - return -EINVAL; - temp_reg = RREG32(MC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - j++; - - if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) { - if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) - return -EINVAL; - table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - j++; - } - break; - case MC_SEQ_RESERVE_M: - temp_reg = RREG32(MC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP; - for(k = 0; k < table->num_entries; k++) - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - j++; - break; - default: - break; - } - } - - table->last = j; - - return 0; -} - -static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg) -{ - bool result = true; - switch (in_reg) { - case MC_SEQ_RAS_TIMING: - *out_reg = MC_SEQ_RAS_TIMING_LP; - break; - case MC_SEQ_CAS_TIMING: - *out_reg = MC_SEQ_CAS_TIMING_LP; - break; - case MC_SEQ_MISC_TIMING: - *out_reg = MC_SEQ_MISC_TIMING_LP; - break; - case MC_SEQ_MISC_TIMING2: - *out_reg = MC_SEQ_MISC_TIMING2_LP; - break; - case MC_SEQ_RD_CTL_D0: - *out_reg = MC_SEQ_RD_CTL_D0_LP; - break; - case MC_SEQ_RD_CTL_D1: - *out_reg = MC_SEQ_RD_CTL_D1_LP; - break; - case MC_SEQ_WR_CTL_D0: - *out_reg = MC_SEQ_WR_CTL_D0_LP; - break; - case MC_SEQ_WR_CTL_D1: - *out_reg = MC_SEQ_WR_CTL_D1_LP; - break; - case MC_PMG_CMD_EMRS: - *out_reg = MC_SEQ_PMG_CMD_EMRS_LP; - break; - case MC_PMG_CMD_MRS: - *out_reg = MC_SEQ_PMG_CMD_MRS_LP; - break; - case MC_PMG_CMD_MRS1: - *out_reg = MC_SEQ_PMG_CMD_MRS1_LP; - break; - case MC_SEQ_PMG_TIMING: - *out_reg = MC_SEQ_PMG_TIMING_LP; - break; - case MC_PMG_CMD_MRS2: - *out_reg = MC_SEQ_PMG_CMD_MRS2_LP; - break; - case MC_SEQ_WR_CTL_2: - *out_reg = MC_SEQ_WR_CTL_2_LP; - break; - default: - result = false; - break; - } - - return result; -} - -static void si_set_valid_flag(struct si_mc_reg_table *table) -{ - u8 i, j; - - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) { - table->valid_flag |= 1 << i; - break; - } - } - } -} - -static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table) -{ - u32 i; - u16 address; - - for (i = 0; i < table->last; i++) - table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ? - address : table->mc_reg_address[i].s1; - -} - -static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table, - struct si_mc_reg_table *si_table) -{ - u8 i, j; - - if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) - return -EINVAL; - if (table->num_entries > MAX_AC_TIMING_ENTRIES) - return -EINVAL; - - for (i = 0; i < table->last; i++) - si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - si_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - si_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - si_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - si_table->num_entries = table->num_entries; - - return 0; -} - -static int si_initialize_mc_reg_table(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - struct atom_mc_reg_table *table; - struct si_mc_reg_table *si_table = &si_pi->mc_reg_table; - u8 module_index = rv770_get_memory_module_index(adev); - int ret; - - table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL); - if (!table) - return -ENOMEM; - - WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING)); - WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING)); - WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING)); - WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2)); - WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS)); - WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS)); - WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1)); - WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0)); - WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1)); - WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0)); - WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1)); - WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING)); - WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2)); - WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2)); - - ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table); - if (ret) - goto init_mc_done; - - ret = si_copy_vbios_mc_reg_table(table, si_table); - if (ret) - goto init_mc_done; - - si_set_s0_mc_reg_index(si_table); - - ret = si_set_mc_special_registers(adev, si_table); - if (ret) - goto init_mc_done; - - si_set_valid_flag(si_table); - -init_mc_done: - kfree(table); - - return ret; - -} - -static void si_populate_mc_reg_addresses(struct amdgpu_device *adev, - SMC_SIslands_MCRegisters *mc_reg_table) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 i, j; - - for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) { - if (si_pi->mc_reg_table.valid_flag & (1 << j)) { - if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) - break; - mc_reg_table->address[i].s0 = - cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - mc_reg_table->last = (u8)i; -} - -static void si_convert_mc_registers(const struct si_mc_reg_entry *entry, - SMC_SIslands_MCRegisterSet *data, - u32 num_entries, u32 valid_flag) -{ - u32 i, j; - - for(i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & (1 << j)) { - data->value[i] = cpu_to_be32(entry->mc_data[j]); - i++; - } - } -} - -static void si_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev, - struct rv7xx_pl *pl, - SMC_SIslands_MCRegisterSet *mc_reg_table_data) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 i = 0; - - for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) { - if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max) - break; - } - - if ((i == si_pi->mc_reg_table.num_entries) && (i > 0)) - --i; - - si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, si_pi->mc_reg_table.last, - si_pi->mc_reg_table.valid_flag); -} - -static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state, - SMC_SIslands_MCRegisters *mc_reg_table) -{ - struct si_ps *state = si_get_ps(amdgpu_state); - int i; - - for (i = 0; i < state->performance_level_count; i++) { - si_convert_mc_reg_table_entry_to_smc(adev, - &state->performance_levels[i], - &mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]); - } -} - -static int si_populate_mc_reg_table(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_boot_state) -{ - struct si_ps *boot_state = si_get_ps(amdgpu_boot_state); - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ulv_param *ulv = &si_pi->ulv; - SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; - - memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); - - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_seq_index, 1); - - si_populate_mc_reg_addresses(adev, smc_mc_reg_table); - - si_convert_mc_reg_table_entry_to_smc(adev, &boot_state->performance_levels[0], - &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]); - - si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], - &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT], - si_pi->mc_reg_table.last, - si_pi->mc_reg_table.valid_flag); - - if (ulv->supported && ulv->pl.vddc != 0) - si_convert_mc_reg_table_entry_to_smc(adev, &ulv->pl, - &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]); - else - si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], - &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT], - si_pi->mc_reg_table.last, - si_pi->mc_reg_table.valid_flag); - - si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table); - - return amdgpu_si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start, - (u8 *)smc_mc_reg_table, - sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end); -} - -static int si_upload_mc_reg_table(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state) -{ - struct si_ps *new_state = si_get_ps(amdgpu_new_state); - struct si_power_info *si_pi = si_get_pi(adev); - u32 address = si_pi->mc_reg_table_start + - offsetof(SMC_SIslands_MCRegisters, - data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]); - SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; - - memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); - - si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table); - - return amdgpu_si_copy_bytes_to_smc(adev, address, - (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], - sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, - si_pi->sram_end); -} - -static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) -{ - if (enable) - WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); - else - WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); -} - -static enum amdgpu_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_state) -{ - struct si_ps *state = si_get_ps(amdgpu_state); - int i; - u16 pcie_speed, max_speed = 0; - - for (i = 0; i < state->performance_level_count; i++) { - pcie_speed = state->performance_levels[i].pcie_gen; - if (max_speed < pcie_speed) - max_speed = pcie_speed; - } - return max_speed; -} - -static u16 si_get_current_pcie_speed(struct amdgpu_device *adev) -{ - u32 speed_cntl; - - speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL) & LC_CURRENT_DATA_RATE_MASK; - speed_cntl >>= LC_CURRENT_DATA_RATE_SHIFT; - - return (u16)speed_cntl; -} - -static void si_request_link_speed_change_before_state_change(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - struct amdgpu_ps *amdgpu_current_state) -{ - struct si_power_info *si_pi = si_get_pi(adev); - enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); - enum amdgpu_pcie_gen current_link_speed; - - if (si_pi->force_pcie_gen == AMDGPU_PCIE_GEN_INVALID) - current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state); - else - current_link_speed = si_pi->force_pcie_gen; - - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; - si_pi->pspp_notify_required = false; - if (target_link_speed > current_link_speed) { - switch (target_link_speed) { -#if defined(CONFIG_ACPI) - case AMDGPU_PCIE_GEN3: - if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0) - break; - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN2; - if (current_link_speed == AMDGPU_PCIE_GEN2) - break; - /* fall through */ - case AMDGPU_PCIE_GEN2: - if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) - break; -#endif - /* fall through */ - default: - si_pi->force_pcie_gen = si_get_current_pcie_speed(adev); - break; - } - } else { - if (target_link_speed < current_link_speed) - si_pi->pspp_notify_required = true; - } -} - -static void si_notify_link_speed_change_after_state_change(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - struct amdgpu_ps *amdgpu_current_state) -{ - struct si_power_info *si_pi = si_get_pi(adev); - enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); - u8 request; - - if (si_pi->pspp_notify_required) { - if (target_link_speed == AMDGPU_PCIE_GEN3) - request = PCIE_PERF_REQ_PECI_GEN3; - else if (target_link_speed == AMDGPU_PCIE_GEN2) - request = PCIE_PERF_REQ_PECI_GEN2; - else - request = PCIE_PERF_REQ_PECI_GEN1; - - if ((request == PCIE_PERF_REQ_PECI_GEN1) && - (si_get_current_pcie_speed(adev) > 0)) - return; - -#if defined(CONFIG_ACPI) - amdgpu_acpi_pcie_performance_request(adev, request, false); -#endif - } -} - -#if 0 -static int si_ds_request(struct amdgpu_device *adev, - bool ds_status_on, u32 count_write) -{ - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - - if (eg_pi->sclk_deep_sleep) { - if (ds_status_on) - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) == - PPSMC_Result_OK) ? - 0 : -EINVAL; - else - return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) == - PPSMC_Result_OK) ? 0 : -EINVAL; - } - return 0; -} -#endif - -static void si_set_max_cu_value(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - - if (adev->asic_type == CHIP_VERDE) { - switch (adev->pdev->device) { - case 0x6820: - case 0x6825: - case 0x6821: - case 0x6823: - case 0x6827: - si_pi->max_cu = 10; - break; - case 0x682D: - case 0x6824: - case 0x682F: - case 0x6826: - si_pi->max_cu = 8; - break; - case 0x6828: - case 0x6830: - case 0x6831: - case 0x6838: - case 0x6839: - case 0x683D: - si_pi->max_cu = 10; - break; - case 0x683B: - case 0x683F: - case 0x6829: - si_pi->max_cu = 8; - break; - default: - si_pi->max_cu = 0; - break; - } - } else { - si_pi->max_cu = 0; - } -} - -static int si_patch_single_dependency_table_based_on_leakage(struct amdgpu_device *adev, - struct amdgpu_clock_voltage_dependency_table *table) -{ - u32 i; - int j; - u16 leakage_voltage; - - if (table) { - for (i = 0; i < table->count; i++) { - switch (si_get_leakage_voltage_from_leakage_index(adev, - table->entries[i].v, - &leakage_voltage)) { - case 0: - table->entries[i].v = leakage_voltage; - break; - case -EAGAIN: - return -EINVAL; - case -EINVAL: - default: - break; - } - } - - for (j = (table->count - 2); j >= 0; j--) { - table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ? - table->entries[j].v : table->entries[j + 1].v; - } - } - return 0; -} - -static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *adev) -{ - int ret = 0; - - ret = si_patch_single_dependency_table_based_on_leakage(adev, - &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk); - if (ret) - DRM_ERROR("Could not patch vddc_on_sclk leakage table\n"); - ret = si_patch_single_dependency_table_based_on_leakage(adev, - &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk); - if (ret) - DRM_ERROR("Could not patch vddc_on_mclk leakage table\n"); - ret = si_patch_single_dependency_table_based_on_leakage(adev, - &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk); - if (ret) - DRM_ERROR("Could not patch vddci_on_mclk leakage table\n"); - return ret; -} - -static void si_set_pcie_lane_width_in_smc(struct amdgpu_device *adev, - struct amdgpu_ps *amdgpu_new_state, - struct amdgpu_ps *amdgpu_current_state) -{ - u32 lane_width; - u32 new_lane_width = - ((amdgpu_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; - u32 current_lane_width = - ((amdgpu_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; - - if (new_lane_width != current_lane_width) { - amdgpu_set_pcie_lanes(adev, new_lane_width); - lane_width = amdgpu_get_pcie_lanes(adev); - si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); - } -} - -static void si_dpm_setup_asic(struct amdgpu_device *adev) -{ - si_read_clock_registers(adev); - si_enable_acpi_power_management(adev); -} - -static int si_thermal_enable_alert(struct amdgpu_device *adev, - bool enable) -{ - u32 thermal_int = RREG32(CG_THERMAL_INT); - - if (enable) { - PPSMC_Result result; - - thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); - WREG32(CG_THERMAL_INT, thermal_int); - result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); - if (result != PPSMC_Result_OK) { - DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); - return -EINVAL; - } - } else { - thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; - WREG32(CG_THERMAL_INT, thermal_int); - } - - return 0; -} - -static int si_thermal_set_temperature_range(struct amdgpu_device *adev, - int min_temp, int max_temp) -{ - int low_temp = 0 * 1000; - int high_temp = 255 * 1000; - - if (low_temp < min_temp) - low_temp = min_temp; - if (high_temp > max_temp) - high_temp = max_temp; - if (high_temp < low_temp) { - DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); - return -EINVAL; - } - - WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); - WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); - WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); - - adev->pm.dpm.thermal.min_temp = low_temp; - adev->pm.dpm.thermal.max_temp = high_temp; - - return 0; -} - -static void si_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - - if (si_pi->fan_ctrl_is_in_default_mode) { - tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT; - si_pi->fan_ctrl_default_mode = tmp; - tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT; - si_pi->t_min = tmp; - si_pi->fan_ctrl_is_in_default_mode = false; - } - - tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; - tmp |= TMIN(0); - WREG32(CG_FDO_CTRL2, tmp); - - tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; - tmp |= FDO_PWM_MODE(mode); - WREG32(CG_FDO_CTRL2, tmp); -} - -static int si_thermal_setup_fan_table(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE }; - u32 duty100; - u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2; - u16 fdo_min, slope1, slope2; - u32 reference_clock, tmp; - int ret; - u64 tmp64; - - if (!si_pi->fan_table_start) { - adev->pm.dpm.fan.ucode_fan_control = false; - return 0; - } - - duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; - - if (duty100 == 0) { - adev->pm.dpm.fan.ucode_fan_control = false; - return 0; - } - - tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100; - do_div(tmp64, 10000); - fdo_min = (u16)tmp64; - - t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min; - t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med; - - pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min; - pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med; - - slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100); - fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100); - fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100); - fan_table.slope1 = cpu_to_be16(slope1); - fan_table.slope2 = cpu_to_be16(slope2); - fan_table.fdo_min = cpu_to_be16(fdo_min); - fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst); - fan_table.hys_up = cpu_to_be16(1); - fan_table.hys_slope = cpu_to_be16(1); - fan_table.temp_resp_lim = cpu_to_be16(5); - reference_clock = amdgpu_asic_get_xclk(adev); - - fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay * - reference_clock) / 1600); - fan_table.fdo_max = cpu_to_be16((u16)duty100); - - tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; - fan_table.temp_src = (uint8_t)tmp; - - ret = amdgpu_si_copy_bytes_to_smc(adev, - si_pi->fan_table_start, - (u8 *)(&fan_table), - sizeof(fan_table), - si_pi->sram_end); - - if (ret) { - DRM_ERROR("Failed to load fan table to the SMC."); - adev->pm.dpm.fan.ucode_fan_control = false; - } - - return ret; -} - -static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - PPSMC_Result ret; - - ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StartFanControl); - if (ret == PPSMC_Result_OK) { - si_pi->fan_is_controlled_by_smc = true; - return 0; - } else { - return -EINVAL; - } -} - -static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - PPSMC_Result ret; - - ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StopFanControl); - - if (ret == PPSMC_Result_OK) { - si_pi->fan_is_controlled_by_smc = false; - return 0; - } else { - return -EINVAL; - } -} - -static int si_dpm_get_fan_speed_percent(void *handle, - u32 *speed) -{ - u32 duty, duty100; - u64 tmp64; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.no_fan) - return -ENOENT; - - duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; - duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT; - - if (duty100 == 0) - return -EINVAL; - - tmp64 = (u64)duty * 100; - do_div(tmp64, duty100); - *speed = (u32)tmp64; - - if (*speed > 100) - *speed = 100; - - return 0; -} - -static int si_dpm_set_fan_speed_percent(void *handle, - u32 speed) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - u32 duty, duty100; - u64 tmp64; - - if (adev->pm.no_fan) - return -ENOENT; - - if (si_pi->fan_is_controlled_by_smc) - return -EINVAL; - - if (speed > 100) - return -EINVAL; - - duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; - - if (duty100 == 0) - return -EINVAL; - - tmp64 = (u64)speed * duty100; - do_div(tmp64, 100); - duty = (u32)tmp64; - - tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK; - tmp |= FDO_STATIC_DUTY(duty); - WREG32(CG_FDO_CTRL0, tmp); - - return 0; -} - -static void si_dpm_set_fan_control_mode(void *handle, u32 mode) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (mode) { - /* stop auto-manage */ - if (adev->pm.dpm.fan.ucode_fan_control) - si_fan_ctrl_stop_smc_fan_control(adev); - si_fan_ctrl_set_static_mode(adev, mode); - } else { - /* restart auto-manage */ - if (adev->pm.dpm.fan.ucode_fan_control) - si_thermal_start_smc_fan_control(adev); - else - si_fan_ctrl_set_default_mode(adev); - } -} - -static u32 si_dpm_get_fan_control_mode(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - - if (si_pi->fan_is_controlled_by_smc) - return 0; - - tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; - return (tmp >> FDO_PWM_MODE_SHIFT); -} - -#if 0 -static int si_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev, - u32 *speed) -{ - u32 tach_period; - u32 xclk = amdgpu_asic_get_xclk(adev); - - if (adev->pm.no_fan) - return -ENOENT; - - if (adev->pm.fan_pulses_per_revolution == 0) - return -ENOENT; - - tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT; - if (tach_period == 0) - return -ENOENT; - - *speed = 60 * xclk * 10000 / tach_period; - - return 0; -} - -static int si_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev, - u32 speed) -{ - u32 tach_period, tmp; - u32 xclk = amdgpu_asic_get_xclk(adev); - - if (adev->pm.no_fan) - return -ENOENT; - - if (adev->pm.fan_pulses_per_revolution == 0) - return -ENOENT; - - if ((speed < adev->pm.fan_min_rpm) || - (speed > adev->pm.fan_max_rpm)) - return -EINVAL; - - if (adev->pm.dpm.fan.ucode_fan_control) - si_fan_ctrl_stop_smc_fan_control(adev); - - tach_period = 60 * xclk * 10000 / (8 * speed); - tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK; - tmp |= TARGET_PERIOD(tach_period); - WREG32(CG_TACH_CTRL, tmp); - - si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM); - - return 0; -} -#endif - -static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev) -{ - struct si_power_info *si_pi = si_get_pi(adev); - u32 tmp; - - if (!si_pi->fan_ctrl_is_in_default_mode) { - tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; - tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode); - WREG32(CG_FDO_CTRL2, tmp); - - tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; - tmp |= TMIN(si_pi->t_min); - WREG32(CG_FDO_CTRL2, tmp); - si_pi->fan_ctrl_is_in_default_mode = true; - } -} - -static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev) -{ - if (adev->pm.dpm.fan.ucode_fan_control) { - si_fan_ctrl_start_smc_fan_control(adev); - si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC); - } -} - -static void si_thermal_initialize(struct amdgpu_device *adev) -{ - u32 tmp; - - if (adev->pm.fan_pulses_per_revolution) { - tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK; - tmp |= EDGE_PER_REV(adev->pm.fan_pulses_per_revolution -1); - WREG32(CG_TACH_CTRL, tmp); - } - - tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK; - tmp |= TACH_PWM_RESP_RATE(0x28); - WREG32(CG_FDO_CTRL2, tmp); -} - -static int si_thermal_start_thermal_controller(struct amdgpu_device *adev) -{ - int ret; - - si_thermal_initialize(adev); - ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - ret = si_thermal_enable_alert(adev, true); - if (ret) - return ret; - if (adev->pm.dpm.fan.ucode_fan_control) { - ret = si_halt_smc(adev); - if (ret) - return ret; - ret = si_thermal_setup_fan_table(adev); - if (ret) - return ret; - ret = si_resume_smc(adev); - if (ret) - return ret; - si_thermal_start_smc_fan_control(adev); - } - - return 0; -} - -static void si_thermal_stop_thermal_controller(struct amdgpu_device *adev) -{ - if (!adev->pm.no_fan) { - si_fan_ctrl_set_default_mode(adev); - si_fan_ctrl_stop_smc_fan_control(adev); - } -} - -static int si_dpm_enable(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; - int ret; - - if (amdgpu_si_is_smc_running(adev)) - return -EINVAL; - if (pi->voltage_control || si_pi->voltage_control_svi2) - si_enable_voltage_control(adev, true); - if (pi->mvdd_control) - si_get_mvdd_configuration(adev); - if (pi->voltage_control || si_pi->voltage_control_svi2) { - ret = si_construct_voltage_tables(adev); - if (ret) { - DRM_ERROR("si_construct_voltage_tables failed\n"); - return ret; - } - } - if (eg_pi->dynamic_ac_timing) { - ret = si_initialize_mc_reg_table(adev); - if (ret) - eg_pi->dynamic_ac_timing = false; - } - if (pi->dynamic_ss) - si_enable_spread_spectrum(adev, true); - if (pi->thermal_protection) - si_enable_thermal_protection(adev, true); - si_setup_bsp(adev); - si_program_git(adev); - si_program_tp(adev); - si_program_tpp(adev); - si_program_sstp(adev); - si_enable_display_gap(adev); - si_program_vc(adev); - ret = si_upload_firmware(adev); - if (ret) { - DRM_ERROR("si_upload_firmware failed\n"); - return ret; - } - ret = si_process_firmware_header(adev); - if (ret) { - DRM_ERROR("si_process_firmware_header failed\n"); - return ret; - } - ret = si_initial_switch_from_arb_f0_to_f1(adev); - if (ret) { - DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n"); - return ret; - } - ret = si_init_smc_table(adev); - if (ret) { - DRM_ERROR("si_init_smc_table failed\n"); - return ret; - } - ret = si_init_smc_spll_table(adev); - if (ret) { - DRM_ERROR("si_init_smc_spll_table failed\n"); - return ret; - } - ret = si_init_arb_table_index(adev); - if (ret) { - DRM_ERROR("si_init_arb_table_index failed\n"); - return ret; - } - if (eg_pi->dynamic_ac_timing) { - ret = si_populate_mc_reg_table(adev, boot_ps); - if (ret) { - DRM_ERROR("si_populate_mc_reg_table failed\n"); - return ret; - } - } - ret = si_initialize_smc_cac_tables(adev); - if (ret) { - DRM_ERROR("si_initialize_smc_cac_tables failed\n"); - return ret; - } - ret = si_initialize_hardware_cac_manager(adev); - if (ret) { - DRM_ERROR("si_initialize_hardware_cac_manager failed\n"); - return ret; - } - ret = si_initialize_smc_dte_tables(adev); - if (ret) { - DRM_ERROR("si_initialize_smc_dte_tables failed\n"); - return ret; - } - ret = si_populate_smc_tdp_limits(adev, boot_ps); - if (ret) { - DRM_ERROR("si_populate_smc_tdp_limits failed\n"); - return ret; - } - ret = si_populate_smc_tdp_limits_2(adev, boot_ps); - if (ret) { - DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n"); - return ret; - } - si_program_response_times(adev); - si_program_ds_registers(adev); - si_dpm_start_smc(adev); - ret = si_notify_smc_display_change(adev, false); - if (ret) { - DRM_ERROR("si_notify_smc_display_change failed\n"); - return ret; - } - si_enable_sclk_control(adev, true); - si_start_dpm(adev); - - si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); - si_thermal_start_thermal_controller(adev); - - return 0; -} - -static int si_set_temperature_range(struct amdgpu_device *adev) -{ - int ret; - - ret = si_thermal_enable_alert(adev, false); - if (ret) - return ret; - ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - ret = si_thermal_enable_alert(adev, true); - if (ret) - return ret; - - return ret; -} - -static void si_dpm_disable(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; - - if (!amdgpu_si_is_smc_running(adev)) - return; - si_thermal_stop_thermal_controller(adev); - si_disable_ulv(adev); - si_clear_vc(adev); - if (pi->thermal_protection) - si_enable_thermal_protection(adev, false); - si_enable_power_containment(adev, boot_ps, false); - si_enable_smc_cac(adev, boot_ps, false); - si_enable_spread_spectrum(adev, false); - si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, false); - si_stop_dpm(adev); - si_reset_to_default(adev); - si_dpm_stop_smc(adev); - si_force_switch_to_arb_f0(adev); - - ni_update_current_ps(adev, boot_ps); -} - -static int si_dpm_pre_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; - struct amdgpu_ps *new_ps = &requested_ps; - - ni_update_requested_ps(adev, new_ps); - si_apply_state_adjust_rules(adev, &eg_pi->requested_rps); - - return 0; -} - -static int si_power_control_set_level(struct amdgpu_device *adev) -{ - struct amdgpu_ps *new_ps = adev->pm.dpm.requested_ps; - int ret; - - ret = si_restrict_performance_levels_before_switch(adev); - if (ret) - return ret; - ret = si_halt_smc(adev); - if (ret) - return ret; - ret = si_populate_smc_tdp_limits(adev, new_ps); - if (ret) - return ret; - ret = si_populate_smc_tdp_limits_2(adev, new_ps); - if (ret) - return ret; - ret = si_resume_smc(adev); - if (ret) - return ret; - ret = si_set_sw_state(adev); - if (ret) - return ret; - return 0; -} - -static void si_set_vce_clock(struct amdgpu_device *adev, - struct amdgpu_ps *new_rps, - struct amdgpu_ps *old_rps) -{ - if ((old_rps->evclk != new_rps->evclk) || - (old_rps->ecclk != new_rps->ecclk)) { - /* Turn the clocks on when encoding, off otherwise */ - if (new_rps->evclk || new_rps->ecclk) { - /* Place holder for future VCE1.0 porting to amdgpu - vce_v1_0_enable_mgcg(adev, false, false);*/ - } else { - /* Place holder for future VCE1.0 porting to amdgpu - vce_v1_0_enable_mgcg(adev, true, false); - amdgpu_asic_set_vce_clocks(adev, new_rps->evclk, new_rps->ecclk);*/ - } - } -} - -static int si_dpm_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct amdgpu_ps *new_ps = &eg_pi->requested_rps; - struct amdgpu_ps *old_ps = &eg_pi->current_rps; - int ret; - - ret = si_disable_ulv(adev); - if (ret) { - DRM_ERROR("si_disable_ulv failed\n"); - return ret; - } - ret = si_restrict_performance_levels_before_switch(adev); - if (ret) { - DRM_ERROR("si_restrict_performance_levels_before_switch failed\n"); - return ret; - } - if (eg_pi->pcie_performance_request) - si_request_link_speed_change_before_state_change(adev, new_ps, old_ps); - ni_set_uvd_clock_before_set_eng_clock(adev, new_ps, old_ps); - ret = si_enable_power_containment(adev, new_ps, false); - if (ret) { - DRM_ERROR("si_enable_power_containment failed\n"); - return ret; - } - ret = si_enable_smc_cac(adev, new_ps, false); - if (ret) { - DRM_ERROR("si_enable_smc_cac failed\n"); - return ret; - } - ret = si_halt_smc(adev); - if (ret) { - DRM_ERROR("si_halt_smc failed\n"); - return ret; - } - ret = si_upload_sw_state(adev, new_ps); - if (ret) { - DRM_ERROR("si_upload_sw_state failed\n"); - return ret; - } - ret = si_upload_smc_data(adev); - if (ret) { - DRM_ERROR("si_upload_smc_data failed\n"); - return ret; - } - ret = si_upload_ulv_state(adev); - if (ret) { - DRM_ERROR("si_upload_ulv_state failed\n"); - return ret; - } - if (eg_pi->dynamic_ac_timing) { - ret = si_upload_mc_reg_table(adev, new_ps); - if (ret) { - DRM_ERROR("si_upload_mc_reg_table failed\n"); - return ret; - } - } - ret = si_program_memory_timing_parameters(adev, new_ps); - if (ret) { - DRM_ERROR("si_program_memory_timing_parameters failed\n"); - return ret; - } - si_set_pcie_lane_width_in_smc(adev, new_ps, old_ps); - - ret = si_resume_smc(adev); - if (ret) { - DRM_ERROR("si_resume_smc failed\n"); - return ret; - } - ret = si_set_sw_state(adev); - if (ret) { - DRM_ERROR("si_set_sw_state failed\n"); - return ret; - } - ni_set_uvd_clock_after_set_eng_clock(adev, new_ps, old_ps); - si_set_vce_clock(adev, new_ps, old_ps); - if (eg_pi->pcie_performance_request) - si_notify_link_speed_change_after_state_change(adev, new_ps, old_ps); - ret = si_set_power_state_conditionally_enable_ulv(adev, new_ps); - if (ret) { - DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n"); - return ret; - } - ret = si_enable_smc_cac(adev, new_ps, true); - if (ret) { - DRM_ERROR("si_enable_smc_cac failed\n"); - return ret; - } - ret = si_enable_power_containment(adev, new_ps, true); - if (ret) { - DRM_ERROR("si_enable_power_containment failed\n"); - return ret; - } - - ret = si_power_control_set_level(adev); - if (ret) { - DRM_ERROR("si_power_control_set_level failed\n"); - return ret; - } - - return 0; -} - -static void si_dpm_post_set_power_state(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct amdgpu_ps *new_ps = &eg_pi->requested_rps; - - ni_update_current_ps(adev, new_ps); -} - -#if 0 -void si_dpm_reset_asic(struct amdgpu_device *adev) -{ - si_restrict_performance_levels_before_switch(adev); - si_disable_ulv(adev); - si_set_boot_state(adev); -} -#endif - -static void si_dpm_display_configuration_changed(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - si_program_display_gap(adev); -} - - -static void si_parse_pplib_non_clock_info(struct amdgpu_device *adev, - struct amdgpu_ps *rps, - struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, - u8 table_rev) -{ - rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); - rps->class = le16_to_cpu(non_clock_info->usClassification); - rps->class2 = le16_to_cpu(non_clock_info->usClassification2); - - if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { - rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); - rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); - } else if (r600_is_uvd_state(rps->class, rps->class2)) { - rps->vclk = RV770_DEFAULT_VCLK_FREQ; - rps->dclk = RV770_DEFAULT_DCLK_FREQ; - } else { - rps->vclk = 0; - rps->dclk = 0; - } - - if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) - adev->pm.dpm.boot_ps = rps; - if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - adev->pm.dpm.uvd_ps = rps; -} - -static void si_parse_pplib_clock_info(struct amdgpu_device *adev, - struct amdgpu_ps *rps, int index, - union pplib_clock_info *clock_info) -{ - struct rv7xx_power_info *pi = rv770_get_pi(adev); - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_power_info *si_pi = si_get_pi(adev); - struct si_ps *ps = si_get_ps(rps); - u16 leakage_voltage; - struct rv7xx_pl *pl = &ps->performance_levels[index]; - int ret; - - ps->performance_level_count = index + 1; - - pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow); - pl->sclk |= clock_info->si.ucEngineClockHigh << 16; - pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); - pl->mclk |= clock_info->si.ucMemoryClockHigh << 16; - - pl->vddc = le16_to_cpu(clock_info->si.usVDDC); - pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); - pl->flags = le32_to_cpu(clock_info->si.ulFlags); - pl->pcie_gen = amdgpu_get_pcie_gen_support(adev, - si_pi->sys_pcie_mask, - si_pi->boot_pcie_gen, - clock_info->si.ucPCIEGen); - - /* patch up vddc if necessary */ - ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, - &leakage_voltage); - if (ret == 0) - pl->vddc = leakage_voltage; - - if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { - pi->acpi_vddc = pl->vddc; - eg_pi->acpi_vddci = pl->vddci; - si_pi->acpi_pcie_gen = pl->pcie_gen; - } - - if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) && - index == 0) { - /* XXX disable for A0 tahiti */ - si_pi->ulv.supported = false; - si_pi->ulv.pl = *pl; - si_pi->ulv.one_pcie_lane_in_ulv = false; - si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT; - si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT; - si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT; - } - - if (pi->min_vddc_in_table > pl->vddc) - pi->min_vddc_in_table = pl->vddc; - - if (pi->max_vddc_in_table < pl->vddc) - pi->max_vddc_in_table = pl->vddc; - - /* patch up boot state */ - if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { - u16 vddc, vddci, mvdd; - amdgpu_atombios_get_default_voltages(adev, &vddc, &vddci, &mvdd); - pl->mclk = adev->clock.default_mclk; - pl->sclk = adev->clock.default_sclk; - pl->vddc = vddc; - pl->vddci = vddci; - si_pi->mvdd_bootup_value = mvdd; - } - - if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == - ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { - adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk; - adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk; - adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc; - adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci; - } -} - -union pplib_power_state { - struct _ATOM_PPLIB_STATE v1; - struct _ATOM_PPLIB_STATE_V2 v2; -}; - -static int si_parse_power_table(struct amdgpu_device *adev) -{ - struct amdgpu_mode_info *mode_info = &adev->mode_info; - struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; - union pplib_power_state *power_state; - int i, j, k, non_clock_array_index, clock_array_index; - union pplib_clock_info *clock_info; - struct _StateArray *state_array; - struct _ClockInfoArray *clock_info_array; - struct _NonClockInfoArray *non_clock_info_array; - union power_info *power_info; - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - u16 data_offset; - u8 frev, crev; - u8 *power_state_offset; - struct si_ps *ps; - - if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, - &frev, &crev, &data_offset)) - return -EINVAL; - power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); - - amdgpu_add_thermal_controller(adev); - - state_array = (struct _StateArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usStateArrayOffset)); - clock_info_array = (struct _ClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); - non_clock_info_array = (struct _NonClockInfoArray *) - (mode_info->atom_context->bios + data_offset + - le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); - - adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, - sizeof(struct amdgpu_ps), - GFP_KERNEL); - if (!adev->pm.dpm.ps) - return -ENOMEM; - power_state_offset = (u8 *)state_array->states; - for (i = 0; i < state_array->ucNumEntries; i++) { - u8 *idx; - power_state = (union pplib_power_state *)power_state_offset; - non_clock_array_index = power_state->v2.nonClockInfoIndex; - non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) - &non_clock_info_array->nonClockInfo[non_clock_array_index]; - ps = kzalloc(sizeof(struct si_ps), GFP_KERNEL); - if (ps == NULL) { - kfree(adev->pm.dpm.ps); - return -ENOMEM; - } - adev->pm.dpm.ps[i].ps_priv = ps; - si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], - non_clock_info, - non_clock_info_array->ucEntrySize); - k = 0; - idx = (u8 *)&power_state->v2.clockInfoIndex[0]; - for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { - clock_array_index = idx[j]; - if (clock_array_index >= clock_info_array->ucNumEntries) - continue; - if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS) - break; - clock_info = (union pplib_clock_info *) - ((u8 *)&clock_info_array->clockInfo[0] + - (clock_array_index * clock_info_array->ucEntrySize)); - si_parse_pplib_clock_info(adev, - &adev->pm.dpm.ps[i], k, - clock_info); - k++; - } - power_state_offset += 2 + power_state->v2.ucNumDPMLevels; - } - adev->pm.dpm.num_ps = state_array->ucNumEntries; - - /* fill in the vce power states */ - for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { - u32 sclk, mclk; - clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; - clock_info = (union pplib_clock_info *) - &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; - sclk = le16_to_cpu(clock_info->si.usEngineClockLow); - sclk |= clock_info->si.ucEngineClockHigh << 16; - mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); - mclk |= clock_info->si.ucMemoryClockHigh << 16; - adev->pm.dpm.vce_states[i].sclk = sclk; - adev->pm.dpm.vce_states[i].mclk = mclk; - } - - return 0; -} - -static int si_dpm_init(struct amdgpu_device *adev) -{ - struct rv7xx_power_info *pi; - struct evergreen_power_info *eg_pi; - struct ni_power_info *ni_pi; - struct si_power_info *si_pi; - struct atom_clock_dividers dividers; - int ret; - - si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL); - if (si_pi == NULL) - return -ENOMEM; - adev->pm.dpm.priv = si_pi; - ni_pi = &si_pi->ni; - eg_pi = &ni_pi->eg; - pi = &eg_pi->rv7xx; - - si_pi->sys_pcie_mask = - adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK; - si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; - si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); - - si_set_max_cu_value(adev); - - rv770_get_max_vddc(adev); - si_get_leakage_vddc(adev); - si_patch_dependency_tables_based_on_leakage(adev); - - pi->acpi_vddc = 0; - eg_pi->acpi_vddci = 0; - pi->min_vddc_in_table = 0; - pi->max_vddc_in_table = 0; - - ret = amdgpu_get_platform_caps(adev); - if (ret) - return ret; - - ret = amdgpu_parse_extended_power_table(adev); - if (ret) - return ret; - - ret = si_parse_power_table(adev); - if (ret) - return ret; - - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = - kcalloc(4, - sizeof(struct amdgpu_clock_voltage_dependency_entry), - GFP_KERNEL); - if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { - amdgpu_free_extended_power_table(adev); - return -ENOMEM; - } - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000; - adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900; - - if (adev->pm.dpm.voltage_response_time == 0) - adev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; - if (adev->pm.dpm.backbias_response_time == 0) - adev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT; - - ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, - 0, false, ÷rs); - if (ret) - pi->ref_div = dividers.ref_div + 1; - else - pi->ref_div = R600_REFERENCEDIVIDER_DFLT; - - eg_pi->smu_uvd_hs = false; - - pi->mclk_strobe_mode_threshold = 40000; - if (si_is_special_1gb_platform(adev)) - pi->mclk_stutter_mode_threshold = 0; - else - pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold; - pi->mclk_edc_enable_threshold = 40000; - eg_pi->mclk_edc_wr_enable_threshold = 40000; - - ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold; - - pi->voltage_control = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, - VOLTAGE_OBJ_GPIO_LUT); - if (!pi->voltage_control) { - si_pi->voltage_control_svi2 = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, - VOLTAGE_OBJ_SVID2); - if (si_pi->voltage_control_svi2) - amdgpu_atombios_get_svi2_info(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, - &si_pi->svd_gpio_id, &si_pi->svc_gpio_id); - } - - pi->mvdd_control = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_MVDDC, - VOLTAGE_OBJ_GPIO_LUT); - - eg_pi->vddci_control = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, - VOLTAGE_OBJ_GPIO_LUT); - if (!eg_pi->vddci_control) - si_pi->vddci_control_svi2 = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, - VOLTAGE_OBJ_SVID2); - - si_pi->vddc_phase_shed_control = - amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, - VOLTAGE_OBJ_PHASE_LUT); - - rv770_get_engine_memory_ss(adev); - - pi->asi = RV770_ASI_DFLT; - pi->pasi = CYPRESS_HASI_DFLT; - pi->vrc = SISLANDS_VRC_DFLT; - - pi->gfx_clock_gating = true; - - eg_pi->sclk_deep_sleep = true; - si_pi->sclk_deep_sleep_above_low = false; - - if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE) - pi->thermal_protection = true; - else - pi->thermal_protection = false; - - eg_pi->dynamic_ac_timing = true; - - eg_pi->light_sleep = true; -#if defined(CONFIG_ACPI) - eg_pi->pcie_performance_request = - amdgpu_acpi_is_pcie_performance_request_supported(adev); -#else - eg_pi->pcie_performance_request = false; -#endif - - si_pi->sram_end = SMC_RAM_END; - - adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4; - adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000; - adev->pm.dpm.dyn_state.vddc_vddci_delta = 200; - adev->pm.dpm.dyn_state.valid_sclk_values.count = 0; - adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL; - adev->pm.dpm.dyn_state.valid_mclk_values.count = 0; - adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL; - - si_initialize_powertune_defaults(adev); - - /* make sure dc limits are valid */ - if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) || - (adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0)) - adev->pm.dpm.dyn_state.max_clock_voltage_on_dc = - adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; - - si_pi->fan_ctrl_is_in_default_mode = true; - - return 0; -} - -static void si_dpm_fini(struct amdgpu_device *adev) -{ - int i; - - if (adev->pm.dpm.ps) - for (i = 0; i < adev->pm.dpm.num_ps; i++) - kfree(adev->pm.dpm.ps[i].ps_priv); - kfree(adev->pm.dpm.ps); - kfree(adev->pm.dpm.priv); - kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); - amdgpu_free_extended_power_table(adev); -} - -static void si_dpm_debugfs_print_current_performance_level(void *handle, - struct seq_file *m) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct amdgpu_ps *rps = &eg_pi->current_rps; - struct si_ps *ps = si_get_ps(rps); - struct rv7xx_pl *pl; - u32 current_index = - (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> - CURRENT_STATE_INDEX_SHIFT; - - if (current_index >= ps->performance_level_count) { - seq_printf(m, "invalid dpm profile %d\n", current_index); - } else { - pl = &ps->performance_levels[current_index]; - seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); - seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", - current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); - } -} - -static int si_dpm_set_interrupt_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned type, - enum amdgpu_interrupt_state state) -{ - u32 cg_thermal_int; - - switch (type) { - case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH: - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); - cg_thermal_int |= THERM_INT_MASK_HIGH; - WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); - break; - case AMDGPU_IRQ_STATE_ENABLE: - cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); - cg_thermal_int &= ~THERM_INT_MASK_HIGH; - WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); - break; - default: - break; - } - break; - - case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW: - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); - cg_thermal_int |= THERM_INT_MASK_LOW; - WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); - break; - case AMDGPU_IRQ_STATE_ENABLE: - cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); - cg_thermal_int &= ~THERM_INT_MASK_LOW; - WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); - break; - default: - break; - } - break; - - default: - break; - } - return 0; -} - -static int si_dpm_process_interrupt(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - bool queue_thermal = false; - - if (entry == NULL) - return -EINVAL; - - switch (entry->src_id) { - case 230: /* thermal low to high */ - DRM_DEBUG("IH: thermal low to high\n"); - adev->pm.dpm.thermal.high_to_low = false; - queue_thermal = true; - break; - case 231: /* thermal high to low */ - DRM_DEBUG("IH: thermal high to low\n"); - adev->pm.dpm.thermal.high_to_low = true; - queue_thermal = true; - break; - default: - break; - } - - if (queue_thermal) - schedule_work(&adev->pm.dpm.thermal.work); - - return 0; -} - -static int si_dpm_late_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (!adev->pm.dpm_enabled) - return 0; - - ret = si_set_temperature_range(adev); - if (ret) - return ret; -#if 0 //TODO ? - si_dpm_powergate_uvd(adev, true); -#endif - return 0; -} - -/** - * si_dpm_init_microcode - load ucode images from disk - * - * @adev: amdgpu_device pointer - * - * Use the firmware interface to load the ucode images into - * the driver (not loaded into hw). - * Returns 0 on success, error on failure. - */ -static int si_dpm_init_microcode(struct amdgpu_device *adev) -{ - const char *chip_name; - char fw_name[30]; - int err; - - DRM_DEBUG("\n"); - switch (adev->asic_type) { - case CHIP_TAHITI: - chip_name = "tahiti"; - break; - case CHIP_PITCAIRN: - if ((adev->pdev->revision == 0x81) && - ((adev->pdev->device == 0x6810) || - (adev->pdev->device == 0x6811))) - chip_name = "pitcairn_k"; - else - chip_name = "pitcairn"; - break; - case CHIP_VERDE: - if (((adev->pdev->device == 0x6820) && - ((adev->pdev->revision == 0x81) || - (adev->pdev->revision == 0x83))) || - ((adev->pdev->device == 0x6821) && - ((adev->pdev->revision == 0x83) || - (adev->pdev->revision == 0x87))) || - ((adev->pdev->revision == 0x87) && - ((adev->pdev->device == 0x6823) || - (adev->pdev->device == 0x682b)))) - chip_name = "verde_k"; - else - chip_name = "verde"; - break; - case CHIP_OLAND: - if (((adev->pdev->revision == 0x81) && - ((adev->pdev->device == 0x6600) || - (adev->pdev->device == 0x6604) || - (adev->pdev->device == 0x6605) || - (adev->pdev->device == 0x6610))) || - ((adev->pdev->revision == 0x83) && - (adev->pdev->device == 0x6610))) - chip_name = "oland_k"; - else - chip_name = "oland"; - break; - case CHIP_HAINAN: - if (((adev->pdev->revision == 0x81) && - (adev->pdev->device == 0x6660)) || - ((adev->pdev->revision == 0x83) && - ((adev->pdev->device == 0x6660) || - (adev->pdev->device == 0x6663) || - (adev->pdev->device == 0x6665) || - (adev->pdev->device == 0x6667)))) - chip_name = "hainan_k"; - else if ((adev->pdev->revision == 0xc3) && - (adev->pdev->device == 0x6665)) - chip_name = "banks_k_2"; - else - chip_name = "hainan"; - break; - default: BUG(); - } - - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); - err = request_firmware(&adev->pm.fw, fw_name, adev->dev); - if (err) - goto out; - err = amdgpu_ucode_validate(adev->pm.fw); - -out: - if (err) { - DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n", - err, fw_name); - release_firmware(adev->pm.fw); - adev->pm.fw = NULL; - } - return err; - -} - -static int si_dpm_sw_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, &adev->pm.dpm.thermal.irq); - if (ret) - return ret; - - ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, &adev->pm.dpm.thermal.irq); - if (ret) - return ret; - - /* default to balanced state */ - adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; - adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; - adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO; - adev->pm.default_sclk = adev->clock.default_sclk; - adev->pm.default_mclk = adev->clock.default_mclk; - adev->pm.current_sclk = adev->clock.default_sclk; - adev->pm.current_mclk = adev->clock.default_mclk; - adev->pm.int_thermal_type = THERMAL_TYPE_NONE; - - if (amdgpu_dpm == 0) - return 0; - - ret = si_dpm_init_microcode(adev); - if (ret) - return ret; - - INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); - mutex_lock(&adev->pm.mutex); - ret = si_dpm_init(adev); - if (ret) - goto dpm_failed; - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - if (amdgpu_dpm == 1) - amdgpu_pm_print_power_states(adev); - mutex_unlock(&adev->pm.mutex); - DRM_INFO("amdgpu: dpm initialized\n"); - - return 0; - -dpm_failed: - si_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); - DRM_ERROR("amdgpu: dpm initialization failed\n"); - return ret; -} - -static int si_dpm_sw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - flush_work(&adev->pm.dpm.thermal.work); - - mutex_lock(&adev->pm.mutex); - si_dpm_fini(adev); - mutex_unlock(&adev->pm.mutex); - - return 0; -} - -static int si_dpm_hw_init(void *handle) -{ - int ret; - - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (!amdgpu_dpm) - return 0; - - mutex_lock(&adev->pm.mutex); - si_dpm_setup_asic(adev); - ret = si_dpm_enable(adev); - if (ret) - adev->pm.dpm_enabled = false; - else - adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); - amdgpu_pm_compute_clocks(adev); - return ret; -} - -static int si_dpm_hw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - si_dpm_disable(adev); - mutex_unlock(&adev->pm.mutex); - } - - return 0; -} - -static int si_dpm_suspend(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - mutex_lock(&adev->pm.mutex); - /* disable dpm */ - si_dpm_disable(adev); - /* reset the power state */ - adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; - mutex_unlock(&adev->pm.mutex); - } - return 0; -} - -static int si_dpm_resume(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev->pm.dpm_enabled) { - /* asic init will reset to the boot state */ - mutex_lock(&adev->pm.mutex); - si_dpm_setup_asic(adev); - ret = si_dpm_enable(adev); - if (ret) - adev->pm.dpm_enabled = false; - else - adev->pm.dpm_enabled = true; - mutex_unlock(&adev->pm.mutex); - if (adev->pm.dpm_enabled) - amdgpu_pm_compute_clocks(adev); - } - return 0; -} - -static bool si_dpm_is_idle(void *handle) -{ - /* XXX */ - return true; -} - -static int si_dpm_wait_for_idle(void *handle) -{ - /* XXX */ - return 0; -} - -static int si_dpm_soft_reset(void *handle) -{ - return 0; -} - -static int si_dpm_set_clockgating_state(void *handle, - enum amd_clockgating_state state) -{ - return 0; -} - -static int si_dpm_set_powergating_state(void *handle, - enum amd_powergating_state state) -{ - return 0; -} - -/* get temperature in millidegrees */ -static int si_dpm_get_temp(void *handle) -{ - u32 temp; - int actual_temp = 0; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> - CTF_TEMP_SHIFT; - - if (temp & 0x200) - actual_temp = 255; - else - actual_temp = temp & 0x1ff; - - actual_temp = (actual_temp * 1000); - - return actual_temp; -} - -static u32 si_dpm_get_sclk(void *handle, bool low) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); - - if (low) - return requested_state->performance_levels[0].sclk; - else - return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; -} - -static u32 si_dpm_get_mclk(void *handle, bool low) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); - - if (low) - return requested_state->performance_levels[0].mclk; - else - return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; -} - -static void si_dpm_print_power_state(void *handle, - void *current_ps) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps; - struct si_ps *ps = si_get_ps(rps); - struct rv7xx_pl *pl; - int i; - - amdgpu_dpm_print_class_info(rps->class, rps->class2); - amdgpu_dpm_print_cap_info(rps->caps); - DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); - for (i = 0; i < ps->performance_level_count; i++) { - pl = &ps->performance_levels[i]; - if (adev->asic_type >= CHIP_TAHITI) - DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", - i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); - else - DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", - i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); - } - amdgpu_dpm_print_ps_status(adev, rps); -} - -static int si_dpm_early_init(void *handle) -{ - - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - adev->powerplay.pp_funcs = &si_dpm_funcs; - adev->powerplay.pp_handle = adev; - si_dpm_set_irq_funcs(adev); - return 0; -} - -static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1, - const struct rv7xx_pl *si_cpl2) -{ - return ((si_cpl1->mclk == si_cpl2->mclk) && - (si_cpl1->sclk == si_cpl2->sclk) && - (si_cpl1->pcie_gen == si_cpl2->pcie_gen) && - (si_cpl1->vddc == si_cpl2->vddc) && - (si_cpl1->vddci == si_cpl2->vddci)); -} - -static int si_check_state_equal(void *handle, - void *current_ps, - void *request_ps, - bool *equal) -{ - struct si_ps *si_cps; - struct si_ps *si_rps; - int i; - struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; - struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) - return -EINVAL; - - si_cps = si_get_ps((struct amdgpu_ps *)cps); - si_rps = si_get_ps((struct amdgpu_ps *)rps); - - if (si_cps == NULL) { - printk("si_cps is NULL\n"); - *equal = false; - return 0; - } - - if (si_cps->performance_level_count != si_rps->performance_level_count) { - *equal = false; - return 0; - } - - for (i = 0; i < si_cps->performance_level_count; i++) { - if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]), - &(si_rps->performance_levels[i]))) { - *equal = false; - return 0; - } - } - - /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ - *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); - *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); - - return 0; -} - -static int si_dpm_read_sensor(void *handle, int idx, - void *value, int *size) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); - struct amdgpu_ps *rps = &eg_pi->current_rps; - struct si_ps *ps = si_get_ps(rps); - uint32_t sclk, mclk; - u32 pl_index = - (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> - CURRENT_STATE_INDEX_SHIFT; - - /* size must be at least 4 bytes for all sensors */ - if (*size < 4) - return -EINVAL; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - if (pl_index < ps->performance_level_count) { - sclk = ps->performance_levels[pl_index].sclk; - *((uint32_t *)value) = sclk; - *size = 4; - return 0; - } - return -EINVAL; - case AMDGPU_PP_SENSOR_GFX_MCLK: - if (pl_index < ps->performance_level_count) { - mclk = ps->performance_levels[pl_index].mclk; - *((uint32_t *)value) = mclk; - *size = 4; - return 0; - } - return -EINVAL; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = si_dpm_get_temp(adev); - *size = 4; - return 0; - default: - return -EINVAL; - } -} - -static const struct amd_ip_funcs si_dpm_ip_funcs = { - .name = "si_dpm", - .early_init = si_dpm_early_init, - .late_init = si_dpm_late_init, - .sw_init = si_dpm_sw_init, - .sw_fini = si_dpm_sw_fini, - .hw_init = si_dpm_hw_init, - .hw_fini = si_dpm_hw_fini, - .suspend = si_dpm_suspend, - .resume = si_dpm_resume, - .is_idle = si_dpm_is_idle, - .wait_for_idle = si_dpm_wait_for_idle, - .soft_reset = si_dpm_soft_reset, - .set_clockgating_state = si_dpm_set_clockgating_state, - .set_powergating_state = si_dpm_set_powergating_state, -}; - -const struct amdgpu_ip_block_version si_smu_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 6, - .minor = 0, - .rev = 0, - .funcs = &si_dpm_ip_funcs, -}; - -static const struct amd_pm_funcs si_dpm_funcs = { - .pre_set_power_state = &si_dpm_pre_set_power_state, - .set_power_state = &si_dpm_set_power_state, - .post_set_power_state = &si_dpm_post_set_power_state, - .display_configuration_changed = &si_dpm_display_configuration_changed, - .get_sclk = &si_dpm_get_sclk, - .get_mclk = &si_dpm_get_mclk, - .print_power_state = &si_dpm_print_power_state, - .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, - .force_performance_level = &si_dpm_force_performance_level, - .vblank_too_short = &si_dpm_vblank_too_short, - .set_fan_control_mode = &si_dpm_set_fan_control_mode, - .get_fan_control_mode = &si_dpm_get_fan_control_mode, - .set_fan_speed_percent = &si_dpm_set_fan_speed_percent, - .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, - .check_state_equal = &si_check_state_equal, - .get_vce_clock_state = amdgpu_get_vce_clock_state, - .read_sensor = &si_dpm_read_sensor, -}; - -static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { - .set = si_dpm_set_interrupt_state, - .process = si_dpm_process_interrupt, -}; - -static void si_dpm_set_irq_funcs(struct amdgpu_device *adev) -{ - adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; - adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs; -} - diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.h b/drivers/gpu/drm/amd/amdgpu/si_dpm.h deleted file mode 100644 index bc0be6818e21..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.h +++ /dev/null @@ -1,1015 +0,0 @@ -/* - * Copyright 2012 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 __SI_DPM_H__ -#define __SI_DPM_H__ - -#include "amdgpu_atombios.h" -#include "sislands_smc.h" - -#define MC_CG_CONFIG 0x96f -#define MC_ARB_CG 0x9fa -#define CG_ARB_REQ(x) ((x) << 0) -#define CG_ARB_REQ_MASK (0xff << 0) - -#define MC_ARB_DRAM_TIMING_1 0x9fc -#define MC_ARB_DRAM_TIMING_2 0x9fd -#define MC_ARB_DRAM_TIMING_3 0x9fe -#define MC_ARB_DRAM_TIMING2_1 0x9ff -#define MC_ARB_DRAM_TIMING2_2 0xa00 -#define MC_ARB_DRAM_TIMING2_3 0xa01 - -#define MAX_NO_OF_MVDD_VALUES 2 -#define MAX_NO_VREG_STEPS 32 -#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 -#define SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE 32 -#define SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 -#define RV770_ASI_DFLT 1000 -#define CYPRESS_HASI_DFLT 400000 -#define PCIE_PERF_REQ_PECI_GEN1 2 -#define PCIE_PERF_REQ_PECI_GEN2 3 -#define PCIE_PERF_REQ_PECI_GEN3 4 -#define RV770_DEFAULT_VCLK_FREQ 53300 /* 10 khz */ -#define RV770_DEFAULT_DCLK_FREQ 40000 /* 10 khz */ - -#define SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE 16 - -#define RV770_SMC_TABLE_ADDRESS 0xB000 -#define RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 3 - -#define SMC_STROBE_RATIO 0x0F -#define SMC_STROBE_ENABLE 0x10 - -#define SMC_MC_EDC_RD_FLAG 0x01 -#define SMC_MC_EDC_WR_FLAG 0x02 -#define SMC_MC_RTT_ENABLE 0x04 -#define SMC_MC_STUTTER_EN 0x08 - -#define RV770_SMC_VOLTAGEMASK_VDDC 0 -#define RV770_SMC_VOLTAGEMASK_MVDD 1 -#define RV770_SMC_VOLTAGEMASK_VDDCI 2 -#define RV770_SMC_VOLTAGEMASK_MAX 4 - -#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 -#define NISLANDS_SMC_STROBE_RATIO 0x0F -#define NISLANDS_SMC_STROBE_ENABLE 0x10 - -#define NISLANDS_SMC_MC_EDC_RD_FLAG 0x01 -#define NISLANDS_SMC_MC_EDC_WR_FLAG 0x02 -#define NISLANDS_SMC_MC_RTT_ENABLE 0x04 -#define NISLANDS_SMC_MC_STUTTER_EN 0x08 - -#define MAX_NO_VREG_STEPS 32 - -#define NISLANDS_SMC_VOLTAGEMASK_VDDC 0 -#define NISLANDS_SMC_VOLTAGEMASK_MVDD 1 -#define NISLANDS_SMC_VOLTAGEMASK_VDDCI 2 -#define NISLANDS_SMC_VOLTAGEMASK_MAX 4 - -#define SISLANDS_MCREGISTERTABLE_INITIAL_SLOT 0 -#define SISLANDS_MCREGISTERTABLE_ACPI_SLOT 1 -#define SISLANDS_MCREGISTERTABLE_ULV_SLOT 2 -#define SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT 3 - -#define SISLANDS_LEAKAGE_INDEX0 0xff01 -#define SISLANDS_MAX_LEAKAGE_COUNT 4 - -#define SISLANDS_MAX_HARDWARE_POWERLEVELS 5 -#define SISLANDS_INITIAL_STATE_ARB_INDEX 0 -#define SISLANDS_ACPI_STATE_ARB_INDEX 1 -#define SISLANDS_ULV_STATE_ARB_INDEX 2 -#define SISLANDS_DRIVER_STATE_ARB_INDEX 3 - -#define SISLANDS_DPM2_MAX_PULSE_SKIP 256 - -#define SISLANDS_DPM2_NEAR_TDP_DEC 10 -#define SISLANDS_DPM2_ABOVE_SAFE_INC 5 -#define SISLANDS_DPM2_BELOW_SAFE_INC 20 - -#define SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT 80 - -#define SISLANDS_DPM2_MAXPS_PERCENT_H 99 -#define SISLANDS_DPM2_MAXPS_PERCENT_M 99 - -#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER 0x3FFF -#define SISLANDS_DPM2_SQ_RAMP_MIN_POWER 0x12 -#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 -#define SISLANDS_DPM2_SQ_RAMP_STI_SIZE 0x1E -#define SISLANDS_DPM2_SQ_RAMP_LTI_RATIO 0xF - -#define SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN 10 - -#define SISLANDS_VRC_DFLT 0xC000B3 -#define SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT 1687 -#define SISLANDS_CGULVPARAMETER_DFLT 0x00040035 -#define SISLANDS_CGULVCONTROL_DFLT 0x1f007550 - -#define SI_ASI_DFLT 10000 -#define SI_BSP_DFLT 0x41EB -#define SI_BSU_DFLT 0x2 -#define SI_AH_DFLT 5 -#define SI_RLP_DFLT 25 -#define SI_RMP_DFLT 65 -#define SI_LHP_DFLT 40 -#define SI_LMP_DFLT 15 -#define SI_TD_DFLT 0 -#define SI_UTC_DFLT_00 0x24 -#define SI_UTC_DFLT_01 0x22 -#define SI_UTC_DFLT_02 0x22 -#define SI_UTC_DFLT_03 0x22 -#define SI_UTC_DFLT_04 0x22 -#define SI_UTC_DFLT_05 0x22 -#define SI_UTC_DFLT_06 0x22 -#define SI_UTC_DFLT_07 0x22 -#define SI_UTC_DFLT_08 0x22 -#define SI_UTC_DFLT_09 0x22 -#define SI_UTC_DFLT_10 0x22 -#define SI_UTC_DFLT_11 0x22 -#define SI_UTC_DFLT_12 0x22 -#define SI_UTC_DFLT_13 0x22 -#define SI_UTC_DFLT_14 0x22 -#define SI_DTC_DFLT_00 0x24 -#define SI_DTC_DFLT_01 0x22 -#define SI_DTC_DFLT_02 0x22 -#define SI_DTC_DFLT_03 0x22 -#define SI_DTC_DFLT_04 0x22 -#define SI_DTC_DFLT_05 0x22 -#define SI_DTC_DFLT_06 0x22 -#define SI_DTC_DFLT_07 0x22 -#define SI_DTC_DFLT_08 0x22 -#define SI_DTC_DFLT_09 0x22 -#define SI_DTC_DFLT_10 0x22 -#define SI_DTC_DFLT_11 0x22 -#define SI_DTC_DFLT_12 0x22 -#define SI_DTC_DFLT_13 0x22 -#define SI_DTC_DFLT_14 0x22 -#define SI_VRC_DFLT 0x0000C003 -#define SI_VOLTAGERESPONSETIME_DFLT 1000 -#define SI_BACKBIASRESPONSETIME_DFLT 1000 -#define SI_VRU_DFLT 0x3 -#define SI_SPLLSTEPTIME_DFLT 0x1000 -#define SI_SPLLSTEPUNIT_DFLT 0x3 -#define SI_TPU_DFLT 0 -#define SI_TPC_DFLT 0x200 -#define SI_SSTU_DFLT 0 -#define SI_SST_DFLT 0x00C8 -#define SI_GICST_DFLT 0x200 -#define SI_FCT_DFLT 0x0400 -#define SI_FCTU_DFLT 0 -#define SI_CTXCGTT3DRPHC_DFLT 0x20 -#define SI_CTXCGTT3DRSDC_DFLT 0x40 -#define SI_VDDC3DOORPHC_DFLT 0x100 -#define SI_VDDC3DOORSDC_DFLT 0x7 -#define SI_VDDC3DOORSU_DFLT 0 -#define SI_MPLLLOCKTIME_DFLT 100 -#define SI_MPLLRESETTIME_DFLT 150 -#define SI_VCOSTEPPCT_DFLT 20 -#define SI_ENDINGVCOSTEPPCT_DFLT 5 -#define SI_REFERENCEDIVIDER_DFLT 4 - -#define SI_PM_NUMBER_OF_TC 15 -#define SI_PM_NUMBER_OF_SCLKS 20 -#define SI_PM_NUMBER_OF_MCLKS 4 -#define SI_PM_NUMBER_OF_VOLTAGE_LEVELS 4 -#define SI_PM_NUMBER_OF_ACTIVITY_LEVELS 3 - -/* XXX are these ok? */ -#define SI_TEMP_RANGE_MIN (90 * 1000) -#define SI_TEMP_RANGE_MAX (120 * 1000) - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -enum ni_dc_cac_level -{ - NISLANDS_DCCAC_LEVEL_0 = 0, - NISLANDS_DCCAC_LEVEL_1, - NISLANDS_DCCAC_LEVEL_2, - NISLANDS_DCCAC_LEVEL_3, - NISLANDS_DCCAC_LEVEL_4, - NISLANDS_DCCAC_LEVEL_5, - NISLANDS_DCCAC_LEVEL_6, - NISLANDS_DCCAC_LEVEL_7, - NISLANDS_DCCAC_MAX_LEVELS -}; - -enum si_cac_config_reg_type -{ - SISLANDS_CACCONFIG_MMR = 0, - SISLANDS_CACCONFIG_CGIND, - SISLANDS_CACCONFIG_MAX -}; - -enum si_power_level { - SI_POWER_LEVEL_LOW = 0, - SI_POWER_LEVEL_MEDIUM = 1, - SI_POWER_LEVEL_HIGH = 2, - SI_POWER_LEVEL_CTXSW = 3, -}; - -enum si_td { - SI_TD_AUTO, - SI_TD_UP, - SI_TD_DOWN, -}; - -enum si_display_watermark { - SI_DISPLAY_WATERMARK_LOW = 0, - SI_DISPLAY_WATERMARK_HIGH = 1, -}; - -enum si_display_gap -{ - SI_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, - SI_PM_DISPLAY_GAP_VBLANK = 1, - SI_PM_DISPLAY_GAP_WATERMARK = 2, - SI_PM_DISPLAY_GAP_IGNORE = 3, -}; - -extern const struct amdgpu_ip_block_version si_smu_ip_block; - -struct ni_leakage_coeffients -{ - u32 at; - u32 bt; - u32 av; - u32 bv; - s32 t_slope; - s32 t_intercept; - u32 t_ref; -}; - -struct SMC_Evergreen_MCRegisterAddress -{ - uint16_t s0; - uint16_t s1; -}; - -typedef struct SMC_Evergreen_MCRegisterAddress SMC_Evergreen_MCRegisterAddress; - -struct evergreen_mc_reg_entry { - u32 mclk_max; - u32 mc_data[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; -}; - -struct evergreen_mc_reg_table { - u8 last; - u8 num_entries; - u16 valid_flag; - struct evergreen_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMC_Evergreen_MCRegisterAddress mc_reg_address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; -}; - -struct SMC_Evergreen_MCRegisterSet -{ - uint32_t value[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; -}; - -typedef struct SMC_Evergreen_MCRegisterSet SMC_Evergreen_MCRegisterSet; - -struct SMC_Evergreen_MCRegisters -{ - uint8_t last; - uint8_t reserved[3]; - SMC_Evergreen_MCRegisterAddress address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; - SMC_Evergreen_MCRegisterSet data[5]; -}; - -typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters; - -struct SMC_NIslands_MCRegisterSet -{ - uint32_t value[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -typedef struct SMC_NIslands_MCRegisterSet SMC_NIslands_MCRegisterSet; - -struct ni_mc_reg_entry { - u32 mclk_max; - u32 mc_data[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -struct SMC_NIslands_MCRegisterAddress -{ - uint16_t s0; - uint16_t s1; -}; - -typedef struct SMC_NIslands_MCRegisterAddress SMC_NIslands_MCRegisterAddress; - -struct SMC_NIslands_MCRegisters -{ - uint8_t last; - uint8_t reserved[3]; - SMC_NIslands_MCRegisterAddress address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; - SMC_NIslands_MCRegisterSet data[SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; -}; - -typedef struct SMC_NIslands_MCRegisters SMC_NIslands_MCRegisters; - -struct evergreen_ulv_param { - bool supported; - struct rv7xx_pl *pl; -}; - -struct evergreen_arb_registers { - u32 mc_arb_dram_timing; - u32 mc_arb_dram_timing2; - u32 mc_arb_rfsh_rate; - u32 mc_arb_burst_time; -}; - -struct at { - u32 rlp; - u32 rmp; - u32 lhp; - u32 lmp; -}; - -struct ni_clock_registers { - u32 cg_spll_func_cntl; - u32 cg_spll_func_cntl_2; - u32 cg_spll_func_cntl_3; - u32 cg_spll_func_cntl_4; - u32 cg_spll_spread_spectrum; - u32 cg_spll_spread_spectrum_2; - u32 mclk_pwrmgt_cntl; - u32 dll_cntl; - u32 mpll_ad_func_cntl; - u32 mpll_ad_func_cntl_2; - u32 mpll_dq_func_cntl; - u32 mpll_dq_func_cntl_2; - u32 mpll_ss1; - u32 mpll_ss2; -}; - -struct RV770_SMC_SCLK_VALUE -{ - uint32_t vCG_SPLL_FUNC_CNTL; - uint32_t vCG_SPLL_FUNC_CNTL_2; - uint32_t vCG_SPLL_FUNC_CNTL_3; - uint32_t vCG_SPLL_SPREAD_SPECTRUM; - uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t sclk_value; -}; - -typedef struct RV770_SMC_SCLK_VALUE RV770_SMC_SCLK_VALUE; - -struct RV770_SMC_MCLK_VALUE -{ - uint32_t vMPLL_AD_FUNC_CNTL; - uint32_t vMPLL_AD_FUNC_CNTL_2; - uint32_t vMPLL_DQ_FUNC_CNTL; - uint32_t vMPLL_DQ_FUNC_CNTL_2; - uint32_t vMCLK_PWRMGT_CNTL; - uint32_t vDLL_CNTL; - uint32_t vMPLL_SS; - uint32_t vMPLL_SS2; - uint32_t mclk_value; -}; - -typedef struct RV770_SMC_MCLK_VALUE RV770_SMC_MCLK_VALUE; - - -struct RV730_SMC_MCLK_VALUE -{ - uint32_t vMCLK_PWRMGT_CNTL; - uint32_t vDLL_CNTL; - uint32_t vMPLL_FUNC_CNTL; - uint32_t vMPLL_FUNC_CNTL2; - uint32_t vMPLL_FUNC_CNTL3; - uint32_t vMPLL_SS; - uint32_t vMPLL_SS2; - uint32_t mclk_value; -}; - -typedef struct RV730_SMC_MCLK_VALUE RV730_SMC_MCLK_VALUE; - -struct RV770_SMC_VOLTAGE_VALUE -{ - uint16_t value; - uint8_t index; - uint8_t padding; -}; - -typedef struct RV770_SMC_VOLTAGE_VALUE RV770_SMC_VOLTAGE_VALUE; - -union RV7XX_SMC_MCLK_VALUE -{ - RV770_SMC_MCLK_VALUE mclk770; - RV730_SMC_MCLK_VALUE mclk730; -}; - -typedef union RV7XX_SMC_MCLK_VALUE RV7XX_SMC_MCLK_VALUE, *LPRV7XX_SMC_MCLK_VALUE; - -struct RV770_SMC_HW_PERFORMANCE_LEVEL -{ - uint8_t arbValue; - union{ - uint8_t seqValue; - uint8_t ACIndex; - }; - uint8_t displayWatermark; - uint8_t gen2PCIE; - uint8_t gen2XSP; - uint8_t backbias; - uint8_t strobeMode; - uint8_t mcFlags; - uint32_t aT; - uint32_t bSP; - RV770_SMC_SCLK_VALUE sclk; - RV7XX_SMC_MCLK_VALUE mclk; - RV770_SMC_VOLTAGE_VALUE vddc; - RV770_SMC_VOLTAGE_VALUE mvdd; - RV770_SMC_VOLTAGE_VALUE vddci; - uint8_t reserved1; - uint8_t reserved2; - uint8_t stateFlags; - uint8_t padding; -}; - -typedef struct RV770_SMC_HW_PERFORMANCE_LEVEL RV770_SMC_HW_PERFORMANCE_LEVEL; - -struct RV770_SMC_SWSTATE -{ - uint8_t flags; - uint8_t padding1; - uint8_t padding2; - uint8_t padding3; - RV770_SMC_HW_PERFORMANCE_LEVEL levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; -}; - -typedef struct RV770_SMC_SWSTATE RV770_SMC_SWSTATE; - -struct RV770_SMC_VOLTAGEMASKTABLE -{ - uint8_t highMask[RV770_SMC_VOLTAGEMASK_MAX]; - uint32_t lowMask[RV770_SMC_VOLTAGEMASK_MAX]; -}; - -typedef struct RV770_SMC_VOLTAGEMASKTABLE RV770_SMC_VOLTAGEMASKTABLE; - -struct RV770_SMC_STATETABLE -{ - uint8_t thermalProtectType; - uint8_t systemFlags; - uint8_t maxVDDCIndexInPPTable; - uint8_t extraFlags; - uint8_t highSMIO[MAX_NO_VREG_STEPS]; - uint32_t lowSMIO[MAX_NO_VREG_STEPS]; - RV770_SMC_VOLTAGEMASKTABLE voltageMaskTable; - RV770_SMC_SWSTATE initialState; - RV770_SMC_SWSTATE ACPIState; - RV770_SMC_SWSTATE driverState; - RV770_SMC_SWSTATE ULVState; -}; - -typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE; - -struct vddc_table_entry { - u16 vddc; - u8 vddc_index; - u8 high_smio; - u32 low_smio; -}; - -struct rv770_clock_registers { - u32 cg_spll_func_cntl; - u32 cg_spll_func_cntl_2; - u32 cg_spll_func_cntl_3; - u32 cg_spll_spread_spectrum; - u32 cg_spll_spread_spectrum_2; - u32 mpll_ad_func_cntl; - u32 mpll_ad_func_cntl_2; - u32 mpll_dq_func_cntl; - u32 mpll_dq_func_cntl_2; - u32 mclk_pwrmgt_cntl; - u32 dll_cntl; - u32 mpll_ss1; - u32 mpll_ss2; -}; - -struct rv730_clock_registers { - u32 cg_spll_func_cntl; - u32 cg_spll_func_cntl_2; - u32 cg_spll_func_cntl_3; - u32 cg_spll_spread_spectrum; - u32 cg_spll_spread_spectrum_2; - u32 mclk_pwrmgt_cntl; - u32 dll_cntl; - u32 mpll_func_cntl; - u32 mpll_func_cntl2; - u32 mpll_func_cntl3; - u32 mpll_ss; - u32 mpll_ss2; -}; - -union r7xx_clock_registers { - struct rv770_clock_registers rv770; - struct rv730_clock_registers rv730; -}; - -struct rv7xx_power_info { - /* flags */ - bool mem_gddr5; - bool pcie_gen2; - bool dynamic_pcie_gen2; - bool acpi_pcie_gen2; - bool boot_in_gen2; - bool voltage_control; /* vddc */ - bool mvdd_control; - bool sclk_ss; - bool mclk_ss; - bool dynamic_ss; - bool gfx_clock_gating; - bool mg_clock_gating; - bool mgcgtssm; - bool power_gating; - bool thermal_protection; - bool display_gap; - bool dcodt; - bool ulps; - /* registers */ - union r7xx_clock_registers clk_regs; - u32 s0_vid_lower_smio_cntl; - /* voltage */ - u32 vddc_mask_low; - u32 mvdd_mask_low; - u32 mvdd_split_frequency; - u32 mvdd_low_smio[MAX_NO_OF_MVDD_VALUES]; - u16 max_vddc; - u16 max_vddc_in_table; - u16 min_vddc_in_table; - struct vddc_table_entry vddc_table[MAX_NO_VREG_STEPS]; - u8 valid_vddc_entries; - /* dc odt */ - u32 mclk_odt_threshold; - u8 odt_value_0[2]; - u8 odt_value_1[2]; - /* stored values */ - u32 boot_sclk; - u16 acpi_vddc; - u32 ref_div; - u32 active_auto_throttle_sources; - u32 mclk_stutter_mode_threshold; - u32 mclk_strobe_mode_threshold; - u32 mclk_edc_enable_threshold; - u32 bsp; - u32 bsu; - u32 pbsp; - u32 pbsu; - u32 dsp; - u32 psp; - u32 asi; - u32 pasi; - u32 vrc; - u32 restricted_levels; - u32 rlp; - u32 rmp; - u32 lhp; - u32 lmp; - /* smc offsets */ - u16 state_table_start; - u16 soft_regs_start; - u16 sram_end; - /* scratch structs */ - RV770_SMC_STATETABLE smc_statetable; -}; - -struct rv7xx_pl { - u32 sclk; - u32 mclk; - u16 vddc; - u16 vddci; /* eg+ only */ - u32 flags; - enum amdgpu_pcie_gen pcie_gen; /* si+ only */ -}; - -struct rv7xx_ps { - struct rv7xx_pl high; - struct rv7xx_pl medium; - struct rv7xx_pl low; - bool dc_compatible; -}; - -struct si_ps { - u16 performance_level_count; - bool dc_compatible; - struct rv7xx_pl performance_levels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; -}; - -struct ni_mc_reg_table { - u8 last; - u8 num_entries; - u16 valid_flag; - struct ni_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -struct ni_cac_data -{ - struct ni_leakage_coeffients leakage_coefficients; - u32 i_leakage; - s32 leakage_minimum_temperature; - u32 pwr_const; - u32 dc_cac_value; - u32 bif_cac_value; - u32 lkge_pwr; - u8 mc_wr_weight; - u8 mc_rd_weight; - u8 allow_ovrflw; - u8 num_win_tdp; - u8 l2num_win_tdp; - u8 lts_truncate_n; -}; - -struct evergreen_power_info { - /* must be first! */ - struct rv7xx_power_info rv7xx; - /* flags */ - bool vddci_control; - bool dynamic_ac_timing; - bool abm; - bool mcls; - bool light_sleep; - bool memory_transition; - bool pcie_performance_request; - bool pcie_performance_request_registered; - bool sclk_deep_sleep; - bool dll_default_on; - bool ls_clock_gating; - bool smu_uvd_hs; - bool uvd_enabled; - /* stored values */ - u16 acpi_vddci; - u8 mvdd_high_index; - u8 mvdd_low_index; - u32 mclk_edc_wr_enable_threshold; - struct evergreen_mc_reg_table mc_reg_table; - struct atom_voltage_table vddc_voltage_table; - struct atom_voltage_table vddci_voltage_table; - struct evergreen_arb_registers bootup_arb_registers; - struct evergreen_ulv_param ulv; - struct at ats[2]; - /* smc offsets */ - u16 mc_reg_table_start; - struct amdgpu_ps current_rps; - struct rv7xx_ps current_ps; - struct amdgpu_ps requested_rps; - struct rv7xx_ps requested_ps; -}; - -struct PP_NIslands_Dpm2PerfLevel -{ - uint8_t MaxPS; - uint8_t TgtAct; - uint8_t MaxPS_StepInc; - uint8_t MaxPS_StepDec; - uint8_t PSST; - uint8_t NearTDPDec; - uint8_t AboveSafeInc; - uint8_t BelowSafeInc; - uint8_t PSDeltaLimit; - uint8_t PSDeltaWin; - uint8_t Reserved[6]; -}; - -typedef struct PP_NIslands_Dpm2PerfLevel PP_NIslands_Dpm2PerfLevel; - -struct PP_NIslands_DPM2Parameters -{ - uint32_t TDPLimit; - uint32_t NearTDPLimit; - uint32_t SafePowerLimit; - uint32_t PowerBoostLimit; -}; -typedef struct PP_NIslands_DPM2Parameters PP_NIslands_DPM2Parameters; - -struct NISLANDS_SMC_SCLK_VALUE -{ - uint32_t vCG_SPLL_FUNC_CNTL; - uint32_t vCG_SPLL_FUNC_CNTL_2; - uint32_t vCG_SPLL_FUNC_CNTL_3; - uint32_t vCG_SPLL_FUNC_CNTL_4; - uint32_t vCG_SPLL_SPREAD_SPECTRUM; - uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t sclk_value; -}; - -typedef struct NISLANDS_SMC_SCLK_VALUE NISLANDS_SMC_SCLK_VALUE; - -struct NISLANDS_SMC_MCLK_VALUE -{ - uint32_t vMPLL_FUNC_CNTL; - uint32_t vMPLL_FUNC_CNTL_1; - uint32_t vMPLL_FUNC_CNTL_2; - uint32_t vMPLL_AD_FUNC_CNTL; - uint32_t vMPLL_AD_FUNC_CNTL_2; - uint32_t vMPLL_DQ_FUNC_CNTL; - uint32_t vMPLL_DQ_FUNC_CNTL_2; - uint32_t vMCLK_PWRMGT_CNTL; - uint32_t vDLL_CNTL; - uint32_t vMPLL_SS; - uint32_t vMPLL_SS2; - uint32_t mclk_value; -}; - -typedef struct NISLANDS_SMC_MCLK_VALUE NISLANDS_SMC_MCLK_VALUE; - -struct NISLANDS_SMC_VOLTAGE_VALUE -{ - uint16_t value; - uint8_t index; - uint8_t padding; -}; - -typedef struct NISLANDS_SMC_VOLTAGE_VALUE NISLANDS_SMC_VOLTAGE_VALUE; - -struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL -{ - uint8_t arbValue; - uint8_t ACIndex; - uint8_t displayWatermark; - uint8_t gen2PCIE; - uint8_t reserved1; - uint8_t reserved2; - uint8_t strobeMode; - uint8_t mcFlags; - uint32_t aT; - uint32_t bSP; - NISLANDS_SMC_SCLK_VALUE sclk; - NISLANDS_SMC_MCLK_VALUE mclk; - NISLANDS_SMC_VOLTAGE_VALUE vddc; - NISLANDS_SMC_VOLTAGE_VALUE mvdd; - NISLANDS_SMC_VOLTAGE_VALUE vddci; - NISLANDS_SMC_VOLTAGE_VALUE std_vddc; - uint32_t powergate_en; - uint8_t hUp; - uint8_t hDown; - uint8_t stateFlags; - uint8_t arbRefreshState; - uint32_t SQPowerThrottle; - uint32_t SQPowerThrottle_2; - uint32_t reserved[2]; - PP_NIslands_Dpm2PerfLevel dpm2; -}; - -typedef struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL NISLANDS_SMC_HW_PERFORMANCE_LEVEL; - -struct NISLANDS_SMC_SWSTATE -{ - uint8_t flags; - uint8_t levelCount; - uint8_t padding2; - uint8_t padding3; - NISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[]; -}; - -typedef struct NISLANDS_SMC_SWSTATE NISLANDS_SMC_SWSTATE; - -struct NISLANDS_SMC_VOLTAGEMASKTABLE -{ - uint8_t highMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; - uint32_t lowMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; -}; - -typedef struct NISLANDS_SMC_VOLTAGEMASKTABLE NISLANDS_SMC_VOLTAGEMASKTABLE; - -#define NISLANDS_MAX_NO_VREG_STEPS 32 - -struct NISLANDS_SMC_STATETABLE -{ - uint8_t thermalProtectType; - uint8_t systemFlags; - uint8_t maxVDDCIndexInPPTable; - uint8_t extraFlags; - uint8_t highSMIO[NISLANDS_MAX_NO_VREG_STEPS]; - uint32_t lowSMIO[NISLANDS_MAX_NO_VREG_STEPS]; - NISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; - PP_NIslands_DPM2Parameters dpm2Params; - NISLANDS_SMC_SWSTATE initialState; - NISLANDS_SMC_SWSTATE ACPIState; - NISLANDS_SMC_SWSTATE ULVState; - NISLANDS_SMC_SWSTATE driverState; - NISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; -}; - -typedef struct NISLANDS_SMC_STATETABLE NISLANDS_SMC_STATETABLE; - -struct ni_power_info { - /* must be first! */ - struct evergreen_power_info eg; - struct ni_clock_registers clock_registers; - struct ni_mc_reg_table mc_reg_table; - u32 mclk_rtt_mode_threshold; - /* flags */ - bool use_power_boost_limit; - bool support_cac_long_term_average; - bool cac_enabled; - bool cac_configuration_required; - bool driver_calculate_cac_leakage; - bool pc_enabled; - bool enable_power_containment; - bool enable_cac; - bool enable_sq_ramping; - /* smc offsets */ - u16 arb_table_start; - u16 fan_table_start; - u16 cac_table_start; - u16 spll_table_start; - /* CAC stuff */ - struct ni_cac_data cac_data; - u32 dc_cac_table[NISLANDS_DCCAC_MAX_LEVELS]; - const struct ni_cac_weights *cac_weights; - u8 lta_window_size; - u8 lts_truncate; - struct si_ps current_ps; - struct si_ps requested_ps; - /* scratch structs */ - SMC_NIslands_MCRegisters smc_mc_reg_table; - NISLANDS_SMC_STATETABLE smc_statetable; -}; - -struct si_cac_config_reg -{ - u32 offset; - u32 mask; - u32 shift; - u32 value; - enum si_cac_config_reg_type type; -}; - -struct si_powertune_data -{ - u32 cac_window; - u32 l2_lta_window_size_default; - u8 lts_truncate_default; - u8 shift_n_default; - u8 operating_temp; - struct ni_leakage_coeffients leakage_coefficients; - u32 fixed_kt; - u32 lkge_lut_v0_percent; - u8 dc_cac[NISLANDS_DCCAC_MAX_LEVELS]; - bool enable_powertune_by_default; -}; - -struct si_dyn_powertune_data -{ - u32 cac_leakage; - s32 leakage_minimum_temperature; - u32 wintime; - u32 l2_lta_window_size; - u8 lts_truncate; - u8 shift_n; - u8 dc_pwr_value; - bool disable_uvd_powertune; -}; - -struct si_dte_data -{ - u32 tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; - u32 r[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; - u32 k; - u32 t0; - u32 max_t; - u8 window_size; - u8 temp_select; - u8 dte_mode; - u8 tdep_count; - u8 t_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - u32 tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - u32 tdep_r[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - u32 t_threshold; - bool enable_dte_by_default; -}; - -struct si_clock_registers { - u32 cg_spll_func_cntl; - u32 cg_spll_func_cntl_2; - u32 cg_spll_func_cntl_3; - u32 cg_spll_func_cntl_4; - u32 cg_spll_spread_spectrum; - u32 cg_spll_spread_spectrum_2; - u32 dll_cntl; - u32 mclk_pwrmgt_cntl; - u32 mpll_ad_func_cntl; - u32 mpll_dq_func_cntl; - u32 mpll_func_cntl; - u32 mpll_func_cntl_1; - u32 mpll_func_cntl_2; - u32 mpll_ss1; - u32 mpll_ss2; -}; - -struct si_mc_reg_entry { - u32 mclk_max; - u32 mc_data[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -struct si_mc_reg_table { - u8 last; - u8 num_entries; - u16 valid_flag; - struct si_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -struct si_leakage_voltage_entry -{ - u16 voltage; - u16 leakage_index; -}; - -struct si_leakage_voltage -{ - u16 count; - struct si_leakage_voltage_entry entries[SISLANDS_MAX_LEAKAGE_COUNT]; -}; - - -struct si_ulv_param { - bool supported; - u32 cg_ulv_control; - u32 cg_ulv_parameter; - u32 volt_change_delay; - struct rv7xx_pl pl; - bool one_pcie_lane_in_ulv; -}; - -struct si_power_info { - /* must be first! */ - struct ni_power_info ni; - struct si_clock_registers clock_registers; - struct si_mc_reg_table mc_reg_table; - struct atom_voltage_table mvdd_voltage_table; - struct atom_voltage_table vddc_phase_shed_table; - struct si_leakage_voltage leakage_voltage; - u16 mvdd_bootup_value; - struct si_ulv_param ulv; - u32 max_cu; - /* pcie gen */ - enum amdgpu_pcie_gen force_pcie_gen; - enum amdgpu_pcie_gen boot_pcie_gen; - enum amdgpu_pcie_gen acpi_pcie_gen; - u32 sys_pcie_mask; - /* flags */ - bool enable_dte; - bool enable_ppm; - bool vddc_phase_shed_control; - bool pspp_notify_required; - bool sclk_deep_sleep_above_low; - bool voltage_control_svi2; - bool vddci_control_svi2; - /* smc offsets */ - u32 sram_end; - u32 state_table_start; - u32 soft_regs_start; - u32 mc_reg_table_start; - u32 arb_table_start; - u32 cac_table_start; - u32 dte_table_start; - u32 spll_table_start; - u32 papm_cfg_table_start; - u32 fan_table_start; - /* CAC stuff */ - const struct si_cac_config_reg *cac_weights; - const struct si_cac_config_reg *lcac_config; - const struct si_cac_config_reg *cac_override; - const struct si_powertune_data *powertune_data; - struct si_dyn_powertune_data dyn_powertune_data; - /* DTE stuff */ - struct si_dte_data dte_data; - /* scratch structs */ - SMC_SIslands_MCRegisters smc_mc_reg_table; - SISLANDS_SMC_STATETABLE smc_statetable; - PP_SIslands_PAPMParameters papm_parm; - /* SVI2 */ - u8 svd_gpio_id; - u8 svc_gpio_id; - /* fan control */ - bool fan_ctrl_is_in_default_mode; - u32 t_min; - u32 fan_ctrl_default_mode; - bool fan_is_controlled_by_smc; -}; - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/si_smc.c b/drivers/gpu/drm/amd/amdgpu/si_smc.c deleted file mode 100644 index 8f994ffa9cd1..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/si_smc.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright 2011 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Alex Deucher - */ - -#include - -#include "amdgpu.h" -#include "sid.h" -#include "ppsmc.h" -#include "amdgpu_ucode.h" -#include "sislands_smc.h" - -static int si_set_smc_sram_address(struct amdgpu_device *adev, - u32 smc_address, u32 limit) -{ - if (smc_address & 3) - return -EINVAL; - if ((smc_address + 3) > limit) - return -EINVAL; - - WREG32(SMC_IND_INDEX_0, smc_address); - WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); - - return 0; -} - -int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit) -{ - unsigned long flags; - int ret = 0; - u32 data, original_data, addr, extra_shift; - - if (smc_start_address & 3) - return -EINVAL; - if ((smc_start_address + byte_count) > limit) - return -EINVAL; - - addr = smc_start_address; - - spin_lock_irqsave(&adev->smc_idx_lock, flags); - while (byte_count >= 4) { - /* SMC address space is BE */ - data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; - - ret = si_set_smc_sram_address(adev, addr, limit); - if (ret) - goto done; - - WREG32(SMC_IND_DATA_0, data); - - src += 4; - byte_count -= 4; - addr += 4; - } - - /* RMW for the final bytes */ - if (byte_count > 0) { - data = 0; - - ret = si_set_smc_sram_address(adev, addr, limit); - if (ret) - goto done; - - original_data = RREG32(SMC_IND_DATA_0); - extra_shift = 8 * (4 - byte_count); - - while (byte_count > 0) { - /* SMC address space is BE */ - data = (data << 8) + *src++; - byte_count--; - } - - data <<= extra_shift; - data |= (original_data & ~((~0UL) << extra_shift)); - - ret = si_set_smc_sram_address(adev, addr, limit); - if (ret) - goto done; - - WREG32(SMC_IND_DATA_0, data); - } - -done: - spin_unlock_irqrestore(&adev->smc_idx_lock, flags); - - return ret; -} - -void amdgpu_si_start_smc(struct amdgpu_device *adev) -{ - u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); - - tmp &= ~RST_REG; - - WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); -} - -void amdgpu_si_reset_smc(struct amdgpu_device *adev) -{ - u32 tmp; - - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - RREG32(CB_CGTT_SCLK_CTRL); - - tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL) | - RST_REG; - WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); -} - -int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev) -{ - static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; - - return amdgpu_si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); -} - -void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable) -{ - u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); - - if (enable) - tmp &= ~CK_DISABLE; - else - tmp |= CK_DISABLE; - - WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); -} - -bool amdgpu_si_is_smc_running(struct amdgpu_device *adev) -{ - u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); - u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); - - if (!(rst & RST_REG) && !(clk & CK_DISABLE)) - return true; - - return false; -} - -PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, - PPSMC_Msg msg) -{ - u32 tmp; - int i; - - if (!amdgpu_si_is_smc_running(adev)) - return PPSMC_Result_Failed; - - WREG32(SMC_MESSAGE_0, msg); - - for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32(SMC_RESP_0); - if (tmp != 0) - break; - udelay(1); - } - - return (PPSMC_Result)RREG32(SMC_RESP_0); -} - -PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev) -{ - u32 tmp; - int i; - - if (!amdgpu_si_is_smc_running(adev)) - return PPSMC_Result_OK; - - for (i = 0; i < adev->usec_timeout; i++) { - tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); - if ((tmp & CKEN) == 0) - break; - udelay(1); - } - - return PPSMC_Result_OK; -} - -int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) -{ - const struct smc_firmware_header_v1_0 *hdr; - unsigned long flags; - u32 ucode_start_address; - u32 ucode_size; - const u8 *src; - u32 data; - - if (!adev->pm.fw) - return -EINVAL; - - hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data; - - amdgpu_ucode_print_smc_hdr(&hdr->header); - - adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); - ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); - ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); - src = (const u8 *) - (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); - if (ucode_size & 3) - return -EINVAL; - - spin_lock_irqsave(&adev->smc_idx_lock, flags); - WREG32(SMC_IND_INDEX_0, ucode_start_address); - WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); - while (ucode_size >= 4) { - /* SMC address space is BE */ - data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; - - WREG32(SMC_IND_DATA_0, data); - - src += 4; - ucode_size -= 4; - } - WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); - spin_unlock_irqrestore(&adev->smc_idx_lock, flags); - - return 0; -} - -int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&adev->smc_idx_lock, flags); - ret = si_set_smc_sram_address(adev, smc_address, limit); - if (ret == 0) - *value = RREG32(SMC_IND_DATA_0); - spin_unlock_irqrestore(&adev->smc_idx_lock, flags); - - return ret; -} - -int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 value, u32 limit) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&adev->smc_idx_lock, flags); - ret = si_set_smc_sram_address(adev, smc_address, limit); - if (ret == 0) - WREG32(SMC_IND_DATA_0, value); - spin_unlock_irqrestore(&adev->smc_idx_lock, flags); - - return ret; -} diff --git a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h b/drivers/gpu/drm/amd/amdgpu/sislands_smc.h deleted file mode 100644 index d2930eceaf3c..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/sislands_smc.h +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright 2013 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 PP_SISLANDS_SMC_H -#define PP_SISLANDS_SMC_H - -#include "ppsmc.h" - -#pragma pack(push, 1) - -#define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 - -struct PP_SIslands_Dpm2PerfLevel -{ - uint8_t MaxPS; - uint8_t TgtAct; - uint8_t MaxPS_StepInc; - uint8_t MaxPS_StepDec; - uint8_t PSSamplingTime; - uint8_t NearTDPDec; - uint8_t AboveSafeInc; - uint8_t BelowSafeInc; - uint8_t PSDeltaLimit; - uint8_t PSDeltaWin; - uint16_t PwrEfficiencyRatio; - uint8_t Reserved[4]; -}; - -typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel; - -struct PP_SIslands_DPM2Status -{ - uint32_t dpm2Flags; - uint8_t CurrPSkip; - uint8_t CurrPSkipPowerShift; - uint8_t CurrPSkipTDP; - uint8_t CurrPSkipOCP; - uint8_t MaxSPLLIndex; - uint8_t MinSPLLIndex; - uint8_t CurrSPLLIndex; - uint8_t InfSweepMode; - uint8_t InfSweepDir; - uint8_t TDPexceeded; - uint8_t reserved; - uint8_t SwitchDownThreshold; - uint32_t SwitchDownCounter; - uint32_t SysScalingFactor; -}; - -typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status; - -struct PP_SIslands_DPM2Parameters -{ - uint32_t TDPLimit; - uint32_t NearTDPLimit; - uint32_t SafePowerLimit; - uint32_t PowerBoostLimit; - uint32_t MinLimitDelta; -}; -typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters; - -struct PP_SIslands_PAPMStatus -{ - uint32_t EstimatedDGPU_T; - uint32_t EstimatedDGPU_P; - uint32_t EstimatedAPU_T; - uint32_t EstimatedAPU_P; - uint8_t dGPU_T_Limit_Exceeded; - uint8_t reserved[3]; -}; -typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus; - -struct PP_SIslands_PAPMParameters -{ - uint32_t NearTDPLimitTherm; - uint32_t NearTDPLimitPAPM; - uint32_t PlatformPowerLimit; - uint32_t dGPU_T_Limit; - uint32_t dGPU_T_Warning; - uint32_t dGPU_T_Hysteresis; -}; -typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters; - -struct SISLANDS_SMC_SCLK_VALUE -{ - uint32_t vCG_SPLL_FUNC_CNTL; - uint32_t vCG_SPLL_FUNC_CNTL_2; - uint32_t vCG_SPLL_FUNC_CNTL_3; - uint32_t vCG_SPLL_FUNC_CNTL_4; - uint32_t vCG_SPLL_SPREAD_SPECTRUM; - uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t sclk_value; -}; - -typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE; - -struct SISLANDS_SMC_MCLK_VALUE -{ - uint32_t vMPLL_FUNC_CNTL; - uint32_t vMPLL_FUNC_CNTL_1; - uint32_t vMPLL_FUNC_CNTL_2; - uint32_t vMPLL_AD_FUNC_CNTL; - uint32_t vMPLL_DQ_FUNC_CNTL; - uint32_t vMCLK_PWRMGT_CNTL; - uint32_t vDLL_CNTL; - uint32_t vMPLL_SS; - uint32_t vMPLL_SS2; - uint32_t mclk_value; -}; - -typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE; - -struct SISLANDS_SMC_VOLTAGE_VALUE -{ - uint16_t value; - uint8_t index; - uint8_t phase_settings; -}; - -typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE; - -struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL -{ - uint8_t ACIndex; - uint8_t displayWatermark; - uint8_t gen2PCIE; - uint8_t UVDWatermark; - uint8_t VCEWatermark; - uint8_t strobeMode; - uint8_t mcFlags; - uint8_t padding; - uint32_t aT; - uint32_t bSP; - SISLANDS_SMC_SCLK_VALUE sclk; - SISLANDS_SMC_MCLK_VALUE mclk; - SISLANDS_SMC_VOLTAGE_VALUE vddc; - SISLANDS_SMC_VOLTAGE_VALUE mvdd; - SISLANDS_SMC_VOLTAGE_VALUE vddci; - SISLANDS_SMC_VOLTAGE_VALUE std_vddc; - uint8_t hysteresisUp; - uint8_t hysteresisDown; - uint8_t stateFlags; - uint8_t arbRefreshState; - uint32_t SQPowerThrottle; - uint32_t SQPowerThrottle_2; - uint32_t MaxPoweredUpCU; - SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc; - SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc; - uint32_t reserved[2]; - PP_SIslands_Dpm2PerfLevel dpm2; -}; - -#define SISLANDS_SMC_STROBE_RATIO 0x0F -#define SISLANDS_SMC_STROBE_ENABLE 0x10 - -#define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01 -#define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02 -#define SISLANDS_SMC_MC_RTT_ENABLE 0x04 -#define SISLANDS_SMC_MC_STUTTER_EN 0x08 -#define SISLANDS_SMC_MC_PG_EN 0x10 - -typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL; - -struct SISLANDS_SMC_SWSTATE -{ - uint8_t flags; - uint8_t levelCount; - uint8_t padding2; - uint8_t padding3; - SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1]; -}; - -typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE; - -#define SISLANDS_SMC_VOLTAGEMASK_VDDC 0 -#define SISLANDS_SMC_VOLTAGEMASK_MVDD 1 -#define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2 -#define SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING 3 -#define SISLANDS_SMC_VOLTAGEMASK_MAX 4 - -struct SISLANDS_SMC_VOLTAGEMASKTABLE -{ - uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX]; -}; - -typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE; - -#define SISLANDS_MAX_NO_VREG_STEPS 32 - -struct SISLANDS_SMC_STATETABLE -{ - uint8_t thermalProtectType; - uint8_t systemFlags; - uint8_t maxVDDCIndexInPPTable; - uint8_t extraFlags; - uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS]; - SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; - SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable; - PP_SIslands_DPM2Parameters dpm2Params; - SISLANDS_SMC_SWSTATE initialState; - SISLANDS_SMC_SWSTATE ACPIState; - SISLANDS_SMC_SWSTATE ULVState; - SISLANDS_SMC_SWSTATE driverState; - SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; -}; - -typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE; - -#define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0 -#define SI_SMC_SOFT_REGISTER_delay_vreg 0xC -#define SI_SMC_SOFT_REGISTER_delay_acpi 0x28 -#define SI_SMC_SOFT_REGISTER_seq_index 0x5C -#define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60 -#define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70 -#define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78 -#define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88 -#define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C -#define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98 -#define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8 -#define SI_SMC_SOFT_REGISTER_crtc_index 0xC4 -#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8 -#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC -#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4 -#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC -#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100 -#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118 -#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c -#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 - -struct PP_SIslands_FanTable -{ - uint8_t fdo_mode; - uint8_t padding; - int16_t temp_min; - int16_t temp_med; - int16_t temp_max; - int16_t slope1; - int16_t slope2; - int16_t fdo_min; - int16_t hys_up; - int16_t hys_down; - int16_t hys_slope; - int16_t temp_resp_lim; - int16_t temp_curr; - int16_t slope_curr; - int16_t pwm_curr; - uint32_t refresh_period; - int16_t fdo_max; - uint8_t temp_src; - int8_t padding2; -}; - -typedef struct PP_SIslands_FanTable PP_SIslands_FanTable; - -#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 -#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 - -#define SMC_SISLANDS_SCALE_I 7 -#define SMC_SISLANDS_SCALE_R 12 - -struct PP_SIslands_CacConfig -{ - uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES]; - uint32_t lkge_lut_V0; - uint32_t lkge_lut_Vstep; - uint32_t WinTime; - uint32_t R_LL; - uint32_t calculation_repeats; - uint32_t l2numWin_TDP; - uint32_t dc_cac; - uint8_t lts_truncate_n; - uint8_t SHIFT_N; - uint8_t log2_PG_LKG_SCALE; - uint8_t cac_temp; - uint32_t lkge_lut_T0; - uint32_t lkge_lut_Tstep; -}; - -typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig; - -#define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16 -#define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 - -struct SMC_SIslands_MCRegisterAddress -{ - uint16_t s0; - uint16_t s1; -}; - -typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress; - -struct SMC_SIslands_MCRegisterSet -{ - uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; -}; - -typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet; - -struct SMC_SIslands_MCRegisters -{ - uint8_t last; - uint8_t reserved[3]; - SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; - SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; -}; - -typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters; - -struct SMC_SIslands_MCArbDramTimingRegisterSet -{ - uint32_t mc_arb_dram_timing; - uint32_t mc_arb_dram_timing2; - uint8_t mc_arb_rfsh_rate; - uint8_t mc_arb_burst_time; - uint8_t padding[2]; -}; - -typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet; - -struct SMC_SIslands_MCArbDramTimingRegisters -{ - uint8_t arb_current; - uint8_t reserved[3]; - SMC_SIslands_MCArbDramTimingRegisterSet data[16]; -}; - -typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters; - -struct SMC_SISLANDS_SPLL_DIV_TABLE -{ - uint32_t freq[256]; - uint32_t ss[256]; -}; - -#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff -#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0 -#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000 -#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25 -#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff -#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0 -#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000 -#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20 - -typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE; - -#define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5 - -#define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16 - -struct Smc_SIslands_DTE_Configuration -{ - uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; - uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; - uint32_t K; - uint32_t T0; - uint32_t MaxT; - uint8_t WindowSize; - uint8_t Tdep_count; - uint8_t temp_select; - uint8_t DTE_mode; - uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; - uint32_t Tthreshold; -}; - -typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; - -#define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1 - -#define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000 - -#define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0 -#define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4 -#define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC -#define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10 -#define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14 -#define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18 -#define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24 -#define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30 -#define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38 -#define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40 -#define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48 - -#pragma pack(pop) - -int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, - u32 smc_start_address, - const u8 *src, u32 byte_count, u32 limit); -void amdgpu_si_start_smc(struct amdgpu_device *adev); -void amdgpu_si_reset_smc(struct amdgpu_device *adev); -int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev); -void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable); -bool amdgpu_si_is_smc_running(struct amdgpu_device *adev); -PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); -PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev); -int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); -int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 *value, u32 limit); -int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, - u32 value, u32 limit); - -#endif - diff --git a/drivers/gpu/drm/amd/pm/Makefile b/drivers/gpu/drm/amd/pm/Makefile new file mode 100644 index 000000000000..f01e86030cd1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/Makefile @@ -0,0 +1,46 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +subdir-ccflags-y += \ + -I$(FULL_AMD_PATH)/pm/inc/ \ + -I$(FULL_AMD_PATH)/include/asic_reg \ + -I$(FULL_AMD_PATH)/include \ + -I$(FULL_AMD_PATH)/pm/swsmu \ + -I$(FULL_AMD_PATH)/pm/swsmu/smu11 \ + -I$(FULL_AMD_PATH)/pm/swsmu/smu12 \ + -I$(FULL_AMD_PATH)/pm/powerplay \ + -I$(FULL_AMD_PATH)/pm/powerplay/smumgr\ + -I$(FULL_AMD_PATH)/pm/powerplay/hwmgr + +AMD_PM_PATH = ../pm + +PM_LIBS = swsmu powerplay + +AMD_PM = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/,$(PM_LIBS))) + +include $(AMD_PM) + +PM_MGR = amdgpu_dpm.o amdgpu_pm.o + +AMD_PM_POWER = $(addprefix $(AMD_PM_PATH)/,$(PM_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PM_POWER) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c new file mode 100644 index 000000000000..e480b54f6545 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -0,0 +1,1689 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include "amdgpu.h" +#include "amdgpu_atombios.h" +#include "amdgpu_i2c.h" +#include "amdgpu_dpm.h" +#include "atom.h" +#include "amd_pcie.h" +#include "amdgpu_display.h" +#include "hwmgr.h" +#include + +#define WIDTH_4K 3840 + +void amdgpu_dpm_print_class_info(u32 class, u32 class2) +{ + const char *s; + + switch (class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) { + case ATOM_PPLIB_CLASSIFICATION_UI_NONE: + default: + s = "none"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BATTERY: + s = "battery"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_BALANCED: + s = "balanced"; + break; + case ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE: + s = "performance"; + break; + } + printk("\tui class: %s\n", s); + printk("\tinternal class:"); + if (((class & ~ATOM_PPLIB_CLASSIFICATION_UI_MASK) == 0) && + (class2 == 0)) + pr_cont(" none"); + else { + if (class & ATOM_PPLIB_CLASSIFICATION_BOOT) + pr_cont(" boot"); + if (class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + pr_cont(" thermal"); + if (class & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + pr_cont(" limited_pwr"); + if (class & ATOM_PPLIB_CLASSIFICATION_REST) + pr_cont(" rest"); + if (class & ATOM_PPLIB_CLASSIFICATION_FORCED) + pr_cont(" forced"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + pr_cont(" 3d_perf"); + if (class & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) + pr_cont(" ovrdrv"); + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + pr_cont(" uvd"); + if (class & ATOM_PPLIB_CLASSIFICATION_3DLOW) + pr_cont(" 3d_low"); + if (class & ATOM_PPLIB_CLASSIFICATION_ACPI) + pr_cont(" acpi"); + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + pr_cont(" uvd_hd2"); + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + pr_cont(" uvd_hd"); + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + pr_cont(" uvd_sd"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + pr_cont(" limited_pwr2"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + pr_cont(" ulv"); + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + pr_cont(" uvd_mvc"); + } + pr_cont("\n"); +} + +void amdgpu_dpm_print_cap_info(u32 caps) +{ + printk("\tcaps:"); + if (caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) + pr_cont(" single_disp"); + if (caps & ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK) + pr_cont(" video"); + if (caps & ATOM_PPLIB_DISALLOW_ON_DC) + pr_cont(" no_dc"); + pr_cont("\n"); +} + +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + printk("\tstatus:"); + if (rps == adev->pm.dpm.current_ps) + pr_cont(" c"); + if (rps == adev->pm.dpm.requested_ps) + pr_cont(" r"); + if (rps == adev->pm.dpm.boot_ps) + pr_cont(" b"); + pr_cont("\n"); +} + +void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) +{ + struct drm_device *ddev = adev->ddev; + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + + adev->pm.dpm.new_active_crtcs = 0; + adev->pm.dpm.new_active_crtc_count = 0; + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (amdgpu_crtc->enabled) { + adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); + adev->pm.dpm.new_active_crtc_count++; + } + } + } +} + + +u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + u32 vblank_in_pixels; + u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { + vblank_in_pixels = + amdgpu_crtc->hw_mode.crtc_htotal * + (amdgpu_crtc->hw_mode.crtc_vblank_end - + amdgpu_crtc->hw_mode.crtc_vdisplay + + (amdgpu_crtc->v_border * 2)); + + vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock; + break; + } + } + } + + return vblank_time_us; +} + +u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) +{ + struct drm_device *dev = adev->ddev; + struct drm_crtc *crtc; + struct amdgpu_crtc *amdgpu_crtc; + u32 vrefresh = 0; + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { + vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + break; + } + } + } + + return vrefresh; +} + +bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor) +{ + switch (sensor) { + case THERMAL_TYPE_RV6XX: + case THERMAL_TYPE_RV770: + case THERMAL_TYPE_EVERGREEN: + case THERMAL_TYPE_SUMO: + case THERMAL_TYPE_NI: + case THERMAL_TYPE_SI: + case THERMAL_TYPE_CI: + case THERMAL_TYPE_KV: + return true; + case THERMAL_TYPE_ADT7473_WITH_INTERNAL: + case THERMAL_TYPE_EMC2103_WITH_INTERNAL: + return false; /* need special handling */ + case THERMAL_TYPE_NONE: + case THERMAL_TYPE_EXTERNAL: + case THERMAL_TYPE_EXTERNAL_GPIO: + default: + return false; + } +} + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; +}; + +union fan_info { + struct _ATOM_PPLIB_FANTABLE fan; + struct _ATOM_PPLIB_FANTABLE2 fan2; + struct _ATOM_PPLIB_FANTABLE3 fan3; +}; + +static int amdgpu_parse_clk_voltage_dep_table(struct amdgpu_clock_voltage_dependency_table *amdgpu_table, + ATOM_PPLIB_Clock_Voltage_Dependency_Table *atom_table) +{ + u32 size = atom_table->ucNumEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + int i; + ATOM_PPLIB_Clock_Voltage_Dependency_Record *entry; + + amdgpu_table->entries = kzalloc(size, GFP_KERNEL); + if (!amdgpu_table->entries) + return -ENOMEM; + + entry = &atom_table->entries[0]; + for (i = 0; i < atom_table->ucNumEntries; i++) { + amdgpu_table->entries[i].clk = le16_to_cpu(entry->usClockLow) | + (entry->ucClockHigh << 16); + amdgpu_table->entries[i].v = le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_Clock_Voltage_Dependency_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_Clock_Voltage_Dependency_Record)); + } + amdgpu_table->count = atom_table->ucNumEntries; + + return 0; +} + +int amdgpu_get_platform_caps(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + adev->pm.dpm.platform_caps = le32_to_cpu(power_info->pplib.ulPlatformCaps); + adev->pm.dpm.backbias_response_time = le16_to_cpu(power_info->pplib.usBackbiasTime); + adev->pm.dpm.voltage_response_time = le16_to_cpu(power_info->pplib.usVoltageTime); + + return 0; +} + +/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 + +int amdgpu_parse_extended_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + union power_info *power_info; + union fan_info *fan_info; + ATOM_PPLIB_Clock_Voltage_Dependency_Table *dep_table; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + int ret, i; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + /* fan table */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { + if (power_info->pplib3.usFanTableOffset) { + fan_info = (union fan_info *)(mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib3.usFanTableOffset)); + adev->pm.dpm.fan.t_hyst = fan_info->fan.ucTHyst; + adev->pm.dpm.fan.t_min = le16_to_cpu(fan_info->fan.usTMin); + adev->pm.dpm.fan.t_med = le16_to_cpu(fan_info->fan.usTMed); + adev->pm.dpm.fan.t_high = le16_to_cpu(fan_info->fan.usTHigh); + adev->pm.dpm.fan.pwm_min = le16_to_cpu(fan_info->fan.usPWMMin); + adev->pm.dpm.fan.pwm_med = le16_to_cpu(fan_info->fan.usPWMMed); + adev->pm.dpm.fan.pwm_high = le16_to_cpu(fan_info->fan.usPWMHigh); + if (fan_info->fan.ucFanTableFormat >= 2) + adev->pm.dpm.fan.t_max = le16_to_cpu(fan_info->fan2.usTMax); + else + adev->pm.dpm.fan.t_max = 10900; + adev->pm.dpm.fan.cycle_delay = 100000; + if (fan_info->fan.ucFanTableFormat >= 3) { + adev->pm.dpm.fan.control_mode = fan_info->fan3.ucFanControlMode; + adev->pm.dpm.fan.default_max_fan_pwm = + le16_to_cpu(fan_info->fan3.usFanPWMMax); + adev->pm.dpm.fan.default_fan_output_sensitivity = 4836; + adev->pm.dpm.fan.fan_output_sensitivity = + le16_to_cpu(fan_info->fan3.usFanOutputSensitivity); + } + adev->pm.dpm.fan.ucode_fan_control = true; + } + } + + /* clock dependancy tables, shedding tables */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE4)) { + if (power_info->pplib4.usVddcDependencyOnSCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcDependencyOnSCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usVddciDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddciDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usVddcDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usMvddDependencyOnMCLKOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usMvddDependencyOnMCLKOffset)); + ret = amdgpu_parse_clk_voltage_dep_table(&adev->pm.dpm.dyn_state.mvdd_dependency_on_mclk, + dep_table); + if (ret) { + amdgpu_free_extended_power_table(adev); + return ret; + } + } + if (power_info->pplib4.usMaxClockVoltageOnDCOffset) { + ATOM_PPLIB_Clock_Voltage_Limit_Table *clk_v = + (ATOM_PPLIB_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usMaxClockVoltageOnDCOffset)); + if (clk_v->ucNumEntries) { + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk = + le16_to_cpu(clk_v->entries[0].usSclkLow) | + (clk_v->entries[0].ucSclkHigh << 16); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk = + le16_to_cpu(clk_v->entries[0].usMclkLow) | + (clk_v->entries[0].ucMclkHigh << 16); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc = + le16_to_cpu(clk_v->entries[0].usVddc); + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddci = + le16_to_cpu(clk_v->entries[0].usVddci); + } + } + if (power_info->pplib4.usVddcPhaseShedLimitsTableOffset) { + ATOM_PPLIB_PhaseSheddingLimits_Table *psl = + (ATOM_PPLIB_PhaseSheddingLimits_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib4.usVddcPhaseShedLimitsTableOffset)); + ATOM_PPLIB_PhaseSheddingLimits_Record *entry; + + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries = + kcalloc(psl->ucNumEntries, + sizeof(struct amdgpu_phase_shedding_limits_entry), + GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + + entry = &psl->entries[0]; + for (i = 0; i < psl->ucNumEntries; i++) { + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].sclk = + le16_to_cpu(entry->usSclkLow) | (entry->ucSclkHigh << 16); + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].mclk = + le16_to_cpu(entry->usMclkLow) | (entry->ucMclkHigh << 16); + adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries[i].voltage = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_PhaseSheddingLimits_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_PhaseSheddingLimits_Record)); + } + adev->pm.dpm.dyn_state.phase_shedding_limits_table.count = + psl->ucNumEntries; + } + } + + /* cac data */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE5)) { + adev->pm.dpm.tdp_limit = le32_to_cpu(power_info->pplib5.ulTDPLimit); + adev->pm.dpm.near_tdp_limit = le32_to_cpu(power_info->pplib5.ulNearTDPLimit); + adev->pm.dpm.near_tdp_limit_adjusted = adev->pm.dpm.near_tdp_limit; + adev->pm.dpm.tdp_od_limit = le16_to_cpu(power_info->pplib5.usTDPODLimit); + if (adev->pm.dpm.tdp_od_limit) + adev->pm.dpm.power_control = true; + else + adev->pm.dpm.power_control = false; + adev->pm.dpm.tdp_adjustment = 0; + adev->pm.dpm.sq_ramping_threshold = le32_to_cpu(power_info->pplib5.ulSQRampingThreshold); + adev->pm.dpm.cac_leakage = le32_to_cpu(power_info->pplib5.ulCACLeakage); + adev->pm.dpm.load_line_slope = le16_to_cpu(power_info->pplib5.usLoadLineSlope); + if (power_info->pplib5.usCACLeakageTableOffset) { + ATOM_PPLIB_CAC_Leakage_Table *cac_table = + (ATOM_PPLIB_CAC_Leakage_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib5.usCACLeakageTableOffset)); + ATOM_PPLIB_CAC_Leakage_Record *entry; + u32 size = cac_table->ucNumEntries * sizeof(struct amdgpu_cac_leakage_table); + adev->pm.dpm.dyn_state.cac_leakage_table.entries = kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.cac_leakage_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + entry = &cac_table->entries[0]; + for (i = 0; i < cac_table->ucNumEntries; i++) { + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_EVV) { + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc1 = + le16_to_cpu(entry->usVddc1); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc2 = + le16_to_cpu(entry->usVddc2); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc3 = + le16_to_cpu(entry->usVddc3); + } else { + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].vddc = + le16_to_cpu(entry->usVddc); + adev->pm.dpm.dyn_state.cac_leakage_table.entries[i].leakage = + le32_to_cpu(entry->ulLeakageValue); + } + entry = (ATOM_PPLIB_CAC_Leakage_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_CAC_Leakage_Record)); + } + adev->pm.dpm.dyn_state.cac_leakage_table.count = cac_table->ucNumEntries; + } + } + + /* ext tables */ + if (le16_to_cpu(power_info->pplib.usTableSize) >= + sizeof(struct _ATOM_PPLIB_POWERPLAYTABLE3)) { + ATOM_PPLIB_EXTENDEDHEADER *ext_hdr = (ATOM_PPLIB_EXTENDEDHEADER *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib3.usExtendendedHeaderOffset)); + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) && + ext_hdr->usVCETableOffset) { + VCEClockInfoArray *array = (VCEClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1); + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + + 1 + array->ucNumEntries * sizeof(VCEClockInfo)); + ATOM_PPLIB_VCE_State_Table *states = + (ATOM_PPLIB_VCE_State_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usVCETableOffset) + 1 + + 1 + (array->ucNumEntries * sizeof (VCEClockInfo)) + + 1 + (limits->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record))); + ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *entry; + ATOM_PPLIB_VCE_State_Record *state_entry; + VCEClockInfo *vce_clk; + u32 size = limits->numEntries * + sizeof(struct amdgpu_vce_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + state_entry = &states->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + vce_clk = (VCEClockInfo *) + ((u8 *)&array->entries[0] + + (entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].evclk = + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].ecclk = + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); + adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record)); + } + adev->pm.dpm.num_of_vce_states = + states->numEntries > AMD_MAX_VCE_LEVELS ? + AMD_MAX_VCE_LEVELS : states->numEntries; + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { + vce_clk = (VCEClockInfo *) + ((u8 *)&array->entries[0] + + (state_entry->ucVCEClockInfoIndex * sizeof(VCEClockInfo))); + adev->pm.dpm.vce_states[i].evclk = + le16_to_cpu(vce_clk->usEVClkLow) | (vce_clk->ucEVClkHigh << 16); + adev->pm.dpm.vce_states[i].ecclk = + le16_to_cpu(vce_clk->usECClkLow) | (vce_clk->ucECClkHigh << 16); + adev->pm.dpm.vce_states[i].clk_idx = + state_entry->ucClockInfoIndex & 0x3f; + adev->pm.dpm.vce_states[i].pstate = + (state_entry->ucClockInfoIndex & 0xc0) >> 6; + state_entry = (ATOM_PPLIB_VCE_State_Record *) + ((u8 *)state_entry + sizeof(ATOM_PPLIB_VCE_State_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) && + ext_hdr->usUVDTableOffset) { + UVDClockInfoArray *array = (UVDClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1); + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *limits = + (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usUVDTableOffset) + 1 + + 1 + (array->ucNumEntries * sizeof (UVDClockInfo))); + ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_uvd_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + UVDClockInfo *uvd_clk = (UVDClockInfo *) + ((u8 *)&array->entries[0] + + (entry->ucUVDClockInfoIndex * sizeof(UVDClockInfo))); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].vclk = + le16_to_cpu(uvd_clk->usVClkLow) | (uvd_clk->ucVClkHigh << 16); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].dclk = + le16_to_cpu(uvd_clk->usDClkLow) | (uvd_clk->ucDClkHigh << 16); + adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_UVD_Clock_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) && + ext_hdr->usSAMUTableOffset) { + ATOM_PPLIB_SAMClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usSAMUTableOffset) + 1); + ATOM_PPLIB_SAMClk_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(entry->usSAMClockLow) | (entry->ucSAMClockHigh << 16); + adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_SAMClk_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_SAMClk_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) && + ext_hdr->usPPMTableOffset) { + ATOM_PPLIB_PPM_Table *ppm = (ATOM_PPLIB_PPM_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPPMTableOffset)); + adev->pm.dpm.dyn_state.ppm_table = + kzalloc(sizeof(struct amdgpu_ppm_table), GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.ppm_table) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.ppm_table->ppm_design = ppm->ucPpmDesign; + adev->pm.dpm.dyn_state.ppm_table->cpu_core_number = + le16_to_cpu(ppm->usCpuCoreNumber); + adev->pm.dpm.dyn_state.ppm_table->platform_tdp = + le32_to_cpu(ppm->ulPlatformTDP); + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdp = + le32_to_cpu(ppm->ulSmallACPlatformTDP); + adev->pm.dpm.dyn_state.ppm_table->platform_tdc = + le32_to_cpu(ppm->ulPlatformTDC); + adev->pm.dpm.dyn_state.ppm_table->small_ac_platform_tdc = + le32_to_cpu(ppm->ulSmallACPlatformTDC); + adev->pm.dpm.dyn_state.ppm_table->apu_tdp = + le32_to_cpu(ppm->ulApuTDP); + adev->pm.dpm.dyn_state.ppm_table->dgpu_tdp = + le32_to_cpu(ppm->ulDGpuTDP); + adev->pm.dpm.dyn_state.ppm_table->dgpu_ulv_power = + le32_to_cpu(ppm->ulDGpuUlvPower); + adev->pm.dpm.dyn_state.ppm_table->tj_max = + le32_to_cpu(ppm->ulTjmax); + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) && + ext_hdr->usACPTableOffset) { + ATOM_PPLIB_ACPClk_Voltage_Limit_Table *limits = + (ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usACPTableOffset) + 1); + ATOM_PPLIB_ACPClk_Voltage_Limit_Record *entry; + u32 size = limits->numEntries * + sizeof(struct amdgpu_clock_voltage_dependency_entry); + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries = + kzalloc(size, GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.count = + limits->numEntries; + entry = &limits->entries[0]; + for (i = 0; i < limits->numEntries; i++) { + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].clk = + le16_to_cpu(entry->usACPClockLow) | (entry->ucACPClockHigh << 16); + adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table.entries[i].v = + le16_to_cpu(entry->usVoltage); + entry = (ATOM_PPLIB_ACPClk_Voltage_Limit_Record *) + ((u8 *)entry + sizeof(ATOM_PPLIB_ACPClk_Voltage_Limit_Record)); + } + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) && + ext_hdr->usPowerTuneTableOffset) { + u8 rev = *(u8 *)(mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + ATOM_PowerTune_Table *pt; + adev->pm.dpm.dyn_state.cac_tdp_table = + kzalloc(sizeof(struct amdgpu_cac_tdp_table), GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.cac_tdp_table) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + if (rev > 0) { + ATOM_PPLIB_POWERTUNE_Table_V1 *ppt = (ATOM_PPLIB_POWERTUNE_Table_V1 *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = + ppt->usMaximumPowerDeliveryLimit; + pt = &ppt->power_tune_table; + } else { + ATOM_PPLIB_POWERTUNE_Table *ppt = (ATOM_PPLIB_POWERTUNE_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usPowerTuneTableOffset)); + adev->pm.dpm.dyn_state.cac_tdp_table->maximum_power_delivery_limit = 255; + pt = &ppt->power_tune_table; + } + adev->pm.dpm.dyn_state.cac_tdp_table->tdp = le16_to_cpu(pt->usTDP); + adev->pm.dpm.dyn_state.cac_tdp_table->configurable_tdp = + le16_to_cpu(pt->usConfigurableTDP); + adev->pm.dpm.dyn_state.cac_tdp_table->tdc = le16_to_cpu(pt->usTDC); + adev->pm.dpm.dyn_state.cac_tdp_table->battery_power_limit = + le16_to_cpu(pt->usBatteryPowerLimit); + adev->pm.dpm.dyn_state.cac_tdp_table->small_power_limit = + le16_to_cpu(pt->usSmallPowerLimit); + adev->pm.dpm.dyn_state.cac_tdp_table->low_cac_leakage = + le16_to_cpu(pt->usLowCACLeakage); + adev->pm.dpm.dyn_state.cac_tdp_table->high_cac_leakage = + le16_to_cpu(pt->usHighCACLeakage); + } + if ((le16_to_cpu(ext_hdr->usSize) >= SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) && + ext_hdr->usSclkVddgfxTableOffset) { + dep_table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(ext_hdr->usSclkVddgfxTableOffset)); + ret = amdgpu_parse_clk_voltage_dep_table( + &adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk, + dep_table); + if (ret) { + kfree(adev->pm.dpm.dyn_state.vddgfx_dependency_on_sclk.entries); + return ret; + } + } + } + + return 0; +} + +void amdgpu_free_extended_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_dpm_dynamic_state *dyn_state = &adev->pm.dpm.dyn_state; + + kfree(dyn_state->vddc_dependency_on_sclk.entries); + kfree(dyn_state->vddci_dependency_on_mclk.entries); + kfree(dyn_state->vddc_dependency_on_mclk.entries); + kfree(dyn_state->mvdd_dependency_on_mclk.entries); + kfree(dyn_state->cac_leakage_table.entries); + kfree(dyn_state->phase_shedding_limits_table.entries); + kfree(dyn_state->ppm_table); + kfree(dyn_state->cac_tdp_table); + kfree(dyn_state->vce_clock_voltage_dependency_table.entries); + kfree(dyn_state->uvd_clock_voltage_dependency_table.entries); + kfree(dyn_state->samu_clock_voltage_dependency_table.entries); + kfree(dyn_state->acp_clock_voltage_dependency_table.entries); + kfree(dyn_state->vddgfx_dependency_on_sclk.entries); +} + +static const char *pp_lib_thermal_controller_names[] = { + "NONE", + "lm63", + "adm1032", + "adm1030", + "max6649", + "lm64", + "f75375", + "RV6xx", + "RV770", + "adt7473", + "NONE", + "External GPIO", + "Evergreen", + "emc2103", + "Sumo", + "Northern Islands", + "Southern Islands", + "lm96163", + "Sea Islands", + "Kaveri/Kabini", +}; + +void amdgpu_add_thermal_controller(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + ATOM_PPLIB_POWERPLAYTABLE *power_table; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + ATOM_PPLIB_THERMALCONTROLLER *controller; + struct amdgpu_i2c_bus_rec i2c_bus; + u16 data_offset; + u8 frev, crev; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return; + power_table = (ATOM_PPLIB_POWERPLAYTABLE *) + (mode_info->atom_context->bios + data_offset); + controller = &power_table->sThermalController; + + /* add the i2c bus for thermal/fan chip */ + if (controller->ucType > 0) { + if (controller->ucFanParameters & ATOM_PP_FANPARAMETERS_NOFAN) + adev->pm.no_fan = true; + adev->pm.fan_pulses_per_revolution = + controller->ucFanParameters & ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + if (adev->pm.fan_pulses_per_revolution) { + adev->pm.fan_min_rpm = controller->ucFanMinRPM; + adev->pm.fan_max_rpm = controller->ucFanMaxRPM; + } + if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV6xx) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_RV6XX; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_RV770) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_RV770; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EVERGREEN) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EVERGREEN; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SUMO) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_SUMO; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_NISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_NI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_SISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_SI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_CISLANDS) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_CI; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_KAVERI) { + DRM_INFO("Internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_KV; + } else if (controller->ucType == ATOM_PP_THERMALCONTROLLER_EXTERNAL_GPIO) { + DRM_INFO("External GPIO thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL_GPIO; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL) { + DRM_INFO("ADT7473 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_ADT7473_WITH_INTERNAL; + } else if (controller->ucType == + ATOM_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL) { + DRM_INFO("EMC2103 with internal thermal controller %s fan control\n", + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EMC2103_WITH_INTERNAL; + } else if (controller->ucType < ARRAY_SIZE(pp_lib_thermal_controller_names)) { + DRM_INFO("Possible %s thermal controller at 0x%02x %s fan control\n", + pp_lib_thermal_controller_names[controller->ucType], + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + adev->pm.int_thermal_type = THERMAL_TYPE_EXTERNAL; + i2c_bus = amdgpu_atombios_lookup_i2c_gpio(adev, controller->ucI2cLine); + adev->pm.i2c_bus = amdgpu_i2c_lookup(adev, &i2c_bus); + if (adev->pm.i2c_bus) { + struct i2c_board_info info = { }; + const char *name = pp_lib_thermal_controller_names[controller->ucType]; + info.addr = controller->ucI2cAddress >> 1; + strlcpy(info.type, name, sizeof(info.type)); + i2c_new_client_device(&adev->pm.i2c_bus->adapter, &info); + } + } else { + DRM_INFO("Unknown thermal controller type %d at 0x%02x %s fan control\n", + controller->ucType, + controller->ucI2cAddress >> 1, + (controller->ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN) ? "without" : "with"); + } + } +} + +enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, + u32 sys_mask, + enum amdgpu_pcie_gen asic_gen, + enum amdgpu_pcie_gen default_gen) +{ + switch (asic_gen) { + case AMDGPU_PCIE_GEN1: + return AMDGPU_PCIE_GEN1; + case AMDGPU_PCIE_GEN2: + return AMDGPU_PCIE_GEN2; + case AMDGPU_PCIE_GEN3: + return AMDGPU_PCIE_GEN3; + default: + if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) && + (default_gen == AMDGPU_PCIE_GEN3)) + return AMDGPU_PCIE_GEN3; + else if ((sys_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) && + (default_gen == AMDGPU_PCIE_GEN2)) + return AMDGPU_PCIE_GEN2; + else + return AMDGPU_PCIE_GEN1; + } + return AMDGPU_PCIE_GEN1; +} + +struct amd_vce_state* +amdgpu_get_vce_clock_state(void *handle, u32 idx) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (idx < adev->pm.dpm.num_of_vce_states) + return &adev->pm.dpm.vce_states[idx]; + + return NULL; +} + +int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low) +{ + uint32_t clk_freq; + int ret = 0; + if (is_support_sw_smu(adev)) { + ret = smu_get_dpm_freq_range(&adev->smu, SMU_GFXCLK, + low ? &clk_freq : NULL, + !low ? &clk_freq : NULL); + if (ret) + return 0; + return clk_freq * 100; + + } else { + return (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (low)); + } +} + +int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low) +{ + uint32_t clk_freq; + int ret = 0; + if (is_support_sw_smu(adev)) { + ret = smu_get_dpm_freq_range(&adev->smu, SMU_UCLK, + low ? &clk_freq : NULL, + !low ? &clk_freq : NULL); + if (ret) + return 0; + return clk_freq * 100; + + } else { + return (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (low)); + } +} + +int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, uint32_t block_type, bool gate) +{ + int ret = 0; + bool swsmu = is_support_sw_smu(adev); + + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: + case AMD_IP_BLOCK_TYPE_VCE: + if (swsmu) { + ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); + } else if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->set_powergating_by_smu) { + /* + * TODO: need a better lock mechanism + * + * Here adev->pm.mutex lock protection is enforced on + * UVD and VCE cases only. Since for other cases, there + * may be already lock protection in amdgpu_pm.c. + * This is a quick fix for the deadlock issue below. + * NFO: task ocltst:2028 blocked for more than 120 seconds. + * Tainted: G OE 5.0.0-37-generic #40~18.04.1-Ubuntu + * echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. + * cltst D 0 2028 2026 0x00000000 + * all Trace: + * __schedule+0x2c0/0x870 + * schedule+0x2c/0x70 + * schedule_preempt_disabled+0xe/0x10 + * __mutex_lock.isra.9+0x26d/0x4e0 + * __mutex_lock_slowpath+0x13/0x20 + * ? __mutex_lock_slowpath+0x13/0x20 + * mutex_lock+0x2f/0x40 + * amdgpu_dpm_set_powergating_by_smu+0x64/0xe0 [amdgpu] + * gfx_v8_0_enable_gfx_static_mg_power_gating+0x3c/0x70 [amdgpu] + * gfx_v8_0_set_powergating_state+0x66/0x260 [amdgpu] + * amdgpu_device_ip_set_powergating_state+0x62/0xb0 [amdgpu] + * pp_dpm_force_performance_level+0xe7/0x100 [amdgpu] + * amdgpu_set_dpm_forced_performance_level+0x129/0x330 [amdgpu] + */ + mutex_lock(&adev->pm.mutex); + ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( + (adev)->powerplay.pp_handle, block_type, gate)); + mutex_unlock(&adev->pm.mutex); + } + break; + case AMD_IP_BLOCK_TYPE_GFX: + case AMD_IP_BLOCK_TYPE_VCN: + case AMD_IP_BLOCK_TYPE_SDMA: + if (swsmu) + ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); + else if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->set_powergating_by_smu) + ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( + (adev)->powerplay.pp_handle, block_type, gate)); + break; + case AMD_IP_BLOCK_TYPE_JPEG: + if (swsmu) + ret = smu_dpm_set_power_gate(&adev->smu, block_type, gate); + break; + case AMD_IP_BLOCK_TYPE_GMC: + case AMD_IP_BLOCK_TYPE_ACP: + if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->set_powergating_by_smu) + ret = ((adev)->powerplay.pp_funcs->set_powergating_by_smu( + (adev)->powerplay.pp_handle, block_type, gate)); + break; + default: + break; + } + + return ret; +} + +int amdgpu_dpm_baco_enter(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + int ret = 0; + + if (is_support_sw_smu(adev)) { + ret = smu_baco_enter(smu); + } else { + if (!pp_funcs || !pp_funcs->set_asic_baco_state) + return -ENOENT; + + /* enter BACO state */ + ret = pp_funcs->set_asic_baco_state(pp_handle, 1); + } + + return ret; +} + +int amdgpu_dpm_baco_exit(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + int ret = 0; + + if (is_support_sw_smu(adev)) { + ret = smu_baco_exit(smu); + } else { + if (!pp_funcs || !pp_funcs->set_asic_baco_state) + return -ENOENT; + + /* exit BACO state */ + ret = pp_funcs->set_asic_baco_state(pp_handle, 0); + } + + return ret; +} + +int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, + enum pp_mp1_state mp1_state) +{ + int ret = 0; + + if (is_support_sw_smu(adev)) { + ret = smu_set_mp1_state(&adev->smu, mp1_state); + } else if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->set_mp1_state) { + ret = adev->powerplay.pp_funcs->set_mp1_state( + adev->powerplay.pp_handle, + mp1_state); + } + + return ret; +} + +bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + bool baco_cap; + + if (is_support_sw_smu(adev)) { + return smu_baco_is_support(smu); + } else { + if (!pp_funcs || !pp_funcs->get_asic_baco_capability) + return false; + + if (pp_funcs->get_asic_baco_capability(pp_handle, &baco_cap)) + return false; + + return baco_cap ? true : false; + } +} + +int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev)) { + return smu_mode2_reset(smu); + } else { + if (!pp_funcs || !pp_funcs->asic_reset_mode_2) + return -ENOENT; + + return pp_funcs->asic_reset_mode_2(pp_handle); + } +} + +int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) +{ + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + int ret = 0; + + dev_info(adev->dev, "GPU BACO reset\n"); + + if (is_support_sw_smu(adev)) { + ret = smu_baco_enter(smu); + if (ret) + return ret; + + ret = smu_baco_exit(smu); + if (ret) + return ret; + } else { + if (!pp_funcs + || !pp_funcs->set_asic_baco_state) + return -ENOENT; + + /* enter BACO state */ + ret = pp_funcs->set_asic_baco_state(pp_handle, 1); + if (ret) + return ret; + + /* exit BACO state */ + ret = pp_funcs->set_asic_baco_state(pp_handle, 0); + if (ret) + return ret; + } + + return 0; +} + +bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev) +{ + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev)) + return smu_mode1_reset_is_support(smu); + + return false; +} + +int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev) +{ + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev)) + return smu_mode1_reset(smu); + + return -EOPNOTSUPP; +} + +int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, + enum PP_SMC_POWER_PROFILE type, + bool en) +{ + int ret = 0; + + if (is_support_sw_smu(adev)) + ret = smu_switch_power_profile(&adev->smu, type, en); + else if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->switch_power_profile) + ret = adev->powerplay.pp_funcs->switch_power_profile( + adev->powerplay.pp_handle, type, en); + + return ret; +} + +int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, + uint32_t pstate) +{ + int ret = 0; + + if (is_support_sw_smu(adev)) + ret = smu_set_xgmi_pstate(&adev->smu, pstate); + else if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->set_xgmi_pstate) + ret = adev->powerplay.pp_funcs->set_xgmi_pstate(adev->powerplay.pp_handle, + pstate); + + return ret; +} + +int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, + uint32_t cstate) +{ + int ret = 0; + const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; + void *pp_handle = adev->powerplay.pp_handle; + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev)) + ret = smu_set_df_cstate(smu, cstate); + else if (pp_funcs && + pp_funcs->set_df_cstate) + ret = pp_funcs->set_df_cstate(pp_handle, cstate); + + return ret; +} + +int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en) +{ + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev)) + return smu_allow_xgmi_power_down(smu, en); + + return 0; +} + +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + struct smu_context *smu = &adev->smu; + int ret = 0; + + if (is_support_sw_smu(adev)) + ret = smu_enable_mgpu_fan_boost(smu); + else if (pp_funcs && pp_funcs->enable_mgpu_fan_boost) + ret = pp_funcs->enable_mgpu_fan_boost(pp_handle); + + return ret; +} + +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = 0; + + if (pp_funcs && pp_funcs->set_clockgating_by_smu) + ret = pp_funcs->set_clockgating_by_smu(pp_handle, + msg_id); + + return ret; +} + +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire) +{ + void *pp_handle = adev->powerplay.pp_handle; + const struct amd_pm_funcs *pp_funcs = + adev->powerplay.pp_funcs; + int ret = -EOPNOTSUPP; + + if (pp_funcs && pp_funcs->smu_i2c_bus_access) + ret = pp_funcs->smu_i2c_bus_access(pp_handle, + acquire); + + return ret; +} + +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) +{ + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + if (power_supply_is_system_supplied() > 0) + adev->pm.ac_power = true; + else + adev->pm.ac_power = false; + if (adev->powerplay.pp_funcs && + adev->powerplay.pp_funcs->enable_bapm) + amdgpu_dpm_enable_bapm(adev, adev->pm.ac_power); + mutex_unlock(&adev->pm.mutex); + + if (is_support_sw_smu(adev)) + smu_set_ac_dc(&adev->smu); + } +} + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + + if (!data || !size) + return -EINVAL; + + if (is_support_sw_smu(adev)) + ret = smu_read_sensor(&adev->smu, sensor, data, size); + else { + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->read_sensor) + ret = adev->powerplay.pp_funcs->read_sensor((adev)->powerplay.pp_handle, + sensor, data, size); + else + ret = -EINVAL; + } + + return ret; +} + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work) +{ + struct amdgpu_device *adev = + container_of(work, struct amdgpu_device, + pm.dpm.thermal.work); + /* switch to the thermal state */ + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + int temp, size = sizeof(temp); + + if (!adev->pm.dpm_enabled) + return; + + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, + (void *)&temp, &size)) { + if (temp < adev->pm.dpm.thermal.min_temp) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } else { + if (adev->pm.dpm.thermal.high_to_low) + /* switch back the user state */ + dpm_state = adev->pm.dpm.user_state; + } + mutex_lock(&adev->pm.mutex); + if (dpm_state == POWER_STATE_TYPE_INTERNAL_THERMAL) + adev->pm.dpm.thermal_active = true; + else + adev->pm.dpm.thermal_active = false; + adev->pm.dpm.state = dpm_state; + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); +} + +static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, + enum amd_pm_state_type dpm_state) +{ + int i; + struct amdgpu_ps *ps; + u32 ui_class; + bool single_display = (adev->pm.dpm.new_active_crtc_count < 2) ? + true : false; + + /* check if the vblank period is too short to adjust the mclk */ + if (single_display && adev->powerplay.pp_funcs->vblank_too_short) { + if (amdgpu_dpm_vblank_too_short(adev)) + single_display = false; + } + + /* certain older asics have a separare 3D performance state, + * so try that first if the user selected performance + */ + if (dpm_state == POWER_STATE_TYPE_PERFORMANCE) + dpm_state = POWER_STATE_TYPE_INTERNAL_3DPERF; + /* balanced states don't exist at the moment */ + if (dpm_state == POWER_STATE_TYPE_BALANCED) + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + +restart_search: + /* Pick the best power state based on current conditions */ + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + ps = &adev->pm.dpm.ps[i]; + ui_class = ps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK; + switch (dpm_state) { + /* user states */ + case POWER_STATE_TYPE_BATTERY: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_BALANCED: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_BALANCED) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + case POWER_STATE_TYPE_PERFORMANCE: + if (ui_class == ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + if (ps->caps & ATOM_PPLIB_SINGLE_DISPLAY_ONLY) { + if (single_display) + return ps; + } else + return ps; + } + break; + /* internal states */ + case POWER_STATE_TYPE_INTERNAL_UVD: + if (adev->pm.dpm.uvd_ps) + return adev->pm.dpm.uvd_ps; + else + break; + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_BOOT: + return adev->pm.dpm.boot_ps; + case POWER_STATE_TYPE_INTERNAL_THERMAL: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ACPI: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_ULV: + if (ps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + return ps; + break; + case POWER_STATE_TYPE_INTERNAL_3DPERF: + if (ps->class & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + return ps; + break; + default: + break; + } + } + /* use a fallback state if we didn't match */ + switch (dpm_state) { + case POWER_STATE_TYPE_INTERNAL_UVD_SD: + dpm_state = POWER_STATE_TYPE_INTERNAL_UVD_HD; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_UVD_HD: + case POWER_STATE_TYPE_INTERNAL_UVD_HD2: + case POWER_STATE_TYPE_INTERNAL_UVD_MVC: + if (adev->pm.dpm.uvd_ps) { + return adev->pm.dpm.uvd_ps; + } else { + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + } + case POWER_STATE_TYPE_INTERNAL_THERMAL: + dpm_state = POWER_STATE_TYPE_INTERNAL_ACPI; + goto restart_search; + case POWER_STATE_TYPE_INTERNAL_ACPI: + dpm_state = POWER_STATE_TYPE_BATTERY; + goto restart_search; + case POWER_STATE_TYPE_BATTERY: + case POWER_STATE_TYPE_BALANCED: + case POWER_STATE_TYPE_INTERNAL_3DPERF: + dpm_state = POWER_STATE_TYPE_PERFORMANCE; + goto restart_search; + default: + break; + } + + return NULL; +} + +static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) +{ + struct amdgpu_ps *ps; + enum amd_pm_state_type dpm_state; + int ret; + bool equal = false; + + /* if dpm init failed */ + if (!adev->pm.dpm_enabled) + return; + + if (adev->pm.dpm.user_state != adev->pm.dpm.state) { + /* add other state override checks here */ + if ((!adev->pm.dpm.thermal_active) && + (!adev->pm.dpm.uvd_active)) + adev->pm.dpm.state = adev->pm.dpm.user_state; + } + dpm_state = adev->pm.dpm.state; + + ps = amdgpu_dpm_pick_power_state(adev, dpm_state); + if (ps) + adev->pm.dpm.requested_ps = ps; + else + return; + + if (amdgpu_dpm == 1 && adev->powerplay.pp_funcs->print_power_state) { + printk("switching from power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.current_ps); + printk("switching to power state:\n"); + amdgpu_dpm_print_power_state(adev, adev->pm.dpm.requested_ps); + } + + /* update whether vce is active */ + ps->vce_active = adev->pm.dpm.vce_active; + if (adev->powerplay.pp_funcs->display_configuration_changed) + amdgpu_dpm_display_configuration_changed(adev); + + ret = amdgpu_dpm_pre_set_power_state(adev); + if (ret) + return; + + if (adev->powerplay.pp_funcs->check_state_equal) { + if (0 != amdgpu_dpm_check_state_equal(adev, adev->pm.dpm.current_ps, adev->pm.dpm.requested_ps, &equal)) + equal = false; + } + + if (equal) + return; + + amdgpu_dpm_set_power_state(adev); + amdgpu_dpm_post_set_power_state(adev); + + adev->pm.dpm.current_active_crtcs = adev->pm.dpm.new_active_crtcs; + adev->pm.dpm.current_active_crtc_count = adev->pm.dpm.new_active_crtc_count; + + if (adev->powerplay.pp_funcs->force_performance_level) { + if (adev->pm.dpm.thermal_active) { + enum amd_dpm_forced_level level = adev->pm.dpm.forced_level; + /* force low perf level for thermal */ + amdgpu_dpm_force_performance_level(adev, AMD_DPM_FORCED_LEVEL_LOW); + /* save the user's level */ + adev->pm.dpm.forced_level = level; + } else { + /* otherwise, user selected level */ + amdgpu_dpm_force_performance_level(adev, adev->pm.dpm.forced_level); + } + } +} + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) +{ + int i = 0; + + if (!adev->pm.dpm_enabled) + return; + + if (adev->mode_info.num_crtc) + amdgpu_display_bandwidth_update(adev); + + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->sched.ready) + amdgpu_fence_wait_empty(ring); + } + + if (is_support_sw_smu(adev)) { + struct smu_dpm_context *smu_dpm = &adev->smu.smu_dpm; + smu_handle_task(&adev->smu, + smu_dpm->dpm_level, + AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, + true); + } else { + if (adev->powerplay.pp_funcs->dispatch_tasks) { + if (!amdgpu_device_has_dc_support(adev)) { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count; + adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev); + adev->pm.pm_display_cfg.min_vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we have issues with mclk switching with refresh rates over 120 hz on the non-DC code. */ + if (adev->pm.pm_display_cfg.vrefresh > 120) + adev->pm.pm_display_cfg.min_vblank_time = 0; + if (adev->powerplay.pp_funcs->display_configuration_change) + adev->powerplay.pp_funcs->display_configuration_change( + adev->powerplay.pp_handle, + &adev->pm.pm_display_cfg); + mutex_unlock(&adev->pm.mutex); + } + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL); + } else { + mutex_lock(&adev->pm.mutex); + amdgpu_dpm_get_active_displays(adev); + amdgpu_dpm_change_power_state_locked(adev); + mutex_unlock(&adev->pm.mutex); + } + } +} + +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + } else { + adev->pm.dpm.uvd_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_UVD, !enable); + if (ret) + DRM_ERROR("Dpm %s uvd failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + + /* enable/disable Low Memory PState for UVD (4k videos) */ + if (adev->asic_type == CHIP_STONEY && + adev->uvd.decode_image_width >= WIDTH_4K) { + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if (hwmgr && hwmgr->hwmgr_func && + hwmgr->hwmgr_func->update_nbdpm_pstate) + hwmgr->hwmgr_func->update_nbdpm_pstate(hwmgr, + !enable, + true); + } + } +} + +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + if (adev->family == AMDGPU_FAMILY_SI) { + mutex_lock(&adev->pm.mutex); + if (enable) { + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; + } else { + adev->pm.dpm.vce_active = false; + } + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } else { + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_VCE, !enable); + if (ret) + DRM_ERROR("Dpm %s vce failed, ret = %d. \n", + enable ? "enable" : "disable", ret); + } +} + +void amdgpu_pm_print_power_states(struct amdgpu_device *adev) +{ + int i; + + if (adev->powerplay.pp_funcs->print_power_state == NULL) + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) + amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); + +} + +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable) +{ + int ret = 0; + + ret = amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_JPEG, !enable); + if (ret) + DRM_ERROR("Dpm %s jpeg failed, ret = %d. \n", + enable ? "enable" : "disable", ret); +} + +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version) +{ + int r; + + if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { + r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); + if (r) { + pr_err("smu firmware loading failed\n"); + return r; + } + *smu_version = adev->pm.fw_version; + } + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c new file mode 100644 index 000000000000..5fc6a9a13096 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -0,0 +1,3613 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Rafał Miłecki + * Alex Deucher + */ + +#include + +#include "amdgpu.h" +#include "amdgpu_drv.h" +#include "amdgpu_pm.h" +#include "amdgpu_dpm.h" +#include "amdgpu_smu.h" +#include "atom.h" +#include +#include +#include +#include +#include +#include "hwmgr.h" + +static const struct cg_flag_name clocks[] = { + {AMD_CG_SUPPORT_GFX_MGCG, "Graphics Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_MGLS, "Graphics Medium Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CGCG, "Graphics Coarse Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_CGLS, "Graphics Coarse Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CGTS, "Graphics Coarse Grain Tree Shader Clock Gating"}, + {AMD_CG_SUPPORT_GFX_CGTS_LS, "Graphics Coarse Grain Tree Shader Light Sleep"}, + {AMD_CG_SUPPORT_GFX_CP_LS, "Graphics Command Processor Light Sleep"}, + {AMD_CG_SUPPORT_GFX_RLC_LS, "Graphics Run List Controller Light Sleep"}, + {AMD_CG_SUPPORT_GFX_3D_CGCG, "Graphics 3D Coarse Grain Clock Gating"}, + {AMD_CG_SUPPORT_GFX_3D_CGLS, "Graphics 3D Coarse Grain memory Light Sleep"}, + {AMD_CG_SUPPORT_MC_LS, "Memory Controller Light Sleep"}, + {AMD_CG_SUPPORT_MC_MGCG, "Memory Controller Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_SDMA_LS, "System Direct Memory Access Light Sleep"}, + {AMD_CG_SUPPORT_SDMA_MGCG, "System Direct Memory Access Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_BIF_MGCG, "Bus Interface Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_BIF_LS, "Bus Interface Light Sleep"}, + {AMD_CG_SUPPORT_UVD_MGCG, "Unified Video Decoder Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_VCE_MGCG, "Video Compression Engine Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_HDP_LS, "Host Data Path Light Sleep"}, + {AMD_CG_SUPPORT_HDP_MGCG, "Host Data Path Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_MGCG, "Digital Right Management Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DRM_LS, "Digital Right Management Light Sleep"}, + {AMD_CG_SUPPORT_ROM_MGCG, "Rom Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_DF_MGCG, "Data Fabric Medium Grain Clock Gating"}, + + {AMD_CG_SUPPORT_ATHUB_MGCG, "Address Translation Hub Medium Grain Clock Gating"}, + {AMD_CG_SUPPORT_ATHUB_LS, "Address Translation Hub Light Sleep"}, + {0, NULL}, +}; + +static const struct hwmon_temp_label { + enum PP_HWMON_TEMP channel; + const char *label; +} temp_label[] = { + {PP_TEMP_EDGE, "edge"}, + {PP_TEMP_JUNCTION, "junction"}, + {PP_TEMP_MEM, "mem"}, +}; + +/** + * DOC: power_dpm_state + * + * The power_dpm_state file is a legacy interface and is only provided for + * backwards compatibility. The amdgpu driver provides a sysfs API for adjusting + * certain power related parameters. The file power_dpm_state is used for this. + * It accepts the following arguments: + * + * - battery + * + * - balanced + * + * - performance + * + * battery + * + * On older GPUs, the vbios provided a special power state for battery + * operation. Selecting battery switched to this state. This is no + * longer provided on newer GPUs so the option does nothing in that case. + * + * balanced + * + * On older GPUs, the vbios provided a special power state for balanced + * operation. Selecting balanced switched to this state. This is no + * longer provided on newer GPUs so the option does nothing in that case. + * + * performance + * + * On older GPUs, the vbios provided a special power state for performance + * operation. Selecting performance switched to this state. This is no + * longer provided on newer GPUs so the option does nothing in that case. + * + */ + +static ssize_t amdgpu_get_power_dpm_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + enum amd_pm_state_type pm; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + if (adev->smu.ppt_funcs->get_current_power_state) + pm = smu_get_current_power_state(&adev->smu); + else + pm = adev->pm.dpm.user_state; + } else if (adev->powerplay.pp_funcs->get_current_power_state) { + pm = amdgpu_dpm_get_current_power_state(adev); + } else { + pm = adev->pm.dpm.user_state; + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", + (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : + (pm == POWER_STATE_TYPE_BALANCED) ? "balanced" : "performance"); +} + +static ssize_t amdgpu_set_power_dpm_state(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + enum amd_pm_state_type state; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + if (strncmp("battery", buf, strlen("battery")) == 0) + state = POWER_STATE_TYPE_BATTERY; + else if (strncmp("balanced", buf, strlen("balanced")) == 0) + state = POWER_STATE_TYPE_BALANCED; + else if (strncmp("performance", buf, strlen("performance")) == 0) + state = POWER_STATE_TYPE_PERFORMANCE; + else + return -EINVAL; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.user_state = state; + mutex_unlock(&adev->pm.mutex); + } else if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.user_state = state; + mutex_unlock(&adev->pm.mutex); + + amdgpu_pm_compute_clocks(adev); + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + + +/** + * DOC: power_dpm_force_performance_level + * + * The amdgpu driver provides a sysfs API for adjusting certain power + * related parameters. The file power_dpm_force_performance_level is + * used for this. It accepts the following arguments: + * + * - auto + * + * - low + * + * - high + * + * - manual + * + * - profile_standard + * + * - profile_min_sclk + * + * - profile_min_mclk + * + * - profile_peak + * + * auto + * + * When auto is selected, the driver will attempt to dynamically select + * the optimal power profile for current conditions in the driver. + * + * low + * + * When low is selected, the clocks are forced to the lowest power state. + * + * high + * + * When high is selected, the clocks are forced to the highest power state. + * + * manual + * + * When manual is selected, the user can manually adjust which power states + * are enabled for each clock domain via the sysfs pp_dpm_mclk, pp_dpm_sclk, + * and pp_dpm_pcie files and adjust the power state transition heuristics + * via the pp_power_profile_mode sysfs file. + * + * profile_standard + * profile_min_sclk + * profile_min_mclk + * profile_peak + * + * When the profiling modes are selected, clock and power gating are + * disabled and the clocks are set for different profiling cases. This + * mode is recommended for profiling specific work loads where you do + * not want clock or power gating for clock fluctuation to interfere + * with your results. profile_standard sets the clocks to a fixed clock + * level which varies from asic to asic. profile_min_sclk forces the sclk + * to the lowest level. profile_min_mclk forces the mclk to the lowest level. + * profile_peak sets all clocks (mclk, sclk, pcie) to the highest levels. + * + */ + +static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + enum amd_dpm_forced_level level = 0xff; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + level = smu_get_performance_level(&adev->smu); + else if (adev->powerplay.pp_funcs->get_performance_level) + level = amdgpu_dpm_get_performance_level(adev); + else + level = adev->pm.dpm.forced_level; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return snprintf(buf, PAGE_SIZE, "%s\n", + (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : + (level == AMD_DPM_FORCED_LEVEL_HIGH) ? "high" : + (level == AMD_DPM_FORCED_LEVEL_MANUAL) ? "manual" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) ? "profile_standard" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) ? "profile_min_sclk" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) ? "profile_min_mclk" : + (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) ? "profile_peak" : + "unknown"); +} + +static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + enum amd_dpm_forced_level level; + enum amd_dpm_forced_level current_level = 0xff; + int ret = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + if (strncmp("low", buf, strlen("low")) == 0) { + level = AMD_DPM_FORCED_LEVEL_LOW; + } else if (strncmp("high", buf, strlen("high")) == 0) { + level = AMD_DPM_FORCED_LEVEL_HIGH; + } else if (strncmp("auto", buf, strlen("auto")) == 0) { + level = AMD_DPM_FORCED_LEVEL_AUTO; + } else if (strncmp("manual", buf, strlen("manual")) == 0) { + level = AMD_DPM_FORCED_LEVEL_MANUAL; + } else if (strncmp("profile_exit", buf, strlen("profile_exit")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_EXIT; + } else if (strncmp("profile_standard", buf, strlen("profile_standard")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD; + } else if (strncmp("profile_min_sclk", buf, strlen("profile_min_sclk")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK; + } else if (strncmp("profile_min_mclk", buf, strlen("profile_min_mclk")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK; + } else if (strncmp("profile_peak", buf, strlen("profile_peak")) == 0) { + level = AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + } else { + return -EINVAL; + } + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + current_level = smu_get_performance_level(&adev->smu); + else if (adev->powerplay.pp_funcs->get_performance_level) + current_level = amdgpu_dpm_get_performance_level(adev); + + if (current_level == level) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return count; + } + + if (adev->asic_type == CHIP_RAVEN) { + if (!(adev->apu_flags & AMD_APU_IS_RAVEN2)) { + if (current_level != AMD_DPM_FORCED_LEVEL_MANUAL && level == AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, false); + else if (current_level == AMD_DPM_FORCED_LEVEL_MANUAL && level != AMD_DPM_FORCED_LEVEL_MANUAL) + amdgpu_gfx_off_ctrl(adev, true); + } + } + + /* profile_exit setting is valid only when current mode is in profile mode */ + if (!(current_level & (AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) && + (level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT)) { + pr_err("Currently not in any profile mode!\n"); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + + if (is_support_sw_smu(adev)) { + ret = smu_force_performance_level(&adev->smu, level); + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } else if (adev->powerplay.pp_funcs->force_performance_level) { + mutex_lock(&adev->pm.mutex); + if (adev->pm.dpm.thermal_active) { + mutex_unlock(&adev->pm.mutex); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + ret = amdgpu_dpm_force_performance_level(adev, level); + if (ret) { + mutex_unlock(&adev->pm.mutex); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } else { + adev->pm.dpm.forced_level = level; + } + mutex_unlock(&adev->pm.mutex); + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +static ssize_t amdgpu_get_pp_num_states(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + struct pp_states_info data; + int i, buf_len, ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + ret = smu_get_power_num_states(&adev->smu, &data); + if (ret) + return ret; + } else if (adev->powerplay.pp_funcs->get_pp_num_states) { + amdgpu_dpm_get_pp_num_states(adev, &data); + } else { + memset(&data, 0, sizeof(data)); + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + buf_len = snprintf(buf, PAGE_SIZE, "states: %d\n", data.nums); + for (i = 0; i < data.nums; i++) + buf_len += snprintf(buf + buf_len, PAGE_SIZE, "%d %s\n", i, + (data.states[i] == POWER_STATE_TYPE_INTERNAL_BOOT) ? "boot" : + (data.states[i] == POWER_STATE_TYPE_BATTERY) ? "battery" : + (data.states[i] == POWER_STATE_TYPE_BALANCED) ? "balanced" : + (data.states[i] == POWER_STATE_TYPE_PERFORMANCE) ? "performance" : "default"); + + return buf_len; +} + +static ssize_t amdgpu_get_pp_cur_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + struct pp_states_info data; + struct smu_context *smu = &adev->smu; + enum amd_pm_state_type pm = 0; + int i = 0, ret = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + pm = smu_get_current_power_state(smu); + ret = smu_get_power_num_states(smu, &data); + if (ret) + return ret; + } else if (adev->powerplay.pp_funcs->get_current_power_state + && adev->powerplay.pp_funcs->get_pp_num_states) { + pm = amdgpu_dpm_get_current_power_state(adev); + amdgpu_dpm_get_pp_num_states(adev, &data); + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + for (i = 0; i < data.nums; i++) { + if (pm == data.states[i]) + break; + } + + if (i == data.nums) + i = -EINVAL; + + return snprintf(buf, PAGE_SIZE, "%d\n", i); +} + +static ssize_t amdgpu_get_pp_force_state(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + + if (adev->in_gpu_reset) + return -EPERM; + + if (adev->pp_force_state_enabled) + return amdgpu_get_pp_cur_state(dev, attr, buf); + else + return snprintf(buf, PAGE_SIZE, "\n"); +} + +static ssize_t amdgpu_set_pp_force_state(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + enum amd_pm_state_type state = 0; + unsigned long idx; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + if (strlen(buf) == 1) + adev->pp_force_state_enabled = false; + else if (is_support_sw_smu(adev)) + adev->pp_force_state_enabled = false; + else if (adev->powerplay.pp_funcs->dispatch_tasks && + adev->powerplay.pp_funcs->get_pp_num_states) { + struct pp_states_info data; + + ret = kstrtoul(buf, 0, &idx); + if (ret || idx >= ARRAY_SIZE(data.states)) + return -EINVAL; + + idx = array_index_nospec(idx, ARRAY_SIZE(data.states)); + + amdgpu_dpm_get_pp_num_states(adev, &data); + state = data.states[idx]; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + /* only set user selected power states */ + if (state != POWER_STATE_TYPE_INTERNAL_BOOT && + state != POWER_STATE_TYPE_DEFAULT) { + amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_ENABLE_USER_STATE, &state); + adev->pp_force_state_enabled = true; + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + } + + return count; +} + +/** + * DOC: pp_table + * + * The amdgpu driver provides a sysfs API for uploading new powerplay + * tables. The file pp_table is used for this. Reading the file + * will dump the current power play table. Writing to the file + * will attempt to upload a new powerplay table and re-initialize + * powerplay using that new table. + * + */ + +static ssize_t amdgpu_get_pp_table(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + char *table = NULL; + int size, ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + size = smu_sys_get_pp_table(&adev->smu, (void **)&table); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + if (size < 0) + return size; + } else if (adev->powerplay.pp_funcs->get_pp_table) { + size = amdgpu_dpm_get_pp_table(adev, &table); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + if (size < 0) + return size; + } else { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return 0; + } + + if (size >= PAGE_SIZE) + size = PAGE_SIZE - 1; + + memcpy(buf, table, size); + + return size; +} + +static ssize_t amdgpu_set_pp_table(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + return ret; + } + } else if (adev->powerplay.pp_funcs->set_pp_table) + amdgpu_dpm_set_pp_table(adev, buf, count); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +/** + * DOC: pp_od_clk_voltage + * + * The amdgpu driver provides a sysfs API for adjusting the clocks and voltages + * 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: + * + * - a list of engine clock levels and voltages labeled OD_SCLK + * + * - a list of memory clock levels and voltages labeled OD_MCLK + * + * - a list of valid ranges for sclk, mclk, and voltage labeled OD_RANGE + * + * To manually adjust these settings, first select manual using + * power_dpm_force_performance_level. Enter a new value for each + * level by writing a string that contains "s/m level clock voltage" to + * the file. E.g., "s 1 500 820" will update sclk level 1 to be 500 MHz + * at 820 mV; "m 0 350 810" will update mclk level 0 to be 350 MHz at + * 810 mV. When you have edited all of the states as needed, write + * "c" (commit) to the file to commit your changes. If you want to reset to the + * default power levels, write "r" (reset) to the file to reset them. + * + * + * < For Vega20 and newer ASICs > + * + * Reading the file will display: + * + * - minimum and maximum engine clock labeled OD_SCLK + * + * - maximum memory clock labeled OD_MCLK + * + * - three points labeled OD_VDDC_CURVE. + * They can be used to calibrate the sclk voltage curve. + * + * - a list of valid ranges for sclk, mclk, and voltage curve points + * labeled OD_RANGE + * + * To manually adjust these settings: + * + * - First select manual using power_dpm_force_performance_level + * + * - For clock frequency setting, enter a new value by writing a + * string that contains "s/m index clock" to the file. The index + * should be 0 if to set minimum clock. And 1 if to set maximum + * clock. E.g., "s 0 500" will update minimum sclk to be 500 MHz. + * "m 1 800" will update maximum mclk to be 800Mhz. + * + * For sclk voltage curve, enter the new values by writing a + * string that contains "vc point clock voltage" to the file. The + * points are indexed by 0, 1 and 2. E.g., "vc 0 300 600" will + * update point1 with clock set as 300Mhz and voltage as + * 600mV. "vc 2 1000 1000" will update point3 with clock set + * as 1000Mhz and voltage 1000mV. + * + * - When you have edited all of the states as needed, write "c" (commit) + * to the file to commit your changes + * + * - If you want to reset to the default power levels, write "r" (reset) + * to the file to reset them + * + */ + +static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t parameter_size = 0; + long parameter[64]; + char buf_cpy[128]; + char *tmp_str; + char *sub_str; + const char delimiter[3] = {' ', '\n', '\0'}; + uint32_t type; + + if (adev->in_gpu_reset) + return -EPERM; + + if (count > 127) + return -EINVAL; + + if (*buf == 's') + type = PP_OD_EDIT_SCLK_VDDC_TABLE; + else if (*buf == 'm') + type = PP_OD_EDIT_MCLK_VDDC_TABLE; + else if(*buf == 'r') + type = PP_OD_RESTORE_DEFAULT_TABLE; + else if (*buf == 'c') + type = PP_OD_COMMIT_DPM_TABLE; + else if (!strncmp(buf, "vc", 2)) + type = PP_OD_EDIT_VDDC_CURVE; + else + return -EINVAL; + + memcpy(buf_cpy, buf, count+1); + + tmp_str = buf_cpy; + + if (type == PP_OD_EDIT_VDDC_CURVE) + tmp_str++; + while (isspace(*++tmp_str)); + + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); + if (ret) + return -EINVAL; + parameter_size++; + + while (isspace(*tmp_str)) + tmp_str++; + } + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + ret = smu_od_edit_dpm_table(&adev->smu, type, + parameter, parameter_size); + + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } else { + if (adev->powerplay.pp_funcs->odn_edit_dpm_table) { + ret = amdgpu_dpm_odn_edit_dpm_table(adev, type, + parameter, parameter_size); + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } + + if (type == PP_OD_COMMIT_DPM_TABLE) { + if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, + AMD_PP_TASK_READJUST_POWER_STATE, + NULL); + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return count; + } else { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + size = smu_print_clk_levels(&adev->smu, SMU_OD_SCLK, buf); + size += smu_print_clk_levels(&adev->smu, SMU_OD_MCLK, buf+size); + size += smu_print_clk_levels(&adev->smu, SMU_OD_VDDC_CURVE, buf+size); + size += smu_print_clk_levels(&adev->smu, SMU_OD_RANGE, buf+size); + } else if (adev->powerplay.pp_funcs->print_clock_levels) { + size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); + size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf+size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf+size); + size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf+size); + } else { + size = snprintf(buf, PAGE_SIZE, "\n"); + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +/** + * DOC: pp_features + * + * The amdgpu driver provides a sysfs API for adjusting what powerplay + * features to be enabled. The file pp_features is used for this. And + * this is only available for Vega10 and later dGPUs. + * + * Reading back the file will show you the followings: + * - Current ppfeature masks + * - List of the all supported powerplay features with their naming, + * bitmasks and enablement status('Y'/'N' means "enabled"/"disabled"). + * + * To manually enable or disable a specific feature, just set or clear + * the corresponding bit from original ppfeature masks and input the + * new ppfeature masks. + */ +static ssize_t amdgpu_set_pp_features(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint64_t featuremask; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = kstrtou64(buf, 0, &featuremask); + if (ret) + return -EINVAL; + + pr_debug("featuremask = 0x%llx\n", featuremask); + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + return -EINVAL; + } + } else if (adev->powerplay.pp_funcs->set_ppfeature_status) { + ret = amdgpu_dpm_set_ppfeature_status(adev, featuremask); + if (ret) { + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + return -EINVAL; + } + } + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +static ssize_t amdgpu_get_pp_features(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_get_ppfeature_status(adev, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +/** + * DOC: pp_dpm_sclk pp_dpm_mclk pp_dpm_socclk pp_dpm_fclk pp_dpm_dcefclk pp_dpm_pcie + * + * The amdgpu driver provides a sysfs API for adjusting what power levels + * are enabled for a given power state. The files pp_dpm_sclk, pp_dpm_mclk, + * pp_dpm_socclk, pp_dpm_fclk, pp_dpm_dcefclk and pp_dpm_pcie are used for + * this. + * + * pp_dpm_socclk and pp_dpm_dcefclk interfaces are only available for + * Vega10 and later ASICs. + * pp_dpm_fclk interface is only available for Vega20 and later ASICs. + * + * Reading back the files will show you the available power levels within + * the power state and the clock information for those levels. + * + * To manually adjust these states, first select manual using + * power_dpm_force_performance_level. + * Secondly, enter a new value for each level by inputing a string that + * contains " echo xx xx xx > pp_dpm_sclk/mclk/pcie" + * E.g., + * + * .. code-block:: bash + * + * echo "4 5 6" > pp_dpm_sclk + * + * will enable sclk levels 4, 5, and 6. + * + * NOTE: change to the dcefclk max dpm level is not supported now + */ + +static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_SCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +/* + * Worst case: 32 bits individually specified, in octal at 12 characters + * per line (+1 for \n). + */ +#define AMDGPU_MASK_BUF_MAX (32 * 13) + +static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) +{ + int ret; + long level; + char *sub_str = NULL; + char *tmp; + char buf_cpy[AMDGPU_MASK_BUF_MAX + 1]; + const char delimiter[3] = {' ', '\n', '\0'}; + size_t bytes; + + *mask = 0; + + bytes = min(count, sizeof(buf_cpy) - 1); + memcpy(buf_cpy, buf, bytes); + buf_cpy[bytes] = '\0'; + tmp = buf_cpy; + while (tmp[0]) { + sub_str = strsep(&tmp, delimiter); + if (strlen(sub_str)) { + ret = kstrtol(sub_str, 0, &level); + if (ret) + return -EINVAL; + *mask |= 1 << level; + } else + break; + } + + return 0; +} + +static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t mask = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_MCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint32_t mask = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_SOCCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t mask = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + ret = amdgpu_dpm_force_clock_level(adev, PP_SOCCLK, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_FCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t mask = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + ret = amdgpu_dpm_force_clock_level(adev, PP_FCLK, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_DCEFCLK, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t mask = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + ret = amdgpu_dpm_force_clock_level(adev, PP_DCEFCLK, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_print_clock_levels(adev, PP_PCIE, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + uint32_t mask = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = amdgpu_read_mask(buf, count, &mask); + if (ret) + return ret; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + ret = amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); + else + ret = 0; + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (ret) + return -EINVAL; + + return count; +} + +static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint32_t value = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} + +static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + long int value; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = kstrtol(buf, 0, &value); + + if (ret) + return -EINVAL; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + value = smu_set_od_percentage(&(adev->smu), SMU_OD_SCLK, (uint32_t)value); + } else { + if (adev->powerplay.pp_funcs->set_sclk_od) + amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); + + if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + } else { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint32_t value = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} + +static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int ret; + long int value; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = kstrtol(buf, 0, &value); + + if (ret) + return -EINVAL; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) { + value = smu_set_od_percentage(&(adev->smu), SMU_OD_MCLK, (uint32_t)value); + } else { + if (adev->powerplay.pp_funcs->set_mclk_od) + amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); + + if (adev->powerplay.pp_funcs->dispatch_tasks) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + } else { + adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; + amdgpu_pm_compute_clocks(adev); + } + } + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return count; +} + +/** + * DOC: pp_power_profile_mode + * + * The amdgpu driver provides a sysfs API for adjusting the heuristics + * related to switching between power levels in a power state. The file + * pp_power_profile_mode is used for this. + * + * Reading this file outputs a list of all of the predefined power profiles + * and the relevant heuristics settings for that profile. + * + * To select a profile or create a custom profile, first select manual using + * power_dpm_force_performance_level. Writing the number of a predefined + * profile to pp_power_profile_mode will enable those heuristics. To + * create a custom set of heuristics, write a string of numbers to the file + * starting with the number of the custom profile along with a setting + * for each heuristic parameter. Due to differences across asic families + * the heuristic parameters vary from family to family. + * + */ + +static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + ssize_t size; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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) + size = amdgpu_dpm_get_power_profile_mode(adev, buf); + else + size = snprintf(buf, PAGE_SIZE, "\n"); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + + +static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + int ret; + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint32_t parameter_size = 0; + long parameter[64]; + char *sub_str, buf_cpy[128]; + char *tmp_str; + uint32_t i = 0; + char tmp[2]; + long int profile_mode = 0; + const char delimiter[3] = {' ', '\n', '\0'}; + + if (adev->in_gpu_reset) + return -EPERM; + + tmp[0] = *(buf); + tmp[1] = '\0'; + ret = kstrtol(tmp, 0, &profile_mode); + if (ret) + return -EINVAL; + + if (profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + if (count < 2 || count > 127) + return -EINVAL; + while (isspace(*++buf)) + i++; + memcpy(buf_cpy, buf, count-i); + tmp_str = buf_cpy; + while (tmp_str[0]) { + sub_str = strsep(&tmp_str, delimiter); + ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); + if (ret) + return -EINVAL; + parameter_size++; + while (isspace(*tmp_str)) + tmp_str++; + } + } + parameter[parameter_size] = profile_mode; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + 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); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (!ret) + return count; + + return -EINVAL; +} + +/** + * DOC: gpu_busy_percent + * + * The amdgpu driver provides a sysfs API for reading how busy the GPU + * is as a percentage. The file gpu_busy_percent is used for this. + * The SMU firmware computes a percentage of load based on the + * aggregate activity level in the IP cores. + */ +static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int r, value, size = sizeof(value); + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return r; + } + + /* read the IP busy sensor */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, + (void *)&value, &size); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} + +/** + * DOC: mem_busy_percent + * + * The amdgpu driver provides a sysfs API for reading how busy the VRAM + * is as a percentage. The file mem_busy_percent is used for this. + * The SMU firmware computes a percentage of load based on the + * aggregate activity level in the IP cores. + */ +static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + int r, value, size = sizeof(value); + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return r; + } + + /* read the IP busy sensor */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, + (void *)&value, &size); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} + +/** + * DOC: pcie_bw + * + * The amdgpu driver provides a sysfs API for estimating how much data + * has been received and sent by the GPU in the last second through PCIe. + * The file pcie_bw is used for this. + * The Perf counters count the number of received and sent messages and return + * those values, as well as the maximum payload size of a PCIe packet (mps). + * Note that it is not possible to easily and quickly obtain the size of each + * packet transmitted, so we output the max payload size (mps) to allow for + * quick estimation of the PCIe bandwidth usage + */ +static ssize_t amdgpu_get_pcie_bw(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + uint64_t count0 = 0, count1 = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + if (adev->flags & AMD_IS_APU) + return -ENODATA; + + if (!adev->asic_funcs->get_pcie_usage) + return -ENODATA; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + amdgpu_asic_get_pcie_usage(adev, &count0, &count1); + + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return snprintf(buf, PAGE_SIZE, "%llu %llu %i\n", + count0, count1, pcie_get_mps(adev->pdev)); +} + +/** + * DOC: unique_id + * + * The amdgpu driver provides a sysfs API for providing a unique ID for the GPU + * The file unique_id is used for this. + * This will provide a Unique ID that will persist from machine to machine + * + * NOTE: This will only work for GFX9 and newer. This file will be absent + * on unsupported ASICs (GFX8 and older) + */ +static ssize_t amdgpu_get_unique_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + + if (adev->in_gpu_reset) + return -EPERM; + + if (adev->unique_id) + return snprintf(buf, PAGE_SIZE, "%016llx\n", adev->unique_id); + + return 0; +} + +/** + * DOC: thermal_throttling_logging + * + * Thermal throttling pulls down the clock frequency and thus the performance. + * It's an useful mechanism to protect the chip from overheating. Since it + * impacts performance, the user controls whether it is enabled and if so, + * the log frequency. + * + * Reading back the file shows you the status(enabled or disabled) and + * the interval(in seconds) between each thermal logging. + * + * Writing an integer to the file, sets a new logging interval, in seconds. + * The value should be between 1 and 3600. If the value is less than 1, + * thermal logging is disabled. Values greater than 3600 are ignored. + */ +static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + + return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", + adev->ddev->unique, + atomic_read(&adev->throttling_logging_enabled) ? "enabled" : "disabled", + adev->throttling_logging_rs.interval / HZ + 1); +} + +static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + long throttling_logging_interval; + unsigned long flags; + int ret = 0; + + ret = kstrtol(buf, 0, &throttling_logging_interval); + if (ret) + return ret; + + if (throttling_logging_interval > 3600) + return -EINVAL; + + if (throttling_logging_interval > 0) { + raw_spin_lock_irqsave(&adev->throttling_logging_rs.lock, flags); + /* + * Reset the ratelimit timer internals. + * This can effectively restart the timer. + */ + adev->throttling_logging_rs.interval = + (throttling_logging_interval - 1) * HZ; + adev->throttling_logging_rs.begin = 0; + adev->throttling_logging_rs.printed = 0; + adev->throttling_logging_rs.missed = 0; + raw_spin_unlock_irqrestore(&adev->throttling_logging_rs.lock, flags); + + atomic_set(&adev->throttling_logging_enabled, 1); + } else { + atomic_set(&adev->throttling_logging_enabled, 0); + } + + return count; +} + +/** + * DOC: gpu_metrics + * + * The amdgpu driver provides a sysfs API for retrieving current gpu + * metrics data. The file gpu_metrics is used for this. Reading the + * file will dump all the current gpu metrics data. + * + * These data include temperature, frequency, engines utilization, + * power consume, throttler status, fan speed and cpu core statistics( + * available for APU only). That's it will give a snapshot of all sensors + * at the same time. + */ +static ssize_t amdgpu_get_gpu_metrics(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct drm_device *ddev = dev_get_drvdata(dev); + struct amdgpu_device *adev = ddev->dev_private; + void *gpu_metrics; + ssize_t size = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(ddev->dev); + return ret; + } + + if (is_support_sw_smu(adev)) + size = smu_sys_get_gpu_metrics(&adev->smu, &gpu_metrics); + else if (adev->powerplay.pp_funcs->get_gpu_metrics) + size = amdgpu_dpm_get_gpu_metrics(adev, &gpu_metrics); + + if (size <= 0) + goto out; + + if (size >= PAGE_SIZE) + size = PAGE_SIZE - 1; + + memcpy(buf, gpu_metrics, size); + +out: + pm_runtime_mark_last_busy(ddev->dev); + pm_runtime_put_autosuspend(ddev->dev); + + return size; +} + +static struct amdgpu_device_attr amdgpu_device_attrs[] = { + AMDGPU_DEVICE_ATTR_RW(power_dpm_state, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(power_dpm_force_performance_level, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(pp_num_states, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(pp_cur_state, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_force_state, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_table, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_sclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_mclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_socclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_fclk, ATTR_FLAG_BASIC|ATTR_FLAG_ONEVF), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_dcefclk, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_dpm_pcie, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_sclk_od, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_mclk_od, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_power_profile_mode, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_od_clk_voltage, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(gpu_busy_percent, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(mem_busy_percent, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(pcie_bw, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(pp_features, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(unique_id, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RW(thermal_throttling_logging, ATTR_FLAG_BASIC), + AMDGPU_DEVICE_ATTR_RO(gpu_metrics, ATTR_FLAG_BASIC), +}; + +static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, + uint32_t mask, enum amdgpu_device_attr_states *states) +{ + struct device_attribute *dev_attr = &attr->dev_attr; + const char *attr_name = dev_attr->attr.name; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + enum amd_asic_type asic_type = adev->asic_type; + + if (!(attr->flags & mask)) { + *states = ATTR_STATE_UNSUPPORTED; + return 0; + } + +#define DEVICE_ATTR_IS(_name) (!strcmp(attr_name, #_name)) + + if (DEVICE_ATTR_IS(pp_dpm_socclk)) { + if (asic_type < CHIP_VEGA10) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { + if (asic_type < CHIP_VEGA10 || asic_type == CHIP_ARCTURUS) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { + if (asic_type < CHIP_VEGA20) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_dpm_pcie)) { + if (asic_type == CHIP_ARCTURUS) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { + *states = ATTR_STATE_UNSUPPORTED; + if ((is_support_sw_smu(adev) && adev->smu.od_enabled) || + (!is_support_sw_smu(adev) && hwmgr->od_enabled)) + *states = ATTR_STATE_SUPPORTED; + } else if (DEVICE_ATTR_IS(mem_busy_percent)) { + if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pcie_bw)) { + /* PCIe Perf counters won't work on APU nodes */ + if (adev->flags & AMD_IS_APU) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(unique_id)) { + if (asic_type != CHIP_VEGA10 && + asic_type != CHIP_VEGA20 && + asic_type != CHIP_ARCTURUS) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(pp_features)) { + if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) + *states = ATTR_STATE_UNSUPPORTED; + } else if (DEVICE_ATTR_IS(gpu_metrics)) { + if (asic_type < CHIP_VEGA12) + *states = ATTR_STATE_UNSUPPORTED; + } + + if (asic_type == CHIP_ARCTURUS) { + /* Arcturus does not support standalone mclk/socclk/fclk level setting */ + if (DEVICE_ATTR_IS(pp_dpm_mclk) || + DEVICE_ATTR_IS(pp_dpm_socclk) || + DEVICE_ATTR_IS(pp_dpm_fclk)) { + dev_attr->attr.mode &= ~S_IWUGO; + dev_attr->store = NULL; + } + } + +#undef DEVICE_ATTR_IS + + return 0; +} + + +static int amdgpu_device_attr_create(struct amdgpu_device *adev, + struct amdgpu_device_attr *attr, + uint32_t mask, struct list_head *attr_list) +{ + int ret = 0; + struct device_attribute *dev_attr = &attr->dev_attr; + const char *name = dev_attr->attr.name; + enum amdgpu_device_attr_states attr_states = ATTR_STATE_SUPPORTED; + struct amdgpu_device_attr_entry *attr_entry; + + int (*attr_update)(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, + uint32_t mask, enum amdgpu_device_attr_states *states) = default_attr_update; + + BUG_ON(!attr); + + attr_update = attr->attr_update ? attr_update : default_attr_update; + + ret = attr_update(adev, attr, mask, &attr_states); + if (ret) { + dev_err(adev->dev, "failed to update device file %s, ret = %d\n", + name, ret); + return ret; + } + + if (attr_states == ATTR_STATE_UNSUPPORTED) + return 0; + + ret = device_create_file(adev->dev, dev_attr); + if (ret) { + dev_err(adev->dev, "failed to create device file %s, ret = %d\n", + name, ret); + } + + attr_entry = kmalloc(sizeof(*attr_entry), GFP_KERNEL); + if (!attr_entry) + return -ENOMEM; + + attr_entry->attr = attr; + INIT_LIST_HEAD(&attr_entry->entry); + + list_add_tail(&attr_entry->entry, attr_list); + + return ret; +} + +static void amdgpu_device_attr_remove(struct amdgpu_device *adev, struct amdgpu_device_attr *attr) +{ + struct device_attribute *dev_attr = &attr->dev_attr; + + device_remove_file(adev->dev, dev_attr); +} + +static void amdgpu_device_attr_remove_groups(struct amdgpu_device *adev, + struct list_head *attr_list); + +static int amdgpu_device_attr_create_groups(struct amdgpu_device *adev, + struct amdgpu_device_attr *attrs, + uint32_t counts, + uint32_t mask, + struct list_head *attr_list) +{ + int ret = 0; + uint32_t i = 0; + + for (i = 0; i < counts; i++) { + ret = amdgpu_device_attr_create(adev, &attrs[i], mask, attr_list); + if (ret) + goto failed; + } + + return 0; + +failed: + amdgpu_device_attr_remove_groups(adev, attr_list); + + return ret; +} + +static void amdgpu_device_attr_remove_groups(struct amdgpu_device *adev, + struct list_head *attr_list) +{ + struct amdgpu_device_attr_entry *entry, *entry_tmp; + + if (list_empty(attr_list)) + return ; + + list_for_each_entry_safe(entry, entry_tmp, attr_list, entry) { + amdgpu_device_attr_remove(adev, entry->attr); + list_del(&entry->entry); + kfree(entry); + } +} + +static ssize_t amdgpu_hwmon_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int channel = to_sensor_dev_attr(attr)->index; + int r, temp = 0, size = sizeof(temp); + + if (adev->in_gpu_reset) + return -EPERM; + + if (channel >= PP_TEMP_MAX) + return -EINVAL; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + switch (channel) { + case PP_TEMP_JUNCTION: + /* get current junction temperature */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_HOTSPOT_TEMP, + (void *)&temp, &size); + break; + case PP_TEMP_EDGE: + /* get current edge temperature */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_EDGE_TEMP, + (void *)&temp, &size); + break; + case PP_TEMP_MEM: + /* get current memory temperature */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_TEMP, + (void *)&temp, &size); + break; + default: + r = -EINVAL; + break; + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t amdgpu_hwmon_show_temp_thresh(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int hyst = to_sensor_dev_attr(attr)->index; + int temp; + + if (hyst) + temp = adev->pm.dpm.thermal.min_temp; + else + temp = adev->pm.dpm.thermal.max_temp; + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t amdgpu_hwmon_show_hotspot_temp_thresh(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int hyst = to_sensor_dev_attr(attr)->index; + int temp; + + if (hyst) + temp = adev->pm.dpm.thermal.min_hotspot_temp; + else + temp = adev->pm.dpm.thermal.max_hotspot_crit_temp; + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t amdgpu_hwmon_show_mem_temp_thresh(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int hyst = to_sensor_dev_attr(attr)->index; + int temp; + + if (hyst) + temp = adev->pm.dpm.thermal.min_mem_temp; + else + temp = adev->pm.dpm.thermal.max_mem_crit_temp; + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t amdgpu_hwmon_show_temp_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int channel = to_sensor_dev_attr(attr)->index; + + if (channel >= PP_TEMP_MAX) + return -EINVAL; + + return snprintf(buf, PAGE_SIZE, "%s\n", temp_label[channel].label); +} + +static ssize_t amdgpu_hwmon_show_temp_emergency(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int channel = to_sensor_dev_attr(attr)->index; + int temp = 0; + + if (channel >= PP_TEMP_MAX) + return -EINVAL; + + switch (channel) { + case PP_TEMP_JUNCTION: + temp = adev->pm.dpm.thermal.max_hotspot_emergency_temp; + break; + case PP_TEMP_EDGE: + temp = adev->pm.dpm.thermal.max_edge_emergency_temp; + break; + case PP_TEMP_MEM: + temp = adev->pm.dpm.thermal.max_mem_emergency_temp; + break; + } + + return snprintf(buf, PAGE_SIZE, "%d\n", temp); +} + +static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 pwm_mode = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(adev->ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return ret; + } + + 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); + return -EINVAL; + } + + pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return sprintf(buf, "%i\n", pwm_mode); +} + +static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err, ret; + int value; + + if (adev->in_gpu_reset) + return -EPERM; + + err = kstrtoint(buf, 10, &value); + if (err) + return err; + + ret = pm_runtime_get_sync(adev->ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return ret; + } + + 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); + return -EINVAL; + } + + amdgpu_dpm_set_fan_control_mode(adev, value); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return count; +} + +static ssize_t amdgpu_hwmon_get_pwm1_min(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%i\n", 0); +} + +static ssize_t amdgpu_hwmon_get_pwm1_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%i\n", 255); +} + +static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 value; + u32 pwm_mode; + + if (adev->in_gpu_reset) + return -EPERM; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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); + + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { + pr_info("manual fan speed control should be enabled first\n"); + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return -EINVAL; + } + + err = kstrtou32(buf, 10, &value); + if (err) { + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + value = (value * 100) / 255; + + if (is_support_sw_smu(adev)) + err = smu_set_fan_speed_percent(&adev->smu, value); + else if (adev->powerplay.pp_funcs->set_fan_speed_percent) + err = amdgpu_dpm_set_fan_speed_percent(adev, value); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + return count; +} + +static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 speed = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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) + err = amdgpu_dpm_get_fan_speed_percent(adev, &speed); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + speed = (speed * 255) / 100; + + return sprintf(buf, "%i\n", speed); +} + +static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 speed = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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) + err = amdgpu_dpm_get_fan_speed_rpm(adev, &speed); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + return sprintf(buf, "%i\n", speed); +} + +static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 min_rpm = 0; + u32 size = sizeof(min_rpm); + int r; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, + (void *)&min_rpm, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", min_rpm); +} + +static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 max_rpm = 0; + u32 size = sizeof(max_rpm); + int r; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, + (void *)&max_rpm, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", max_rpm); +} + +static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 rpm = 0; + + if (adev->in_gpu_reset) + return -EPERM; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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) + err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + return sprintf(buf, "%i\n", rpm); +} + +static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 value; + u32 pwm_mode; + + if (adev->in_gpu_reset) + return -EPERM; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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); + + if (pwm_mode != AMD_FAN_CTRL_MANUAL) { + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return -ENODATA; + } + + err = kstrtou32(buf, 10, &value); + if (err) { + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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) + err = amdgpu_dpm_set_fan_speed_rpm(adev, value); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + return count; +} + +static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 pwm_mode = 0; + int ret; + + if (adev->in_gpu_reset) + return -EPERM; + + ret = pm_runtime_get_sync(adev->ddev->dev); + if (ret < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return ret; + } + + 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); + return -EINVAL; + } + + pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); +} + +static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + int value; + u32 pwm_mode; + + if (adev->in_gpu_reset) + return -EPERM; + + err = kstrtoint(buf, 10, &value); + if (err) + return err; + + if (value == 0) + pwm_mode = AMD_FAN_CTRL_AUTO; + else if (value == 1) + pwm_mode = AMD_FAN_CTRL_MANUAL; + else + return -EINVAL; + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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); + return -EINVAL; + } + amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return count; +} + +static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 vddgfx; + int r, size = sizeof(vddgfx); + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + /* get the voltage */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, + (void *)&vddgfx, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", vddgfx); +} + +static ssize_t amdgpu_hwmon_show_vddgfx_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "vddgfx\n"); +} + +static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 vddnb; + int r, size = sizeof(vddnb); + + if (adev->in_gpu_reset) + return -EPERM; + + /* only APUs have vddnb */ + if (!(adev->flags & AMD_IS_APU)) + return -EINVAL; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + /* get the voltage */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, + (void *)&vddnb, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%d\n", vddnb); +} + +static ssize_t amdgpu_hwmon_show_vddnb_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "vddnb\n"); +} + +static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + u32 query = 0; + int r, size = sizeof(u32); + unsigned uw; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + /* get the voltage */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, + (void *)&query, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + /* convert to microwatts */ + uw = (query >> 8) * 1000000 + (query & 0xff) * 1000; + + return snprintf(buf, PAGE_SIZE, "%u\n", uw); +} + +static ssize_t amdgpu_hwmon_show_power_cap_min(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%i\n", 0); +} + +static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t limit = 0; + ssize_t size; + int r; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + if (is_support_sw_smu(adev)) { + smu_get_power_limit(&adev->smu, &limit, true); + size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); + } else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) { + adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, true); + size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); + } else { + size = snprintf(buf, PAGE_SIZE, "\n"); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return size; +} + +static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t limit = 0; + ssize_t size; + int r; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + if (is_support_sw_smu(adev)) { + smu_get_power_limit(&adev->smu, &limit, false); + size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); + } else if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_power_limit) { + adev->powerplay.pp_funcs->get_power_limit(adev->powerplay.pp_handle, &limit, false); + size = snprintf(buf, PAGE_SIZE, "%u\n", limit * 1000000); + } else { + size = snprintf(buf, PAGE_SIZE, "\n"); + } + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + return size; +} + + +static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + int err; + u32 value; + + if (adev->in_gpu_reset) + return -EPERM; + + if (amdgpu_sriov_vf(adev)) + return -EINVAL; + + err = kstrtou32(buf, 10, &value); + if (err) + return err; + + value = value / 1000000; /* convert to Watt */ + + + err = pm_runtime_get_sync(adev->ddev->dev); + if (err < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return err; + } + + 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) + err = adev->powerplay.pp_funcs->set_power_limit(adev->powerplay.pp_handle, value); + else + err = -EINVAL; + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (err) + return err; + + return count; +} + +static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t sclk; + int r, size = sizeof(sclk); + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + /* get the sclk */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, + (void *)&sclk, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%u\n", sclk * 10 * 1000); +} + +static ssize_t amdgpu_hwmon_show_sclk_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "sclk\n"); +} + +static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t mclk; + int r, size = sizeof(mclk); + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(adev->ddev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(adev->ddev->dev); + return r; + } + + /* get the sclk */ + r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, + (void *)&mclk, &size); + + pm_runtime_mark_last_busy(adev->ddev->dev); + pm_runtime_put_autosuspend(adev->ddev->dev); + + if (r) + return r; + + return snprintf(buf, PAGE_SIZE, "%u\n", mclk * 10 * 1000); +} + +static ssize_t amdgpu_hwmon_show_mclk_label(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "mclk\n"); +} + +/** + * DOC: hwmon + * + * The amdgpu driver exposes the following sensor interfaces: + * + * - GPU temperature (via the on-die sensor) + * + * - GPU voltage + * + * - Northbridge voltage (APUs only) + * + * - GPU power + * + * - GPU fan + * + * - GPU gfx/compute engine clock + * + * - GPU memory clock (dGPU only) + * + * hwmon interfaces for GPU temperature: + * + * - temp[1-3]_input: the on die GPU temperature in millidegrees Celsius + * - temp2_input and temp3_input are supported on SOC15 dGPUs only + * + * - temp[1-3]_label: temperature channel label + * - temp2_label and temp3_label are supported on SOC15 dGPUs only + * + * - temp[1-3]_crit: temperature critical max value in millidegrees Celsius + * - temp2_crit and temp3_crit are supported on SOC15 dGPUs only + * + * - temp[1-3]_crit_hyst: temperature hysteresis for critical limit in millidegrees Celsius + * - temp2_crit_hyst and temp3_crit_hyst are supported on SOC15 dGPUs only + * + * - temp[1-3]_emergency: temperature emergency max value(asic shutdown) in millidegrees Celsius + * - these are supported on SOC15 dGPUs only + * + * hwmon interfaces for GPU voltage: + * + * - in0_input: the voltage on the GPU in millivolts + * + * - in1_input: the voltage on the Northbridge in millivolts + * + * hwmon interfaces for GPU power: + * + * - power1_average: average power used by the GPU in microWatts + * + * - power1_cap_min: minimum cap supported in microWatts + * + * - power1_cap_max: maximum cap supported in microWatts + * + * - power1_cap: selected power cap in microWatts + * + * hwmon interfaces for GPU fan: + * + * - pwm1: pulse width modulation fan level (0-255) + * + * - pwm1_enable: pulse width modulation fan control method (0: no fan speed control, 1: manual fan speed control using pwm interface, 2: automatic fan speed control) + * + * - pwm1_min: pulse width modulation fan control minimum level (0) + * + * - pwm1_max: pulse width modulation fan control maximum level (255) + * + * - fan1_min: an minimum value Unit: revolution/min (RPM) + * + * - fan1_max: an maxmum value Unit: revolution/max (RPM) + * + * - fan1_input: fan speed in RPM + * + * - fan[1-\*]_target: Desired fan speed Unit: revolution/min (RPM) + * + * - fan[1-\*]_enable: Enable or disable the sensors.1: Enable 0: Disable + * + * hwmon interfaces for GPU clocks: + * + * - freq1_input: the gfx/compute clock in hertz + * + * - freq2_input: the memory clock in hertz + * + * You can use hwmon tools like sensors to view this information on your system. + * + */ + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_EDGE); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, amdgpu_hwmon_show_temp_thresh, NULL, 1); +static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_EDGE); +static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_JUNCTION); +static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, amdgpu_hwmon_show_hotspot_temp_thresh, NULL, 0); +static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, amdgpu_hwmon_show_hotspot_temp_thresh, NULL, 1); +static SENSOR_DEVICE_ATTR(temp2_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_JUNCTION); +static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, amdgpu_hwmon_show_temp, NULL, PP_TEMP_MEM); +static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, amdgpu_hwmon_show_mem_temp_thresh, NULL, 0); +static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, amdgpu_hwmon_show_mem_temp_thresh, NULL, 1); +static SENSOR_DEVICE_ATTR(temp3_emergency, S_IRUGO, amdgpu_hwmon_show_temp_emergency, NULL, PP_TEMP_MEM); +static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_EDGE); +static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_JUNCTION); +static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, amdgpu_hwmon_show_temp_label, NULL, PP_TEMP_MEM); +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1, amdgpu_hwmon_set_pwm1, 0); +static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_enable, amdgpu_hwmon_set_pwm1_enable, 0); +static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0); +static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, amdgpu_hwmon_get_fan1_min, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, amdgpu_hwmon_get_fan1_max, NULL, 0); +static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_target, amdgpu_hwmon_set_fan1_target, 0); +static SENSOR_DEVICE_ATTR(fan1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_enable, amdgpu_hwmon_set_fan1_enable, 0); +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0); +static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0); +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, amdgpu_hwmon_show_vddnb_label, NULL, 0); +static SENSOR_DEVICE_ATTR(power1_average, S_IRUGO, amdgpu_hwmon_show_power_avg, NULL, 0); +static SENSOR_DEVICE_ATTR(power1_cap_max, S_IRUGO, amdgpu_hwmon_show_power_cap_max, NULL, 0); +static SENSOR_DEVICE_ATTR(power1_cap_min, S_IRUGO, amdgpu_hwmon_show_power_cap_min, NULL, 0); +static SENSOR_DEVICE_ATTR(power1_cap, S_IRUGO | S_IWUSR, amdgpu_hwmon_show_power_cap, amdgpu_hwmon_set_power_cap, 0); +static SENSOR_DEVICE_ATTR(freq1_input, S_IRUGO, amdgpu_hwmon_show_sclk, NULL, 0); +static SENSOR_DEVICE_ATTR(freq1_label, S_IRUGO, amdgpu_hwmon_show_sclk_label, NULL, 0); +static SENSOR_DEVICE_ATTR(freq2_input, S_IRUGO, amdgpu_hwmon_show_mclk, NULL, 0); +static SENSOR_DEVICE_ATTR(freq2_label, S_IRUGO, amdgpu_hwmon_show_mclk_label, NULL, 0); + +static struct attribute *hwmon_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp2_input.dev_attr.attr, + &sensor_dev_attr_temp2_crit.dev_attr.attr, + &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp3_input.dev_attr.attr, + &sensor_dev_attr_temp3_crit.dev_attr.attr, + &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_emergency.dev_attr.attr, + &sensor_dev_attr_temp2_emergency.dev_attr.attr, + &sensor_dev_attr_temp3_emergency.dev_attr.attr, + &sensor_dev_attr_temp1_label.dev_attr.attr, + &sensor_dev_attr_temp2_label.dev_attr.attr, + &sensor_dev_attr_temp3_label.dev_attr.attr, + &sensor_dev_attr_pwm1.dev_attr.attr, + &sensor_dev_attr_pwm1_enable.dev_attr.attr, + &sensor_dev_attr_pwm1_min.dev_attr.attr, + &sensor_dev_attr_pwm1_max.dev_attr.attr, + &sensor_dev_attr_fan1_input.dev_attr.attr, + &sensor_dev_attr_fan1_min.dev_attr.attr, + &sensor_dev_attr_fan1_max.dev_attr.attr, + &sensor_dev_attr_fan1_target.dev_attr.attr, + &sensor_dev_attr_fan1_enable.dev_attr.attr, + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in0_label.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in1_label.dev_attr.attr, + &sensor_dev_attr_power1_average.dev_attr.attr, + &sensor_dev_attr_power1_cap_max.dev_attr.attr, + &sensor_dev_attr_power1_cap_min.dev_attr.attr, + &sensor_dev_attr_power1_cap.dev_attr.attr, + &sensor_dev_attr_freq1_input.dev_attr.attr, + &sensor_dev_attr_freq1_label.dev_attr.attr, + &sensor_dev_attr_freq2_input.dev_attr.attr, + &sensor_dev_attr_freq2_label.dev_attr.attr, + NULL +}; + +static umode_t hwmon_attributes_visible(struct kobject *kobj, + struct attribute *attr, int index) +{ + struct device *dev = kobj_to_dev(kobj); + struct amdgpu_device *adev = dev_get_drvdata(dev); + umode_t effective_mode = attr->mode; + + /* under multi-vf mode, the hwmon attributes are all not supported */ + if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) + return 0; + + /* there is no fan under pp one vf mode */ + if (amdgpu_sriov_is_pp_one_vf(adev) && + (attr == &sensor_dev_attr_pwm1.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_input.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_target.dev_attr.attr || + attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) + return 0; + + /* Skip fan attributes if fan is not present */ + if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_input.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_target.dev_attr.attr || + attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) + return 0; + + /* Skip fan attributes on APU */ + if ((adev->flags & AMD_IS_APU) && + (attr == &sensor_dev_attr_pwm1.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_input.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_target.dev_attr.attr || + attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) + return 0; + + /* Skip crit temp on APU */ + if ((adev->flags & AMD_IS_APU) && (adev->family >= AMDGPU_FAMILY_CZ) && + (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr)) + return 0; + + /* Skip limit attributes if DPM is not enabled */ + if (!adev->pm.dpm_enabled && + (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr || + attr == &sensor_dev_attr_pwm1.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_input.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr || + attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_target.dev_attr.attr || + attr == &sensor_dev_attr_fan1_enable.dev_attr.attr)) + return 0; + + if (!is_support_sw_smu(adev)) { + /* mask fan attributes if we have no bindings for this asic to expose */ + if ((!adev->powerplay.pp_funcs->get_fan_speed_percent && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't query fan */ + (!adev->powerplay.pp_funcs->get_fan_control_mode && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't query state */ + effective_mode &= ~S_IRUGO; + + if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && + attr == &sensor_dev_attr_pwm1.dev_attr.attr) || /* can't manage fan */ + (!adev->powerplay.pp_funcs->set_fan_control_mode && + attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ + effective_mode &= ~S_IWUSR; + } + + if (((adev->flags & AMD_IS_APU) || + adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ + adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ + (attr == &sensor_dev_attr_power1_average.dev_attr.attr || + attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || + attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| + attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) + return 0; + + if (!is_support_sw_smu(adev)) { + /* hide max/min values if we can't both query and manage the fan */ + if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && + !adev->powerplay.pp_funcs->get_fan_speed_percent) && + (!adev->powerplay.pp_funcs->set_fan_speed_rpm && + !adev->powerplay.pp_funcs->get_fan_speed_rpm) && + (attr == &sensor_dev_attr_pwm1_max.dev_attr.attr || + attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) + return 0; + + if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm && + !adev->powerplay.pp_funcs->get_fan_speed_rpm) && + (attr == &sensor_dev_attr_fan1_max.dev_attr.attr || + attr == &sensor_dev_attr_fan1_min.dev_attr.attr)) + return 0; + } + + if ((adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ + adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ + (attr == &sensor_dev_attr_in0_input.dev_attr.attr || + attr == &sensor_dev_attr_in0_label.dev_attr.attr)) + return 0; + + /* only APUs have vddnb */ + if (!(adev->flags & AMD_IS_APU) && + (attr == &sensor_dev_attr_in1_input.dev_attr.attr || + attr == &sensor_dev_attr_in1_label.dev_attr.attr)) + return 0; + + /* no mclk on APUs */ + if ((adev->flags & AMD_IS_APU) && + (attr == &sensor_dev_attr_freq2_input.dev_attr.attr || + attr == &sensor_dev_attr_freq2_label.dev_attr.attr)) + return 0; + + /* only SOC15 dGPUs support hotspot and mem temperatures */ + if (((adev->flags & AMD_IS_APU) || + adev->asic_type < CHIP_VEGA10) && + (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr || + attr == &sensor_dev_attr_temp3_crit.dev_attr.attr || + attr == &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr || + attr == &sensor_dev_attr_temp1_emergency.dev_attr.attr || + attr == &sensor_dev_attr_temp2_emergency.dev_attr.attr || + attr == &sensor_dev_attr_temp3_emergency.dev_attr.attr || + attr == &sensor_dev_attr_temp2_input.dev_attr.attr || + attr == &sensor_dev_attr_temp3_input.dev_attr.attr || + attr == &sensor_dev_attr_temp2_label.dev_attr.attr || + attr == &sensor_dev_attr_temp3_label.dev_attr.attr)) + return 0; + + return effective_mode; +} + +static const struct attribute_group hwmon_attrgroup = { + .attrs = hwmon_attributes, + .is_visible = hwmon_attributes_visible, +}; + +static const struct attribute_group *hwmon_groups[] = { + &hwmon_attrgroup, + NULL +}; + +int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) +{ + int ret; + uint32_t mask = 0; + + if (adev->pm.sysfs_initialized) + return 0; + + if (adev->pm.dpm_enabled == 0) + return 0; + + INIT_LIST_HEAD(&adev->pm.pm_attr_list); + + adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, + DRIVER_NAME, adev, + hwmon_groups); + if (IS_ERR(adev->pm.int_hwmon_dev)) { + ret = PTR_ERR(adev->pm.int_hwmon_dev); + dev_err(adev->dev, + "Unable to register hwmon device: %d\n", ret); + return ret; + } + + switch (amdgpu_virt_get_sriov_vf_mode(adev)) { + case SRIOV_VF_MODE_ONE_VF: + mask = ATTR_FLAG_ONEVF; + break; + case SRIOV_VF_MODE_MULTI_VF: + mask = 0; + break; + case SRIOV_VF_MODE_BARE_METAL: + default: + mask = ATTR_FLAG_MASK_ALL; + break; + } + + ret = amdgpu_device_attr_create_groups(adev, + amdgpu_device_attrs, + ARRAY_SIZE(amdgpu_device_attrs), + mask, + &adev->pm.pm_attr_list); + if (ret) + return ret; + + adev->pm.sysfs_initialized = true; + + return 0; +} + +void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) +{ + if (adev->pm.dpm_enabled == 0) + return; + + if (adev->pm.int_hwmon_dev) + hwmon_device_unregister(adev->pm.int_hwmon_dev); + + amdgpu_device_attr_remove_groups(adev, &adev->pm.pm_attr_list); +} + +/* + * Debugfs info + */ +#if defined(CONFIG_DEBUG_FS) + +static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) +{ + uint32_t value; + uint64_t value64; + uint32_t query = 0; + int size; + + /* GPU Clocks */ + size = sizeof(value); + seq_printf(m, "GFX Clocks and Power:\n"); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (MCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (SCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (PSTATE_SCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (PSTATE_MCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&value, &size)) + seq_printf(m, "\t%u mV (VDDGFX)\n", value); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&value, &size)) + seq_printf(m, "\t%u mV (VDDNB)\n", value); + size = sizeof(uint32_t); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size)) + seq_printf(m, "\t%u.%u W (average GPU)\n", query >> 8, query & 0xff); + size = sizeof(value); + seq_printf(m, "\n"); + + /* GPU Temp */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_TEMP, (void *)&value, &size)) + seq_printf(m, "GPU Temperature: %u C\n", value/1000); + + /* GPU Load */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_LOAD, (void *)&value, &size)) + seq_printf(m, "GPU Load: %u %%\n", value); + /* MEM Load */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MEM_LOAD, (void *)&value, &size)) + seq_printf(m, "MEM Load: %u %%\n", value); + + seq_printf(m, "\n"); + + /* SMC feature mask */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size)) + seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64); + + if (adev->asic_type > CHIP_VEGA20) { + /* VCN clocks */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) { + if (!value) { + seq_printf(m, "VCN: Disabled\n"); + } else { + seq_printf(m, "VCN: Enabled\n"); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (DCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (VCLK)\n", value/100); + } + } + seq_printf(m, "\n"); + } else { + /* UVD clocks */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_POWER, (void *)&value, &size)) { + if (!value) { + seq_printf(m, "UVD: Disabled\n"); + } else { + seq_printf(m, "UVD: Enabled\n"); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_DCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (DCLK)\n", value/100); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_UVD_VCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (VCLK)\n", value/100); + } + } + seq_printf(m, "\n"); + + /* VCE clocks */ + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_POWER, (void *)&value, &size)) { + if (!value) { + seq_printf(m, "VCE: Disabled\n"); + } else { + seq_printf(m, "VCE: Enabled\n"); + if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCE_ECCLK, (void *)&value, &size)) + seq_printf(m, "\t%u MHz (ECCLK)\n", value/100); + } + } + } + + return 0; +} + +static void amdgpu_parse_cg_state(struct seq_file *m, u32 flags) +{ + int i; + + for (i = 0; clocks[i].flag; i++) + seq_printf(m, "\t%s: %s\n", clocks[i].name, + (flags & clocks[i].flag) ? "On" : "Off"); +} + +static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct amdgpu_device *adev = dev->dev_private; + u32 flags = 0; + int r; + + if (adev->in_gpu_reset) + return -EPERM; + + r = pm_runtime_get_sync(dev->dev); + if (r < 0) { + pm_runtime_put_autosuspend(dev->dev); + return r; + } + + if (!adev->pm.dpm_enabled) { + seq_printf(m, "dpm not enabled\n"); + pm_runtime_mark_last_busy(dev->dev); + pm_runtime_put_autosuspend(dev->dev); + return 0; + } + + if (!is_support_sw_smu(adev) && + adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { + mutex_lock(&adev->pm.mutex); + if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) + adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); + else + seq_printf(m, "Debugfs support not implemented for this asic\n"); + mutex_unlock(&adev->pm.mutex); + r = 0; + } else { + r = amdgpu_debugfs_pm_info_pp(m, adev); + } + if (r) + goto out; + + amdgpu_device_ip_get_clockgating_state(adev, &flags); + + 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); + + return r; +} + +static const struct drm_info_list amdgpu_pm_info_list[] = { + {"amdgpu_pm_info", amdgpu_debugfs_pm_info, 0, NULL}, +}; +#endif + +int amdgpu_debugfs_pm_init(struct amdgpu_device *adev) +{ +#if defined(CONFIG_DEBUG_FS) + return amdgpu_debugfs_add_files(adev, amdgpu_pm_info_list, ARRAY_SIZE(amdgpu_pm_info_list)); +#else + return 0; +#endif +} diff --git a/drivers/gpu/drm/amd/pm/inc/amd_powerplay.h b/drivers/gpu/drm/amd/pm/inc/amd_powerplay.h new file mode 100644 index 000000000000..fe3665965416 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/amd_powerplay.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 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 _AMD_POWERPLAY_H_ +#define _AMD_POWERPLAY_H_ + +#include +#include +#include +#include "amd_shared.h" +#include "cgs_common.h" +#include "dm_pp_interface.h" +#include "kgd_pp_interface.h" +#include "amdgpu.h" + +#endif /* _AMD_POWERPLAY_H_ */ diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h new file mode 100644 index 000000000000..dff4a5f99bb0 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h @@ -0,0 +1,565 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __AMDGPU_DPM_H__ +#define __AMDGPU_DPM_H__ + +enum amdgpu_int_thermal_type { + THERMAL_TYPE_NONE, + THERMAL_TYPE_EXTERNAL, + THERMAL_TYPE_EXTERNAL_GPIO, + THERMAL_TYPE_RV6XX, + THERMAL_TYPE_RV770, + THERMAL_TYPE_ADT7473_WITH_INTERNAL, + THERMAL_TYPE_EVERGREEN, + THERMAL_TYPE_SUMO, + THERMAL_TYPE_NI, + THERMAL_TYPE_SI, + THERMAL_TYPE_EMC2103_WITH_INTERNAL, + THERMAL_TYPE_CI, + THERMAL_TYPE_KV, +}; + +enum amdgpu_dpm_auto_throttle_src { + AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, + AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL +}; + +enum amdgpu_dpm_event_src { + AMDGPU_DPM_EVENT_SRC_ANALOG = 0, + AMDGPU_DPM_EVENT_SRC_EXTERNAL = 1, + AMDGPU_DPM_EVENT_SRC_DIGITAL = 2, + AMDGPU_DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, + AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL = 4 +}; + +struct amdgpu_ps { + u32 caps; /* vbios flags */ + u32 class; /* vbios flags */ + u32 class2; /* vbios flags */ + /* UVD clocks */ + u32 vclk; + u32 dclk; + /* VCE clocks */ + u32 evclk; + u32 ecclk; + bool vce_active; + enum amd_vce_level vce_level; + /* asic priv */ + void *ps_priv; +}; + +struct amdgpu_dpm_thermal { + /* thermal interrupt work */ + struct work_struct work; + /* low temperature threshold */ + int min_temp; + /* high temperature threshold */ + int max_temp; + /* edge max emergency(shutdown) temp */ + int max_edge_emergency_temp; + /* hotspot low temperature threshold */ + int min_hotspot_temp; + /* hotspot high temperature critical threshold */ + int max_hotspot_crit_temp; + /* hotspot max emergency(shutdown) temp */ + int max_hotspot_emergency_temp; + /* memory low temperature threshold */ + int min_mem_temp; + /* memory high temperature critical threshold */ + int max_mem_crit_temp; + /* memory max emergency(shutdown) temp */ + int max_mem_emergency_temp; + /* was last interrupt low to high or high to low */ + bool high_to_low; + /* interrupt source */ + struct amdgpu_irq_src irq; +}; + +enum amdgpu_clk_action +{ + AMDGPU_SCLK_UP = 1, + AMDGPU_SCLK_DOWN +}; + +struct amdgpu_blacklist_clocks +{ + u32 sclk; + u32 mclk; + enum amdgpu_clk_action action; +}; + +struct amdgpu_clock_and_voltage_limits { + u32 sclk; + u32 mclk; + u16 vddc; + u16 vddci; +}; + +struct amdgpu_clock_array { + u32 count; + u32 *values; +}; + +struct amdgpu_clock_voltage_dependency_entry { + u32 clk; + u16 v; +}; + +struct amdgpu_clock_voltage_dependency_table { + u32 count; + struct amdgpu_clock_voltage_dependency_entry *entries; +}; + +union amdgpu_cac_leakage_entry { + struct { + u16 vddc; + u32 leakage; + }; + struct { + u16 vddc1; + u16 vddc2; + u16 vddc3; + }; +}; + +struct amdgpu_cac_leakage_table { + u32 count; + union amdgpu_cac_leakage_entry *entries; +}; + +struct amdgpu_phase_shedding_limits_entry { + u16 voltage; + u32 sclk; + u32 mclk; +}; + +struct amdgpu_phase_shedding_limits_table { + u32 count; + struct amdgpu_phase_shedding_limits_entry *entries; +}; + +struct amdgpu_uvd_clock_voltage_dependency_entry { + u32 vclk; + u32 dclk; + u16 v; +}; + +struct amdgpu_uvd_clock_voltage_dependency_table { + u8 count; + struct amdgpu_uvd_clock_voltage_dependency_entry *entries; +}; + +struct amdgpu_vce_clock_voltage_dependency_entry { + u32 ecclk; + u32 evclk; + u16 v; +}; + +struct amdgpu_vce_clock_voltage_dependency_table { + u8 count; + struct amdgpu_vce_clock_voltage_dependency_entry *entries; +}; + +struct amdgpu_ppm_table { + u8 ppm_design; + u16 cpu_core_number; + u32 platform_tdp; + u32 small_ac_platform_tdp; + u32 platform_tdc; + u32 small_ac_platform_tdc; + u32 apu_tdp; + u32 dgpu_tdp; + u32 dgpu_ulv_power; + u32 tj_max; +}; + +struct amdgpu_cac_tdp_table { + u16 tdp; + u16 configurable_tdp; + u16 tdc; + u16 battery_power_limit; + u16 small_power_limit; + u16 low_cac_leakage; + u16 high_cac_leakage; + u16 maximum_power_delivery_limit; +}; + +struct amdgpu_dpm_dynamic_state { + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_sclk; + struct amdgpu_clock_voltage_dependency_table vddci_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table mvdd_dependency_on_mclk; + struct amdgpu_clock_voltage_dependency_table vddc_dependency_on_dispclk; + struct amdgpu_uvd_clock_voltage_dependency_table uvd_clock_voltage_dependency_table; + struct amdgpu_vce_clock_voltage_dependency_table vce_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table samu_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table acp_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table vddgfx_dependency_on_sclk; + struct amdgpu_clock_array valid_sclk_values; + struct amdgpu_clock_array valid_mclk_values; + struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_dc; + struct amdgpu_clock_and_voltage_limits max_clock_voltage_on_ac; + u32 mclk_sclk_ratio; + u32 sclk_mclk_delta; + u16 vddc_vddci_delta; + u16 min_vddc_for_pcie_gen2; + struct amdgpu_cac_leakage_table cac_leakage_table; + struct amdgpu_phase_shedding_limits_table phase_shedding_limits_table; + struct amdgpu_ppm_table *ppm_table; + struct amdgpu_cac_tdp_table *cac_tdp_table; +}; + +struct amdgpu_dpm_fan { + u16 t_min; + u16 t_med; + u16 t_high; + u16 pwm_min; + u16 pwm_med; + u16 pwm_high; + u8 t_hyst; + u32 cycle_delay; + u16 t_max; + u8 control_mode; + u16 default_max_fan_pwm; + u16 default_fan_output_sensitivity; + u16 fan_output_sensitivity; + bool ucode_fan_control; +}; + +enum amdgpu_pcie_gen { + AMDGPU_PCIE_GEN1 = 0, + AMDGPU_PCIE_GEN2 = 1, + AMDGPU_PCIE_GEN3 = 2, + AMDGPU_PCIE_GEN_INVALID = 0xffff +}; + +#define amdgpu_dpm_pre_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->pre_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_post_set_power_state(adev) \ + ((adev)->powerplay.pp_funcs->post_set_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_display_configuration_changed(adev) \ + ((adev)->powerplay.pp_funcs->display_configuration_changed((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_print_power_state(adev, ps) \ + ((adev)->powerplay.pp_funcs->print_power_state((adev)->powerplay.pp_handle, (ps))) + +#define amdgpu_dpm_vblank_too_short(adev) \ + ((adev)->powerplay.pp_funcs->vblank_too_short((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_enable_bapm(adev, e) \ + ((adev)->powerplay.pp_funcs->enable_bapm((adev)->powerplay.pp_handle, (e))) + +#define amdgpu_dpm_set_fan_control_mode(adev, m) \ + ((adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m))) + +#define amdgpu_dpm_get_fan_control_mode(adev) \ + ((adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ + ((adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s))) + +#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ + ((adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s))) + +#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \ + ((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) + +#define amdgpu_dpm_set_fan_speed_rpm(adev, s) \ + ((adev)->powerplay.pp_funcs->set_fan_speed_rpm)((adev)->powerplay.pp_handle, (s)) + +#define amdgpu_dpm_force_performance_level(adev, l) \ + ((adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l))) + +#define amdgpu_dpm_get_current_power_state(adev) \ + ((adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_get_pp_num_states(adev, data) \ + ((adev)->powerplay.pp_funcs->get_pp_num_states((adev)->powerplay.pp_handle, data)) + +#define amdgpu_dpm_get_pp_table(adev, table) \ + ((adev)->powerplay.pp_funcs->get_pp_table((adev)->powerplay.pp_handle, table)) + +#define amdgpu_dpm_set_pp_table(adev, buf, size) \ + ((adev)->powerplay.pp_funcs->set_pp_table((adev)->powerplay.pp_handle, buf, size)) + +#define amdgpu_dpm_print_clock_levels(adev, type, buf) \ + ((adev)->powerplay.pp_funcs->print_clock_levels((adev)->powerplay.pp_handle, type, buf)) + +#define amdgpu_dpm_force_clock_level(adev, type, level) \ + ((adev)->powerplay.pp_funcs->force_clock_level((adev)->powerplay.pp_handle, type, level)) + +#define amdgpu_dpm_get_sclk_od(adev) \ + ((adev)->powerplay.pp_funcs->get_sclk_od((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_sclk_od(adev, value) \ + ((adev)->powerplay.pp_funcs->set_sclk_od((adev)->powerplay.pp_handle, value)) + +#define amdgpu_dpm_get_mclk_od(adev) \ + ((adev)->powerplay.pp_funcs->get_mclk_od((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_set_mclk_od(adev, value) \ + ((adev)->powerplay.pp_funcs->set_mclk_od((adev)->powerplay.pp_handle, value)) + +#define amdgpu_dpm_dispatch_task(adev, task_id, user_state) \ + ((adev)->powerplay.pp_funcs->dispatch_tasks)((adev)->powerplay.pp_handle, (task_id), (user_state)) + +#define amdgpu_dpm_check_state_equal(adev, cps, rps, equal) \ + ((adev)->powerplay.pp_funcs->check_state_equal((adev)->powerplay.pp_handle, (cps), (rps), (equal))) + +#define amdgpu_dpm_get_vce_clock_state(adev, i) \ + ((adev)->powerplay.pp_funcs->get_vce_clock_state((adev)->powerplay.pp_handle, (i))) + +#define amdgpu_dpm_get_performance_level(adev) \ + ((adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle)) + +#define amdgpu_dpm_reset_power_profile_state(adev, request) \ + ((adev)->powerplay.pp_funcs->reset_power_profile_state(\ + (adev)->powerplay.pp_handle, request)) + +#define amdgpu_dpm_get_power_profile_mode(adev, buf) \ + ((adev)->powerplay.pp_funcs->get_power_profile_mode(\ + (adev)->powerplay.pp_handle, buf)) + +#define amdgpu_dpm_set_power_profile_mode(adev, parameter, size) \ + ((adev)->powerplay.pp_funcs->set_power_profile_mode(\ + (adev)->powerplay.pp_handle, parameter, size)) + +#define amdgpu_dpm_odn_edit_dpm_table(adev, type, parameter, size) \ + ((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\ + (adev)->powerplay.pp_handle, type, parameter, size)) + +#define amdgpu_dpm_get_ppfeature_status(adev, buf) \ + ((adev)->powerplay.pp_funcs->get_ppfeature_status(\ + (adev)->powerplay.pp_handle, (buf))) + +#define amdgpu_dpm_set_ppfeature_status(adev, ppfeatures) \ + ((adev)->powerplay.pp_funcs->set_ppfeature_status(\ + (adev)->powerplay.pp_handle, (ppfeatures))) + +#define amdgpu_dpm_get_gpu_metrics(adev, table) \ + ((adev)->powerplay.pp_funcs->get_gpu_metrics((adev)->powerplay.pp_handle, table)) + +struct amdgpu_dpm { + struct amdgpu_ps *ps; + /* number of valid power states */ + int num_ps; + /* current power state that is active */ + struct amdgpu_ps *current_ps; + /* requested power state */ + struct amdgpu_ps *requested_ps; + /* boot up power state */ + struct amdgpu_ps *boot_ps; + /* default uvd power state */ + struct amdgpu_ps *uvd_ps; + /* vce requirements */ + u32 num_of_vce_states; + struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; + enum amd_vce_level vce_level; + enum amd_pm_state_type state; + enum amd_pm_state_type user_state; + enum amd_pm_state_type last_state; + enum amd_pm_state_type last_user_state; + u32 platform_caps; + u32 voltage_response_time; + u32 backbias_response_time; + void *priv; + u32 new_active_crtcs; + int new_active_crtc_count; + u32 current_active_crtcs; + int current_active_crtc_count; + struct amdgpu_dpm_dynamic_state dyn_state; + struct amdgpu_dpm_fan fan; + u32 tdp_limit; + u32 near_tdp_limit; + u32 near_tdp_limit_adjusted; + u32 sq_ramping_threshold; + u32 cac_leakage; + u16 tdp_od_limit; + u32 tdp_adjustment; + u16 load_line_slope; + bool power_control; + /* special states active */ + bool thermal_active; + bool uvd_active; + bool vce_active; + /* thermal handling */ + struct amdgpu_dpm_thermal thermal; + /* forced levels */ + enum amd_dpm_forced_level forced_level; +}; + +struct amdgpu_pm { + struct mutex mutex; + u32 current_sclk; + u32 current_mclk; + u32 default_sclk; + u32 default_mclk; + struct amdgpu_i2c_chan *i2c_bus; + bool bus_locked; + /* internal thermal controller on rv6xx+ */ + enum amdgpu_int_thermal_type int_thermal_type; + struct device *int_hwmon_dev; + /* fan control parameters */ + bool no_fan; + u8 fan_pulses_per_revolution; + u8 fan_min_rpm; + u8 fan_max_rpm; + /* dpm */ + bool dpm_enabled; + bool sysfs_initialized; + struct amdgpu_dpm dpm; + const struct firmware *fw; /* SMC firmware */ + uint32_t fw_version; + uint32_t pcie_gen_mask; + uint32_t pcie_mlw_mask; + struct amd_pp_display_configuration pm_display_cfg;/* set by dc */ + uint32_t smu_prv_buffer_size; + struct amdgpu_bo *smu_prv_buffer; + bool ac_power; + /* powerplay feature */ + uint32_t pp_feature; + + /* Used for I2C access to various EEPROMs on relevant ASICs */ + struct i2c_adapter smu_i2c; + struct list_head pm_attr_list; +}; + +#define R600_SSTU_DFLT 0 +#define R600_SST_DFLT 0x00C8 + +/* XXX are these ok? */ +#define R600_TEMP_RANGE_MIN (90 * 1000) +#define R600_TEMP_RANGE_MAX (120 * 1000) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +enum amdgpu_td { + AMDGPU_TD_AUTO, + AMDGPU_TD_UP, + AMDGPU_TD_DOWN, +}; + +enum amdgpu_display_watermark { + AMDGPU_DISPLAY_WATERMARK_LOW = 0, + AMDGPU_DISPLAY_WATERMARK_HIGH = 1, +}; + +enum amdgpu_display_gap +{ + AMDGPU_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, + AMDGPU_PM_DISPLAY_GAP_VBLANK = 1, + AMDGPU_PM_DISPLAY_GAP_WATERMARK = 2, + AMDGPU_PM_DISPLAY_GAP_IGNORE = 3, +}; + +void amdgpu_dpm_print_class_info(u32 class, u32 class2); +void amdgpu_dpm_print_cap_info(u32 caps); +void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, + struct amdgpu_ps *rps); +u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev); +u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev); +void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev); +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size); + +bool amdgpu_is_internal_thermal_sensor(enum amdgpu_int_thermal_type sensor); + +int amdgpu_get_platform_caps(struct amdgpu_device *adev); + +int amdgpu_parse_extended_power_table(struct amdgpu_device *adev); +void amdgpu_free_extended_power_table(struct amdgpu_device *adev); + +void amdgpu_add_thermal_controller(struct amdgpu_device *adev); + +enum amdgpu_pcie_gen amdgpu_get_pcie_gen_support(struct amdgpu_device *adev, + u32 sys_mask, + enum amdgpu_pcie_gen asic_gen, + enum amdgpu_pcie_gen default_gen); + +struct amd_vce_state* +amdgpu_get_vce_clock_state(void *handle, u32 idx); + +int amdgpu_dpm_set_powergating_by_smu(struct amdgpu_device *adev, + uint32_t block_type, bool gate); + +extern int amdgpu_dpm_get_sclk(struct amdgpu_device *adev, bool low); + +extern int amdgpu_dpm_get_mclk(struct amdgpu_device *adev, bool low); + +int amdgpu_dpm_set_xgmi_pstate(struct amdgpu_device *adev, + uint32_t pstate); + +int amdgpu_dpm_switch_power_profile(struct amdgpu_device *adev, + enum PP_SMC_POWER_PROFILE type, + bool en); + +int amdgpu_dpm_baco_reset(struct amdgpu_device *adev); + +int amdgpu_dpm_mode2_reset(struct amdgpu_device *adev); + +bool amdgpu_dpm_is_baco_supported(struct amdgpu_device *adev); + +bool amdgpu_dpm_is_mode1_reset_supported(struct amdgpu_device *adev); +int amdgpu_dpm_mode1_reset(struct amdgpu_device *adev); + +int amdgpu_dpm_set_mp1_state(struct amdgpu_device *adev, + enum pp_mp1_state mp1_state); + +int amdgpu_dpm_baco_exit(struct amdgpu_device *adev); + +int amdgpu_dpm_baco_enter(struct amdgpu_device *adev); + +int amdgpu_dpm_set_df_cstate(struct amdgpu_device *adev, + uint32_t cstate); + +int amdgpu_dpm_allow_xgmi_power_down(struct amdgpu_device *adev, bool en); + +int amdgpu_dpm_enable_mgpu_fan_boost(struct amdgpu_device *adev); + +int amdgpu_dpm_set_clockgating_by_smu(struct amdgpu_device *adev, + uint32_t msg_id); + +int amdgpu_dpm_smu_i2c_bus_access(struct amdgpu_device *adev, + bool acquire); + +void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); + +int amdgpu_dpm_read_sensor(struct amdgpu_device *adev, enum amd_pp_sensors sensor, + void *data, uint32_t *size); + +void amdgpu_dpm_thermal_work_handler(struct work_struct *work); + +void amdgpu_pm_compute_clocks(struct amdgpu_device *adev); +void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable); +void amdgpu_dpm_enable_jpeg(struct amdgpu_device *adev, bool enable); +void amdgpu_pm_print_power_states(struct amdgpu_device *adev); +int amdgpu_pm_load_smu_firmware(struct amdgpu_device *adev, uint32_t *smu_version); + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h new file mode 100644 index 000000000000..45a22e101d15 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_pm.h @@ -0,0 +1,89 @@ +/* + * Copyright 2014 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef __AMDGPU_PM_H__ +#define __AMDGPU_PM_H__ + +struct cg_flag_name +{ + u32 flag; + const char *name; +}; + +enum amdgpu_device_attr_flags { + ATTR_FLAG_BASIC = (1 << 0), + ATTR_FLAG_ONEVF = (1 << 16), +}; + +#define ATTR_FLAG_TYPE_MASK (0x0000ffff) +#define ATTR_FLAG_MODE_MASK (0xffff0000) +#define ATTR_FLAG_MASK_ALL (0xffffffff) + +enum amdgpu_device_attr_states { + ATTR_STATE_UNSUPPORTED = 0, + ATTR_STATE_SUPPORTED, +}; + +struct amdgpu_device_attr { + struct device_attribute dev_attr; + enum amdgpu_device_attr_flags flags; + int (*attr_update)(struct amdgpu_device *adev, struct amdgpu_device_attr *attr, + uint32_t mask, enum amdgpu_device_attr_states *states); + +}; + +struct amdgpu_device_attr_entry { + struct list_head entry; + struct amdgpu_device_attr *attr; +}; + +#define to_amdgpu_device_attr(_dev_attr) \ + container_of(_dev_attr, struct amdgpu_device_attr, dev_attr) + +#define __AMDGPU_DEVICE_ATTR(_name, _mode, _show, _store, _flags, ...) \ + { .dev_attr = __ATTR(_name, _mode, _show, _store), \ + .flags = _flags, \ + ##__VA_ARGS__, } + +#define AMDGPU_DEVICE_ATTR(_name, _mode, _flags, ...) \ + __AMDGPU_DEVICE_ATTR(_name, _mode, \ + amdgpu_get_##_name, amdgpu_set_##_name, \ + _flags, ##__VA_ARGS__) + +#define AMDGPU_DEVICE_ATTR_RW(_name, _flags, ...) \ + AMDGPU_DEVICE_ATTR(_name, S_IRUGO | S_IWUSR, \ + _flags, ##__VA_ARGS__) + +#define AMDGPU_DEVICE_ATTR_RO(_name, _flags, ...) \ + __AMDGPU_DEVICE_ATTR(_name, S_IRUGO, \ + amdgpu_get_##_name, NULL, \ + _flags, ##__VA_ARGS__) + +int amdgpu_pm_sysfs_init(struct amdgpu_device *adev); +int amdgpu_pm_virt_sysfs_init(struct amdgpu_device *adev); +void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev); +void amdgpu_pm_virt_sysfs_fini(struct amdgpu_device *adev); + +int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h new file mode 100644 index 000000000000..bbe4a343e9f1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -0,0 +1,806 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef __AMDGPU_SMU_H__ +#define __AMDGPU_SMU_H__ + +#include "amdgpu.h" +#include "kgd_pp_interface.h" +#include "dm_pp_interface.h" +#include "dm_pp_smu.h" +#include "smu_types.h" + +#define SMU_THERMAL_MINIMUM_ALERT_TEMP 0 +#define SMU_THERMAL_MAXIMUM_ALERT_TEMP 255 +#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 + +struct smu_hw_power_state { + unsigned int magic; +}; + +struct smu_power_state; + +enum smu_state_ui_label { + SMU_STATE_UI_LABEL_NONE, + SMU_STATE_UI_LABEL_BATTERY, + SMU_STATE_UI_TABEL_MIDDLE_LOW, + SMU_STATE_UI_LABEL_BALLANCED, + SMU_STATE_UI_LABEL_MIDDLE_HIGHT, + SMU_STATE_UI_LABEL_PERFORMANCE, + SMU_STATE_UI_LABEL_BACO, +}; + +enum smu_state_classification_flag { + SMU_STATE_CLASSIFICATION_FLAG_BOOT = 0x0001, + SMU_STATE_CLASSIFICATION_FLAG_THERMAL = 0x0002, + SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE = 0x0004, + SMU_STATE_CLASSIFICATION_FLAG_RESET = 0x0008, + SMU_STATE_CLASSIFICATION_FLAG_FORCED = 0x0010, + SMU_STATE_CLASSIFICATION_FLAG_USER_3D_PERFORMANCE = 0x0020, + SMU_STATE_CLASSIFICATION_FLAG_USER_2D_PERFORMANCE = 0x0040, + SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE = 0x0080, + SMU_STATE_CLASSIFICATION_FLAG_AC_OVERDIRVER_TEMPLATE = 0x0100, + SMU_STATE_CLASSIFICATION_FLAG_UVD = 0x0200, + SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE_LOW = 0x0400, + SMU_STATE_CLASSIFICATION_FLAG_ACPI = 0x0800, + SMU_STATE_CLASSIFICATION_FLAG_HD2 = 0x1000, + SMU_STATE_CLASSIFICATION_FLAG_UVD_HD = 0x2000, + SMU_STATE_CLASSIFICATION_FLAG_UVD_SD = 0x4000, + SMU_STATE_CLASSIFICATION_FLAG_USER_DC_PERFORMANCE = 0x8000, + SMU_STATE_CLASSIFICATION_FLAG_DC_OVERDIRVER_TEMPLATE = 0x10000, + SMU_STATE_CLASSIFICATION_FLAG_BACO = 0x20000, + SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE2 = 0x40000, + SMU_STATE_CLASSIFICATION_FLAG_ULV = 0x80000, + SMU_STATE_CLASSIFICATION_FLAG_UVD_MVC = 0x100000, +}; + +struct smu_state_classification_block { + enum smu_state_ui_label ui_label; + enum smu_state_classification_flag flags; + int bios_index; + bool temporary_state; + bool to_be_deleted; +}; + +struct smu_state_pcie_block { + unsigned int lanes; +}; + +enum smu_refreshrate_source { + SMU_REFRESHRATE_SOURCE_EDID, + SMU_REFRESHRATE_SOURCE_EXPLICIT +}; + +struct smu_state_display_block { + bool disable_frame_modulation; + bool limit_refreshrate; + enum smu_refreshrate_source refreshrate_source; + int explicit_refreshrate; + int edid_refreshrate_index; + bool enable_vari_bright; +}; + +struct smu_state_memroy_block { + bool dll_off; + uint8_t m3arb; + uint8_t unused[3]; +}; + +struct smu_state_software_algorithm_block { + bool disable_load_balancing; + bool enable_sleep_for_timestamps; +}; + +struct smu_temperature_range { + int min; + int max; + int edge_emergency_max; + int hotspot_min; + int hotspot_crit_max; + int hotspot_emergency_max; + int mem_min; + int mem_crit_max; + int mem_emergency_max; + int software_shutdown_temp; +}; + +struct smu_state_validation_block { + bool single_display_only; + bool disallow_on_dc; + uint8_t supported_power_levels; +}; + +struct smu_uvd_clocks { + uint32_t vclk; + uint32_t dclk; +}; + +/** +* Structure to hold a SMU Power State. +*/ +struct smu_power_state { + uint32_t id; + struct list_head ordered_list; + struct list_head all_states_list; + + struct smu_state_classification_block classification; + struct smu_state_validation_block validation; + struct smu_state_pcie_block pcie; + struct smu_state_display_block display; + struct smu_state_memroy_block memory; + struct smu_state_software_algorithm_block software; + struct smu_uvd_clocks uvd_clocks; + struct smu_hw_power_state hardware; +}; + +enum smu_power_src_type +{ + SMU_POWER_SOURCE_AC, + SMU_POWER_SOURCE_DC, + SMU_POWER_SOURCE_COUNT, +}; + +enum smu_memory_pool_size +{ + SMU_MEMORY_POOL_SIZE_ZERO = 0, + SMU_MEMORY_POOL_SIZE_256_MB = 0x10000000, + SMU_MEMORY_POOL_SIZE_512_MB = 0x20000000, + SMU_MEMORY_POOL_SIZE_1_GB = 0x40000000, + SMU_MEMORY_POOL_SIZE_2_GB = 0x80000000, +}; + +#define SMU_TABLE_INIT(tables, table_id, s, a, d) \ + do { \ + tables[table_id].size = s; \ + tables[table_id].align = a; \ + tables[table_id].domain = d; \ + } while (0) + +struct smu_table { + uint64_t size; + uint32_t align; + uint8_t domain; + uint64_t mc_address; + void *cpu_addr; + struct amdgpu_bo *bo; +}; + +enum smu_perf_level_designation { + PERF_LEVEL_ACTIVITY, + PERF_LEVEL_POWER_CONTAINMENT, +}; + +struct smu_performance_level { + uint32_t core_clock; + uint32_t memory_clock; + uint32_t vddc; + uint32_t vddci; + uint32_t non_local_mem_freq; + uint32_t non_local_mem_width; +}; + +struct smu_clock_info { + uint32_t min_mem_clk; + uint32_t max_mem_clk; + uint32_t min_eng_clk; + uint32_t max_eng_clk; + uint32_t min_bus_bandwidth; + uint32_t max_bus_bandwidth; +}; + +struct smu_bios_boot_up_values +{ + uint32_t revision; + uint32_t gfxclk; + uint32_t uclk; + uint32_t socclk; + uint32_t dcefclk; + uint32_t eclk; + uint32_t vclk; + uint32_t dclk; + uint16_t vddc; + uint16_t vddci; + uint16_t mvddc; + uint16_t vdd_gfx; + uint8_t cooling_id; + uint32_t pp_table_id; + uint32_t format_revision; + uint32_t content_revision; + uint32_t fclk; +}; + +enum smu_table_id +{ + SMU_TABLE_PPTABLE = 0, + SMU_TABLE_WATERMARKS, + SMU_TABLE_CUSTOM_DPM, + SMU_TABLE_DPMCLOCKS, + SMU_TABLE_AVFS, + SMU_TABLE_AVFS_PSM_DEBUG, + SMU_TABLE_AVFS_FUSE_OVERRIDE, + SMU_TABLE_PMSTATUSLOG, + SMU_TABLE_SMU_METRICS, + SMU_TABLE_DRIVER_SMU_CONFIG, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + SMU_TABLE_OVERDRIVE, + SMU_TABLE_I2C_COMMANDS, + SMU_TABLE_PACE, + SMU_TABLE_COUNT, +}; + +struct smu_table_context +{ + void *power_play_table; + uint32_t power_play_table_size; + void *hardcode_pptable; + unsigned long metrics_time; + void *metrics_table; + void *clocks_table; + void *watermarks_table; + + void *max_sustainable_clocks; + struct smu_bios_boot_up_values boot_values; + void *driver_pptable; + struct smu_table tables[SMU_TABLE_COUNT]; + /* + * The driver table is just a staging buffer for + * uploading/downloading content from the SMU. + * + * And the table_id for SMU_MSG_TransferTableSmu2Dram/ + * SMU_MSG_TransferTableDram2Smu instructs SMU + * which content driver is interested. + */ + struct smu_table driver_table; + struct smu_table memory_pool; + uint8_t thermal_controller_type; + + void *overdrive_table; + void *boot_overdrive_table; + + uint32_t gpu_metrics_table_size; + void *gpu_metrics_table; +}; + +struct smu_dpm_context { + uint32_t dpm_context_size; + void *dpm_context; + void *golden_dpm_context; + bool enable_umd_pstate; + enum amd_dpm_forced_level dpm_level; + enum amd_dpm_forced_level saved_dpm_level; + enum amd_dpm_forced_level requested_dpm_level; + struct smu_power_state *dpm_request_power_state; + struct smu_power_state *dpm_current_power_state; + struct mclock_latency_table *mclk_latency_table; +}; + +struct smu_power_gate { + bool uvd_gated; + bool vce_gated; + atomic_t vcn_gated; + atomic_t jpeg_gated; + struct mutex vcn_gate_lock; + struct mutex jpeg_gate_lock; +}; + +struct smu_power_context { + void *power_context; + uint32_t power_context_size; + struct smu_power_gate power_gate; +}; + + +#define SMU_FEATURE_MAX (64) +struct smu_feature +{ + uint32_t feature_num; + DECLARE_BITMAP(supported, SMU_FEATURE_MAX); + DECLARE_BITMAP(allowed, SMU_FEATURE_MAX); + DECLARE_BITMAP(enabled, SMU_FEATURE_MAX); + struct mutex mutex; +}; + +struct smu_clocks { + uint32_t engine_clock; + uint32_t memory_clock; + uint32_t bus_bandwidth; + uint32_t engine_clock_in_sr; + uint32_t dcef_clock; + uint32_t dcef_clock_in_sr; +}; + +#define MAX_REGULAR_DPM_NUM 16 +struct mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; +struct mclock_latency_table { + uint32_t count; + struct mclk_latency_entries entries[MAX_REGULAR_DPM_NUM]; +}; + +enum smu_reset_mode +{ + SMU_RESET_MODE_0, + SMU_RESET_MODE_1, + SMU_RESET_MODE_2, +}; + +enum smu_baco_state +{ + SMU_BACO_STATE_ENTER = 0, + SMU_BACO_STATE_EXIT, +}; + +struct smu_baco_context +{ + struct mutex mutex; + uint32_t state; + bool platform_support; +}; + +struct pstates_clk_freq { + uint32_t min; + uint32_t standard; + uint32_t peak; +}; + +struct smu_umd_pstate_table { + struct pstates_clk_freq gfxclk_pstate; + struct pstates_clk_freq socclk_pstate; + struct pstates_clk_freq uclk_pstate; + struct pstates_clk_freq vclk_pstate; + struct pstates_clk_freq dclk_pstate; +}; + +struct cmn2asic_msg_mapping { + int valid_mapping; + int map_to; + int valid_in_vf; +}; + +struct cmn2asic_mapping { + int valid_mapping; + int map_to; +}; + +#define WORKLOAD_POLICY_MAX 7 +struct smu_context +{ + struct amdgpu_device *adev; + struct amdgpu_irq_src irq_source; + + const struct pptable_funcs *ppt_funcs; + const struct cmn2asic_msg_mapping *message_map; + const struct cmn2asic_mapping *clock_map; + const struct cmn2asic_mapping *feature_map; + const struct cmn2asic_mapping *table_map; + const struct cmn2asic_mapping *pwr_src_map; + const struct cmn2asic_mapping *workload_map; + struct mutex mutex; + struct mutex sensor_lock; + struct mutex metrics_lock; + struct mutex message_lock; + uint64_t pool_size; + + struct smu_table_context smu_table; + struct smu_dpm_context smu_dpm; + struct smu_power_context smu_power; + struct smu_feature smu_feature; + struct amd_pp_display_configuration *display_config; + struct smu_baco_context smu_baco; + struct smu_temperature_range thermal_range; + void *od_settings; +#if defined(CONFIG_DEBUG_FS) + struct dentry *debugfs_sclk; +#endif + + struct smu_umd_pstate_table pstate_table; + uint32_t pstate_sclk; + uint32_t pstate_mclk; + + bool od_enabled; + uint32_t current_power_limit; + uint32_t max_power_limit; + + /* soft pptable */ + uint32_t ppt_offset_bytes; + uint32_t ppt_size_bytes; + uint8_t *ppt_start_addr; + + bool support_power_containment; + bool disable_watermark; + +#define WATERMARKS_EXIST (1 << 0) +#define WATERMARKS_LOADED (1 << 1) + uint32_t watermarks_bitmap; + uint32_t hard_min_uclk_req_from_dal; + bool disable_uclk_switch; + + uint32_t workload_mask; + uint32_t workload_prority[WORKLOAD_POLICY_MAX]; + uint32_t workload_setting[WORKLOAD_POLICY_MAX]; + uint32_t power_profile_mode; + uint32_t default_power_profile_mode; + bool pm_enabled; + bool is_apu; + + uint32_t smc_driver_if_version; + uint32_t smc_fw_if_version; + uint32_t smc_fw_version; + + bool uploading_custom_pp_table; + bool dc_controlled_by_gpio; + + struct work_struct throttling_logging_work; + atomic64_t throttle_int_counter; +}; + +struct i2c_adapter; + +struct pptable_funcs { + int (*run_btc)(struct smu_context *smu); + int (*get_allowed_feature_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); + enum amd_pm_state_type (*get_current_power_state)(struct smu_context *smu); + int (*set_default_dpm_table)(struct smu_context *smu); + int (*set_power_state)(struct smu_context *smu); + int (*populate_umd_state_clk)(struct smu_context *smu); + int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf); + int (*force_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t mask); + int (*set_default_od8_settings)(struct smu_context *smu); + int (*get_od_percentage)(struct smu_context *smu, enum smu_clk_type clk_type); + int (*set_od_percentage)(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t value); + int (*od_edit_dpm_table)(struct smu_context *smu, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); + int (*get_clock_by_type_with_latency)(struct smu_context *smu, + enum smu_clk_type clk_type, + struct + pp_clock_levels_with_latency + *clocks); + int (*get_clock_by_type_with_voltage)(struct smu_context *smu, + enum amd_pp_clock_type type, + struct + pp_clock_levels_with_voltage + *clocks); + int (*get_power_profile_mode)(struct smu_context *smu, char *buf); + int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size); + int (*dpm_set_vcn_enable)(struct smu_context *smu, bool enable); + int (*dpm_set_jpeg_enable)(struct smu_context *smu, bool enable); + int (*read_sensor)(struct smu_context *smu, enum amd_pp_sensors sensor, + void *data, uint32_t *size); + int (*pre_display_config_changed)(struct smu_context *smu); + int (*display_config_changed)(struct smu_context *smu); + int (*apply_clocks_adjust_rules)(struct smu_context *smu); + int (*notify_smc_display_config)(struct smu_context *smu); + int (*set_cpu_power_state)(struct smu_context *smu); + bool (*is_dpm_running)(struct smu_context *smu); + int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); + int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); + int (*set_watermarks_table)(struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); + int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); + int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); + int (*set_default_od_settings)(struct smu_context *smu); + int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level); + int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch); + void (*dump_pptable)(struct smu_context *smu); + int (*get_power_limit)(struct smu_context *smu); + int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state); + int (*allow_xgmi_power_down)(struct smu_context *smu, bool en); + int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap); + int (*i2c_init)(struct smu_context *smu, struct i2c_adapter *control); + void (*i2c_fini)(struct smu_context *smu, struct i2c_adapter *control); + void (*get_unique_id)(struct smu_context *smu); + int (*get_dpm_clock_table)(struct smu_context *smu, struct dpm_clocks *clock_table); + int (*init_microcode)(struct smu_context *smu); + int (*load_microcode)(struct smu_context *smu); + void (*fini_microcode)(struct smu_context *smu); + int (*init_smc_tables)(struct smu_context *smu); + int (*fini_smc_tables)(struct smu_context *smu); + int (*init_power)(struct smu_context *smu); + int (*fini_power)(struct smu_context *smu); + int (*check_fw_status)(struct smu_context *smu); + int (*setup_pptable)(struct smu_context *smu); + int (*get_vbios_bootup_values)(struct smu_context *smu); + int (*check_fw_version)(struct smu_context *smu); + int (*powergate_sdma)(struct smu_context *smu, bool gate); + int (*set_gfx_cgpg)(struct smu_context *smu, bool enable); + int (*write_pptable)(struct smu_context *smu); + int (*set_driver_table_location)(struct smu_context *smu); + int (*set_tool_table_location)(struct smu_context *smu); + int (*notify_memory_pool_location)(struct smu_context *smu); + int (*set_last_dcef_min_deep_sleep_clk)(struct smu_context *smu); + int (*system_features_control)(struct smu_context *smu, bool en); + int (*send_smc_msg_with_param)(struct smu_context *smu, + enum smu_message_type msg, uint32_t param, uint32_t *read_arg); + int (*send_smc_msg)(struct smu_context *smu, + enum smu_message_type msg, + uint32_t *read_arg); + int (*init_display_count)(struct smu_context *smu, uint32_t count); + int (*set_allowed_mask)(struct smu_context *smu); + int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); + int (*feature_is_enabled)(struct smu_context *smu, enum smu_feature_mask mask); + int (*disable_all_features_with_exception)(struct smu_context *smu, enum smu_feature_mask mask); + int (*notify_display_change)(struct smu_context *smu); + int (*set_power_limit)(struct smu_context *smu, uint32_t n); + int (*init_max_sustainable_clocks)(struct smu_context *smu); + int (*enable_thermal_alert)(struct smu_context *smu); + int (*disable_thermal_alert)(struct smu_context *smu); + int (*set_min_dcef_deep_sleep)(struct smu_context *smu, uint32_t clk); + int (*set_active_display_count)(struct smu_context *smu, uint32_t count); + int (*store_cc6_data)(struct smu_context *smu, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, + bool pstate_switch_disable); + int (*get_clock_by_type)(struct smu_context *smu, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks); + int (*get_max_high_clocks)(struct smu_context *smu, + struct amd_pp_simple_clock_info *clocks); + int (*display_clock_voltage_request)(struct smu_context *smu, struct + pp_display_clock_request + *clock_req); + int (*get_dal_power_level)(struct smu_context *smu, + struct amd_pp_simple_clock_info *clocks); + int (*get_perf_level)(struct smu_context *smu, + enum smu_perf_level_designation designation, + struct smu_performance_level *level); + int (*get_current_shallow_sleep_clocks)(struct smu_context *smu, + struct smu_clock_info *clocks); + int (*notify_smu_enable_pwe)(struct smu_context *smu); + int (*conv_power_profile_to_pplib_workload)(int power_profile); + uint32_t (*get_fan_control_mode)(struct smu_context *smu); + int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode); + int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed); + int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed); + int (*set_xgmi_pstate)(struct smu_context *smu, uint32_t pstate); + int (*gfx_off_control)(struct smu_context *smu, bool enable); + uint32_t (*get_gfx_off_status)(struct smu_context *smu); + int (*register_irq_handler)(struct smu_context *smu); + int (*set_azalia_d3_pme)(struct smu_context *smu); + int (*get_max_sustainable_clocks_by_dc)(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); + bool (*baco_is_support)(struct smu_context *smu); + enum smu_baco_state (*baco_get_state)(struct smu_context *smu); + int (*baco_set_state)(struct smu_context *smu, enum smu_baco_state state); + int (*baco_enter)(struct smu_context *smu); + int (*baco_exit)(struct smu_context *smu); + bool (*mode1_reset_is_support)(struct smu_context *smu); + int (*mode1_reset)(struct smu_context *smu); + int (*mode2_reset)(struct smu_context *smu); + int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max); + int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max); + int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu); + int (*set_power_source)(struct smu_context *smu, enum smu_power_src_type power_src); + void (*log_thermal_throttling_event)(struct smu_context *smu); + size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); + int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); + ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); + int (*enable_mgpu_fan_boost)(struct smu_context *smu); +}; + +typedef enum { + METRICS_CURR_GFXCLK, + METRICS_CURR_SOCCLK, + METRICS_CURR_UCLK, + METRICS_CURR_VCLK, + METRICS_CURR_VCLK1, + METRICS_CURR_DCLK, + METRICS_CURR_DCLK1, + METRICS_CURR_FCLK, + METRICS_CURR_DCEFCLK, + METRICS_AVERAGE_GFXCLK, + METRICS_AVERAGE_SOCCLK, + METRICS_AVERAGE_FCLK, + METRICS_AVERAGE_UCLK, + METRICS_AVERAGE_VCLK, + METRICS_AVERAGE_DCLK, + METRICS_AVERAGE_GFXACTIVITY, + METRICS_AVERAGE_MEMACTIVITY, + METRICS_AVERAGE_VCNACTIVITY, + METRICS_AVERAGE_SOCKETPOWER, + METRICS_TEMPERATURE_EDGE, + METRICS_TEMPERATURE_HOTSPOT, + METRICS_TEMPERATURE_MEM, + METRICS_TEMPERATURE_VRGFX, + METRICS_TEMPERATURE_VRSOC, + METRICS_TEMPERATURE_VRMEM, + METRICS_THROTTLER_STATUS, + METRICS_CURR_FANSPEED, +} MetricsMember_t; + +enum smu_cmn2asic_mapping_type { + CMN2ASIC_MAPPING_MSG, + CMN2ASIC_MAPPING_CLK, + CMN2ASIC_MAPPING_FEATURE, + CMN2ASIC_MAPPING_TABLE, + CMN2ASIC_MAPPING_PWR, + CMN2ASIC_MAPPING_WORKLOAD, +}; + +#define MSG_MAP(msg, index, valid_in_vf) \ + [SMU_MSG_##msg] = {1, (index), (valid_in_vf)} + +#define CLK_MAP(clk, index) \ + [SMU_##clk] = {1, (index)} + +#define FEA_MAP(fea) \ + [SMU_FEATURE_##fea##_BIT] = {1, FEATURE_##fea##_BIT} + +#define TAB_MAP(tab) \ + [SMU_TABLE_##tab] = {1, TABLE_##tab} + +#define TAB_MAP_VALID(tab) \ + [SMU_TABLE_##tab] = {1, TABLE_##tab} + +#define TAB_MAP_INVALID(tab) \ + [SMU_TABLE_##tab] = {0, TABLE_##tab} + +#define PWR_MAP(tab) \ + [SMU_POWER_SOURCE_##tab] = {1, POWER_SOURCE_##tab} + +#define WORKLOAD_MAP(profile, workload) \ + [profile] = {1, (workload)} + +#if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4) +int smu_load_microcode(struct smu_context *smu); + +int smu_check_fw_status(struct smu_context *smu); + +int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled); + +int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); + +int smu_get_power_limit(struct smu_context *smu, + uint32_t *limit, + bool max_setting); + +int smu_set_power_limit(struct smu_context *smu, uint32_t limit); +int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf); +int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type); +int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value); + +int smu_od_edit_dpm_table(struct smu_context *smu, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); + +int smu_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size); +int smu_get_power_profile_mode(struct smu_context *smu, char *buf); + +int smu_set_power_profile_mode(struct smu_context *smu, + long *param, + uint32_t param_size, + bool lock_needed); +int smu_get_fan_control_mode(struct smu_context *smu); +int smu_set_fan_control_mode(struct smu_context *smu, int value); +int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed); +int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); +int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed); + +int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk); +int smu_set_active_display_count(struct smu_context *smu, uint32_t count); + +int smu_get_clock_by_type(struct smu_context *smu, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks); + +int smu_get_max_high_clocks(struct smu_context *smu, + struct amd_pp_simple_clock_info *clocks); + +int smu_get_clock_by_type_with_latency(struct smu_context *smu, + enum smu_clk_type clk_type, + struct pp_clock_levels_with_latency *clocks); + +int smu_get_clock_by_type_with_voltage(struct smu_context *smu, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks); + +int smu_display_clock_voltage_request(struct smu_context *smu, + struct pp_display_clock_request *clock_req); +int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disable_memory_clock_switch); +int smu_notify_smu_enable_pwe(struct smu_context *smu); + +int smu_set_xgmi_pstate(struct smu_context *smu, + uint32_t pstate); + +int smu_set_azalia_d3_pme(struct smu_context *smu); + +bool smu_baco_is_support(struct smu_context *smu); + +int smu_baco_get_state(struct smu_context *smu, enum smu_baco_state *state); + +int smu_baco_enter(struct smu_context *smu); +int smu_baco_exit(struct smu_context *smu); + +bool smu_mode1_reset_is_support(struct smu_context *smu); +int smu_mode1_reset(struct smu_context *smu); +int smu_mode2_reset(struct smu_context *smu); + +extern const struct amd_ip_funcs smu_ip_funcs; + +extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; +extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; + +bool is_support_sw_smu(struct amdgpu_device *adev); +int smu_reset(struct smu_context *smu); +int smu_sys_get_pp_table(struct smu_context *smu, void **table); +int smu_sys_set_pp_table(struct smu_context *smu, void *buf, size_t size); +int smu_get_power_num_states(struct smu_context *smu, struct pp_states_info *state_info); +enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu); +int smu_write_watermarks_table(struct smu_context *smu); +int smu_set_watermarks_for_clock_ranges( + struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); + +/* smu to display interface */ +extern int smu_display_configuration_change(struct smu_context *smu, const + struct amd_pp_display_configuration + *display_config); +extern int smu_get_current_clocks(struct smu_context *smu, + struct amd_pp_clock_info *clocks); +extern int smu_dpm_set_power_gate(struct smu_context *smu,uint32_t block_type, bool gate); +extern int smu_handle_task(struct smu_context *smu, + enum amd_dpm_forced_level level, + enum amd_pp_task task_id, + bool lock_needed); +int smu_switch_power_profile(struct smu_context *smu, + enum PP_SMC_POWER_PROFILE type, + bool en); +int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t *min, uint32_t *max); +int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t min, uint32_t max); +enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu); +int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level); +int smu_set_display_count(struct smu_context *smu, uint32_t count); +int smu_set_ac_dc(struct smu_context *smu); +size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf); +int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask); +int smu_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t mask); +int smu_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state); +int smu_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state); +int smu_allow_xgmi_power_down(struct smu_context *smu, bool en); + +int smu_get_max_sustainable_clocks_by_dc(struct smu_context *smu, + struct pp_smu_nv_clock_table *max_clocks); + +int smu_get_uclk_dpm_states(struct smu_context *smu, + unsigned int *clock_values_in_khz, + unsigned int *num_states); + +int smu_get_dpm_clock_table(struct smu_context *smu, + struct dpm_clocks *clock_table); + +int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); + +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); + +int smu_enable_mgpu_fan_boost(struct smu_context *smu); + +#endif +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h new file mode 100644 index 000000000000..79afb132164e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/arcturus_ppsmc.h @@ -0,0 +1,127 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef ARCTURUS_PP_SMC_H +#define ARCTURUS_PP_SMC_H + +#pragma pack(push, 1) + +// SMU Response Codes: +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +// Message Definitions: +// BASIC +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 +#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 +#define PPSMC_MSG_EnableAllSmuFeatures 0x6 +#define PPSMC_MSG_DisableAllSmuFeatures 0x7 +#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 +#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 +#define PPSMC_MSG_DisableSmuFeaturesLow 0xA +#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB +#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC +#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD +#define PPSMC_MSG_SetDriverDramAddrHigh 0xE +#define PPSMC_MSG_SetDriverDramAddrLow 0xF +#define PPSMC_MSG_SetToolsDramAddrHigh 0x10 +#define PPSMC_MSG_SetToolsDramAddrLow 0x11 +#define PPSMC_MSG_TransferTableSmu2Dram 0x12 +#define PPSMC_MSG_TransferTableDram2Smu 0x13 +#define PPSMC_MSG_UseDefaultPPTable 0x14 +#define PPSMC_MSG_UseBackupPPTable 0x15 +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x16 +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x17 + +//BACO/BAMACO/BOMACO +#define PPSMC_MSG_EnterBaco 0x18 +#define PPSMC_MSG_ExitBaco 0x19 +#define PPSMC_MSG_ArmD3 0x1A + +//DPM +#define PPSMC_MSG_SetSoftMinByFreq 0x1B +#define PPSMC_MSG_SetSoftMaxByFreq 0x1C +#define PPSMC_MSG_SetHardMinByFreq 0x1D +#define PPSMC_MSG_SetHardMaxByFreq 0x1E +#define PPSMC_MSG_GetMinDpmFreq 0x1F +#define PPSMC_MSG_GetMaxDpmFreq 0x20 +#define PPSMC_MSG_GetDpmFreqByIndex 0x21 + +#define PPSMC_MSG_SetWorkloadMask 0x22 +#define PPSMC_MSG_SetDfSwitchType 0x23 +#define PPSMC_MSG_GetVoltageByDpm 0x24 +#define PPSMC_MSG_GetVoltageByDpmOverdrive 0x25 + +#define PPSMC_MSG_SetPptLimit 0x26 +#define PPSMC_MSG_GetPptLimit 0x27 + +//Power Gating +#define PPSMC_MSG_PowerUpVcn0 0x28 +#define PPSMC_MSG_PowerDownVcn0 0x29 +#define PPSMC_MSG_PowerUpVcn1 0x2A +#define PPSMC_MSG_PowerDownVcn1 0x2B + +//Resets and reload +#define PPSMC_MSG_PrepareMp1ForUnload 0x2C +#define PPSMC_MSG_PrepareMp1ForReset 0x2D +#define PPSMC_MSG_PrepareMp1ForShutdown 0x2E +#define PPSMC_MSG_SoftReset 0x2F + +//BTC +#define PPSMC_MSG_RunAfllBtc 0x30 +#define PPSMC_MSG_RunDcBtc 0x31 + +//Debug +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x33 +#define PPSMC_MSG_DramLogSetDramAddrLow 0x34 +#define PPSMC_MSG_DramLogSetDramSize 0x35 +#define PPSMC_MSG_GetDebugData 0x36 + +//WAFL and XGMI +#define PPSMC_MSG_WaflTest 0x37 +#define PPSMC_MSG_SetXgmiMode 0x38 + +//Others +#define PPSMC_MSG_SetMemoryChannelEnable 0x39 + +//OOB +#define PPSMC_MSG_SetNumBadHbmPagesRetired 0x3A + +#define PPSMC_MSG_DFCstateControl 0x3B +#define PPSMC_MSG_GmiPwrDnControl 0x3D +#define PPSMC_Message_Count 0x3E + +#define PPSMC_MSG_ReadSerialNumTop32 0x40 +#define PPSMC_MSG_ReadSerialNumBottom32 0x41 + +typedef uint32_t PPSMC_Result; +typedef uint32_t PPSMC_Msg; +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h new file mode 100644 index 000000000000..9b698780aed8 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/cz_ppsmc.h @@ -0,0 +1,186 @@ +/* + * Copyright 2014 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 CZ_PP_SMC_H +#define CZ_PP_SMC_H + +#pragma pack(push, 1) + +/* Fan control algorithm:*/ +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +enum DPM_ARRAY { + DPM_ARRAY_HARD_MAX, + DPM_ARRAY_HARD_MIN, + DPM_ARRAY_SOFT_MAX, + DPM_ARRAY_SOFT_MIN +}; + +/* + * Return codes for driver to SMC communication. + * Leave these #define-s, enums might not be exactly 8-bits on the microcontroller. + */ +#define PPSMC_Result_OK ((uint16_t)0x01) +#define PPSMC_Result_NoMore ((uint16_t)0x02) +#define PPSMC_Result_NotNow ((uint16_t)0x03) +#define PPSMC_Result_Failed ((uint16_t)0xFF) +#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) + +#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) + +/* + * Supported driver messages + */ +#define PPSMC_MSG_Test ((uint16_t) 0x1) +#define PPSMC_MSG_GetFeatureStatus ((uint16_t) 0x2) +#define PPSMC_MSG_EnableAllSmuFeatures ((uint16_t) 0x3) +#define PPSMC_MSG_DisableAllSmuFeatures ((uint16_t) 0x4) +#define PPSMC_MSG_OptimizeBattery ((uint16_t) 0x5) +#define PPSMC_MSG_MaximizePerf ((uint16_t) 0x6) +#define PPSMC_MSG_UVDPowerOFF ((uint16_t) 0x7) +#define PPSMC_MSG_UVDPowerON ((uint16_t) 0x8) +#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x9) +#define PPSMC_MSG_VCEPowerON ((uint16_t) 0xA) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0xB) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0xC) +#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0xD) +#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0xE) +#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0xF) +#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x10) +#define PPSMC_MSG_SetMinDeepSleepSclk ((uint16_t) 0x11) +#define PPSMC_MSG_SetSclkSoftMin ((uint16_t) 0x12) +#define PPSMC_MSG_SetSclkSoftMax ((uint16_t) 0x13) +#define PPSMC_MSG_SetSclkHardMin ((uint16_t) 0x14) +#define PPSMC_MSG_SetSclkHardMax ((uint16_t) 0x15) +#define PPSMC_MSG_SetLclkSoftMin ((uint16_t) 0x16) +#define PPSMC_MSG_SetLclkSoftMax ((uint16_t) 0x17) +#define PPSMC_MSG_SetLclkHardMin ((uint16_t) 0x18) +#define PPSMC_MSG_SetLclkHardMax ((uint16_t) 0x19) +#define PPSMC_MSG_SetUvdSoftMin ((uint16_t) 0x1A) +#define PPSMC_MSG_SetUvdSoftMax ((uint16_t) 0x1B) +#define PPSMC_MSG_SetUvdHardMin ((uint16_t) 0x1C) +#define PPSMC_MSG_SetUvdHardMax ((uint16_t) 0x1D) +#define PPSMC_MSG_SetEclkSoftMin ((uint16_t) 0x1E) +#define PPSMC_MSG_SetEclkSoftMax ((uint16_t) 0x1F) +#define PPSMC_MSG_SetEclkHardMin ((uint16_t) 0x20) +#define PPSMC_MSG_SetEclkHardMax ((uint16_t) 0x21) +#define PPSMC_MSG_SetAclkSoftMin ((uint16_t) 0x22) +#define PPSMC_MSG_SetAclkSoftMax ((uint16_t) 0x23) +#define PPSMC_MSG_SetAclkHardMin ((uint16_t) 0x24) +#define PPSMC_MSG_SetAclkHardMax ((uint16_t) 0x25) +#define PPSMC_MSG_SetNclkSoftMin ((uint16_t) 0x26) +#define PPSMC_MSG_SetNclkSoftMax ((uint16_t) 0x27) +#define PPSMC_MSG_SetNclkHardMin ((uint16_t) 0x28) +#define PPSMC_MSG_SetNclkHardMax ((uint16_t) 0x29) +#define PPSMC_MSG_SetPstateSoftMin ((uint16_t) 0x2A) +#define PPSMC_MSG_SetPstateSoftMax ((uint16_t) 0x2B) +#define PPSMC_MSG_SetPstateHardMin ((uint16_t) 0x2C) +#define PPSMC_MSG_SetPstateHardMax ((uint16_t) 0x2D) +#define PPSMC_MSG_DisableLowMemoryPstate ((uint16_t) 0x2E) +#define PPSMC_MSG_EnableLowMemoryPstate ((uint16_t) 0x2F) +#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x30) +#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x31) +#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x32) +#define PPSMC_MSG_DriverDramAddrHi ((uint16_t) 0x33) +#define PPSMC_MSG_DriverDramAddrLo ((uint16_t) 0x34) +#define PPSMC_MSG_CondExecDramAddrHi ((uint16_t) 0x35) +#define PPSMC_MSG_CondExecDramAddrLo ((uint16_t) 0x36) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x37) +#define PPSMC_MSG_DriverResetMode ((uint16_t) 0x38) +#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x39) +#define PPSMC_MSG_SetDisplayPhyConfig ((uint16_t) 0x3A) +#define PPSMC_MSG_GetMaxSclkLevel ((uint16_t) 0x3B) +#define PPSMC_MSG_GetMaxLclkLevel ((uint16_t) 0x3C) +#define PPSMC_MSG_GetMaxUvdLevel ((uint16_t) 0x3D) +#define PPSMC_MSG_GetMaxEclkLevel ((uint16_t) 0x3E) +#define PPSMC_MSG_GetMaxAclkLevel ((uint16_t) 0x3F) +#define PPSMC_MSG_GetMaxNclkLevel ((uint16_t) 0x40) +#define PPSMC_MSG_GetMaxPstate ((uint16_t) 0x41) +#define PPSMC_MSG_DramAddrHiVirtual ((uint16_t) 0x42) +#define PPSMC_MSG_DramAddrLoVirtual ((uint16_t) 0x43) +#define PPSMC_MSG_DramAddrHiPhysical ((uint16_t) 0x44) +#define PPSMC_MSG_DramAddrLoPhysical ((uint16_t) 0x45) +#define PPSMC_MSG_DramBufferSize ((uint16_t) 0x46) +#define PPSMC_MSG_SetMmPwrLogDramAddrHi ((uint16_t) 0x47) +#define PPSMC_MSG_SetMmPwrLogDramAddrLo ((uint16_t) 0x48) +#define PPSMC_MSG_SetClkTableAddrHi ((uint16_t) 0x49) +#define PPSMC_MSG_SetClkTableAddrLo ((uint16_t) 0x4A) +#define PPSMC_MSG_GetConservativePowerLimit ((uint16_t) 0x4B) + +#define PPSMC_MSG_InitJobs ((uint16_t) 0x252) +#define PPSMC_MSG_ExecuteJob ((uint16_t) 0x254) + +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) + +#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) + +#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) +#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) + +#define PPSMC_MSG_AllowLowSclkInterrupt ((uint16_t) 0x184) +#define PPSMC_MSG_MmPowerMonitorStart ((uint16_t) 0x18F) +#define PPSMC_MSG_MmPowerMonitorStop ((uint16_t) 0x190) +#define PPSMC_MSG_MmPowerMonitorRestart ((uint16_t) 0x191) + +#define PPSMC_MSG_SetClockGateMask ((uint16_t) 0x260) +#define PPSMC_MSG_SetFpsThresholdLo ((uint16_t) 0x264) +#define PPSMC_MSG_SetFpsThresholdHi ((uint16_t) 0x265) +#define PPSMC_MSG_SetLowSclkIntrThreshold ((uint16_t) 0x266) + +#define PPSMC_MSG_ClkTableXferToDram ((uint16_t) 0x267) +#define PPSMC_MSG_ClkTableXferToSmu ((uint16_t) 0x268) +#define PPSMC_MSG_GetAverageGraphicsActivity ((uint16_t) 0x269) +#define PPSMC_MSG_GetAverageGioActivity ((uint16_t) 0x26A) +#define PPSMC_MSG_SetLoggerBufferSize ((uint16_t) 0x26B) +#define PPSMC_MSG_SetLoggerAddressHigh ((uint16_t) 0x26C) +#define PPSMC_MSG_SetLoggerAddressLow ((uint16_t) 0x26D) +#define PPSMC_MSG_SetWatermarkFrequency ((uint16_t) 0x26E) +#define PPSMC_MSG_SetDisplaySizePowerParams ((uint16_t) 0x26F) + +/* REMOVE LATER*/ +#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) + +/* Feature Enable Masks*/ +#define NB_DPM_MASK 0x00000800 +#define VDDGFX_MASK 0x00800000 +#define VCE_DPM_MASK 0x00400000 +#define ACP_DPM_MASK 0x00040000 +#define UVD_DPM_MASK 0x00010000 +#define GFX_CU_PG_MASK 0x00004000 +#define SCLK_DPM_MASK 0x00080000 + +#if !defined(SMC_MICROCODE) +#pragma pack(pop) + +#endif + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h new file mode 100644 index 000000000000..7ae494569a60 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/fiji_ppsmc.h @@ -0,0 +1,412 @@ +/* + * Copyright 2015 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 _FIJI_PP_SMC_H_ +#define _FIJI_PP_SMC_H_ + +#pragma pack(push, 1) + +#define PPSMC_SWSTATE_FLAG_DC 0x01 +#define PPSMC_SWSTATE_FLAG_UVD 0x02 +#define PPSMC_SWSTATE_FLAG_VCE 0x04 + +#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 +#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 +#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff + +#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 +#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 +#define PPSMC_SYSTEMFLAG_GDDR5 0x04 + +#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 + +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 +#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 + +/* Defines for DPM 2.0 */ +#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 +#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 +#define PPSMC_DPM2FLAGS_OCP 0x04 + +/* Defines for display watermark level */ +#define PPSMC_DISPLAY_WATERMARK_LOW 0 +#define PPSMC_DISPLAY_WATERMARK_HIGH 1 + +/* In the HW performance level's state flags: */ +#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 +#define PPSMC_STATEFLAG_POWERBOOST 0x02 +#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 +#define PPSMC_STATEFLAG_POWERSHIFT 0x08 +#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 +#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 +#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 + +/* Fan control algorithm: */ +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +/* Gemini Modes*/ +#define PPSMC_GeminiModeNone 0 /*Single GPU board*/ +#define PPSMC_GeminiModeMaster 1 /*Master GPU on a Gemini board*/ +#define PPSMC_GeminiModeSlave 2 /*Slave GPU on a Gemini board*/ + + +/* Return codes for driver to SMC communication. */ +#define PPSMC_Result_OK ((uint16_t)0x01) +#define PPSMC_Result_NoMore ((uint16_t)0x02) + +#define PPSMC_Result_NotNow ((uint16_t)0x03) + +#define PPSMC_Result_Failed ((uint16_t)0xFF) +#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) + +#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) + + +#define PPSMC_MSG_Halt ((uint16_t)0x10) +#define PPSMC_MSG_Resume ((uint16_t)0x11) +#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) +#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) +#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) +#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) +#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) +#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) +#define PPSMC_MSG_LevelUp ((uint16_t)0x18) +#define PPSMC_MSG_LevelDown ((uint16_t)0x19) +#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) +#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) + +#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) +#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) +#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) +#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) +#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) + +#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) +#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) +#define PPSMC_MSG_EnableCac ((uint16_t)0x53) +#define PPSMC_MSG_DisableCac ((uint16_t)0x54) +#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) +#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) +#define PPSMC_CACHistoryStart ((uint16_t)0x57) +#define PPSMC_CACHistoryStop ((uint16_t)0x58) +#define PPSMC_TDPClampingActive ((uint16_t)0x59) +#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) +#define PPSMC_StartFanControl ((uint16_t)0x5B) +#define PPSMC_StopFanControl ((uint16_t)0x5C) +#define PPSMC_NoDisplay ((uint16_t)0x5D) +#define PPSMC_HasDisplay ((uint16_t)0x5E) +#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) +#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) +#define PPSMC_MSG_EnableULV ((uint16_t)0x62) +#define PPSMC_MSG_DisableULV ((uint16_t)0x63) +#define PPSMC_MSG_EnterULV ((uint16_t)0x64) +#define PPSMC_MSG_ExitULV ((uint16_t)0x65) +#define PPSMC_PowerShiftActive ((uint16_t)0x6A) +#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) +#define PPSMC_OCPActive ((uint16_t)0x6C) +#define PPSMC_OCPInactive ((uint16_t)0x6D) +#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) +#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) +#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) +#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) +#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) +#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) +#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) +#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) +#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) +#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) +#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) +#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) +#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) +#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) +#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) +#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) + +#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) +#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) +#define PPSMC_FlushDataCache ((uint16_t)0x80) +#define PPSMC_FlushInstrCache ((uint16_t)0x81) + +#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) +#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) + +#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) + +#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) +#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) +#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) +#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) + +#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) + +#define PPSMC_MSG_BREAK ((uint16_t)0xF8) + +/* Trinity Specific Messages*/ +#define PPSMC_MSG_Test ((uint16_t) 0x100) +#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) +#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) +#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) +#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) +#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) +#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) +#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) +#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) +#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) +#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) +#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) +#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) +#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) +#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) +#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) +#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) +#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) +#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) +#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) +#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) +#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) +#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) +#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) +#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) +#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) +#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) +#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) +#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) +#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_VddNB_Request ((uint16_t) 0x125) +#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint32_t) 0x126) +#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint32_t) 0x127) +#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) + +#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) +#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) +#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) +#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) +#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) +#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) +#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) +#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) +#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) +#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) +#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) +#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) +#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) +#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) +#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) +#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) +#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) +#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) +#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) +#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) +#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) +#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) +#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) +#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) +#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) +#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) +#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) + +#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) +#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) + +#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) +#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) +#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150) +#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151) +#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t) 0x152) +#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t) 0x153) +#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154) +#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155) +#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156) +#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157) +#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158) +#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159) +#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a) +#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b) +#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t) 0x15c) +#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) +#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) +#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) +#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) +#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) +#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) +#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) +#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) +#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) +#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) +#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) +#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) +#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) +#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) +#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t) 0x16c) +#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t) 0x16d) +#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t) 0x16e) +#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t) 0x16f) +#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) +#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) +#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) +#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) +#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) +#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) +#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) +#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) +#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) +#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) +#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) +#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) +#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) +#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) +#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) +#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) +#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) +#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) +#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) +#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) +#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) +#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) +#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) +#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) +#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) +#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) +#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) +#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) +#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) +#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) +#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) +#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) +#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) +#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) +#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) +#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) +#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) +#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) +#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) +#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) +#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) +#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) +#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) + +#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) +#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) +#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) +#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) +#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) +#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) +#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) +#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) +#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) + +#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) +#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) +#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) +#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) +#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) +#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) +#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) + +#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) +#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) +#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) +#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) +#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) +#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) +#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) +#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) +#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) +#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) +#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) +#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) +#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) +#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) +#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) +#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) +#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) +#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) +#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) +#define PPSMC_MSG_EnableAvfs ((uint16_t) 0x26A) +#define PPSMC_MSG_DisableAvfs ((uint16_t) 0x26B) +#define PPSMC_MSG_PerformBtc ((uint16_t) 0x26C) +#define PPSMC_MSG_GetHbmCode ((uint16_t) 0x26D) +#define PPSMC_MSG_GetVrVddcTemperature ((uint16_t) 0x26E) +#define PPSMC_MSG_GetVrMvddTemperature ((uint16_t) 0x26F) +#define PPSMC_MSG_GetLiquidTemperature ((uint16_t) 0x270) +#define PPSMC_MSG_GetPlxTemperature ((uint16_t) 0x271) +#define PPSMC_MSG_RequestI2CControl ((uint16_t) 0x272) +#define PPSMC_MSG_ReleaseI2CControl ((uint16_t) 0x273) +#define PPSMC_MSG_LedConfig ((uint16_t) 0x274) +#define PPSMC_MSG_SetHbmFanCode ((uint16_t) 0x275) +#define PPSMC_MSG_SetHbmThrottleCode ((uint16_t) 0x276) + +#define PPSMC_MSG_GetEnabledPsm ((uint16_t) 0x400) +#define PPSMC_MSG_AgmStartPsm ((uint16_t) 0x401) +#define PPSMC_MSG_AgmReadPsm ((uint16_t) 0x402) +#define PPSMC_MSG_AgmResetPsm ((uint16_t) 0x403) +#define PPSMC_MSG_ReadVftCell ((uint16_t) 0x404) + +/* AVFS Only - Remove Later */ +#define PPSMC_MSG_VftTableIsValid ((uint16_t) 0x666) + +/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ +#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 +#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 +#define PPSMC_EVENT_STATUS_DC 0x00000004 + +typedef uint16_t PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/hardwaremanager.h b/drivers/gpu/drm/amd/pm/inc/hardwaremanager.h new file mode 100644 index 000000000000..6e0be6027705 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/hardwaremanager.h @@ -0,0 +1,469 @@ +/* + * Copyright 2015 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 _HARDWARE_MANAGER_H_ +#define _HARDWARE_MANAGER_H_ + + + +struct pp_hwmgr; +struct pp_hw_power_state; +struct pp_power_state; +enum amd_dpm_forced_level; +struct PP_TemperatureRange; + + +struct phm_fan_speed_info { + uint32_t min_percent; + uint32_t max_percent; + uint32_t min_rpm; + uint32_t max_rpm; + bool supports_percent_read; + bool supports_percent_write; + bool supports_rpm_read; + bool supports_rpm_write; +}; + +/* Automatic Power State Throttling */ +enum PHM_AutoThrottleSource +{ + PHM_AutoThrottleSource_Thermal, + PHM_AutoThrottleSource_External +}; + +typedef enum PHM_AutoThrottleSource PHM_AutoThrottleSource; + +enum phm_platform_caps { + PHM_PlatformCaps_AtomBiosPpV1 = 0, + PHM_PlatformCaps_PowerPlaySupport, + PHM_PlatformCaps_ACOverdriveSupport, + PHM_PlatformCaps_BacklightSupport, + PHM_PlatformCaps_ThermalController, + PHM_PlatformCaps_BiosPowerSourceControl, + PHM_PlatformCaps_DisableVoltageTransition, + PHM_PlatformCaps_DisableEngineTransition, + PHM_PlatformCaps_DisableMemoryTransition, + PHM_PlatformCaps_DynamicPowerManagement, + PHM_PlatformCaps_EnableASPML0s, + PHM_PlatformCaps_EnableASPML1, + PHM_PlatformCaps_OD5inACSupport, + PHM_PlatformCaps_OD5inDCSupport, + PHM_PlatformCaps_SoftStateOD5, + PHM_PlatformCaps_NoOD5Support, + PHM_PlatformCaps_ContinuousHardwarePerformanceRange, + PHM_PlatformCaps_ActivityReporting, + PHM_PlatformCaps_EnableBackbias, + PHM_PlatformCaps_OverdriveDisabledByPowerBudget, + PHM_PlatformCaps_ShowPowerBudgetWarning, + PHM_PlatformCaps_PowerBudgetWaiverAvailable, + PHM_PlatformCaps_GFXClockGatingSupport, + PHM_PlatformCaps_MMClockGatingSupport, + PHM_PlatformCaps_AutomaticDCTransition, + PHM_PlatformCaps_GeminiPrimary, + PHM_PlatformCaps_MemorySpreadSpectrumSupport, + PHM_PlatformCaps_EngineSpreadSpectrumSupport, + PHM_PlatformCaps_StepVddc, + PHM_PlatformCaps_DynamicPCIEGen2Support, + PHM_PlatformCaps_SMC, + PHM_PlatformCaps_FaultyInternalThermalReading, /* Internal thermal controller reports faulty temperature value when DAC2 is active */ + PHM_PlatformCaps_EnableVoltageControl, /* indicates voltage can be controlled */ + PHM_PlatformCaps_EnableSideportControl, /* indicates Sideport can be controlled */ + PHM_PlatformCaps_VideoPlaybackEEUNotification, /* indicates EEU notification of video start/stop is required */ + PHM_PlatformCaps_TurnOffPll_ASPML1, /* PCIE Turn Off PLL in ASPM L1 */ + PHM_PlatformCaps_EnableHTLinkControl, /* indicates HT Link can be controlled by ACPI or CLMC overridden/automated mode. */ + PHM_PlatformCaps_PerformanceStateOnly, /* indicates only performance power state to be used on current system. */ + PHM_PlatformCaps_ExclusiveModeAlwaysHigh, /* In Exclusive (3D) mode always stay in High state. */ + PHM_PlatformCaps_DisableMGClockGating, /* to disable Medium Grain Clock Gating or not */ + PHM_PlatformCaps_DisableMGCGTSSM, /* TO disable Medium Grain Clock Gating Shader Complex control */ + PHM_PlatformCaps_UVDAlwaysHigh, /* In UVD mode always stay in High state */ + PHM_PlatformCaps_DisablePowerGating, /* to disable power gating */ + PHM_PlatformCaps_CustomThermalPolicy, /* indicates only performance power state to be used on current system. */ + PHM_PlatformCaps_StayInBootState, /* Stay in Boot State, do not do clock/voltage or PCIe Lane and Gen switching (RV7xx and up). */ + PHM_PlatformCaps_SMCAllowSeparateSWThermalState, /* SMC use separate SW thermal state, instead of the default SMC thermal policy. */ + PHM_PlatformCaps_MultiUVDStateSupport, /* Powerplay state table supports multi UVD states. */ + PHM_PlatformCaps_EnableSCLKDeepSleepForUVD, /* With HW ECOs, we don't need to disable SCLK Deep Sleep for UVD state. */ + PHM_PlatformCaps_EnableMCUHTLinkControl, /* Enable HT link control by MCU */ + PHM_PlatformCaps_ABM, /* ABM support.*/ + PHM_PlatformCaps_KongThermalPolicy, /* A thermal policy specific for Kong */ + PHM_PlatformCaps_SwitchVDDNB, /* if the users want to switch VDDNB */ + PHM_PlatformCaps_ULPS, /* support ULPS mode either through ACPI state or ULPS state */ + PHM_PlatformCaps_NativeULPS, /* hardware capable of ULPS state (other than through the ACPI state) */ + PHM_PlatformCaps_EnableMVDDControl, /* indicates that memory voltage can be controlled */ + PHM_PlatformCaps_ControlVDDCI, /* Control VDDCI separately from VDDC. */ + PHM_PlatformCaps_DisableDCODT, /* indicates if DC ODT apply or not */ + PHM_PlatformCaps_DynamicACTiming, /* if the SMC dynamically re-programs MC SEQ register values */ + PHM_PlatformCaps_EnableThermalIntByGPIO, /* enable throttle control through GPIO */ + PHM_PlatformCaps_BootStateOnAlert, /* Go to boot state on alerts, e.g. on an AC->DC transition. */ + PHM_PlatformCaps_DontWaitForVBlankOnAlert, /* Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). */ + PHM_PlatformCaps_Force3DClockSupport, /* indicates if the platform supports force 3D clock. */ + PHM_PlatformCaps_MicrocodeFanControl, /* Fan is controlled by the SMC microcode. */ + PHM_PlatformCaps_AdjustUVDPriorityForSP, + PHM_PlatformCaps_DisableLightSleep, /* Light sleep for evergreen family. */ + PHM_PlatformCaps_DisableMCLS, /* MC Light sleep */ + PHM_PlatformCaps_RegulatorHot, /* Enable throttling on 'regulator hot' events. */ + PHM_PlatformCaps_BACO, /* Support Bus Alive Chip Off mode */ + PHM_PlatformCaps_DisableDPM, /* Disable DPM, supported from Llano */ + PHM_PlatformCaps_DynamicM3Arbiter, /* support dynamically change m3 arbitor parameters */ + PHM_PlatformCaps_SclkDeepSleep, /* support sclk deep sleep */ + PHM_PlatformCaps_DynamicPatchPowerState, /* this ASIC supports to patch power state dynamically */ + PHM_PlatformCaps_ThermalAutoThrottling, /* enabling auto thermal throttling, */ + PHM_PlatformCaps_SumoThermalPolicy, /* A thermal policy specific for Sumo */ + PHM_PlatformCaps_PCIEPerformanceRequest, /* support to change RC voltage */ + PHM_PlatformCaps_BLControlledByGPU, /* support varibright */ + PHM_PlatformCaps_PowerContainment, /* support DPM2 power containment (AKA TDP clamping) */ + PHM_PlatformCaps_SQRamping, /* support DPM2 SQ power throttle */ + PHM_PlatformCaps_CAC, /* support Capacitance * Activity power estimation */ + PHM_PlatformCaps_NIChipsets, /* Northern Island and beyond chipsets */ + PHM_PlatformCaps_TrinityChipsets, /* Trinity chipset */ + PHM_PlatformCaps_EvergreenChipsets, /* Evergreen family chipset */ + PHM_PlatformCaps_PowerControl, /* Cayman and beyond chipsets */ + PHM_PlatformCaps_DisableLSClockGating, /* to disable Light Sleep control for HDP memories */ + PHM_PlatformCaps_BoostState, /* this ASIC supports boost state */ + PHM_PlatformCaps_UserMaxClockForMultiDisplays, /* indicates if max memory clock is used for all status when multiple displays are connected */ + PHM_PlatformCaps_RegWriteDelay, /* indicates if back to back reg write delay is required */ + PHM_PlatformCaps_NonABMSupportInPPLib, /* ABM is not supported in PPLIB, (moved from PPLIB to DAL) */ + PHM_PlatformCaps_GFXDynamicMGPowerGating, /* Enable Dynamic MG PowerGating on Trinity */ + PHM_PlatformCaps_DisableSMUUVDHandshake, /* Disable SMU UVD Handshake */ + PHM_PlatformCaps_DTE, /* Support Digital Temperature Estimation */ + PHM_PlatformCaps_W5100Specifc_SmuSkipMsgDTE, /* This is for the feature requested by David B., and Tonny W.*/ + PHM_PlatformCaps_UVDPowerGating, /* enable UVD power gating, supported from Llano */ + PHM_PlatformCaps_UVDDynamicPowerGating, /* enable UVD Dynamic power gating, supported from UVD5 */ + PHM_PlatformCaps_VCEPowerGating, /* Enable VCE power gating, supported for TN and later ASICs */ + PHM_PlatformCaps_SamuPowerGating, /* Enable SAMU power gating, supported for KV and later ASICs */ + PHM_PlatformCaps_UVDDPM, /* UVD clock DPM */ + PHM_PlatformCaps_VCEDPM, /* VCE clock DPM */ + PHM_PlatformCaps_SamuDPM, /* SAMU clock DPM */ + PHM_PlatformCaps_AcpDPM, /* ACP clock DPM */ + PHM_PlatformCaps_SclkDeepSleepAboveLow, /* Enable SCLK Deep Sleep on all DPM states */ + PHM_PlatformCaps_DynamicUVDState, /* Dynamic UVD State */ + PHM_PlatformCaps_WantSAMClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ + PHM_PlatformCaps_WantUVDClkWithDummyBackEnd, /* Set UVD Clk With Dummy Back End */ + PHM_PlatformCaps_WantVCEClkWithDummyBackEnd, /* Set VCE Clk With Dummy Back End */ + PHM_PlatformCaps_WantACPClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ + PHM_PlatformCaps_OD6inACSupport, /* indicates that the ASIC/back end supports OD6 */ + PHM_PlatformCaps_OD6inDCSupport, /* indicates that the ASIC/back end supports OD6 in DC */ + PHM_PlatformCaps_EnablePlatformPowerManagement, /* indicates that Platform Power Management feature is supported */ + PHM_PlatformCaps_SurpriseRemoval, /* indicates that surprise removal feature is requested */ + PHM_PlatformCaps_NewCACVoltage, /* indicates new CAC voltage table support */ + PHM_PlatformCaps_DiDtSupport, /* for dI/dT feature */ + PHM_PlatformCaps_DBRamping, /* for dI/dT feature */ + PHM_PlatformCaps_TDRamping, /* for dI/dT feature */ + PHM_PlatformCaps_TCPRamping, /* for dI/dT feature */ + PHM_PlatformCaps_DBRRamping, /* for dI/dT feature */ + PHM_PlatformCaps_DiDtEDCEnable, /* for dI/dT feature */ + PHM_PlatformCaps_GCEDC, /* for dI/dT feature */ + PHM_PlatformCaps_PSM, /* for dI/dT feature */ + PHM_PlatformCaps_EnableSMU7ThermalManagement, /* SMC will manage thermal events */ + PHM_PlatformCaps_FPS, /* FPS support */ + PHM_PlatformCaps_ACP, /* ACP support */ + PHM_PlatformCaps_SclkThrottleLowNotification, /* SCLK Throttle Low Notification */ + PHM_PlatformCaps_XDMAEnabled, /* XDMA engine is enabled */ + PHM_PlatformCaps_UseDummyBackEnd, /* use dummy back end */ + PHM_PlatformCaps_EnableDFSBypass, /* Enable DFS bypass */ + PHM_PlatformCaps_VddNBDirectRequest, + PHM_PlatformCaps_PauseMMSessions, + PHM_PlatformCaps_UnTabledHardwareInterface, /* Tableless/direct call hardware interface for CI and newer ASICs */ + PHM_PlatformCaps_SMU7, /* indicates that vpuRecoveryBegin without SMU shutdown */ + PHM_PlatformCaps_RevertGPIO5Polarity, /* indicates revert GPIO5 plarity table support */ + PHM_PlatformCaps_Thermal2GPIO17, /* indicates thermal2GPIO17 table support */ + PHM_PlatformCaps_ThermalOutGPIO, /* indicates ThermalOutGPIO support, pin number is assigned by VBIOS */ + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock, /* Disable memory clock switch during Framelock */ + PHM_PlatformCaps_ForceMclkHigh, /* Disable memory clock switching by forcing memory clock high */ + PHM_PlatformCaps_VRHotGPIOConfigurable, /* indicates VR_HOT GPIO configurable */ + PHM_PlatformCaps_TempInversion, /* enable Temp Inversion feature */ + PHM_PlatformCaps_IOIC3, + PHM_PlatformCaps_ConnectedStandby, + PHM_PlatformCaps_EVV, + PHM_PlatformCaps_EnableLongIdleBACOSupport, + PHM_PlatformCaps_CombinePCCWithThermalSignal, + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc, + PHM_PlatformCaps_StablePState, + PHM_PlatformCaps_OD6PlusinACSupport, + PHM_PlatformCaps_OD6PlusinDCSupport, + PHM_PlatformCaps_ODThermalLimitUnlock, + PHM_PlatformCaps_ReducePowerLimit, + PHM_PlatformCaps_ODFuzzyFanControlSupport, + PHM_PlatformCaps_GeminiRegulatorFanControlSupport, + PHM_PlatformCaps_ControlVDDGFX, + PHM_PlatformCaps_BBBSupported, + PHM_PlatformCaps_DisableVoltageIsland, + PHM_PlatformCaps_FanSpeedInTableIsRPM, + PHM_PlatformCaps_GFXClockGatingManagedInCAIL, + PHM_PlatformCaps_IcelandULPSSWWorkAround, + PHM_PlatformCaps_FPSEnhancement, + PHM_PlatformCaps_LoadPostProductionFirmware, + PHM_PlatformCaps_VpuRecoveryInProgress, + PHM_PlatformCaps_Falcon_QuickTransition, + PHM_PlatformCaps_AVFS, + PHM_PlatformCaps_ClockStretcher, + PHM_PlatformCaps_TablelessHardwareInterface, + PHM_PlatformCaps_EnableDriverEVV, + PHM_PlatformCaps_SPLLShutdownSupport, + PHM_PlatformCaps_VirtualBatteryState, + PHM_PlatformCaps_IgnoreForceHighClockRequestsInAPUs, + PHM_PlatformCaps_DisableMclkSwitchForVR, + PHM_PlatformCaps_SMU8, + PHM_PlatformCaps_VRHotPolarityHigh, + PHM_PlatformCaps_IPS_UlpsExclusive, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme, + PHM_PlatformCaps_GeminiAsymmetricPower, + PHM_PlatformCaps_OCLPowerOptimization, + PHM_PlatformCaps_MaxPCIEBandWidth, + PHM_PlatformCaps_PerfPerWattOptimizationSupport, + PHM_PlatformCaps_UVDClientMCTuning, + PHM_PlatformCaps_ODNinACSupport, + PHM_PlatformCaps_ODNinDCSupport, + PHM_PlatformCaps_OD8inACSupport, + PHM_PlatformCaps_OD8inDCSupport, + PHM_PlatformCaps_UMDPState, + PHM_PlatformCaps_AutoWattmanSupport, + PHM_PlatformCaps_AutoWattmanEnable_CCCState, + PHM_PlatformCaps_FreeSyncActive, + PHM_PlatformCaps_EnableShadowPstate, + PHM_PlatformCaps_customThermalManagement, + PHM_PlatformCaps_staticFanControl, + PHM_PlatformCaps_Virtual_System, + PHM_PlatformCaps_LowestUclkReservedForUlv, + PHM_PlatformCaps_EnableBoostState, + PHM_PlatformCaps_AVFSSupport, + PHM_PlatformCaps_ThermalPolicyDelay, + PHM_PlatformCaps_CustomFanControlSupport, + PHM_PlatformCaps_BAMACO, + PHM_PlatformCaps_Max +}; + +#define PHM_MAX_NUM_CAPS_BITS_PER_FIELD (sizeof(uint32_t)*8) + +/* Number of uint32_t entries used by CAPS table */ +#define PHM_MAX_NUM_CAPS_ULONG_ENTRIES \ + ((PHM_PlatformCaps_Max + ((PHM_MAX_NUM_CAPS_BITS_PER_FIELD) - 1)) / (PHM_MAX_NUM_CAPS_BITS_PER_FIELD)) + +struct pp_hw_descriptor { + uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; +}; + +enum PHM_PerformanceLevelDesignation { + PHM_PerformanceLevelDesignation_Activity, + PHM_PerformanceLevelDesignation_PowerContainment +}; + +typedef enum PHM_PerformanceLevelDesignation PHM_PerformanceLevelDesignation; + +struct PHM_PerformanceLevel { + uint32_t coreClock; + uint32_t memory_clock; + uint32_t vddc; + uint32_t vddci; + uint32_t nonLocalMemoryFreq; + uint32_t nonLocalMemoryWidth; +}; + +typedef struct PHM_PerformanceLevel PHM_PerformanceLevel; + +/* Function for setting a platform cap */ +static inline void phm_cap_set(uint32_t *caps, + enum phm_platform_caps c) +{ + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] |= (1UL << + (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); +} + +static inline void phm_cap_unset(uint32_t *caps, + enum phm_platform_caps c) +{ + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &= ~(1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); +} + +static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps c) +{ + return (0 != (caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] & + (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))))); +} + +#define PP_CAP(c) phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, (c)) + +#define PP_PCIEGenInvalid 0xffff +enum PP_PCIEGen { + PP_PCIEGen1 = 0, /* PCIE 1.0 - Transfer rate of 2.5 GT/s */ + PP_PCIEGen2, /*PCIE 2.0 - Transfer rate of 5.0 GT/s */ + PP_PCIEGen3 /*PCIE 3.0 - Transfer rate of 8.0 GT/s */ +}; + +typedef enum PP_PCIEGen PP_PCIEGen; + +#define PP_Min_PCIEGen PP_PCIEGen1 +#define PP_Max_PCIEGen PP_PCIEGen3 +#define PP_Min_PCIELane 1 +#define PP_Max_PCIELane 16 + +enum phm_clock_Type { + PHM_DispClock = 1, + PHM_SClock, + PHM_MemClock +}; + +#define MAX_NUM_CLOCKS 16 + +struct PP_Clocks { + uint32_t engineClock; + uint32_t memoryClock; + uint32_t BusBandwidth; + uint32_t engineClockInSR; + uint32_t dcefClock; + uint32_t dcefClockInSR; +}; + +struct pp_clock_info { + uint32_t min_mem_clk; + uint32_t max_mem_clk; + uint32_t min_eng_clk; + uint32_t max_eng_clk; + uint32_t min_bus_bandwidth; + uint32_t max_bus_bandwidth; +}; + +struct phm_platform_descriptor { + uint32_t platformCaps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; + uint32_t vbiosInterruptId; + struct PP_Clocks overdriveLimit; + struct PP_Clocks clockStep; + uint32_t hardwareActivityPerformanceLevels; + uint32_t minimumClocksReductionPercentage; + uint32_t minOverdriveVDDC; + uint32_t maxOverdriveVDDC; + uint32_t overdriveVDDCStep; + uint32_t hardwarePerformanceLevels; + uint16_t powerBudget; + uint32_t TDPLimit; + uint32_t nearTDPLimit; + uint32_t nearTDPLimitAdjusted; + uint32_t SQRampingThreshold; + uint32_t CACLeakage; + uint16_t TDPODLimit; + uint32_t TDPAdjustment; + bool TDPAdjustmentPolarity; + uint16_t LoadLineSlope; + uint32_t VidMinLimit; + uint32_t VidMaxLimit; + uint32_t VidStep; + uint32_t VidAdjustment; + bool VidAdjustmentPolarity; +}; + +struct phm_clocks { + uint32_t num_of_entries; + uint32_t clock[MAX_NUM_CLOCKS]; +}; + +#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 +#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 +#define DPMTABLE_UPDATE_SCLK 0x00000004 +#define DPMTABLE_UPDATE_MCLK 0x00000008 +#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 +#define DPMTABLE_UPDATE_SOCCLK 0x00000020 + +struct phm_odn_performance_level { + uint32_t clock; + uint32_t vddc; + bool enabled; +}; + +struct phm_odn_clock_levels { + uint32_t size; + uint32_t options; + uint32_t flags; + uint32_t num_of_pl; + /* variable-sized array, specify by num_of_pl. */ + struct phm_odn_performance_level entries[8]; +}; + +extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr); +extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); +extern int phm_setup_asic(struct pp_hwmgr *hwmgr); +extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); +extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); +extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); +extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); +extern int phm_set_power_state(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pcurrent_state, + const struct pp_hw_power_state *pnew_power_state); + +extern int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *adjusted_ps, + const struct pp_power_state *current_ps); + +extern int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr); + +extern int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level); +extern int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr); +extern int phm_display_configuration_changed(struct pp_hwmgr *hwmgr); +extern int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); +extern int phm_register_irq_handlers(struct pp_hwmgr *hwmgr); +extern int phm_start_thermal_controller(struct pp_hwmgr *hwmgr); +extern int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr); + +extern int phm_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal); + +extern int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config); + +extern int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info); + +extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr); + +extern int phm_power_down_asic(struct pp_hwmgr *hwmgr); + +extern int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level); + +extern int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + struct pp_clock_info *pclock_info, + PHM_PerformanceLevelDesignation designation); + +extern int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info); + +extern int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks); + +extern int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks); +extern int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks); +extern int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_ranges); +extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock); + +extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); +extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr); + +extern int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count); + +#endif /* _HARDWARE_MANAGER_H_ */ + diff --git a/drivers/gpu/drm/amd/pm/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/inc/hwmgr.h new file mode 100644 index 000000000000..1b3529efc91e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/hwmgr.h @@ -0,0 +1,824 @@ +/* + * Copyright 2015 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 _HWMGR_H_ +#define _HWMGR_H_ + +#include +#include "amd_powerplay.h" +#include "hardwaremanager.h" +#include "hwmgr_ppt.h" +#include "ppatomctrl.h" +#include "power_state.h" +#include "smu_helper.h" + +struct pp_hwmgr; +struct phm_fan_speed_info; +struct pp_atomctrl_voltage_table; + +#define VOLTAGE_SCALE 4 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 + +enum DISPLAY_GAP { + DISPLAY_GAP_VBLANK_OR_WM = 0, /* Wait for vblank or MCHG watermark. */ + DISPLAY_GAP_VBLANK = 1, /* Wait for vblank. */ + DISPLAY_GAP_WATERMARK = 2, /* Wait for MCHG watermark. (Note that HW may deassert WM in VBI depending on DC_STUTTER_CNTL.) */ + DISPLAY_GAP_IGNORE = 3 /* Do not wait. */ +}; +typedef enum DISPLAY_GAP DISPLAY_GAP; + +enum BACO_STATE { + BACO_STATE_OUT = 0, + BACO_STATE_IN, +}; + +struct vi_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +struct vi_dpm_table { + uint32_t count; + struct vi_dpm_level dpm_level[1]; +}; + +#define PCIE_PERF_REQ_REMOVE_REGISTRY 0 +#define PCIE_PERF_REQ_FORCE_LOWPOWER 1 +#define PCIE_PERF_REQ_GEN1 2 +#define PCIE_PERF_REQ_GEN2 3 +#define PCIE_PERF_REQ_GEN3 4 + +enum PHM_BackEnd_Magic { + PHM_Dummy_Magic = 0xAA5555AA, + PHM_RV770_Magic = 0xDCBAABCD, + PHM_Kong_Magic = 0x239478DF, + PHM_NIslands_Magic = 0x736C494E, + PHM_Sumo_Magic = 0x8339FA11, + PHM_SIslands_Magic = 0x369431AC, + PHM_Trinity_Magic = 0x96751873, + PHM_CIslands_Magic = 0x38AC78B0, + PHM_Kv_Magic = 0xDCBBABC0, + PHM_VIslands_Magic = 0x20130307, + PHM_Cz_Magic = 0x67DCBA25, + PHM_Rv_Magic = 0x20161121 +}; + +struct phm_set_power_state_input { + const struct pp_hw_power_state *pcurrent_state; + const struct pp_hw_power_state *pnew_state; +}; + +struct phm_clock_array { + uint32_t count; + uint32_t values[1]; +}; + +struct phm_clock_voltage_dependency_record { + uint32_t clk; + uint32_t v; +}; + +struct phm_vceclock_voltage_dependency_record { + uint32_t ecclk; + uint32_t evclk; + uint32_t v; +}; + +struct phm_uvdclock_voltage_dependency_record { + uint32_t vclk; + uint32_t dclk; + uint32_t v; +}; + +struct phm_samuclock_voltage_dependency_record { + uint32_t samclk; + uint32_t v; +}; + +struct phm_acpclock_voltage_dependency_record { + uint32_t acpclk; + uint32_t v; +}; + +struct phm_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + struct phm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_phase_shedding_limits_record { + uint32_t Voltage; + uint32_t Sclk; + uint32_t Mclk; +}; + +struct phm_uvd_clock_voltage_dependency_record { + uint32_t vclk; + uint32_t dclk; + uint32_t v; +}; + +struct phm_uvd_clock_voltage_dependency_table { + uint8_t count; + struct phm_uvd_clock_voltage_dependency_record entries[1]; +}; + +struct phm_acp_clock_voltage_dependency_record { + uint32_t acpclk; + uint32_t v; +}; + +struct phm_acp_clock_voltage_dependency_table { + uint32_t count; + struct phm_acp_clock_voltage_dependency_record entries[1]; +}; + +struct phm_vce_clock_voltage_dependency_record { + uint32_t ecclk; + uint32_t evclk; + uint32_t v; +}; + +struct phm_phase_shedding_limits_table { + uint32_t count; + struct phm_phase_shedding_limits_record entries[1]; +}; + +struct phm_vceclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_uvdclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_samuclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_acpclock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_vce_clock_voltage_dependency_table { + uint8_t count; + struct phm_vce_clock_voltage_dependency_record entries[1]; +}; + + +enum SMU_ASIC_RESET_MODE +{ + SMU_ASIC_RESET_MODE_0, + SMU_ASIC_RESET_MODE_1, + SMU_ASIC_RESET_MODE_2, +}; + +struct pp_smumgr_func { + char *name; + int (*smu_init)(struct pp_hwmgr *hwmgr); + int (*smu_fini)(struct pp_hwmgr *hwmgr); + int (*start_smu)(struct pp_hwmgr *hwmgr); + int (*check_fw_load_finish)(struct pp_hwmgr *hwmgr, + uint32_t firmware); + int (*request_smu_load_fw)(struct pp_hwmgr *hwmgr); + int (*request_smu_load_specific_fw)(struct pp_hwmgr *hwmgr, + uint32_t firmware); + uint32_t (*get_argument)(struct pp_hwmgr *hwmgr); + int (*send_msg_to_smc)(struct pp_hwmgr *hwmgr, uint16_t msg); + int (*send_msg_to_smc_with_parameter)(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter); + int (*download_pptable_settings)(struct pp_hwmgr *hwmgr, + void **table); + int (*upload_pptable_settings)(struct pp_hwmgr *hwmgr); + int (*update_smc_table)(struct pp_hwmgr *hwmgr, uint32_t type); + int (*process_firmware_header)(struct pp_hwmgr *hwmgr); + int (*update_sclk_threshold)(struct pp_hwmgr *hwmgr); + int (*thermal_setup_fan_table)(struct pp_hwmgr *hwmgr); + int (*thermal_avfs_enable)(struct pp_hwmgr *hwmgr); + int (*init_smc_table)(struct pp_hwmgr *hwmgr); + int (*populate_all_graphic_levels)(struct pp_hwmgr *hwmgr); + int (*populate_all_memory_levels)(struct pp_hwmgr *hwmgr); + int (*initialize_mc_reg_table)(struct pp_hwmgr *hwmgr); + uint32_t (*get_offsetof)(uint32_t type, uint32_t member); + uint32_t (*get_mac_definition)(uint32_t value); + bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); + bool (*is_hw_avfs_present)(struct pp_hwmgr *hwmgr); + int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting); + int (*smc_table_manager)(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); /*rw: true for read, false for write */ +}; + +struct pp_hwmgr_func { + int (*backend_init)(struct pp_hwmgr *hw_mgr); + int (*backend_fini)(struct pp_hwmgr *hw_mgr); + int (*asic_setup)(struct pp_hwmgr *hw_mgr); + int (*get_power_state_size)(struct pp_hwmgr *hw_mgr); + + int (*apply_state_adjust_rules)(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps); + + int (*apply_clocks_adjust_rules)(struct pp_hwmgr *hwmgr); + + int (*force_dpm_level)(struct pp_hwmgr *hw_mgr, + enum amd_dpm_forced_level level); + + int (*dynamic_state_management_enable)( + struct pp_hwmgr *hw_mgr); + int (*dynamic_state_management_disable)( + struct pp_hwmgr *hw_mgr); + + int (*patch_boot_state)(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps); + + int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, + unsigned long, struct pp_power_state *); + int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); + int (*powerdown_uvd)(struct pp_hwmgr *hwmgr); + void (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); + void (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); + void (*powergate_acp)(struct pp_hwmgr *hwmgr, bool bgate); + uint32_t (*get_mclk)(struct pp_hwmgr *hwmgr, bool low); + uint32_t (*get_sclk)(struct pp_hwmgr *hwmgr, bool low); + int (*power_state_set)(struct pp_hwmgr *hwmgr, + const void *state); + int (*notify_smc_display_config_after_ps_adjustment)(struct pp_hwmgr *hwmgr); + int (*pre_display_config_changed)(struct pp_hwmgr *hwmgr); + int (*display_config_changed)(struct pp_hwmgr *hwmgr); + int (*disable_clock_power_gating)(struct pp_hwmgr *hwmgr); + int (*update_clock_gatings)(struct pp_hwmgr *hwmgr, + const uint32_t *msg_id); + int (*set_max_fan_rpm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); + int (*set_max_fan_pwm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); + int (*stop_thermal_controller)(struct pp_hwmgr *hwmgr); + int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); + void (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode); + uint32_t (*get_fan_control_mode)(struct pp_hwmgr *hwmgr); + int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent); + int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed); + int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent); + int (*get_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t *speed); + int (*reset_fan_speed_to_default)(struct pp_hwmgr *hwmgr); + int (*uninitialize_thermal_controller)(struct pp_hwmgr *hwmgr); + int (*register_irq_handlers)(struct pp_hwmgr *hwmgr); + bool (*check_smc_update_required_for_display_configuration)(struct pp_hwmgr *hwmgr); + int (*check_states_equal)(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal); + int (*set_cpu_power_state)(struct pp_hwmgr *hwmgr); + int (*store_cc6_data)(struct pp_hwmgr *hwmgr, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, + bool pstate_switch_disable); + int (*get_dal_power_level)(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info); + int (*get_performance_level)(struct pp_hwmgr *, const struct pp_hw_power_state *, + PHM_PerformanceLevelDesignation, uint32_t, PHM_PerformanceLevel *); + int (*get_current_shallow_sleep_clocks)(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *state, struct pp_clock_info *clock_info); + int (*get_clock_by_type)(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks); + int (*get_clock_by_type_with_latency)(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks); + int (*get_clock_by_type_with_voltage)(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks); + int (*set_watermarks_for_clocks_ranges)(struct pp_hwmgr *hwmgr, void *clock_ranges); + int (*display_clock_voltage_request)(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock); + int (*get_max_high_clocks)(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); + int (*power_off_asic)(struct pp_hwmgr *hwmgr); + int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); + int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); + int (*powergate_gfx)(struct pp_hwmgr *hwmgr, bool enable); + int (*get_sclk_od)(struct pp_hwmgr *hwmgr); + int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); + int (*get_mclk_od)(struct pp_hwmgr *hwmgr); + int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); + int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size); + int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); + int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); + int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); + int (*set_min_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); + int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size); + int (*update_nbdpm_pstate)(struct pp_hwmgr *hwmgr, + bool enable, + bool lock); + int (*get_thermal_temperature_range)(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range); + int (*get_power_profile_mode)(struct pp_hwmgr *hwmgr, char *buf); + int (*set_power_profile_mode)(struct pp_hwmgr *hwmgr, long *input, uint32_t size); + int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size); + int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); + int (*powergate_mmhub)(struct pp_hwmgr *hwmgr); + int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); + int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate); + int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); + int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); + int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); + int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); + int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf); + int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks); + int (*set_mp1_state)(struct pp_hwmgr *hwmgr, enum pp_mp1_state mp1_state); + int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode); + int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire); + int (*set_df_cstate)(struct pp_hwmgr *hwmgr, enum pp_df_cstate state); + int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate); + int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr, + bool disable); + ssize_t (*get_gpu_metrics)(struct pp_hwmgr *hwmgr, void **table); +}; + +struct pp_table_func { + int (*pptable_init)(struct pp_hwmgr *hw_mgr); + int (*pptable_fini)(struct pp_hwmgr *hw_mgr); + int (*pptable_get_number_of_vce_state_table_entries)(struct pp_hwmgr *hw_mgr); + int (*pptable_get_vce_state_table_entry)( + struct pp_hwmgr *hwmgr, + unsigned long i, + struct amd_vce_state *vce_state, + void **clock_info, + unsigned long *flag); +}; + +union phm_cac_leakage_record { + struct { + uint16_t Vddc; /* in CI, we use it for StdVoltageHiSidd */ + uint32_t Leakage; /* in CI, we use it for StdVoltageLoSidd */ + }; + struct { + uint16_t Vddc1; + uint16_t Vddc2; + uint16_t Vddc3; + }; +}; + +struct phm_cac_leakage_table { + uint32_t count; + union phm_cac_leakage_record entries[1]; +}; + +struct phm_samu_clock_voltage_dependency_record { + uint32_t samclk; + uint32_t v; +}; + + +struct phm_samu_clock_voltage_dependency_table { + uint8_t count; + struct phm_samu_clock_voltage_dependency_record entries[1]; +}; + +struct phm_cac_tdp_table { + uint16_t usTDP; + uint16_t usConfigurableTDP; + uint16_t usTDC; + uint16_t usBatteryPowerLimit; + uint16_t usSmallPowerLimit; + uint16_t usLowCACLeakage; + uint16_t usHighCACLeakage; + uint16_t usMaximumPowerDeliveryLimit; + uint16_t usEDCLimit; + uint16_t usOperatingTempMinLimit; + uint16_t usOperatingTempMaxLimit; + uint16_t usOperatingTempStep; + uint16_t usOperatingTempHyst; + uint16_t usDefaultTargetOperatingTemp; + uint16_t usTargetOperatingTemp; + uint16_t usPowerTuneDataSetID; + uint16_t usSoftwareShutdownTemp; + uint16_t usClockStretchAmount; + uint16_t usTemperatureLimitHotspot; + uint16_t usTemperatureLimitLiquid1; + uint16_t usTemperatureLimitLiquid2; + uint16_t usTemperatureLimitVrVddc; + uint16_t usTemperatureLimitVrMvdd; + uint16_t usTemperatureLimitPlx; + uint8_t ucLiquid1_I2C_address; + uint8_t ucLiquid2_I2C_address; + uint8_t ucLiquid_I2C_Line; + uint8_t ucVr_I2C_address; + uint8_t ucVr_I2C_Line; + uint8_t ucPlx_I2C_address; + uint8_t ucPlx_I2C_Line; + uint32_t usBoostPowerLimit; + uint8_t ucCKS_LDO_REFSEL; +}; + +struct phm_tdp_table { + uint16_t usTDP; + uint16_t usConfigurableTDP; + uint16_t usTDC; + uint16_t usBatteryPowerLimit; + uint16_t usSmallPowerLimit; + uint16_t usLowCACLeakage; + uint16_t usHighCACLeakage; + uint16_t usMaximumPowerDeliveryLimit; + uint16_t usEDCLimit; + uint16_t usOperatingTempMinLimit; + uint16_t usOperatingTempMaxLimit; + uint16_t usOperatingTempStep; + uint16_t usOperatingTempHyst; + uint16_t usDefaultTargetOperatingTemp; + uint16_t usTargetOperatingTemp; + uint16_t usPowerTuneDataSetID; + uint16_t usSoftwareShutdownTemp; + uint16_t usClockStretchAmount; + uint16_t usTemperatureLimitTedge; + uint16_t usTemperatureLimitHotspot; + uint16_t usTemperatureLimitLiquid1; + uint16_t usTemperatureLimitLiquid2; + uint16_t usTemperatureLimitHBM; + uint16_t usTemperatureLimitVrVddc; + uint16_t usTemperatureLimitVrMvdd; + uint16_t usTemperatureLimitPlx; + uint8_t ucLiquid1_I2C_address; + uint8_t ucLiquid2_I2C_address; + uint8_t ucLiquid_I2C_Line; + uint8_t ucVr_I2C_address; + uint8_t ucVr_I2C_Line; + uint8_t ucPlx_I2C_address; + uint8_t ucPlx_I2C_Line; + uint8_t ucLiquid_I2C_LineSDA; + uint8_t ucVr_I2C_LineSDA; + uint8_t ucPlx_I2C_LineSDA; + uint32_t usBoostPowerLimit; + uint16_t usBoostStartTemperature; + uint16_t usBoostStopTemperature; + uint32_t ulBoostClock; +}; + +struct phm_ppm_table { + uint8_t ppm_design; + uint16_t cpu_core_number; + uint32_t platform_tdp; + uint32_t small_ac_platform_tdp; + uint32_t platform_tdc; + uint32_t small_ac_platform_tdc; + uint32_t apu_tdp; + uint32_t dgpu_tdp; + uint32_t dgpu_ulv_power; + uint32_t tj_max; +}; + +struct phm_vq_budgeting_record { + uint32_t ulCUs; + uint32_t ulSustainableSOCPowerLimitLow; + uint32_t ulSustainableSOCPowerLimitHigh; + uint32_t ulMinSclkLow; + uint32_t ulMinSclkHigh; + uint8_t ucDispConfig; + uint32_t ulDClk; + uint32_t ulEClk; + uint32_t ulSustainableSclk; + uint32_t ulSustainableCUs; +}; + +struct phm_vq_budgeting_table { + uint8_t numEntries; + struct phm_vq_budgeting_record entries[1]; +}; + +struct phm_clock_and_voltage_limits { + uint32_t sclk; + uint32_t mclk; + uint32_t gfxclk; + uint16_t vddc; + uint16_t vddci; + uint16_t vddgfx; + uint16_t vddmem; +}; + +/* Structure to hold PPTable information */ + +struct phm_ppt_v1_information { + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_socclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dcefclk; + struct phm_clock_array *valid_sclk_values; + struct phm_clock_array *valid_mclk_values; + struct phm_clock_array *valid_socclk_values; + struct phm_clock_array *valid_dcefclk_values; + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; + struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; + struct phm_ppm_table *ppm_parameter_table; + struct phm_cac_tdp_table *cac_dtp_table; + struct phm_tdp_table *tdp_table; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddmem_lookup_table; + struct phm_ppt_v1_pcie_table *pcie_table; + struct phm_ppt_v1_gpio_table *gpio_table; + uint16_t us_ulv_voltage_offset; + uint16_t us_ulv_smnclk_did; + uint16_t us_ulv_mp1clk_did; + uint16_t us_ulv_gfxclk_bypass; + uint16_t us_gfxclk_slew_rate; + uint16_t us_min_gfxclk_freq_limit; +}; + +struct phm_ppt_v2_information { + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_socclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dcefclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_pixclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dispclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_phyclk; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table; + + struct phm_clock_voltage_dependency_table *vddc_dep_on_dalpwrl; + + struct phm_clock_array *valid_sclk_values; + struct phm_clock_array *valid_mclk_values; + struct phm_clock_array *valid_socclk_values; + struct phm_clock_array *valid_dcefclk_values; + + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; + + struct phm_ppm_table *ppm_parameter_table; + struct phm_cac_tdp_table *cac_dtp_table; + struct phm_tdp_table *tdp_table; + + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddmem_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddci_lookup_table; + + struct phm_ppt_v1_pcie_table *pcie_table; + + uint16_t us_ulv_voltage_offset; + uint16_t us_ulv_smnclk_did; + uint16_t us_ulv_mp1clk_did; + uint16_t us_ulv_gfxclk_bypass; + uint16_t us_gfxclk_slew_rate; + uint16_t us_min_gfxclk_freq_limit; + + uint8_t uc_gfx_dpm_voltage_mode; + uint8_t uc_soc_dpm_voltage_mode; + uint8_t uc_uclk_dpm_voltage_mode; + uint8_t uc_uvd_dpm_voltage_mode; + uint8_t uc_vce_dpm_voltage_mode; + uint8_t uc_mp0_dpm_voltage_mode; + uint8_t uc_dcef_dpm_voltage_mode; +}; + +struct phm_ppt_v3_information +{ + uint8_t uc_thermal_controller_type; + + uint16_t us_small_power_limit1; + uint16_t us_small_power_limit2; + uint16_t us_boost_power_limit; + + uint16_t us_od_turbo_power_limit; + uint16_t us_od_powersave_power_limit; + uint16_t us_software_shutdown_temp; + + uint32_t *power_saving_clock_max; + uint32_t *power_saving_clock_min; + + uint8_t *od_feature_capabilities; + uint32_t *od_settings_max; + uint32_t *od_settings_min; + + void *smc_pptable; +}; + +struct phm_dynamic_state_info { + struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; + struct phm_clock_array *valid_sclk_values; + struct phm_clock_array *valid_mclk_values; + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; + uint32_t mclk_sclk_ratio; + uint32_t sclk_mclk_delta; + uint32_t vddc_vddci_delta; + uint32_t min_vddc_for_pcie_gen2; + struct phm_cac_leakage_table *cac_leakage_table; + struct phm_phase_shedding_limits_table *vddc_phase_shed_limits_table; + + struct phm_vce_clock_voltage_dependency_table + *vce_clock_voltage_dependency_table; + struct phm_uvd_clock_voltage_dependency_table + *uvd_clock_voltage_dependency_table; + struct phm_acp_clock_voltage_dependency_table + *acp_clock_voltage_dependency_table; + struct phm_samu_clock_voltage_dependency_table + *samu_clock_voltage_dependency_table; + + struct phm_ppm_table *ppm_parameter_table; + struct phm_cac_tdp_table *cac_dtp_table; + struct phm_clock_voltage_dependency_table *vdd_gfx_dependency_on_sclk; +}; + +struct pp_fan_info { + bool bNoFan; + uint8_t ucTachometerPulsesPerRevolution; + uint32_t ulMinRPM; + uint32_t ulMaxRPM; +}; + +struct pp_advance_fan_control_parameters { + uint16_t usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + uint16_t usTMed; /* The middle temperature where we change slopes. */ + uint16_t usTHigh; /* The high temperature for setting the second slope. */ + uint16_t usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + uint16_t usPWMMed; /* The PWM value (in percent) at TMed. */ + uint16_t usPWMHigh; /* The PWM value at THigh. */ + uint8_t ucTHyst; /* Temperature hysteresis. Integer. */ + uint32_t ulCycleDelay; /* The time between two invocations of the fan control routine in microseconds. */ + uint16_t usTMax; /* The max temperature */ + uint8_t ucFanControlMode; + uint16_t usFanPWMMinLimit; + uint16_t usFanPWMMaxLimit; + uint16_t usFanPWMStep; + uint16_t usDefaultMaxFanPWM; + uint16_t usFanOutputSensitivity; + uint16_t usDefaultFanOutputSensitivity; + uint16_t usMaxFanPWM; /* The max Fan PWM value for Fuzzy Fan Control feature */ + uint16_t usFanRPMMinLimit; /* Minimum limit range in percentage, need to calculate based on minRPM/MaxRpm */ + uint16_t usFanRPMMaxLimit; /* Maximum limit range in percentage, usually set to 100% by default */ + uint16_t usFanRPMStep; /* Step increments/decerements, in percent */ + uint16_t usDefaultMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, default from PPTable */ + uint16_t usMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, user defined */ + uint16_t usFanCurrentLow; /* Low current */ + uint16_t usFanCurrentHigh; /* High current */ + uint16_t usFanRPMLow; /* Low RPM */ + uint16_t usFanRPMHigh; /* High RPM */ + uint32_t ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + uint8_t ucTargetTemperature; /* Advanced fan controller target temperature. */ + uint8_t ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + uint16_t usFanGainEdge; /* The following is added for Fiji */ + uint16_t usFanGainHotspot; + uint16_t usFanGainLiquid; + uint16_t usFanGainVrVddc; + uint16_t usFanGainVrMvdd; + uint16_t usFanGainPlx; + uint16_t usFanGainHbm; + uint8_t ucEnableZeroRPM; + uint8_t ucFanStopTemperature; + uint8_t ucFanStartTemperature; + uint32_t ulMaxFanSCLKAcousticLimit; /* Maximum Fan Controller SCLK Frequency Acoustic Limit. */ + uint32_t ulTargetGfxClk; + uint16_t usZeroRPMStartTemperature; + uint16_t usZeroRPMStopTemperature; + uint16_t usMGpuThrottlingRPMLimit; +}; + +struct pp_thermal_controller_info { + uint8_t ucType; + uint8_t ucI2cLine; + uint8_t ucI2cAddress; + uint8_t use_hw_fan_control; + struct pp_fan_info fanInfo; + struct pp_advance_fan_control_parameters advanceFanControlParameters; +}; + +struct phm_microcode_version_info { + uint32_t SMC; + uint32_t DMCU; + uint32_t MC; + uint32_t NB; +}; + +enum PP_TABLE_VERSION { + PP_TABLE_V0 = 0, + PP_TABLE_V1, + PP_TABLE_V2, + PP_TABLE_MAX +}; + +/** + * The main hardware manager structure. + */ +#define Workload_Policy_Max 6 + +struct pp_hwmgr { + void *adev; + uint32_t chip_family; + uint32_t chip_id; + uint32_t smu_version; + bool not_vf; + bool pm_en; + bool pp_one_vf; + struct mutex smu_lock; + struct mutex msg_lock; + + uint32_t pp_table_version; + void *device; + struct pp_smumgr *smumgr; + const void *soft_pp_table; + uint32_t soft_pp_table_size; + void *hardcode_pp_table; + bool need_pp_table_upload; + + struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; + uint32_t num_vce_state_tables; + + enum amd_dpm_forced_level dpm_level; + enum amd_dpm_forced_level saved_dpm_level; + enum amd_dpm_forced_level request_dpm_level; + uint32_t usec_timeout; + void *pptable; + struct phm_platform_descriptor platform_descriptor; + void *backend; + + void *smu_backend; + const struct pp_smumgr_func *smumgr_funcs; + bool is_kicker; + + enum PP_DAL_POWERLEVEL dal_power_level; + struct phm_dynamic_state_info dyn_state; + const struct pp_hwmgr_func *hwmgr_func; + const struct pp_table_func *pptable_func; + + struct pp_power_state *ps; + uint32_t num_ps; + struct pp_thermal_controller_info thermal_controller; + bool fan_ctrl_is_in_default_mode; + uint32_t fan_ctrl_default_mode; + bool fan_ctrl_enabled; + uint32_t tmin; + struct phm_microcode_version_info microcode_version_info; + uint32_t ps_size; + struct pp_power_state *current_ps; + struct pp_power_state *request_ps; + struct pp_power_state *boot_ps; + struct pp_power_state *uvd_ps; + const struct amd_pp_display_configuration *display_config; + uint32_t feature_mask; + bool avfs_supported; + /* UMD Pstate */ + bool en_umd_pstate; + uint32_t power_profile_mode; + uint32_t default_power_profile_mode; + uint32_t pstate_sclk; + uint32_t pstate_mclk; + bool od_enabled; + uint32_t power_limit; + uint32_t default_power_limit; + uint32_t workload_mask; + uint32_t workload_prority[Workload_Policy_Max]; + uint32_t workload_setting[Workload_Policy_Max]; + bool gfxoff_state_changed_by_workload; +}; + +int hwmgr_early_init(struct pp_hwmgr *hwmgr); +int hwmgr_sw_init(struct pp_hwmgr *hwmgr); +int hwmgr_sw_fini(struct pp_hwmgr *hwmgr); +int hwmgr_hw_init(struct pp_hwmgr *hwmgr); +int hwmgr_hw_fini(struct pp_hwmgr *hwmgr); +int hwmgr_suspend(struct pp_hwmgr *hwmgr); +int hwmgr_resume(struct pp_hwmgr *hwmgr); + +int hwmgr_handle_task(struct pp_hwmgr *hwmgr, + enum amd_pp_task task_id, + enum amd_pm_state_type *user_state); + + +#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU + + +#endif /* _HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h b/drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h new file mode 100644 index 000000000000..6a53b7e74ccd --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/polaris10_pwrvirus.h @@ -0,0 +1,1793 @@ +/* + * Copyright 2015 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 _POLARIS10_PWRVIRUS_H +#define _POLARIS10_PWRVIRUS_H + + +#define mmCP_HYP_MEC1_UCODE_ADDR 0xf81a +#define mmCP_HYP_MEC1_UCODE_DATA 0xf81b +#define mmCP_HYP_MEC2_UCODE_ADDR 0xf81c +#define mmCP_HYP_MEC2_UCODE_DATA 0xf81d + +struct PWR_Command_Table { + uint32_t data; + uint32_t reg; +}; + +typedef struct PWR_Command_Table PWR_Command_Table; + +struct PWR_DFY_Section { + uint32_t dfy_cntl; + uint32_t dfy_addr_hi, dfy_addr_lo; + uint32_t dfy_size; + uint32_t dfy_data[]; +}; + +typedef struct PWR_DFY_Section PWR_DFY_Section; + +static const PWR_Command_Table pwr_virus_table_pre[] = { + { 0x00000000, mmRLC_CNTL }, + { 0x00000002, mmRLC_SRM_CNTL }, + { 0x15000000, mmCP_ME_CNTL }, + { 0x50000000, mmCP_MEC_CNTL }, + { 0x80000004, mmCP_DFY_CNTL }, + { 0x0840800a, mmCP_RB0_CNTL }, + { 0xf30fff0f, mmTCC_CTRL }, + { 0x00000002, mmTCC_EXE_DISABLE }, + { 0x000000ff, mmTCP_ADDR_CONFIG }, + { 0x540ff000, mmCP_CPC_IC_BASE_LO }, + { 0x000000b4, mmCP_CPC_IC_BASE_HI }, + { 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, + { 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, + { 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00000000, 0xFFFFFFFF }, +}; + +static const PWR_DFY_Section pwr_virus_section1 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540fe800, + .dfy_data = { + 0x7e000200, 0x7e020201, 0x7e040204, 0x7e060205, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, + 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54106f00, 0x000400b4, 0x00004000, 0x00804fac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 416 +}; + +static const PWR_DFY_Section pwr_virus_section2 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540fef00, + .dfy_data = { + 0xc0031502, 0x00001e00, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 16 +}; + +static const PWR_DFY_Section pwr_virus_section3 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540ff000, + .dfy_data = { + 0xc424000b, 0x80000145, 0x94800001, 0x94c00001, 0x95000001, 0x95400001, 0x95800001, 0xdc810000, + 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xc4080061, 0xd8400013, 0xd8000003, 0xc40c0001, + 0x24ccffff, 0x3cd08000, 0x9500fffd, 0x1cd0ffcf, 0x7d018001, 0xc4140004, 0x050c0019, 0xd8400008, + 0x84c00000, 0x80000023, 0x80000067, 0x8000006a, 0x8000006d, 0x80000079, 0x80000084, 0x8000008f, + 0x80000099, 0x800000a0, 0x800000af, 0xd8400053, 0xc4080007, 0x388c0001, 0x08880002, 0x04100003, + 0x94c00005, 0x98800003, 0x04100004, 0x8000002d, 0x04100005, 0x8c00003f, 0x8c000043, 0x28cc0000, + 0xccc00050, 0x8c000055, 0x28080001, 0xcc000004, 0x7d808001, 0xd8400013, 0xd88130b8, 0xcd400008, + 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, 0xcc800005, 0xdc080000, 0x80000168, 0xc40c000e, + 0x28cc0008, 0xccc00013, 0x90000000, 0xcd013278, 0xc4113278, 0x95000001, 0x24cc0700, 0xd8400029, + 0xc4113255, 0xcd01324f, 0xc4113254, 0x1d10ffdf, 0xcd013254, 0x10cc0014, 0x1d10c017, 0x7d0d000a, + 0xd8400013, 0xd8400008, 0xcd0130b7, 0x14cc0010, 0x90000000, 0xd9c00036, 0x8000005d, 0xd8400013, + 0xc00c4000, 0xccc130b5, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc40c0021, 0x14d00011, 0x9500fffe, + 0xdc030000, 0xd800000c, 0xd800000d, 0xc40c005e, 0x94c01b10, 0xd8400013, 0x90000000, 0xc00e0080, + 0xccc130b5, 0x8000013b, 0xc00e0800, 0xccc130b5, 0x8000013b, 0xd8400053, 0x04100006, 0x8c00003f, + 0x8c000043, 0x28cc0000, 0xccc00050, 0x8c000055, 0x280c0008, 0xccc00052, 0xd8000021, 0x28180039, + 0x80000034, 0xd8400053, 0x04100007, 0x8c00003f, 0x8c000043, 0x28cc0001, 0xccc00050, 0x8c000055, + 0x280c0010, 0xccc00052, 0x28180039, 0x80000034, 0xd8400053, 0x04100008, 0x8c00003f, 0x8c000043, + 0x28cc0003, 0xccc00050, 0x8c000055, 0x280c0020, 0xccc00052, 0x28180039, 0x80000034, 0xdc030000, + 0xd8000069, 0x28080001, 0xc428000d, 0x7ca88004, 0xcc800079, 0x04280001, 0xcc00006f, 0x8000013b, + 0x80000034, 0x04100010, 0x8c00003f, 0x8c000043, 0xccc00078, 0x8c000055, 0x28180080, 0x80000034, + 0x04100001, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xcd013278, 0xc4113278, 0x95000001, 0xc00c4000, + 0xc4113254, 0x1d10c017, 0xd8400013, 0xd8400008, 0xccc130b5, 0xcd0130b7, 0x8000013b, 0x95c00001, + 0x96000001, 0x96400001, 0x96800001, 0x96c00001, 0x97000001, 0x97400001, 0x97800001, 0x97c00001, + 0xdc810000, 0xc40c000c, 0xcd4c0380, 0xcdcc0388, 0x55dc0020, 0xcdcc038c, 0xce0c0390, 0x56200020, + 0xce0c0394, 0xce4c0398, 0x56640020, 0xce4c039c, 0xce8c03a0, 0x56a80020, 0xce8c03a4, 0xcecc03a8, + 0x56ec0020, 0xcecc03ac, 0xcf0c03b0, 0x57300020, 0xcf0c03b4, 0xcf4c03b8, 0x57740020, 0xcf4c03bc, + 0xcf8c03c0, 0x57b80020, 0xcf8c03c4, 0xcfcc03c8, 0x57fc0020, 0xcfcc03cc, 0xd9000033, 0xc41c0009, + 0x25dc0010, 0x95c0fffe, 0xd8400013, 0xc41c000c, 0x05dc002f, 0xcdc12009, 0xc41d200a, 0xd8400013, + 0xcc012009, 0xd9000034, 0x25e01c00, 0x12200013, 0x25e40300, 0x12640008, 0x25e800c0, 0x12a80002, + 0x25ec003f, 0x7e25c00a, 0x7eae400a, 0x7de5c00a, 0xddc10000, 0xc02ee000, 0xcec1c200, 0xc40c005f, + 0xccc00037, 0x24d000ff, 0x31100006, 0x9500007b, 0x8c000190, 0xdc1c0000, 0xd8400013, 0xcdc1c200, + 0xc40c000c, 0xc4df0388, 0xc4d7038c, 0x51540020, 0x7d5dc01a, 0xc4e30390, 0xc4d70394, 0x51540020, + 0x7d62001a, 0xc4e70398, 0xc4d7039c, 0x51540020, 0x7d66401a, 0xc4eb03a0, 0xc4d703a4, 0x51540020, + 0x7d6a801a, 0xc4ef03a8, 0xc4d703ac, 0x51540020, 0x7d6ec01a, 0xc4f303b0, 0xc4d703b4, 0x51540020, + 0x7d73001a, 0xc4f703b8, 0xc4d703bc, 0x51540020, 0x7d77401a, 0xc4fb03c0, 0xc4d703c4, 0x51540020, + 0x7d7b801a, 0xc4ff03c8, 0xc4d703cc, 0x51540020, 0x7d7fc01a, 0xdc080000, 0xcc800013, 0xc4d70380, + 0xc4080001, 0x1c88001c, 0xcd400008, 0xc40c0083, 0x94c00010, 0xdc0e0000, 0x94c0000e, 0xc40c0082, + 0x24d00001, 0x9900000b, 0x18cc01e3, 0x3cd00004, 0x95000008, 0xc40c0085, 0x18cc006a, 0x98c00005, + 0xc40c0082, 0x18cc01e3, 0x3cd00004, 0x9900fffa, 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, + 0xcc800004, 0xdc080000, 0x90000000, 0xc4080001, 0x1c88001c, 0xcd400008, 0xdc180000, 0xdc140000, + 0xdc100000, 0xdc0c0000, 0xcc800004, 0xdc080000, 0x90000000, 0xd8400051, 0xc428000c, 0x04180018, + 0x32640002, 0x9a80001f, 0x9a40001e, 0xcd800013, 0xc4293265, 0x040c0000, 0x1aac0027, 0x2aa80080, + 0xce813265, 0x9ac00017, 0xd80002f1, 0x04080002, 0x08880001, 0xd8080250, 0xd8080258, 0xd8080230, + 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, 0xd8080278, 0xd8080280, 0xd8080228, + 0xd8000367, 0x9880fff3, 0x04080010, 0x08880001, 0xd80c0309, 0xd80c0319, 0x04cc0001, 0x9880fffc, + 0x7c408001, 0x88000000, 0xc00e0100, 0xd8400013, 0xd8400008, 0xccc130b5, 0x8000016e, 0xc4180032, + 0x29980008, 0xcd800013, 0x95800001, 0x7c40c001, 0x18d0003f, 0x24d4001f, 0x24d80001, 0x155c0001, + 0x05e80180, 0x9900000b, 0x202c003d, 0xcd800010, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x86800000, + 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0xc4200007, 0x0a200001, 0xce000010, 0x80001b70, + 0x7c40c001, 0x8c000190, 0xc410001b, 0xd8000032, 0xd8000031, 0x9900091a, 0x7c408001, 0x88000000, + 0x24d000ff, 0x05280196, 0x18d4fe04, 0x29540008, 0xcd400013, 0x86800000, 0x800001b4, 0x8000032b, + 0x80000350, 0x80000352, 0x8000035f, 0x80000701, 0x8000047c, 0x8000019f, 0x80000800, 0xc419325b, + 0x1d98001f, 0xcd81325b, 0x8c00003f, 0xc4140004, 0xd8400008, 0x04100002, 0x8c000043, 0x28cc0002, + 0xccc00050, 0xc43c0044, 0x27fc0003, 0x9bc00002, 0x97c00006, 0xc00c4000, 0xccc130b5, 0x8c000055, + 0xd8400013, 0xd88130b8, 0xcd400008, 0x90000000, 0xd8400008, 0xcd400013, 0x7d40c001, 0xd8400028, + 0xd8400029, 0xd9400036, 0xc4193256, 0xc41d3254, 0x15540008, 0xcd400009, 0xcd40005b, 0xcd40005e, + 0xcd40005d, 0xd840006d, 0xc421325a, 0xc42d3249, 0x11540015, 0x19a4003c, 0x1998003f, 0x1af0007d, + 0x11dc000b, 0x1264001f, 0x15dc000d, 0x7d65400a, 0x13300018, 0x1a38003f, 0x7dd5c00a, 0x7df1c00a, + 0xcd800045, 0xcdc00100, 0xc411326a, 0xc415326b, 0xc419326c, 0xc41d326d, 0xc425326e, 0xc4293279, + 0xce800077, 0xcd000056, 0xcd400057, 0xcd800058, 0xcdc00059, 0xc4193265, 0x259c8000, 0x99c00004, + 0xce40005a, 0x29988000, 0xcd813265, 0xc4113248, 0x2510000f, 0xcd000073, 0xc418000d, 0xc411326f, + 0x17300019, 0x97000009, 0x25140fff, 0x95400007, 0xd800003a, 0x8c001b6d, 0xc4153279, 0xcd400077, + 0xcd00005f, 0xd8000075, 0x26f00001, 0x15100010, 0x7d190004, 0xcd000035, 0x97000035, 0x1af07fe8, + 0xd8800013, 0xd8400010, 0xd8400008, 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, + 0x04300010, 0xdf430000, 0x7c434001, 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, + 0xdf030000, 0xd4412e40, 0xd8400013, 0xcc41c030, 0xcc41c031, 0xc43dc031, 0xccc00013, 0x04343000, + 0xc4113246, 0xc41d3245, 0xcf413267, 0x51100020, 0x7dd1c01a, 0xc4353267, 0x45dc0160, 0xc810001f, + 0x1b4c0057, 0x1b700213, 0x1b740199, 0x7f4f400a, 0x7f73400a, 0x55180020, 0x2198003f, 0xd1c00025, + 0xcf400024, 0xcd000026, 0xcd800026, 0xd8400027, 0x9bc00001, 0x248dfffe, 0xd8800013, 0xccc12e00, + 0x7c434001, 0x7c434001, 0x8c00142b, 0xc43c000e, 0x1af4007d, 0x2bfc0008, 0x33740003, 0x26d80001, + 0xcfc00013, 0x1ae8003e, 0x9680000c, 0xc4253277, 0x26680001, 0x96800009, 0x2a640002, 0xce413277, + 0xd8400013, 0xc4253348, 0xce413348, 0xc4253348, 0x96400001, 0xcfc00013, 0x9b400003, 0x958000d8, + 0x80000315, 0xc4253277, 0x04303000, 0x26680001, 0xcf013267, 0xc4193246, 0xc41d3245, 0xc4313267, + 0x96800041, 0x51980020, 0x1b342010, 0x7d9d801a, 0x1714000c, 0x25540800, 0x1b30c012, 0x459801b0, + 0x7d77400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0xd180001e, 0xd8400021, 0x04240010, 0x199c01e2, + 0x7e5e4002, 0x3e5c0004, 0x3e540002, 0xc428000f, 0x9a80ffff, 0x95c00006, 0xc80c0011, 0xc8140011, + 0x54d00020, 0x55580020, 0x80000282, 0x95400015, 0xc80c0011, 0x0a640002, 0x041c0001, 0x45980008, + 0x54d00020, 0x96400004, 0xc8140011, 0x45980004, 0x041c0000, 0xcf00001c, 0xd180001e, 0xd8400021, + 0xc428000f, 0x9a80ffff, 0x99c00003, 0xc8180011, 0x80000282, 0xc8140011, 0x55580020, 0x80000282, + 0x45980004, 0xc80c0011, 0xcf00001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8100011, + 0xc8140011, 0x55580020, 0xd8400013, 0xccc1334e, 0xcd01334f, 0xcd413350, 0xcd813351, 0xd881334d, + 0xcfc00013, 0xc4193273, 0xc41d3275, 0xc40d3271, 0xc4113270, 0xc4153274, 0x50cc0020, 0x7cd0c01a, + 0x7cdcc011, 0x05900008, 0xcd00006a, 0xcdc0006b, 0xc41d3272, 0x7d594002, 0x54d00020, 0xd8800013, + 0xccc12e23, 0xcd012e24, 0xcdc12e25, 0xcfc00013, 0xc4193246, 0xc41d3245, 0xc4313267, 0x15540002, + 0x51980020, 0x7d9d801a, 0xc81c001f, 0x1b340057, 0x1b280213, 0x1b300199, 0x45980198, 0x7f37000a, + 0x7f2b000a, 0x55e40020, 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0xcd40000d, + 0xcd40000a, 0xc40d3249, 0x20cc003c, 0xccc13249, 0xc4113274, 0xdd430000, 0xc01e0001, 0x29dc0002, + 0x04280000, 0xd8000036, 0xcc400078, 0xcc400078, 0x2d540002, 0x95400022, 0x078c0000, 0x07d40000, + 0x8c00120d, 0x8c001239, 0x8c001232, 0x04f80000, 0x057c0000, 0xcdc00013, 0xc414000d, 0xc41c0019, + 0x7dd5c005, 0x25dc0001, 0xd840007c, 0xd8400074, 0xd8400069, 0xc40c005e, 0x94c018a6, 0xd4412e22, + 0xd800007c, 0xc40c005e, 0x94c018a2, 0x95c00007, 0xc40c0019, 0x7cd4c005, 0x24cc0001, 0x94c00008, + 0x9680fffc, 0x800002e3, 0xc40c0057, 0x7cd0c002, 0x94c00003, 0x9680fffd, 0x800002e3, 0xd8000069, + 0xcfc00013, 0xcd013273, 0xcd013275, 0xd8000074, 0xc414005e, 0x9540188f, 0xcfc00013, 0xc40d3249, + 0xc013cfff, 0x7cd0c009, 0xccc13249, 0x9680000b, 0xc40c0077, 0x38d00001, 0x99000006, 0x04cc0002, + 0xdcc30000, 0xc40c005e, 0x94c01882, 0xd4400078, 0xd800000d, 0x80000304, 0x7c41c001, 0x7c41c001, + 0xd840002f, 0xc41c0015, 0x95c0ffff, 0xd8400030, 0xc41c0016, 0x95c0ffff, 0xd8000030, 0xc41c0016, + 0x99c0ffff, 0xd800002f, 0xc41c0015, 0x99c0ffff, 0xc81c001f, 0x49980198, 0x55e40020, 0x459801a0, + 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0x04302000, 0xcfc00013, 0xcf013267, + 0xc4313267, 0x96800004, 0x97000001, 0xd8000036, 0x80000329, 0xd8800013, 0xcc812e00, 0x04302000, + 0xcfc00013, 0xcf013267, 0xc4313267, 0x97000001, 0xc4193256, 0xc42d3249, 0x16ec001f, 0xd8000028, + 0xd800002b, 0x1998003e, 0xcec00031, 0xd8000036, 0xd8000010, 0x97800004, 0xd8400010, 0xce00000a, + 0x1a18003e, 0xcd800008, 0x90000000, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, + 0x7d43c001, 0xcd400013, 0xc4093249, 0x1888003e, 0x94800015, 0xd8400074, 0x8c000671, 0xcd400013, + 0x9a400006, 0xc419324c, 0x259c0001, 0x1598001f, 0x95c0000d, 0x9580000c, 0x99000003, 0xd8400036, + 0x04100001, 0xc40c0021, 0x14d80011, 0x24dc00ff, 0x31e00002, 0x31dc0003, 0x9580fff0, 0x9a000003, + 0x99c00002, 0xd9c00036, 0x94800004, 0xd8000074, 0xc418005e, 0x95801827, 0xcf800008, 0x90000000, + 0xd8800036, 0x90000000, 0xd8c00036, 0xc424000b, 0x32640002, 0x9a400004, 0xc4180014, 0x9580ffff, + 0xd840002f, 0xc40c0021, 0x14dc0011, 0x95c0fffe, 0xccc00037, 0x8c000190, 0x90000000, 0xd8400008, + 0xd800006d, 0xc41d3246, 0xc4193245, 0x51dc0020, 0x7d9d801a, 0xd8400028, 0xd8400029, 0xc420000b, + 0x32200002, 0x9a0000ad, 0x04200032, 0xd9000010, 0xde030000, 0xd8400033, 0x04080000, 0xc43c0009, + 0x27fc0002, 0x97c0fffe, 0xc42c0015, 0x96c0ffff, 0xd800002e, 0xc42d3249, 0x1af4003e, 0x9740004d, + 0xc428000d, 0xc4080060, 0x7ca88005, 0x24880001, 0x7f4b4009, 0x97400046, 0xc4313274, 0xc4100057, + 0x7d33400c, 0x97400009, 0x28240100, 0x7e6a4004, 0xce400079, 0x1eecffdd, 0xcec13249, 0xcf013273, + 0xcf013275, 0x800003c3, 0xc429326f, 0x1aa80030, 0x96800006, 0x28240001, 0xc428000d, 0x06a80008, + 0x7e6a8004, 0xce800035, 0xc41d3272, 0x25cc0001, 0x10cc0004, 0x19e80042, 0x25dc0006, 0x11dc0001, + 0x7e8e800a, 0x7de9c00a, 0xc40d3271, 0xc4293270, 0x50cc0020, 0x7ce8c01a, 0x7cd30011, 0x11e80007, + 0x2aa80000, 0xce80001c, 0xd300001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc4300011, 0x1b30003f, + 0x33300000, 0xc4240059, 0x1660001f, 0x7e320009, 0xc0328000, 0x7e72400a, 0x0430000c, 0x9a000002, + 0x04300008, 0xc02ac000, 0x7d310002, 0x17300002, 0x2aa87600, 0x7cd0c011, 0xcdc00024, 0xd0c00025, + 0xce800026, 0x04280222, 0xce800026, 0x96000002, 0xce400026, 0xd8400027, 0xc4280058, 0x22ec003d, + 0xcec13249, 0xcd013273, 0xce813275, 0xd800007b, 0xc8380018, 0x57b00020, 0x04343108, 0xc429325d, + 0x040c3000, 0x13740008, 0x2374007e, 0x32a80003, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, + 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0x94800003, 0xd4400078, 0x800003e7, 0x04200022, 0xde030000, + 0xccc00024, 0xd1800025, 0xcf400026, 0xd4400026, 0xd8400027, 0x04200010, 0xde030000, 0xccc00024, + 0x45980104, 0xd1800025, 0xd4400026, 0xcf800026, 0xcf000026, 0xd8400027, 0x49980104, 0x9a80000a, + 0xc81c001f, 0x45980168, 0x55e00020, 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, + 0x800003f2, 0x8c000448, 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xc40d3249, + 0x18cc003e, 0xd8400030, 0xc42c0016, 0x96c0ffff, 0xd8000030, 0xc42c0016, 0x9ac0ffff, 0xd800002f, + 0xc42c0015, 0x9ac0ffff, 0xd8400034, 0xc4300025, 0xc4340024, 0xc4380081, 0xcf813279, 0xcf41326e, + 0xcf01326d, 0x94c0000d, 0x254c0700, 0xc424001e, 0x10cc0010, 0x1a641fe8, 0x28cc0726, 0x2a640200, + 0xd8400013, 0xccc1237b, 0x2264003f, 0xcd400013, 0xd8813260, 0xce41325b, 0xc4240033, 0xc4280034, + 0xd9000036, 0xd8000010, 0x8c001427, 0x96400006, 0xde430000, 0xce40000c, 0xc40c005e, 0x94c01755, + 0xd4400078, 0x9680000a, 0xce80000a, 0x06a80002, 0xd8400010, 0xde830000, 0xce80000d, 0xc40c005e, + 0x94c0174c, 0xd4400078, 0xd8000010, 0x8c00142b, 0xc4393265, 0x2bb80040, 0xd8400032, 0xcf813265, + 0xc4200012, 0x9a00ffff, 0xc4100044, 0x19180024, 0xc8100072, 0x551c003f, 0x99c00003, 0x95800010, + 0x8000043d, 0xc00c8000, 0xd840006c, 0x28200000, 0x8000043f, 0xc00c4000, 0x282000f0, 0xcd400013, + 0xd8400008, 0xc4113255, 0xcd01324f, 0xd8400013, 0xd88130b8, 0xccc130b5, 0xce000053, 0x90000000, + 0x195c00e8, 0xc4100004, 0x2555fff0, 0xc0360001, 0x042c0000, 0x29540001, 0xd8400008, 0x04240000, + 0x04280004, 0xc420000b, 0x32200002, 0x9a000009, 0xcd400013, 0xcec1c200, 0xc5e124dc, 0x0aa80001, + 0x7ef6c001, 0x7e624001, 0x96000001, 0x9a80fff9, 0xc02ee000, 0xcd400013, 0x2555fff0, 0xcec1c200, + 0x29540008, 0xc81c001f, 0xcd400013, 0x55e00020, 0xc42d3255, 0xc4353259, 0xd8013260, 0x45980158, + 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, 0x49980158, 0x45980170, 0xc4200012, + 0x16200010, 0x9a00fffe, 0xccc00024, 0xd1800025, 0xc429324f, 0xce400026, 0xce800026, 0xcec00026, + 0xcf400026, 0xd8400027, 0xcd000008, 0x90000000, 0xc40d325b, 0x7d43c001, 0x195400e8, 0x1154000a, + 0x18dc00e8, 0x05e80488, 0x18d0006c, 0x18f807f0, 0x18e40077, 0x18ec0199, 0x7e6e400a, 0x86800000, + 0x8000048e, 0x80000494, 0x800004de, 0x80000685, 0x80000686, 0x800006ac, 0x1ccc001f, 0xccc1325b, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x90000000, 0xc4293254, 0x1264000a, 0xc4300004, 0x7d79400a, + 0x7e7a400a, 0x52a8001e, 0x15180001, 0x7d69401a, 0x202c007d, 0xcec1325b, 0x95000008, 0x95800028, + 0xc42d3267, 0xc4193246, 0xc41d3245, 0x1aec0028, 0xc40d325c, 0x800004cc, 0xc42d3256, 0xc419324e, + 0x26e8003f, 0x1aec003e, 0x12f4000e, 0xc41d324d, 0xc40d324f, 0x7d75401a, 0x04100002, 0x7d290004, + 0x7f8f4001, 0x7f52800f, 0x51980020, 0x7d9d801a, 0x50e00002, 0x51980008, 0x9a800002, 0x800004d1, + 0x7d0dc002, 0x6665fc00, 0x7e5e401a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, + 0xce400002, 0x7f534002, 0x6665fc00, 0x7e76401a, 0xd1800002, 0xce400002, 0x800004d7, 0xc42d325a, + 0xc4193258, 0x1aec003e, 0xc41d3257, 0xc4213259, 0x12f4000e, 0x7d75401a, 0x51980020, 0x52200002, + 0x7d9d801a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, 0xce400002, 0x202c003d, + 0xcf000008, 0xcfc00013, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x90000000, 0xc4193260, 0x259c0007, + 0x15980004, 0x05e804e3, 0x86800000, 0x800004e7, 0x800004f0, 0x80000505, 0x8000016a, 0xc4380004, + 0xcfc00013, 0xd8400008, 0xc435325d, 0xd801325b, 0x277401ef, 0xcf41325d, 0xcf800008, 0x90000000, + 0xc4380004, 0xd8400008, 0x8c000671, 0x9640fff4, 0x17e00008, 0xc418000d, 0xce000009, 0xd84131db, + 0xcf800008, 0xcd800009, 0xc430001e, 0xcfc00013, 0xc42d325b, 0x1b301ff8, 0x2b300400, 0x2330003f, + 0x26edf000, 0x7ef2c00a, 0xd8413260, 0xcec1325b, 0x90000000, 0x05a80507, 0x86800000, 0x8000050c, + 0x80000528, 0x8000057d, 0x800005c2, 0x800005f3, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, + 0x9a400012, 0x1bd400e8, 0xc42c004a, 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000c, 0xc4100019, + 0x7d150005, 0x25100001, 0x99000008, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, + 0xd801326f, 0x80000624, 0x04240012, 0x1be00fe4, 0xce413260, 0xce000066, 0xcf800008, 0x90000000, + 0xd8400068, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, 0x9a400013, 0x1bd400e8, 0xc42c004a, + 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000d, 0xc4100019, 0x7d150005, 0x25100001, 0x99000009, + 0xd8400067, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, 0xd801326f, 0x80000624, + 0x1bd400e8, 0xc42c0060, 0x7ed6c005, 0x26ec0001, 0xc4113271, 0xc4153270, 0xc4193272, 0xc41d3273, + 0x04280022, 0x51100020, 0x7d51401a, 0xc4113274, 0xc4213275, 0xc4253276, 0xc4313248, 0xd1400061, + 0x2730000f, 0x13300010, 0x7db1800a, 0xcd800060, 0x96c00002, 0x05dc0008, 0xcdc00062, 0x042c3000, + 0xcd000063, 0xce000064, 0xce400065, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xce813260, + 0x52ec0020, 0x7ef2c01a, 0xc820001f, 0x1b700057, 0x1b680213, 0x1b740199, 0x46ec0188, 0x7f73400a, + 0x7f6b400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, + 0xc418000d, 0x17e00008, 0xce000009, 0xcec13267, 0xc42d3267, 0x26e01000, 0x9a00fffe, 0xd8400013, + 0xd9c131fc, 0xcd800009, 0xcf800008, 0x96c00001, 0x90000000, 0xc4380004, 0xd8400008, 0xc4113277, + 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0x29dc0001, 0x25140001, 0x191807e4, + 0x192007ec, 0x95400004, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x9580000e, 0x09980001, 0x041c0001, + 0x95800005, 0x09980001, 0x51dc0001, 0x69dc0001, 0x9980fffd, 0x7de20014, 0x561c0020, 0xd8400013, + 0xce013344, 0xcdc13345, 0xcfc00013, 0x95400022, 0x042c3000, 0xcec13267, 0xc42d3246, 0xc4313245, + 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, 0xc419334e, 0xc41d334f, 0xc4213350, + 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, 0x1b740199, 0x46ec01b0, 0x7f6b400a, + 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, 0xcdc00026, 0xce000026, 0xce400026, + 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, 0x04280032, 0xce813260, 0xd8800068, + 0xcf800008, 0x90000000, 0xc4380004, 0xd8400008, 0x2010007d, 0xcd01325b, 0xc411325b, 0x1910003e, + 0x9500fffe, 0x04100040, 0xcd00001b, 0xd8400021, 0xc410000f, 0x9900ffff, 0x04100060, 0xcd00001b, + 0xd8400021, 0xc410000f, 0x9900ffff, 0xcfc00013, 0x2010003d, 0xcd01325b, 0xc4113277, 0x25140001, + 0x191807e4, 0x9540000b, 0x2511fffd, 0xcd013277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, + 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x95800005, 0xd8400013, 0xd8013344, 0xd8013345, + 0xcfc00013, 0xc4180050, 0xc41c0052, 0x04280042, 0xcd813273, 0xcdc13275, 0xce813260, 0xd9000068, + 0xd8400067, 0xcf800008, 0x90000000, 0x07d40000, 0x8c00120d, 0x8c00124f, 0x8c001232, 0x057c0000, + 0x042c3000, 0xc4380004, 0xcfc00013, 0xd8400008, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, + 0x52ec0020, 0x7ef2c01a, 0x1b680057, 0x1b700213, 0x1b740199, 0xc820001f, 0x46ec0190, 0x7f6b400a, + 0x7f73400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, + 0xcfc00013, 0xcec13267, 0xc4153249, 0x2154003d, 0xc41c0019, 0x1bd800e8, 0x7dd9c005, 0x25dc0001, + 0xc42c004a, 0xcd80005e, 0xc420004d, 0xcec0005e, 0x11dc0010, 0x7e1e000a, 0xcd413249, 0xce01326f, + 0x28340001, 0x05980008, 0x7f598004, 0xcd800035, 0x1be800e8, 0xc42c004a, 0xce80005e, 0xd801327a, + 0xd800005f, 0xd8000075, 0xd800007f, 0xc424004c, 0xce41326e, 0xcec0005e, 0x28240100, 0x7e6a4004, + 0xce400079, 0xc435325d, 0x277401ef, 0x04240020, 0xce41325e, 0xd801325b, 0xd8013260, 0xcf41325d, + 0xda000068, 0xcf800008, 0x90000000, 0xc4113277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, + 0x11dc0008, 0x29dc0001, 0x25140001, 0x9540002d, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x042c3000, + 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, + 0xc419334e, 0xc41d334f, 0xc4213350, 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, + 0x1b740199, 0x46ec01b0, 0x7f6b400a, 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, + 0xcdc00026, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, + 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, + 0x90000000, 0xc430000b, 0x33300002, 0x04240000, 0x9b000010, 0x1be000e8, 0x042c0000, 0xc0360001, + 0x04280004, 0xd8400013, 0xcec1c200, 0xc63124dc, 0x0aa80001, 0x7ef6c001, 0x7e724001, 0x97000001, + 0x9a80fff9, 0xc02ee000, 0xd8400013, 0xcec1c200, 0x90000000, 0x90000000, 0xc4253260, 0x7fc14001, + 0xc40d3249, 0x18cc003e, 0x98c00005, 0x194c1c03, 0xccc0003b, 0xc40c002d, 0x80000697, 0xc420004a, + 0x194c00e8, 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x98c00003, + 0x8c0007e0, 0x95c00008, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, 0xcf01325b, + 0x90000000, 0xcd400013, 0xd801325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x25100007, 0x31100005, + 0x9900008e, 0xc40c0007, 0xd9000010, 0x8000075e, 0x202c007d, 0xcec1325b, 0xc4293265, 0xc4353254, + 0x26a9feff, 0xc4380004, 0xd8400008, 0x1374000b, 0xc40c000d, 0xd8000009, 0x1774000d, 0xd8400013, + 0xc41d30b8, 0xcfc00013, 0x95c00008, 0xc411325d, 0xd801325b, 0xccc00009, 0xcf800008, 0x251001ef, + 0xcd01325d, 0x90000000, 0xce813265, 0xcf400100, 0xc00ac006, 0xc00e0000, 0x28880700, 0x28cc0014, + 0x8c0006de, 0x14cc0010, 0x30d4000f, 0x04cc0001, 0x10cc0010, 0x28cc0014, 0x99400009, 0xd8400013, + 0xc41530b8, 0xcfc00013, 0xc4193265, 0x19980028, 0x99400003, 0x99800002, 0x800006c8, 0xcfc00013, + 0xc411325d, 0xd801325b, 0xcf800008, 0x251001ef, 0xcd01325d, 0x90000000, 0x15600008, 0xce000009, + 0xc8380023, 0xc4180081, 0x11a00002, 0x7fa38011, 0xc4100026, 0x05980008, 0x7d1a0002, 0x282c2002, + 0x3e280008, 0xcec00013, 0xc4300027, 0x042c0008, 0xd3800025, 0xcf000024, 0x202400d0, 0x7ca48001, + 0xcc800026, 0xccc00026, 0x28240006, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800004, 0x32280000, + 0x9a800002, 0x9a000000, 0xd8400027, 0x24d8003f, 0xd840003c, 0xcec0003a, 0xd8800013, 0xcd81a2a4, + 0x90000000, 0xc41d325d, 0x25dc0007, 0xc40d3249, 0x18cc003e, 0x94c0000a, 0xc420004a, 0x194c00e8, + 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x80000712, 0x194c1c03, + 0xccc0003b, 0xc40c002d, 0x05e80714, 0x86800000, 0x8000071c, 0x80000720, 0x80000747, 0x8000071d, + 0x800007c4, 0x80000732, 0x80000745, 0x80000744, 0x90000000, 0x98c00006, 0x8000072e, 0x90000000, + 0x98c00003, 0x8c0007e0, 0x95c0000c, 0xcd400013, 0xc4253265, 0x2a64008c, 0xce413265, 0xc430001e, + 0x1b301fe8, 0x2b300400, 0x2330003f, 0xd8013260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, + 0x04240000, 0x8000075e, 0x98c0fff1, 0x8c0007e0, 0x95c00002, 0x80000723, 0xcd400013, 0xc41f02f1, + 0x95c00004, 0xd8013247, 0xd801325d, 0x80000743, 0xd8813247, 0xd801325d, 0xc4100004, 0xd8400008, + 0xd8400013, 0xd88130b8, 0xcd000008, 0x90000000, 0x04100001, 0x98c0ffde, 0x8000072e, 0x98c00003, + 0x8c0007e0, 0x95c00012, 0xc4340004, 0xd8400008, 0x15600008, 0xc418000d, 0xce000009, 0xd8400013, + 0xd84131db, 0xcf400008, 0xcd800009, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, + 0xd8413260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, 0x04240000, 0xcd400013, 0x041c3000, + 0xcdc13267, 0xc41d3267, 0xc41d3265, 0x25dc8000, 0x95c00007, 0xc41c004a, 0x195800e8, 0xcd80005e, + 0xc418004c, 0xcd81326e, 0xcdc0005e, 0xc41d3265, 0x25dd7fff, 0xcdc13265, 0xc41d3246, 0xc4193245, + 0xc42d3267, 0x51e00020, 0x7e1a001a, 0x46200200, 0x04283247, 0x04300033, 0x1af80057, 0x1af40213, + 0x042c000c, 0x7f7b400a, 0x7f6f400a, 0xcf400024, 0xd2000025, 0xcd800026, 0xcdc00026, 0xc6990000, + 0x329c325d, 0x99c00008, 0x329c3269, 0x99c00006, 0x329c3267, 0x95c00005, 0xc01defff, 0x7d9d8009, + 0x8000078a, 0x25980000, 0x0b300001, 0x06a80001, 0xcd800026, 0x9b00fff2, 0xd8400027, 0xc43c0012, + 0x9bc0ffff, 0xcd400013, 0xd801325b, 0xc431325a, 0xc03e7ff0, 0x7f3f0009, 0xcf01325a, 0xc4313249, + 0x1f30001f, 0xcf013249, 0xc03e4000, 0xcfc13254, 0xcd400013, 0xd8013254, 0xc431325d, 0xd801324f, + 0xd8013255, 0xd8013247, 0xd801325d, 0x1b300028, 0x8c00120d, 0x8c001219, 0x8c001232, 0xc4380004, + 0xd8400008, 0xd8400013, 0x9900000d, 0xd88130b8, 0x9700000b, 0xc43d30b5, 0x1bf0003a, 0x9b000b80, + 0x203c003a, 0xc430000e, 0x27300700, 0x13300014, 0x2b300001, 0xcf0130b7, 0xcfc130b5, 0x46200008, + 0xcf400024, 0xd2000025, 0xd8000026, 0xd8400027, 0x043c2000, 0xcd400013, 0xcfc13267, 0xc43d3267, + 0x9bc00001, 0xccc00010, 0xcf800008, 0x90000000, 0xc4080007, 0xd9000010, 0xc4193260, 0x259c0003, + 0x31dc0003, 0x95c00014, 0x040c3000, 0xd8400008, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, + 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0xc4193246, 0xc41d3245, 0x51980020, 0x7d9d801a, 0x8c000448, + 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xcc800010, 0xd801325d, 0x90000000, + 0xc418000b, 0x31980002, 0x041c0000, 0x9980001c, 0x19580066, 0x15600008, 0x040c0000, 0xc0120001, + 0x11980003, 0x04240004, 0x7da18001, 0xc4200007, 0xc4340004, 0xd9000010, 0xd8400008, 0xd8400013, + 0xccc1c200, 0xc41d24db, 0x7cd0c001, 0x0a640001, 0x7dd9c005, 0x25dc0001, 0x99c00002, 0x9a40fff8, + 0xc418005e, 0x9580137b, 0xc00ee000, 0xd8400013, 0xccc1c200, 0xce000010, 0xcf400008, 0x90000000, + 0xd840004f, 0xc4113269, 0x19080070, 0x190c00e8, 0x2510003f, 0x2518000f, 0xcd813268, 0x05a80809, + 0x86800000, 0x8000080e, 0x8000080f, 0x80000898, 0x80000946, 0x800009e1, 0x80000a5a, 0x04a80811, + 0x86800000, 0x80000815, 0x80000834, 0x8000085e, 0x8000085e, 0x04341001, 0xcf400013, 0xc4380004, + 0xd8400008, 0xc42d3045, 0xcec1c091, 0x31300021, 0x9700000b, 0xd84002f1, 0xd8400013, 0xc43130b8, + 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, 0xcf800008, 0x9b000241, 0x8000084a, 0xcf400013, + 0xd8400008, 0xc43130b6, 0x9b000003, 0xc02f0001, 0xcec130b6, 0xc4252087, 0x5668001a, 0x26a80005, + 0x9a80fffd, 0xcf400013, 0xd80130b6, 0x8000084a, 0xc4380004, 0xd8400008, 0x04341001, 0xcf400013, + 0xc431ecaa, 0x27300080, 0x9b000010, 0xc02e0001, 0xcec130b6, 0xcf400013, 0xd80130b6, 0x31300021, + 0x9700000a, 0xd84002f1, 0xd8400013, 0xc43130b8, 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, + 0xcf800008, 0x9b00021d, 0xdd410000, 0x040c0005, 0xd84802e9, 0x8c001a41, 0xc43b02f1, 0x9b800006, + 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0xcf800008, 0xcec80278, 0x56f00020, 0xcf080280, + 0x8c001608, 0xdc140000, 0xcd400013, 0xd8813247, 0xd80802e9, 0x8000085e, 0xcd400013, 0x31100011, + 0x950001fa, 0xc02e0001, 0x2aec0008, 0xc01c0020, 0xc0180001, 0xc00c0007, 0x11a40006, 0x7de6000a, + 0x10e40008, 0x7e26000a, 0x7e2e000a, 0xce000013, 0xc4113254, 0x1d10ffdf, 0x2110003e, 0xcd013254, + 0xd801324f, 0xd8013255, 0x1d10ff9e, 0xcd013254, 0xd8013247, 0xd801325d, 0xd801325e, 0xc0245301, + 0xce413249, 0xd801325f, 0xc425326c, 0xc0121fff, 0x29108eff, 0x7e524009, 0xce41326c, 0xc425325a, + 0xc0127ff0, 0x7e524009, 0xce41325a, 0xc425325b, 0xc0131fff, 0x7e524009, 0xce41325b, 0xd801326d, + 0xd801326e, 0xd8013279, 0x94c00003, 0x08cc0001, 0x80000866, 0xc00c0007, 0x95800003, 0x09980001, + 0x80000866, 0xc0100010, 0x7dd2400c, 0x9a400004, 0xc0180003, 0x7dd1c002, 0x80000866, 0x80000a5a, + 0x04a8089a, 0x86800000, 0x8000089e, 0x800008fa, 0x80000945, 0x80000945, 0x31300022, 0x97000007, + 0xc4380004, 0xd8400008, 0xd8400013, 0xc43130b8, 0x27300001, 0xcf800008, 0xcd400013, 0x04183000, + 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000036, 0x45980008, 0xd180001e, + 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002f, 0xc43c0004, 0xd8400008, 0xd8400013, + 0x13b80001, 0xc79d3300, 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, + 0x964012a4, 0x7c028009, 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x800008d2, + 0xc4180006, 0x9980ffff, 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, + 0x9980fffd, 0xc02620c0, 0xce41c078, 0xce81c080, 0xcc01c081, 0xcf01c082, 0x57240020, 0xce41c083, + 0xc0260400, 0x7e6e400a, 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x800008d2, 0xc4180006, 0x9980ffff, + 0xcdf93300, 0xce393301, 0xcfc00008, 0xcd400013, 0xc43c0004, 0xd8400008, 0x04182000, 0xcd813267, + 0xcfc00008, 0x80000903, 0x31240022, 0x96400008, 0x04100001, 0xc4380004, 0xd8400008, 0xd8400013, + 0xc43130b8, 0x27300001, 0xcf800008, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x7ec30011, + 0x32f80000, 0x9b800011, 0x043c0020, 0x04280000, 0x67180001, 0x0bfc0001, 0x57300001, 0x95800006, + 0x8c001628, 0x9a400003, 0xd981325d, 0x80000915, 0xd9c1325d, 0x06a80001, 0x9bc0fff6, 0x7f818001, + 0x8c001606, 0x7d838001, 0x94800010, 0xcd400013, 0xc41d3259, 0xc421325a, 0x16240014, 0x12640014, + 0x1a2801f0, 0x12a80010, 0x2620ffff, 0x7e2a000a, 0x7de1c001, 0x7e5e400a, 0x9b800002, 0x2264003f, + 0xce41325a, 0xd8013259, 0xc40c0007, 0xd9000010, 0x8c00075e, 0xc4af0228, 0x043c0000, 0x66d80001, + 0x95800010, 0x04300002, 0x1330000d, 0x13f40014, 0x7f73400a, 0xcf400013, 0x04380040, 0xcf80001b, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, + 0x07fc0001, 0x56ec0001, 0x33e80010, 0x9680ffec, 0x80000a5a, 0x80000a5a, 0x04a80948, 0x86800000, + 0x8000094c, 0x8000099b, 0x800009e0, 0x800009e0, 0xc43c0004, 0xd8400008, 0xcd400013, 0x04183000, + 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000033, 0x45980008, 0xd180001e, + 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002c, 0xd8400013, 0x13b80001, 0xc79d3300, + 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, 0x964011fe, 0x7c028009, + 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x80000978, 0xc4180006, 0x9980ffff, + 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, 0x9980fffd, 0xc0260010, + 0xce41c078, 0xcf01c080, 0x57240020, 0xce41c081, 0xce81c082, 0xcc01c083, 0xc0260800, 0x7e6e400a, + 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x80000978, 0xc4180006, 0x9980ffff, 0xcdf93300, 0xce393301, + 0x04182000, 0xcd813267, 0xcfc00008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, 0x7dda801a, + 0x7d41c001, 0x7e838011, 0xd84802e9, 0x8c001802, 0x469c0390, 0xc4313267, 0x04183000, 0xcd813267, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, 0x45dc0004, 0xd1c0001e, + 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4240011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc4280011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc42c0011, + 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4300011, 0x45dc0004, 0xd1c0001e, + 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4340011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc4380011, 0xcd400013, 0x04182000, 0xcd813267, 0x043c0001, 0x8c0014df, 0x80000a5a, + 0x80000a5a, 0x31280014, 0xce8802ef, 0x9a800062, 0x31280034, 0x9a800060, 0x04a809e8, 0x86800000, + 0x800009ec, 0x80000a45, 0x80000a59, 0x80000a59, 0xcd400013, 0xc4113246, 0xc4193245, 0x51100020, + 0x7d91801a, 0x45980400, 0xc4b30258, 0xc4a70250, 0x53300020, 0x7e72401a, 0xc4313267, 0x1b342010, + 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0x042c0020, + 0x66740001, 0x97400041, 0xcd400013, 0x04383000, 0xcf813267, 0xc4393267, 0x9b800001, 0xd180001e, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4300011, 0x1b38007e, 0x33b40003, 0x9b400003, 0x4598001c, + 0x9740002f, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc40c0011, 0x45980004, + 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x45980004, 0xd180001e, 0xd8400021, + 0xc438000f, 0x9b80ffff, 0xc4340011, 0xcf4002eb, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, + 0x9b80ffff, 0xc4340011, 0xcf4002ec, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, + 0xc4340011, 0xcf4002ed, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4340011, + 0xcf4002ee, 0x45980004, 0xcd400013, 0x04382000, 0xcf813267, 0xd84802e9, 0x8c001715, 0xcd400013, + 0x04382000, 0xcf813267, 0x56640001, 0x0aec0001, 0x9ac0ffbc, 0xc4380004, 0xd8400008, 0x04341001, + 0xcf400013, 0x94800005, 0xc431ecaa, 0x27300080, 0x97000002, 0x80000a55, 0xc43130b6, 0x233c0032, + 0xcfc130b6, 0xcf400013, 0xcf0130b6, 0xc49302ef, 0x99000003, 0xcd400013, 0xd8413247, 0xcf800008, + 0x80000a5a, 0x80000a5a, 0xcd400013, 0x04180001, 0x5198001f, 0xcd813268, 0xc4193269, 0x2598000f, + 0x9980fffe, 0xd80002f1, 0xcd400013, 0xd8013268, 0xd800004f, 0x90000000, 0xcd400013, 0x04380001, + 0x53b8001f, 0x7db9801a, 0xcd813268, 0x80000a5e, 0xd8400029, 0xc40c005e, 0x94c01106, 0xd8800013, + 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xd8400029, 0xc40c005e, 0x94c010fd, + 0x7c40c001, 0x50640020, 0x7ce4c01a, 0xd0c00072, 0xc80c0072, 0x58e801fc, 0x12a80009, 0x2aa80000, + 0xd0c0001e, 0xce80001c, 0xd8400021, 0xc424000f, 0x9a40ffff, 0x04240010, 0x18dc01e2, 0x7e5e4002, + 0x3e5c0003, 0x3e540002, 0x95c00006, 0xc8180011, 0xc8100011, 0xc8100011, 0x55140020, 0x80000aa2, + 0x9540000a, 0xc8180011, 0x44cc0008, 0x55900020, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, + 0xc4140011, 0x80000aa2, 0x44cc0004, 0xc4180011, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, + 0xc8100011, 0x55140020, 0xd8800013, 0xcd812e01, 0xcd012e02, 0xcd412e03, 0xcc412e00, 0xc428000e, + 0x2aa80008, 0xce800013, 0xc4253249, 0x2264003f, 0xce413249, 0xce800013, 0xc4253249, 0x96400001, + 0xd800002a, 0xc410001a, 0xc40c0021, 0xc4140028, 0x95000005, 0x1e64001f, 0xce800013, 0xce413249, + 0x80001b70, 0x14d00010, 0xc4180030, 0xc41c0007, 0x99000004, 0x99400009, 0x9980000c, 0x80000ab1, + 0xccc00037, 0x8c000190, 0xc420001c, 0xd8000032, 0x9a0010ac, 0x80000aa7, 0xd880003f, 0x95c00002, + 0xd8c0003f, 0x80001082, 0xd8800040, 0x95c00002, 0xd8c00040, 0x800010de, 0xc010ffff, 0x18d403f7, + 0x7d0cc009, 0xc41b0367, 0x7d958004, 0x7d85800a, 0xdc1e0000, 0x90000000, 0xc424000b, 0x32640002, + 0x7c40c001, 0x18d001fc, 0x05280adc, 0x86800000, 0x80000af1, 0x80000adf, 0x80000ae7, 0x8c000ace, + 0xd8c00013, 0x96400002, 0xd8400013, 0xcd8d2000, 0x99c00010, 0x7c408001, 0x88000000, 0x18d803f7, + 0xc010ffff, 0x7d0cc009, 0x04140000, 0x11940014, 0x29544001, 0x9a400002, 0x29544003, 0xcd400013, + 0x80000af4, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44d2000, 0x7c408001, 0x88000000, 0xc424000b, + 0x32640002, 0x7c40c001, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44dc000, 0x7c408001, 0x88000000, + 0x7c40c001, 0x18d0003c, 0x95000006, 0x8c000ace, 0xd8800013, 0xcd8d2c00, 0x99c00003, 0x80000b0a, + 0xd8800013, 0xd44d2c00, 0x7c408001, 0x88000000, 0x7c40c001, 0x28148004, 0x24d800ff, 0xccc00019, + 0xcd400013, 0xd4593240, 0x7c408001, 0x88000000, 0xd8400029, 0xc40c005e, 0x94c0105e, 0x7c410001, + 0x50540020, 0x7c418001, 0x2198003f, 0x199c0034, 0xc40c0007, 0x95c00028, 0xc428000e, 0x2aa80008, + 0xce800013, 0xc42d324f, 0xc4313255, 0x7ef3400c, 0x9b400021, 0xd800002a, 0x80001b70, 0xc40c0007, + 0x14e80001, 0x9a8000af, 0xd9000010, 0x041c0002, 0x042c01c8, 0x8c000d61, 0xccc00010, 0xd8400029, + 0xc40c005e, 0x94c01043, 0x7c410001, 0x50540020, 0x7c418001, 0x18a01fe8, 0x3620005c, 0x9a00000e, + 0x2464003f, 0xd8400013, 0xc6290ce7, 0x16ac001f, 0x96c00004, 0x26ac003f, 0x7ee6c00d, 0x96c00005, + 0x06200001, 0x2620000f, 0x9a00fff8, 0x8000016a, 0xce000367, 0xc424005e, 0x9640102e, 0xc428000e, + 0x199c0037, 0x19a00035, 0x2aa80008, 0xce800013, 0x95c0005d, 0xd800002a, 0xc42d3256, 0xc431325a, + 0x2330003f, 0x16f8001f, 0x9780000d, 0xc4253248, 0xc035f0ff, 0x7e764009, 0x19b401f8, 0x13740008, + 0x7e76400a, 0xce800013, 0xce413248, 0xcf01325a, 0xce800013, 0xc431325a, 0x97000001, 0x7d15001a, + 0xd1000072, 0xc8100072, 0x55140020, 0x199c0034, 0xd8400010, 0xd8400029, 0x9b800004, 0x1ae4003e, + 0xce400008, 0x80000b7c, 0xc4353254, 0x16a80008, 0x1aec003c, 0x19a4003f, 0x12a80015, 0x12ec001f, + 0x1374000b, 0x7eae800a, 0xc02e4000, 0x1774000d, 0x7eae800a, 0xce400008, 0x7f6b400a, 0x95c00005, + 0xc43d3248, 0x1bfc01e8, 0x13fc0018, 0x7dbd800a, 0x1d98ff15, 0x592c00fc, 0xcd80000a, 0x12e00016, + 0x7da1800a, 0x592c007e, 0x12e00015, 0x7da1800a, 0xd1000001, 0xcd800001, 0x11a0000c, 0x1264001e, + 0x1620000c, 0x7e26000a, 0x7e32000a, 0x12e4001b, 0x7e26000a, 0x5924007e, 0x12640017, 0x7e26000a, + 0x19a4003c, 0x12640018, 0x7e26000a, 0xd800002a, 0xce01325a, 0xcd013257, 0xcd413258, 0xc429325a, + 0xc40c005e, 0x94c00fdb, 0x96800001, 0x95c00003, 0x7c40c001, 0x7c410001, 0x9780f5ca, 0xcf400100, + 0xc40c0007, 0xd9000010, 0x8c00120d, 0x8c001219, 0x8c001232, 0xccc00010, 0x8c001b6d, 0x7c408001, + 0x88000000, 0xc42d324e, 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x52ec0008, + 0x07740003, 0x04240002, 0x269c003f, 0x7e5e4004, 0x7f67000f, 0x97000003, 0x7f674002, 0x0b740001, + 0x53740002, 0x7ef6c011, 0x1ab42010, 0x1ab8c006, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f7b400a, + 0x7f6b400a, 0xcf40001c, 0xd2c0001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4180011, 0x9a000003, + 0x8c000bec, 0x80000b47, 0xc42c001d, 0xc4313256, 0x1b34060b, 0x1b300077, 0x7f370009, 0x13300017, + 0x04340100, 0x26ec00ff, 0xc03a8004, 0x7ef6c00a, 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, + 0xc40c0032, 0xc410001d, 0x28cc0008, 0xccc00013, 0xc415325b, 0x7c418001, 0x7c418001, 0x18580037, + 0x251000ff, 0xc421325d, 0x262001ef, 0xce01325d, 0x99800004, 0x7d15400a, 0xcd41325b, 0x80000168, + 0x1d54001f, 0xcd41325b, 0x7c408001, 0x88000000, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, + 0x7eae800a, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0xcd280200, 0xcd680208, + 0xcda80210, 0x9b00000c, 0x9b400014, 0x9b800017, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, + 0x7eae800a, 0xc6930200, 0xc6970208, 0xc69b0210, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, + 0x8c000190, 0xd8000032, 0x90000000, 0xd8000028, 0xd800002b, 0x80000168, 0xd900003f, 0x97c00002, + 0xd940003f, 0x80001082, 0xd9000040, 0x97c00002, 0xd9400040, 0x800010de, 0xc40c0021, 0x14fc0011, + 0x24f800ff, 0x33b80001, 0x97c0fffc, 0x9b800007, 0xccc00037, 0x8c000190, 0xd8000032, 0xd8000028, + 0xd800002b, 0x80001b70, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, 0x04140000, + 0xc418000e, 0x29980008, 0x7d83c001, 0xcd800013, 0xc4093249, 0x1888003e, 0x94800020, 0xd8400074, + 0x8c000671, 0x9a400009, 0xc418000e, 0x29980008, 0xcd800013, 0xc419324c, 0x259c0001, 0x1598001f, + 0x95c00016, 0x95800015, 0x99000003, 0xd8400036, 0x04100001, 0xc40c0021, 0x14d80011, 0x24e000ff, + 0x321c0002, 0x32200001, 0x9580ffee, 0x99c00014, 0x96000004, 0xccc00037, 0x04140001, 0x80000c30, + 0x9480000a, 0xd8000074, 0xc418005e, 0x95800f29, 0xcf800008, 0x80000c16, 0x94800004, 0xd8000074, + 0xc418005e, 0x95800f23, 0xd9c00036, 0x99400002, 0xccc00037, 0xcf800008, 0x80000c16, 0x94800004, + 0xd8000074, 0xc418005e, 0x95800f1a, 0xccc00037, 0xd8800036, 0x80001b70, 0x041c0003, 0x042c01c8, + 0x8c000d61, 0xc4200007, 0xc40c0077, 0x94c00001, 0x7c418001, 0xc428000e, 0x9600f502, 0x0a200001, + 0x98c0f500, 0x2aa80008, 0xce000010, 0x9a000f05, 0xce800013, 0xc431325a, 0xc42d3256, 0x1f30001f, + 0x16e4001f, 0xcf01325a, 0xc431325a, 0x97000001, 0x9640f4f4, 0xc434000b, 0x33740002, 0x9b40f4f1, + 0xc4353254, 0x16a80008, 0x1aec003c, 0x12a80015, 0x12ec001f, 0x1374000b, 0x7eae800a, 0xc02e4000, + 0x1774000d, 0x7eae800a, 0x7f6b400a, 0xcf400100, 0x12780001, 0x2bb80001, 0xc00ac005, 0xc00e0002, + 0x28cc8000, 0x28884900, 0x28cc0014, 0x80000ff3, 0xc43c0007, 0x7c40c001, 0x17fc0001, 0xd8400013, + 0x9bc00004, 0xd8400029, 0xc424005e, 0x96400ee1, 0xcc41c40a, 0xcc41c40c, 0xcc41c40d, 0x7c414001, + 0x24d0007f, 0x15580010, 0x255400ff, 0xcd01c411, 0xcd81c40f, 0xcd41c40e, 0xcc41c410, 0x7c414001, + 0x7c418001, 0x04200000, 0x18e80033, 0x18ec0034, 0xcc41c414, 0xcc41c415, 0xcd81c413, 0xcd41c412, + 0x18dc0032, 0x7c030011, 0x7c038011, 0x95c00027, 0x96c00002, 0xc431c417, 0xc435c416, 0x96800004, + 0x96c00002, 0xc439c419, 0xc43dc418, 0xc41c000e, 0x29dc0008, 0xcdc00013, 0xcf413261, 0x96c00002, + 0xcf013262, 0x96800004, 0xcfc13263, 0x96c00002, 0xcf813264, 0x18dc0030, 0xc43c0007, 0x95c00017, + 0x17fc0001, 0x9ac00005, 0x7d77000c, 0x9bc00015, 0x9700000a, 0x80000cd6, 0x51b80020, 0x53300020, + 0x7f97801a, 0x7f37001a, 0x7f3b000c, 0x9bc0000d, 0x97800002, 0x80000cd6, 0x9a000018, 0xd8400013, + 0x28200001, 0x80000ca7, 0x18dc0031, 0x95c00003, 0xc435c40b, 0x9740fffd, 0xd800002a, 0x80001b70, + 0xc4280032, 0x2aa80008, 0xce800013, 0xc40d325b, 0x97000002, 0x800012c2, 0xc438001d, 0x1bb81ff0, + 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0xc428000e, 0xc43c0007, + 0x2aa80008, 0xc438001d, 0xce800013, 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, + 0x7ff3c00a, 0x80000cf4, 0xc43d325a, 0x1bfc0677, 0x13fc0017, 0x04300100, 0x1bb81fe8, 0x7f73400a, + 0xc032800b, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, 0x80000c16, 0xc43c0007, 0x7c40c001, + 0x18d42011, 0x17fc0001, 0x18d001e8, 0x24cc007f, 0x7cd4c00a, 0x9bc00004, 0xd8400029, 0xc428005e, + 0x96800e6c, 0x7c414001, 0x50580020, 0x7d59401a, 0xd1400072, 0xc8140072, 0x596001fc, 0x12200009, + 0x7ce0c00a, 0x7c418001, 0x505c0020, 0x7d9d801a, 0x7c41c001, 0x50600020, 0x7de1c01a, 0x7c420001, + 0xccc0001b, 0xd140001d, 0xd180001f, 0xd1c00020, 0xd8400021, 0x95000010, 0x04300000, 0xc428000f, + 0x9a80ffff, 0xc8240010, 0x7e5e800c, 0x9bc00015, 0x9a80000c, 0x9b000024, 0x28300001, 0x122c0004, + 0x06ec0001, 0x0aec0001, 0x9ac0ffff, 0xd8400021, 0x80000d1f, 0xc428000f, 0x9a80ffff, 0xc8240010, + 0x566c0020, 0xc428000e, 0x2aa80008, 0xce800013, 0xce413261, 0xcec13262, 0xd800002a, 0x80001b70, + 0xc4340032, 0x2b740008, 0xcf400013, 0xc40d325b, 0x96800005, 0x566c0020, 0xce413261, 0xcec13262, + 0x800012c2, 0xc438001d, 0x1bb81fe8, 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, + 0x80001b70, 0xc43c0007, 0xc438001d, 0xc428000e, 0x2aa80008, 0xce800013, 0x13f4000c, 0x9bc00006, + 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x80000d57, 0xc43d325a, 0x1bfc0677, 0x13fc0017, + 0x04300100, 0x1bb81fe8, 0x7f73400a, 0xc0328009, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, + 0x80000c16, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0xc4253246, 0xc4113245, 0x04143000, 0xcd413267, + 0x52640020, 0x7e51001a, 0xc4153267, 0x7d2d0011, 0x19640057, 0x19580213, 0x19600199, 0x7da6400a, + 0x7e26400a, 0xd1000025, 0xce400024, 0xcdc00026, 0xd8400027, 0x04142000, 0xcfc00013, 0xcd413267, + 0xc4153267, 0x99400001, 0x90000000, 0x7c40c001, 0x18d001e8, 0x18d40030, 0x18d80034, 0x05280d83, + 0x7c420001, 0x7c424001, 0x86800000, 0x80000d8a, 0x8000016a, 0x80000d95, 0x80000db1, 0x8000016a, + 0x80000d95, 0x80000dbc, 0x11540010, 0x7e010001, 0x8c00187c, 0x7d75400a, 0xcd400013, 0xd4610000, + 0x9580f3d8, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0xd8000016, 0x526c0020, 0x18e80058, + 0x7e2ec01a, 0xd2c00072, 0xc82c0072, 0x5ae0073a, 0x7ea2800a, 0x9940000a, 0xce800024, 0xd2c00025, + 0xd4400026, 0xd8400027, 0x9580f3c6, 0xc4380012, 0x9b80ffff, 0x7c408001, 0x88000000, 0xdc3a0000, + 0x0bb80001, 0xce800024, 0xd2c00025, 0xcc400026, 0xd8400027, 0x9b80fffb, 0x9980fff5, 0x7c408001, + 0x88000000, 0xc02a0001, 0x2aa80001, 0x16200002, 0xce800013, 0xce01c405, 0xd441c406, 0x9580f3b1, + 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, 0x32640002, 0x9a40000b, 0x11540010, + 0x29540002, 0xcd400013, 0xd4610000, 0x9580f3a5, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, + 0x88000000, 0xd4400078, 0x80000168, 0xd8400029, 0xc40c005e, 0x94c00da7, 0x7c40c001, 0x50500020, + 0x7cd0c01a, 0xd0c00072, 0xc8280072, 0x5aac007e, 0x12d80017, 0x7c41c001, 0x7d9d800a, 0x56a00020, + 0x2620ffff, 0x7da1800a, 0x51980020, 0x7e82400a, 0x7e58c01a, 0x19d4003d, 0x28182002, 0x99400030, + 0x8c00104f, 0xc430000d, 0xc4340035, 0xd800002a, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, + 0xc011000f, 0xc4240004, 0x11a00002, 0x7c908009, 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, + 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, 0x20880188, 0x54ec0020, 0x7cb4800a, 0xc4300027, + 0x04380008, 0xd1400025, 0xcf000024, 0x20240090, 0x7ca48001, 0xcc800026, 0xccc00026, 0xcec00026, + 0xcec00026, 0x28240004, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800005, 0x32280000, 0x9a800002, + 0x9a000000, 0x7c018001, 0xd8400027, 0xd8000016, 0xcf80003a, 0xd901a2a4, 0x80001037, 0xc418000e, + 0x29980008, 0xcd800013, 0xc421326c, 0x1624001f, 0x9a40fffe, 0xd841325f, 0xd8800033, 0xc43c0009, + 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xd8800034, 0xc429325f, + 0x26ac0001, 0x9ac0fffe, 0x26ac0002, 0x96c00003, 0xd800002a, 0x80001b70, 0xc43c0007, 0xc430001e, + 0xd8800033, 0x13f4000c, 0x1b301ff0, 0x2b300300, 0x2330003f, 0x7f37000a, 0x9680000b, 0xc43c0009, + 0x27fc0004, 0x97c0fffe, 0xd8400039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xcf01325b, 0xd8800034, + 0x80000c16, 0xd8800034, 0x8c0001a2, 0x80001b70, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, + 0x18ac0024, 0x2b304000, 0x7c40c001, 0xcec00008, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, + 0x29980008, 0xcd800013, 0xc4113249, 0x1910003e, 0x99000002, 0xd840003d, 0x7c410001, 0xd4400078, + 0x51100020, 0xcf01326c, 0x7cd0c01a, 0xc421326c, 0x12a80014, 0x2220003f, 0x7e2a000a, 0xcd800013, + 0xce01326c, 0xd8800033, 0xc43c0009, 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, + 0x9bc0ffff, 0xd8800034, 0x80001190, 0x7c40c001, 0x18dc003d, 0x95c00004, 0x041c0001, 0x042c01c8, + 0x8c000d61, 0x18d40030, 0x18d001e8, 0x18fc0034, 0x24e8000f, 0x06a80e71, 0x7c418001, 0x7c41c001, + 0x86800000, 0x80000edd, 0x80000e91, 0x80000e91, 0x80000ea1, 0x80000eaa, 0x80000e7c, 0x80000e7f, + 0x80000e7f, 0x80000e87, 0x80000e8f, 0x8000016a, 0x51dc0020, 0x7d9e001a, 0x80000ee6, 0xc420000e, + 0x2a200008, 0xce000013, 0xc4213262, 0xc4253261, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc420000e, + 0x2a200008, 0xce000013, 0xc4213264, 0xc4253263, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc820001f, + 0x80000ee6, 0x18e82005, 0x51e00020, 0x2aa80000, 0x7da1801a, 0xd1800072, 0xc8180072, 0x59a001fc, + 0x12200009, 0x7ea2800a, 0xce80001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8200011, + 0x80000ee6, 0x15980002, 0xd8400013, 0xcd81c400, 0xc421c401, 0x95400041, 0xc425c401, 0x52640020, + 0x7e26001a, 0x80000ee6, 0x31ac2580, 0x9ac00011, 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, + 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, + 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, 0xc4340004, 0xd8400008, 0x80000ede, 0x39ac7c06, + 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, + 0x80000ebc, 0x39acc335, 0x3db0c336, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9002, 0x3db09001, + 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9012, 0x3db09011, 0x9ac00003, 0x97000002, 0x80000ebc, + 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000ebc, 0xc4340004, 0xd8400013, 0xc5a10000, + 0x95400005, 0x05980001, 0xc5a50000, 0x52640020, 0x7e26001a, 0xcf400008, 0x05280eea, 0x7c418001, + 0x7c41c001, 0x86800000, 0x80000ef1, 0x8000016a, 0x80000efe, 0x80000f11, 0x80000f2e, 0x80000efe, + 0x80000f1f, 0xc4340004, 0xd8400013, 0xce190000, 0x95400005, 0x05980001, 0x56200020, 0xce190000, + 0xcf400008, 0x97c0f26f, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x51ec0020, 0x18e80058, + 0x7daec01a, 0xd2c00072, 0xc82c0072, 0x5af8073a, 0x7eba800a, 0xd2c00025, 0xce800024, 0xce000026, + 0x95400003, 0x56240020, 0xce400026, 0xd8400027, 0x97c0f25c, 0xc4380012, 0x9b80ffff, 0x7c408001, + 0x88000000, 0xc02a0001, 0x2aa80001, 0x15980002, 0xce800013, 0xcd81c405, 0xce01c406, 0x95400003, + 0x56240020, 0xce41c406, 0x97c0f24e, 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, + 0x32640002, 0x9a40f247, 0xd8800013, 0xce190000, 0x95400004, 0x05980001, 0x56200020, 0xce190000, + 0x97c0f240, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x31ac2580, 0x9ac00011, + 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, + 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, + 0xc4340004, 0xd8400008, 0x80000ef2, 0x39ac7c06, 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000f40, + 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, 0x80000f40, 0x39acc335, 0x3db0c336, 0x9ac00003, + 0x97000002, 0x80000f40, 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9002, + 0x3db09002, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9012, 0x3db09012, 0x9ac00003, 0x97000002, + 0x80000f40, 0x80000ef1, 0xc40c0006, 0x98c0ffff, 0x7c40c001, 0x7c410001, 0x7c414001, 0x7c418001, + 0x7c41c001, 0x7c43c001, 0x95c00001, 0xc434000e, 0x2b740008, 0x2b780001, 0xcf400013, 0xd8c1325e, + 0xcf80001a, 0xd8400013, 0x7c034001, 0x7c038001, 0x18e0007d, 0x32240003, 0x9a400006, 0x32240000, + 0x9a400004, 0xcd01c080, 0xcd41c081, 0x80000f88, 0x51640020, 0x7e52401a, 0xd2400072, 0xc8280072, + 0xce81c080, 0x56ac0020, 0x26f0ffff, 0xcf01c081, 0x1af000fc, 0x1334000a, 0x24e02000, 0x7f63400a, + 0x18e00074, 0x32240003, 0x9a400006, 0x32240000, 0x9a400004, 0xcd81c082, 0xcdc1c083, 0x80000f9d, + 0x51e40020, 0x7e5a401a, 0xd2400072, 0xc8280072, 0xce81c082, 0x56ac0020, 0x26f0ffff, 0xcf01c083, + 0x1af000fc, 0x13380016, 0x18e00039, 0x12200019, 0x7fa3800a, 0x7fb7800a, 0x18e0007d, 0x1220001d, + 0x7fa3800a, 0x18e00074, 0x12200014, 0x7fa3800a, 0xcf81c078, 0xcfc1c084, 0x80000c16, 0x7c40c001, + 0x18dc003d, 0x95c00004, 0x041c0000, 0x042c01c8, 0x8c000d61, 0x18d001e8, 0x31140005, 0x99400003, + 0x31140006, 0x95400002, 0x8c00104f, 0x05280fb7, 0x28140002, 0xcd400013, 0x86800000, 0x80000fbe, + 0x80000fbe, 0x80000fc2, 0x80000fbe, 0x80000fd1, 0x80000ff2, 0x80000ff2, 0x24cc003f, 0xccc1a2a4, + 0x7c408001, 0x88000000, 0x7c414001, 0x18e80039, 0x52a8003b, 0x50580020, 0x24cc003f, 0x7d59401a, + 0xd1400072, 0xc8140072, 0x7d69401a, 0xc41c0017, 0x99c0ffff, 0xd140004b, 0xccc1a2a4, 0x7c408001, + 0x88000000, 0xc414000d, 0x04180001, 0x24cc003f, 0x7d958004, 0xcd800035, 0xccc1a2a4, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x97c00002, 0xd8400074, 0xc4100019, 0x7d150005, + 0x25100001, 0x9500000b, 0x97c0fffc, 0xc4180021, 0x159c0011, 0x259800ff, 0x31a00003, 0x31a40001, + 0x7e25800a, 0x95c0fff5, 0x9580fff4, 0x80000fef, 0xc411326f, 0x1d100010, 0xcd01326f, 0x97c00002, + 0xd8000074, 0x80001b70, 0x04380000, 0xc430000d, 0xc8140023, 0xc4180081, 0x13300005, 0xc011000f, + 0xc4240004, 0x33b40003, 0x97400003, 0xc0340008, 0x80000ffe, 0xc4340035, 0x11a00002, 0x7c908009, + 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x282c2002, + 0x208801a8, 0x3e280008, 0x7cb4800a, 0xcec00013, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, + 0x20240030, 0x7ca48001, 0xcc800026, 0xccc00026, 0x9b800013, 0xcc400026, 0x7c414001, 0x28340000, + 0xcf400013, 0x507c0020, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, + 0xcd400026, 0xcfc00026, 0xd4400026, 0x9a80000e, 0x32280000, 0x9a80000b, 0x8000102f, 0xcc000026, + 0xcc000026, 0xcc000026, 0xcc000026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, + 0x7c018001, 0xcc000026, 0xd8400027, 0x1cccfe08, 0xd8800013, 0xcec0003a, 0xccc1a2a4, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x9bc00007, 0xc428000e, 0x16a80008, 0xce800009, + 0xc42c005e, 0x96c00b33, 0xd840003c, 0xc4200025, 0x7da2400f, 0x7da28002, 0x7e1ac002, 0x0aec0001, + 0x96400002, 0x7d2ac002, 0x3ef40010, 0x9b40f11d, 0x04380030, 0xcf81325e, 0x80000c16, 0xde410000, + 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xddc10000, 0xde010000, 0xc40c000e, 0x7c024001, + 0x28cc0008, 0xccc00013, 0xc8100086, 0x5510003f, 0xc40d3249, 0x18cc003e, 0x98c00003, 0x99000011, + 0x80001075, 0x9900000c, 0xc40c0026, 0xc4100081, 0xc4140025, 0x7d15800f, 0x7d15c002, 0x7d520002, + 0x0a200001, 0x95800002, 0x7cde0002, 0x3e20001a, 0x9a000009, 0x040c0030, 0xccc1325e, 0x80001071, + 0xd9c00036, 0xd8400029, 0xc40c005e, 0x94c00b01, 0x04240001, 0xdc200000, 0xdc1c0000, 0xdc180000, + 0xdc140000, 0xdc100000, 0xdc0c0000, 0x96400004, 0xdc240000, 0xdc0c0000, 0x80000c16, 0xdc240000, + 0x90000000, 0xcc40003f, 0xd8c00010, 0xc4080029, 0xcc80003b, 0xc418000e, 0x18a800e5, 0x1d980008, + 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0x18a400e5, 0x12500009, 0x248c0008, 0x94c00006, + 0x200c006d, 0x7cd0c00a, 0xccc1326c, 0xc421326c, 0x96000001, 0xcd800013, 0x200c0228, 0x7cd0c00a, + 0xccc1326c, 0xc421326c, 0x96000001, 0xc40c002a, 0xc410002b, 0x18881fe8, 0x18d4072c, 0x18cc00d1, + 0x7cd4c00a, 0x3094000d, 0x38d80000, 0x311c0003, 0x99400006, 0x30940007, 0x1620001f, 0x9940001d, + 0x9a000023, 0x800010c4, 0x9580001a, 0x99c00019, 0xccc00041, 0x25140001, 0xc418002c, 0x9940000d, + 0x259c007f, 0x95c00013, 0x19a00030, 0xcdc0001b, 0xd8400021, 0xd8400022, 0xc430000f, 0x17300001, + 0x9b00fffe, 0x9a000012, 0xd8400023, 0x800010cb, 0x199c0fe8, 0xcdc0001b, 0xd8400021, 0xd8400023, + 0xc430000f, 0x17300001, 0x9b00fffe, 0x800010cb, 0xd8c00010, 0xd8000022, 0xd8000023, 0xc430005e, + 0x97000aac, 0x7c408001, 0x88000000, 0xc43c000e, 0xc434002e, 0x2bfc0008, 0x2020002c, 0xcfc00013, + 0xce01326c, 0x17780001, 0x27740001, 0x07a810d8, 0xcf400010, 0xc421326c, 0x96000001, 0x86800000, + 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0x8000104c, 0xcc400040, 0xd8800010, 0xc4180032, + 0x29980008, 0xcd800013, 0x200c007d, 0xccc1325b, 0xc411325b, 0x95000001, 0x7c408001, 0x88000000, + 0x28240007, 0xde430000, 0xd4400078, 0x80001190, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, + 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0xc40d3249, 0x18cc003e, + 0x98c00002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x7c40c001, 0x7c410001, 0x7c414001, + 0x192400fd, 0x50580020, 0x7d59401a, 0x7c41c001, 0x06681110, 0x7c420001, 0xcc400078, 0x18ac0024, + 0x19180070, 0x19100078, 0xcec00008, 0x18f40058, 0x5978073a, 0x7f7b400a, 0x97000001, 0x86800000, + 0x80001117, 0x80001118, 0x80001122, 0x8000112d, 0x80001130, 0x80001133, 0x8000016a, 0x8000117b, + 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, 0xcf400024, 0xcdc00026, + 0xd8400027, 0x8000117b, 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, + 0xcf400024, 0xcdc00026, 0xce000026, 0xd8400027, 0x8000117b, 0xc81c001f, 0x55e00020, 0x80001122, + 0xc81c0020, 0x55e00020, 0x80001122, 0x8c00116b, 0xd8400013, 0xc02a0200, 0x7e8e8009, 0x22a8003d, + 0x22a80074, 0x2774001c, 0x13740014, 0x7eb6800a, 0x25ecffff, 0x55700020, 0x15f40010, 0x13740002, + 0x275c001f, 0x95c00027, 0x7c018001, 0x7f41c001, 0x15dc0002, 0x39e00008, 0x25dc0007, 0x7dc1c01e, + 0x05dc0001, 0x96000004, 0x05e40008, 0x8c00116e, 0x80001168, 0x7dc2001e, 0x06200001, 0x05e40008, + 0x7e62000e, 0x9a000004, 0x7da58001, 0x8c00116e, 0x80001165, 0x7dc2001e, 0x06200001, 0x7e1a0001, + 0x05cc0008, 0x7e0d000e, 0x95000007, 0x7e02401e, 0x06640001, 0x06640008, 0x05d80008, 0x8c00116e, + 0x80001168, 0x7dc2401e, 0x06640001, 0x7da58001, 0x8c00116e, 0x05e00008, 0x7da2000c, 0x9600ffe6, + 0x17640002, 0x8c00116e, 0x80001190, 0xc4200006, 0x9a00ffff, 0x90000000, 0x8c00116b, 0xc420000e, + 0x2a200001, 0xce00001a, 0xce81c078, 0xcec1c080, 0xcc01c081, 0xcd41c082, 0xcf01c083, 0x12640002, + 0x22640435, 0xce41c084, 0x90000000, 0x0528117e, 0x312c0003, 0x86800000, 0x80001190, 0x80001185, + 0x80001182, 0x80001182, 0xc4300012, 0x9b00ffff, 0x9ac0000c, 0xc03a0400, 0xc4340004, 0xd8400013, + 0xd8400008, 0xc418000e, 0x15980008, 0x1198001c, 0x7d81c00a, 0xcdc130b7, 0xcf8130b5, 0xcf400008, + 0x04240008, 0xc418000e, 0xc41c0049, 0x19a000e8, 0x29a80008, 0x7de2c00c, 0xce800013, 0xc421325e, + 0x26200010, 0xc415326d, 0x9a000006, 0xc420007d, 0x96000004, 0x96c00003, 0xce40003e, 0x800011a3, + 0x7d654001, 0xcd41326d, 0x7c020001, 0x96000005, 0xc4100026, 0xc4240081, 0xc4140025, 0x800011b6, + 0xc4253279, 0xc415326d, 0xc431326c, 0x2730003f, 0x3b380006, 0x97800004, 0x3f38000b, 0x9b800004, + 0x800011b4, 0x04300006, 0x800011b4, 0x0430000b, 0x04380002, 0x7fb10004, 0x7e57000f, 0x7e578002, + 0x7d67c002, 0x0be40001, 0x97000002, 0x7d3a4002, 0x202c002c, 0xc421325e, 0x04280020, 0xcec1326c, + 0x26200010, 0x3e640010, 0x96000003, 0x96400002, 0xce81325e, 0xc4300028, 0xc434002e, 0x17780001, + 0x27740001, 0x07a811cf, 0x9b00feb8, 0xcf400010, 0xc414005e, 0x954009a7, 0x86800000, 0x80000168, + 0x80000aa7, 0x80000bfc, 0x800012e9, 0x80000168, 0x8c00120d, 0x7c40c001, 0xccc1c07c, 0xcc41c07d, + 0xcc41c08c, 0x7c410001, 0xcc41c079, 0xcd01c07e, 0x7c414001, 0x18f0012f, 0x18f40612, 0x18cc00c1, + 0x7f73400a, 0x7cf7400a, 0x39600004, 0x9a000002, 0xc0140004, 0x11600001, 0x18fc003e, 0x9740001c, + 0xcf400041, 0xc425c07f, 0x97c00003, 0x166c001f, 0x800011ee, 0x1a6c003e, 0x96c00006, 0x04200002, + 0x0a200001, 0x9a00ffff, 0xd8400013, 0x800011e8, 0xc428002c, 0x96800010, 0x26ac007f, 0xcec0001b, + 0xd8400021, 0x1ab00030, 0x1aac0fe8, 0xc434000f, 0x9b40ffff, 0x97000008, 0xcec0001b, 0xd8400021, + 0xc434000f, 0x9b40ffff, 0x80001205, 0x0a200001, 0x9a00ffff, 0xd8400013, 0xc425c07f, 0x166c001f, + 0x11600001, 0x9ac0fffa, 0x8c001232, 0x7c408001, 0x88000000, 0xd8000033, 0xc438000b, 0xc43c0009, + 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, 0x7ffbc00c, 0x97c0fffd, + 0x90000000, 0xc03a2800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380040, + 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, + 0x9b80ffff, 0x04380002, 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, + 0x9bc0fffa, 0x90000000, 0xd8400013, 0xd801c07f, 0xd8400013, 0xc43dc07f, 0xcfc00078, 0xd8000034, + 0x90000000, 0xc03ae000, 0xcf81c200, 0xc03a0800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, + 0xcc01c07e, 0x04380040, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380002, 0x0bb80001, + 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, 0xc03ae000, + 0xcf81c200, 0xc03a4000, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380002, + 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, + 0xc40c0007, 0x30d00002, 0x99000052, 0xd8400029, 0xc424005e, 0x9640090f, 0x7c410001, 0xc428000e, + 0x1514001f, 0x19180038, 0x2aa80008, 0x99400030, 0x30dc0001, 0xce800013, 0x99c0000a, 0xc42d324e, + 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x1ab0c006, 0x52ec0008, 0x8000127f, + 0xc42d3258, 0xc4313257, 0x52ec0020, 0x7ef2c01a, 0xc4353259, 0xc429325a, 0x1ab0c012, 0x07740001, + 0x04240002, 0x26a0003f, 0x7e624004, 0x7f67800f, 0x97800002, 0x04340000, 0x53740002, 0x7ef6c011, + 0x1ab42010, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f73400a, 0x7f6b400a, 0xcf40001c, 0xd2c0001e, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x1514001f, 0x99400006, 0x9980000a, 0x8c0012e1, + 0xc40c0007, 0x04100000, 0x80001267, 0xd800002a, 0xc424005e, 0x964008d7, 0xd9800036, 0x80000c16, + 0xc42c001d, 0x95c00005, 0xc431325a, 0x1b300677, 0x11dc000c, 0x800012aa, 0xc4313256, 0x1b34060b, + 0x1b300077, 0x7f37000a, 0x13300017, 0x04340100, 0x26ec00ff, 0xc03a8002, 0x7ef6c00a, 0x7edec00a, + 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, 0xc4140032, 0xc410001d, 0x29540008, 0xcd400013, + 0xc40d325b, 0x1858003f, 0x251000ff, 0x99800007, 0x7d0cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, + 0xcd01325d, 0x80000168, 0x18d0006c, 0x18d407f0, 0x9900000e, 0x04100002, 0xc4193256, 0xc41d324f, + 0x2598003f, 0x7d190004, 0x7d5d4001, 0x7d52000f, 0x9a000003, 0xcd41324f, 0x800012d8, 0x7d514002, + 0xcd41324f, 0x800012d8, 0xc4193259, 0xc41d325a, 0x7d958001, 0x7dd5c002, 0xcd813259, 0xcdc1325a, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x1ccc001e, 0xccc1325b, 0xc40d325b, 0x94c00001, 0x7c408001, + 0x88000000, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0x9b000004, 0x9b40000c, + 0x9b80000f, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, 0x8c000190, 0xd8000032, 0x90000000, + 0xd8000028, 0xd800002b, 0x80000168, 0xd980003f, 0x97c00002, 0xd9c0003f, 0x80001082, 0xd9800040, + 0x97c00002, 0xd9c00040, 0x800010de, 0xc43c0007, 0x33f80003, 0x97800051, 0xcc80003b, 0x24b00008, + 0xc418000e, 0x1330000a, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, + 0xc4353249, 0x1b74003e, 0x9b400002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x97000001, + 0x7c434001, 0x1b4c00f8, 0x7c410001, 0x7c414001, 0x50700020, 0x04e81324, 0x18ac0024, 0x7c41c001, + 0x50600020, 0xcc400078, 0x30e40004, 0x9a400007, 0x7d71401a, 0x596401fc, 0x12640009, 0x1b74008d, + 0x7e76400a, 0x2a640000, 0xcec00008, 0x86800000, 0x8000016a, 0x8000016a, 0x8000016a, 0x8000016a, + 0x8000132c, 0x8000133b, 0x80001344, 0x8000016a, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42530b5, + 0x1a68003a, 0x9a80fffe, 0x2024003a, 0xc418000e, 0x25980700, 0x11980014, 0x7d19000a, 0xcd0130b7, + 0xce4130b5, 0xcf400008, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, 0x9a80ffff, + 0xc4240011, 0x7de6800f, 0x9a80ffea, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, + 0x9a80ffff, 0xc8240011, 0x7de1c01a, 0x7de6800f, 0x9a80ffe0, 0x80001190, 0x8c00104f, 0x28182002, + 0xc430000d, 0xc4340035, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, 0xc4240004, 0x11a00002, + 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, + 0x7cb4800a, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, 0x20240030, 0x7ca48001, 0xcc800026, + 0x7c434001, 0x1b4c00f8, 0xcf400026, 0xcc400026, 0x28340000, 0xcf400013, 0x7c414001, 0x507c0020, + 0x30e40004, 0x9a400005, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, + 0xcd400026, 0xcfc00026, 0xd4400026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, + 0x7c018001, 0xd8400027, 0xd8800013, 0x04380028, 0xcec0003a, 0xcf81a2a4, 0x80001037, 0xd8400029, + 0xc40c005e, 0x94c007eb, 0x7c40c001, 0x50500020, 0x7d0d001a, 0xd1000072, 0xc8100072, 0x591c01fc, + 0x11dc0009, 0x45140210, 0x595801fc, 0x11980009, 0x29dc0000, 0xcdc0001c, 0xd140001e, 0xd8400021, + 0xc418000f, 0x9980ffff, 0xc4200011, 0x1624001f, 0x96400069, 0xc40c000e, 0x28cc0008, 0xccc00013, + 0xce013249, 0x1a307fe8, 0xcf00000a, 0x23304076, 0xd1000001, 0xcf000001, 0xc41d3254, 0xc4253256, + 0x18cc00e8, 0x10cc0015, 0x4514020c, 0xd140001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, + 0xce013248, 0x1a2001e8, 0x12200014, 0x2a204001, 0xce000013, 0x1a64003c, 0x1264001f, 0x11dc0009, + 0x15dc000b, 0x7dcdc00a, 0x7e5dc00a, 0xcdc00100, 0xd8800013, 0xd8400010, 0xd800002a, 0xd8400008, + 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, 0x04300010, 0xdf430000, 0x7c434001, + 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, 0xdf030000, 0xd4412e40, 0xd8400013, + 0xcc41c030, 0xcc41c031, 0x248dfffe, 0xccc12e00, 0xd8800013, 0xcc812e00, 0x7c434001, 0x7c434001, + 0x8c00142b, 0xd8000010, 0xc40c000e, 0x28cc0008, 0xccc00013, 0x45140248, 0xd140001e, 0xd8400021, + 0xc418000f, 0x9980ffff, 0xc8200011, 0xce013257, 0x56200020, 0xce013258, 0x0434000c, 0xdb000024, + 0xd1400025, 0xd8000026, 0xd8000026, 0xd8400027, 0x45540008, 0xd140001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc8200011, 0xce013259, 0x56200020, 0xc0337fff, 0x7f220009, 0xce01325a, 0x55300020, + 0x7d01c001, 0x042c01d0, 0x8c000d61, 0x06ec0004, 0x7f01c001, 0x8c000d61, 0x041c0002, 0x042c01c8, + 0x8c000d61, 0xc4380012, 0x9b80ffff, 0xd800002a, 0x80000aa7, 0xd800002a, 0x7c408001, 0x88000000, + 0xd8400029, 0x7c40c001, 0x50500020, 0x8c001427, 0x7cd0c01a, 0xc4200007, 0xd0c00072, 0xc8240072, + 0xd240001e, 0x7c414001, 0x19682011, 0x5a6c01fc, 0x12ec0009, 0x7eeac00a, 0x2aec0000, 0xcec0001c, + 0xd8400021, 0xc430000f, 0x9b00ffff, 0xc4180011, 0x7c438001, 0x99800007, 0xdf830000, 0xcfa0000c, + 0x8c00142b, 0xd4400078, 0xd800002a, 0x80001b70, 0x8c00142b, 0xd800002a, 0x80001b70, 0xd8000012, + 0xc43c0008, 0x9bc0ffff, 0x90000000, 0xd8400012, 0xc43c0008, 0x97c0ffff, 0x90000000, 0xc4380007, + 0x7c40c001, 0x17b80001, 0x18d40038, 0x7c410001, 0x9b800004, 0xd8400029, 0xc414005e, 0x9540073d, + 0x18c80066, 0x7c414001, 0x30880001, 0x7c418001, 0x94800008, 0x8c00187c, 0xcf400013, 0xc42c0004, + 0xd8400008, 0xcd910000, 0xcec00008, 0x7d410001, 0x043c0000, 0x7c41c001, 0x7c420001, 0x04240001, + 0x06200001, 0x4220000c, 0x0a640001, 0xcc000078, 0x9a40fffe, 0x24e80007, 0x24ec0010, 0xd8400013, + 0x9ac00006, 0xc42c0004, 0xd8400008, 0xc5310000, 0xcec00008, 0x80001465, 0x51540020, 0x7d15001a, + 0xd1000072, 0xc82c0072, 0xd2c0001e, 0x18f02011, 0x5aec01fc, 0x12ec0009, 0x7ef2c00a, 0x2aec0000, + 0xcec0001c, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc4300011, 0x96800012, 0x12a80001, 0x0aa80001, + 0x06a8146a, 0x7f1f0009, 0x86800000, 0x7f1b400f, 0x80001478, 0x7f1b400e, 0x80001478, 0x7f1b400c, + 0x8000147a, 0x7f1b400d, 0x8000147a, 0x7f1b400f, 0x8000147a, 0x7f1b400e, 0x8000147a, 0x7f334002, + 0x97400014, 0x8000147b, 0x9b400012, 0x9b800005, 0x9bc0001f, 0x7e024001, 0x043c0001, 0x8000144a, + 0xc40c0032, 0xc438001d, 0x28cc0008, 0xccc00013, 0xc43d325b, 0x1bb81ff0, 0x7fbfc00a, 0xcfc1325b, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0x94800007, 0x8c00187c, 0xcf400013, 0xc42c0004, + 0xd8400008, 0xcd910000, 0xcec00008, 0x9b800003, 0xd800002a, 0x80001b70, 0xc40c0032, 0x28cc0008, + 0xccc00013, 0xc40d325b, 0x800012c2, 0xc40c000e, 0xc43c0007, 0xc438001d, 0x28cc0008, 0xccc00013, + 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x800014a9, 0xc43d325a, + 0x1bfc0677, 0x04300100, 0x1bb81ff0, 0x7f73400a, 0xc0328007, 0x7fb7800a, 0x13fc0017, 0x7ff3c00a, + 0x7ffbc00a, 0xcfc1325b, 0xc03a0002, 0xc4340004, 0xd8400013, 0xd8400008, 0xcf8130b5, 0xcf400008, + 0x80000c16, 0x043c0000, 0xc414000e, 0x29540008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, + 0x7dd9c01a, 0x45dc0390, 0xc4313267, 0x04183000, 0xcd813267, 0x1b380057, 0x1b340213, 0x1b300199, + 0x7f7b400a, 0x7f73400a, 0xcf400024, 0xd1c00025, 0xcc800026, 0x7c420001, 0xce000026, 0x7c424001, + 0xce400026, 0x7c428001, 0xce800026, 0x7c42c001, 0xcec00026, 0x7c430001, 0xcf000026, 0x7c434001, + 0xcf400026, 0x7c438001, 0xcf800026, 0xd8400027, 0xcd400013, 0x04182000, 0xcd813267, 0xd840004f, + 0x1a0800fd, 0x109c000a, 0xc4193265, 0x7dd9c00a, 0xcdc13265, 0x2620ffff, 0xce080228, 0x9880000e, + 0xce480250, 0xce880258, 0xd8080230, 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, + 0xd8080278, 0xd8080280, 0xd800004f, 0x97c0ec75, 0x90000000, 0x040c0000, 0x041c0010, 0x26180001, + 0x09dc0001, 0x16200001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80230, 0xd8080238, 0xd8080240, + 0xd8080248, 0x040c0000, 0xce480250, 0xce880258, 0x52a80020, 0x7e6a401a, 0x041c0020, 0x66580001, + 0x09dc0001, 0x56640001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80260, 0xd8080268, 0xd8080270, + 0xd8080278, 0xd8080280, 0x040c0000, 0xcec80288, 0xcf080290, 0xcec80298, 0xcf0802a0, 0x040c0000, + 0x041c0010, 0xcf4802a8, 0x27580001, 0x09dc0001, 0x17740001, 0x95800002, 0x04cc0001, 0x99c0fffb, + 0xccc802b0, 0xd80802b8, 0x178c000b, 0x27b8003f, 0x7cf8c001, 0xcf8802c0, 0xccc802c8, 0xcf8802d0, + 0xcf8802d8, 0xd800004f, 0x97c00002, 0x90000000, 0x7c408001, 0x88000000, 0xc40c000e, 0x28cc0008, + 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c418001, 0x25b8ffff, 0xc4930240, 0xc48f0238, 0x04cc0001, + 0x24cc000f, 0x7cd2800c, 0x9a80000b, 0xc5230309, 0x2620ffff, 0x7e3a400c, 0x9a400004, 0x05100001, + 0x2510000f, 0x80001539, 0xcd08034b, 0xd4400078, 0x80000168, 0xc48f0230, 0xc4930240, 0x98c00004, + 0xcd880353, 0x8c00163f, 0xc49b0353, 0xc4930238, 0xc48f0228, 0x05100001, 0x2510000f, 0x7cd14005, + 0x25540001, 0x99400004, 0x05100001, 0x2510000f, 0x8000154f, 0xc48f0230, 0x7c41c001, 0xcd080238, + 0xcd08034b, 0x08cc0001, 0x2598ffff, 0x3d200008, 0xccc80230, 0xcd900309, 0xd8100319, 0x04340801, + 0x2198003f, 0xcf400013, 0xcd910ce7, 0xc4190ce6, 0x7d918005, 0x25980001, 0x9580fffd, 0x7d918004, + 0xcd810ce6, 0x9a000003, 0xcdd1054f, 0x8000156e, 0x090c0008, 0xcdcd050e, 0x040c0000, 0x110c0014, + 0x28cc4001, 0xccc00013, 0xcc41230a, 0xcc41230b, 0xcc41230c, 0xcc41230d, 0xcc480329, 0xcc48032a, + 0xcc4802e0, 0xd8000055, 0xc48f02e0, 0x24d8003f, 0x09940001, 0x44100001, 0x9580002c, 0x95400005, + 0x09540001, 0x51100001, 0x69100001, 0x8000157f, 0x24cc003f, 0xc4970290, 0xc49b0288, 0x51540020, + 0x7d59401a, 0xc49b02a0, 0xc49f0298, 0x51980020, 0x7d9d801a, 0x041c0040, 0x04200000, 0x7dcdc002, + 0x7d924019, 0x7d26400c, 0x09dc0001, 0x9a400008, 0x51100001, 0x06200001, 0x99c0fffa, 0xc48f0230, + 0xc4930240, 0x8c00163f, 0x80001579, 0x7d010021, 0x7d914019, 0xc4930238, 0x55580020, 0xcd480298, + 0xcd8802a0, 0x10d40010, 0x12180016, 0xc51f0309, 0x7d95800a, 0x7d62000a, 0x7dd9c00a, 0xd8400013, + 0xcdd00309, 0xce113320, 0xc48f02e0, 0xc49b02b0, 0x18dc01e8, 0x7dd9400e, 0xc48f0230, 0xc4930240, + 0x95c0001d, 0x95400003, 0x8c00163f, 0x800015aa, 0xc48f0238, 0xc4a302b8, 0x12240004, 0x7e5e400a, + 0xc4ab02a8, 0x04100000, 0xce4c0319, 0x7d9d8002, 0x7ea14005, 0x25540001, 0x99400004, 0x06200001, + 0x2620000f, 0x800015bc, 0x09dc0001, 0x04240001, 0x7e624004, 0x06200001, 0x7d25000a, 0x2620000f, + 0x99c0fff4, 0xd8400013, 0xcd0d3330, 0xce0802b8, 0xcd8802b0, 0xc4ab02e0, 0x1aa807f0, 0xc48f02d0, + 0xc49702d8, 0xc49b02c8, 0xc49f02c0, 0x96800028, 0x7d4e000f, 0x9600000b, 0x7d964002, 0x7e6a000f, + 0x96000003, 0x7d694001, 0x800015e9, 0x7cde4002, 0x7e6a000f, 0x96000008, 0x7de94001, 0x800015e9, + 0x7cd64002, 0x7e6a000e, 0x96000003, 0x7d694001, 0x800015e9, 0xc48f0230, 0xc4930240, 0x8c00163f, + 0x800015cd, 0xc4930238, 0x7d698002, 0xcd4802d8, 0x129c0008, 0xc50f0319, 0x11a0000e, 0x11140001, + 0xc4340004, 0xd8400008, 0xd8400013, 0x7e1e000a, 0x1198000a, 0xcd953300, 0x7e0e000a, 0x12a8000a, + 0xce953301, 0xce100319, 0xcf400008, 0xc4b70280, 0xc4b30278, 0x7f73800a, 0x536c0020, 0x7ef2c01a, + 0x9780eb68, 0x8c001608, 0xd8080278, 0xd8080280, 0x7c408001, 0x88000000, 0x043c0003, 0x80001609, + 0x043c0001, 0x30b40000, 0x9b400011, 0xc4b70258, 0xc4b30250, 0x53780020, 0x7fb3801a, 0x7faf8019, + 0x04300020, 0x04280000, 0x67b40001, 0x0b300001, 0x57b80001, 0x97400002, 0x06a80001, 0x9b00fffb, + 0xc4bb0260, 0x7fab8001, 0xcf880260, 0x04300020, 0x04280000, 0x66f40001, 0x0b300001, 0x56ec0001, + 0x97400005, 0x8c001628, 0xc4353247, 0x7f7f4009, 0x9b40fffe, 0x06a80001, 0x9b00fff7, 0x90000000, + 0x269c0007, 0x11dc0008, 0x29dc0008, 0x26a00018, 0x12200003, 0x7de1c00a, 0x26a00060, 0x06200020, + 0x16200001, 0x7de1c00a, 0xcdc00013, 0x90000000, 0x269c0018, 0x26a00007, 0x26a40060, 0x11dc0006, + 0x12200006, 0x16640001, 0x29dc0008, 0x7de1c00a, 0x7de5c00a, 0xcdc00013, 0x90000000, 0xc4b70228, + 0x05100001, 0x04cc0001, 0x2510000f, 0xccc80230, 0x7f514005, 0x25540001, 0x99400004, 0x05100001, + 0x2510000f, 0x80001644, 0xc4b30248, 0xcd080240, 0x7f130005, 0x27300001, 0x9b000002, 0x8c001688, + 0x8c00120d, 0x8c001219, 0x8c001232, 0x04300001, 0x04340801, 0x7f130004, 0xcf400013, 0xcf01051e, + 0xc42d051f, 0x7ed2c005, 0x26ec0001, 0x96c0fffd, 0xcf01051f, 0xd8000055, 0xc5170309, 0x195c07f0, + 0x196007f6, 0x04340000, 0x95c00008, 0x09dc0001, 0x04340001, 0x95c00005, 0x09dc0001, 0x53740001, + 0x6b740001, 0x80001665, 0xc4a702a0, 0xc4ab0298, 0x52640020, 0x7e6a401a, 0x7f634014, 0x7e76401a, + 0xc4300004, 0xd8400008, 0xd8400013, 0x56680020, 0xd8113320, 0xce480298, 0xce8802a0, 0xc5170319, + 0xc4b702b0, 0x255c000f, 0x7f5f4001, 0xd8113330, 0xcf4802b0, 0x11340001, 0x195c07e8, 0x196007ee, + 0xd8353300, 0x7e1e4001, 0xd8353301, 0xce4802d0, 0xd8100309, 0xd8100319, 0xcf000008, 0x90000000, + 0xc4970258, 0xc48f0250, 0x51540020, 0x7cd4c01a, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, + 0x04140020, 0x04280000, 0x64d80001, 0x09540001, 0x54cc0001, 0x95800060, 0x8c001628, 0xc4193247, + 0x25980001, 0x9580005c, 0x7dc24001, 0xc41d3248, 0x25dc000f, 0x7dd2000c, 0x96000057, 0xc41d3255, + 0xc435324f, 0x7df5c00c, 0x99c00004, 0xc4193265, 0x25980040, 0x9580fffe, 0xc439325b, 0x1bb0003f, + 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, 0x1bb000e4, + 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x800016f1, 0xce400013, 0xc033ffff, + 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, 0xd8c00033, + 0xc4300009, 0x27300008, 0x9700fffe, 0x1a7003e6, 0x27380003, 0x13b80004, 0x27300003, 0x13300003, + 0x7fb38001, 0x1a7000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, 0x1a700064, + 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x0b300003, 0x800016df, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, + 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xce400013, 0xc431325d, + 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xd841325d, 0x2030007b, 0xcf01325b, + 0x800016f2, 0xd841325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9c, 0x8c001608, + 0xd8080278, 0xd8080280, 0x90000000, 0xd840004f, 0xc414000e, 0x29540008, 0xcd400013, 0xc43d3265, + 0x1bc800ea, 0xd80802e9, 0x7c40c001, 0x18fc0064, 0x9bc00042, 0xc4193246, 0xc41d3245, 0x51980020, + 0x7dd9801a, 0x45980400, 0xc4313267, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x9bc00001, 0x1b380057, + 0x1b340213, 0x1b300199, 0x7f7b400a, 0x7f73400a, 0xcf400024, 0x14f4001d, 0xc4bf02e9, 0x9bc0001c, + 0x7c410001, 0x192807fa, 0xc4bf0258, 0xc4a70250, 0x53fc0020, 0x7e7e401a, 0x042c0000, 0x04300000, + 0x667c0001, 0x56640001, 0x06ec0001, 0x97c0fffd, 0x07300001, 0x0aec0001, 0x7eebc00c, 0x06ec0001, + 0x97c0fff8, 0x0b300001, 0x43300007, 0x53300002, 0x7db30011, 0xd3000025, 0xc03ec005, 0x2bfca200, + 0xcfc00026, 0xccc00026, 0xcd000026, 0x192807fa, 0xc01f007f, 0x7d1d0009, 0x2110007d, 0x8c001628, + 0x203c003f, 0xcfc13256, 0x8c0017f5, 0xcd013254, 0x18fc01e8, 0xcfc13248, 0x8c00185b, 0xd8413247, + 0x0b740001, 0x9b40ffd5, 0xd800004f, 0xc4bf02e9, 0x97c0ea24, 0x90000000, 0x14d4001d, 0xc4930260, + 0x7d52400e, 0xc49f0258, 0xc4a30250, 0x51dc0020, 0x7de1801a, 0x96400017, 0x7d534002, 0xc4af0270, + 0x7dae4005, 0x26640001, 0x32e0001f, 0x9a400006, 0x06ec0001, 0x96000002, 0x042c0000, 0xcec80270, + 0x8000174f, 0x0b740001, 0x8c00178a, 0x05100001, 0x9b40fff3, 0xc4af0280, 0xc4b30278, 0x52ec0020, + 0x7ef2c01a, 0x8c001608, 0xd8080278, 0xd8080280, 0xc4ab0268, 0x7daa4005, 0x26640001, 0x32a0001f, + 0x9a400005, 0x06a80001, 0x96000002, 0x24280000, 0x80001765, 0x7c410001, 0xc01f007f, 0x09540001, + 0x7d1d0009, 0x2110007d, 0x8c001628, 0xd8013256, 0x8c0017f2, 0xcd013254, 0xc4113248, 0x15100004, + 0x11100004, 0xc4b3034b, 0x7f13000a, 0xcf013248, 0xc4930260, 0x8c001855, 0x32a4001f, 0xd8413247, + 0xd800004f, 0x09100001, 0x06a80001, 0x96400002, 0x24280000, 0xcd080260, 0xce880268, 0x9940ffc0, + 0x7c408001, 0x88000000, 0x7ec28001, 0x8c001628, 0x32e0001f, 0xc4253247, 0x26640001, 0x9640005e, + 0xc4293265, 0xc4253255, 0xc431324f, 0x7e72400c, 0x26a80040, 0x9a400002, 0x9680fff7, 0xc429325b, + 0x1aa4003f, 0x96400049, 0x1aa400e8, 0x32680003, 0x9a800046, 0x32640002, 0x9640000a, 0xc4293260, + 0x1aa400e4, 0x32640004, 0x96400040, 0xc425325d, 0x26640010, 0x9a40fffe, 0x800017e2, 0xcdc00013, + 0xc027ffff, 0x2e6400ff, 0xc429325b, 0x7e6a4009, 0xce41325b, 0xc429325b, 0x26a800ff, 0x9a80fffe, + 0xd8c00033, 0xc4240009, 0x26640008, 0x9640fffe, 0x19e403e6, 0x26680003, 0x12a80004, 0x26640003, + 0x12640003, 0x7ea68001, 0x19e400e8, 0x7ea68001, 0x12640001, 0x7ea68001, 0x06a80002, 0xd8400013, + 0x19e40064, 0x32640002, 0x96400009, 0x16a40005, 0x06640003, 0xce412082, 0xcc01203f, 0xd8400013, + 0xcc01203f, 0x0a640003, 0x800017d0, 0x16a40005, 0xce412082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x12640005, 0x7ea64002, 0xc4292083, 0x7ea68005, 0x26a80001, 0x9a80ffdf, 0xd8c00034, 0xcdc00013, + 0xc425325d, 0x26640010, 0x9a40fffe, 0xc429325b, 0x26a400ff, 0x9a40ffca, 0xd841325d, 0x2024007b, + 0xce41325b, 0x800017e3, 0xd841325d, 0xc4a70280, 0xc4ab0278, 0x52640020, 0x7e6a401a, 0x04280001, + 0x7eae8014, 0x7e6a401a, 0x56680020, 0xce480278, 0xce880280, 0x06ec0001, 0x96000002, 0x042c0000, + 0xcec80270, 0x90000000, 0x7c438001, 0x7c420001, 0x800017fe, 0xc4bf02e9, 0x9bc00006, 0x7c438001, + 0x7c420001, 0xcf800026, 0xce000026, 0x800017fe, 0xc43b02eb, 0xc42302ec, 0xcf813245, 0xce013246, + 0x52200020, 0x7fa3801a, 0x47b8020c, 0x15e00008, 0x1220000a, 0x2a206032, 0x513c001e, 0x7e3e001a, + 0xc4bf02e9, 0x9bc00005, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x8000180f, 0xcd400013, 0xc4313267, + 0x1b3c0077, 0x1b300199, 0x7ff3000a, 0x1330000a, 0x2b300032, 0x043c3000, 0xcfc13267, 0xc43d3267, + 0xd200000b, 0xc4200007, 0xd3800002, 0xcf000002, 0xd8000040, 0x96000002, 0xd8400040, 0xd8400018, + 0x043c2000, 0xcfc13267, 0xd8000018, 0xd8800010, 0xcdc00013, 0x7dc30001, 0xdc1e0000, 0x04380032, + 0xcf80000e, 0x8c001427, 0xcc413248, 0xc43d3269, 0x27fc000f, 0x33fc0003, 0x97c00011, 0x043c001f, + 0xdfc30000, 0xd4413249, 0x7c43c001, 0x7c43c001, 0x043c0024, 0x0bfc0021, 0xdfc30000, 0xd441326a, + 0x173c0008, 0x1b300303, 0x7f3f0001, 0x043c0001, 0x7ff3c004, 0xcfc13084, 0x80001842, 0x043c0024, + 0xdfc30000, 0xd4413249, 0x7c43c001, 0x23fc003f, 0xcfc1326d, 0x0bb80026, 0xdf830000, 0xd441326e, + 0x7c438001, 0x7c438001, 0xc4393265, 0x1fb8ffc6, 0xddc30000, 0xcf813265, 0x9a000003, 0xcdc0000c, + 0x80001852, 0xcdc0000d, 0xce000010, 0x8c00142b, 0x90000000, 0x7c41c001, 0x7c420001, 0xcdc13252, + 0xce013253, 0x8c001628, 0x80001878, 0xc49f02e9, 0x99c00018, 0x7c41c001, 0x7c420001, 0xcdc13252, + 0xce013253, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x97c0ffff, + 0xcdc00026, 0xce000026, 0xd8400027, 0xc41c0012, 0x99c0ffff, 0xc43c000e, 0x2bfc0008, 0xcfc00013, + 0x043c2000, 0xcfc13267, 0x8c001628, 0x80001878, 0xc41f02ed, 0xc42302ee, 0xcdc13252, 0xce013253, + 0x04200001, 0x7e2a0004, 0xce013084, 0x90000000, 0x28340001, 0x313c0bcc, 0x9bc00010, 0x393c051f, + 0x9bc00004, 0x3d3c050e, 0x9bc0000c, 0x97c0000c, 0x393c0560, 0x9bc00004, 0x3d3c054f, 0x9bc00007, + 0x97c00007, 0x393c1538, 0x9bc00005, 0x3d3c1537, 0x9bc00002, 0x97c00002, 0x2b740800, 0x90000000, + 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e8007c, 0x7c42c001, + 0x06a8189a, 0x86800000, 0x8000189e, 0x800018c5, 0x800018f2, 0x8000016a, 0x7c414001, 0x18d0007e, + 0x50580020, 0x09200001, 0x7d59401a, 0xd1400072, 0xc8140072, 0x09240002, 0x7c418001, 0x7c41c001, + 0x99000011, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42130b5, 0x1a24002c, 0x9a40fffe, 0x2020002c, + 0xc418000d, 0x1198001c, 0x10cc0004, 0x14cc0004, 0x7cd8c00a, 0xccc130b7, 0xce0130b5, 0xcf400008, + 0x80000168, 0xd1400025, 0x5978073a, 0x2bb80002, 0xcf800024, 0xcd800026, 0xcdc00026, 0xd8400027, + 0x9600e8a8, 0xc4300012, 0x9b00ffff, 0x9640e8a5, 0x800018a9, 0x04140000, 0xc55b0309, 0x3d5c0010, + 0x05540001, 0x2598ffff, 0x09780001, 0x7dad800c, 0x99c0ffd2, 0x9580fff9, 0xc4970258, 0xc4930250, + 0x51540020, 0x7d15001a, 0x04140020, 0x04280000, 0x442c0000, 0x65180001, 0x09540001, 0x55100001, + 0x9580000b, 0x8c001628, 0xc41d3248, 0x04300001, 0x7f2b0014, 0x25dc000f, 0x7df9c00c, 0x95c00004, + 0x7ef2c01a, 0xd8c13260, 0xd901325d, 0x06a80001, 0x9940fff1, 0x04140020, 0x04280000, 0x66d80001, + 0x09540001, 0x56ec0001, 0x95800005, 0x8c001628, 0xc421325d, 0x26240007, 0x9a40fffe, 0x06a80001, + 0x9940fff7, 0x8000189e, 0x04140020, 0x04280000, 0x09540001, 0x8c001628, 0xc41d3254, 0xc023007f, + 0x19e4003e, 0x7de1c009, 0x7dee000c, 0x96400008, 0x96000007, 0xd8c13260, 0xd901325d, 0xc421325d, + 0x261c0007, 0x99c0fffe, 0x8000189e, 0x06a80001, 0x9940fff0, 0x8000189e, 0xc40c000e, 0x28cc0008, + 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e00064, 0x06281911, 0x14f4001d, 0x24cc0003, + 0x86800000, 0x80001915, 0x800019af, 0x80001a2b, 0x8000016a, 0xcc48032b, 0xcc480333, 0xcc48033b, + 0xcc480343, 0x98800011, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, + 0x04203000, 0xce013267, 0xc4213267, 0x9a000001, 0x1b3c0057, 0x1b200213, 0x1b300199, 0x7e3e000a, + 0x7e32000a, 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, + 0x52ec0020, 0x7ef2c01a, 0x04180000, 0x04140020, 0x04280000, 0x7f438001, 0x8c001628, 0xc41d3247, + 0x25dc0001, 0x95c00068, 0xc4213254, 0x1a1c003e, 0x95c00065, 0xc01f007f, 0x7e1e0009, 0x97800062, + 0x0bb80001, 0x43bc0008, 0x7fcbc001, 0xc7df032b, 0x7e1fc00c, 0x97c0fffa, 0x043c0101, 0x94c00002, + 0x043c0102, 0xc439325b, 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, + 0x97000009, 0xc4393260, 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, + 0x80001994, 0x8c001628, 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, + 0x27b800ff, 0x9b80fffe, 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, + 0x13b80004, 0x27300003, 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, + 0x07b80002, 0xd8400013, 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, + 0xcc01203f, 0xd8400013, 0xcc01203f, 0x0b300003, 0x80001982, 0x17b00005, 0xcf012082, 0xcc01203f, + 0xd8400013, 0xcc01203f, 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, + 0xd8c00034, 0xcdc00013, 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffcb, + 0xcfc1325d, 0x2030007b, 0xcf01325b, 0x80001995, 0xcfc1325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, + 0x98800009, 0x41bc0007, 0x53fc0002, 0x7e7fc011, 0xd3c00025, 0xd8000026, 0xd8400027, 0xc43c0012, + 0x9bc0ffff, 0x653c0001, 0x7dbd8001, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff8f, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0x043c2000, 0xcfc13267, 0xd8080278, 0xd8080280, 0x80000168, 0x7c410001, + 0x04140000, 0xc55b0309, 0x3d5c0010, 0x2598ffff, 0x05540001, 0x7d91800c, 0x95c00003, 0xd4400078, + 0x80000168, 0x9580fff8, 0x09780001, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, + 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x09540001, 0x55100001, + 0x9580005d, 0x8c001628, 0xc4253247, 0x26640001, 0x04200101, 0x96400058, 0x7dc24001, 0xc41d3248, + 0x25dc000f, 0x7df9c00c, 0x95c00053, 0x94c00002, 0x04200102, 0x7e41c001, 0xc425325b, 0x1a70003f, + 0x97000049, 0x1a7000e8, 0x33240003, 0x9a400046, 0x33300002, 0x9700000a, 0xc4253260, 0x1a7000e4, + 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001a21, 0xcdc00013, 0xc033ffff, + 0x2f3000ff, 0xc425325b, 0x7f270009, 0xcf01325b, 0xc425325b, 0x266400ff, 0x9a40fffe, 0xd8c00033, + 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27240003, 0x12640004, 0x27300003, 0x13300003, + 0x7e724001, 0x19f000e8, 0x7e724001, 0x13300001, 0x7e724001, 0x06640002, 0xd8400013, 0x19f00064, + 0x33300002, 0x97000009, 0x16700005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x0b300003, 0x80001a0f, 0x16700005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, + 0x7e730002, 0xc4252083, 0x7e724005, 0x26640001, 0x9a40ffdf, 0xd8c00034, 0xcdc00013, 0xc431325d, + 0x27300010, 0x9b00fffe, 0xc425325b, 0x267000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, 0xcf01325b, + 0x80001a22, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9f, 0xd4400078, + 0xd8080278, 0xd8080280, 0x80000168, 0x8c001a31, 0xd4400078, 0xd8080278, 0xd8080280, 0x7c408001, + 0x88000000, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, 0x04203000, + 0xce013267, 0xc4213267, 0x9a000001, 0x1b180057, 0x1b200213, 0x1b300199, 0x7e1a000a, 0x7e32000a, + 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, 0x52ec0020, + 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x95800060, 0x8c001628, 0xc4193247, 0x25980001, + 0x04200101, 0x94c00005, 0x30f00005, 0x04200005, 0x9b000002, 0x04200102, 0x95800056, 0xc439325b, + 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, + 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001aa2, 0xcdc00013, + 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, + 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, 0x13b80004, 0x27300003, + 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, + 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, + 0xcc01203f, 0x0b300003, 0x80001a90, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xcdc00013, + 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, + 0xcf00325b, 0x80001aa3, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0xc49b02e9, 0x99800005, + 0xd2400025, 0x4664001c, 0xd8000026, 0xd8400027, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff9c, + 0xc49b02e9, 0x99800008, 0xc430000e, 0x2b300008, 0xcf000013, 0x04302000, 0xcf013267, 0xc4313267, + 0x97000001, 0x90000000, 0x244c00ff, 0xcc4c0200, 0x7c408001, 0x88000000, 0xc44f0200, 0xc410000b, + 0xc414000c, 0x7d158010, 0x059cc000, 0xd8400013, 0xccdd0000, 0x7c408001, 0x88000000, 0xc40c0037, + 0x94c0ffff, 0xcc000049, 0xc40c003a, 0x94c0ffff, 0x7c40c001, 0x24d00001, 0x9500e69a, 0x18d0003b, + 0x18d40021, 0x99400006, 0xd840004a, 0xc40c003c, 0x94c0ffff, 0x14cc0001, 0x94c00028, 0xd8000033, + 0xc438000b, 0xc43c0009, 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, + 0x7ffbc00c, 0x97c0fffd, 0x99000004, 0xc0120840, 0x282c0040, 0x80001ae8, 0xc0121841, 0x282c001a, + 0xcd01c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04200004, 0xcec0001b, 0xd8400021, + 0x0a200001, 0x9a00ffff, 0xc425c07f, 0x166c001f, 0x04200004, 0x9ac0fffb, 0xc434000f, 0x9b40ffff, + 0xd801c07f, 0xd8400013, 0xc425c07f, 0xce400078, 0xd8000034, 0x9940e66b, 0xd800004a, 0x7c408001, + 0x88000000, 0xc40c0036, 0x24d00001, 0x9900fffe, 0x18cc0021, 0xccc00047, 0xcc000046, 0xc40c0039, + 0x94c0ffff, 0xc40c003d, 0x98c0ffff, 0x7c40c001, 0x24d003ff, 0x18d47fea, 0x18d87ff4, 0xcd00004c, + 0xcd40004e, 0xcd80004d, 0xd8400013, 0xcd41c405, 0xc02a0001, 0x2aa80001, 0xce800013, 0xcd01c406, + 0xcc01c406, 0xcc01c406, 0xc40c0006, 0x98c0ffff, 0xc414000e, 0x29540008, 0x295c0001, 0xcd400013, + 0xd8c1325e, 0xcdc0001a, 0x11980002, 0x4110000c, 0xc0160800, 0x7d15000a, 0xc0164010, 0xd8400013, + 0xcd41c078, 0xcc01c080, 0xcc01c081, 0xcd81c082, 0xcc01c083, 0xcd01c084, 0xc40c0006, 0x98c0ffff, + 0xd8400048, 0xc40c003b, 0x94c0ffff, 0x80000c16, 0xd8400013, 0xd801c40a, 0xd901c40d, 0xd801c410, + 0xd801c40e, 0xd801c40f, 0xc40c0040, 0x04140001, 0x09540001, 0x9940ffff, 0x04140096, 0xd8400013, + 0xccc1c400, 0xc411c401, 0x9500fffa, 0xc424003e, 0x04d00001, 0x11100002, 0xcd01c40c, 0xc0180034, + 0xcd81c411, 0xd841c414, 0x0a540001, 0xcd41c412, 0x2468000f, 0xc419c416, 0x41980003, 0xc41c003f, + 0x7dda0001, 0x12200002, 0x10cc0002, 0xccc1c40c, 0xd901c411, 0xce41c412, 0xd8800013, 0xce292e40, + 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xc43c0007, 0xdc120000, 0x31144000, + 0x95400005, 0xdc030000, 0xd800002a, 0xcc3c000c, 0x80001b70, 0x33f80003, 0xd4400078, 0x9780e601, + 0x188cfff0, 0x04e40002, 0x80001190, 0x7c408001, 0x88000000, 0xc424005e, 0x96400006, 0x90000000, + 0xc424005e, 0x96400003, 0x7c408001, 0x88000000, 0x80001b74, 0x80000168, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 7440 +}; + +static const PWR_DFY_Section pwr_virus_section4 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54106500, + .dfy_data = { + 0x7e000200, 0x7e020204, 0xc00a0505, 0x00000000, 0xbf8c007f, 0xb8900904, 0xb8911a04, 0xb8920304, + 0xb8930b44, 0x921c0d0c, 0x921c1c13, 0x921d0c12, 0x811c1d1c, 0x811c111c, 0x921cff1c, 0x00000400, + 0x921dff10, 0x00000100, 0x81181d1c, 0x7e040218, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 240 +}; + +static const PWR_DFY_Section pwr_virus_section5 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54106900, + .dfy_data = { + 0x7e080200, 0x7e100204, 0xbefc00ff, 0x00010000, 0x24200087, 0x262200ff, 0x000001f0, 0x20222282, + 0x28182111, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 384 +}; + +static const PWR_DFY_Section pwr_virus_section6 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54116f00, + .dfy_data = { + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4540fe8, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000041, 0x0000000c, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54116f00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb454105e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x000000c0, 0x00000010, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117300, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541065, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x0000001c, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117700, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541069, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000444, 0x0000008a, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117b00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 1024 +}; + +static const PWR_Command_Table pwr_virus_table_post[] = { + { 0x00000000, mmCP_MEC_CNTL }, + { 0x00000000, mmCP_MEC_CNTL }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x54116f00, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000005, mmSRBM_GFX_CNTL }, + { 0x54117300, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000006, mmSRBM_GFX_CNTL }, + { 0x54117700, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000007, mmSRBM_GFX_CNTL }, + { 0x54117b00, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000104, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000204, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000304, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000404, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000504, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000604, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000704, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000005, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000105, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000205, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000305, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000405, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000505, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000605, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000705, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000006, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000106, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000206, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000306, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000406, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000506, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000606, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000706, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000007, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000107, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000207, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000307, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000407, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000507, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000607, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000707, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000008, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000108, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000208, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000308, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000408, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000508, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000608, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000708, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000009, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000109, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000209, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000309, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000409, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000509, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000609, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000709, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, 0xFFFFFFFF }, +}; + + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/power_state.h b/drivers/gpu/drm/amd/pm/inc/power_state.h new file mode 100644 index 000000000000..a5f2227a3971 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/power_state.h @@ -0,0 +1,196 @@ +/* + * Copyright 2015 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 PP_POWERSTATE_H +#define PP_POWERSTATE_H + +struct pp_hw_power_state { + unsigned int magic; +}; + +struct pp_power_state; + + +#define PP_INVALID_POWER_STATE_ID (0) + + +/* + * An item of a list containing Power States. + */ + +struct PP_StateLinkedList { + struct pp_power_state *next; + struct pp_power_state *prev; +}; + + +enum PP_StateUILabel { + PP_StateUILabel_None, + PP_StateUILabel_Battery, + PP_StateUILabel_MiddleLow, + PP_StateUILabel_Balanced, + PP_StateUILabel_MiddleHigh, + PP_StateUILabel_Performance, + PP_StateUILabel_BACO +}; + +enum PP_StateClassificationFlag { + PP_StateClassificationFlag_Boot = 0x0001, + PP_StateClassificationFlag_Thermal = 0x0002, + PP_StateClassificationFlag_LimitedPowerSource = 0x0004, + PP_StateClassificationFlag_Rest = 0x0008, + PP_StateClassificationFlag_Forced = 0x0010, + PP_StateClassificationFlag_User3DPerformance = 0x0020, + PP_StateClassificationFlag_User2DPerformance = 0x0040, + PP_StateClassificationFlag_3DPerformance = 0x0080, + PP_StateClassificationFlag_ACOverdriveTemplate = 0x0100, + PP_StateClassificationFlag_Uvd = 0x0200, + PP_StateClassificationFlag_3DPerformanceLow = 0x0400, + PP_StateClassificationFlag_ACPI = 0x0800, + PP_StateClassificationFlag_HD2 = 0x1000, + PP_StateClassificationFlag_UvdHD = 0x2000, + PP_StateClassificationFlag_UvdSD = 0x4000, + PP_StateClassificationFlag_UserDCPerformance = 0x8000, + PP_StateClassificationFlag_DCOverdriveTemplate = 0x10000, + PP_StateClassificationFlag_BACO = 0x20000, + PP_StateClassificationFlag_LimitedPowerSource_2 = 0x40000, + PP_StateClassificationFlag_ULV = 0x80000, + PP_StateClassificationFlag_UvdMVC = 0x100000, +}; + +typedef unsigned int PP_StateClassificationFlags; + +struct PP_StateClassificationBlock { + enum PP_StateUILabel ui_label; + enum PP_StateClassificationFlag flags; + int bios_index; + bool temporary_state; + bool to_be_deleted; +}; + +struct PP_StatePcieBlock { + unsigned int lanes; +}; + +enum PP_RefreshrateSource { + PP_RefreshrateSource_EDID, + PP_RefreshrateSource_Explicit +}; + +struct PP_StateDisplayBlock { + bool disableFrameModulation; + bool limitRefreshrate; + enum PP_RefreshrateSource refreshrateSource; + int explicitRefreshrate; + int edidRefreshrateIndex; + bool enableVariBright; +}; + +struct PP_StateMemroyBlock { + bool dllOff; + uint8_t m3arb; + uint8_t unused[3]; +}; + +struct PP_StateSoftwareAlgorithmBlock { + bool disableLoadBalancing; + bool enableSleepForTimestamps; +}; + +#define PP_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 + +/** + * Type to hold a temperature range. + */ +struct PP_TemperatureRange { + int min; + int max; + int edge_emergency_max; + int hotspot_min; + int hotspot_crit_max; + int hotspot_emergency_max; + int mem_min; + int mem_crit_max; + int mem_emergency_max; +}; + +struct PP_StateValidationBlock { + bool singleDisplayOnly; + bool disallowOnDC; + uint8_t supportedPowerLevels; +}; + +struct PP_UVD_CLOCKS { + uint32_t VCLK; + uint32_t DCLK; +}; + +/** +* Structure to hold a PowerPlay Power State. +*/ +struct pp_power_state { + uint32_t id; + struct PP_StateLinkedList orderedList; + struct PP_StateLinkedList allStatesList; + + struct PP_StateClassificationBlock classification; + struct PP_StateValidationBlock validation; + struct PP_StatePcieBlock pcie; + struct PP_StateDisplayBlock display; + struct PP_StateMemroyBlock memory; + struct PP_TemperatureRange temperatures; + struct PP_StateSoftwareAlgorithmBlock software; + struct PP_UVD_CLOCKS uvd_clocks; + struct pp_hw_power_state hardware; +}; + +enum PP_MMProfilingState { + PP_MMProfilingState_NA = 0, + PP_MMProfilingState_Started, + PP_MMProfilingState_Stopped +}; + +struct pp_clock_engine_request { + unsigned long client_type; + unsigned long ctx_id; + uint64_t context_handle; + unsigned long sclk; + unsigned long sclk_hard_min; + unsigned long mclk; + unsigned long iclk; + unsigned long evclk; + unsigned long ecclk; + unsigned long ecclk_hard_min; + unsigned long vclk; + unsigned long dclk; + unsigned long sclk_over_drive; + unsigned long mclk_over_drive; + unsigned long sclk_threshold; + unsigned long flag; + unsigned long vclk_ceiling; + unsigned long dclk_ceiling; + unsigned long num_cus; + unsigned long pm_flag; + enum PP_MMProfilingState mm_profiling_state; +}; + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/pp_debug.h b/drivers/gpu/drm/amd/pm/inc/pp_debug.h new file mode 100644 index 000000000000..cea65093b6ad --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/pp_debug.h @@ -0,0 +1,62 @@ + +/* + * Copyright 2015 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 PP_DEBUG_H +#define PP_DEBUG_H + +#ifdef pr_fmt +#undef pr_fmt +#endif + +#define pr_fmt(fmt) "amdgpu: [powerplay] " fmt + +#include +#include +#include + +#define PP_ASSERT_WITH_CODE(cond, msg, code) \ + do { \ + if (!(cond)) { \ + pr_warn_ratelimited("%s\n", msg); \ + code; \ + } \ + } while (0) + +#define PP_ASSERT(cond, msg) \ + do { \ + if (!(cond)) { \ + pr_warn_ratelimited("%s\n", msg); \ + } \ + } while (0) + +#define PP_DBG_LOG(fmt, ...) \ + do { \ + pr_debug(fmt, ##__VA_ARGS__); \ + } while (0) + + +#define GET_FLEXIBLE_ARRAY_MEMBER_ADDR(type, member, ptr, n) \ + (type *)((char *)&(ptr)->member + (sizeof(type) * (n))) + +#endif /* PP_DEBUG_H */ + diff --git a/drivers/gpu/drm/amd/pm/inc/pp_endian.h b/drivers/gpu/drm/amd/pm/inc/pp_endian.h new file mode 100644 index 000000000000..f49d1963fe85 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/pp_endian.h @@ -0,0 +1,38 @@ +/* + * Copyright 2016 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 _PP_ENDIAN_H_ +#define _PP_ENDIAN_H_ + +#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X) +#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X) + +#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X) +#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X) + +#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X)) +#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X)) + +#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X)) + +#endif /* _PP_ENDIAN_H_ */ diff --git a/drivers/gpu/drm/amd/pm/inc/pp_thermal.h b/drivers/gpu/drm/amd/pm/inc/pp_thermal.h new file mode 100644 index 000000000000..3e30768f9e1c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/pp_thermal.h @@ -0,0 +1,44 @@ +/* + * Copyright 2018 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 PP_THERMAL_H +#define PP_THERMAL_H + +#include "power_state.h" + +static const struct PP_TemperatureRange SMU7ThermalWithDelayPolicy[] = +{ + {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, + { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, +}; + +static const struct PP_TemperatureRange SMU7ThermalPolicy[] = +{ + {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, + { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, +}; + +#define CTF_OFFSET_EDGE 5 +#define CTF_OFFSET_HOTSPOT 5 +#define CTF_OFFSET_HBM 5 + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/ppinterrupt.h b/drivers/gpu/drm/amd/pm/inc/ppinterrupt.h new file mode 100644 index 000000000000..c067e0925b6b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/ppinterrupt.h @@ -0,0 +1,46 @@ +/* + * Copyright 2015 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 _PP_INTERRUPT_H_ +#define _PP_INTERRUPT_H_ + +enum amd_thermal_irq { + AMD_THERMAL_IRQ_LOW_TO_HIGH = 0, + AMD_THERMAL_IRQ_HIGH_TO_LOW, + + AMD_THERMAL_IRQ_LAST +}; + +/* The type of the interrupt callback functions in PowerPlay */ +typedef int (*irq_handler_func_t)(void *private_data, + unsigned src_id, const uint32_t *iv_entry); + +/* Event Manager action chain list information */ +struct pp_interrupt_registration_info { + irq_handler_func_t call_back; /* Pointer to callback function */ + void *context; /* Pointer to callback function context */ + uint32_t src_id; /* Registered interrupt id */ + const uint32_t *iv_entry; +}; + +#endif /* _PP_INTERRUPT_H_ */ diff --git a/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h new file mode 100644 index 000000000000..df4677da736c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/rv_ppsmc.h @@ -0,0 +1,94 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef RAVEN_PP_SMC_H +#define RAVEN_PP_SMC_H + +#pragma pack(push, 1) + +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_PowerUpGfx 0x6 +#define PPSMC_MSG_EnableGfxOff 0x7 +#define PPSMC_MSG_DisableGfxOff 0x8 +#define PPSMC_MSG_PowerDownIspByTile 0x9 +#define PPSMC_MSG_PowerUpIspByTile 0xA +#define PPSMC_MSG_PowerDownVcn 0xB +#define PPSMC_MSG_PowerUpVcn 0xC +#define PPSMC_MSG_PowerDownSdma 0xD +#define PPSMC_MSG_PowerUpSdma 0xE +#define PPSMC_MSG_SetHardMinIspclkByFreq 0xF +#define PPSMC_MSG_SetHardMinVcn 0x10 +#define PPSMC_MSG_SetMinDisplayClock 0x11 +#define PPSMC_MSG_SetHardMinFclkByFreq 0x12 +#define PPSMC_MSG_SetAllowFclkSwitch 0x13 +#define PPSMC_MSG_SetMinVideoGfxclkFreq 0x14 +#define PPSMC_MSG_ActiveProcessNotify 0x15 +#define PPSMC_MSG_SetCustomPolicy 0x16 +#define PPSMC_MSG_SetVideoFps 0x17 +#define PPSMC_MSG_SetDisplayCount 0x18 +#define PPSMC_MSG_QueryPowerLimit 0x19 +#define PPSMC_MSG_SetDriverDramAddrHigh 0x1A +#define PPSMC_MSG_SetDriverDramAddrLow 0x1B +#define PPSMC_MSG_TransferTableSmu2Dram 0x1C +#define PPSMC_MSG_TransferTableDram2Smu 0x1D +#define PPSMC_MSG_DeviceDriverReset 0x1E +#define PPSMC_MSG_SetGfxclkOverdriveByFreqVid 0x1F +#define PPSMC_MSG_SetHardMinDcefclkByFreq 0x20 +#define PPSMC_MSG_SetHardMinSocclkByFreq 0x21 +#define PPSMC_MSG_SetMinVddcrSocVoltage 0x22 +#define PPSMC_MSG_SetMinVideoFclkFreq 0x23 +#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x24 +#define PPSMC_MSG_ForcePowerDownGfx 0x25 +#define PPSMC_MSG_SetPhyclkVoltageByFreq 0x26 +#define PPSMC_MSG_SetDppclkVoltageByFreq 0x27 +#define PPSMC_MSG_SetSoftMinVcn 0x28 +#define PPSMC_MSG_GetGfxclkFrequency 0x2A +#define PPSMC_MSG_GetFclkFrequency 0x2B +#define PPSMC_MSG_GetMinGfxclkFrequency 0x2C +#define PPSMC_MSG_GetMaxGfxclkFrequency 0x2D +#define PPSMC_MSG_SoftReset 0x2E +#define PPSMC_MSG_SetGfxCGPG 0x2F +#define PPSMC_MSG_SetSoftMaxGfxClk 0x30 +#define PPSMC_MSG_SetHardMinGfxClk 0x31 +#define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x32 +#define PPSMC_MSG_SetSoftMaxFclkByFreq 0x33 +#define PPSMC_MSG_SetSoftMaxVcn 0x34 +#define PPSMC_MSG_PowerGateMmHub 0x35 +#define PPSMC_MSG_SetRccPfcPmeRestoreRegister 0x36 +#define PPSMC_Message_Count 0x37 + +typedef uint16_t PPSMC_Result; +typedef int PPSMC_Msg; + + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu10.h b/drivers/gpu/drm/amd/pm/inc/smu10.h new file mode 100644 index 000000000000..b96520528240 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu10.h @@ -0,0 +1,190 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU10_H +#define SMU10_H + +#pragma pack(push, 1) + +#define ENABLE_DEBUG_FEATURES + +/* Feature Control Defines */ +#define FEATURE_CCLK_CONTROLLER_BIT 0 +#define FEATURE_FAN_CONTROLLER_BIT 1 +#define FEATURE_DATA_CALCULATION_BIT 2 +#define FEATURE_PPT_BIT 3 +#define FEATURE_TDC_BIT 4 +#define FEATURE_THERMAL_BIT 5 +#define FEATURE_FIT_BIT 6 +#define FEATURE_EDC_BIT 7 +#define FEATURE_PLL_POWER_DOWN_BIT 8 +#define FEATURE_ULV_BIT 9 +#define FEATURE_VDDOFF_BIT 10 +#define FEATURE_VCN_DPM_BIT 11 +#define FEATURE_ACP_DPM_BIT 12 +#define FEATURE_ISP_DPM_BIT 13 +#define FEATURE_FCLK_DPM_BIT 14 +#define FEATURE_SOCCLK_DPM_BIT 15 +#define FEATURE_MP0CLK_DPM_BIT 16 +#define FEATURE_LCLK_DPM_BIT 17 +#define FEATURE_SHUBCLK_DPM_BIT 18 +#define FEATURE_DCEFCLK_DPM_BIT 19 +#define FEATURE_GFX_DPM_BIT 20 +#define FEATURE_DS_GFXCLK_BIT 21 +#define FEATURE_DS_SOCCLK_BIT 22 +#define FEATURE_DS_LCLK_BIT 23 +#define FEATURE_DS_DCEFCLK_BIT 24 +#define FEATURE_DS_SHUBCLK_BIT 25 +#define FEATURE_RM_BIT 26 +#define FEATURE_S0i2_BIT 27 +#define FEATURE_WHISPER_MODE_BIT 28 +#define FEATURE_DS_FCLK_BIT 29 +#define FEATURE_DS_SMNCLK_BIT 30 +#define FEATURE_DS_MP1CLK_BIT 31 +#define FEATURE_DS_MP0CLK_BIT 32 +#define FEATURE_MGCG_BIT 33 +#define FEATURE_DS_FUSE_SRAM_BIT 34 +#define FEATURE_GFX_CKS 35 +#define FEATURE_PSI0_BIT 36 +#define FEATURE_PROCHOT_BIT 37 +#define FEATURE_CPUOFF_BIT 38 +#define FEATURE_STAPM_BIT 39 +#define FEATURE_CORE_CSTATES_BIT 40 +#define FEATURE_SPARE_41_BIT 41 +#define FEATURE_SPARE_42_BIT 42 +#define FEATURE_SPARE_43_BIT 43 +#define FEATURE_SPARE_44_BIT 44 +#define FEATURE_SPARE_45_BIT 45 +#define FEATURE_SPARE_46_BIT 46 +#define FEATURE_SPARE_47_BIT 47 +#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_SPARE_49_BIT 49 +#define FEATURE_SPARE_50_BIT 50 +#define FEATURE_SPARE_51_BIT 51 +#define FEATURE_SPARE_52_BIT 52 +#define FEATURE_SPARE_53_BIT 53 +#define FEATURE_SPARE_54_BIT 54 +#define FEATURE_SPARE_55_BIT 55 +#define FEATURE_SPARE_56_BIT 56 +#define FEATURE_SPARE_57_BIT 57 +#define FEATURE_SPARE_58_BIT 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 + +#define NUM_FEATURES 64 + +#define FEATURE_CCLK_CONTROLLER_MASK (1 << FEATURE_CCLK_CONTROLLER_BIT) +#define FEATURE_FAN_CONTROLLER_MASK (1 << FEATURE_FAN_CONTROLLER_BIT) +#define FEATURE_DATA_CALCULATION_MASK (1 << FEATURE_DATA_CALCULATION_BIT) +#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT) +#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT) +#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT) +#define FEATURE_FIT_MASK (1 << FEATURE_FIT_BIT) +#define FEATURE_EDC_MASK (1 << FEATURE_EDC_BIT) +#define FEATURE_PLL_POWER_DOWN_MASK (1 << FEATURE_PLL_POWER_DOWN_BIT) +#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT) +#define FEATURE_VDDOFF_MASK (1 << FEATURE_VDDOFF_BIT) +#define FEATURE_VCN_DPM_MASK (1 << FEATURE_VCN_DPM_BIT) +#define FEATURE_ACP_DPM_MASK (1 << FEATURE_ACP_DPM_BIT) +#define FEATURE_ISP_DPM_MASK (1 << FEATURE_ISP_DPM_BIT) +#define FEATURE_FCLK_DPM_MASK (1 << FEATURE_FCLK_DPM_BIT) +#define FEATURE_SOCCLK_DPM_MASK (1 << FEATURE_SOCCLK_DPM_BIT) +#define FEATURE_MP0CLK_DPM_MASK (1 << FEATURE_MP0CLK_DPM_BIT) +#define FEATURE_LCLK_DPM_MASK (1 << FEATURE_LCLK_DPM_BIT) +#define FEATURE_SHUBCLK_DPM_MASK (1 << FEATURE_SHUBCLK_DPM_BIT) +#define FEATURE_DCEFCLK_DPM_MASK (1 << FEATURE_DCEFCLK_DPM_BIT) +#define FEATURE_GFX_DPM_MASK (1 << FEATURE_GFX_DPM_BIT) +#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT) +#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT) +#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT) +#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT) +#define FEATURE_DS_SHUBCLK_MASK (1 << FEATURE_DS_SHUBCLK_BIT) +#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT) +#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT) +#define FEATURE_DS_SMNCLK_MASK (1 << FEATURE_DS_SMNCLK_BIT) +#define FEATURE_DS_MP1CLK_MASK (1 << FEATURE_DS_MP1CLK_BIT) +#define FEATURE_DS_MP0CLK_MASK (1 << FEATURE_DS_MP0CLK_BIT) +#define FEATURE_MGCG_MASK (1 << FEATURE_MGCG_BIT) +#define FEATURE_DS_FUSE_SRAM_MASK (1 << FEATURE_DS_FUSE_SRAM_BIT) +#define FEATURE_PSI0_MASK (1 << FEATURE_PSI0_BIT) +#define FEATURE_STAPM_MASK (1 << FEATURE_STAPM_BIT) +#define FEATURE_PROCHOT_MASK (1 << FEATURE_PROCHOT_BIT) +#define FEATURE_CPUOFF_MASK (1 << FEATURE_CPUOFF_BIT) +#define FEATURE_CORE_CSTATES_MASK (1 << FEATURE_CORE_CSTATES_BIT) + +/* Workload bits */ +#define WORKLOAD_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_COUNT 7 + +typedef struct { + /* MP1_EXT_SCRATCH0 */ + uint32_t CurrLevel_ACP : 4; + uint32_t CurrLevel_ISP : 4; + uint32_t CurrLevel_VCN : 4; + uint32_t CurrLevel_LCLK : 4; + uint32_t CurrLevel_MP0CLK : 4; + uint32_t CurrLevel_FCLK : 4; + uint32_t CurrLevel_SOCCLK : 4; + uint32_t CurrLevel_DCEFCLK : 4; + /* MP1_EXT_SCRATCH1 */ + uint32_t TargLevel_ACP : 4; + uint32_t TargLevel_ISP : 4; + uint32_t TargLevel_VCN : 4; + uint32_t TargLevel_LCLK : 4; + uint32_t TargLevel_MP0CLK : 4; + uint32_t TargLevel_FCLK : 4; + uint32_t TargLevel_SOCCLK : 4; + uint32_t TargLevel_DCEFCLK : 4; + /* MP1_EXT_SCRATCH2 */ + uint32_t CurrLevel_SHUBCLK : 4; + uint32_t TargLevel_SHUBCLK : 4; + uint32_t InUlv : 1; + uint32_t InS0i2 : 1; + uint32_t InWhisperMode : 1; + uint32_t Reserved : 21; + /* MP1_EXT_SCRATCH3-4 */ + uint32_t Reserved2[2]; + /* MP1_EXT_SCRATCH5 */ + uint32_t FeatureStatus[NUM_FEATURES / 32]; +} FwStatus_t; + +#define TABLE_BIOS_IF 0 /* Called by BIOS */ +#define TABLE_WATERMARKS 1 /* Called by Driver */ +#define TABLE_CUSTOM_DPM 2 /* Called by Driver */ +#define TABLE_PMSTATUSLOG 3 /* Called by Tools for Agm logging */ +#define TABLE_DPMCLOCKS 4 /* Called by Driver */ +#define TABLE_MOMENTARY_PM 5 /* Called by Tools */ +#define TABLE_COUNT 6 + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h new file mode 100644 index 000000000000..dea8fe93da63 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu10_driver_if.h @@ -0,0 +1,116 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU10_DRIVER_IF_H +#define SMU10_DRIVER_IF_H + +#define SMU10_DRIVER_IF_VERSION 0x6 + +#define NUM_DSPCLK_LEVELS 8 + +typedef struct { + int32_t value; + uint32_t numFractionalBits; +} FloatInIntFormat_t; + +typedef enum { + DSPCLK_DCEFCLK = 0, + DSPCLK_DISPCLK, + DSPCLK_PIXCLK, + DSPCLK_PHYCLK, + DSPCLK_COUNT, +} DSPCLK_e; + +typedef struct { + uint16_t Freq; + uint16_t Vid; +} DisplayClockTable_t; + + +typedef struct { + uint16_t MinClock; /* This is either DCFCLK or SOCCLK (in MHz) */ + uint16_t MaxClock; /* This is either DCFCLK or SOCCLK (in MHz) */ + uint16_t MinMclk; + uint16_t MaxMclk; + + uint8_t WmSetting; + uint8_t Padding[3]; +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef struct { + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; + uint32_t MmHubPadding[7]; +} Watermarks_t; + +typedef enum { + CUSTOM_DPM_SETTING_GFXCLK, + CUSTOM_DPM_SETTING_CCLK, + CUSTOM_DPM_SETTING_FCLK_CCX, + CUSTOM_DPM_SETTING_FCLK_GFX, + CUSTOM_DPM_SETTING_FCLK_STALLS, + CUSTOM_DPM_SETTING_LCLK, + CUSTOM_DPM_SETTING_COUNT, +} CUSTOM_DPM_SETTING_e; + +typedef struct { + uint8_t ActiveHystLimit; + uint8_t IdleHystLimit; + uint8_t FPS; + uint8_t MinActiveFreqType; + FloatInIntFormat_t MinActiveFreq; + FloatInIntFormat_t PD_Data_limit; + FloatInIntFormat_t PD_Data_time_constant; + FloatInIntFormat_t PD_Data_error_coeff; + FloatInIntFormat_t PD_Data_error_rate_coeff; +} DpmActivityMonitorCoeffExt_t; + +typedef struct { + DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT]; +} CustomDpmSettings_t; + +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_DCEFCLK_DPM_LEVELS 4 +#define NUM_FCLK_DPM_LEVELS 4 +#define NUM_MEMCLK_DPM_LEVELS 4 + +typedef struct { + uint32_t Freq; /* In MHz */ + uint32_t Vol; /* Millivolts with 2 fractional bits */ +} DpmClock_t; + +typedef struct { + DpmClock_t DcefClocks[NUM_DCEFCLK_DPM_LEVELS]; + DpmClock_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + DpmClock_t FClocks[NUM_FCLK_DPM_LEVELS]; + DpmClock_t MemClocks[NUM_MEMCLK_DPM_LEVELS]; +} DpmClocks_t; + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h new file mode 100644 index 000000000000..fdc6b7a57bc9 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if.h @@ -0,0 +1,893 @@ +/* + * Copyright 2018 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 SMU11_DRIVER_IF_H +#define SMU11_DRIVER_IF_H + +// *** IMPORTANT *** +// SMU TEAM: Always increment the interface version if +// any structure is changed in this file +// Be aware of that the version should be updated in +// smu_v11_0.h, rename is also needed. +// #define SMU11_DRIVER_IF_VERSION 0x13 + +#define PPTABLE_V20_SMU_VERSION 3 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_ECLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_UCLK_DPM_LEVELS 4 +#define NUM_FCLK_DPM_LEVELS 8 +#define NUM_DCEFCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_PIXCLK_DPM_LEVELS 8 +#define NUM_PHYCLK_DPM_LEVELS 8 +#define NUM_LINK_LEVELS 2 +#define NUM_XGMI_LEVELS 2 + +#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) +#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) +#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) +#define MAX_ECLK_DPM_LEVEL (NUM_ECLK_DPM_LEVELS - 1) +#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) +#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) +#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) +#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) +#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) +#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) +#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) +#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) +#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) +#define MAX_XGMI_LEVEL (NUM_XGMI_LEVELS - 1) + +#define PPSMC_GeminiModeNone 0 +#define PPSMC_GeminiModeMaster 1 +#define PPSMC_GeminiModeSlave 2 + + +#define FEATURE_DPM_PREFETCHER_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_UCLK_BIT 2 +#define FEATURE_DPM_SOCCLK_BIT 3 +#define FEATURE_DPM_UVD_BIT 4 +#define FEATURE_DPM_VCE_BIT 5 +#define FEATURE_ULV_BIT 6 +#define FEATURE_DPM_MP0CLK_BIT 7 +#define FEATURE_DPM_LINK_BIT 8 +#define FEATURE_DPM_DCEFCLK_BIT 9 +#define FEATURE_DS_GFXCLK_BIT 10 +#define FEATURE_DS_SOCCLK_BIT 11 +#define FEATURE_DS_LCLK_BIT 12 +#define FEATURE_PPT_BIT 13 +#define FEATURE_TDC_BIT 14 +#define FEATURE_THERMAL_BIT 15 +#define FEATURE_GFX_PER_CU_CG_BIT 16 +#define FEATURE_RM_BIT 17 +#define FEATURE_DS_DCEFCLK_BIT 18 +#define FEATURE_ACDC_BIT 19 +#define FEATURE_VR0HOT_BIT 20 +#define FEATURE_VR1HOT_BIT 21 +#define FEATURE_FW_CTF_BIT 22 +#define FEATURE_LED_DISPLAY_BIT 23 +#define FEATURE_FAN_CONTROL_BIT 24 +#define FEATURE_GFX_EDC_BIT 25 +#define FEATURE_GFXOFF_BIT 26 +#define FEATURE_CG_BIT 27 +#define FEATURE_DPM_FCLK_BIT 28 +#define FEATURE_DS_FCLK_BIT 29 +#define FEATURE_DS_MP1CLK_BIT 30 +#define FEATURE_DS_MP0CLK_BIT 31 +#define FEATURE_XGMI_BIT 32 +#define FEATURE_ECC_BIT 33 +#define FEATURE_SPARE_34_BIT 34 +#define FEATURE_SPARE_35_BIT 35 +#define FEATURE_SPARE_36_BIT 36 +#define FEATURE_SPARE_37_BIT 37 +#define FEATURE_SPARE_38_BIT 38 +#define FEATURE_SPARE_39_BIT 39 +#define FEATURE_SPARE_40_BIT 40 +#define FEATURE_SPARE_41_BIT 41 +#define FEATURE_SPARE_42_BIT 42 +#define FEATURE_SPARE_43_BIT 43 +#define FEATURE_SPARE_44_BIT 44 +#define FEATURE_SPARE_45_BIT 45 +#define FEATURE_SPARE_46_BIT 46 +#define FEATURE_SPARE_47_BIT 47 +#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_SPARE_49_BIT 49 +#define FEATURE_SPARE_50_BIT 50 +#define FEATURE_SPARE_51_BIT 51 +#define FEATURE_SPARE_52_BIT 52 +#define FEATURE_SPARE_53_BIT 53 +#define FEATURE_SPARE_54_BIT 54 +#define FEATURE_SPARE_55_BIT 55 +#define FEATURE_SPARE_56_BIT 56 +#define FEATURE_SPARE_57_BIT 57 +#define FEATURE_SPARE_58_BIT 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 + +#define NUM_FEATURES 64 + +#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) +#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) +#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) +#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) +#define FEATURE_DPM_UVD_MASK (1 << FEATURE_DPM_UVD_BIT ) +#define FEATURE_DPM_VCE_MASK (1 << FEATURE_DPM_VCE_BIT ) +#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT ) +#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) +#define FEATURE_DPM_LINK_MASK (1 << FEATURE_DPM_LINK_BIT ) +#define FEATURE_DPM_DCEFCLK_MASK (1 << FEATURE_DPM_DCEFCLK_BIT ) +#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) +#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) +#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) +#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) +#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) +#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) +#define FEATURE_GFX_PER_CU_CG_MASK (1 << FEATURE_GFX_PER_CU_CG_BIT ) +#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT ) +#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT ) +#define FEATURE_ACDC_MASK (1 << FEATURE_ACDC_BIT ) +#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) +#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) +#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) +#define FEATURE_LED_DISPLAY_MASK (1 << FEATURE_LED_DISPLAY_BIT ) +#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) +#define FEATURE_GFX_EDC_MASK (1 << FEATURE_GFX_EDC_BIT ) +#define FEATURE_GFXOFF_MASK (1 << FEATURE_GFXOFF_BIT ) +#define FEATURE_CG_MASK (1 << FEATURE_CG_BIT ) +#define FEATURE_DPM_FCLK_MASK (1 << FEATURE_DPM_FCLK_BIT ) +#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT ) +#define FEATURE_DS_MP1CLK_MASK (1 << FEATURE_DS_MP1CLK_BIT ) +#define FEATURE_DS_MP0CLK_MASK (1 << FEATURE_DS_MP0CLK_BIT ) +#define FEATURE_XGMI_MASK (1ULL << FEATURE_XGMI_BIT ) +#define FEATURE_ECC_MASK (1ULL << FEATURE_ECC_BIT ) + +#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 +#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_SOCCLK 0x00000004 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_UCLK 0x00000008 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000010 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_UCLK 0x00000020 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000040 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_UCLK 0x00000080 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_SOCCLK 0x00000100 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_UCLK 0x00000200 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_SOCCLK 0x00000400 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_UCLK 0x00000800 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00001000 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00002000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_GFXCLK_SWITCH 0x00004000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_SOCCLK_SWITCH 0x00008000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_UCLK_SWITCH 0x00010000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_FCLK_SWITCH 0x00020000 + +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + + +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + + +#define THROTTLER_STATUS_PADDING_BIT 0 +#define THROTTLER_STATUS_TEMP_EDGE_BIT 1 +#define THROTTLER_STATUS_TEMP_HOTSPOT_BIT 2 +#define THROTTLER_STATUS_TEMP_HBM_BIT 3 +#define THROTTLER_STATUS_TEMP_VR_GFX_BIT 4 +#define THROTTLER_STATUS_TEMP_VR_SOC_BIT 5 +#define THROTTLER_STATUS_TEMP_VR_MEM0_BIT 6 +#define THROTTLER_STATUS_TEMP_VR_MEM1_BIT 7 +#define THROTTLER_STATUS_TEMP_LIQUID_BIT 8 +#define THROTTLER_STATUS_TEMP_PLX_BIT 9 +#define THROTTLER_STATUS_TEMP_SKIN_BIT 10 +#define THROTTLER_STATUS_TDC_GFX_BIT 11 +#define THROTTLER_STATUS_TDC_SOC_BIT 12 +#define THROTTLER_STATUS_PPT_BIT 13 +#define THROTTLER_STATUS_FIT_BIT 14 +#define THROTTLER_STATUS_PPM_BIT 15 + + +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF + + +#define WORKLOAD_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_COUNT 7 + + +#define XGMI_STATE_D0 1 +#define XGMI_STATE_D3 0 + +typedef enum { + I2C_CONTROLLER_PORT_0 = 0, + I2C_CONTROLLER_PORT_1 = 1, +} I2cControllerPort_e; + +typedef enum { + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VDDCI, + I2C_CONTROLLER_NAME_VR_HBM, + I2C_CONTROLLER_NAME_LIQUID_0, + I2C_CONTROLLER_NAME_LIQUID_1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_COUNT, +} I2cControllerName_e; + +typedef enum { + I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, + I2C_CONTROLLER_THROTTLER_VR_GFX, + I2C_CONTROLLER_THROTTLER_VR_SOC, + I2C_CONTROLLER_THROTTLER_VR_VDDCI, + I2C_CONTROLLER_THROTTLER_VR_HBM, + I2C_CONTROLLER_THROTTLER_LIQUID_0, + I2C_CONTROLLER_THROTTLER_LIQUID_1, + I2C_CONTROLLER_THROTTLER_PLX, +} I2cControllerThrottler_e; + +typedef enum { + I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, + I2C_CONTROLLER_PROTOCOL_VR_IR35217, + I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, + I2C_CONTROLLER_PROTOCOL_SPARE_0, + I2C_CONTROLLER_PROTOCOL_SPARE_1, + I2C_CONTROLLER_PROTOCOL_SPARE_2, +} I2cControllerProtocol_e; + +typedef enum { + I2C_CONTROLLER_SPEED_SLOW = 0, + I2C_CONTROLLER_SPEED_FAST = 1, +} I2cControllerSpeed_e; + +typedef struct { + uint32_t Enabled; + uint32_t SlaveAddress; + uint32_t ControllerPort; + uint32_t ControllerName; + + uint32_t ThermalThrottler; + uint32_t I2cProtocol; + uint32_t I2cSpeed; +} I2cControllerConfig_t; + +typedef struct { + uint32_t a; + uint32_t b; + uint32_t c; +} QuadraticInt_t; + +typedef struct { + uint32_t m; + uint32_t b; +} LinearInt_t; + +typedef struct { + uint32_t a; + uint32_t b; + uint32_t c; +} DroopInt_t; + +typedef enum { + PPCLK_GFXCLK, + PPCLK_VCLK, + PPCLK_DCLK, + PPCLK_ECLK, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_DCEFCLK, + PPCLK_DISPCLK, + PPCLK_PIXCLK, + PPCLK_PHYCLK, + PPCLK_FCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef enum { + POWER_SOURCE_AC, + POWER_SOURCE_DC, + POWER_SOURCE_COUNT, +} POWER_SOURCE_e; + +typedef enum { + VOLTAGE_MODE_AVFS = 0, + VOLTAGE_MODE_AVFS_SS, + VOLTAGE_MODE_SS, + VOLTAGE_MODE_COUNT, +} VOLTAGE_MODE_e; + + +typedef enum { + AVFS_VOLTAGE_GFX = 0, + AVFS_VOLTAGE_SOC, + AVFS_VOLTAGE_COUNT, +} AVFS_VOLTAGE_TYPE_e; + + +typedef struct { + uint8_t VoltageMode; + uint8_t SnapToDiscrete; + uint8_t NumDiscreteLevels; + uint8_t padding; + LinearInt_t ConversionToAvfsClk; + QuadraticInt_t SsCurve; +} DpmDescriptor_t; + +typedef struct { + uint32_t Version; + + + uint32_t FeaturesToRun[2]; + + + uint16_t SocketPowerLimitAc0; + uint16_t SocketPowerLimitAc0Tau; + uint16_t SocketPowerLimitAc1; + uint16_t SocketPowerLimitAc1Tau; + uint16_t SocketPowerLimitAc2; + uint16_t SocketPowerLimitAc2Tau; + uint16_t SocketPowerLimitAc3; + uint16_t SocketPowerLimitAc3Tau; + uint16_t SocketPowerLimitDc; + uint16_t SocketPowerLimitDcTau; + uint16_t TdcLimitSoc; + uint16_t TdcLimitSocTau; + uint16_t TdcLimitGfx; + uint16_t TdcLimitGfxTau; + + uint16_t TedgeLimit; + uint16_t ThotspotLimit; + uint16_t ThbmLimit; + uint16_t Tvr_gfxLimit; + uint16_t Tvr_memLimit; + uint16_t Tliquid1Limit; + uint16_t Tliquid2Limit; + uint16_t TplxLimit; + uint32_t FitLimit; + + uint16_t PpmPowerLimit; + uint16_t PpmTemperatureThreshold; + + uint8_t MemoryOnPackage; + uint8_t padding8_limits; + uint16_t Tvr_SocLimit; + + uint16_t UlvVoltageOffsetSoc; + uint16_t UlvVoltageOffsetGfx; + + uint8_t UlvSmnclkDid; + uint8_t UlvMp1clkDid; + uint8_t UlvGfxclkBypass; + uint8_t Padding234; + + + uint16_t MinVoltageGfx; + uint16_t MinVoltageSoc; + uint16_t MaxVoltageGfx; + uint16_t MaxVoltageSoc; + + uint16_t LoadLineResistanceGfx; + uint16_t LoadLineResistanceSoc; + + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; + uint16_t FreqTableEclk [NUM_ECLK_DPM_LEVELS ]; + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; + uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; + uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; + uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; + uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; + + uint16_t DcModeMaxFreq [PPCLK_COUNT ]; + uint16_t Padding8_Clks; + + uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; + uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; + + + uint16_t GfxclkFidle; + uint16_t GfxclkSlewRate; + uint16_t CksEnableFreq; + uint16_t Padding789; + QuadraticInt_t CksVoltageOffset; + uint8_t Padding567[4]; + uint16_t GfxclkDsMaxFreq; + uint8_t GfxclkSource; + uint8_t Padding456; + + uint8_t LowestUclkReservedForUlv; + uint8_t Padding8_Uclk[3]; + + + uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; + uint8_t PcieLaneCount[NUM_LINK_LEVELS]; + uint16_t LclkFreq[NUM_LINK_LEVELS]; + + + uint16_t EnableTdpm; + uint16_t TdpmHighHystTemperature; + uint16_t TdpmLowHystTemperature; + uint16_t GfxclkFreqHighTempLimit; + + + uint16_t FanStopTemp; + uint16_t FanStartTemp; + + uint16_t FanGainEdge; + uint16_t FanGainHotspot; + uint16_t FanGainLiquid; + uint16_t FanGainVrGfx; + uint16_t FanGainVrSoc; + uint16_t FanGainPlx; + uint16_t FanGainHbm; + uint16_t FanPwmMin; + uint16_t FanAcousticLimitRpm; + uint16_t FanThrottlingRpm; + uint16_t FanMaximumRpm; + uint16_t FanTargetTemperature; + uint16_t FanTargetGfxclk; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + + + + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_Avfs[2]; + + QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; + DroopInt_t dBtcGbGfxCksOn; + DroopInt_t dBtcGbGfxCksOff; + DroopInt_t dBtcGbGfxAfll; + DroopInt_t dBtcGbSoc; + LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; + + QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; + + uint16_t DcTol[AVFS_VOLTAGE_COUNT]; + + uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_GfxBtc[2]; + + int16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; + uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; + + + uint8_t XgmiLinkSpeed [NUM_XGMI_LEVELS]; + uint8_t XgmiLinkWidth [NUM_XGMI_LEVELS]; + uint16_t XgmiFclkFreq [NUM_XGMI_LEVELS]; + uint16_t XgmiUclkFreq [NUM_XGMI_LEVELS]; + uint16_t XgmiSocclkFreq [NUM_XGMI_LEVELS]; + uint16_t XgmiSocVoltage [NUM_XGMI_LEVELS]; + + uint32_t DebugOverrides; + QuadraticInt_t ReservedEquation0; + QuadraticInt_t ReservedEquation1; + QuadraticInt_t ReservedEquation2; + QuadraticInt_t ReservedEquation3; + + uint16_t MinVoltageUlvGfx; + uint16_t MinVoltageUlvSoc; + + uint16_t MGpuFanBoostLimitRpm; + uint16_t padding16_Fan; + + uint16_t FanGainVrMem0; + uint16_t FanGainVrMem1; + + uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; + + uint32_t Reserved[11]; + + uint32_t Padding32[3]; + + uint16_t MaxVoltageStepGfx; + uint16_t MaxVoltageStepSoc; + + uint8_t VddGfxVrMapping; + uint8_t VddSocVrMapping; + uint8_t VddMem0VrMapping; + uint8_t VddMem1VrMapping; + + uint8_t GfxUlvPhaseSheddingMask; + uint8_t SocUlvPhaseSheddingMask; + uint8_t ExternalSensorPresent; + uint8_t Padding8_V; + + + uint16_t GfxMaxCurrent; + int8_t GfxOffset; + uint8_t Padding_TelemetryGfx; + + uint16_t SocMaxCurrent; + int8_t SocOffset; + uint8_t Padding_TelemetrySoc; + + uint16_t Mem0MaxCurrent; + int8_t Mem0Offset; + uint8_t Padding_TelemetryMem0; + + uint16_t Mem1MaxCurrent; + int8_t Mem1Offset; + uint8_t Padding_TelemetryMem1; + + + uint8_t AcDcGpio; + uint8_t AcDcPolarity; + uint8_t VR0HotGpio; + uint8_t VR0HotPolarity; + + uint8_t VR1HotGpio; + uint8_t VR1HotPolarity; + uint8_t Padding1; + uint8_t Padding2; + + + + uint8_t LedPin0; + uint8_t LedPin1; + uint8_t LedPin2; + uint8_t padding8_4; + + + uint8_t PllGfxclkSpreadEnabled; + uint8_t PllGfxclkSpreadPercent; + uint16_t PllGfxclkSpreadFreq; + + uint8_t UclkSpreadEnabled; + uint8_t UclkSpreadPercent; + uint16_t UclkSpreadFreq; + + uint8_t FclkSpreadEnabled; + uint8_t FclkSpreadPercent; + uint16_t FclkSpreadFreq; + + uint8_t FllGfxclkSpreadEnabled; + uint8_t FllGfxclkSpreadPercent; + uint16_t FllGfxclkSpreadFreq; + + I2cControllerConfig_t I2cControllers[I2C_CONTROLLER_NAME_COUNT]; + + uint32_t BoardReserved[10]; + + + uint32_t MmHubPadding[8]; + +} PPTable_t; + +typedef struct { + + uint16_t GfxclkAverageLpfTau; + uint16_t SocclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + uint16_t SocketPowerLpfTau; + + + uint32_t MmHubPadding[8]; +} DriverSmuConfig_t; + +typedef struct { + + uint16_t GfxclkFmin; + uint16_t GfxclkFmax; + uint16_t GfxclkFreq1; + uint16_t GfxclkVolt1; + uint16_t GfxclkFreq2; + uint16_t GfxclkVolt2; + uint16_t GfxclkFreq3; + uint16_t GfxclkVolt3; + uint16_t UclkFmax; + int16_t OverDrivePct; + uint16_t FanMaximumRpm; + uint16_t FanMinimumPwm; + uint16_t FanTargetTemperature; + uint16_t MaxOpTemp; + uint16_t FanZeroRpmEnable; + uint16_t Padding; + +} OverDriveTable_t; + +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t CurrSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureHBM ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureLiquid ; + uint16_t TemperaturePlx ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint16_t AverageSocketPower; + uint8_t Padding; + + + uint32_t MmHubPadding[7]; +} SmuMetrics_t; + +typedef struct { + uint16_t MinClock; + uint16_t MaxClock; + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Padding[3]; +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCEFCLK, + WM_COUNT_PP, +} WM_CLOCK_e; + +typedef struct { + + WatermarkRowGeneric_t WatermarkRow[WM_COUNT_PP][NUM_WM_RANGES]; + + uint32_t MmHubPadding[7]; +} Watermarks_t; + +typedef struct { + uint16_t avgPsmCount[45]; + uint16_t minPsmCount[45]; + float avgPsmVoltage[45]; + float minPsmVoltage[45]; + + uint16_t avgScsPsmCount; + uint16_t minScsPsmCount; + float avgScsPsmVoltage; + float minScsPsmVoltage; + + + uint32_t MmHubPadding[6]; +} AvfsDebugTable_t; + +typedef struct { + uint8_t AvfsVersion; + uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; + + int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; + int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; + int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; + + int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; + int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; + int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; + + int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; + int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; + int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; + + int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; + int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; + int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; + + int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; + int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; + int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; + + uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; + + uint32_t VInversion[AVFS_VOLTAGE_COUNT]; + + + int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; + int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; + int32_t P2V_b[AVFS_VOLTAGE_COUNT]; + + uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; + + uint32_t EnabledAvfsModules; + + uint32_t MmHubPadding[7]; +} AvfsFuseOverride_t; + +typedef struct { + + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t Gfx_UseRlcBusy; + uint16_t Gfx_MinActiveFreq; + uint16_t Gfx_BoosterFreq; + uint16_t Gfx_PD_Data_time_constant; + uint32_t Gfx_PD_Data_limit_a; + uint32_t Gfx_PD_Data_limit_b; + uint32_t Gfx_PD_Data_limit_c; + uint32_t Gfx_PD_Data_error_coeff; + uint32_t Gfx_PD_Data_error_rate_coeff; + + uint8_t Soc_ActiveHystLimit; + uint8_t Soc_IdleHystLimit; + uint8_t Soc_FPS; + uint8_t Soc_MinActiveFreqType; + uint8_t Soc_BoosterFreqType; + uint8_t Soc_UseRlcBusy; + uint16_t Soc_MinActiveFreq; + uint16_t Soc_BoosterFreq; + uint16_t Soc_PD_Data_time_constant; + uint32_t Soc_PD_Data_limit_a; + uint32_t Soc_PD_Data_limit_b; + uint32_t Soc_PD_Data_limit_c; + uint32_t Soc_PD_Data_error_coeff; + uint32_t Soc_PD_Data_error_rate_coeff; + + uint8_t Mem_ActiveHystLimit; + uint8_t Mem_IdleHystLimit; + uint8_t Mem_FPS; + uint8_t Mem_MinActiveFreqType; + uint8_t Mem_BoosterFreqType; + uint8_t Mem_UseRlcBusy; + uint16_t Mem_MinActiveFreq; + uint16_t Mem_BoosterFreq; + uint16_t Mem_PD_Data_time_constant; + uint32_t Mem_PD_Data_limit_a; + uint32_t Mem_PD_Data_limit_b; + uint32_t Mem_PD_Data_limit_c; + uint32_t Mem_PD_Data_error_coeff; + uint32_t Mem_PD_Data_error_rate_coeff; + + uint8_t Fclk_ActiveHystLimit; + uint8_t Fclk_IdleHystLimit; + uint8_t Fclk_FPS; + uint8_t Fclk_MinActiveFreqType; + uint8_t Fclk_BoosterFreqType; + uint8_t Fclk_UseRlcBusy; + uint16_t Fclk_MinActiveFreq; + uint16_t Fclk_BoosterFreq; + uint16_t Fclk_PD_Data_time_constant; + uint32_t Fclk_PD_Data_limit_a; + uint32_t Fclk_PD_Data_limit_b; + uint32_t Fclk_PD_Data_limit_c; + uint32_t Fclk_PD_Data_error_coeff; + uint32_t Fclk_PD_Data_error_rate_coeff; + +} DpmActivityMonitorCoeffInt_t; + +#define TABLE_PPTABLE 0 +#define TABLE_WATERMARKS 1 +#define TABLE_AVFS 2 +#define TABLE_AVFS_PSM_DEBUG 3 +#define TABLE_AVFS_FUSE_OVERRIDE 4 +#define TABLE_PMSTATUSLOG 5 +#define TABLE_SMU_METRICS 6 +#define TABLE_DRIVER_SMU_CONFIG 7 +#define TABLE_ACTIVITY_MONITOR_COEFF 8 +#define TABLE_OVERDRIVE 9 +#define TABLE_COUNT 10 + + +#define UCLK_SWITCH_SLOW 0 +#define UCLK_SWITCH_FAST 1 + + +#define SQ_Enable_MASK 0x1 +#define SQ_IR_MASK 0x2 +#define SQ_PCC_MASK 0x4 +#define SQ_EDC_MASK 0x8 + +#define TCP_Enable_MASK 0x100 +#define TCP_IR_MASK 0x200 +#define TCP_PCC_MASK 0x400 +#define TCP_EDC_MASK 0x800 + +#define TD_Enable_MASK 0x10000 +#define TD_IR_MASK 0x20000 +#define TD_PCC_MASK 0x40000 +#define TD_EDC_MASK 0x80000 + +#define DB_Enable_MASK 0x1000000 +#define DB_IR_MASK 0x2000000 +#define DB_PCC_MASK 0x4000000 +#define DB_EDC_MASK 0x8000000 + +#define SQ_Enable_SHIFT 0 +#define SQ_IR_SHIFT 1 +#define SQ_PCC_SHIFT 2 +#define SQ_EDC_SHIFT 3 + +#define TCP_Enable_SHIFT 8 +#define TCP_IR_SHIFT 9 +#define TCP_PCC_SHIFT 10 +#define TCP_EDC_SHIFT 11 + +#define TD_Enable_SHIFT 16 +#define TD_IR_SHIFT 17 +#define TD_PCC_SHIFT 18 +#define TD_EDC_SHIFT 19 + +#define DB_Enable_SHIFT 24 +#define DB_IR_SHIFT 25 +#define DB_PCC_SHIFT 26 +#define DB_EDC_SHIFT 27 + +#define REMOVE_FMAX_MARGIN_BIT 0x0 +#define REMOVE_DCTOL_MARGIN_BIT 0x1 +#define REMOVE_PLATFORM_MARGIN_BIT 0x2 + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h new file mode 100644 index 000000000000..43d43d6addc0 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_arcturus.h @@ -0,0 +1,931 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU11_DRIVER_IF_ARCTURUS_H +#define SMU11_DRIVER_IF_ARCTURUS_H + +// *** IMPORTANT *** +// SMU TEAM: Always increment the interface version if +// any structure is changed in this file +//#define SMU11_DRIVER_IF_VERSION 0x09 + +#define PPTABLE_ARCTURUS_SMU_VERSION 4 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_UCLK_DPM_LEVELS 4 +#define NUM_FCLK_DPM_LEVELS 8 +#define NUM_XGMI_LEVELS 2 +#define NUM_XGMI_PSTATE_LEVELS 4 + +#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) +#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) +#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) +#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) +#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) +#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) +#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) +#define MAX_XGMI_LEVEL (NUM_XGMI_LEVELS - 1) +#define MAX_XGMI_PSTATE_LEVEL (NUM_XGMI_PSTATE_LEVELS - 1) + +// Feature Control Defines +// DPM +#define FEATURE_DPM_PREFETCHER_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_UCLK_BIT 2 +#define FEATURE_DPM_SOCCLK_BIT 3 +#define FEATURE_DPM_FCLK_BIT 4 +#define FEATURE_DPM_MP0CLK_BIT 5 +#define FEATURE_DPM_XGMI_BIT 6 +// Idle +#define FEATURE_DS_GFXCLK_BIT 7 +#define FEATURE_DS_SOCCLK_BIT 8 +#define FEATURE_DS_LCLK_BIT 9 +#define FEATURE_DS_FCLK_BIT 10 +#define FEATURE_DS_UCLK_BIT 11 +#define FEATURE_GFX_ULV_BIT 12 +#define FEATURE_DPM_VCN_BIT 13 +#define FEATURE_RSMU_SMN_CG_BIT 14 +#define FEATURE_WAFL_CG_BIT 15 +// Throttler/Response +#define FEATURE_PPT_BIT 16 +#define FEATURE_TDC_BIT 17 +#define FEATURE_APCC_PLUS_BIT 18 +#define FEATURE_VR0HOT_BIT 19 +#define FEATURE_VR1HOT_BIT 20 +#define FEATURE_FW_CTF_BIT 21 +#define FEATURE_FAN_CONTROL_BIT 22 +#define FEATURE_THERMAL_BIT 23 +// Other +#define FEATURE_OUT_OF_BAND_MONITOR_BIT 24 +#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 25 +#define FEATURE_PER_PART_VMIN_BIT 26 + +#define FEATURE_SPARE_27_BIT 27 +#define FEATURE_SPARE_28_BIT 28 +#define FEATURE_SPARE_29_BIT 29 +#define FEATURE_SPARE_30_BIT 30 +#define FEATURE_SPARE_31_BIT 31 +#define FEATURE_SPARE_32_BIT 32 +#define FEATURE_SPARE_33_BIT 33 +#define FEATURE_SPARE_34_BIT 34 +#define FEATURE_SPARE_35_BIT 35 +#define FEATURE_SPARE_36_BIT 36 +#define FEATURE_SPARE_37_BIT 37 +#define FEATURE_SPARE_38_BIT 38 +#define FEATURE_SPARE_39_BIT 39 +#define FEATURE_SPARE_40_BIT 40 +#define FEATURE_SPARE_41_BIT 41 +#define FEATURE_SPARE_42_BIT 42 +#define FEATURE_SPARE_43_BIT 43 +#define FEATURE_SPARE_44_BIT 44 +#define FEATURE_SPARE_45_BIT 45 +#define FEATURE_SPARE_46_BIT 46 +#define FEATURE_SPARE_47_BIT 47 +#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_SPARE_49_BIT 49 +#define FEATURE_SPARE_50_BIT 50 +#define FEATURE_SPARE_51_BIT 51 +#define FEATURE_SPARE_52_BIT 52 +#define FEATURE_SPARE_53_BIT 53 +#define FEATURE_SPARE_54_BIT 54 +#define FEATURE_SPARE_55_BIT 55 +#define FEATURE_SPARE_56_BIT 56 +#define FEATURE_SPARE_57_BIT 57 +#define FEATURE_SPARE_58_BIT 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 + +#define NUM_FEATURES 64 + + +#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) +#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) +#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) +#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) +#define FEATURE_DPM_FCLK_MASK (1 << FEATURE_DPM_FCLK_BIT ) +#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) +#define FEATURE_DPM_XGMI_MASK (1 << FEATURE_DPM_XGMI_BIT ) + +#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) +#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) +#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) +#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT ) +#define FEATURE_DS_UCLK_MASK (1 << FEATURE_DS_UCLK_BIT ) +#define FEATURE_GFX_ULV_MASK (1 << FEATURE_GFX_ULV_BIT ) +#define FEATURE_DPM_VCN_MASK (1 << FEATURE_DPM_VCN_BIT ) +#define FEATURE_RSMU_SMN_CG_MASK (1 << FEATURE_RSMU_SMN_CG_BIT ) +#define FEATURE_WAFL_CG_MASK (1 << FEATURE_WAFL_CG_BIT ) + +#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) +#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) +#define FEATURE_APCC_PLUS_MASK (1 << FEATURE_APCC_PLUS_BIT ) +#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) +#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) +#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) +#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) +#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) + +#define FEATURE_OUT_OF_BAND_MONITOR_MASK (1 << FEATURE_OUT_OF_BAND_MONITOR_BIT ) +#define FEATURE_TEMP_DEPENDENT_VMIN_MASK (1 << FEATURE_TEMP_DEPENDENT_VMIN_BIT ) +#define FEATURE_PER_PART_VMIN_MASK (1 << FEATURE_PER_PART_VMIN_BIT ) + + +//FIXME need updating +// Debug Overrides Bitmask +#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000001 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000002 + +// I2C Config Bit Defines +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +// VR Mapping Bit Defines +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + +// PSI Bit Defines +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + +// Throttler Control/Status Bits +#define THROTTLER_PADDING_BIT 0 +#define THROTTLER_TEMP_EDGE_BIT 1 +#define THROTTLER_TEMP_HOTSPOT_BIT 2 +#define THROTTLER_TEMP_MEM_BIT 3 +#define THROTTLER_TEMP_VR_GFX_BIT 4 +#define THROTTLER_TEMP_VR_MEM_BIT 5 +#define THROTTLER_TEMP_VR_SOC_BIT 6 +#define THROTTLER_TDC_GFX_BIT 7 +#define THROTTLER_TDC_SOC_BIT 8 +#define THROTTLER_PPT0_BIT 9 +#define THROTTLER_PPT1_BIT 10 +#define THROTTLER_PPT2_BIT 11 +#define THROTTLER_PPT3_BIT 12 +#define THROTTLER_PPM_BIT 13 +#define THROTTLER_FIT_BIT 14 +#define THROTTLER_APCC_BIT 15 +#define THROTTLER_VRHOT0_BIT 16 +#define THROTTLER_VRHOT1_BIT 17 + +// Table transfer status +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF +#define TABLE_TRANSFER_PENDING 0xAB + +// Workload bits +#define WORKLOAD_PPLIB_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 1 +#define WORKLOAD_PPLIB_VIDEO_BIT 2 +#define WORKLOAD_PPLIB_COMPUTE_BIT 3 +#define WORKLOAD_PPLIB_CUSTOM_BIT 4 +#define WORKLOAD_PPLIB_COUNT 5 + +//XGMI performance states +#define XGMI_STATE_D0 1 +#define XGMI_STATE_D3 0 + +#define NUM_I2C_CONTROLLERS 8 + +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +#define MAX_SW_I2C_COMMANDS 8 + +typedef enum { + I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 + I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 + I2C_CONTROLLER_PORT_COUNT, +} I2cControllerPort_e; + +typedef enum { + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_MEM, + I2C_CONTROLLER_NAME_SPARE, + I2C_CONTROLLER_NAME_COUNT, +} I2cControllerName_e; + +typedef enum { + I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, + I2C_CONTROLLER_THROTTLER_VR_GFX, + I2C_CONTROLLER_THROTTLER_VR_SOC, + I2C_CONTROLLER_THROTTLER_VR_MEM, + I2C_CONTROLLER_THROTTLER_COUNT, +} I2cControllerThrottler_e; + +typedef enum { + I2C_CONTROLLER_PROTOCOL_VR_0, + I2C_CONTROLLER_PROTOCOL_VR_1, + I2C_CONTROLLER_PROTOCOL_TMP_0, + I2C_CONTROLLER_PROTOCOL_TMP_1, + I2C_CONTROLLER_PROTOCOL_SPARE_0, + I2C_CONTROLLER_PROTOCOL_SPARE_1, + I2C_CONTROLLER_PROTOCOL_COUNT, +} I2cControllerProtocol_e; + +typedef struct { + uint8_t Enabled; + uint8_t Speed; + uint8_t Padding[2]; + uint32_t SlaveAddress; + uint8_t ControllerPort; + uint8_t ControllerName; + uint8_t ThermalThrotter; + uint8_t I2cProtocol; +} I2cControllerConfig_t; + +typedef enum { + I2C_PORT_SVD_SCL = 0, + I2C_PORT_GPIO, +} I2cPort_e; + +typedef enum { + I2C_SPEED_FAST_50K = 0, //50 Kbits/s + I2C_SPEED_FAST_100K, //100 Kbits/s + I2C_SPEED_FAST_400K, //400 Kbits/s + I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) + I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) + I2C_SPEED_HIGH_2M, //2.3 Mbits/s + I2C_SPEED_COUNT, +} I2cSpeed_e; + +typedef enum { + I2C_CMD_READ = 0, + I2C_CMD_WRITE, + I2C_CMD_COUNT, +} I2cCmdType_e; + +#define CMDCONFIG_STOP_BIT 0 +#define CMDCONFIG_RESTART_BIT 1 + +#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) +#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) + +typedef struct { + uint8_t RegisterAddr; ////only valid for write, ignored for read + uint8_t Cmd; //Read(0) or Write(1) + uint8_t Data; //Return data for read. Data to send for write + uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command +} SwI2cCmd_t; //SW I2C Command Table + +typedef struct { + uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) + uint8_t I2CSpeed; //Slow(0) or Fast(1) + uint16_t SlaveAddress; + uint8_t NumCmds; //Number of commands + uint8_t Padding[3]; + + SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; + + uint32_t MmHubPadding[8]; // SMU internal use + +} SwI2cRequest_t; // SW I2C Request Table + +//D3HOT sequences +typedef enum { + BACO_SEQUENCE, + MSR_SEQUENCE, + BAMACO_SEQUENCE, + ULPS_SEQUENCE, + D3HOT_SEQUENCE_COUNT, +}D3HOTSequence_e; + +//THis is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_DYNAMIC_MODE = 0, + PG_STATIC_MODE, +} PowerGatingMode_e; + +//This is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_POWER_DOWN = 0, + PG_POWER_UP, +} PowerGatingSettings_e; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} QuadraticInt_t; + +typedef struct { + uint32_t m; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable +} LinearInt_t; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} DroopInt_t; + +typedef enum { + GFXCLK_SOURCE_PLL = 0, + GFXCLK_SOURCE_AFLL, + GFXCLK_SOURCE_COUNT, +} GfxclkSrc_e; + +typedef enum { + PPCLK_GFXCLK, + PPCLK_VCLK, + PPCLK_DCLK, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_FCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef enum { + POWER_SOURCE_AC, + POWER_SOURCE_DC, + POWER_SOURCE_COUNT, +} POWER_SOURCE_e; + +typedef enum { + TEMP_EDGE, + TEMP_HOTSPOT, + TEMP_MEM, + TEMP_VR_GFX, + TEMP_VR_SOC, + TEMP_VR_MEM, + TEMP_COUNT +} TEMP_TYPE_e; + +typedef enum { + PPT_THROTTLER_PPT0, + PPT_THROTTLER_PPT1, + PPT_THROTTLER_PPT2, + PPT_THROTTLER_PPT3, + PPT_THROTTLER_COUNT +} PPT_THROTTLER_e; + +typedef enum { + VOLTAGE_MODE_AVFS = 0, + VOLTAGE_MODE_AVFS_SS, + VOLTAGE_MODE_SS, + VOLTAGE_MODE_COUNT, +} VOLTAGE_MODE_e; + +typedef enum { + AVFS_VOLTAGE_GFX = 0, + AVFS_VOLTAGE_SOC, + AVFS_VOLTAGE_COUNT, +} AVFS_VOLTAGE_TYPE_e; + +typedef enum { + GPIO_INT_POLARITY_ACTIVE_LOW = 0, + GPIO_INT_POLARITY_ACTIVE_HIGH, +} GpioIntPolarity_e; + +typedef enum { + MEMORY_TYPE_GDDR6 = 0, + MEMORY_TYPE_HBM, +} MemoryType_e; + +typedef enum { + PWR_CONFIG_TDP = 0, + PWR_CONFIG_TGP, + PWR_CONFIG_TCP_ESTIMATED, + PWR_CONFIG_TCP_MEASURED, +} PwrConfig_e; + +typedef enum { + XGMI_LINK_RATE_2 = 2, // 2Gbps + XGMI_LINK_RATE_4 = 4, // 4Gbps + XGMI_LINK_RATE_8 = 8, // 8Gbps + XGMI_LINK_RATE_12 = 12, // 12Gbps + XGMI_LINK_RATE_16 = 16, // 16Gbps + XGMI_LINK_RATE_17 = 17, // 17Gbps + XGMI_LINK_RATE_18 = 18, // 18Gbps + XGMI_LINK_RATE_19 = 19, // 19Gbps + XGMI_LINK_RATE_20 = 20, // 20Gbps + XGMI_LINK_RATE_21 = 21, // 21Gbps + XGMI_LINK_RATE_22 = 22, // 22Gbps + XGMI_LINK_RATE_23 = 23, // 23Gbps + XGMI_LINK_RATE_24 = 24, // 24Gbps + XGMI_LINK_RATE_25 = 25, // 25Gbps + XGMI_LINK_RATE_COUNT +} XGMI_LINK_RATE_e; + +typedef enum { + XGMI_LINK_WIDTH_1 = 1, // x1 + XGMI_LINK_WIDTH_2 = 2, // x2 + XGMI_LINK_WIDTH_4 = 4, // x4 + XGMI_LINK_WIDTH_8 = 8, // x8 + XGMI_LINK_WIDTH_9 = 9, // x9 + XGMI_LINK_WIDTH_16 = 16, // x16 + XGMI_LINK_WIDTH_COUNT +} XGMI_LINK_WIDTH_e; + +typedef struct { + uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only + uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM + uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used + uint8_t padding; + LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) + QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) + uint16_t SsFmin; // Fmin for SS curve. If SS curve is selected, will use V@SSFmin for F <= Fmin + uint16_t Padding16; +} DpmDescriptor_t; + +typedef struct { + uint32_t Version; + + // SECTION: Feature Enablement + uint32_t FeaturesToRun[2]; + + // SECTION: Infrastructure Limits + uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; + uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; + uint16_t TdcLimitSoc; // Amps + uint16_t TdcLimitSocTau; // Time constant of LPF in ms + uint16_t TdcLimitGfx; // Amps + uint16_t TdcLimitGfxTau; // Time constant of LPF in ms + + uint16_t TedgeLimit; // Celcius + uint16_t ThotspotLimit; // Celcius + uint16_t TmemLimit; // Celcius + uint16_t Tvr_gfxLimit; // Celcius + uint16_t Tvr_memLimit; // Celcius + uint16_t Tvr_socLimit; // Celcius + uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) + + uint16_t PpmPowerLimit; // Switch this this power limit when temperature is above PpmTempThreshold + uint16_t PpmTemperatureThreshold; + + // SECTION: Throttler settings + uint32_t ThrottlerControlMask; // See Throtter masks defines + + // SECTION: ULV Settings + uint16_t UlvVoltageOffsetGfx; // In mV(Q2) + uint16_t UlvPadding; // Padding + + uint8_t UlvGfxclkBypass; // 1 to turn off/bypass Gfxclk during ULV, 0 to leave Gfxclk on during ULV + uint8_t Padding234[3]; + + // SECTION: Voltage Control Parameters + uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX + uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC + uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX + uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC + + uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits + uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits + + //SECTION: DPM Config 1 + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz + + uint32_t Paddingclks[16]; + + // SECTION: DPM Config 2 + uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz + uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) + + // GFXCLK DPM + uint16_t GfxclkFidle; // In MHz + uint16_t GfxclkSlewRate; // for PLL babystepping??? + uint8_t Padding567[4]; + uint16_t GfxclkDsMaxFreq; // In MHz + uint8_t GfxclkSource; // 0 = PLL, 1 = AFLL + uint8_t Padding456; + + // GFXCLK Thermal DPM (formerly 'Boost' Settings) + uint16_t EnableTdpm; + uint16_t TdpmHighHystTemperature; + uint16_t TdpmLowHystTemperature; + uint16_t GfxclkFreqHighTempLimit; // High limit on GFXCLK when temperature is high, for reliability. + + // SECTION: Fan Control + uint16_t FanStopTemp; //Celcius + uint16_t FanStartTemp; //Celcius + + uint16_t FanGainEdge; + uint16_t FanGainHotspot; + uint16_t FanGainVrGfx; + uint16_t FanGainVrSoc; + uint16_t FanGainVrMem; + uint16_t FanGainHbm; + uint16_t FanPwmMin; + uint16_t FanAcousticLimitRpm; + uint16_t FanThrottlingRpm; + uint16_t FanMaximumRpm; + uint16_t FanTargetTemperature; + uint16_t FanTargetGfxclk; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + uint8_t FanTempInputSelect; + uint8_t padding8_Fan; + + // The following are AFC override parameters. Leave at 0 to use FW defaults. + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + + // SECTION: AVFS + // Overrides + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_Avfs[2]; + + QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve + DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb + DroopInt_t dBtcGbGfxAfll; // GHz->V BtcGb + DroopInt_t dBtcGbSoc; // GHz->V BtcGb + LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V + + QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V + + uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 + + uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_GfxBtc[2]; + + uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 + uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 + + uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; // mV Q2 + + // SECTION: XGMI + uint8_t XgmiDpmPstates[NUM_XGMI_LEVELS]; // 2 DPM states, high and low. 0-P0, 1-P1, 2-P2, 3-P3. + uint8_t XgmiDpmSpare[2]; + + // Temperature Dependent Vmin + uint16_t VDDGFX_TVmin; //Celcius + uint16_t VDDSOC_TVmin; //Celcius + uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 + uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 + uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 + uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 + + uint16_t VDDGFX_TVminHystersis; // Celcius + uint16_t VDDSOC_TVminHystersis; // Celcius + + + // SECTION: Advanced Options + uint32_t DebugOverrides; + QuadraticInt_t ReservedEquation0; + QuadraticInt_t ReservedEquation1; + QuadraticInt_t ReservedEquation2; + QuadraticInt_t ReservedEquation3; + + uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode + uint16_t PaddingUlv; // Padding + + // Total Power configuration, use defines from PwrConfig_e + uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured + uint8_t TotalPowerSpare1; + uint16_t TotalPowerSpare2; + + // APCC Settings + uint16_t PccThresholdLow; + uint16_t PccThresholdHigh; + uint32_t PaddingAPCC[6]; //FIXME pending SPEC + + // OOB Settings + uint16_t BasePerformanceCardPower; + uint16_t MaxPerformanceCardPower; + uint16_t BasePerformanceFrequencyCap; //In Mhz + uint16_t MaxPerformanceFrequencyCap; //In Mhz + + // Per-Part Vmin + uint16_t VDDGFX_VminLow; // mv Q2 + uint16_t VDDGFX_TVminLow; //Celcius + uint16_t VDDGFX_VminLow_HiTemp; // mv Q2 + uint16_t VDDGFX_VminLow_LoTemp; // mv Q2 + + // SECTION: Reserved + uint32_t Reserved[7]; + + // SECTION: BOARD PARAMETERS + + // SVI2 Board Parameters + uint16_t MaxVoltageStepGfx; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. + uint16_t MaxVoltageStepSoc; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. + + uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddMemVrMapping; // Use VR_MAPPING* bitfields + uint8_t BoardVrMapping; // Use VR_MAPPING* bitfields + + uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t ExternalSensorPresent; // External RDI connected to TMON (aka TEMP IN) + uint8_t Padding8_V[2]; + + // Telemetry Settings + uint16_t GfxMaxCurrent; // in Amps + int8_t GfxOffset; // in Amps + uint8_t Padding_TelemetryGfx; + + uint16_t SocMaxCurrent; // in Amps + int8_t SocOffset; // in Amps + uint8_t Padding_TelemetrySoc; + + uint16_t MemMaxCurrent; // in Amps + int8_t MemOffset; // in Amps + uint8_t Padding_TelemetryMem; + + uint16_t BoardMaxCurrent; // in Amps + int8_t BoardOffset; // in Amps + uint8_t Padding_TelemetryBoardInput; + + // GPIO Settings + uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event + uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event + uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event + uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event + + // GFXCLK PLL Spread Spectrum + uint8_t PllGfxclkSpreadEnabled; // on or off + uint8_t PllGfxclkSpreadPercent; // Q4.4 + uint16_t PllGfxclkSpreadFreq; // kHz + + // UCLK Spread Spectrum + uint8_t UclkSpreadEnabled; // on or off + uint8_t UclkSpreadPercent; // Q4.4 + uint16_t UclkSpreadFreq; // kHz + + // FCLK Spread Spectrum + uint8_t FclkSpreadEnabled; // on or off + uint8_t FclkSpreadPercent; // Q4.4 + uint16_t FclkSpreadFreq; // kHz + + // GFXCLK Fll Spread Spectrum + uint8_t FllGfxclkSpreadEnabled; // on or off + uint8_t FllGfxclkSpreadPercent; // Q4.4 + uint16_t FllGfxclkSpreadFreq; // kHz + + // I2C Controller Structure + I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; + + // Memory section + uint32_t MemoryChannelEnabled; // For DRAM use only, Max 32 channels enabled bit mask. + + uint8_t DramBitWidth; // For DRAM use only. See Dram Bit width type defines + uint8_t PaddingMem[3]; + + // Total board power + uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power + uint16_t BoardPadding; + + // SECTION: XGMI Training + uint8_t XgmiLinkSpeed [NUM_XGMI_PSTATE_LEVELS]; + uint8_t XgmiLinkWidth [NUM_XGMI_PSTATE_LEVELS]; + + uint16_t XgmiFclkFreq [NUM_XGMI_PSTATE_LEVELS]; + uint16_t XgmiSocVoltage [NUM_XGMI_PSTATE_LEVELS]; + + // GPIO pins for I2C communications with 2nd controller for Input Telemetry Sequence + uint8_t GpioI2cScl; // Serial Clock + uint8_t GpioI2cSda; // Serial Data + uint16_t GpioPadding; + + // Platform input telemetry voltage coefficient + uint32_t BoardVoltageCoeffA; // decode by /1000 + uint32_t BoardVoltageCoeffB; // decode by /1000 + + uint32_t BoardReserved[7]; + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; // SMU internal use + +} PPTable_t; + +typedef struct { + // Time constant parameters for clock averages in ms + uint16_t GfxclkAverageLpfTau; + uint16_t SocclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + + uint16_t SocketPowerLpfTau; + + uint16_t VcnClkAverageLpfTau; + uint16_t padding16; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} DriverSmuConfig_t; + +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureHBM ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureVrMem ; + uint32_t ThrottlerStatus ; + + uint16_t CurrFanSpeed ; + uint16_t AverageVclkFrequency ; + uint16_t AverageDclkFrequency ; + uint16_t VcnActivityPercentage ; + uint32_t EnergyAccumulator ; + + uint32_t Padding[2]; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetrics_t; + + +typedef struct { + uint16_t avgPsmCount[75]; + uint16_t minPsmCount[75]; + float avgPsmVoltage[75]; + float minPsmVoltage[75]; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsDebugTable_t; + +typedef struct { + uint8_t AvfsVersion; + uint8_t Padding; + uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; + + int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; + + uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits + + + int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units + + uint32_t EnabledAvfsModules[3]; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsFuseOverride_t; + +typedef struct { + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint8_t Gfx_UseRlcBusy; + uint8_t PaddingGfx[3]; + uint16_t Gfx_MinActiveFreq; // MHz + uint16_t Gfx_BoosterFreq; // MHz + uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Gfx_PD_Data_limit_a; // Q16 + uint32_t Gfx_PD_Data_limit_b; // Q16 + uint32_t Gfx_PD_Data_limit_c; // Q16 + uint32_t Gfx_PD_Data_error_coeff; // Q16 + uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 + + uint8_t Mem_ActiveHystLimit; + uint8_t Mem_IdleHystLimit; + uint8_t Mem_FPS; + uint8_t Mem_MinActiveFreqType; + uint8_t Mem_BoosterFreqType; + uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint8_t Mem_UseRlcBusy; + uint8_t PaddingMem[3]; + uint16_t Mem_MinActiveFreq; // MHz + uint16_t Mem_BoosterFreq; // MHz + uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Mem_PD_Data_limit_a; // Q16 + uint32_t Mem_PD_Data_limit_b; // Q16 + uint32_t Mem_PD_Data_limit_c; // Q16 + uint32_t Mem_PD_Data_error_coeff; // Q16 + uint32_t Mem_PD_Data_error_rate_coeff; // Q16 + + uint32_t Mem_UpThreshold_Limit; // Q16 + uint8_t Mem_UpHystLimit; + uint8_t Mem_DownHystLimit; + uint16_t Mem_Fps; + + uint32_t BusyThreshold; // Q16 + uint32_t BusyHyst; + uint32_t IdleHyst; + + uint32_t MmHubPadding[8]; // SMU internal use +} DpmActivityMonitorCoeffInt_t; + +// These defines are used with the following messages: +// SMC_MSG_TransferTableDram2Smu +// SMC_MSG_TransferTableSmu2Dram +#define TABLE_PPTABLE 0 +#define TABLE_AVFS 1 +#define TABLE_AVFS_PSM_DEBUG 2 +#define TABLE_AVFS_FUSE_OVERRIDE 3 +#define TABLE_PMSTATUSLOG 4 +#define TABLE_SMU_METRICS 5 +#define TABLE_DRIVER_SMU_CONFIG 6 +#define TABLE_OVERDRIVE 7 +#define TABLE_WAFL_XGMI_TOPOLOGY 8 +#define TABLE_I2C_COMMANDS 9 +#define TABLE_ACTIVITY_MONITOR_COEFF 10 +#define TABLE_COUNT 11 + +// These defines are used with the SMC_MSG_SetUclkFastSwitch message. +typedef enum { + DF_SWITCH_TYPE_FAST = 0, + DF_SWITCH_TYPE_SLOW, + DF_SWITCH_TYPE_COUNT, +} DF_SWITCH_TYPE_e; + +typedef enum { + DRAM_BIT_WIDTH_DISABLED = 0, + DRAM_BIT_WIDTH_X_8, + DRAM_BIT_WIDTH_X_16, + DRAM_BIT_WIDTH_X_32, + DRAM_BIT_WIDTH_X_64, // NOT USED. + DRAM_BIT_WIDTH_X_128, + DRAM_BIT_WIDTH_COUNT, +} DRAM_BIT_WIDTH_TYPE_e; + +#define REMOVE_FMAX_MARGIN_BIT 0x0 +#define REMOVE_DCTOL_MARGIN_BIT 0x1 +#define REMOVE_PLATFORM_MARGIN_BIT 0x2 + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h new file mode 100644 index 000000000000..246d3951a78a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_navi10.h @@ -0,0 +1,1126 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SMU11_DRIVER_IF_NAVI10_H__ +#define __SMU11_DRIVER_IF_NAVI10_H__ + +// *** IMPORTANT *** +// SMU TEAM: Always increment the interface version if +// any structure is changed in this file +// Be aware of that the version should be updated in +// smu_v11_0.h, maybe rename is also needed. +// #define SMU11_DRIVER_IF_VERSION 0x33 + +#define PPTABLE_NV10_SMU_VERSION 8 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_SMNCLK_DPM_LEVELS 2 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DCEFCLK_DPM_LEVELS 8 +#define NUM_PHYCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_PIXCLK_DPM_LEVELS 8 +#define NUM_UCLK_DPM_LEVELS 4 +#define NUM_MP1CLK_DPM_LEVELS 2 +#define NUM_LINK_LEVELS 2 + + +#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) +#define MAX_SMNCLK_DPM_LEVEL (NUM_SMNCLK_DPM_LEVELS - 1) +#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) +#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) +#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) +#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) +#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) +#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) +#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) +#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) +#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) +#define MAX_MP1CLK_DPM_LEVEL (NUM_MP1CLK_DPM_LEVELS - 1) +#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) + +//Gemini Modes +#define PPSMC_GeminiModeNone 0 //Single GPU board +#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board +#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board + +// Feature Control Defines +// DPM +#define FEATURE_DPM_PREFETCHER_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_GFX_PACE_BIT 2 +#define FEATURE_DPM_UCLK_BIT 3 +#define FEATURE_DPM_SOCCLK_BIT 4 +#define FEATURE_DPM_MP0CLK_BIT 5 +#define FEATURE_DPM_LINK_BIT 6 +#define FEATURE_DPM_DCEFCLK_BIT 7 +#define FEATURE_MEM_VDDCI_SCALING_BIT 8 +#define FEATURE_MEM_MVDD_SCALING_BIT 9 + +//Idle +#define FEATURE_DS_GFXCLK_BIT 10 +#define FEATURE_DS_SOCCLK_BIT 11 +#define FEATURE_DS_LCLK_BIT 12 +#define FEATURE_DS_DCEFCLK_BIT 13 +#define FEATURE_DS_UCLK_BIT 14 +#define FEATURE_GFX_ULV_BIT 15 +#define FEATURE_FW_DSTATE_BIT 16 +#define FEATURE_GFXOFF_BIT 17 +#define FEATURE_BACO_BIT 18 +#define FEATURE_VCN_PG_BIT 19 +#define FEATURE_JPEG_PG_BIT 20 +#define FEATURE_USB_PG_BIT 21 +#define FEATURE_RSMU_SMN_CG_BIT 22 +//Throttler/Response +#define FEATURE_PPT_BIT 23 +#define FEATURE_TDC_BIT 24 +#define FEATURE_GFX_EDC_BIT 25 +#define FEATURE_APCC_PLUS_BIT 26 +#define FEATURE_GTHR_BIT 27 +#define FEATURE_ACDC_BIT 28 +#define FEATURE_VR0HOT_BIT 29 +#define FEATURE_VR1HOT_BIT 30 +#define FEATURE_FW_CTF_BIT 31 +#define FEATURE_FAN_CONTROL_BIT 32 +#define FEATURE_THERMAL_BIT 33 +#define FEATURE_GFX_DCS_BIT 34 +//VF +#define FEATURE_RM_BIT 35 +#define FEATURE_LED_DISPLAY_BIT 36 +//Other +#define FEATURE_GFX_SS_BIT 37 +#define FEATURE_OUT_OF_BAND_MONITOR_BIT 38 +#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 39 + +#define FEATURE_MMHUB_PG_BIT 40 +#define FEATURE_ATHUB_PG_BIT 41 +#define FEATURE_APCC_DFLL_BIT 42 +#define FEATURE_SPARE_43_BIT 43 +#define FEATURE_SPARE_44_BIT 44 +#define FEATURE_SPARE_45_BIT 45 +#define FEATURE_SPARE_46_BIT 46 +#define FEATURE_SPARE_47_BIT 47 +#define FEATURE_SPARE_48_BIT 48 +#define FEATURE_SPARE_49_BIT 49 +#define FEATURE_SPARE_50_BIT 50 +#define FEATURE_SPARE_51_BIT 51 +#define FEATURE_SPARE_52_BIT 52 +#define FEATURE_SPARE_53_BIT 53 +#define FEATURE_SPARE_54_BIT 54 +#define FEATURE_SPARE_55_BIT 55 +#define FEATURE_SPARE_56_BIT 56 +#define FEATURE_SPARE_57_BIT 57 +#define FEATURE_SPARE_58_BIT 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 +#define NUM_FEATURES 64 + +// Debug Overrides Bitmask +#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 +#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_SOCCLK 0x00000004 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000008 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000010 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00000020 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00000040 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_DCE_SOCCLK 0x00000080 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_MP0_SOCCLK 0x00000100 +#define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 +#define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 + +// VR Mapping Bit Defines +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + +// PSI Bit Defines +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + +// Throttler Control/Status Bits +#define THROTTLER_PADDING_BIT 0 +#define THROTTLER_TEMP_EDGE_BIT 1 +#define THROTTLER_TEMP_HOTSPOT_BIT 2 +#define THROTTLER_TEMP_MEM_BIT 3 +#define THROTTLER_TEMP_VR_GFX_BIT 4 +#define THROTTLER_TEMP_VR_MEM0_BIT 5 +#define THROTTLER_TEMP_VR_MEM1_BIT 6 +#define THROTTLER_TEMP_VR_SOC_BIT 7 +#define THROTTLER_TEMP_LIQUID0_BIT 8 +#define THROTTLER_TEMP_LIQUID1_BIT 9 +#define THROTTLER_TEMP_PLX_BIT 10 +#define THROTTLER_TEMP_SKIN_BIT 11 +#define THROTTLER_TDC_GFX_BIT 12 +#define THROTTLER_TDC_SOC_BIT 13 +#define THROTTLER_PPT0_BIT 14 +#define THROTTLER_PPT1_BIT 15 +#define THROTTLER_PPT2_BIT 16 +#define THROTTLER_PPT3_BIT 17 +#define THROTTLER_FIT_BIT 18 +#define THROTTLER_PPM_BIT 19 +#define THROTTLER_APCC_BIT 20 + +// FW DState Features Control Bits +#define FW_DSTATE_SOC_ULV_BIT 0 +#define FW_DSTATE_G6_HSR_BIT 1 +#define FW_DSTATE_G6_PHY_VDDCI_OFF_BIT 2 +#define FW_DSTATE_MP0_DS_BIT 3 +#define FW_DSTATE_SMN_DS_BIT 4 +#define FW_DSTATE_MP1_DS_BIT 5 +#define FW_DSTATE_MP1_WHISPER_MODE_BIT 6 +#define FW_DSTATE_LIV_MIN_BIT 7 +#define FW_DSTATE_SOC_PLL_PWRDN_BIT 8 + +#define FW_DSTATE_SOC_ULV_MASK (1 << FW_DSTATE_SOC_ULV_BIT ) +#define FW_DSTATE_G6_HSR_MASK (1 << FW_DSTATE_G6_HSR_BIT ) +#define FW_DSTATE_G6_PHY_VDDCI_OFF_MASK (1 << FW_DSTATE_G6_PHY_VDDCI_OFF_BIT ) +#define FW_DSTATE_MP1_DS_MASK (1 << FW_DSTATE_MP1_DS_BIT ) +#define FW_DSTATE_MP0_DS_MASK (1 << FW_DSTATE_MP0_DS_BIT ) +#define FW_DSTATE_SMN_DS_MASK (1 << FW_DSTATE_SMN_DS_BIT ) +#define FW_DSTATE_MP1_WHISPER_MODE_MASK (1 << FW_DSTATE_MP1_WHISPER_MODE_BIT ) +#define FW_DSTATE_LIV_MIN_MASK (1 << FW_DSTATE_LIV_MIN_BIT ) +#define FW_DSTATE_SOC_PLL_PWRDN_MASK (1 << FW_DSTATE_SOC_PLL_PWRDN_BIT ) + +//I2C Interface + +#define NUM_I2C_CONTROLLERS 8 + +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +#define MAX_SW_I2C_COMMANDS 8 + +typedef enum { + I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 + I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 + I2C_CONTROLLER_PORT_COUNT, +} I2cControllerPort_e; + +typedef enum { + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VDDCI, + I2C_CONTROLLER_NAME_VR_MVDD, + I2C_CONTROLLER_NAME_LIQUID0, + I2C_CONTROLLER_NAME_LIQUID1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_SPARE, + I2C_CONTROLLER_NAME_COUNT, +} I2cControllerName_e; + +typedef enum { + I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, + I2C_CONTROLLER_THROTTLER_VR_GFX, + I2C_CONTROLLER_THROTTLER_VR_SOC, + I2C_CONTROLLER_THROTTLER_VR_VDDCI, + I2C_CONTROLLER_THROTTLER_VR_MVDD, + I2C_CONTROLLER_THROTTLER_LIQUID0, + I2C_CONTROLLER_THROTTLER_LIQUID1, + I2C_CONTROLLER_THROTTLER_PLX, + I2C_CONTROLLER_THROTTLER_COUNT, +} I2cControllerThrottler_e; + +typedef enum { + I2C_CONTROLLER_PROTOCOL_VR_0, + I2C_CONTROLLER_PROTOCOL_VR_1, + I2C_CONTROLLER_PROTOCOL_TMP_0, + I2C_CONTROLLER_PROTOCOL_TMP_1, + I2C_CONTROLLER_PROTOCOL_SPARE_0, + I2C_CONTROLLER_PROTOCOL_SPARE_1, + I2C_CONTROLLER_PROTOCOL_COUNT, +} I2cControllerProtocol_e; + +typedef struct { + uint8_t Enabled; + uint8_t Speed; + uint8_t Padding[2]; + uint32_t SlaveAddress; + uint8_t ControllerPort; + uint8_t ControllerName; + uint8_t ThermalThrotter; + uint8_t I2cProtocol; +} I2cControllerConfig_t; + +typedef enum { + I2C_PORT_SVD_SCL = 0, + I2C_PORT_GPIO, +} I2cPort_e; + +typedef enum { + I2C_SPEED_FAST_50K = 0, //50 Kbits/s + I2C_SPEED_FAST_100K, //100 Kbits/s + I2C_SPEED_FAST_400K, //400 Kbits/s + I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) + I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) + I2C_SPEED_HIGH_2M, //2.3 Mbits/s + I2C_SPEED_COUNT, +} I2cSpeed_e; + +typedef enum { + I2C_CMD_READ = 0, + I2C_CMD_WRITE, + I2C_CMD_COUNT, +} I2cCmdType_e; + +#define CMDCONFIG_STOP_BIT 0 +#define CMDCONFIG_RESTART_BIT 1 + +#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) +#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) + +typedef struct { + uint8_t RegisterAddr; ////only valid for write, ignored for read + uint8_t Cmd; //Read(0) or Write(1) + uint8_t Data; //Return data for read. Data to send for write + uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command +} SwI2cCmd_t; //SW I2C Command Table + +typedef struct { + uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) + uint8_t I2CSpeed; //Slow(0) or Fast(1) + uint16_t SlaveAddress; + uint8_t NumCmds; //Number of commands + uint8_t Padding[3]; + + SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; + + uint32_t MmHubPadding[8]; // SMU internal use + +} SwI2cRequest_t; // SW I2C Request Table + +//D3HOT sequences +typedef enum { + BACO_SEQUENCE, + MSR_SEQUENCE, + BAMACO_SEQUENCE, + ULPS_SEQUENCE, + D3HOT_SEQUENCE_COUNT, +}D3HOTSequence_e; + +//THis is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_DYNAMIC_MODE = 0, + PG_STATIC_MODE, +} PowerGatingMode_e; + +//This is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_POWER_DOWN = 0, + PG_POWER_UP, +} PowerGatingSettings_e; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} QuadraticInt_t; + +typedef struct { + uint32_t m; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable +} LinearInt_t; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} DroopInt_t; + +typedef enum { + GFXCLK_SOURCE_PLL = 0, + GFXCLK_SOURCE_DFLL, + GFXCLK_SOURCE_COUNT, +} GfxclkSrc_e; + +//Only Clks that have DPM descriptors are listed here +typedef enum { + PPCLK_GFXCLK = 0, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_DCLK, + PPCLK_VCLK, + PPCLK_DCEFCLK, + PPCLK_DISPCLK, + PPCLK_PIXCLK, + PPCLK_PHYCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef enum { + POWER_SOURCE_AC, + POWER_SOURCE_DC, + POWER_SOURCE_COUNT, +} POWER_SOURCE_e; + +typedef enum { + PPT_THROTTLER_PPT0, + PPT_THROTTLER_PPT1, + PPT_THROTTLER_PPT2, + PPT_THROTTLER_PPT3, + PPT_THROTTLER_COUNT +} PPT_THROTTLER_e; + +typedef enum { + VOLTAGE_MODE_AVFS = 0, + VOLTAGE_MODE_AVFS_SS, + VOLTAGE_MODE_SS, + VOLTAGE_MODE_COUNT, +} VOLTAGE_MODE_e; + + +typedef enum { + AVFS_VOLTAGE_GFX = 0, + AVFS_VOLTAGE_SOC, + AVFS_VOLTAGE_COUNT, +} AVFS_VOLTAGE_TYPE_e; + +typedef enum { + UCLK_DIV_BY_1 = 0, + UCLK_DIV_BY_2, + UCLK_DIV_BY_4, + UCLK_DIV_BY_8, +} UCLK_DIV_e; + +typedef enum { + GPIO_INT_POLARITY_ACTIVE_LOW = 0, + GPIO_INT_POLARITY_ACTIVE_HIGH, +} GpioIntPolarity_e; + +typedef enum { + MEMORY_TYPE_GDDR6 = 0, + MEMORY_TYPE_HBM, +} MemoryType_e; + +typedef enum { + PWR_CONFIG_TDP = 0, + PWR_CONFIG_TGP, + PWR_CONFIG_TCP_ESTIMATED, + PWR_CONFIG_TCP_MEASURED, +} PwrConfig_e; + +typedef struct { + uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only + uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM + uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used + uint8_t Padding; + LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) + QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) +} DpmDescriptor_t; + +typedef enum { + TEMP_EDGE, + TEMP_HOTSPOT, + TEMP_MEM, + TEMP_VR_GFX, + TEMP_VR_MEM0, + TEMP_VR_MEM1, + TEMP_VR_SOC, + TEMP_LIQUID0, + TEMP_LIQUID1, + TEMP_PLX, + TEMP_COUNT +} TEMP_e; + +//Out of band monitor status defines +//see SPEC //gpu/doc/soc_arch/spec/feature/SMBUS/SMBUS.xlsx +#define POWER_MANAGER_CONTROLLER_NOT_RUNNING 0 +#define POWER_MANAGER_CONTROLLER_RUNNING 1 + +#define POWER_MANAGER_CONTROLLER_BIT 0 +#define MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_BIT 8 +#define GPU_DIE_TEMPERATURE_THROTTLING_BIT 9 +#define HBM_DIE_TEMPERATURE_THROTTLING_BIT 10 +#define TGP_THROTTLING_BIT 11 +#define PCC_THROTTLING_BIT 12 +#define HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_BIT 13 +#define HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_BIT 14 + +#define POWER_MANAGER_CONTROLLER_MASK (1 << POWER_MANAGER_CONTROLLER_BIT ) +#define MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_MASK (1 << MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_BIT ) +#define GPU_DIE_TEMPERATURE_THROTTLING_MASK (1 << GPU_DIE_TEMPERATURE_THROTTLING_BIT ) +#define HBM_DIE_TEMPERATURE_THROTTLING_MASK (1 << HBM_DIE_TEMPERATURE_THROTTLING_BIT ) +#define TGP_THROTTLING_MASK (1 << TGP_THROTTLING_BIT ) +#define PCC_THROTTLING_MASK (1 << PCC_THROTTLING_BIT ) +#define HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_MASK (1 << HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_BIT ) +#define HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_MASK (1 << HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_BIT) + +//This structure to be DMA to SMBUS Config register space +typedef struct { + uint8_t MinorInfoVersion; + uint8_t MajorInfoVersion; + uint8_t TableSize; + uint8_t Reserved; + + uint8_t Reserved1; + uint8_t RevID; + uint16_t DeviceID; + + uint16_t DieTemperatureLimit; + uint16_t FanTargetTemperature; + + uint16_t MemoryTemperatureLimit; + uint16_t MemoryTemperatureLimit1; + + uint16_t TGP; + uint16_t CardPower; + + uint32_t DieTemperatureRegisterOffset; + + uint32_t Reserved2; + + uint32_t Reserved3; + + uint32_t Status; + + uint16_t DieTemperature; + uint16_t CurrentMemoryTemperature; + + uint16_t MemoryTemperature; + uint8_t MemoryHotspotPosition; + uint8_t Reserved4; + + uint32_t BoardLevelEnergyAccumulator; +} OutOfBandMonitor_t; + +typedef struct { + uint32_t Version; + + // SECTION: Feature Enablement + uint32_t FeaturesToRun[2]; + + // SECTION: Infrastructure Limits + uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; + uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; + uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; + uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; + + uint16_t TdcLimitSoc; // Amps + uint16_t TdcLimitSocTau; // Time constant of LPF in ms + uint16_t TdcLimitGfx; // Amps + uint16_t TdcLimitGfxTau; // Time constant of LPF in ms + + uint16_t TedgeLimit; // Celcius + uint16_t ThotspotLimit; // Celcius + uint16_t TmemLimit; // Celcius + uint16_t Tvr_gfxLimit; // Celcius + uint16_t Tvr_mem0Limit; // Celcius + uint16_t Tvr_mem1Limit; // Celcius + uint16_t Tvr_socLimit; // Celcius + uint16_t Tliquid0Limit; // Celcius + uint16_t Tliquid1Limit; // Celcius + uint16_t TplxLimit; // Celcius + uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) + + uint16_t PpmPowerLimit; // Switch this this power limit when temperature is above PpmTempThreshold + uint16_t PpmTemperatureThreshold; + + // SECTION: Throttler settings + uint32_t ThrottlerControlMask; // See Throtter masks defines + + // SECTION: FW DSTATE Settings + uint32_t FwDStateMask; // See FW DState masks defines + + // SECTION: ULV Settings + uint16_t UlvVoltageOffsetSoc; // In mV(Q2) + uint16_t UlvVoltageOffsetGfx; // In mV(Q2) + + uint8_t GceaLinkMgrIdleThreshold; //Set by SMU FW during enablment of SOC_ULV. Controls delay for GFX SDP port disconnection during idle events + uint8_t paddingRlcUlvParams[3]; + + uint8_t UlvSmnclkDid; //DID for ULV mode. 0 means CLK will not be modified in ULV. + uint8_t UlvMp1clkDid; //DID for ULV mode. 0 means CLK will not be modified in ULV. + uint8_t UlvGfxclkBypass; // 1 to turn off/bypass Gfxclk during ULV, 0 to leave Gfxclk on during ULV + uint8_t Padding234; + + uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode + uint16_t MinVoltageUlvSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC in ULV mode + + + // SECTION: Voltage Control Parameters + uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX + uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC + uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX + uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC + + uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits + uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits + + //SECTION: DPM Config 1 + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; // In MHz + uint32_t Paddingclks[16]; + + uint16_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz + uint16_t Padding8_Clks; + + uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 + + // SECTION: DPM Config 2 + uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz + uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) + uint16_t MemVddciVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + uint16_t MemMvddVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + // GFXCLK DPM + uint16_t GfxclkFgfxoffEntry; // in Mhz + uint16_t GfxclkFinit; // in Mhz + uint16_t GfxclkFidle; // in MHz + uint16_t GfxclkSlewRate; // for PLL babystepping??? + uint16_t GfxclkFopt; // in Mhz + uint8_t Padding567[2]; + uint16_t GfxclkDsMaxFreq; // in MHz + uint8_t GfxclkSource; // 0 = PLL, 1 = DFLL + uint8_t Padding456; + + // UCLK section + uint8_t LowestUclkReservedForUlv; // Set this to 1 if UCLK DPM0 is reserved for ULV-mode only + uint8_t paddingUclk[3]; + + uint8_t MemoryType; // 0-GDDR6, 1-HBM + uint8_t MemoryChannels; + uint8_t PaddingMem[2]; + + // Link DPM Settings + uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 + uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 + uint16_t LclkFreq[NUM_LINK_LEVELS]; + + // GFXCLK Thermal DPM (formerly 'Boost' Settings) + uint16_t EnableTdpm; + uint16_t TdpmHighHystTemperature; + uint16_t TdpmLowHystTemperature; + uint16_t GfxclkFreqHighTempLimit; // High limit on GFXCLK when temperature is high, for reliability. + + // SECTION: Fan Control + uint16_t FanStopTemp; //Celcius + uint16_t FanStartTemp; //Celcius + + uint16_t FanGainEdge; + uint16_t FanGainHotspot; + uint16_t FanGainLiquid0; + uint16_t FanGainLiquid1; + uint16_t FanGainVrGfx; + uint16_t FanGainVrSoc; + uint16_t FanGainVrMem0; + uint16_t FanGainVrMem1; + uint16_t FanGainPlx; + uint16_t FanGainMem; + uint16_t FanPwmMin; + uint16_t FanAcousticLimitRpm; + uint16_t FanThrottlingRpm; + uint16_t FanMaximumRpm; + uint16_t FanTargetTemperature; + uint16_t FanTargetGfxclk; + uint8_t FanTempInputSelect; + uint8_t FanPadding; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + //uint8_t padding8_Fan[2]; + + // The following are AFC override parameters. Leave at 0 to use FW defaults. + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + + // SECTION: AVFS + // Overrides + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_Avfs[2]; + + QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve + DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb + DroopInt_t dBtcGbGfxDfll; // GHz->V BtcGb + DroopInt_t dBtcGbSoc; // GHz->V BtcGb + LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V + + QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V + + uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 + + uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_GfxBtc[2]; + + uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 + uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 + + // SECTION: Advanced Options + uint32_t DebugOverrides; + QuadraticInt_t ReservedEquation0; + QuadraticInt_t ReservedEquation1; + QuadraticInt_t ReservedEquation2; + QuadraticInt_t ReservedEquation3; + + // Total Power configuration, use defines from PwrConfig_e + uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured + uint8_t TotalPowerSpare1; + uint16_t TotalPowerSpare2; + + // APCC Settings + uint16_t PccThresholdLow; + uint16_t PccThresholdHigh; + uint32_t MGpuFanBoostLimitRpm; + uint32_t PaddingAPCC[5]; + + // Temperature Dependent Vmin + uint16_t VDDGFX_TVmin; //Celcius + uint16_t VDDSOC_TVmin; //Celcius + uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 + uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 + uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 + uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 + + uint16_t VDDGFX_TVminHystersis; // Celcius + uint16_t VDDSOC_TVminHystersis; // Celcius + + // BTC Setting + uint32_t BtcConfig; + + uint16_t SsFmin[10]; // PPtable value to function similar to VFTFmin for SS Curve; Size is PPCLK_COUNT rounded to nearest multiple of 2 + uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; + + // SECTION: Board Reserved + uint32_t Reserved[8]; + + // SECTION: BOARD PARAMETERS + // I2C Control + I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; + + // SVI2 Board Parameters + uint16_t MaxVoltageStepGfx; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. + uint16_t MaxVoltageStepSoc; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. + + uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields + uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields + + uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t ExternalSensorPresent; // External RDI connected to TMON (aka TEMP IN) + uint8_t Padding8_V; + + // Telemetry Settings + uint16_t GfxMaxCurrent; // in Amps + int8_t GfxOffset; // in Amps + uint8_t Padding_TelemetryGfx; + + uint16_t SocMaxCurrent; // in Amps + int8_t SocOffset; // in Amps + uint8_t Padding_TelemetrySoc; + + uint16_t Mem0MaxCurrent; // in Amps + int8_t Mem0Offset; // in Amps + uint8_t Padding_TelemetryMem0; + + uint16_t Mem1MaxCurrent; // in Amps + int8_t Mem1Offset; // in Amps + uint8_t Padding_TelemetryMem1; + + // GPIO Settings + uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching + uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching + uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event + uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event + + uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event + uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event + uint8_t GthrGpio; // GPIO pin configured for GTHR Event + uint8_t GthrPolarity; // replace GPIO polarity for GTHR + + // LED Display Settings + uint8_t LedPin0; // GPIO number for LedPin[0] + uint8_t LedPin1; // GPIO number for LedPin[1] + uint8_t LedPin2; // GPIO number for LedPin[2] + uint8_t padding8_4; + + // GFXCLK PLL Spread Spectrum + uint8_t PllGfxclkSpreadEnabled; // on or off + uint8_t PllGfxclkSpreadPercent; // Q4.4 + uint16_t PllGfxclkSpreadFreq; // kHz + + // GFXCLK DFLL Spread Spectrum + uint8_t DfllGfxclkSpreadEnabled; // on or off + uint8_t DfllGfxclkSpreadPercent; // Q4.4 + uint16_t DfllGfxclkSpreadFreq; // kHz + + // UCLK Spread Spectrum + uint8_t UclkSpreadEnabled; // on or off + uint8_t UclkSpreadPercent; // Q4.4 + uint16_t UclkSpreadFreq; // kHz + + // SOCCLK Spread Spectrum + uint8_t SoclkSpreadEnabled; // on or off + uint8_t SocclkSpreadPercent; // Q4.4 + uint16_t SocclkSpreadFreq; // kHz + + // Total board power + uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power + uint16_t BoardPadding; + + // Mvdd Svi2 Div Ratio Setting + uint32_t MvddRatio; // This is used for MVDD Vid workaround. It has 16 fractional bits (Q16.16) + + uint8_t RenesesLoadLineEnabled; + uint8_t GfxLoadlineResistance; + uint8_t SocLoadlineResistance; + uint8_t Padding8_Loadline; + + uint32_t BoardReserved[8]; + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; // SMU internal use + +} PPTable_t; + +typedef struct { + // Time constant parameters for clock averages in ms + uint16_t GfxclkAverageLpfTau; + uint16_t SocclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + uint16_t SocketPowerLpfTau; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} DriverSmuConfig_t; + +typedef struct { + + uint16_t GfxclkFmin; // MHz + uint16_t GfxclkFmax; // MHz + uint16_t GfxclkFreq1; // MHz + uint16_t GfxclkVolt1; // mV (Q2) + uint16_t GfxclkFreq2; // MHz + uint16_t GfxclkVolt2; // mV (Q2) + uint16_t GfxclkFreq3; // MHz + uint16_t GfxclkVolt3; // mV (Q2) + uint16_t UclkFmax; // MHz + int16_t OverDrivePct; // % + uint16_t FanMaximumRpm; + uint16_t FanMinimumPwm; + uint16_t FanTargetTemperature; // Degree Celcius + uint16_t MaxOpTemp; // Degree Celcius + uint16_t FanZeroRpmEnable; + uint16_t Padding; + + uint32_t MmHubPadding[8]; // SMU internal use + +} OverDriveTable_t; + +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureMem ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureLiquid0 ; + uint16_t TemperatureLiquid1 ; + uint16_t TemperaturePlx ; + uint16_t Padding16 ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t Padding8_2; + uint16_t CurrFanSpeed; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetrics_t; + +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureMem ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureLiquid0 ; + uint16_t TemperatureLiquid1 ; + uint16_t TemperaturePlx ; + uint16_t Padding16 ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t Padding8_2; + uint16_t CurrFanSpeed; + + uint32_t EnergyAccumulator; + uint16_t AverageVclkFrequency ; + uint16_t AverageDclkFrequency ; + uint16_t VcnActivityPercentage ; + uint16_t padding16_2; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetrics_NV12_t; + +typedef struct { + uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Padding[3]; + + uint32_t MmHubPadding[8]; // SMU internal use +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCEFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef struct { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; + + uint32_t MmHubPadding[8]; // SMU internal use +} Watermarks_t; + +typedef struct { + uint16_t avgPsmCount[28]; + uint16_t minPsmCount[28]; + float avgPsmVoltage[28]; + float minPsmVoltage[28]; + + uint32_t MmHubPadding[32]; // SMU internal use +} AvfsDebugTable_t_NV14; + +typedef struct { + uint16_t avgPsmCount[36]; + uint16_t minPsmCount[36]; + float avgPsmVoltage[36]; + float minPsmVoltage[36]; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsDebugTable_t_NV10; + +typedef struct { + uint8_t AvfsVersion; + uint8_t Padding; + + uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; + + int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; + + uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits + + + int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units + + uint32_t EnabledAvfsModules[2]; //NV10 - 36 AVFS modules + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsFuseOverride_t; + +typedef struct { + + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Gfx_MinActiveFreq; // MHz + uint16_t Gfx_BoosterFreq; // MHz + uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Gfx_PD_Data_limit_a; // Q16 + uint32_t Gfx_PD_Data_limit_b; // Q16 + uint32_t Gfx_PD_Data_limit_c; // Q16 + uint32_t Gfx_PD_Data_error_coeff; // Q16 + uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 + + uint8_t Soc_ActiveHystLimit; + uint8_t Soc_IdleHystLimit; + uint8_t Soc_FPS; + uint8_t Soc_MinActiveFreqType; + uint8_t Soc_BoosterFreqType; + uint8_t Soc_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Soc_MinActiveFreq; // MHz + uint16_t Soc_BoosterFreq; // MHz + uint16_t Soc_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Soc_PD_Data_limit_a; // Q16 + uint32_t Soc_PD_Data_limit_b; // Q16 + uint32_t Soc_PD_Data_limit_c; // Q16 + uint32_t Soc_PD_Data_error_coeff; // Q16 + uint32_t Soc_PD_Data_error_rate_coeff; // Q16 + + uint8_t Mem_ActiveHystLimit; + uint8_t Mem_IdleHystLimit; + uint8_t Mem_FPS; + uint8_t Mem_MinActiveFreqType; + uint8_t Mem_BoosterFreqType; + uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Mem_MinActiveFreq; // MHz + uint16_t Mem_BoosterFreq; // MHz + uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Mem_PD_Data_limit_a; // Q16 + uint32_t Mem_PD_Data_limit_b; // Q16 + uint32_t Mem_PD_Data_limit_c; // Q16 + uint32_t Mem_PD_Data_error_coeff; // Q16 + uint32_t Mem_PD_Data_error_rate_coeff; // Q16 + + uint32_t Mem_UpThreshold_Limit; // Q16 + uint8_t Mem_UpHystLimit; + uint8_t Mem_DownHystLimit; + uint16_t Mem_Fps; + + uint32_t MmHubPadding[8]; // SMU internal use + +} DpmActivityMonitorCoeffInt_t; + + +// Workload bits +#define WORKLOAD_PPLIB_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_COUNT 7 + + +// These defines are used with the following messages: +// SMC_MSG_TransferTableDram2Smu +// SMC_MSG_TransferTableSmu2Dram + +// Table transfer status +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF + +// Table types +#define TABLE_PPTABLE 0 +#define TABLE_WATERMARKS 1 +#define TABLE_AVFS 2 +#define TABLE_AVFS_PSM_DEBUG 3 +#define TABLE_AVFS_FUSE_OVERRIDE 4 +#define TABLE_PMSTATUSLOG 5 +#define TABLE_SMU_METRICS 6 +#define TABLE_DRIVER_SMU_CONFIG 7 +#define TABLE_ACTIVITY_MONITOR_COEFF 8 +#define TABLE_OVERDRIVE 9 +#define TABLE_I2C_COMMANDS 10 +#define TABLE_PACE 11 +#define TABLE_COUNT 12 + +//RLC Pace Table total number of levels +#define RLC_PACE_TABLE_NUM_LEVELS 16 + +typedef struct { + float FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; + + uint32_t MmHubPadding[8]; // SMU internal use +} RlcPaceFlopsPerByteOverride_t; + +// These defines are used with the SMC_MSG_SetUclkFastSwitch message. +#define UCLK_SWITCH_SLOW 0 +#define UCLK_SWITCH_FAST 1 +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h new file mode 100644 index 000000000000..5ef9c92f57c4 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu11_driver_if_sienna_cichlid.h @@ -0,0 +1,1242 @@ +/* + * 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 __SMU11_DRIVER_IF_SIENNA_CICHLID_H__ +#define __SMU11_DRIVER_IF_SIENNA_CICHLID_H__ + +// *** IMPORTANT *** +// SMU TEAM: Always increment the interface version if +// any structure is changed in this file +#define SMU11_DRIVER_IF_VERSION 0x35 + +#define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_SMNCLK_DPM_LEVELS 2 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DCEFCLK_DPM_LEVELS 8 +#define NUM_PHYCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_PIXCLK_DPM_LEVELS 8 +#define NUM_DTBCLK_DPM_LEVELS 8 +#define NUM_UCLK_DPM_LEVELS 4 +#define NUM_MP1CLK_DPM_LEVELS 2 +#define NUM_LINK_LEVELS 2 +#define NUM_FCLK_DPM_LEVELS 8 +#define NUM_XGMI_LEVELS 2 +#define NUM_XGMI_PSTATE_LEVELS 4 +#define NUM_OD_FAN_MAX_POINTS 6 + +#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) +#define MAX_SMNCLK_DPM_LEVEL (NUM_SMNCLK_DPM_LEVELS - 1) +#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) +#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) +#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) +#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) +#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) +#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) +#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) +#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) +#define MAX_DTBCLK_DPM_LEVEL (NUM_DTBCLK_DPM_LEVELS - 1) +#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) +#define MAX_MP1CLK_DPM_LEVEL (NUM_MP1CLK_DPM_LEVELS - 1) +#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) +#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) + +//Gemini Modes +#define PPSMC_GeminiModeNone 0 //Single GPU board +#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board +#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board + +// Feature Control Defines +// DPM +#define FEATURE_DPM_PREFETCHER_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_GFX_GPO_BIT 2 +#define FEATURE_DPM_UCLK_BIT 3 +#define FEATURE_DPM_FCLK_BIT 4 +#define FEATURE_DPM_SOCCLK_BIT 5 +#define FEATURE_DPM_MP0CLK_BIT 6 +#define FEATURE_DPM_LINK_BIT 7 +#define FEATURE_DPM_DCEFCLK_BIT 8 +#define FEATURE_DPM_XGMI_BIT 9 +#define FEATURE_MEM_VDDCI_SCALING_BIT 10 +#define FEATURE_MEM_MVDD_SCALING_BIT 11 + +//Idle +#define FEATURE_DS_GFXCLK_BIT 12 +#define FEATURE_DS_SOCCLK_BIT 13 +#define FEATURE_DS_FCLK_BIT 14 +#define FEATURE_DS_LCLK_BIT 15 +#define FEATURE_DS_DCEFCLK_BIT 16 +#define FEATURE_DS_UCLK_BIT 17 +#define FEATURE_GFX_ULV_BIT 18 +#define FEATURE_FW_DSTATE_BIT 19 +#define FEATURE_GFXOFF_BIT 20 +#define FEATURE_BACO_BIT 21 +#define FEATURE_MM_DPM_PG_BIT 22 +#define FEATURE_SPARE_23_BIT 23 +//Throttler/Response +#define FEATURE_PPT_BIT 24 +#define FEATURE_TDC_BIT 25 +#define FEATURE_APCC_PLUS_BIT 26 +#define FEATURE_GTHR_BIT 27 +#define FEATURE_ACDC_BIT 28 +#define FEATURE_VR0HOT_BIT 29 +#define FEATURE_VR1HOT_BIT 30 +#define FEATURE_FW_CTF_BIT 31 +#define FEATURE_FAN_CONTROL_BIT 32 +#define FEATURE_THERMAL_BIT 33 +#define FEATURE_GFX_DCS_BIT 34 +//VF +#define FEATURE_RM_BIT 35 +#define FEATURE_LED_DISPLAY_BIT 36 +//Other +#define FEATURE_GFX_SS_BIT 37 +#define FEATURE_OUT_OF_BAND_MONITOR_BIT 38 +#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 39 + +#define FEATURE_MMHUB_PG_BIT 40 +#define FEATURE_ATHUB_PG_BIT 41 +#define FEATURE_APCC_DFLL_BIT 42 +#define FEATURE_DF_SUPERV_BIT 43 +#define FEATURE_RSMU_SMN_CG_BIT 44 +#define FEATURE_DF_CSTATE_BIT 45 +#define FEATURE_2_STEP_PSTATE_BIT 46 +#define FEATURE_SMNCLK_DPM_BIT 47 +#define FEATURE_PERLINK_GMIDOWN_BIT 48 +#define FEATURE_GFX_EDC_BIT 49 +#define FEATURE_SPARE_50_BIT 50 +#define FEATURE_SPARE_51_BIT 51 +#define FEATURE_SPARE_52_BIT 52 +#define FEATURE_SPARE_53_BIT 53 +#define FEATURE_SPARE_54_BIT 54 +#define FEATURE_SPARE_55_BIT 55 +#define FEATURE_SPARE_56_BIT 56 +#define FEATURE_SPARE_57_BIT 57 +#define FEATURE_SPARE_58_BIT 58 +#define FEATURE_SPARE_59_BIT 59 +#define FEATURE_SPARE_60_BIT 60 +#define FEATURE_SPARE_61_BIT 61 +#define FEATURE_SPARE_62_BIT 62 +#define FEATURE_SPARE_63_BIT 63 +#define NUM_FEATURES 64 + +//For use with feature control messages +typedef enum { + FEATURE_PWR_ALL, + FEATURE_PWR_S5, + FEATURE_PWR_BACO, + FEATURE_PWR_SOC, + FEATURE_PWR_GFX, + FEATURE_PWR_DOMAIN_COUNT, +} FEATURE_PWR_DOMAIN_e; + + +// Debug Overrides Bitmask +#define DPM_OVERRIDE_DISABLE_FCLK_PID 0x00000001 +#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000004 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_FCLK 0x00000008 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_FCLK 0x00000010 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00000020 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00000040 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_DCE_FCLK 0x00000080 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_MP0_SOCCLK 0x00000100 +#define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 +#define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 +#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCEFCLK 0x00000800 +#define DPM_OVERRIDE_ENABLE_FAST_FCLK_TIMER 0x00001000 +#define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 +#define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 + +// VR Mapping Bit Defines +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + +// PSI Bit Defines +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + +// Throttler Control/Status Bits +#define THROTTLER_PADDING_BIT 0 +#define THROTTLER_TEMP_EDGE_BIT 1 +#define THROTTLER_TEMP_HOTSPOT_BIT 2 +#define THROTTLER_TEMP_MEM_BIT 3 +#define THROTTLER_TEMP_VR_GFX_BIT 4 +#define THROTTLER_TEMP_VR_MEM0_BIT 5 +#define THROTTLER_TEMP_VR_MEM1_BIT 6 +#define THROTTLER_TEMP_VR_SOC_BIT 7 +#define THROTTLER_TEMP_LIQUID0_BIT 8 +#define THROTTLER_TEMP_LIQUID1_BIT 9 +#define THROTTLER_TEMP_PLX_BIT 10 +#define THROTTLER_TDC_GFX_BIT 11 +#define THROTTLER_TDC_SOC_BIT 12 +#define THROTTLER_PPT0_BIT 13 +#define THROTTLER_PPT1_BIT 14 +#define THROTTLER_PPT2_BIT 15 +#define THROTTLER_PPT3_BIT 16 +#define THROTTLER_FIT_BIT 17 +#define THROTTLER_PPM_BIT 18 +#define THROTTLER_APCC_BIT 19 + +// FW DState Features Control Bits +// FW DState Features Control Bits +#define FW_DSTATE_SOC_ULV_BIT 0 +#define FW_DSTATE_G6_HSR_BIT 1 +#define FW_DSTATE_G6_PHY_VDDCI_OFF_BIT 2 +#define FW_DSTATE_MP0_DS_BIT 3 +#define FW_DSTATE_SMN_DS_BIT 4 +#define FW_DSTATE_MP1_DS_BIT 5 +#define FW_DSTATE_MP1_WHISPER_MODE_BIT 6 +#define FW_DSTATE_SOC_LIV_MIN_BIT 7 +#define FW_DSTATE_SOC_PLL_PWRDN_BIT 8 +#define FW_DSTATE_MEM_PLL_PWRDN_BIT 9 +#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT 10 +#define FW_DSTATE_MEM_PSI_BIT 11 + +#define FW_DSTATE_SOC_ULV_MASK (1 << FW_DSTATE_SOC_ULV_BIT ) +#define FW_DSTATE_G6_HSR_MASK (1 << FW_DSTATE_G6_HSR_BIT ) +#define FW_DSTATE_G6_PHY_VDDCI_OFF_MASK (1 << FW_DSTATE_G6_PHY_VDDCI_OFF_BIT ) +#define FW_DSTATE_MP1_DS_MASK (1 << FW_DSTATE_MP1_DS_BIT ) +#define FW_DSTATE_MP0_DS_MASK (1 << FW_DSTATE_MP0_DS_BIT ) +#define FW_DSTATE_SMN_DS_MASK (1 << FW_DSTATE_SMN_DS_BIT ) +#define FW_DSTATE_MP1_WHISPER_MODE_MASK (1 << FW_DSTATE_MP1_WHISPER_MODE_BIT ) +#define FW_DSTATE_SOC_LIV_MIN_MASK (1 << FW_DSTATE_SOC_LIV_MIN_BIT ) +#define FW_DSTATE_SOC_PLL_PWRDN_MASK (1 << FW_DSTATE_SOC_PLL_PWRDN_BIT ) +#define FW_DSTATE_MEM_PLL_PWRDN_MASK (1 << FW_DSTATE_MEM_PLL_PWRDN_BIT ) +#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_MASK (1 << FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT ) +#define FW_DSTATE_MEM_PSI_MASK (1 << FW_DSTATE_MEM_PSI_BIT ) + +// GFX GPO Feature Contains PACE and DEM sub features +#define GFX_GPO_PACE_BIT 0 +#define GFX_GPO_DEM_BIT 1 + +#define GFX_GPO_PACE_MASK (1 << GFX_GPO_PACE_BIT) +#define GFX_GPO_DEM_MASK (1 << GFX_GPO_DEM_BIT ) + +#define GPO_UPDATE_REQ_UCLKDPM_MASK 0x1 +#define GPO_UPDATE_REQ_FCLKDPM_MASK 0x2 +#define GPO_UPDATE_REQ_MALLHIT_MASK 0x4 + + +//LED Display Mask & Control Bits +#define LED_DISPLAY_GFX_DPM_BIT 0 +#define LED_DISPLAY_PCIE_BIT 1 +#define LED_DISPLAY_ERROR_BIT 2 + +//RLC Pace Table total number of levels +#define RLC_PACE_TABLE_NUM_LEVELS 16 + +typedef enum { + DRAM_BIT_WIDTH_DISABLED = 0, + DRAM_BIT_WIDTH_X_8, + DRAM_BIT_WIDTH_X_16, + DRAM_BIT_WIDTH_X_32, + DRAM_BIT_WIDTH_X_64, // NOT USED. + DRAM_BIT_WIDTH_X_128, + DRAM_BIT_WIDTH_COUNT, +} DRAM_BIT_WIDTH_TYPE_e; + +//I2C Interface +#define NUM_I2C_CONTROLLERS 16 + +#define I2C_CONTROLLER_ENABLED 1 +#define I2C_CONTROLLER_DISABLED 0 + +#define MAX_SW_I2C_COMMANDS 24 + +typedef enum { + I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 + I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 + I2C_CONTROLLER_PORT_COUNT, +} I2cControllerPort_e; + +typedef enum { + I2C_CONTROLLER_NAME_VR_GFX = 0, + I2C_CONTROLLER_NAME_VR_SOC, + I2C_CONTROLLER_NAME_VR_VDDCI, + I2C_CONTROLLER_NAME_VR_MVDD, + I2C_CONTROLLER_NAME_LIQUID0, + I2C_CONTROLLER_NAME_LIQUID1, + I2C_CONTROLLER_NAME_PLX, + I2C_CONTROLLER_NAME_OTHER, + I2C_CONTROLLER_NAME_COUNT, +} I2cControllerName_e; + +typedef enum { + I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, + I2C_CONTROLLER_THROTTLER_VR_GFX, + I2C_CONTROLLER_THROTTLER_VR_SOC, + I2C_CONTROLLER_THROTTLER_VR_VDDCI, + I2C_CONTROLLER_THROTTLER_VR_MVDD, + I2C_CONTROLLER_THROTTLER_LIQUID0, + I2C_CONTROLLER_THROTTLER_LIQUID1, + I2C_CONTROLLER_THROTTLER_PLX, + I2C_CONTROLLER_THROTTLER_INA3221, + I2C_CONTROLLER_THROTTLER_COUNT, +} I2cControllerThrottler_e; + +typedef enum { + I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, + I2C_CONTROLLER_PROTOCOL_VR_IR35217, + I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, + I2C_CONTROLLER_PROTOCOL_INA3221, + I2C_CONTROLLER_PROTOCOL_COUNT, +} I2cControllerProtocol_e; + +typedef struct { + uint8_t Enabled; + uint8_t Speed; + uint8_t SlaveAddress; + uint8_t ControllerPort; + uint8_t ControllerName; + uint8_t ThermalThrotter; + uint8_t I2cProtocol; + uint8_t PaddingConfig; +} I2cControllerConfig_t; + +typedef enum { + I2C_PORT_SVD_SCL = 0, + I2C_PORT_GPIO, +} I2cPort_e; + +typedef enum { + I2C_SPEED_FAST_50K = 0, //50 Kbits/s + I2C_SPEED_FAST_100K, //100 Kbits/s + I2C_SPEED_FAST_400K, //400 Kbits/s + I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) + I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) + I2C_SPEED_HIGH_2M, //2.3 Mbits/s + I2C_SPEED_COUNT, +} I2cSpeed_e; + +typedef enum { + I2C_CMD_READ = 0, + I2C_CMD_WRITE, + I2C_CMD_COUNT, +} I2cCmdType_e; + +typedef enum { + FAN_MODE_AUTO = 0, + FAN_MODE_MANUAL_LINEAR, +} FanMode_e; + +#define CMDCONFIG_STOP_BIT 0 +#define CMDCONFIG_RESTART_BIT 1 +#define CMDCONFIG_READWRITE_BIT 2 //bit should be 0 for read, 1 for write + +#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) +#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) +#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT) + +typedef struct { + uint8_t ReadWriteData; //Return data for read. Data to send for write + uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command, and is a read or write +} SwI2cCmd_t; //SW I2C Command Table + +typedef struct { + uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) + uint8_t I2CSpeed; //Use I2cSpeed_e to indicate speed to select + uint8_t SlaveAddress; //Slave address of device + uint8_t NumCmds; //Number of commands + + SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; +} SwI2cRequest_t; // SW I2C Request Table + +typedef struct { + SwI2cRequest_t SwI2cRequest; + + uint32_t Spare[8]; + uint32_t MmHubPadding[8]; // SMU internal use +} SwI2cRequestExternal_t; + +//D3HOT sequences +typedef enum { + BACO_SEQUENCE, + MSR_SEQUENCE, + BAMACO_SEQUENCE, + ULPS_SEQUENCE, + D3HOT_SEQUENCE_COUNT, +} D3HOTSequence_e; + +//THis is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_DYNAMIC_MODE = 0, + PG_STATIC_MODE, +} PowerGatingMode_e; + +//This is aligned with RSMU PGFSM Register Mapping +typedef enum { + PG_POWER_DOWN = 0, + PG_POWER_UP, +} PowerGatingSettings_e; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} QuadraticInt_t; + +typedef struct { + uint32_t a; // store in fixed point, [31:20] signed integer, [19:0] fractional bits + uint32_t b; // store in fixed point, [31:20] signed integer, [19:0] fractional bits + uint32_t c; // store in fixed point, [31:20] signed integer, [19:0] fractional bits +} QuadraticFixedPoint_t; + +typedef struct { + uint32_t m; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable +} LinearInt_t; + +typedef struct { + uint32_t a; // store in IEEE float format in this variable + uint32_t b; // store in IEEE float format in this variable + uint32_t c; // store in IEEE float format in this variable +} DroopInt_t; + +//Piecewise linear droop model, Sienna_Cichlid currently used only for GFX DFLL +#define NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS 5 +typedef enum { + PIECEWISE_LINEAR_FUSED_MODEL = 0, + PIECEWISE_LINEAR_PP_MODEL, + QUADRATIC_PP_MODEL, +} DfllDroopModelSelect_e; + +typedef struct { + uint32_t Fset[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //in GHz, store in IEEE float format + uint32_t Vdroop[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //in V , store in IEEE float format +}PiecewiseLinearDroopInt_t; + +typedef enum { + GFXCLK_SOURCE_PLL = 0, + GFXCLK_SOURCE_DFLL, + GFXCLK_SOURCE_COUNT, +} GFXCLK_SOURCE_e; + +//Only Clks that have DPM descriptors are listed here +typedef enum { + PPCLK_GFXCLK = 0, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_FCLK, + PPCLK_DCLK_0, + PPCLK_VCLK_0, + PPCLK_DCLK_1, + PPCLK_VCLK_1, + PPCLK_DCEFCLK, + PPCLK_DISPCLK, + PPCLK_PIXCLK, + PPCLK_PHYCLK, + PPCLK_DTBCLK, + PPCLK_COUNT, +} PPCLK_e; + +typedef enum { + VOLTAGE_MODE_AVFS = 0, + VOLTAGE_MODE_AVFS_SS, + VOLTAGE_MODE_SS, + VOLTAGE_MODE_COUNT, +} VOLTAGE_MODE_e; + + +typedef enum { + AVFS_VOLTAGE_GFX = 0, + AVFS_VOLTAGE_SOC, + AVFS_VOLTAGE_COUNT, +} AVFS_VOLTAGE_TYPE_e; + +typedef enum { + UCLK_DIV_BY_1 = 0, + UCLK_DIV_BY_2, + UCLK_DIV_BY_4, + UCLK_DIV_BY_8, +} UCLK_DIV_e; + +typedef enum { + GPIO_INT_POLARITY_ACTIVE_LOW = 0, + GPIO_INT_POLARITY_ACTIVE_HIGH, +} GpioIntPolarity_e; + +typedef enum { + PWR_CONFIG_TDP = 0, + PWR_CONFIG_TGP, + PWR_CONFIG_TCP_ESTIMATED, + PWR_CONFIG_TCP_MEASURED, +} PwrConfig_e; + +typedef enum { + XGMI_LINK_RATE_2 = 2, // 2Gbps + XGMI_LINK_RATE_4 = 4, // 4Gbps + XGMI_LINK_RATE_8 = 8, // 8Gbps + XGMI_LINK_RATE_12 = 12, // 12Gbps + XGMI_LINK_RATE_16 = 16, // 16Gbps + XGMI_LINK_RATE_17 = 17, // 17Gbps + XGMI_LINK_RATE_18 = 18, // 18Gbps + XGMI_LINK_RATE_19 = 19, // 19Gbps + XGMI_LINK_RATE_20 = 20, // 20Gbps + XGMI_LINK_RATE_21 = 21, // 21Gbps + XGMI_LINK_RATE_22 = 22, // 22Gbps + XGMI_LINK_RATE_23 = 23, // 23Gbps + XGMI_LINK_RATE_24 = 24, // 24Gbps + XGMI_LINK_RATE_25 = 25, // 25Gbps + XGMI_LINK_RATE_COUNT +} XGMI_LINK_RATE_e; + +typedef enum { + XGMI_LINK_WIDTH_1 = 0, // x1 + XGMI_LINK_WIDTH_2, // x2 + XGMI_LINK_WIDTH_4, // x4 + XGMI_LINK_WIDTH_8, // x8 + XGMI_LINK_WIDTH_9, // x9 + XGMI_LINK_WIDTH_16, // x16 + XGMI_LINK_WIDTH_COUNT +} XGMI_LINK_WIDTH_e; + +typedef struct { + uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only + uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM + uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used + uint8_t Padding; + LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) + QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) + uint16_t SsFmin; // Fmin for SS curve. If SS curve is selected, will use V@SSFmin for F <= Fmin + uint16_t Padding16; +} DpmDescriptor_t; + +typedef enum { + PPT_THROTTLER_PPT0, + PPT_THROTTLER_PPT1, + PPT_THROTTLER_PPT2, + PPT_THROTTLER_PPT3, + PPT_THROTTLER_COUNT +} PPT_THROTTLER_e; + +typedef enum { + TEMP_EDGE, + TEMP_HOTSPOT, + TEMP_MEM, + TEMP_VR_GFX, + TEMP_VR_MEM0, + TEMP_VR_MEM1, + TEMP_VR_SOC, + TEMP_LIQUID0, + TEMP_LIQUID1, + TEMP_PLX, + TEMP_COUNT, +} TEMP_e; + +typedef enum { + TDC_THROTTLER_GFX, + TDC_THROTTLER_SOC, + TDC_THROTTLER_COUNT +} TDC_THROTTLER_e; + +typedef enum { + CUSTOMER_VARIANT_ROW, + CUSTOMER_VARIANT_FALCON, + CUSTOMER_VARIANT_COUNT, +} CUSTOMER_VARIANT_e; + +// Used for 2-step UCLK DPM change workaround +typedef struct { + uint16_t Fmin; + uint16_t Fmax; +} UclkDpmChangeRange_t; + +typedef struct { + // MAJOR SECTION: SKU PARAMETERS + + uint32_t Version; + + // SECTION: Feature Enablement + uint32_t FeaturesToRun[NUM_FEATURES / 32]; + + // SECTION: Infrastructure Limits + uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; // Watts + uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms + uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; // Watts + uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms + + uint16_t TdcLimit[TDC_THROTTLER_COUNT]; // Amps + uint16_t TdcLimitTau[TDC_THROTTLER_COUNT]; // Time constant of LPF in ms + + uint16_t TemperatureLimit[TEMP_COUNT]; // Celcius + + uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) + + // SECTION: Power Configuration + uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured. Use defines from PwrConfig_e + uint8_t TotalPowerPadding[3]; + + // SECTION: APCC Settings + uint32_t ApccPlusResidencyLimit; + + //SECTION: SMNCLK DPM + uint16_t SmnclkDpmFreq [NUM_SMNCLK_DPM_LEVELS]; // in MHz + uint16_t SmnclkDpmVoltage [NUM_SMNCLK_DPM_LEVELS]; // mV(Q2) + + uint32_t PaddingAPCC[4]; + + // SECTION: Throttler settings + uint32_t ThrottlerControlMask; // See Throtter masks defines + + // SECTION: FW DSTATE Settings + uint32_t FwDStateMask; // See FW DState masks defines + + // SECTION: ULV Settings + uint16_t UlvVoltageOffsetSoc; // In mV(Q2) + uint16_t UlvVoltageOffsetGfx; // In mV(Q2) + + uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode + uint16_t MinVoltageUlvSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC in ULV mode + + uint16_t SocLIVmin; // In mV(Q2) Long Idle Vmin (deep ULV), for VDD_SOC + uint16_t PaddingLIVmin; + + uint8_t GceaLinkMgrIdleThreshold; //Set by SMU FW during enablment of GFXOFF. Controls delay for GFX SDP port disconnection during idle events + uint8_t paddingRlcUlvParams[3]; + + // SECTION: Voltage Control Parameters + uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX + uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC + uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX + uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC + + uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits + uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits + + // SECTION: Temperature Dependent Vmin + uint16_t VDDGFX_TVmin; //Celcius + uint16_t VDDSOC_TVmin; //Celcius + uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 + uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 + uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 + uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 + + uint16_t VDDGFX_TVminHystersis; // Celcius + uint16_t VDDSOC_TVminHystersis; // Celcius + + //SECTION: DPM Config 1 + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz + uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz + uint32_t Paddingclks[16]; + + uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz + + uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 + + // Used for MALL performance boost + uint16_t FclkBoostFreq; // In Mhz + uint16_t FclkParamPadding; + + // SECTION: DPM Config 2 + uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz + uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) + uint16_t MemVddciVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + uint16_t MemMvddVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) + // GFXCLK DPM + uint16_t GfxclkFgfxoffEntry; // in Mhz + uint16_t GfxclkFinit; // in Mhz + uint16_t GfxclkFidle; // in MHz + uint8_t GfxclkSource; // 0 = PLL, 1 = DFLL + uint8_t GfxclkPadding; + + // GFX GPO + uint8_t GfxGpoSubFeatureMask; // bit 0 = PACE, bit 1 = DEM + uint8_t GfxGpoEnabledWorkPolicyMask; //Any policy that GPO can be enabled + uint8_t GfxGpoDisabledWorkPolicyMask; //Any policy that GPO can be disabled + uint8_t GfxGpoPadding[1]; + uint32_t GfxGpoVotingAllow; //For indicating which feature changes should result in a GPO table recalculation + + uint32_t GfxGpoPadding32[4]; + + uint16_t GfxDcsFopt; // Optimal GFXCLK for DCS in Mhz + uint16_t GfxDcsFclkFopt; // Optimal FCLK for DCS in Mhz + uint16_t GfxDcsUclkFopt; // Optimal UCLK for DCS in Mhz + + uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase + + uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase + uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch. + + uint32_t DcsMinCreditAccum; //Min amount of positive credit accumulation before waking GFX up as part of DCS. + + uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase. + uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin. + + uint32_t DcsParamPadding[5]; + + uint16_t FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; // Q8.8 + + // UCLK section + uint8_t LowestUclkReservedForUlv; // Set this to 1 if UCLK DPM0 is reserved for ULV-mode only + uint8_t PaddingMem[3]; + + uint8_t UclkDpmPstates [NUM_UCLK_DPM_LEVELS]; // 4 DPM states, 0-P0, 1-P1, 2-P2, 3-P3. + + // Used for 2-Step UCLK change workaround + UclkDpmChangeRange_t UclkDpmSrcFreqRange; // In Mhz + UclkDpmChangeRange_t UclkDpmTargFreqRange; // In Mhz + uint16_t UclkDpmMidstepFreq; // In Mhz + uint16_t UclkMidstepPadding; + + // Link DPM Settings + uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 + uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 + uint16_t LclkFreq[NUM_LINK_LEVELS]; + + // SECTION: Fan Control + uint16_t FanStopTemp; //Celcius + uint16_t FanStartTemp; //Celcius + + uint16_t FanGain[TEMP_COUNT]; + + uint16_t FanPwmMin; + uint16_t FanAcousticLimitRpm; + uint16_t FanThrottlingRpm; + uint16_t FanMaximumRpm; + uint16_t MGpuFanBoostLimitRpm; + uint16_t FanTargetTemperature; + uint16_t FanTargetGfxclk; + uint16_t FanPadding16; + uint8_t FanTempInputSelect; + uint8_t FanPadding; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + + // The following are AFC override parameters. Leave at 0 to use FW defaults. + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + // SECTION: AVFS + // Overrides + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + uint8_t dBtcGbGfxDfllModelSelect; //0 -> fused piece-wise model, 1 -> piece-wise linear(PPTable), 2 -> quadratic model(PPTable) + uint8_t Padding8_Avfs; + + QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve + DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb + DroopInt_t dBtcGbGfxDfll; // GHz->V BtcGb + DroopInt_t dBtcGbSoc; // GHz->V BtcGb + LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V + + PiecewiseLinearDroopInt_t PiecewiseLinearDroopIntGfxDfll; //GHz ->Vstore in IEEE float format + + QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V + + uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 + + uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; + uint8_t Padding8_GfxBtc[2]; + + uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 + uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 + + uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; // mV Q2 + + // SECTION: XGMI + uint8_t XgmiDpmPstates[NUM_XGMI_LEVELS]; // 2 DPM states, high and low. 0-P0, 1-P1, 2-P2, 3-P3. + uint8_t XgmiDpmSpare[2]; + + // SECTION: Advanced Options + uint32_t DebugOverrides; + QuadraticInt_t ReservedEquation0; + QuadraticInt_t ReservedEquation1; + QuadraticInt_t ReservedEquation2; + QuadraticInt_t ReservedEquation3; + + // SECTION: Sku Reserved + uint8_t CustomerVariant; + uint8_t Spare[3]; + uint32_t SkuReserved[14]; + + + // MAJOR SECTION: BOARD PARAMETERS + + //SECTION: Gaming Clocks + uint32_t GamingClk[6]; + + // SECTION: I2C Control + I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; + + uint8_t GpioScl; // GPIO Number for SCL Line, used only for CKSVII2C1 + uint8_t GpioSda; // GPIO Number for SDA Line, used only for CKSVII2C1 + uint8_t FchUsbPdSlaveAddr; //For requesting USB PD controller S-states via FCH I2C when entering PME turn off + uint8_t I2cSpare[1]; + + // SECTION: SVI2 Board Parameters + uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields + uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields + uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields + + uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t VddciUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + uint8_t MvddUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode + + // SECTION: Telemetry Settings + uint16_t GfxMaxCurrent; // in Amps + int8_t GfxOffset; // in Amps + uint8_t Padding_TelemetryGfx; + + uint16_t SocMaxCurrent; // in Amps + int8_t SocOffset; // in Amps + uint8_t Padding_TelemetrySoc; + + uint16_t Mem0MaxCurrent; // in Amps + int8_t Mem0Offset; // in Amps + uint8_t Padding_TelemetryMem0; + + uint16_t Mem1MaxCurrent; // in Amps + int8_t Mem1Offset; // in Amps + uint8_t Padding_TelemetryMem1; + + uint32_t MvddRatio; // This is used for MVDD Svi2 Div Ratio workaround. It has 16 fractional bits (Q16.16) + + // SECTION: GPIO Settings + uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching + uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching + uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event + uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event + + uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event + uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event + uint8_t GthrGpio; // GPIO pin configured for GTHR Event + uint8_t GthrPolarity; // replace GPIO polarity for GTHR + + // LED Display Settings + uint8_t LedPin0; // GPIO number for LedPin[0] + uint8_t LedPin1; // GPIO number for LedPin[1] + uint8_t LedPin2; // GPIO number for LedPin[2] + uint8_t LedEnableMask; + + uint8_t LedPcie; // GPIO number for PCIE results + uint8_t LedError; // GPIO number for Error Cases + uint8_t LedSpare1[2]; + + // SECTION: Clock Spread Spectrum + + // GFXCLK PLL Spread Spectrum + uint8_t PllGfxclkSpreadEnabled; // on or off + uint8_t PllGfxclkSpreadPercent; // Q4.4 + uint16_t PllGfxclkSpreadFreq; // kHz + + // GFXCLK DFLL Spread Spectrum + uint8_t DfllGfxclkSpreadEnabled; // on or off + uint8_t DfllGfxclkSpreadPercent; // Q4.4 + uint16_t DfllGfxclkSpreadFreq; // kHz + + // UCLK Spread Spectrum + uint16_t UclkSpreadPadding; + uint16_t UclkSpreadFreq; // kHz + + // FCLK Spread Spectrum + uint8_t FclkSpreadEnabled; // on or off + uint8_t FclkSpreadPercent; // Q4.4 + uint16_t FclkSpreadFreq; // kHz + + // Section: Memory Config + uint32_t MemoryChannelEnabled; // For DRAM use only, Max 32 channels enabled bit mask. + + uint8_t DramBitWidth; // For DRAM use only. See Dram Bit width type defines + uint8_t PaddingMem1[3]; + + // Section: Total Board Power + uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power + uint16_t BoardPowerPadding; + + // SECTION: XGMI Training + uint8_t XgmiLinkSpeed [NUM_XGMI_PSTATE_LEVELS]; + uint8_t XgmiLinkWidth [NUM_XGMI_PSTATE_LEVELS]; + + uint16_t XgmiFclkFreq [NUM_XGMI_PSTATE_LEVELS]; + uint16_t XgmiSocVoltage [NUM_XGMI_PSTATE_LEVELS]; + + // SECTION: UMC feature flags + uint8_t HsrEnabled; + uint8_t VddqOffEnabled; + uint8_t PaddingUmcFlags[2]; + + // UCLK Spread Spectrum + uint8_t UclkSpreadPercent[16]; + + // SECTION: Board Reserved + uint32_t BoardReserved[11]; + + // SECTION: Structure Padding + + // Padding for MMHUB - do not modify this + uint32_t MmHubPadding[8]; // SMU internal use + +} PPTable_t; + +typedef struct { + // Time constant parameters for clock averages in ms + uint16_t GfxclkAverageLpfTau; + uint16_t FclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + uint16_t SocketPowerLpfTau; + uint16_t VcnClkAverageLpfTau; + uint16_t padding16; +} DriverSmuConfig_t; + +typedef struct { + DriverSmuConfig_t DriverSmuConfig; + + uint32_t Spare[7]; + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} DriverSmuConfigExternal_t; + +typedef struct { + uint16_t GfxclkFmin; // MHz + uint16_t GfxclkFmax; // MHz + QuadraticInt_t CustomGfxVfCurve; // a: mV/MHz^2, b: mv/MHz, c: mV + uint16_t CustomCurveFmin; // MHz + uint16_t UclkFmin; // MHz + uint16_t UclkFmax; // MHz + int16_t OverDrivePct; // % + uint16_t FanMaximumRpm; + uint16_t FanMinimumPwm; + uint16_t FanAcousticLimitRpm; + uint16_t FanTargetTemperature; // Degree Celcius + uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; + uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; + uint16_t MaxOpTemp; // Degree Celcius + uint16_t Padding_16[1]; + uint8_t FanZeroRpmEnable; + uint8_t FanZeroRpmStopTemp; + uint8_t FanMode; + uint8_t Padding[1]; +} OverDriveTable_t; + +typedef struct { + OverDriveTable_t OverDriveTable; + uint32_t Spare[8]; + + uint32_t MmHubPadding[8]; // SMU internal use +} OverDriveTableExternal_t; + +typedef struct { + uint32_t CurrClock[PPCLK_COUNT]; + + 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 ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t AverageSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureMem ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem0 ; + uint16_t TemperatureVrMem1 ; + uint16_t TemperatureVrSoc ; + uint16_t TemperatureLiquid0 ; + uint16_t TemperatureLiquid1 ; + uint16_t TemperaturePlx ; + uint16_t Padding16 ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t CurrFanPwm; + uint16_t CurrFanSpeed; + + //BACO metrics, PMFW-1721 + //metrics for D3hot entry/exit and driver ARM msgs + uint8_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT]; + uint8_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT]; + uint8_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT]; + + //PMFW-4362 + uint32_t EnergyAccumulator; + uint16_t AverageVclk0Frequency ; + uint16_t AverageDclk0Frequency ; + uint16_t AverageVclk1Frequency ; + uint16_t AverageDclk1Frequency ; + uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence + uint8_t PcieRate ; + uint8_t PcieWidth ; + +} SmuMetrics_t; + +typedef struct { + SmuMetrics_t SmuMetrics; + uint32_t Spare[1]; + + // Padding - ignore + uint32_t MmHubPadding[8]; // SMU internal use +} SmuMetricsExternal_t; + +typedef struct { + uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Flags; + uint8_t Padding[2]; + +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCEFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef enum { + WATERMARKS_CLOCK_RANGE = 0, + WATERMARKS_DUMMY_PSTATE, + WATERMARKS_MALL, + WATERMARKS_COUNT, +} WATERMARKS_FLAGS_e; + +typedef struct { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; +} Watermarks_t; + +typedef struct { + Watermarks_t Watermarks; + + uint32_t MmHubPadding[8]; // SMU internal use +} WatermarksExternal_t; + +typedef struct { + uint16_t avgPsmCount[67]; + uint16_t minPsmCount[67]; + float avgPsmVoltage[67]; + float minPsmVoltage[67]; +} AvfsDebugTable_t; + +typedef struct { + AvfsDebugTable_t AvfsDebugTable; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsDebugTableExternal_t; + +typedef struct { + uint8_t AvfsVersion; + uint8_t Padding; + + uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; + + uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; + uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; + + int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 + int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 + + int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; + uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; + + uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits + + + int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 + int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 + int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 + + uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units + + uint32_t EnabledAvfsModules[3]; //Sienna_Cichlid - 67 AVFS modules +} AvfsFuseOverride_t; + +typedef struct { + AvfsFuseOverride_t AvfsFuseOverride; + + uint32_t MmHubPadding[8]; // SMU internal use +} AvfsFuseOverrideExternal_t; + +typedef struct { + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Gfx_MinActiveFreq; // MHz + uint16_t Gfx_BoosterFreq; // MHz + uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Gfx_PD_Data_limit_a; // Q16 + uint32_t Gfx_PD_Data_limit_b; // Q16 + uint32_t Gfx_PD_Data_limit_c; // Q16 + uint32_t Gfx_PD_Data_error_coeff; // Q16 + uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 + + uint8_t Fclk_ActiveHystLimit; + uint8_t Fclk_IdleHystLimit; + uint8_t Fclk_FPS; + uint8_t Fclk_MinActiveFreqType; + uint8_t Fclk_BoosterFreqType; + uint8_t Fclk_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Fclk_MinActiveFreq; // MHz + uint16_t Fclk_BoosterFreq; // MHz + uint16_t Fclk_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Fclk_PD_Data_limit_a; // Q16 + uint32_t Fclk_PD_Data_limit_b; // Q16 + uint32_t Fclk_PD_Data_limit_c; // Q16 + uint32_t Fclk_PD_Data_error_coeff; // Q16 + uint32_t Fclk_PD_Data_error_rate_coeff; // Q16 + + uint8_t Mem_ActiveHystLimit; + uint8_t Mem_IdleHystLimit; + uint8_t Mem_FPS; + uint8_t Mem_MinActiveFreqType; + uint8_t Mem_BoosterFreqType; + uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. + uint16_t Mem_MinActiveFreq; // MHz + uint16_t Mem_BoosterFreq; // MHz + uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms + uint32_t Mem_PD_Data_limit_a; // Q16 + uint32_t Mem_PD_Data_limit_b; // Q16 + uint32_t Mem_PD_Data_limit_c; // Q16 + uint32_t Mem_PD_Data_error_coeff; // Q16 + uint32_t Mem_PD_Data_error_rate_coeff; // Q16 + + uint32_t Mem_UpThreshold_Limit; // Q16 + uint8_t Mem_UpHystLimit; + uint8_t Mem_DownHystLimit; + uint16_t Mem_Fps; + +} DpmActivityMonitorCoeffInt_t; + + +typedef struct { + DpmActivityMonitorCoeffInt_t DpmActivityMonitorCoeffInt; + uint32_t MmHubPadding[8]; // SMU internal use +} DpmActivityMonitorCoeffIntExternal_t; + +// Workload bits +#define WORKLOAD_PPLIB_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_COUNT 7 + + +// These defines are used with the following messages: +// SMC_MSG_TransferTableDram2Smu +// SMC_MSG_TransferTableSmu2Dram + +// Table transfer status +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF + +// Table types +#define TABLE_PPTABLE 0 +#define TABLE_WATERMARKS 1 +#define TABLE_AVFS_PSM_DEBUG 2 +#define TABLE_AVFS_FUSE_OVERRIDE 3 +#define TABLE_PMSTATUSLOG 4 +#define TABLE_SMU_METRICS 5 +#define TABLE_DRIVER_SMU_CONFIG 6 +#define TABLE_ACTIVITY_MONITOR_COEFF 7 +#define TABLE_OVERDRIVE 8 +#define TABLE_I2C_COMMANDS 9 +#define TABLE_PACE 10 +#define TABLE_COUNT 11 + +typedef struct { + float FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; +} RlcPaceFlopsPerByteOverride_t; + +typedef struct { + RlcPaceFlopsPerByteOverride_t RlcPaceFlopsPerByteOverride; + + uint32_t MmHubPadding[8]; // SMU internal use +} RlcPaceFlopsPerByteOverrideExternal_t; + +// These defines are used with the SMC_MSG_SetUclkFastSwitch message. +#define UCLK_SWITCH_SLOW 0 +#define UCLK_SWITCH_FAST 1 +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h b/drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h new file mode 100644 index 000000000000..e9315eb5b48e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu12_driver_if.h @@ -0,0 +1,232 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU12_DRIVER_IF_H +#define SMU12_DRIVER_IF_H + +// *** IMPORTANT *** +// SMU TEAM: Always increment the interface version if +// any structure is changed in this file +#define SMU12_DRIVER_IF_VERSION 14 + +typedef struct { + int32_t value; + uint32_t numFractionalBits; +} FloatInIntFormat_t; + +typedef enum { + DSPCLK_DCFCLK = 0, + DSPCLK_DISPCLK, + DSPCLK_PIXCLK, + DSPCLK_PHYCLK, + DSPCLK_COUNT, +} DSPCLK_e; + +typedef struct { + uint16_t Freq; // in MHz + uint16_t Vid; // min voltage in SVI2 VID +} DisplayClockTable_t; + +typedef struct { + uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz) + uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz) + uint16_t MinMclk; + uint16_t MaxMclk; + + uint8_t WmSetting; + uint8_t WmType; // Used for normal pstate change or memory retraining + uint8_t Padding[2]; +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 +#define WM_PSTATE_CHG 0 +#define WM_RETRAINING 1 + +typedef enum { + WM_SOCCLK = 0, + WM_DCFCLK, + WM_COUNT, +} WM_CLOCK_e; + +typedef struct { + // Watermarks + WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; + + uint32_t MmHubPadding[7]; // SMU internal use +} Watermarks_t; + +typedef enum { + CUSTOM_DPM_SETTING_GFXCLK, + CUSTOM_DPM_SETTING_CCLK, + CUSTOM_DPM_SETTING_FCLK_CCX, + CUSTOM_DPM_SETTING_FCLK_GFX, + CUSTOM_DPM_SETTING_FCLK_STALLS, + CUSTOM_DPM_SETTING_LCLK, + CUSTOM_DPM_SETTING_COUNT, +} CUSTOM_DPM_SETTING_e; + +typedef struct { + uint8_t ActiveHystLimit; + uint8_t IdleHystLimit; + uint8_t FPS; + uint8_t MinActiveFreqType; + FloatInIntFormat_t MinActiveFreq; + FloatInIntFormat_t PD_Data_limit; + FloatInIntFormat_t PD_Data_time_constant; + FloatInIntFormat_t PD_Data_error_coeff; + FloatInIntFormat_t PD_Data_error_rate_coeff; +} DpmActivityMonitorCoeffExt_t; + +typedef struct { + DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT]; +} CustomDpmSettings_t; + + +#define NUM_DCFCLK_DPM_LEVELS 8 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_FCLK_DPM_LEVELS 4 +#define NUM_MEMCLK_DPM_LEVELS 4 +#define NUM_VCN_DPM_LEVELS 8 + +typedef struct { + uint32_t Freq; // In MHz + uint32_t Vol; // Millivolts with 2 fractional bits +} DpmClock_t; + +typedef struct { + DpmClock_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; + DpmClock_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; + DpmClock_t FClocks[NUM_FCLK_DPM_LEVELS]; + DpmClock_t MemClocks[NUM_MEMCLK_DPM_LEVELS]; + DpmClock_t VClocks[NUM_VCN_DPM_LEVELS]; + DpmClock_t DClocks[NUM_VCN_DPM_LEVELS]; + + uint8_t NumDcfClkDpmEnabled; + uint8_t NumSocClkDpmEnabled; + uint8_t NumFClkDpmEnabled; + uint8_t NumMemClkDpmEnabled; + uint8_t NumVClkDpmEnabled; + uint8_t NumDClkDpmEnabled; + uint8_t spare[2]; +} DpmClocks_t; + + +typedef enum { + CLOCK_SMNCLK = 0, + CLOCK_SOCCLK, + CLOCK_MP0CLK, + CLOCK_MP1CLK, + CLOCK_MP2CLK, + CLOCK_VCLK, + CLOCK_LCLK, + CLOCK_DCLK, + CLOCK_ACLK, + CLOCK_ISPCLK, + CLOCK_SHUBCLK, + CLOCK_DISPCLK, + CLOCK_DPPCLK, + CLOCK_DPREFCLK, + CLOCK_DCFCLK, + CLOCK_FCLK, + CLOCK_UMCCLK, + CLOCK_GFXCLK, + CLOCK_COUNT, +} CLOCK_IDs_e; + +// Throttler Status Bitmask +#define THROTTLER_STATUS_BIT_SPL 0 +#define THROTTLER_STATUS_BIT_FPPT 1 +#define THROTTLER_STATUS_BIT_SPPT 2 +#define THROTTLER_STATUS_BIT_SPPT_APU 3 +#define THROTTLER_STATUS_BIT_THM_CORE 4 +#define THROTTLER_STATUS_BIT_THM_GFX 5 +#define THROTTLER_STATUS_BIT_THM_SOC 6 +#define THROTTLER_STATUS_BIT_TDC_VDD 7 +#define THROTTLER_STATUS_BIT_TDC_SOC 8 +#define THROTTLER_STATUS_BIT_PROCHOT_CPU 9 +#define THROTTLER_STATUS_BIT_PROCHOT_GFX 10 +#define THROTTLER_STATUS_BIT_EDC_CPU 11 +#define THROTTLER_STATUS_BIT_EDC_GFX 12 + +typedef struct { + uint16_t ClockFrequency[CLOCK_COUNT]; //[MHz] + + uint16_t AverageGfxclkFrequency; //[MHz] + uint16_t AverageSocclkFrequency; //[MHz] + uint16_t AverageVclkFrequency; //[MHz] + uint16_t AverageFclkFrequency; //[MHz] + + uint16_t AverageGfxActivity; //[centi] + uint16_t AverageUvdActivity; //[centi] + + uint16_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_SOC + uint16_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_SOC + uint16_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_SOC + + uint16_t FanPwm; //[milli] + uint16_t CurrentSocketPower; //[W] + + uint16_t CoreFrequency[8]; //[MHz] + uint16_t CorePower[8]; //[mW] + uint16_t CoreTemperature[8]; //[centi-Celsius] + uint16_t L3Frequency[2]; //[MHz] + uint16_t L3Temperature[2]; //[centi-Celsius] + + uint16_t GfxTemperature; //[centi-Celsius] + uint16_t SocTemperature; //[centi-Celsius] + uint16_t ThrottlerStatus; + uint16_t spare; + + uint16_t StapmOriginalLimit; //[W] + uint16_t StapmCurrentLimit; //[W] + uint16_t ApuPower; //[W] + uint16_t dGpuPower; //[W] + + uint16_t VddTdcValue; //[mA] + uint16_t SocTdcValue; //[mA] + uint16_t VddEdcValue; //[mA] + uint16_t SocEdcValue; //[mA] + uint16_t reserve[2]; +} SmuMetrics_t; + + +// Workload bits +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 0 +#define WORKLOAD_PPLIB_VIDEO_BIT 2 +#define WORKLOAD_PPLIB_VR_BIT 3 +#define WORKLOAD_PPLIB_COMPUTE_BIT 4 +#define WORKLOAD_PPLIB_CUSTOM_BIT 5 +#define WORKLOAD_PPLIB_COUNT 6 + +#define TABLE_BIOS_IF 0 // Called by BIOS +#define TABLE_WATERMARKS 1 // Called by Driver +#define TABLE_CUSTOM_DPM 2 // Called by Driver +#define TABLE_SPARE1 3 +#define TABLE_DPMCLOCKS 4 // Called by Driver +#define TABLE_MOMENTARY_PM 5 // Called by Tools +#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log +#define TABLE_SMU_METRICS 7 // Called by Driver +#define TABLE_COUNT 8 + + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/smu7.h b/drivers/gpu/drm/amd/pm/inc/smu7.h new file mode 100644 index 000000000000..e14072d45918 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/smu7.h @@ -0,0 +1,189 @@ +/* + * Copyright 2013 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 SMU7_H +#define SMU7_H + +#pragma pack(push, 1) + +#define SMU7_CONTEXT_ID_SMC 1 +#define SMU7_CONTEXT_ID_VBIOS 2 + + +#define SMU7_CONTEXT_ID_SMC 1 +#define SMU7_CONTEXT_ID_VBIOS 2 + +#define SMU7_MAX_LEVELS_VDDC 8 +#define SMU7_MAX_LEVELS_VDDCI 4 +#define SMU7_MAX_LEVELS_MVDD 4 +#define SMU7_MAX_LEVELS_VDDNB 8 + +#define SMU7_MAX_LEVELS_GRAPHICS SMU__NUM_SCLK_DPM_STATE // SCLK + SQ DPM + ULV +#define SMU7_MAX_LEVELS_MEMORY SMU__NUM_MCLK_DPM_LEVELS // MCLK Levels DPM +#define SMU7_MAX_LEVELS_GIO SMU__NUM_LCLK_DPM_LEVELS // LCLK Levels +#define SMU7_MAX_LEVELS_LINK SMU__NUM_PCIE_DPM_LEVELS // PCIe speed and number of lanes. +#define SMU7_MAX_LEVELS_UVD 8 // VCLK/DCLK levels for UVD. +#define SMU7_MAX_LEVELS_VCE 8 // ECLK levels for VCE. +#define SMU7_MAX_LEVELS_ACP 8 // ACLK levels for ACP. +#define SMU7_MAX_LEVELS_SAMU 8 // SAMCLK levels for SAMU. +#define SMU7_MAX_ENTRIES_SMIO 32 // Number of entries in SMIO table. + +#define DPM_NO_LIMIT 0 +#define DPM_NO_UP 1 +#define DPM_GO_DOWN 2 +#define DPM_GO_UP 3 + +#define SMU7_FIRST_DPM_GRAPHICS_LEVEL 0 +#define SMU7_FIRST_DPM_MEMORY_LEVEL 0 + +#define GPIO_CLAMP_MODE_VRHOT 1 +#define GPIO_CLAMP_MODE_THERM 2 +#define GPIO_CLAMP_MODE_DC 4 + +#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0 +#define SCRATCH_B_TARG_PCIE_INDEX_MASK (0x7< +#include "amd_powerplay.h" +#include "hwmgr.h" + +enum SMU_TABLE { + SMU_UVD_TABLE = 0, + SMU_VCE_TABLE, + SMU_BIF_TABLE, +}; + +enum SMU_TYPE { + SMU_SoftRegisters = 0, + SMU_Discrete_DpmTable, +}; + +enum SMU_MEMBER { + HandshakeDisables = 0, + VoltageChangeTimeout, + AverageGraphicsActivity, + AverageMemoryActivity, + PreVBlankGap, + VBlankTimeout, + UcodeLoadStatus, + UvdBootLevel, + VceBootLevel, + LowSclkInterruptThreshold, + DRAM_LOG_ADDR_H, + DRAM_LOG_ADDR_L, + DRAM_LOG_PHY_ADDR_H, + DRAM_LOG_PHY_ADDR_L, + DRAM_LOG_BUFF_SIZE, +}; + + +enum SMU_MAC_DEFINITION { + SMU_MAX_LEVELS_GRAPHICS = 0, + SMU_MAX_LEVELS_MEMORY, + SMU_MAX_LEVELS_LINK, + SMU_MAX_ENTRIES_SMIO, + SMU_MAX_LEVELS_VDDC, + SMU_MAX_LEVELS_VDDGFX, + SMU_MAX_LEVELS_VDDCI, + SMU_MAX_LEVELS_MVDD, + SMU_UVD_MCLK_HANDSHAKE_DISABLE, +}; + +enum SMU9_TABLE_ID { + PPTABLE = 0, + WMTABLE, + AVFSTABLE, + TOOLSTABLE, + AVFSFUSETABLE +}; + +enum SMU10_TABLE_ID { + SMU10_WMTABLE = 0, + SMU10_CLOCKTABLE, +}; + +extern int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table); + +extern int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr); + +extern int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t *resp); + +extern int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter, + uint32_t *resp); + +extern int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr); + +extern int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); +extern int smum_process_firmware_header(struct pp_hwmgr *hwmgr); +extern int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr); +extern int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); +extern int smum_init_smc_table(struct pp_hwmgr *hwmgr); +extern int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); +extern int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr); +extern int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); +extern uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, + uint32_t type, uint32_t member); +extern uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value); + +extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); + +extern bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr); + +extern int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting); + +extern int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h new file mode 100644 index 000000000000..63631296d751 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/tonga_ppsmc.h @@ -0,0 +1,420 @@ +/* + * Copyright 2015 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 TONGA_PP_SMC_H +#define TONGA_PP_SMC_H + +#pragma pack(push, 1) + +#define PPSMC_SWSTATE_FLAG_DC 0x01 +#define PPSMC_SWSTATE_FLAG_UVD 0x02 +#define PPSMC_SWSTATE_FLAG_VCE 0x04 +#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 + +#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 +#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 +#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff + +#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 +#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 +#define PPSMC_SYSTEMFLAG_GDDR5 0x04 + +#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 + +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 +#define PPSMC_SYSTEMFLAG_12CHANNEL 0x40 + + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 +#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 + +#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x10 +#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17 0x20 +#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17 0x40 + +/* Defines for DPM 2.0 */ +#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 +#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 +#define PPSMC_DPM2FLAGS_OCP 0x04 + +/* Defines for display watermark level */ + +#define PPSMC_DISPLAY_WATERMARK_LOW 0 +#define PPSMC_DISPLAY_WATERMARK_HIGH 1 + +/* In the HW performance level's state flags:*/ +#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 +#define PPSMC_STATEFLAG_POWERBOOST 0x02 +#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 +#define PPSMC_STATEFLAG_POWERSHIFT 0x08 +#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 +#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 +#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 + +/* Fan control algorithm:*/ +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +/* Return codes for driver to SMC communication.*/ + +#define PPSMC_Result_OK ((uint16_t)0x01) +#define PPSMC_Result_NoMore ((uint16_t)0x02) +#define PPSMC_Result_NotNow ((uint16_t)0x03) + +#define PPSMC_Result_Failed ((uint16_t)0xFF) +#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) + +typedef uint16_t PPSMC_Result; + +#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) + + +#define PPSMC_MSG_Halt ((uint16_t)0x10) +#define PPSMC_MSG_Resume ((uint16_t)0x11) +#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) +#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) +#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) +#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) +#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) +#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) +#define PPSMC_MSG_LevelUp ((uint16_t)0x18) +#define PPSMC_MSG_LevelDown ((uint16_t)0x19) +#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) +#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) + +#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) +#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) +#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) +#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) +#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) + +#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) +#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) +#define PPSMC_MSG_EnableCac ((uint16_t)0x53) +#define PPSMC_MSG_DisableCac ((uint16_t)0x54) +#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) +#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) +#define PPSMC_CACHistoryStart ((uint16_t)0x57) +#define PPSMC_CACHistoryStop ((uint16_t)0x58) +#define PPSMC_TDPClampingActive ((uint16_t)0x59) +#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) +#define PPSMC_StartFanControl ((uint16_t)0x5B) +#define PPSMC_StopFanControl ((uint16_t)0x5C) +#define PPSMC_NoDisplay ((uint16_t)0x5D) +#define PPSMC_HasDisplay ((uint16_t)0x5E) +#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) +#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) +#define PPSMC_MSG_EnableULV ((uint16_t)0x62) +#define PPSMC_MSG_DisableULV ((uint16_t)0x63) +#define PPSMC_MSG_EnterULV ((uint16_t)0x64) +#define PPSMC_MSG_ExitULV ((uint16_t)0x65) +#define PPSMC_PowerShiftActive ((uint16_t)0x6A) +#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) +#define PPSMC_OCPActive ((uint16_t)0x6C) +#define PPSMC_OCPInactive ((uint16_t)0x6D) +#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) +#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) +#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) +#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) +#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) +#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) +#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) +#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) +#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) +#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) +#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) +#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) +#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) +#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) +#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) +#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) + +#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) +#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) +#define PPSMC_FlushDataCache ((uint16_t)0x80) +#define PPSMC_FlushInstrCache ((uint16_t)0x81) + +#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) +#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) + +#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) + +#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) +#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) +#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) +#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) + +#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) +#define PPSMC_MSG_ChangeNearTDPLimit ((uint16_t)0x90) +#define PPSMC_MSG_ChangeSafePowerLimit ((uint16_t)0x91) + +#define PPSMC_MSG_DPMStateSweepStart ((uint16_t)0x92) +#define PPSMC_MSG_DPMStateSweepStop ((uint16_t)0x93) + +#define PPSMC_MSG_OVRDDisableSCLKDS ((uint16_t)0x94) +#define PPSMC_MSG_CancelDisableOVRDSCLKDS ((uint16_t)0x95) +#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint16_t)0x96) +#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint16_t)0x97) +#define PPSMC_MSG_GPIO17 ((uint16_t)0x98) + +#define PPSMC_MSG_API_SetSvi2Volt_Vddc ((uint16_t)0x99) +#define PPSMC_MSG_API_SetSvi2Volt_Vddci ((uint16_t)0x9A) +#define PPSMC_MSG_API_SetSvi2Volt_Mvdd ((uint16_t)0x9B) +#define PPSMC_MSG_API_GetSvi2Volt_Vddc ((uint16_t)0x9C) +#define PPSMC_MSG_API_GetSvi2Volt_Vddci ((uint16_t)0x9D) +#define PPSMC_MSG_API_GetSvi2Volt_Mvdd ((uint16_t)0x9E) + +#define PPSMC_MSG_BREAK ((uint16_t)0xF8) + +/* Trinity Specific Messages*/ +#define PPSMC_MSG_Test ((uint16_t) 0x100) +#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) +#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) +#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) +#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) +#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) +#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) +#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) +#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) +#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) +#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) +#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) +#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) +#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) +#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) +#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) +#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) +#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) +#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) +#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) +#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) +#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) +#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) +#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) +#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) +#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) +#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) +#define PPSMC_MSG_PCIE_PHYPowerDown ((uint16_t) 0x122) +#define PPSMC_MSG_PCIE_PHYPowerUp ((uint16_t) 0x123) +#define PPSMC_MSG_UVD_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) +#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) +#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_NBDPM_Config ((uint16_t) 0x125) +#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint16_t) 0x126) +#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint16_t) 0x127) +#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) + +#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) +#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) +#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) +#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) +#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) +#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) +#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) +#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) +#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) +#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) +#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) +#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) +#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) +#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) +#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) +#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) +#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) +#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) +#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) +#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) +#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) +#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) +#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) +#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) +#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) +#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) +#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) + +#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) +#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) + +#define PPSMC_MSG_DPM_Enable ((uint16_t)0x14e) +#define PPSMC_MSG_DPM_Disable ((uint16_t)0x14f) +#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t)0x150) +#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t)0x151) +#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t)0x152) +#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t)0x153) +#define PPSMC_MSG_UVDDPM_Enable ((uint16_t)0x154) +#define PPSMC_MSG_UVDDPM_Disable ((uint16_t)0x155) +#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t)0x156) +#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t)0x157) +#define PPSMC_MSG_ACPDPM_Enable ((uint16_t)0x158) +#define PPSMC_MSG_ACPDPM_Disable ((uint16_t)0x159) +#define PPSMC_MSG_VCEDPM_Enable ((uint16_t)0x15a) +#define PPSMC_MSG_VCEDPM_Disable ((uint16_t)0x15b) +#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t)0x15c) + +#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) +#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) +#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) +#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) +#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) +#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) +#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) +#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) +#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) +#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) +#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) +#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) +#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) +#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) +#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t)0x16c) +#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t)0x16d) +#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t)0x16e) +#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t)0x16f) +#define PPSMC_MSG_PmStatusLogStart ((uint16_t)0x170) +#define PPSMC_MSG_PmStatusLogSample ((uint16_t)0x171) +#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) +#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) +#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) +#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) +#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) +#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) +#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) +#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) +#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) +#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) +#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) +#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) +#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) +#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) +#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) +#define PPSMC_MSG_UVD_HANDSHAKE_OFF ((uint16_t) 0x183) +#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) +#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) +#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) +#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) +#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) +#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) +#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) +#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) +#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) +#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) +#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) +#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) +#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) +#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) +#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) +#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) +#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) +#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) +#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) +#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) +#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) +#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) +#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) + +#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) +#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) +#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) +#define PPSMC_MSG_Enable_PCC ((uint16_t) 0x19E) +#define PPSMC_MSG_Disable_PCC ((uint16_t) 0x19F) + +#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) +#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) +#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) +#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) +#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) +#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) +#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) +#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) +#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) + +#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) +#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) +#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) +#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) +#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) +#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) +#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) + +#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) +#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) +#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) +#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) +#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) +#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) +#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) +#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) +#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) +#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) +#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) +#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) +#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) +#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) +#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) +#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) +#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) +#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) +#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) + +typedef uint16_t PPSMC_Msg; + +/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ +#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 +#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 +#define PPSMC_EVENT_STATUS_DC 0x00000004 +#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 + + +#pragma pack(pop) +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h new file mode 100644 index 000000000000..715b5a168831 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/vega10_ppsmc.h @@ -0,0 +1,144 @@ +/* + * Copyright 2016 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 PP_SMC_H +#define PP_SMC_H + +#pragma pack(push, 1) + +#define SMU_UCODE_VERSION 0x001c0800 + +/* SMU Response Codes: */ +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +typedef uint16_t PPSMC_Result; + +/* Message Definitions */ +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_EnableSmuFeatures 0x4 +#define PPSMC_MSG_DisableSmuFeatures 0x5 +#define PPSMC_MSG_GetEnabledSmuFeatures 0x6 +#define PPSMC_MSG_SetWorkloadMask 0x7 +#define PPSMC_MSG_SetPptLimit 0x8 +#define PPSMC_MSG_SetDriverDramAddrHigh 0x9 +#define PPSMC_MSG_SetDriverDramAddrLow 0xA +#define PPSMC_MSG_SetToolsDramAddrHigh 0xB +#define PPSMC_MSG_SetToolsDramAddrLow 0xC +#define PPSMC_MSG_TransferTableSmu2Dram 0xD +#define PPSMC_MSG_TransferTableDram2Smu 0xE +#define PPSMC_MSG_UseDefaultPPTable 0xF +#define PPSMC_MSG_UseBackupPPTable 0x10 +#define PPSMC_MSG_RunBtc 0x11 +#define PPSMC_MSG_RequestI2CBus 0x12 +#define PPSMC_MSG_ReleaseI2CBus 0x13 +#define PPSMC_MSG_ConfigureTelemetry 0x14 +#define PPSMC_MSG_SetUlvIpMask 0x15 +#define PPSMC_MSG_SetSocVidOffset 0x16 +#define PPSMC_MSG_SetMemVidOffset 0x17 +#define PPSMC_MSG_GetSocVidOffset 0x18 +#define PPSMC_MSG_GetMemVidOffset 0x19 +#define PPSMC_MSG_SetFloorSocVoltage 0x1A +#define PPSMC_MSG_SoftReset 0x1B +#define PPSMC_MSG_StartBacoMonitor 0x1C +#define PPSMC_MSG_CancelBacoMonitor 0x1D +#define PPSMC_MSG_EnterBaco 0x1E +#define PPSMC_MSG_AllowLowGfxclkInterrupt 0x1F +#define PPSMC_MSG_SetLowGfxclkInterruptThreshold 0x20 +#define PPSMC_MSG_SetSoftMinGfxclkByIndex 0x21 +#define PPSMC_MSG_SetSoftMaxGfxclkByIndex 0x22 +#define PPSMC_MSG_GetCurrentGfxclkIndex 0x23 +#define PPSMC_MSG_SetSoftMinUclkByIndex 0x24 +#define PPSMC_MSG_SetSoftMaxUclkByIndex 0x25 +#define PPSMC_MSG_GetCurrentUclkIndex 0x26 +#define PPSMC_MSG_SetSoftMinUvdByIndex 0x27 +#define PPSMC_MSG_SetSoftMaxUvdByIndex 0x28 +#define PPSMC_MSG_GetCurrentUvdIndex 0x29 +#define PPSMC_MSG_SetSoftMinVceByIndex 0x2A +#define PPSMC_MSG_SetSoftMaxVceByIndex 0x2B +#define PPSMC_MSG_SetHardMinVceByIndex 0x2C +#define PPSMC_MSG_GetCurrentVceIndex 0x2D +#define PPSMC_MSG_SetSoftMinSocclkByIndex 0x2E +#define PPSMC_MSG_SetHardMinSocclkByIndex 0x2F +#define PPSMC_MSG_SetSoftMaxSocclkByIndex 0x30 +#define PPSMC_MSG_GetCurrentSocclkIndex 0x31 +#define PPSMC_MSG_SetMinLinkDpmByIndex 0x32 +#define PPSMC_MSG_GetCurrentLinkIndex 0x33 +#define PPSMC_MSG_GetAverageGfxclkFrequency 0x34 +#define PPSMC_MSG_GetAverageSocclkFrequency 0x35 +#define PPSMC_MSG_GetAverageUclkFrequency 0x36 +#define PPSMC_MSG_GetAverageGfxActivity 0x37 +#define PPSMC_MSG_GetTemperatureEdge 0x38 +#define PPSMC_MSG_GetTemperatureHotspot 0x39 +#define PPSMC_MSG_GetTemperatureHBM 0x3A +#define PPSMC_MSG_GetTemperatureVrSoc 0x3B +#define PPSMC_MSG_GetTemperatureVrMem 0x3C +#define PPSMC_MSG_GetTemperatureLiquid 0x3D +#define PPSMC_MSG_GetTemperaturePlx 0x3E +#define PPSMC_MSG_OverDriveSetPercentage 0x3F +#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x40 +#define PPSMC_MSG_SwitchToAC 0x41 +#define PPSMC_MSG_SetUclkFastSwitch 0x42 +#define PPSMC_MSG_SetUclkDownHyst 0x43 +#define PPSMC_MSG_RemoveDCClamp 0x44 +#define PPSMC_MSG_GfxDeviceDriverReset 0x45 +#define PPSMC_MSG_GetCurrentRpm 0x46 +#define PPSMC_MSG_SetVideoFps 0x47 +#define PPSMC_MSG_SetCustomGfxDpmParameters 0x48 +#define PPSMC_MSG_SetTjMax 0x49 +#define PPSMC_MSG_SetFanTemperatureTarget 0x4A +#define PPSMC_MSG_PrepareMp1ForUnload 0x4B +#define PPSMC_MSG_RequestDisplayClockByFreq 0x4C +#define PPSMC_MSG_GetClockFreqMHz 0x4D +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x4E +#define PPSMC_MSG_DramLogSetDramAddrLow 0x4F +#define PPSMC_MSG_DramLogSetDramSize 0x50 +#define PPSMC_MSG_SetFanMaxRpm 0x51 +#define PPSMC_MSG_SetFanMinPwm 0x52 +#define PPSMC_MSG_ConfigureGfxDidt 0x55 +#define PPSMC_MSG_NumOfDisplays 0x56 +#define PPSMC_MSG_ReadSerialNumTop32 0x58 +#define PPSMC_MSG_ReadSerialNumBottom32 0x59 +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x5A +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x5B +#define PPSMC_MSG_RunAcgBtc 0x5C +#define PPSMC_MSG_RunAcgInClosedLoop 0x5D +#define PPSMC_MSG_RunAcgInOpenLoop 0x5E +#define PPSMC_MSG_InitializeAcg 0x5F +#define PPSMC_MSG_GetCurrPkgPwr 0x61 +#define PPSMC_MSG_GetAverageGfxclkActualFrequency 0x63 +#define PPSMC_MSG_SetPccThrottleLevel 0x67 +#define PPSMC_MSG_UpdatePkgPwrPidAlpha 0x68 +#define PPSMC_Message_Count 0x69 + + +typedef int PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h b/drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h new file mode 100644 index 000000000000..b6ffd08784e7 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/vega12/smu9_driver_if.h @@ -0,0 +1,767 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef VEGA12_SMU9_DRIVER_IF_H +#define VEGA12_SMU9_DRIVER_IF_H + +/**** IMPORTANT *** + * SMU TEAM: Always increment the interface version if + * any structure is changed in this file + */ +#define SMU9_DRIVER_IF_VERSION 0x10 + +#define PPTABLE_V12_SMU_VERSION 1 + +#define NUM_GFXCLK_DPM_LEVELS 16 +#define NUM_VCLK_DPM_LEVELS 8 +#define NUM_DCLK_DPM_LEVELS 8 +#define NUM_ECLK_DPM_LEVELS 8 +#define NUM_MP0CLK_DPM_LEVELS 2 +#define NUM_UCLK_DPM_LEVELS 4 +#define NUM_SOCCLK_DPM_LEVELS 8 +#define NUM_DCEFCLK_DPM_LEVELS 8 +#define NUM_DISPCLK_DPM_LEVELS 8 +#define NUM_PIXCLK_DPM_LEVELS 8 +#define NUM_PHYCLK_DPM_LEVELS 8 +#define NUM_LINK_LEVELS 2 + +#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) +#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) +#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) +#define MAX_ECLK_DPM_LEVEL (NUM_ECLK_DPM_LEVELS - 1) +#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) +#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) +#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) +#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) +#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) +#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) +#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) +#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) + + +#define PPSMC_GeminiModeNone 0 +#define PPSMC_GeminiModeMaster 1 +#define PPSMC_GeminiModeSlave 2 + + +#define FEATURE_DPM_PREFETCHER_BIT 0 +#define FEATURE_DPM_GFXCLK_BIT 1 +#define FEATURE_DPM_UCLK_BIT 2 +#define FEATURE_DPM_SOCCLK_BIT 3 +#define FEATURE_DPM_UVD_BIT 4 +#define FEATURE_DPM_VCE_BIT 5 +#define FEATURE_ULV_BIT 6 +#define FEATURE_DPM_MP0CLK_BIT 7 +#define FEATURE_DPM_LINK_BIT 8 +#define FEATURE_DPM_DCEFCLK_BIT 9 +#define FEATURE_DS_GFXCLK_BIT 10 +#define FEATURE_DS_SOCCLK_BIT 11 +#define FEATURE_DS_LCLK_BIT 12 +#define FEATURE_PPT_BIT 13 +#define FEATURE_TDC_BIT 14 +#define FEATURE_THERMAL_BIT 15 +#define FEATURE_GFX_PER_CU_CG_BIT 16 +#define FEATURE_RM_BIT 17 +#define FEATURE_DS_DCEFCLK_BIT 18 +#define FEATURE_ACDC_BIT 19 +#define FEATURE_VR0HOT_BIT 20 +#define FEATURE_VR1HOT_BIT 21 +#define FEATURE_FW_CTF_BIT 22 +#define FEATURE_LED_DISPLAY_BIT 23 +#define FEATURE_FAN_CONTROL_BIT 24 +#define FEATURE_GFX_EDC_BIT 25 +#define FEATURE_GFXOFF_BIT 26 +#define FEATURE_CG_BIT 27 +#define FEATURE_ACG_BIT 28 +#define FEATURE_SPARE_29_BIT 29 +#define FEATURE_SPARE_30_BIT 30 +#define FEATURE_SPARE_31_BIT 31 + +#define NUM_FEATURES 32 + +#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) +#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) +#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) +#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) +#define FEATURE_DPM_UVD_MASK (1 << FEATURE_DPM_UVD_BIT ) +#define FEATURE_DPM_VCE_MASK (1 << FEATURE_DPM_VCE_BIT ) +#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT ) +#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) +#define FEATURE_DPM_LINK_MASK (1 << FEATURE_DPM_LINK_BIT ) +#define FEATURE_DPM_DCEFCLK_MASK (1 << FEATURE_DPM_DCEFCLK_BIT ) +#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) +#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) +#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) +#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) +#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) +#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) +#define FEATURE_GFX_PER_CU_CG_MASK (1 << FEATURE_GFX_PER_CU_CG_BIT ) +#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT ) +#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT ) +#define FEATURE_ACDC_MASK (1 << FEATURE_ACDC_BIT ) +#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) +#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) +#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) +#define FEATURE_LED_DISPLAY_MASK (1 << FEATURE_LED_DISPLAY_BIT ) +#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) +#define FEATURE_GFX_EDC_MASK (1 << FEATURE_GFX_EDC_BIT ) +#define FEATURE_GFXOFF_MASK (1 << FEATURE_GFXOFF_BIT ) +#define FEATURE_CG_MASK (1 << FEATURE_CG_BIT ) +#define FEATURE_ACG_MASK (1 << FEATURE_ACG_BIT) +#define FEATURE_SPARE_29_MASK (1 << FEATURE_SPARE_29_BIT ) +#define FEATURE_SPARE_30_MASK (1 << FEATURE_SPARE_30_BIT ) +#define FEATURE_SPARE_31_MASK (1 << FEATURE_SPARE_31_BIT ) + + +#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 +#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_SOCCLK 0x00000004 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_UCLK 0x00000008 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000010 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_UCLK 0x00000020 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000040 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_UCLK 0x00000080 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_SOCCLK 0x00000100 +#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_UCLK 0x00000200 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_SOCCLK 0x00000400 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_UCLK 0x00000800 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00001000 +#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00002000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_GFXCLK_SWITCH 0x00004000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_SOCCLK_SWITCH 0x00008000 +#define DPM_OVERRIDE_ENABLE_GFXOFF_UCLK_SWITCH 0x00010000 + + +#define VR_MAPPING_VR_SELECT_MASK 0x01 +#define VR_MAPPING_VR_SELECT_SHIFT 0x00 + +#define VR_MAPPING_PLANE_SELECT_MASK 0x02 +#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 + + +#define PSI_SEL_VR0_PLANE0_PSI0 0x01 +#define PSI_SEL_VR0_PLANE0_PSI1 0x02 +#define PSI_SEL_VR0_PLANE1_PSI0 0x04 +#define PSI_SEL_VR0_PLANE1_PSI1 0x08 +#define PSI_SEL_VR1_PLANE0_PSI0 0x10 +#define PSI_SEL_VR1_PLANE0_PSI1 0x20 +#define PSI_SEL_VR1_PLANE1_PSI0 0x40 +#define PSI_SEL_VR1_PLANE1_PSI1 0x80 + + +#define THROTTLER_STATUS_PADDING_BIT 0 +#define THROTTLER_STATUS_TEMP_EDGE_BIT 1 +#define THROTTLER_STATUS_TEMP_HOTSPOT_BIT 2 +#define THROTTLER_STATUS_TEMP_HBM_BIT 3 +#define THROTTLER_STATUS_TEMP_VR_GFX_BIT 4 +#define THROTTLER_STATUS_TEMP_VR_MEM_BIT 5 +#define THROTTLER_STATUS_TEMP_LIQUID_BIT 6 +#define THROTTLER_STATUS_TEMP_PLX_BIT 7 +#define THROTTLER_STATUS_TEMP_SKIN_BIT 8 +#define THROTTLER_STATUS_TDC_GFX_BIT 9 +#define THROTTLER_STATUS_TDC_SOC_BIT 10 +#define THROTTLER_STATUS_PPT_BIT 11 +#define THROTTLER_STATUS_FIT_BIT 12 +#define THROTTLER_STATUS_PPM_BIT 13 + + +#define TABLE_TRANSFER_OK 0x0 +#define TABLE_TRANSFER_FAILED 0xFF + + +#define WORKLOAD_DEFAULT_BIT 0 +#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 +#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 +#define WORKLOAD_PPLIB_VIDEO_BIT 3 +#define WORKLOAD_PPLIB_VR_BIT 4 +#define WORKLOAD_PPLIB_COMPUTE_BIT 5 +#define WORKLOAD_PPLIB_CUSTOM_BIT 6 +#define WORKLOAD_PPLIB_COUNT 7 + +typedef struct { + uint32_t a; + uint32_t b; + uint32_t c; +} QuadraticInt_t; + +typedef struct { + uint32_t m; + uint32_t b; +} LinearInt_t; + +typedef struct { + uint32_t a; + uint32_t b; + uint32_t c; +} DroopInt_t; + +typedef enum { + PPCLK_GFXCLK, + PPCLK_VCLK, + PPCLK_DCLK, + PPCLK_ECLK, + PPCLK_SOCCLK, + PPCLK_UCLK, + PPCLK_DCEFCLK, + PPCLK_DISPCLK, + PPCLK_PIXCLK, + PPCLK_PHYCLK, + PPCLK_COUNT, +} PPCLK_e; + +enum { + VOLTAGE_MODE_AVFS, + VOLTAGE_MODE_AVFS_SS, + VOLTAGE_MODE_SS, + VOLTAGE_MODE_COUNT, +}; + +typedef struct { + uint8_t VoltageMode; + uint8_t SnapToDiscrete; + uint8_t NumDiscreteLevels; + uint8_t padding; + LinearInt_t ConversionToAvfsClk; + QuadraticInt_t SsCurve; +} DpmDescriptor_t; + +typedef struct { + uint32_t Version; + + + uint32_t FeaturesToRun[2]; + + + uint16_t SocketPowerLimitAc0; + uint16_t SocketPowerLimitAc0Tau; + uint16_t SocketPowerLimitAc1; + uint16_t SocketPowerLimitAc1Tau; + uint16_t SocketPowerLimitAc2; + uint16_t SocketPowerLimitAc2Tau; + uint16_t SocketPowerLimitAc3; + uint16_t SocketPowerLimitAc3Tau; + uint16_t SocketPowerLimitDc; + uint16_t SocketPowerLimitDcTau; + uint16_t TdcLimitSoc; + uint16_t TdcLimitSocTau; + uint16_t TdcLimitGfx; + uint16_t TdcLimitGfxTau; + + uint16_t TedgeLimit; + uint16_t ThotspotLimit; + uint16_t ThbmLimit; + uint16_t Tvr_gfxLimit; + uint16_t Tvr_memLimit; + uint16_t Tliquid1Limit; + uint16_t Tliquid2Limit; + uint16_t TplxLimit; + uint32_t FitLimit; + + uint16_t PpmPowerLimit; + uint16_t PpmTemperatureThreshold; + + uint8_t MemoryOnPackage; + uint8_t padding8_limits[3]; + + + uint16_t UlvVoltageOffsetSoc; + uint16_t UlvVoltageOffsetGfx; + + uint8_t UlvSmnclkDid; + uint8_t UlvMp1clkDid; + uint8_t UlvGfxclkBypass; + uint8_t Padding234; + + + uint16_t MinVoltageGfx; + uint16_t MinVoltageSoc; + uint16_t MaxVoltageGfx; + uint16_t MaxVoltageSoc; + + uint16_t LoadLineResistance; + uint16_t LoadLine_padding; + + + DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; + + uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; + uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; + uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; + uint16_t FreqTableEclk [NUM_ECLK_DPM_LEVELS ]; + uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; + uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; + uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; + uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; + uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; + uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; + + uint16_t DcModeMaxFreq [PPCLK_COUNT ]; + + + uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; + uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; + + + uint16_t GfxclkFidle; + uint16_t GfxclkSlewRate; + uint16_t CksEnableFreq; + uint16_t Padding789; + QuadraticInt_t CksVoltageOffset; + uint16_t AcgThresholdFreqHigh; + uint16_t AcgThresholdFreqLow; + uint16_t GfxclkDsMaxFreq; + uint8_t Padding456[2]; + + + uint8_t LowestUclkReservedForUlv; + uint8_t Padding8_Uclk[3]; + + + uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; + uint8_t PcieLaneCount[NUM_LINK_LEVELS]; + uint16_t LclkFreq[NUM_LINK_LEVELS]; + + + uint16_t EnableTdpm; + uint16_t TdpmHighHystTemperature; + uint16_t TdpmLowHystTemperature; + uint16_t GfxclkFreqHighTempLimit; + + + uint16_t FanStopTemp; + uint16_t FanStartTemp; + + uint16_t FanGainEdge; + uint16_t FanGainHotspot; + uint16_t FanGainLiquid; + uint16_t FanGainVrVddc; + uint16_t FanGainVrMvdd; + uint16_t FanGainPlx; + uint16_t FanGainHbm; + uint16_t FanPwmMin; + uint16_t FanAcousticLimitRpm; + uint16_t FanThrottlingRpm; + uint16_t FanMaximumRpm; + uint16_t FanTargetTemperature; + uint16_t FanTargetGfxclk; + uint8_t FanZeroRpmEnable; + uint8_t FanTachEdgePerRev; + + + + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t FuzzyFan_Reserved; + + + + + uint8_t OverrideAvfsGb; + uint8_t Padding8_Avfs[3]; + + QuadraticInt_t qAvfsGb; + DroopInt_t dBtcGbGfxCksOn; + DroopInt_t dBtcGbGfxCksOff; + DroopInt_t dBtcGbGfxAcg; + DroopInt_t dBtcGbSoc; + LinearInt_t qAgingGbGfx; + LinearInt_t qAgingGbSoc; + + QuadraticInt_t qStaticVoltageOffsetGfx; + QuadraticInt_t qStaticVoltageOffsetSoc; + + uint16_t DcTolGfx; + uint16_t DcTolSoc; + + uint8_t DcBtcGfxEnabled; + uint8_t DcBtcSocEnabled; + uint8_t Padding8_GfxBtc[2]; + + uint16_t DcBtcGfxMin; + uint16_t DcBtcGfxMax; + + uint16_t DcBtcSocMin; + uint16_t DcBtcSocMax; + + + + uint32_t DebugOverrides; + QuadraticInt_t ReservedEquation0; + QuadraticInt_t ReservedEquation1; + QuadraticInt_t ReservedEquation2; + QuadraticInt_t ReservedEquation3; + + uint16_t MinVoltageUlvGfx; + uint16_t MinVoltageUlvSoc; + + uint32_t Reserved[14]; + + + + uint8_t Liquid1_I2C_address; + uint8_t Liquid2_I2C_address; + uint8_t Vr_I2C_address; + uint8_t Plx_I2C_address; + + uint8_t Liquid_I2C_LineSCL; + uint8_t Liquid_I2C_LineSDA; + uint8_t Vr_I2C_LineSCL; + uint8_t Vr_I2C_LineSDA; + + uint8_t Plx_I2C_LineSCL; + uint8_t Plx_I2C_LineSDA; + uint8_t VrSensorPresent; + uint8_t LiquidSensorPresent; + + uint16_t MaxVoltageStepGfx; + uint16_t MaxVoltageStepSoc; + + uint8_t VddGfxVrMapping; + uint8_t VddSocVrMapping; + uint8_t VddMem0VrMapping; + uint8_t VddMem1VrMapping; + + uint8_t GfxUlvPhaseSheddingMask; + uint8_t SocUlvPhaseSheddingMask; + uint8_t ExternalSensorPresent; + uint8_t Padding8_V; + + + uint16_t GfxMaxCurrent; + int8_t GfxOffset; + uint8_t Padding_TelemetryGfx; + + uint16_t SocMaxCurrent; + int8_t SocOffset; + uint8_t Padding_TelemetrySoc; + + uint16_t Mem0MaxCurrent; + int8_t Mem0Offset; + uint8_t Padding_TelemetryMem0; + + uint16_t Mem1MaxCurrent; + int8_t Mem1Offset; + uint8_t Padding_TelemetryMem1; + + + uint8_t AcDcGpio; + uint8_t AcDcPolarity; + uint8_t VR0HotGpio; + uint8_t VR0HotPolarity; + + uint8_t VR1HotGpio; + uint8_t VR1HotPolarity; + uint8_t Padding1; + uint8_t Padding2; + + + + uint8_t LedPin0; + uint8_t LedPin1; + uint8_t LedPin2; + uint8_t padding8_4; + + + uint8_t PllGfxclkSpreadEnabled; + uint8_t PllGfxclkSpreadPercent; + uint16_t PllGfxclkSpreadFreq; + + uint8_t UclkSpreadEnabled; + uint8_t UclkSpreadPercent; + uint16_t UclkSpreadFreq; + + uint8_t SocclkSpreadEnabled; + uint8_t SocclkSpreadPercent; + uint16_t SocclkSpreadFreq; + + uint8_t AcgGfxclkSpreadEnabled; + uint8_t AcgGfxclkSpreadPercent; + uint16_t AcgGfxclkSpreadFreq; + + uint8_t Vr2_I2C_address; + uint8_t padding_vr2[3]; + + uint32_t BoardReserved[9]; + + + uint32_t MmHubPadding[7]; + +} PPTable_t; + +typedef struct { + + uint16_t GfxclkAverageLpfTau; + uint16_t SocclkAverageLpfTau; + uint16_t UclkAverageLpfTau; + uint16_t GfxActivityLpfTau; + uint16_t UclkActivityLpfTau; + + + uint32_t MmHubPadding[7]; +} DriverSmuConfig_t; + +typedef struct { + + uint16_t GfxclkFmin; + uint16_t GfxclkFmax; + uint16_t GfxclkFreq1; + uint16_t GfxclkOffsetVolt1; + uint16_t GfxclkFreq2; + uint16_t GfxclkOffsetVolt2; + uint16_t GfxclkFreq3; + uint16_t GfxclkOffsetVolt3; + uint16_t UclkFmax; + int16_t OverDrivePct; + uint16_t FanMaximumRpm; + uint16_t FanMinimumPwm; + uint16_t FanTargetTemperature; + uint16_t MaxOpTemp; + +} OverDriveTable_t; + +typedef struct { + uint16_t CurrClock[PPCLK_COUNT]; + uint16_t AverageGfxclkFrequency; + uint16_t AverageSocclkFrequency; + uint16_t AverageUclkFrequency ; + uint16_t AverageGfxActivity ; + uint16_t AverageUclkActivity ; + uint8_t CurrSocVoltageOffset ; + uint8_t CurrGfxVoltageOffset ; + uint8_t CurrMemVidOffset ; + uint8_t Padding8 ; + uint16_t CurrSocketPower ; + uint16_t TemperatureEdge ; + uint16_t TemperatureHotspot ; + uint16_t TemperatureHBM ; + uint16_t TemperatureVrGfx ; + uint16_t TemperatureVrMem ; + uint16_t TemperatureLiquid ; + uint16_t TemperaturePlx ; + uint32_t ThrottlerStatus ; + + uint8_t LinkDpmLevel; + uint8_t Padding[3]; + + + uint32_t MmHubPadding[7]; +} SmuMetrics_t; + +typedef struct { + uint16_t MinClock; + uint16_t MaxClock; + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Padding[3]; +} WatermarkRowGeneric_t; + +#define NUM_WM_RANGES 4 + +typedef enum { + WM_SOCCLK = 0, + WM_DCEFCLK, + WM_COUNT_PP, +} WM_CLOCK_e; + +typedef struct { + + WatermarkRowGeneric_t WatermarkRow[WM_COUNT_PP][NUM_WM_RANGES]; + + uint32_t MmHubPadding[7]; +} Watermarks_t; + +typedef struct { + uint16_t avgPsmCount[30]; + uint16_t minPsmCount[30]; + float avgPsmVoltage[30]; + float minPsmVoltage[30]; + + uint32_t MmHubPadding[7]; +} AvfsDebugTable_t; + +typedef struct { + uint8_t AvfsEn; + uint8_t AvfsVersion; + uint8_t OverrideVFT; + uint8_t OverrideAvfsGb; + + uint8_t OverrideTemperatures; + uint8_t OverrideVInversion; + uint8_t OverrideP2V; + uint8_t OverrideP2VCharzFreq; + + int32_t VFT0_m1; + int32_t VFT0_m2; + int32_t VFT0_b; + + int32_t VFT1_m1; + int32_t VFT1_m2; + int32_t VFT1_b; + + int32_t VFT2_m1; + int32_t VFT2_m2; + int32_t VFT2_b; + + int32_t AvfsGb0_m1; + int32_t AvfsGb0_m2; + int32_t AvfsGb0_b; + + int32_t AcBtcGb_m1; + int32_t AcBtcGb_m2; + int32_t AcBtcGb_b; + + uint32_t AvfsTempCold; + uint32_t AvfsTempMid; + uint32_t AvfsTempHot; + + uint32_t GfxVInversion; + uint32_t SocVInversion; + + int32_t P2V_m1; + int32_t P2V_m2; + int32_t P2V_b; + + uint32_t P2VCharzFreq; + + uint32_t EnabledAvfsModules; + + uint32_t MmHubPadding[7]; +} AvfsFuseOverride_t; + +typedef struct { + + uint8_t Gfx_ActiveHystLimit; + uint8_t Gfx_IdleHystLimit; + uint8_t Gfx_FPS; + uint8_t Gfx_MinActiveFreqType; + uint8_t Gfx_BoosterFreqType; + uint8_t Gfx_UseRlcBusy; + uint16_t Gfx_MinActiveFreq; + uint16_t Gfx_BoosterFreq; + uint16_t Gfx_PD_Data_time_constant; + uint32_t Gfx_PD_Data_limit_a; + uint32_t Gfx_PD_Data_limit_b; + uint32_t Gfx_PD_Data_limit_c; + uint32_t Gfx_PD_Data_error_coeff; + uint32_t Gfx_PD_Data_error_rate_coeff; + + uint8_t Soc_ActiveHystLimit; + uint8_t Soc_IdleHystLimit; + uint8_t Soc_FPS; + uint8_t Soc_MinActiveFreqType; + uint8_t Soc_BoosterFreqType; + uint8_t Soc_UseRlcBusy; + uint16_t Soc_MinActiveFreq; + uint16_t Soc_BoosterFreq; + uint16_t Soc_PD_Data_time_constant; + uint32_t Soc_PD_Data_limit_a; + uint32_t Soc_PD_Data_limit_b; + uint32_t Soc_PD_Data_limit_c; + uint32_t Soc_PD_Data_error_coeff; + uint32_t Soc_PD_Data_error_rate_coeff; + + uint8_t Mem_ActiveHystLimit; + uint8_t Mem_IdleHystLimit; + uint8_t Mem_FPS; + uint8_t Mem_MinActiveFreqType; + uint8_t Mem_BoosterFreqType; + uint8_t Mem_UseRlcBusy; + uint16_t Mem_MinActiveFreq; + uint16_t Mem_BoosterFreq; + uint16_t Mem_PD_Data_time_constant; + uint32_t Mem_PD_Data_limit_a; + uint32_t Mem_PD_Data_limit_b; + uint32_t Mem_PD_Data_limit_c; + uint32_t Mem_PD_Data_error_coeff; + uint32_t Mem_PD_Data_error_rate_coeff; + +} DpmActivityMonitorCoeffInt_t; + + + + +#define TABLE_PPTABLE 0 +#define TABLE_WATERMARKS 1 +#define TABLE_AVFS 2 +#define TABLE_AVFS_PSM_DEBUG 3 +#define TABLE_AVFS_FUSE_OVERRIDE 4 +#define TABLE_PMSTATUSLOG 5 +#define TABLE_SMU_METRICS 6 +#define TABLE_DRIVER_SMU_CONFIG 7 +#define TABLE_ACTIVITY_MONITOR_COEFF 8 +#define TABLE_OVERDRIVE 9 +#define TABLE_COUNT 10 + + +#define UCLK_SWITCH_SLOW 0 +#define UCLK_SWITCH_FAST 1 + + +#define SQ_Enable_MASK 0x1 +#define SQ_IR_MASK 0x2 +#define SQ_PCC_MASK 0x4 +#define SQ_EDC_MASK 0x8 + +#define TCP_Enable_MASK 0x100 +#define TCP_IR_MASK 0x200 +#define TCP_PCC_MASK 0x400 +#define TCP_EDC_MASK 0x800 + +#define TD_Enable_MASK 0x10000 +#define TD_IR_MASK 0x20000 +#define TD_PCC_MASK 0x40000 +#define TD_EDC_MASK 0x80000 + +#define DB_Enable_MASK 0x1000000 +#define DB_IR_MASK 0x2000000 +#define DB_PCC_MASK 0x4000000 +#define DB_EDC_MASK 0x8000000 + +#define SQ_Enable_SHIFT 0 +#define SQ_IR_SHIFT 1 +#define SQ_PCC_SHIFT 2 +#define SQ_EDC_SHIFT 3 + +#define TCP_Enable_SHIFT 8 +#define TCP_IR_SHIFT 9 +#define TCP_PCC_SHIFT 10 +#define TCP_EDC_SHIFT 11 + +#define TD_Enable_SHIFT 16 +#define TD_IR_SHIFT 17 +#define TD_PCC_SHIFT 18 +#define TD_EDC_SHIFT 19 + +#define DB_Enable_SHIFT 24 +#define DB_IR_SHIFT 25 +#define DB_PCC_SHIFT 26 +#define DB_EDC_SHIFT 27 + +#define REMOVE_FMAX_MARGIN_BIT 0x0 +#define REMOVE_DCTOL_MARGIN_BIT 0x1 +#define REMOVE_PLATFORM_MARGIN_BIT 0x2 + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h new file mode 100644 index 000000000000..f985c78d746a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/vega12_ppsmc.h @@ -0,0 +1,123 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef VEGA12_PP_SMC_H +#define VEGA12_PP_SMC_H + +#pragma pack(push, 1) + +#define SMU_UCODE_VERSION 0x00270a00 + +/* SMU Response Codes: */ +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 +#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 +#define PPSMC_MSG_EnableAllSmuFeatures 0x6 +#define PPSMC_MSG_DisableAllSmuFeatures 0x7 +#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 +#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 +#define PPSMC_MSG_DisableSmuFeaturesLow 0xA +#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB +#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC +#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD +#define PPSMC_MSG_SetWorkloadMask 0xE +#define PPSMC_MSG_SetPptLimit 0xF +#define PPSMC_MSG_SetDriverDramAddrHigh 0x10 +#define PPSMC_MSG_SetDriverDramAddrLow 0x11 +#define PPSMC_MSG_SetToolsDramAddrHigh 0x12 +#define PPSMC_MSG_SetToolsDramAddrLow 0x13 +#define PPSMC_MSG_TransferTableSmu2Dram 0x14 +#define PPSMC_MSG_TransferTableDram2Smu 0x15 +#define PPSMC_MSG_UseDefaultPPTable 0x16 +#define PPSMC_MSG_UseBackupPPTable 0x17 +#define PPSMC_MSG_RunBtc 0x18 +#define PPSMC_MSG_RequestI2CBus 0x19 +#define PPSMC_MSG_ReleaseI2CBus 0x1A +#define PPSMC_MSG_SetFloorSocVoltage 0x21 +#define PPSMC_MSG_SoftReset 0x22 +#define PPSMC_MSG_StartBacoMonitor 0x23 +#define PPSMC_MSG_CancelBacoMonitor 0x24 +#define PPSMC_MSG_EnterBaco 0x25 +#define PPSMC_MSG_SetSoftMinByFreq 0x26 +#define PPSMC_MSG_SetSoftMaxByFreq 0x27 +#define PPSMC_MSG_SetHardMinByFreq 0x28 +#define PPSMC_MSG_SetHardMaxByFreq 0x29 +#define PPSMC_MSG_GetMinDpmFreq 0x2A +#define PPSMC_MSG_GetMaxDpmFreq 0x2B +#define PPSMC_MSG_GetDpmFreqByIndex 0x2C +#define PPSMC_MSG_GetDpmClockFreq 0x2D +#define PPSMC_MSG_GetSsVoltageByDpm 0x2E +#define PPSMC_MSG_SetMemoryChannelConfig 0x2F +#define PPSMC_MSG_SetGeminiMode 0x30 +#define PPSMC_MSG_SetGeminiApertureHigh 0x31 +#define PPSMC_MSG_SetGeminiApertureLow 0x32 +#define PPSMC_MSG_SetMinLinkDpmByIndex 0x33 +#define PPSMC_MSG_OverridePcieParameters 0x34 +#define PPSMC_MSG_OverDriveSetPercentage 0x35 +#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x36 +#define PPSMC_MSG_ReenableAcDcInterrupt 0x37 +#define PPSMC_MSG_NotifyPowerSource 0x38 +#define PPSMC_MSG_SetUclkFastSwitch 0x39 +#define PPSMC_MSG_SetUclkDownHyst 0x3A +#define PPSMC_MSG_GfxDeviceDriverReset 0x3B +#define PPSMC_MSG_GetCurrentRpm 0x3C +#define PPSMC_MSG_SetVideoFps 0x3D +#define PPSMC_MSG_SetTjMax 0x3E +#define PPSMC_MSG_SetFanTemperatureTarget 0x3F +#define PPSMC_MSG_PrepareMp1ForUnload 0x40 +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x41 +#define PPSMC_MSG_DramLogSetDramAddrLow 0x42 +#define PPSMC_MSG_DramLogSetDramSize 0x43 +#define PPSMC_MSG_SetFanMaxRpm 0x44 +#define PPSMC_MSG_SetFanMinPwm 0x45 +#define PPSMC_MSG_ConfigureGfxDidt 0x46 +#define PPSMC_MSG_NumOfDisplays 0x47 +#define PPSMC_MSG_RemoveMargins 0x48 +#define PPSMC_MSG_ReadSerialNumTop32 0x49 +#define PPSMC_MSG_ReadSerialNumBottom32 0x4A +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x4B +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x4C +#define PPSMC_MSG_RunAcgBtc 0x4D +#define PPSMC_MSG_InitializeAcg 0x4E +#define PPSMC_MSG_EnableAcgBtcTestMode 0x4F +#define PPSMC_MSG_EnableAcgSpreadSpectrum 0x50 +#define PPSMC_MSG_AllowGfxOff 0x51 +#define PPSMC_MSG_DisallowGfxOff 0x52 +#define PPSMC_MSG_GetPptLimit 0x53 +#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x54 +#define PPSMC_Message_Count 0x56 + +typedef uint16_t PPSMC_Result; +typedef int PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h b/drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h new file mode 100644 index 000000000000..0c66f0fe1aaf --- /dev/null +++ b/drivers/gpu/drm/amd/pm/inc/vega20_ppsmc.h @@ -0,0 +1,131 @@ +/* + * Copyright 2018 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 VEGA20_PP_SMC_H +#define VEGA20_PP_SMC_H + +#pragma pack(push, 1) + +// SMU Response Codes: +#define PPSMC_Result_OK 0x1 +#define PPSMC_Result_Failed 0xFF +#define PPSMC_Result_UnknownCmd 0xFE +#define PPSMC_Result_CmdRejectedPrereq 0xFD +#define PPSMC_Result_CmdRejectedBusy 0xFC + +// Message Definitions: +#define PPSMC_MSG_TestMessage 0x1 +#define PPSMC_MSG_GetSmuVersion 0x2 +#define PPSMC_MSG_GetDriverIfVersion 0x3 +#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 +#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 +#define PPSMC_MSG_EnableAllSmuFeatures 0x6 +#define PPSMC_MSG_DisableAllSmuFeatures 0x7 +#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 +#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 +#define PPSMC_MSG_DisableSmuFeaturesLow 0xA +#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB +#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC +#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD +#define PPSMC_MSG_SetWorkloadMask 0xE +#define PPSMC_MSG_SetPptLimit 0xF +#define PPSMC_MSG_SetDriverDramAddrHigh 0x10 +#define PPSMC_MSG_SetDriverDramAddrLow 0x11 +#define PPSMC_MSG_SetToolsDramAddrHigh 0x12 +#define PPSMC_MSG_SetToolsDramAddrLow 0x13 +#define PPSMC_MSG_TransferTableSmu2Dram 0x14 +#define PPSMC_MSG_TransferTableDram2Smu 0x15 +#define PPSMC_MSG_UseDefaultPPTable 0x16 +#define PPSMC_MSG_UseBackupPPTable 0x17 +#define PPSMC_MSG_RunBtc 0x18 +#define PPSMC_MSG_RequestI2CBus 0x19 +#define PPSMC_MSG_ReleaseI2CBus 0x1A +#define PPSMC_MSG_SetFloorSocVoltage 0x21 +#define PPSMC_MSG_SoftReset 0x22 +#define PPSMC_MSG_StartBacoMonitor 0x23 +#define PPSMC_MSG_CancelBacoMonitor 0x24 +#define PPSMC_MSG_EnterBaco 0x25 +#define PPSMC_MSG_SetSoftMinByFreq 0x26 +#define PPSMC_MSG_SetSoftMaxByFreq 0x27 +#define PPSMC_MSG_SetHardMinByFreq 0x28 +#define PPSMC_MSG_SetHardMaxByFreq 0x29 +#define PPSMC_MSG_GetMinDpmFreq 0x2A +#define PPSMC_MSG_GetMaxDpmFreq 0x2B +#define PPSMC_MSG_GetDpmFreqByIndex 0x2C +#define PPSMC_MSG_GetDpmClockFreq 0x2D +#define PPSMC_MSG_GetSsVoltageByDpm 0x2E +#define PPSMC_MSG_SetMemoryChannelConfig 0x2F +#define PPSMC_MSG_SetGeminiMode 0x30 +#define PPSMC_MSG_SetGeminiApertureHigh 0x31 +#define PPSMC_MSG_SetGeminiApertureLow 0x32 +#define PPSMC_MSG_SetMinLinkDpmByIndex 0x33 +#define PPSMC_MSG_OverridePcieParameters 0x34 +#define PPSMC_MSG_OverDriveSetPercentage 0x35 +#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x36 +#define PPSMC_MSG_ReenableAcDcInterrupt 0x37 +#define PPSMC_MSG_NotifyPowerSource 0x38 +#define PPSMC_MSG_SetUclkFastSwitch 0x39 +#define PPSMC_MSG_SetUclkDownHyst 0x3A +//#define PPSMC_MSG_GfxDeviceDriverReset 0x3B +#define PPSMC_MSG_GetCurrentRpm 0x3C +#define PPSMC_MSG_SetVideoFps 0x3D +#define PPSMC_MSG_SetTjMax 0x3E +#define PPSMC_MSG_SetFanTemperatureTarget 0x3F +#define PPSMC_MSG_PrepareMp1ForUnload 0x40 +#define PPSMC_MSG_DramLogSetDramAddrHigh 0x41 +#define PPSMC_MSG_DramLogSetDramAddrLow 0x42 +#define PPSMC_MSG_DramLogSetDramSize 0x43 +#define PPSMC_MSG_SetFanMaxRpm 0x44 +#define PPSMC_MSG_SetFanMinPwm 0x45 +#define PPSMC_MSG_ConfigureGfxDidt 0x46 +#define PPSMC_MSG_NumOfDisplays 0x47 +#define PPSMC_MSG_RemoveMargins 0x48 +#define PPSMC_MSG_ReadSerialNumTop32 0x49 +#define PPSMC_MSG_ReadSerialNumBottom32 0x4A +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x4B +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x4C +#define PPSMC_MSG_WaflTest 0x4D +#define PPSMC_MSG_SetFclkGfxClkRatio 0x4E +// Unused ID 0x4F to 0x50 +#define PPSMC_MSG_AllowGfxOff 0x51 +#define PPSMC_MSG_DisallowGfxOff 0x52 +#define PPSMC_MSG_GetPptLimit 0x53 +#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x54 +#define PPSMC_MSG_GetDebugData 0x55 +#define PPSMC_MSG_SetXgmiMode 0x56 +#define PPSMC_MSG_RunAfllBtc 0x57 +#define PPSMC_MSG_ExitBaco 0x58 +#define PPSMC_MSG_PrepareMp1ForReset 0x59 +#define PPSMC_MSG_PrepareMp1ForShutdown 0x5A +#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x5D +#define PPSMC_MSG_GetAVFSVoltageByDpm 0x5F +#define PPSMC_MSG_BacoWorkAroundFlushVDCI 0x60 +#define PPSMC_MSG_DFCstateControl 0x63 +#define PPSMC_Message_Count 0x64 + +typedef uint32_t PPSMC_Result; +typedef uint32_t PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/Makefile b/drivers/gpu/drm/amd/pm/powerplay/Makefile new file mode 100644 index 000000000000..0fb114adc79f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/Makefile @@ -0,0 +1,39 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +AMD_PP_PATH = ../pm/powerplay + +PP_LIBS = smumgr hwmgr + +AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/powerplay/,$(PP_LIBS))) + +include $(AMD_POWERPLAY) + +POWER_MGR-y = amd_powerplay.o + +POWER_MGR-$(CONFIG_DRM_AMDGPU_CIK)+= kv_dpm.o kv_smc.o + +POWER_MGR-$(CONFIG_DRM_AMDGPU_SI)+= si_dpm.o si_smc.o + +AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR-y)) + +AMD_POWERPLAY_FILES += $(AMD_PP_POWER) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c new file mode 100644 index 000000000000..a6321f2063c1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -0,0 +1,1680 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include +#include +#include "amd_shared.h" +#include "amd_powerplay.h" +#include "power_state.h" +#include "amdgpu.h" +#include "hwmgr.h" + + +static const struct amd_pm_funcs pp_dpm_funcs; + +static int amd_powerplay_create(struct amdgpu_device *adev) +{ + struct pp_hwmgr *hwmgr; + + if (adev == NULL) + return -EINVAL; + + hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL); + if (hwmgr == NULL) + return -ENOMEM; + + hwmgr->adev = adev; + hwmgr->not_vf = !amdgpu_sriov_vf(adev); + hwmgr->device = amdgpu_cgs_create_device(adev); + mutex_init(&hwmgr->smu_lock); + mutex_init(&hwmgr->msg_lock); + hwmgr->chip_family = adev->family; + hwmgr->chip_id = adev->asic_type; + hwmgr->feature_mask = adev->pm.pp_feature; + hwmgr->display_config = &adev->pm.pm_display_cfg; + adev->powerplay.pp_handle = hwmgr; + adev->powerplay.pp_funcs = &pp_dpm_funcs; + return 0; +} + + +static void amd_powerplay_destroy(struct amdgpu_device *adev) +{ + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + mutex_destroy(&hwmgr->msg_lock); + + kfree(hwmgr->hardcode_pp_table); + hwmgr->hardcode_pp_table = NULL; + + kfree(hwmgr); + hwmgr = NULL; +} + +static int pp_early_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = handle; + + ret = amd_powerplay_create(adev); + + if (ret != 0) + return ret; + + ret = hwmgr_early_init(adev->powerplay.pp_handle); + if (ret) + return -EINVAL; + + return 0; +} + +static int pp_sw_init(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + int ret = 0; + + ret = hwmgr_sw_init(hwmgr); + + pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully"); + + return ret; +} + +static int pp_sw_fini(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + hwmgr_sw_fini(hwmgr); + + release_firmware(adev->pm.fw); + adev->pm.fw = NULL; + + return 0; +} + +static int pp_hw_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + ret = hwmgr_hw_init(hwmgr); + + if (ret) + pr_err("powerplay hw init failed\n"); + + return ret; +} + +static int pp_hw_fini(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + hwmgr_hw_fini(hwmgr); + + return 0; +} + +static void pp_reserve_vram_for_smu(struct amdgpu_device *adev) +{ + int r = -EINVAL; + void *cpu_ptr = NULL; + uint64_t gpu_addr; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, + &adev->pm.smu_prv_buffer, + &gpu_addr, + &cpu_ptr)) { + DRM_ERROR("amdgpu: failed to create smu prv buffer\n"); + return; + } + + if (hwmgr->hwmgr_func->notify_cac_buffer_info) + r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr, + lower_32_bits((unsigned long)cpu_ptr), + upper_32_bits((unsigned long)cpu_ptr), + lower_32_bits(gpu_addr), + upper_32_bits(gpu_addr), + adev->pm.smu_prv_buffer_size); + + if (r) { + amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL); + adev->pm.smu_prv_buffer = NULL; + DRM_ERROR("amdgpu: failed to notify SMU buffer address\n"); + } +} + +static int pp_late_init(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + if (hwmgr && hwmgr->pm_en) { + mutex_lock(&hwmgr->smu_lock); + hwmgr_handle_task(hwmgr, + AMD_PP_TASK_COMPLETE_INIT, NULL); + mutex_unlock(&hwmgr->smu_lock); + } + if (adev->pm.smu_prv_buffer_size != 0) + pp_reserve_vram_for_smu(adev); + + return 0; +} + +static void pp_late_fini(void *handle) +{ + struct amdgpu_device *adev = handle; + + if (adev->pm.smu_prv_buffer) + amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL); + amd_powerplay_destroy(adev); +} + + +static bool pp_is_idle(void *handle) +{ + return false; +} + +static int pp_wait_for_idle(void *handle) +{ + return 0; +} + +static int pp_sw_reset(void *handle) +{ + return 0; +} + +static int pp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static int pp_suspend(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + return hwmgr_suspend(hwmgr); +} + +static int pp_resume(void *handle) +{ + struct amdgpu_device *adev = handle; + struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; + + return hwmgr_resume(hwmgr); +} + +static int pp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static const struct amd_ip_funcs pp_ip_funcs = { + .name = "powerplay", + .early_init = pp_early_init, + .late_init = pp_late_init, + .sw_init = pp_sw_init, + .sw_fini = pp_sw_fini, + .hw_init = pp_hw_init, + .hw_fini = pp_hw_fini, + .late_fini = pp_late_fini, + .suspend = pp_suspend, + .resume = pp_resume, + .is_idle = pp_is_idle, + .wait_for_idle = pp_wait_for_idle, + .soft_reset = pp_sw_reset, + .set_clockgating_state = pp_set_clockgating_state, + .set_powergating_state = pp_set_powergating_state, +}; + +const struct amdgpu_ip_block_version pp_smu_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &pp_ip_funcs, +}; + +/* This interface only be supported On Vi, + * because only smu7/8 can help to load gfx/sdma fw, + * smu need to be enabled before load other ip's fw. + * so call start smu to load smu7 fw and other ip's fw + */ +static int pp_dpm_load_fw(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu) + return -EINVAL; + + if (hwmgr->smumgr_funcs->start_smu(hwmgr)) { + pr_err("fw load failed\n"); + return -EINVAL; + } + + return 0; +} + +static int pp_dpm_fw_loading_complete(void *handle) +{ + return 0; +} + +static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id); +} + +static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level *level) +{ + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + if (!(hwmgr->dpm_level & profile_mode_mask)) { + /* enter umd pstate, save current level, disable gfx cg*/ + if (*level & profile_mode_mask) { + hwmgr->saved_dpm_level = hwmgr->dpm_level; + hwmgr->en_umd_pstate = true; + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ + if (!(*level & profile_mode_mask)) { + if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + *level = hwmgr->saved_dpm_level; + hwmgr->en_umd_pstate = false; + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + } +} + +static int pp_dpm_force_performance_level(void *handle, + enum amd_dpm_forced_level level) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (level == hwmgr->dpm_level) + return 0; + + mutex_lock(&hwmgr->smu_lock); + pp_dpm_en_umd_pstate(hwmgr, &level); + hwmgr->request_dpm_level = level; + hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static enum amd_dpm_forced_level pp_dpm_get_performance_level( + void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + enum amd_dpm_forced_level level; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + level = hwmgr->dpm_level; + mutex_unlock(&hwmgr->smu_lock); + return level; +} + +static uint32_t pp_dpm_get_sclk(void *handle, bool low) +{ + struct pp_hwmgr *hwmgr = handle; + uint32_t clk = 0; + + if (!hwmgr || !hwmgr->pm_en) + return 0; + + if (hwmgr->hwmgr_func->get_sclk == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low); + mutex_unlock(&hwmgr->smu_lock); + return clk; +} + +static uint32_t pp_dpm_get_mclk(void *handle, bool low) +{ + struct pp_hwmgr *hwmgr = handle; + uint32_t clk = 0; + + if (!hwmgr || !hwmgr->pm_en) + return 0; + + if (hwmgr->hwmgr_func->get_mclk == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low); + mutex_unlock(&hwmgr->smu_lock); + return clk; +} + +static void pp_dpm_powergate_vce(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return; + + if (hwmgr->hwmgr_func->powergate_vce == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return; + } + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); + mutex_unlock(&hwmgr->smu_lock); +} + +static void pp_dpm_powergate_uvd(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return; + + if (hwmgr->hwmgr_func->powergate_uvd == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return; + } + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); + mutex_unlock(&hwmgr->smu_lock); +} + +static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, + enum amd_pm_state_type *user_state) +{ + int ret = 0; + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr_handle_task(hwmgr, task_id, user_state); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + struct pp_power_state *state; + enum amd_pm_state_type pm_type; + + if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + state = hwmgr->current_ps; + + switch (state->classification.ui_label) { + case PP_StateUILabel_Battery: + pm_type = POWER_STATE_TYPE_BATTERY; + break; + case PP_StateUILabel_Balanced: + pm_type = POWER_STATE_TYPE_BALANCED; + break; + case PP_StateUILabel_Performance: + pm_type = POWER_STATE_TYPE_PERFORMANCE; + break; + default: + if (state->classification.flags & PP_StateClassificationFlag_Boot) + pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; + else + pm_type = POWER_STATE_TYPE_DEFAULT; + break; + } + mutex_unlock(&hwmgr->smu_lock); + + return pm_type; +} + +static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return; + + if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return; + } + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); + mutex_unlock(&hwmgr->smu_lock); +} + +static uint32_t pp_dpm_get_fan_control_mode(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + uint32_t mode = 0; + + if (!hwmgr || !hwmgr->pm_en) + return 0; + + if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); + mutex_unlock(&hwmgr->smu_lock); + return mode; +} + +static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_get_pp_num_states(void *handle, + struct pp_states_info *data) +{ + struct pp_hwmgr *hwmgr = handle; + int i; + + memset(data, 0, sizeof(*data)); + + if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + data->nums = hwmgr->num_ps; + + for (i = 0; i < hwmgr->num_ps; i++) { + struct pp_power_state *state = (struct pp_power_state *) + ((unsigned long)hwmgr->ps + i * hwmgr->ps_size); + switch (state->classification.ui_label) { + case PP_StateUILabel_Battery: + data->states[i] = POWER_STATE_TYPE_BATTERY; + break; + case PP_StateUILabel_Balanced: + data->states[i] = POWER_STATE_TYPE_BALANCED; + break; + case PP_StateUILabel_Performance: + data->states[i] = POWER_STATE_TYPE_PERFORMANCE; + break; + default: + if (state->classification.flags & PP_StateClassificationFlag_Boot) + data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT; + else + data->states[i] = POWER_STATE_TYPE_DEFAULT; + } + } + mutex_unlock(&hwmgr->smu_lock); + return 0; +} + +static int pp_dpm_get_pp_table(void *handle, char **table) +{ + struct pp_hwmgr *hwmgr = handle; + int size = 0; + + if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + *table = (char *)hwmgr->soft_pp_table; + size = hwmgr->soft_pp_table_size; + mutex_unlock(&hwmgr->smu_lock); + return size; +} + +static int amd_powerplay_reset(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + int ret; + + ret = hwmgr_hw_fini(hwmgr); + if (ret) + return ret; + + ret = hwmgr_hw_init(hwmgr); + if (ret) + return ret; + + return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL); +} + +static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = -ENOMEM; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + if (!hwmgr->hardcode_pp_table) { + hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table, + hwmgr->soft_pp_table_size, + GFP_KERNEL); + if (!hwmgr->hardcode_pp_table) + goto err; + } + + memcpy(hwmgr->hardcode_pp_table, buf, size); + + hwmgr->soft_pp_table = hwmgr->hardcode_pp_table; + + ret = amd_powerplay_reset(handle); + if (ret) + goto err; + + if (hwmgr->hwmgr_func->avfs_control) { + ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false); + if (ret) + goto err; + } + mutex_unlock(&hwmgr->smu_lock); + return 0; +err: + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_force_clock_level(void *handle, + enum pp_clock_type type, uint32_t mask) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->force_clock_level == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + pr_debug("force clock level is for dpm manual mode only.\n"); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_print_clock_levels(void *handle, + enum pp_clock_type type, char *buf) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->print_clock_levels == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_get_sclk_od(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_sclk_od == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_set_sclk_od(void *handle, uint32_t value) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_sclk_od == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_get_mclk_od(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_mclk_od == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_set_mclk_od(void *handle, uint32_t value) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_mclk_od == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_read_sensor(void *handle, int idx, + void *value, int *size) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en || !value) + return -EINVAL; + + switch (idx) { + case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK: + *((uint32_t *)value) = hwmgr->pstate_sclk; + return 0; + case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK: + *((uint32_t *)value) = hwmgr->pstate_mclk; + return 0; + case AMDGPU_PP_SENSOR_MIN_FAN_RPM: + *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM; + return 0; + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM; + return 0; + default: + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size); + mutex_unlock(&hwmgr->smu_lock); + return ret; + } +} + +static struct amd_vce_state* +pp_dpm_get_vce_clock_state(void *handle, unsigned idx) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return NULL; + + if (idx < hwmgr->num_vce_state_tables) + return &hwmgr->vce_states[idx]; + return NULL; +} + +static int pp_get_power_profile_mode(void *handle, char *buf) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en || !buf) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return snprintf(buf, PAGE_SIZE, "\n"); + } + + return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf); +} + +static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = -EINVAL; + + if (!hwmgr || !hwmgr->pm_en) + return ret; + + if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return ret; + } + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + pr_debug("power profile setting is for manual dpm mode only.\n"); + return ret; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size); +} + +static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en) + return 0; + + if (hwmgr->hwmgr_func->set_mp1_state) + return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state); + + return 0; +} + +static int pp_dpm_switch_power_profile(void *handle, + enum PP_SMC_POWER_PROFILE type, bool en) +{ + struct pp_hwmgr *hwmgr = handle; + long workload; + uint32_t index; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + if (!en) { + hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]); + index = fls(hwmgr->workload_mask); + index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; + workload = hwmgr->workload_setting[index]; + } else { + hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]); + index = fls(hwmgr->workload_mask); + index = index <= Workload_Policy_Max ? index - 1 : 0; + workload = hwmgr->workload_setting[index]; + } + + if (type == PP_SMC_POWER_PROFILE_COMPUTE && + hwmgr->hwmgr_func->disable_power_features_for_compute_performance) { + if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en)) { + mutex_unlock(&hwmgr->smu_lock); + return -EINVAL; + } + } + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) + hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_power_limit(void *handle, uint32_t limit) +{ + struct pp_hwmgr *hwmgr = handle; + uint32_t max_power_limit; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_power_limit == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + if (limit == 0) + limit = hwmgr->default_power_limit; + + max_power_limit = hwmgr->default_power_limit; + if (hwmgr->od_enabled) { + max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); + max_power_limit /= 100; + } + + if (limit > max_power_limit) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_power_limit(hwmgr, limit); + hwmgr->power_limit = limit; + mutex_unlock(&hwmgr->smu_lock); + return 0; +} + +static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en ||!limit) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + if (default_limit) { + *limit = hwmgr->default_power_limit; + if (hwmgr->od_enabled) { + *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); + *limit /= 100; + } + } + else + *limit = hwmgr->power_limit; + + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_display_configuration_change(void *handle, + const struct amd_pp_display_configuration *display_config) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + phm_store_dal_configuration_data(hwmgr, display_config); + mutex_unlock(&hwmgr->smu_lock); + return 0; +} + +static int pp_get_display_power_level(void *handle, + struct amd_pp_simple_clock_info *output) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en ||!output) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_get_dal_power_level(hwmgr, output); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_get_current_clocks(void *handle, + struct amd_pp_clock_info *clocks) +{ + struct amd_pp_simple_clock_info simple_clocks = { 0 }; + struct pp_clock_info hw_clocks; + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + phm_get_dal_power_level(hwmgr, &simple_clocks); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) + ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, + &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment); + else + ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, + &hw_clocks, PHM_PerformanceLevelDesignation_Activity); + + if (ret) { + pr_debug("Error in phm_get_clock_info \n"); + mutex_unlock(&hwmgr->smu_lock); + return -EINVAL; + } + + clocks->min_engine_clock = hw_clocks.min_eng_clk; + clocks->max_engine_clock = hw_clocks.max_eng_clk; + clocks->min_memory_clock = hw_clocks.min_mem_clk; + clocks->max_memory_clock = hw_clocks.max_mem_clk; + clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth; + clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth; + + clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; + clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; + + if (simple_clocks.level == 0) + clocks->max_clocks_state = PP_DAL_POWERLEVEL_7; + else + clocks->max_clocks_state = simple_clocks.level; + + if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) { + clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; + clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; + } + mutex_unlock(&hwmgr->smu_lock); + return 0; +} + +static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (clocks == NULL) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_get_clock_by_type(hwmgr, type, clocks); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_get_clock_by_type_with_latency(void *handle, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en ||!clocks) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks); + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_get_clock_by_type_with_voltage(void *handle, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en ||!clocks) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + + ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks); + + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_set_watermarks_for_clocks_ranges(void *handle, + void *clock_ranges) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en || !clock_ranges) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_set_watermarks_for_clocks_ranges(hwmgr, + clock_ranges); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_display_clock_voltage_request(void *handle, + struct pp_display_clock_request *clock) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en ||!clock) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_display_clock_voltage_request(hwmgr, clock); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_get_display_mode_validation_clocks(void *handle, + struct amd_pp_simple_clock_info *clocks) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en ||!clocks) + return -EINVAL; + + clocks->level = PP_DAL_POWERLEVEL_7; + + mutex_lock(&hwmgr->smu_lock); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) + ret = phm_get_max_high_clocks(hwmgr, clocks); + + mutex_unlock(&hwmgr->smu_lock); + return ret; +} + +static int pp_dpm_powergate_mmhub(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->powergate_mmhub == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->powergate_mmhub(hwmgr); +} + +static int pp_dpm_powergate_gfx(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return 0; + + if (hwmgr->hwmgr_func->powergate_gfx == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate); +} + +static void pp_dpm_powergate_acp(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return; + + if (hwmgr->hwmgr_func->powergate_acp == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return; + } + + hwmgr->hwmgr_func->powergate_acp(hwmgr, gate); +} + +static void pp_dpm_powergate_sdma(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return; + + if (hwmgr->hwmgr_func->powergate_sdma == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return; + } + + hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate); +} + +static int pp_set_powergating_by_smu(void *handle, + uint32_t block_type, bool gate) +{ + int ret = 0; + + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: + case AMD_IP_BLOCK_TYPE_VCN: + pp_dpm_powergate_uvd(handle, gate); + break; + case AMD_IP_BLOCK_TYPE_VCE: + pp_dpm_powergate_vce(handle, gate); + break; + case AMD_IP_BLOCK_TYPE_GMC: + pp_dpm_powergate_mmhub(handle); + break; + case AMD_IP_BLOCK_TYPE_GFX: + ret = pp_dpm_powergate_gfx(handle, gate); + break; + case AMD_IP_BLOCK_TYPE_ACP: + pp_dpm_powergate_acp(handle, gate); + break; + case AMD_IP_BLOCK_TYPE_SDMA: + pp_dpm_powergate_sdma(handle, gate); + break; + default: + break; + } + return ret; +} + +static int pp_notify_smu_enable_pwe(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->smus_notify_pwe(hwmgr); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_enable_mgpu_fan_boost(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || + hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) { + pr_debug("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) { + pr_debug("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) { + pr_debug("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_active_display_count(void *handle, uint32_t count) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + mutex_lock(&hwmgr->smu_lock); + ret = phm_set_active_display_count(hwmgr, count); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_get_asic_baco_capability(void *handle, bool *cap) +{ + struct pp_hwmgr *hwmgr = handle; + + *cap = false; + if (!hwmgr) + return -EINVAL; + + if (!(hwmgr->not_vf && amdgpu_dpm) || + !hwmgr->hwmgr_func->get_asic_baco_capability) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_get_asic_baco_state(void *handle, int *state) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_asic_baco_state(void *handle, int state) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!(hwmgr->not_vf && amdgpu_dpm) || + !hwmgr->hwmgr_func->set_asic_baco_state) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_get_ppfeature_status(void *handle, char *buf) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en || !buf) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_asic_reset_mode_2(void *handle) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->asic_reset == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_smu_i2c_bus_access(void *handle, bool acquire) +{ + struct pp_hwmgr *hwmgr = handle; + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en) + return -EINVAL; + + if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) { + pr_info_ratelimited("%s was not implemented.\n", __func__); + return -EINVAL; + } + + mutex_lock(&hwmgr->smu_lock); + ret = hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire); + mutex_unlock(&hwmgr->smu_lock); + + return ret; +} + +static int pp_set_df_cstate(void *handle, enum pp_df_cstate state) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_df_cstate(hwmgr, state); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate) + return 0; + + mutex_lock(&hwmgr->smu_lock); + hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate); + mutex_unlock(&hwmgr->smu_lock); + + return 0; +} + +static ssize_t pp_get_gpu_metrics(void *handle, void **table) +{ + struct pp_hwmgr *hwmgr = handle; + ssize_t size; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&hwmgr->smu_lock); + size = hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); + mutex_unlock(&hwmgr->smu_lock); + + return size; +} + +static const struct amd_pm_funcs pp_dpm_funcs = { + .load_firmware = pp_dpm_load_fw, + .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, + .force_performance_level = pp_dpm_force_performance_level, + .get_performance_level = pp_dpm_get_performance_level, + .get_current_power_state = pp_dpm_get_current_power_state, + .dispatch_tasks = pp_dpm_dispatch_tasks, + .set_fan_control_mode = pp_dpm_set_fan_control_mode, + .get_fan_control_mode = pp_dpm_get_fan_control_mode, + .set_fan_speed_percent = pp_dpm_set_fan_speed_percent, + .get_fan_speed_percent = pp_dpm_get_fan_speed_percent, + .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm, + .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm, + .get_pp_num_states = pp_dpm_get_pp_num_states, + .get_pp_table = pp_dpm_get_pp_table, + .set_pp_table = pp_dpm_set_pp_table, + .force_clock_level = pp_dpm_force_clock_level, + .print_clock_levels = pp_dpm_print_clock_levels, + .get_sclk_od = pp_dpm_get_sclk_od, + .set_sclk_od = pp_dpm_set_sclk_od, + .get_mclk_od = pp_dpm_get_mclk_od, + .set_mclk_od = pp_dpm_set_mclk_od, + .read_sensor = pp_dpm_read_sensor, + .get_vce_clock_state = pp_dpm_get_vce_clock_state, + .switch_power_profile = pp_dpm_switch_power_profile, + .set_clockgating_by_smu = pp_set_clockgating_by_smu, + .set_powergating_by_smu = pp_set_powergating_by_smu, + .get_power_profile_mode = pp_get_power_profile_mode, + .set_power_profile_mode = pp_set_power_profile_mode, + .odn_edit_dpm_table = pp_odn_edit_dpm_table, + .set_mp1_state = pp_dpm_set_mp1_state, + .set_power_limit = pp_set_power_limit, + .get_power_limit = pp_get_power_limit, +/* export to DC */ + .get_sclk = pp_dpm_get_sclk, + .get_mclk = pp_dpm_get_mclk, + .display_configuration_change = pp_display_configuration_change, + .get_display_power_level = pp_get_display_power_level, + .get_current_clocks = pp_get_current_clocks, + .get_clock_by_type = pp_get_clock_by_type, + .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency, + .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage, + .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges, + .display_clock_voltage_request = pp_display_clock_voltage_request, + .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks, + .notify_smu_enable_pwe = pp_notify_smu_enable_pwe, + .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost, + .set_active_display_count = pp_set_active_display_count, + .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk, + .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq, + .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq, + .get_asic_baco_capability = pp_get_asic_baco_capability, + .get_asic_baco_state = pp_get_asic_baco_state, + .set_asic_baco_state = pp_set_asic_baco_state, + .get_ppfeature_status = pp_get_ppfeature_status, + .set_ppfeature_status = pp_set_ppfeature_status, + .asic_reset_mode_2 = pp_asic_reset_mode_2, + .smu_i2c_bus_access = pp_smu_i2c_bus_access, + .set_df_cstate = pp_set_df_cstate, + .set_xgmi_pstate = pp_set_xgmi_pstate, + .get_gpu_metrics = pp_get_gpu_metrics, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h new file mode 100644 index 000000000000..2fcc4b60153c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/cik_dpm.h @@ -0,0 +1,29 @@ +/* + * Copyright 2014 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 __CIK_DPM_H__ +#define __CIK_DPM_H__ + +extern const struct amdgpu_ip_block_version kv_smu_ip_block; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile new file mode 100644 index 000000000000..2773966ae434 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/Makefile @@ -0,0 +1,44 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'hw manager' sub-component of powerplay. +# It provides the hardware management services for the driver. + +HARDWARE_MGR = hwmgr.o processpptables.o \ + hardwaremanager.o smu8_hwmgr.o \ + pppcielanes.o\ + process_pptables_v1_0.o ppatomctrl.o ppatomfwctrl.o \ + smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \ + smu7_clockpowergating.o \ + vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \ + vega10_thermal.o smu10_hwmgr.o pp_psm.o\ + vega12_processpptables.o vega12_hwmgr.o \ + vega12_thermal.o \ + pp_overdriver.o smu_helper.o \ + vega20_processpptables.o vega20_hwmgr.o vega20_powertune.o \ + vega20_thermal.o common_baco.o vega10_baco.o vega20_baco.o \ + vega12_baco.o smu9_baco.o tonga_baco.o polaris_baco.o fiji_baco.o \ + ci_baco.o smu7_baco.o + +AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c new file mode 100644 index 000000000000..3be40114e63d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.c @@ -0,0 +1,195 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "ci_baco.h" + +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "bif/bif_4_1_d.h" +#include "bif/bif_4_1_sh_mask.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" + +#include "gca/gfx_7_2_d.h" +#include "gca/gfx_7_2_sh_mask.h" + +static const struct baco_cmd_entry gpio_tbl[] = +{ + { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, + { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, + { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, + { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } +}; + +static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } +}; + +static const struct baco_cmd_entry use_bclk_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } +}; + +static const struct baco_cmd_entry turn_off_plls_tbl[] = +{ + { CMD_READMODIFYWRITE, mmDISPPLL_BG_CNTL, DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK, DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_DC }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__OSC_EN_MASK, CG_CLKPIN_CNTL_DC__OSC_EN__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__XTALIN_SEL_MASK, CG_CLKPIN_CNTL_DC__XTALIN_SEL__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_RESET_MASK, PLL_CNTL__PLL_RESET__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_POWER_DOWN_MASK, PLL_CNTL__PLL_POWER_DOWN__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_BYPASS_CAL_MASK, PLL_CNTL__PLL_BYPASS_CAL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 }, + { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL_MASK, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL__SHIFT, 0, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x2 } +}; + +static const struct baco_cmd_entry enter_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } +}; + +#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK + +static const struct baco_cmd_entry exit_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, + { CMD_DELAY_MS, 0, 0, 0, 20, 0 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } +}; + +static const struct baco_cmd_entry clean_baco_tbl[] = +{ + { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 } +}; + +int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu7_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); + baco_program_registers(hwmgr, enable_fb_req_rej_tbl, + ARRAY_SIZE(enable_fb_req_rej_tbl)); + baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); + baco_program_registers(hwmgr, turn_off_plls_tbl, + ARRAY_SIZE(turn_off_plls_tbl)); + if (baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h new file mode 100644 index 000000000000..17041f187020 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ci_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __CI_BACO_H__ +#define __CI_BACO_H__ +#include "smu7_baco.h" + +extern int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c new file mode 100644 index 000000000000..1c73776bd606 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.c @@ -0,0 +1,120 @@ +/* + * Copyright 2018 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 "common_baco.h" + + +static bool baco_wait_register(struct pp_hwmgr *hwmgr, u32 reg, u32 mask, u32 value) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + u32 timeout = 5000, data; + + do { + msleep(1); + data = RREG32(reg); + timeout--; + } while (value != (data & mask) && (timeout != 0)); + + if (timeout == 0) + return false; + + return true; +} + +static bool baco_cmd_handler(struct pp_hwmgr *hwmgr, u32 command, u32 reg, u32 mask, + u32 shift, u32 value, u32 timeout) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + u32 data; + bool ret = true; + + switch (command) { + case CMD_WRITE: + WREG32(reg, value << shift); + break; + case CMD_READMODIFYWRITE: + data = RREG32(reg); + data = (data & (~mask)) | (value << shift); + WREG32(reg, data); + break; + case CMD_WAITFOR: + ret = baco_wait_register(hwmgr, reg, mask, value); + break; + case CMD_DELAY_MS: + if (timeout) + /* Delay in milli Seconds */ + msleep(timeout); + break; + case CMD_DELAY_US: + if (timeout) + /* Delay in micro Seconds */ + udelay(timeout); + break; + + default: + dev_warn(adev->dev, "Invalid BACO command.\n"); + ret = false; + } + + return ret; +} + +bool baco_program_registers(struct pp_hwmgr *hwmgr, + const struct baco_cmd_entry *entry, + const u32 array_size) +{ + u32 i, reg = 0; + + for (i = 0; i < array_size; i++) { + if ((entry[i].cmd == CMD_WRITE) || + (entry[i].cmd == CMD_READMODIFYWRITE) || + (entry[i].cmd == CMD_WAITFOR)) + reg = entry[i].reg_offset; + if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask, + entry[i].shift, entry[i].val, entry[i].timeout)) + return false; + } + + return true; +} + +bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr, + const struct soc15_baco_cmd_entry *entry, + const u32 array_size) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + u32 i, reg = 0; + + for (i = 0; i < array_size; i++) { + if ((entry[i].cmd == CMD_WRITE) || + (entry[i].cmd == CMD_READMODIFYWRITE) || + (entry[i].cmd == CMD_WAITFOR)) + reg = adev->reg_offset[entry[i].hwip][entry[i].inst][entry[i].seg] + + entry[i].reg_offset; + if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask, + entry[i].shift, entry[i].val, entry[i].timeout)) + return false; + } + + return true; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h new file mode 100644 index 000000000000..8393eb62706d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/common_baco.h @@ -0,0 +1,63 @@ +/* + * Copyright 2018 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 __COMMON_BOCO_H__ +#define __COMMON_BOCO_H__ +#include "hwmgr.h" + + +enum baco_cmd_type { + CMD_WRITE = 0, + CMD_READMODIFYWRITE, + CMD_WAITFOR, + CMD_DELAY_MS, + CMD_DELAY_US, +}; + +struct baco_cmd_entry { + enum baco_cmd_type cmd; + uint32_t reg_offset; + uint32_t mask; + uint32_t shift; + uint32_t timeout; + uint32_t val; +}; + +struct soc15_baco_cmd_entry { + enum baco_cmd_type cmd; + uint32_t hwip; + uint32_t inst; + uint32_t seg; + uint32_t reg_offset; + uint32_t mask; + uint32_t shift; + uint32_t timeout; + uint32_t val; +}; + +extern bool baco_program_registers(struct pp_hwmgr *hwmgr, + const struct baco_cmd_entry *entry, + const u32 array_size); +extern bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr, + const struct soc15_baco_cmd_entry *entry, + const u32 array_size); +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c new file mode 100644 index 000000000000..c0368f2dfb21 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.c @@ -0,0 +1,196 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "fiji_baco.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" + + +static const struct baco_cmd_entry gpio_tbl[] = +{ + { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, + { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, + { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, + { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } +}; + +static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } +}; + +static const struct baco_cmd_entry use_bclk_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 } +}; + +static const struct baco_cmd_entry turn_off_plls_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 } +}; + +static const struct baco_cmd_entry clk_req_b_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 } +}; + +static const struct baco_cmd_entry enter_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } +}; + +#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK + +static const struct baco_cmd_entry exit_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } +}; + +static const struct baco_cmd_entry clean_baco_tbl[] = +{ + { CMD_WRITE, mmBIOS_SCRATCH_0, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_1, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_2, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_3, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_4, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_5, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_8, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_9, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_10, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_11, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_12, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_13, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_14, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_15, 0, 0, 0, 0 } +}; + +int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu7_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); + baco_program_registers(hwmgr, enable_fb_req_rej_tbl, + ARRAY_SIZE(enable_fb_req_rej_tbl)); + baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); + baco_program_registers(hwmgr, turn_off_plls_tbl, + ARRAY_SIZE(turn_off_plls_tbl)); + baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl)); + if (baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h new file mode 100644 index 000000000000..47f402900bdb --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/fiji_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __FIJI_BACO_H__ +#define __FIJI_BACO_H__ +#include "smu7_baco.h" + +extern int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c new file mode 100644 index 000000000000..9454ab50f9a1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -0,0 +1,544 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include "hwmgr.h" +#include "hardwaremanager.h" +#include "power_state.h" + + +#define TEMP_RANGE_MIN (0) +#define TEMP_RANGE_MAX (80 * 1000) + +#define PHM_FUNC_CHECK(hw) \ + do { \ + if ((hw) == NULL || (hw)->hwmgr_func == NULL) \ + return -EINVAL; \ + } while (0) + +int phm_setup_asic(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->asic_setup) + return hwmgr->hwmgr_func->asic_setup(hwmgr); + + return 0; +} + +int phm_power_down_asic(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->power_off_asic) + return hwmgr->hwmgr_func->power_off_asic(hwmgr); + + return 0; +} + +int phm_set_power_state(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pcurrent_state, + const struct pp_hw_power_state *pnew_power_state) +{ + struct phm_set_power_state_input states; + + PHM_FUNC_CHECK(hwmgr); + + states.pcurrent_state = pcurrent_state; + states.pnew_state = pnew_power_state; + + if (NULL != hwmgr->hwmgr_func->power_state_set) + return hwmgr->hwmgr_func->power_state_set(hwmgr, &states); + + return 0; +} + +int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = NULL; + int ret = -EINVAL; + PHM_FUNC_CHECK(hwmgr); + adev = hwmgr->adev; + + /* Skip for suspend/resume case */ + if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr) + && !amdgpu_passthrough(adev) && adev->in_suspend) { + pr_info("dpm has been enabled\n"); + return 0; + } + + if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) + ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); + + return ret; +} + +int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr) +{ + int ret = -EINVAL; + + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->not_vf) + return 0; + + if (!smum_is_dpm_running(hwmgr)) { + pr_info("dpm has been disabled\n"); + return 0; + } + + if (hwmgr->hwmgr_func->dynamic_state_management_disable) + ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr); + + return ret; +} + +int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) +{ + int ret = 0; + + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->force_dpm_level != NULL) + ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + + return ret; +} + +int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *adjusted_ps, + const struct pp_power_state *current_ps) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL) + return hwmgr->hwmgr_func->apply_state_adjust_rules( + hwmgr, + adjusted_ps, + current_ps); + return 0; +} + +int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->apply_clocks_adjust_rules != NULL) + return hwmgr->hwmgr_func->apply_clocks_adjust_rules(hwmgr); + return 0; +} + +int phm_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->powerdown_uvd != NULL) + return hwmgr->hwmgr_func->powerdown_uvd(hwmgr); + return 0; +} + + +int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating) + return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr); + + return 0; +} + +int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->pre_display_config_changed) + hwmgr->hwmgr_func->pre_display_config_changed(hwmgr); + + return 0; + +} + +int phm_display_configuration_changed(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->display_config_changed) + hwmgr->hwmgr_func->display_config_changed(hwmgr); + + return 0; +} + +int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment) + hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr); + + return 0; +} + +int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->not_vf) + return 0; + + if (hwmgr->hwmgr_func->stop_thermal_controller == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr); +} + +int phm_register_irq_handlers(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->register_irq_handlers != NULL) + return hwmgr->hwmgr_func->register_irq_handlers(hwmgr); + + return 0; +} + +/** +* Initializes the thermal controller subsystem. +* +* @param pHwMgr the address of the powerplay hardware manager. +* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher. +*/ +int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + struct PP_TemperatureRange range = { + TEMP_RANGE_MIN, + TEMP_RANGE_MAX, + TEMP_RANGE_MAX, + TEMP_RANGE_MIN, + TEMP_RANGE_MAX, + TEMP_RANGE_MAX, + TEMP_RANGE_MIN, + TEMP_RANGE_MAX, + TEMP_RANGE_MAX}; + struct amdgpu_device *adev = hwmgr->adev; + + if (!hwmgr->not_vf) + return 0; + + if (hwmgr->hwmgr_func->get_thermal_temperature_range) + hwmgr->hwmgr_func->get_thermal_temperature_range( + hwmgr, &range); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController) + && hwmgr->hwmgr_func->start_thermal_controller != NULL) + ret = hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range); + + adev->pm.dpm.thermal.min_temp = range.min; + adev->pm.dpm.thermal.max_temp = range.max; + adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max; + adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min; + adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max; + adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max; + adev->pm.dpm.thermal.min_mem_temp = range.mem_min; + adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max; + adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max; + + return ret; +} + + +bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + if (hwmgr->pp_one_vf) + return false; + + if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL) + return false; + + return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr); +} + + +int phm_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->check_states_equal == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal); +} + +int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config) +{ + int index = 0; + int number_of_active_display = 0; + + PHM_FUNC_CHECK(hwmgr); + + if (display_config == NULL) + return -EINVAL; + + if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) + hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); + + for (index = 0; index < display_config->num_path_including_non_display; index++) { + if (display_config->displays[index].controller_id != 0) + number_of_active_display++; + } + + if (NULL != hwmgr->hwmgr_func->set_active_display_count) + hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display); + + if (hwmgr->hwmgr_func->store_cc6_data == NULL) + return -EINVAL; + + /* TODO: pass other display configuration in the future */ + + if (hwmgr->hwmgr_func->store_cc6_data) + hwmgr->hwmgr_func->store_cc6_data(hwmgr, + display_config->cpu_pstate_separation_time, + display_config->cpu_cc6_disable, + display_config->cpu_pstate_disable, + display_config->nb_pstate_switch_disable); + + return 0; +} + +int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ + PHM_FUNC_CHECK(hwmgr); + + if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL) + return -EINVAL; + return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info); +} + +int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->set_cpu_power_state != NULL) + return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr); + + return 0; +} + + +int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + PHM_FUNC_CHECK(hwmgr); + if (hwmgr->hwmgr_func->get_performance_level == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level); + + +} + + +/** +* Gets Clock Info. +* +* @param pHwMgr the address of the powerplay hardware manager. +* @param pPowerState the address of the Power State structure. +* @param pClockInfo the address of PP_ClockInfo structure where the result will be returned. +* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end. +*/ +int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info, + PHM_PerformanceLevelDesignation designation) +{ + int result; + PHM_PerformanceLevel performance_level = {0}; + + PHM_FUNC_CHECK(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL); + PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL); + + result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result); + + + pclock_info->min_mem_clk = performance_level.memory_clock; + pclock_info->min_eng_clk = performance_level.coreClock; + pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth; + + + result = phm_get_performance_level(hwmgr, state, designation, + (hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result); + + pclock_info->max_mem_clk = performance_level.memory_clock; + pclock_info->max_eng_clk = performance_level.coreClock; + pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth; + + return 0; +} + +int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info); + +} + +int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->get_clock_by_type == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks); + +} + +int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks); + +} + +int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks); + +} + +int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_ranges) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges) + return -EINVAL; + + return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr, + clock_ranges); +} + +int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->display_clock_voltage_request) + return -EINVAL; + + return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock); +} + +int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->get_max_high_clocks == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks); +} + +int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->not_vf) + return 0; + + if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr); +} + +int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->set_active_display_count) + return -EINVAL; + + return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count); +} + +int phm_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) + return -EINVAL; + + return hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); +} + +int phm_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq) + return -EINVAL; + + return hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); +} + +int phm_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + PHM_FUNC_CHECK(hwmgr); + + if (!hwmgr->hwmgr_func->set_hard_min_fclk_by_freq) + return -EINVAL; + + return hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c new file mode 100644 index 000000000000..f48fdc7f0382 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr.c @@ -0,0 +1,564 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include +#include +#include +#include "power_state.h" +#include "hwmgr.h" +#include "ppsmc.h" +#include "amd_acpi.h" +#include "pp_psm.h" + +extern const struct pp_smumgr_func ci_smu_funcs; +extern const struct pp_smumgr_func smu8_smu_funcs; +extern const struct pp_smumgr_func iceland_smu_funcs; +extern const struct pp_smumgr_func tonga_smu_funcs; +extern const struct pp_smumgr_func fiji_smu_funcs; +extern const struct pp_smumgr_func polaris10_smu_funcs; +extern const struct pp_smumgr_func vegam_smu_funcs; +extern const struct pp_smumgr_func vega10_smu_funcs; +extern const struct pp_smumgr_func vega12_smu_funcs; +extern const struct pp_smumgr_func smu10_smu_funcs; +extern const struct pp_smumgr_func vega20_smu_funcs; + +extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr); +extern int smu8_init_function_pointers(struct pp_hwmgr *hwmgr); +extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr); +extern int vega12_hwmgr_init(struct pp_hwmgr *hwmgr); +extern int vega20_hwmgr_init(struct pp_hwmgr *hwmgr); +extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); + +static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr); +static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); +static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); +static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr); +static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr); +static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr); +static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr); + + +static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr) +{ + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; + hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; + + hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; + hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; + hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; + hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE; +} + +int hwmgr_early_init(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev; + + if (!hwmgr) + return -EINVAL; + + hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; + hwmgr->pp_table_version = PP_TABLE_V1; + hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; + hwmgr->request_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; + hwmgr_init_default_caps(hwmgr); + hwmgr_set_user_specify_caps(hwmgr); + hwmgr->fan_ctrl_is_in_default_mode = true; + hwmgr_init_workload_prority(hwmgr); + hwmgr->gfxoff_state_changed_by_workload = false; + + adev = hwmgr->adev; + + switch (hwmgr->chip_family) { + case AMDGPU_FAMILY_CI: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + hwmgr->smumgr_funcs = &ci_smu_funcs; + ci_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~(PP_VBI_TIME_SUPPORT_MASK | + PP_ENABLE_GFX_CG_THRU_SMU | + PP_GFXOFF_MASK); + hwmgr->pp_table_version = PP_TABLE_V0; + hwmgr->od_enabled = false; + smu7_init_function_pointers(hwmgr); + break; + case AMDGPU_FAMILY_CZ: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + hwmgr->od_enabled = false; + hwmgr->smumgr_funcs = &smu8_smu_funcs; + hwmgr->feature_mask &= ~PP_GFXOFF_MASK; + smu8_init_function_pointers(hwmgr); + break; + case AMDGPU_FAMILY_VI: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + hwmgr->feature_mask &= ~PP_GFXOFF_MASK; + switch (hwmgr->chip_id) { + case CHIP_TOPAZ: + hwmgr->smumgr_funcs = &iceland_smu_funcs; + topaz_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | + PP_ENABLE_GFX_CG_THRU_SMU); + hwmgr->pp_table_version = PP_TABLE_V0; + hwmgr->od_enabled = false; + break; + case CHIP_TONGA: + hwmgr->smumgr_funcs = &tonga_smu_funcs; + tonga_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK; + break; + case CHIP_FIJI: + hwmgr->smumgr_funcs = &fiji_smu_funcs; + fiji_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | + PP_ENABLE_GFX_CG_THRU_SMU); + break; + case CHIP_POLARIS11: + case CHIP_POLARIS10: + case CHIP_POLARIS12: + hwmgr->smumgr_funcs = &polaris10_smu_funcs; + polaris_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK); + break; + case CHIP_VEGAM: + hwmgr->smumgr_funcs = &vegam_smu_funcs; + polaris_set_asic_special_caps(hwmgr); + hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK); + break; + default: + return -EINVAL; + } + smu7_init_function_pointers(hwmgr); + break; + case AMDGPU_FAMILY_AI: + switch (hwmgr->chip_id) { + case CHIP_VEGA10: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + hwmgr->feature_mask &= ~PP_GFXOFF_MASK; + hwmgr->smumgr_funcs = &vega10_smu_funcs; + vega10_hwmgr_init(hwmgr); + break; + case CHIP_VEGA12: + hwmgr->smumgr_funcs = &vega12_smu_funcs; + vega12_hwmgr_init(hwmgr); + break; + case CHIP_VEGA20: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + hwmgr->feature_mask &= ~PP_GFXOFF_MASK; + hwmgr->smumgr_funcs = &vega20_smu_funcs; + vega20_hwmgr_init(hwmgr); + break; + default: + return -EINVAL; + } + break; + case AMDGPU_FAMILY_RV: + switch (hwmgr->chip_id) { + case CHIP_RAVEN: + hwmgr->od_enabled = false; + hwmgr->smumgr_funcs = &smu10_smu_funcs; + smu10_init_function_pointers(hwmgr); + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +int hwmgr_sw_init(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr|| !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->smu_init) + return -EINVAL; + + phm_register_irq_handlers(hwmgr); + pr_info("hwmgr_sw_init smu backed is %s\n", hwmgr->smumgr_funcs->name); + + return hwmgr->smumgr_funcs->smu_init(hwmgr); +} + + +int hwmgr_sw_fini(struct pp_hwmgr *hwmgr) +{ + if (hwmgr && hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->smu_fini) + hwmgr->smumgr_funcs->smu_fini(hwmgr); + + return 0; +} + +int hwmgr_hw_init(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + hwmgr->pp_one_vf = amdgpu_sriov_is_pp_one_vf((struct amdgpu_device *)hwmgr->adev); + hwmgr->pm_en = (amdgpu_dpm && (hwmgr->not_vf || hwmgr->pp_one_vf)) + ? true : false; + if (!hwmgr->pm_en) + return 0; + + if (!hwmgr->pptable_func || + !hwmgr->pptable_func->pptable_init || + !hwmgr->hwmgr_func->backend_init) { + hwmgr->pm_en = false; + pr_info("dpm not supported \n"); + return 0; + } + + ret = hwmgr->pptable_func->pptable_init(hwmgr); + if (ret) + goto err; + + ((struct amdgpu_device *)hwmgr->adev)->pm.no_fan = + hwmgr->thermal_controller.fanInfo.bNoFan; + + ret = hwmgr->hwmgr_func->backend_init(hwmgr); + if (ret) + goto err1; + /* make sure dc limits are valid */ + if ((hwmgr->dyn_state.max_clock_voltage_on_dc.sclk == 0) || + (hwmgr->dyn_state.max_clock_voltage_on_dc.mclk == 0)) + hwmgr->dyn_state.max_clock_voltage_on_dc = + hwmgr->dyn_state.max_clock_voltage_on_ac; + + ret = psm_init_power_state_table(hwmgr); + if (ret) + goto err2; + + ret = phm_setup_asic(hwmgr); + if (ret) + goto err2; + + ret = phm_enable_dynamic_state_management(hwmgr); + if (ret) + goto err2; + ret = phm_start_thermal_controller(hwmgr); + ret |= psm_set_performance_states(hwmgr); + if (ret) + goto err2; + + ((struct amdgpu_device *)hwmgr->adev)->pm.dpm_enabled = true; + + return 0; +err2: + if (hwmgr->hwmgr_func->backend_fini) + hwmgr->hwmgr_func->backend_fini(hwmgr); +err1: + if (hwmgr->pptable_func->pptable_fini) + hwmgr->pptable_func->pptable_fini(hwmgr); +err: + return ret; +} + +int hwmgr_hw_fini(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf) + return 0; + + phm_stop_thermal_controller(hwmgr); + psm_set_boot_states(hwmgr); + psm_adjust_power_state_dynamic(hwmgr, true, NULL); + phm_disable_dynamic_state_management(hwmgr); + phm_disable_clock_power_gatings(hwmgr); + + if (hwmgr->hwmgr_func->backend_fini) + hwmgr->hwmgr_func->backend_fini(hwmgr); + if (hwmgr->pptable_func->pptable_fini) + hwmgr->pptable_func->pptable_fini(hwmgr); + return psm_fini_power_state_table(hwmgr); +} + +int hwmgr_suspend(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf) + return 0; + + phm_disable_smc_firmware_ctf(hwmgr); + ret = psm_set_boot_states(hwmgr); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL); + if (ret) + return ret; + ret = phm_power_down_asic(hwmgr); + + return ret; +} + +int hwmgr_resume(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + if (!hwmgr) + return -EINVAL; + + if (!hwmgr->not_vf || !hwmgr->pm_en) + return 0; + + ret = phm_setup_asic(hwmgr); + if (ret) + return ret; + + ret = phm_enable_dynamic_state_management(hwmgr); + if (ret) + return ret; + ret = phm_start_thermal_controller(hwmgr); + ret |= psm_set_performance_states(hwmgr); + if (ret) + return ret; + + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + + return ret; +} + +static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) +{ + switch (state) { + case POWER_STATE_TYPE_BATTERY: + return PP_StateUILabel_Battery; + case POWER_STATE_TYPE_BALANCED: + return PP_StateUILabel_Balanced; + case POWER_STATE_TYPE_PERFORMANCE: + return PP_StateUILabel_Performance; + default: + return PP_StateUILabel_None; + } +} + +int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id, + enum amd_pm_state_type *user_state) +{ + int ret = 0; + + if (hwmgr == NULL) + return -EINVAL; + + switch (task_id) { + case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: + if (!hwmgr->not_vf) + return ret; + ret = phm_pre_display_configuration_changed(hwmgr); + if (ret) + return ret; + ret = phm_set_cpu_power_state(hwmgr); + if (ret) + return ret; + ret = psm_set_performance_states(hwmgr); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); + break; + case AMD_PP_TASK_ENABLE_USER_STATE: + { + enum PP_StateUILabel requested_ui_label; + struct pp_power_state *requested_ps = NULL; + + if (!hwmgr->not_vf) + return ret; + if (user_state == NULL) { + ret = -EINVAL; + break; + } + + requested_ui_label = power_state_convert(*user_state); + ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps); + if (ret) + return ret; + ret = psm_adjust_power_state_dynamic(hwmgr, true, requested_ps); + break; + } + case AMD_PP_TASK_COMPLETE_INIT: + case AMD_PP_TASK_READJUST_POWER_STATE: + ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL); + break; + default: + break; + } + return ret; +} + +void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM); + +#if defined(CONFIG_ACPI) + if (amdgpu_acpi_is_pcie_performance_request_supported(hwmgr->adev)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); +#endif + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPowerManagement); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMC); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + return; +} + +int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC); + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC); + } + + if (hwmgr->feature_mask & PP_OVERDRIVE_MASK) + hwmgr->od_enabled = true; + + return 0; +} + +int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + + if (hwmgr->chip_id != CHIP_POLARIS10) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SPLLShutdownSupport); + + if (hwmgr->chip_id != CHIP_POLARIS11) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + } + return 0; +} + +int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + return 0; +} + +int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + return 0; +} + +int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + return 0; +} + +int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport); + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h new file mode 100644 index 000000000000..c0193e09d58a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hwmgr_ppt.h @@ -0,0 +1,116 @@ +/* + * Copyright 2015 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 PP_HWMGR_PPT_H +#define PP_HWMGR_PPT_H + +#include "hardwaremanager.h" +#include "smumgr.h" +#include "atom-types.h" + +struct phm_ppt_v1_clock_voltage_dependency_record { + uint32_t clk; + uint8_t vddInd; + uint8_t vddciInd; + uint8_t mvddInd; + uint16_t vdd_offset; + uint16_t vddc; + uint16_t vddgfx; + uint16_t vddci; + uint16_t mvdd; + uint8_t phases; + uint8_t cks_enable; + uint8_t cks_voffset; + uint32_t sclk_offset; +}; + +typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record; + +struct phm_ppt_v1_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table; + + +/* Multimedia Clock Voltage Dependency records and table */ +struct phm_ppt_v1_mm_clock_voltage_dependency_record { + uint32_t dclk; /* UVD D-clock */ + uint32_t vclk; /* UVD V-clock */ + uint32_t eclk; /* VCE clock */ + uint32_t aclk; /* ACP clock */ + uint32_t samclock; /* SAMU clock */ + uint8_t vddcInd; + uint16_t vddgfx_offset; + uint16_t vddc; + uint16_t vddgfx; + uint8_t phases; +}; +typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock_voltage_dependency_record; + +struct phm_ppt_v1_mm_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_mm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table; + +struct phm_ppt_v1_voltage_lookup_record { + uint16_t us_calculated; + uint16_t us_vdd; /* Base voltage */ + uint16_t us_cac_low; + uint16_t us_cac_mid; + uint16_t us_cac_high; +}; +typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record; + +struct phm_ppt_v1_voltage_lookup_table { + uint32_t count; + phm_ppt_v1_voltage_lookup_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table; + +/* PCIE records and Table */ + +struct phm_ppt_v1_pcie_record { + uint8_t gen_speed; + uint8_t lane_width; + uint16_t usreserved; + uint16_t reserved; + uint32_t pcie_sclk; +}; +typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; + +struct phm_ppt_v1_pcie_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_pcie_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table; + +struct phm_ppt_v1_gpio_table { + uint8_t vrhot_triggered_sclk_dpm_index; /* SCLK DPM level index to switch to when VRHot is triggered */ +}; +typedef struct phm_ppt_v1_gpio_table phm_ppt_v1_gpio_table; + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c new file mode 100644 index 000000000000..8f8e296f2fe9 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.c @@ -0,0 +1,222 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "polaris_baco.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "dce/dce_11_0_d.h" +#include "dce/dce_11_0_sh_mask.h" + +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" + +static const struct baco_cmd_entry gpio_tbl[] = +{ + { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, + { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, + { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, + { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } +}; + +static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } +}; + +static const struct baco_cmd_entry use_bclk_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } +}; + +static const struct baco_cmd_entry turn_off_plls_tbl[] = +{ + { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 }, + { CMD_DELAY_US, 0, 0, 0, 1, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_READMODIFYWRITE, 0xda2, 0x40, 0x6, 0, 0x0 }, + { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, + { CMD_READMODIFYWRITE, 0xda2, 0x8, 0x3, 0, 0x0 }, + { CMD_READMODIFYWRITE, 0xda2, 0x3fff00, 0x8, 0, 0x32 }, + { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, + { CMD_READMODIFYWRITE, mmMPLL_FUNC_CNTL_2, MPLL_FUNC_CNTL_2__ISO_DIS_P_MASK, MPLL_FUNC_CNTL_2__ISO_DIS_P__SHIFT, 0, 0x0 }, + { CMD_DELAY_US, 0, 0, 0, 5, 0x0 } +}; + +static const struct baco_cmd_entry clk_req_b_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 } +}; + +static const struct baco_cmd_entry enter_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } +}; + +#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK + +static const struct baco_cmd_entry exit_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } +}; + +static const struct baco_cmd_entry clean_baco_tbl[] = +{ + { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } +}; + +static const struct baco_cmd_entry use_bclk_tbl_vg[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 } +}; + +static const struct baco_cmd_entry turn_off_plls_tbl_vg[] = +{ + { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 }, + { CMD_DELAY_US, 0, 0, 0, 1, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, + { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, + { CMD_DELAY_US, 0, 0, 0, 5, 0x0 } +}; + +int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu7_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); + baco_program_registers(hwmgr, enable_fb_req_rej_tbl, + ARRAY_SIZE(enable_fb_req_rej_tbl)); + if (hwmgr->chip_id == CHIP_VEGAM) { + baco_program_registers(hwmgr, use_bclk_tbl_vg, ARRAY_SIZE(use_bclk_tbl_vg)); + baco_program_registers(hwmgr, turn_off_plls_tbl_vg, + ARRAY_SIZE(turn_off_plls_tbl_vg)); + } else { + baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); + baco_program_registers(hwmgr, turn_off_plls_tbl, + ARRAY_SIZE(turn_off_plls_tbl)); + } + baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl)); + if (baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h new file mode 100644 index 000000000000..87a5fa0a157a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/polaris_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __POLARIS_BACO_H__ +#define __POLARIS_BACO_H__ +#include "smu7_baco.h" + +extern int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c new file mode 100644 index 000000000000..8de384bf9a8f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.c @@ -0,0 +1,1288 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "pp_overdriver.h" +#include + +static const struct phm_fuses_default vega10_fuses_default[] = { + { 0x0213EA94DE0E4964, 0x00003C96, 0xFFFFE226, 0x00000656, 0x00002203, 0xFFFFF201, 0x000003FF, 0x00002203, 0xFFFFF201, 0x000003FF }, + { 0x0213EA94DE0A1884, 0x00003CC5, 0xFFFFE23A, 0x0000064E, 0x00002258, 0xFFFFF1F7, 0x000003FC, 0x00002258, 0xFFFFF1F7, 0x000003FC }, + { 0x0213EA94DE0E31A4, 0x00003CAF, 0xFFFFE36E, 0x00000602, 0x00001E98, 0xFFFFF569, 0x00000357, 0x00001E98, 0xFFFFF569, 0x00000357 }, + { 0x0213EA94DE2C1144, 0x0000391A, 0xFFFFE548, 0x000005C9, 0x00001B98, 0xFFFFF707, 0x00000324, 0x00001B98, 0xFFFFF707, 0x00000324 }, + { 0x0213EA94DE2C18C4, 0x00003821, 0xFFFFE674, 0x00000597, 0x00002196, 0xFFFFF361, 0x000003C0, 0x00002196, 0xFFFFF361, 0x000003C0 }, + { 0x0213EA94DE263884, 0x000044A2, 0xFFFFDCB7, 0x00000738, 0x0000325C, 0xFFFFE6A7, 0x000005E6, 0x0000325C, 0xFFFFE6A7, 0x000005E6 }, + { 0x0213EA94DE082924, 0x00004057, 0xFFFFE1CF, 0x0000063C, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, + { 0x0213EA94DE284924, 0x00003FD0, 0xFFFFDF0F, 0x000006E5, 0x0000267C, 0xFFFFEE2D, 0x000004AB, 0x0000267C, 0xFFFFEE2D, 0x000004AB }, + { 0x0213EA94DE280904, 0x00003F13, 0xFFFFE010, 0x000006AD, 0x000020E7, 0xFFFFF266, 0x000003EC, 0x000020E7, 0xFFFFF266, 0x000003EC }, + { 0x0213EA94DE082044, 0x00004088, 0xFFFFDFAB, 0x000006B6, 0x0000252B, 0xFFFFEFDB, 0x00000458, 0x0000252B, 0xFFFFEFDB, 0x00000458 }, + { 0x0213EA94DE283884, 0x00003EF6, 0xFFFFE017, 0x000006AA, 0x00001F67, 0xFFFFF369, 0x000003BE, 0x00001F67, 0xFFFFF369, 0x000003BE }, + { 0x0213EA94DE2C2184, 0x00003CDD, 0xFFFFE2A7, 0x0000063C, 0x000026C6, 0xFFFFEF38, 0x00000478, 0x000026C6, 0xFFFFEF38, 0x00000478 }, + { 0x0213EA94DE105124, 0x00003FA8, 0xFFFFDF02, 0x000006F0, 0x000027FE, 0xFFFFECF6, 0x000004EA, 0x000027FE, 0xFFFFECF6, 0x000004EA }, + { 0x0213EA94DE2638C4, 0x00004670, 0xFFFFDC40, 0x00000742, 0x00003A7A, 0xFFFFE1A7, 0x000006B6, 0x00003A7A, 0xFFFFE1A7, 0x000006B6 }, + { 0x0213EA94DE2C3024, 0x00003CDC, 0xFFFFE18C, 0x00000683, 0x00002A69, 0xFFFFEBE7, 0x00000515, 0x00002A69, 0xFFFFEBE7, 0x00000515 }, + { 0x0213EA94DE0E38C4, 0x00003CEC, 0xFFFFE38E, 0x00000601, 0x00002752, 0xFFFFEFA7, 0x00000453, 0x00002752, 0xFFFFEFA7, 0x00000453 }, + { 0x0213EA94DE2C1124, 0x000037D0, 0xFFFFE634, 0x000005A7, 0x00001CD2, 0xFFFFF644, 0x00000348, 0x00001CD2, 0xFFFFF644, 0x00000348 }, + { 0x0213EA94DE283964, 0x00003DF5, 0xFFFFE0A5, 0x00000698, 0x00001FD5, 0xFFFFF30E, 0x000003D1, 0x00001FD5, 0xFFFFF30E, 0x000003D1 }, + { 0x0213EA94DE0828C4, 0x00004201, 0xFFFFE03E, 0x00000688, 0x00003206, 0xFFFFE852, 0x0000058A, 0x00003206, 0xFFFFE852, 0x0000058A }, + { 0x0213EA94DE2C1864, 0x00003BED, 0xFFFFE2F5, 0x00000638, 0x0000270D, 0xFFFFEED0, 0x0000048E, 0x0000270D, 0xFFFFEED0, 0x0000048E }, + { 0x0213EA94DE0A1904, 0x00003E82, 0xFFFFE1BE, 0x00000654, 0x000025FB, 0xFFFFEFFA, 0x00000448, 0x000025FB, 0xFFFFEFFA, 0x00000448 }, + { 0x0213EA94DE2C40C4, 0x00003962, 0xFFFFE4B9, 0x000005EF, 0x00002385, 0xFFFFF156, 0x00000423, 0x00002385, 0xFFFFF156, 0x00000423 }, + { 0x0213EA94DE2C0944, 0x00003D88, 0xFFFFE21A, 0x00000655, 0x0000295A, 0xFFFFED68, 0x000004C4, 0x0000295A, 0xFFFFED68, 0x000004C4 }, + { 0x0213EA94DE2C1104, 0x00003AA4, 0xFFFFE4A3, 0x000005E0, 0x000022EF, 0xFFFFF250, 0x000003EB, 0x000022EF, 0xFFFFF250, 0x000003EB }, + { 0x0213EA94DE0E29A4, 0x00003D97, 0xFFFFE30D, 0x0000060D, 0x0000205D, 0xFFFFF45D, 0x00000380, 0x0000205D, 0xFFFFF45D, 0x00000380 }, + { 0x0213EA94DE2C40A4, 0x000039B6, 0xFFFFE446, 0x00000605, 0x00002325, 0xFFFFF16C, 0x0000041F, 0x00002325, 0xFFFFF16C, 0x0000041F }, + { 0x0213EA94DE263904, 0x0000457E, 0xFFFFDCF6, 0x00000722, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, + { 0x0213EA94DE0A1924, 0x00003FB8, 0xFFFFE101, 0x00000670, 0x00002787, 0xFFFFEEF5, 0x00000471, 0x00002787, 0xFFFFEEF5, 0x00000471 }, + { 0x0213EA94DE0E38A4, 0x00003BB2, 0xFFFFE430, 0x000005EA, 0x000024A5, 0xFFFFF162, 0x00000409, 0x000024A5, 0xFFFFF162, 0x00000409 }, + { 0x0213EA94DE082144, 0x00003EC5, 0xFFFFE1BD, 0x0000064F, 0x000022F0, 0xFFFFF227, 0x000003E8, 0x000022F0, 0xFFFFF227, 0x000003E8 }, + { 0x0213EA94DE2C3164, 0x000038A7, 0xFFFFE59F, 0x000005C1, 0x000021CC, 0xFFFFF2DF, 0x000003D9, 0x000021CC, 0xFFFFF2DF, 0x000003D9 }, + { 0x0213EA94DE324184, 0x00002995, 0xFFFFEF7A, 0x0000044C, 0x00001552, 0xFFFFFB5D, 0x00000292, 0x00001552, 0xFFFFFB5D, 0x00000292 }, + { 0x0213EA94DE2C4064, 0x00003B26, 0xFFFFE2D3, 0x00000649, 0x000023B4, 0xFFFFF09B, 0x00000449, 0x000023B4, 0xFFFFF09B, 0x00000449 }, + { 0x0213EA94DE081124, 0x000040D2, 0xFFFFE00A, 0x00000696, 0x000022DA, 0xFFFFF1E9, 0x000003F2, 0x000022DA, 0xFFFFF1E9, 0x000003F2 }, + { 0x0213EA94DE2C3924, 0x00003C98, 0xFFFFE365, 0x00000618, 0x00002D5D, 0xFFFFEB3A, 0x0000051D, 0x00002D5D, 0xFFFFEB3A, 0x0000051D }, + { 0x0213EA94DE2C10A4, 0x00003BBD, 0xFFFFE37E, 0x00000617, 0x0000252E, 0xFFFFF06E, 0x00000441, 0x0000252E, 0xFFFFF06E, 0x00000441 }, + { 0x0213EA94DE262924, 0x00004363, 0xFFFFDF7A, 0x000006A0, 0x000031F5, 0xFFFFE880, 0x0000057B, 0x000031F5, 0xFFFFE880, 0x0000057B }, + { 0x0213EA94DE0E3844, 0x00003CFC, 0xFFFFE2AF, 0x0000062E, 0x0000212A, 0xFFFFF335, 0x000003BF, 0x0000212A, 0xFFFFF335, 0x000003BF }, + { 0x0213EA94DE1C4924, 0x0000252D, 0xFFFFF31B, 0x000003C3, 0x00001A1A, 0xFFFFF882, 0x00000325, 0x00001A1A, 0xFFFFF882, 0x00000325 }, + { 0x0213EA94DE0A29A4, 0x00003FE2, 0xFFFFDFEF, 0x000006AC, 0x000025A2, 0xFFFFEF84, 0x00000462, 0x000025A2, 0xFFFFEF84, 0x00000462 }, + { 0x0213EA94DE0820E4, 0x000040A5, 0xFFFFE13B, 0x0000065B, 0x00002C13, 0xFFFFEC75, 0x000004D7, 0x00002C13, 0xFFFFEC75, 0x000004D7 }, + { 0x0213EA94DE0E48A4, 0x00003E42, 0xFFFFE1B3, 0x00000657, 0x0000221D, 0xFFFFF273, 0x000003DE, 0x0000221D, 0xFFFFF273, 0x000003DE }, + { 0x0213EA94DE0A20E4, 0x00003E7F, 0xFFFFE255, 0x00000638, 0x00002D30, 0xFFFFEB8A, 0x00000503, 0x00002D30, 0xFFFFEB8A, 0x00000503 }, + { 0x0213EA94DE2C29C4, 0x00003E56, 0xFFFFE16D, 0x00000670, 0x000028DC, 0xFFFFEDA0, 0x000004BA, 0x000028DC, 0xFFFFEDA0, 0x000004BA }, + { 0x0213EA94DE2630A4, 0x000044AD, 0xFFFFDE24, 0x000006DD, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, + { 0x0213EA94DE2C20E4, 0x00003AF3, 0xFFFFE5B0, 0x000005A6, 0x00002CF6, 0xFFFFEC75, 0x000004DD, 0x00002CF6, 0xFFFFEC75, 0x000004DD }, + { 0x0213EA94DE0A2084, 0x00003E66, 0xFFFFE19E, 0x0000065B, 0x00002332, 0xFFFFF1B9, 0x000003FD, 0x00002332, 0xFFFFF1B9, 0x000003FD }, + { 0x0213EA94DE082884, 0x00003FB4, 0xFFFFE0A5, 0x00000686, 0x0000253E, 0xFFFFF02E, 0x00000444, 0x0000253E, 0xFFFFF02E, 0x00000444 }, + { 0x0213EA94DE2818A4, 0x00003E28, 0xFFFFE14D, 0x0000066E, 0x00001FE2, 0xFFFFF39A, 0x000003B1, 0x00001FE2, 0xFFFFF39A, 0x000003B1 }, + { 0x0213EA94DE2C0904, 0x000039E6, 0xFFFFE44B, 0x000005FE, 0x0000210C, 0xFFFFF2F4, 0x000003DA, 0x0000210C, 0xFFFFF2F4, 0x000003DA }, + { 0x0213EA94DE2C5104, 0x00003A4D, 0xFFFFE252, 0x0000067A, 0x000027E2, 0xFFFFECED, 0x000004FA, 0x000027E2, 0xFFFFECED, 0x000004FA }, + { 0x0213EA94DE0A2964, 0x00004065, 0xFFFFE02F, 0x0000069B, 0x0000299D, 0xFFFFED38, 0x000004C2, 0x0000299D, 0xFFFFED38, 0x000004C2 }, + { 0x0213EA94DE0E20A4, 0x000039EE, 0xFFFFE603, 0x00000594, 0x0000214F, 0xFFFFF429, 0x0000038E, 0x0000214F, 0xFFFFF429, 0x0000038E }, + { 0x0213EA94DE0E48E4, 0x00003BD2, 0xFFFFE351, 0x00000618, 0x000020B8, 0xFFFFF377, 0x000003B4, 0x000020B8, 0xFFFFF377, 0x000003B4 }, + { 0x0213EA94DE0A3124, 0x00003FAA, 0xFFFFE183, 0x0000065E, 0x000032AE, 0xFFFFE7C2, 0x000005A6, 0x000032AE, 0xFFFFE7C2, 0x000005A6 }, + { 0x0213EA94DE2C2984, 0x00003AFB, 0xFFFFE3E4, 0x00000608, 0x00002293, 0xFFFFF21F, 0x000003FA, 0x00002293, 0xFFFFF21F, 0x000003FA }, + { 0x0213EA94DE262064, 0x0000448B, 0xFFFFDD5D, 0x0000070D, 0x00002E4E, 0xFFFFE9DF, 0x00000551, 0x00002E4E, 0xFFFFE9DF, 0x00000551 }, + { 0x0213EA94DE0E2184, 0x00003D46, 0xFFFFE39B, 0x000005F3, 0x0000218E, 0xFFFFF3CD, 0x00000398, 0x0000218E, 0xFFFFF3CD, 0x00000398 }, + { 0x0213EA94DE0848E4, 0x00003F01, 0xFFFFDFD9, 0x000006BF, 0x000023AF, 0xFFFFF04E, 0x0000044C, 0x000023AF, 0xFFFFF04E, 0x0000044C }, + { 0x0213EA94DE1029A4, 0x0000403D, 0xFFFFDF6B, 0x000006C9, 0x0000270D, 0xFFFFEE4B, 0x0000049E, 0x0000270D, 0xFFFFEE4B, 0x0000049E }, + { 0x0213EA94DE0E3964, 0x00003C11, 0xFFFFE35C, 0x00000613, 0x000020F9, 0xFFFFF365, 0x000003B9, 0x000020F9, 0xFFFFF365, 0x000003B9 }, + { 0x0213EA94DE2C3884, 0x00003B58, 0xFFFFE37D, 0x0000061F, 0x00002698, 0xFFFFEF46, 0x00000478, 0x00002698, 0xFFFFEF46, 0x00000478 }, + { 0x0213EA94DE2841A4, 0x00003EBC, 0xFFFFDF7A, 0x000006D6, 0x0000212B, 0xFFFFF195, 0x0000041B, 0x0000212B, 0xFFFFF195, 0x0000041B }, + { 0x0213EA94DE0848C4, 0x00004050, 0xFFFFDEB3, 0x000006FE, 0x00002D6C, 0xFFFFE961, 0x00000582, 0x00002D6C, 0xFFFFE961, 0x00000582 }, + { 0x0213EA94DE262044, 0x000043F0, 0xFFFFDD9C, 0x00000702, 0x00002B31, 0xFFFFEBEA, 0x000004F7, 0x00002B31, 0xFFFFEBEA, 0x000004F7 }, + { 0x0213EA94DE100924, 0x00003EFA, 0xFFFFE093, 0x00000696, 0x000026DB, 0xFFFFEEB3, 0x00000489, 0x000026DB, 0xFFFFEEB3, 0x00000489 }, + { 0x0213EA94DE082064, 0x0000425D, 0xFFFFDE8D, 0x000006E6, 0x00002CA4, 0xFFFFEAD2, 0x00000531, 0x00002CA4, 0xFFFFEAD2, 0x00000531 }, + { 0x0213EA94DE2639A4, 0x000043B0, 0xFFFFDD03, 0x00000728, 0x00002946, 0xFFFFECA6, 0x000004DE, 0x00002946, 0xFFFFECA6, 0x000004DE }, + { 0x0213EA94DE282864, 0x00003F6A, 0xFFFFE03A, 0x0000069D, 0x00002208, 0xFFFFF1F8, 0x000003F6, 0x00002208, 0xFFFFF1F8, 0x000003F6 }, + { 0x0213EA94DE2C2964, 0x00003A94, 0xFFFFE4A7, 0x000005E2, 0x000024D0, 0xFFFFF100, 0x00000426, 0x000024D0, 0xFFFFF100, 0x00000426 }, + { 0x0213EA94DE2810C4, 0x00003F2F, 0xFFFFE0A3, 0x00000688, 0x00002198, 0xFFFFF271, 0x000003E2, 0x00002198, 0xFFFFF271, 0x000003E2 }, + { 0x0213EA94DE1048E4, 0x00003EA5, 0xFFFFE032, 0x000006AE, 0x0000227C, 0xFFFFF130, 0x00000426, 0x0000227C, 0xFFFFF130, 0x00000426 }, + { 0x0213EA94DE264144, 0x0000442F, 0xFFFFDBC4, 0x0000078B, 0x00003CD6, 0xFFFFDE6C, 0x0000076C, 0x00003CD6, 0xFFFFDE6C, 0x0000076C }, + { 0x0213EA94DE282884, 0x00003DDE, 0xFFFFE174, 0x00000668, 0x00001FF4, 0xFFFFF38F, 0x000003B1, 0x00001FF4, 0xFFFFF38F, 0x000003B1 }, + { 0x0213EA94DE0A3144, 0x000040B0, 0xFFFFE016, 0x000006A0, 0x00002DBB, 0xFFFFEA7F, 0x00000537, 0x00002DBB, 0xFFFFEA7F, 0x00000537 }, + { 0x0213EA94DE2C3104, 0x00003429, 0xFFFFEA97, 0x000004DD, 0x000024D5, 0xFFFFF26F, 0x000003DF, 0x000024D5, 0xFFFFF26F, 0x000003DF }, + { 0x0213EA94DE0E1904, 0x00003AEB, 0xFFFFE590, 0x000005A3, 0x000022CB, 0xFFFFF347, 0x000003B2, 0x000022CB, 0xFFFFF347, 0x000003B2 }, + { 0x0213EA94DE283904, 0x00003B8E, 0xFFFFE2EF, 0x00000636, 0x00002351, 0xFFFFF143, 0x0000041C, 0x00002351, 0xFFFFF143, 0x0000041C }, + { 0x0213EA94DE3240C4, 0x00002926, 0xFFFFF0B0, 0x00000410, 0x0000194E, 0xFFFFF94E, 0x000002E9, 0x0000194E, 0xFFFFF94E, 0x000002E9 }, + { 0x0213EA94DE283184, 0x0000402B, 0xFFFFDF78, 0x000006C2, 0x00002273, 0xFFFFF16C, 0x00000414, 0x00002273, 0xFFFFF16C, 0x00000414 }, + { 0x0213EA94DE0A10A4, 0x00003D6A, 0xFFFFE1D3, 0x00000659, 0x00002006, 0xFFFFF394, 0x000003B1, 0x00002006, 0xFFFFF394, 0x000003B1 }, + { 0x0213EA94DE284064, 0x00004042, 0xFFFFDFD8, 0x000006A8, 0x00002135, 0xFFFFF29F, 0x000003D9, 0x00002135, 0xFFFFF29F, 0x000003D9 }, + { 0x0213EA94DE0820A4, 0x0000405B, 0xFFFFE093, 0x00000682, 0x0000288F, 0xFFFFEE3A, 0x00000491, 0x0000288F, 0xFFFFEE3A, 0x00000491 }, + { 0x0213EA94DE2C48A4, 0x00003A49, 0xFFFFE30C, 0x00000648, 0x000023F9, 0xFFFFF02D, 0x00000460, 0x000023F9, 0xFFFFF02D, 0x00000460 }, + { 0x0213EA94DE282964, 0x00003D59, 0xFFFFE1CC, 0x0000065B, 0x00002013, 0xFFFFF37D, 0x000003B6, 0x00002013, 0xFFFFF37D, 0x000003B6 }, + { 0x0213EA94DE2C3984, 0x000040C1, 0xFFFFDF8C, 0x000006CA, 0x00003271, 0xFFFFE6CA, 0x000005EA, 0x00003271, 0xFFFFE6CA, 0x000005EA }, + { 0x0213EA94DE2620E4, 0x000042E9, 0xFFFFDFDC, 0x0000068C, 0x00002ED9, 0xFFFFEAAF, 0x0000051B, 0x00002ED9, 0xFFFFEAAF, 0x0000051B }, + { 0x0213EA94DE083084, 0x000042ED, 0xFFFFDE50, 0x000006F0, 0x00002FCF, 0xFFFFE8BB, 0x0000058C, 0x00002FCF, 0xFFFFE8BB, 0x0000058C }, + { 0x0213EA94DE0A4104, 0x00003EBD, 0xFFFFE099, 0x00000698, 0x00002709, 0xFFFFEE7B, 0x00000495, 0x00002709, 0xFFFFEE7B, 0x00000495 }, + { 0x0213EA94DE284904, 0x00003F71, 0xFFFFDF82, 0x000006C9, 0x0000219B, 0xFFFFF1AD, 0x0000040F, 0x0000219B, 0xFFFFF1AD, 0x0000040F }, + { 0x0213EA94DE2808E4, 0x00003E73, 0xFFFFE080, 0x0000069B, 0x000020E7, 0xFFFFF273, 0x000003E9, 0x000020E7, 0xFFFFF273, 0x000003E9 }, + { 0x0213EA94DE0E3184, 0x00003E14, 0xFFFFE278, 0x0000062C, 0x00002275, 0xFFFFF2B3, 0x000003CE, 0x00002275, 0xFFFFF2B3, 0x000003CE }, + { 0x0213EA94DE2C21A4, 0x00003ABB, 0xFFFFE3B9, 0x00000615, 0x00002192, 0xFFFFF28F, 0x000003EB, 0x00002192, 0xFFFFF28F, 0x000003EB }, + { 0x0213EA94DE283124, 0x00003D53, 0xFFFFE255, 0x00000643, 0x0000275B, 0xFFFFEEED, 0x00000479, 0x0000275B, 0xFFFFEEED, 0x00000479 }, + { 0x0213EA94DE262864, 0x000043E3, 0xFFFFDDC3, 0x000006FB, 0x00002B6B, 0xFFFFEBD6, 0x000004FA, 0x00002B6B, 0xFFFFEBD6, 0x000004FA }, + { 0x0213EA94DE0E2144, 0x00003BDE, 0xFFFFE507, 0x000005B4, 0x000022CE, 0xFFFFF358, 0x000003AB, 0x000022CE, 0xFFFFF358, 0x000003AB }, + { 0x0213EA94DE323164, 0x00002460, 0xFFFFF3B5, 0x000003A2, 0x000014E7, 0xFFFFFC32, 0x0000027C, 0x000014E7, 0xFFFFFC32, 0x0000027C }, + { 0x0213EA94DE2820C4, 0x00003D20, 0xFFFFE298, 0x0000062F, 0x00002080, 0xFFFFF3AF, 0x000003A8, 0x00002080, 0xFFFFF3AF, 0x000003A8 }, + { 0x0213EA94DE081904, 0x00003E14, 0xFFFFE221, 0x00000641, 0x000021BB, 0xFFFFF2EA, 0x000003CA, 0x000021BB, 0xFFFFF2EA, 0x000003CA }, + { 0x0213EA94DE0A40C4, 0x00003DE1, 0xFFFFE14E, 0x00000677, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, + { 0x0213EA94DE261084, 0x00004372, 0xFFFFDDF8, 0x000006F5, 0x00002B3F, 0xFFFFEBE8, 0x000004F8, 0x00002B3F, 0xFFFFEBE8, 0x000004F8 }, + { 0x0213EA94DE0A28C4, 0x00003E4F, 0xFFFFE2A3, 0x0000062B, 0x00002F5A, 0xFFFFEA37, 0x0000053B, 0x00002F5A, 0xFFFFEA37, 0x0000053B }, + { 0x0213EA94DE2850E4, 0x00003E07, 0xFFFFE02F, 0x000006B6, 0x0000216B, 0xFFFFF1A3, 0x00000416, 0x0000216B, 0xFFFFF1A3, 0x00000416 }, + { 0x0213EA94DE2838A4, 0x00003DAB, 0xFFFFE128, 0x0000067F, 0x0000216F, 0xFFFFF236, 0x000003F3, 0x0000216F, 0xFFFFF236, 0x000003F3 }, + { 0x0213EA94DE2C2924, 0x0000364B, 0xFFFFE8CB, 0x0000052A, 0x00002568, 0xFFFFF1B2, 0x00000400, 0x00002568, 0xFFFFF1B2, 0x00000400 }, + { 0x0213EA94DE261064, 0x00004219, 0xFFFFDE87, 0x000006E8, 0x00002C59, 0xFFFFEAEE, 0x00000529, 0x00002C59, 0xFFFFEAEE, 0x00000529 }, + { 0x0213EA94DE0E1944, 0x000039A8, 0xFFFFE602, 0x00000594, 0x00001D06, 0xFFFFF6F0, 0x00000316, 0x00001D06, 0xFFFFF6F0, 0x00000316 }, + { 0x0213EA94DE2610E4, 0x00004052, 0xFFFFE01C, 0x00000698, 0x00002310, 0xFFFFF1A1, 0x000003FE, 0x00002310, 0xFFFFF1A1, 0x000003FE }, + { 0x0213EA94DE0E2824, 0x00003C1C, 0xFFFFE3EB, 0x000005F1, 0x00002289, 0xFFFFF2CF, 0x000003C9, 0x00002289, 0xFFFFF2CF, 0x000003C9 }, + { 0x0213EA94DE0E5124, 0x00003F19, 0xFFFFE085, 0x0000069E, 0x00002B94, 0xFFFFEB72, 0x0000051D, 0x00002B94, 0xFFFFEB72, 0x0000051D }, + { 0x0213EA94DE0E41A4, 0x00003C51, 0xFFFFE2AD, 0x00000638, 0x0000206B, 0xFFFFF361, 0x000003BE, 0x0000206B, 0xFFFFF361, 0x000003BE }, + { 0x0213EA94DE2610C4, 0x000040B9, 0xFFFFDFBB, 0x000006AB, 0x0000241F, 0xFFFFF0CC, 0x00000425, 0x0000241F, 0xFFFFF0CC, 0x00000425 }, + { 0x0213EA94DE0A2064, 0x00003E62, 0xFFFFE12C, 0x00000678, 0x00002445, 0xFFFFF09E, 0x00000435, 0x00002445, 0xFFFFF09E, 0x00000435 }, + { 0x0213EA94DE0E1984, 0x00003C97, 0xFFFFE399, 0x000005FB, 0x0000209D, 0xFFFFF41D, 0x0000038F, 0x0000209D, 0xFFFFF41D, 0x0000038F }, + { 0x0213EA94DE0E3144, 0x00003FF9, 0xFFFFE1E9, 0x0000063E, 0x00002E96, 0xFFFFEAF5, 0x00000516, 0x00002E96, 0xFFFFEAF5, 0x00000516 }, + { 0x0213EA94DE0A3084, 0x00003F04, 0xFFFFE109, 0x0000067A, 0x000026E1, 0xFFFFEF0B, 0x00000476, 0x000026E1, 0xFFFFEF0B, 0x00000476 }, + { 0x0213EA94DE101124, 0x00003E3E, 0xFFFFE187, 0x00000660, 0x00002049, 0xFFFFF38D, 0x000003B0, 0x00002049, 0xFFFFF38D, 0x000003B0 }, + { 0x0213EA94DE282944, 0x00003D58, 0xFFFFE253, 0x0000063D, 0x00002158, 0xFFFFF308, 0x000003C3, 0x00002158, 0xFFFFF308, 0x000003C3 }, + { 0x0213EA94DE0840C4, 0x00004074, 0xFFFFDF8D, 0x000006C0, 0x00002799, 0xFFFFEE19, 0x000004A5, 0x00002799, 0xFFFFEE19, 0x000004A5 }, + { 0x0213EA94DE281924, 0x00003DAF, 0xFFFFE1C9, 0x00000659, 0x000020E5, 0xFFFFF313, 0x000003C6, 0x000020E5, 0xFFFFF313, 0x000003C6 }, + { 0x0213EA94DE0A3964, 0x000041DD, 0xFFFFDDFA, 0x0000071B, 0x0000348D, 0xFFFFE4B4, 0x0000064C, 0x0000348D, 0xFFFFE4B4, 0x0000064C }, + { 0x0213EA94DE2C2884, 0x00003947, 0xFFFFE5AE, 0x000005B8, 0x000024A6, 0xFFFFF140, 0x0000041D, 0x000024A6, 0xFFFFF140, 0x0000041D }, + { 0x0213EA94DE101844, 0x00003D35, 0xFFFFE197, 0x0000066E, 0x00002248, 0xFFFFF1BC, 0x00000408, 0x00002248, 0xFFFFF1BC, 0x00000408 }, + { 0x0213EA94DE0A18E4, 0x00003F4F, 0xFFFFE13E, 0x0000066D, 0x00002AF0, 0xFFFFEC99, 0x000004DB, 0x00002AF0, 0xFFFFEC99, 0x000004DB }, + { 0x0213EA94DE263944, 0x0000430F, 0xFFFFDDFB, 0x000006FC, 0x00002D4D, 0xFFFFEA55, 0x00000540, 0x00002D4D, 0xFFFFEA55, 0x00000540 }, + { 0x0213EA94DE0E2944, 0x00003B22, 0xFFFFE543, 0x000005B1, 0x000022E1, 0xFFFFF31B, 0x000003B9, 0x000022E1, 0xFFFFF31B, 0x000003B9 }, + { 0x0213EA94DE0E2084, 0x00003978, 0xFFFFE611, 0x00000592, 0x00001C36, 0xFFFFF771, 0x00000302, 0x00001C36, 0xFFFFF771, 0x00000302 }, + { 0x0213EA94DE262164, 0x000044DF, 0xFFFFDDAB, 0x000006F2, 0x00002CEA, 0xFFFFEB47, 0x00000507, 0x00002CEA, 0xFFFFEB47, 0x00000507 }, + { 0x0213EA94DE0A38C4, 0x00003E9B, 0xFFFFE12C, 0x0000067C, 0x00002B79, 0xFFFFEBD9, 0x00000503, 0x00002B79, 0xFFFFEBD9, 0x00000503 }, + { 0x0213EA94DE263044, 0x00004464, 0xFFFFDCD3, 0x00000731, 0x00002D14, 0xFFFFEA2D, 0x0000054E, 0x00002D14, 0xFFFFEA2D, 0x0000054E }, + { 0x0213EA94DE281124, 0x00003FB3, 0xFFFFE052, 0x00000693, 0x000020AC, 0xFFFFF311, 0x000003C6, 0x000020AC, 0xFFFFF311, 0x000003C6 }, + { 0x0213EA94DE2C1084, 0x00003BDA, 0xFFFFE2FB, 0x00000636, 0x0000261E, 0xFFFFEF72, 0x00000471, 0x0000261E, 0xFFFFEF72, 0x00000471 }, + { 0x0213EA94DE2C1964, 0x00003D72, 0xFFFFE28A, 0x0000063E, 0x000029D8, 0xFFFFED54, 0x000004C7, 0x000029D8, 0xFFFFED54, 0x000004C7 }, + { 0x0213EA94DE2C2824, 0x00003E26, 0xFFFFE102, 0x00000694, 0x00002DD1, 0xFFFFE9CA, 0x0000056D, 0x00002DD1, 0xFFFFE9CA, 0x0000056D }, + { 0x0213EA94DE104124, 0x000041CD, 0xFFFFDE97, 0x000006ED, 0x00002DE5, 0xFFFFE9B9, 0x00000565, 0x00002DE5, 0xFFFFE9B9, 0x00000565 }, + { 0x0213EA94DE0A2984, 0x00003F30, 0xFFFFE06E, 0x00000698, 0x000024FF, 0xFFFFEFFC, 0x0000044F, 0x000024FF, 0xFFFFEFFC, 0x0000044F }, + { 0x0213EA94DE2C38C4, 0x0000378B, 0xFFFFE6B4, 0x00000594, 0x000023A7, 0xFFFFF1DC, 0x00000407, 0x000023A7, 0xFFFFF1DC, 0x00000407 }, + { 0x0213EA94DE0E4164, 0x00003CD7, 0xFFFFE28D, 0x00000636, 0x00002036, 0xFFFFF3B5, 0x000003AA, 0x00002036, 0xFFFFF3B5, 0x000003AA }, + { 0x0213EA94DE0A3884, 0x00003EF9, 0xFFFFE0AA, 0x0000068D, 0x000024D3, 0xFFFFF02F, 0x00000445, 0x000024D3, 0xFFFFF02F, 0x00000445 }, + { 0x0213EA94DE283944, 0x00003D08, 0xFFFFE1BB, 0x00000665, 0x00002159, 0xFFFFF26F, 0x000003E6, 0x00002159, 0xFFFFF26F, 0x000003E6 }, + { 0x0213EA94DE2C20C4, 0x000038A9, 0xFFFFE6CA, 0x00000580, 0x000025D3, 0xFFFFF101, 0x00000421, 0x000025D3, 0xFFFFF101, 0x00000421 }, + { 0x0213EA94DE0A20A4, 0x00003E45, 0xFFFFE1F8, 0x0000064D, 0x000027E3, 0xFFFFEEBB, 0x0000047F, 0x000027E3, 0xFFFFEEBB, 0x0000047F }, + { 0x0213EA94DE0E3864, 0x00003F76, 0xFFFFE128, 0x0000066E, 0x0000286B, 0xFFFFEE4C, 0x00000493, 0x0000286B, 0xFFFFEE4C, 0x00000493 }, + { 0x0213EA94DE264104, 0x0000440D, 0xFFFFDCA2, 0x0000074F, 0x00003817, 0xFFFFE256, 0x000006AF, 0x00003817, 0xFFFFE256, 0x000006AF }, + { 0x0213EA94DE105104, 0x00003EE1, 0xFFFFDFA7, 0x000006D4, 0x000027EA, 0xFFFFED2B, 0x000004DE, 0x000027EA, 0xFFFFED2B, 0x000004DE }, + { 0x0213EA94DE2C3864, 0x00003C62, 0xFFFFE285, 0x0000064A, 0x00002520, 0xFFFFF001, 0x0000045C, 0x00002520, 0xFFFFF001, 0x0000045C }, + { 0x0213EA94DE323964, 0x0000272E, 0xFFFFF17A, 0x000003FA, 0x0000150B, 0xFFFFFBD5, 0x00000284, 0x0000150B, 0xFFFFFBD5, 0x00000284 }, + { 0x0213EA94DE261924, 0x00004275, 0xFFFFDF69, 0x000006A5, 0x000025AA, 0xFFFFF05C, 0x0000042B, 0x000025AA, 0xFFFFF05C, 0x0000042B }, + { 0x0213EA94DE0E40E4, 0x00003CAA, 0xFFFFE392, 0x000005FF, 0x000023A8, 0xFFFFF20E, 0x000003E9, 0x000023A8, 0xFFFFF20E, 0x000003E9 }, + { 0x0213EA94DE2C50C4, 0x00003CF8, 0xFFFFE0FB, 0x000006A6, 0x00002CA7, 0xFFFFE9FF, 0x0000056E, 0x00002CA7, 0xFFFFE9FF, 0x0000056E }, + { 0x0213EA94DE282124, 0x00003D00, 0xFFFFE296, 0x00000633, 0x000021C1, 0xFFFFF2C8, 0x000003CF, 0x000021C1, 0xFFFFF2C8, 0x000003CF }, + { 0x0213EA94DE2838E4, 0x00003B46, 0xFFFFE301, 0x00000632, 0x0000204C, 0xFFFFF33B, 0x000003C8, 0x0000204C, 0xFFFFF33B, 0x000003C8 }, + { 0x0213EA94DE204164, 0x00002026, 0xFFFFF5CE, 0x00000368, 0x00001598, 0xFFFFFB29, 0x000002C3, 0x00001598, 0xFFFFFB29, 0x000002C3 }, + { 0x0213EA94DE283164, 0x00003DCA, 0xFFFFE178, 0x00000668, 0x00001FDB, 0xFFFFF39D, 0x000003AF, 0x00001FDB, 0xFFFFF39D, 0x000003AF }, + { 0x0213EA94DE2C48C4, 0x00003A59, 0xFFFFE327, 0x00000642, 0x000024B9, 0xFFFFEFC4, 0x00000471, 0x000024B9, 0xFFFFEFC4, 0x00000471 }, + { 0x0213EA94DE2C2944, 0x00003C26, 0xFFFFE440, 0x000005EB, 0x00002C0F, 0xFFFFEC88, 0x000004E0, 0x00002C0F, 0xFFFFEC88, 0x000004E0 }, + { 0x0213EA94DE083884, 0x00004149, 0xFFFFDEB8, 0x000006E7, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, + { 0x0213EA94DE0E4124, 0x00003EB4, 0xFFFFE1E5, 0x0000064D, 0x0000299F, 0xFFFFEDB3, 0x000004A9, 0x0000299F, 0xFFFFEDB3, 0x000004A9 }, + { 0x0213EA94DE2C39A4, 0x00003BBF, 0xFFFFE268, 0x0000065A, 0x00002504, 0xFFFFEFB0, 0x00000470, 0x00002504, 0xFFFFEFB0, 0x00000470 }, + { 0x0213EA94DE084904, 0x00004203, 0xFFFFDDC6, 0x00000720, 0x0000303B, 0xFFFFE78F, 0x000005D0, 0x0000303B, 0xFFFFE78F, 0x000005D0 }, + { 0x0213EA94DE0E3984, 0x00003DA3, 0xFFFFE244, 0x0000063E, 0x000021B4, 0xFFFFF2DA, 0x000003CD, 0x000021B4, 0xFFFFF2DA, 0x000003CD }, + { 0x0213EA94DE0A38E4, 0x00004035, 0xFFFFE065, 0x0000069B, 0x00003323, 0xFFFFE6D6, 0x000005D8, 0x00003323, 0xFFFFE6D6, 0x000005D8 }, + { 0x0213EA94DE2C1164, 0x00003944, 0xFFFFE4E5, 0x000005E2, 0x00001F3C, 0xFFFFF456, 0x0000039D, 0x00001F3C, 0xFFFFF456, 0x0000039D }, + { 0x0213EA94DE061904, 0x000032D8, 0xFFFFEAE8, 0x000004E6, 0x00001812, 0xFFFFFA1C, 0x000002BC, 0x00001812, 0xFFFFFA1C, 0x000002BC }, + { 0x0213F0FD42D22944, 0x000041F6, 0xFFFFE025, 0x0000069A, 0x0000241E, 0xFFFFF1B4, 0x00000402, 0x0000241E, 0xFFFFF1B4, 0x00000402 }, + { 0x0213F0FE990C30A4, 0x00003300, 0xFFFFEB60, 0x000004C1, 0x00001E15, 0xFFFFF6A6, 0x0000033B, 0x00001E15, 0xFFFFF6A6, 0x0000033B }, + { 0x0213EA94DE0408A4, 0x000037F0, 0xFFFFE68F, 0x0000059B, 0x00001F8A, 0xFFFFF467, 0x000003A3, 0x00001F8A, 0xFFFFF467, 0x000003A3 }, + { 0x0213F0FE99182984, 0x000025D8, 0xFFFFF2AA, 0x000003C3, 0x000018A8, 0xFFFFF9BE, 0x000002D2, 0x000018A8, 0xFFFFF9BE, 0x000002D2 }, + { 0x0213F0FE990620C4, 0x0000364F, 0xFFFFE988, 0x000004FC, 0x00001E51, 0xFFFFF633, 0x0000034F, 0x00001E51, 0xFFFFF633, 0x0000034F }, + { 0x0213EA94DE061144, 0x00002288, 0xFFFFF483, 0x0000036C, 0x0000280F, 0xFFFFEF39, 0x0000047B, 0x0000280F, 0xFFFFEF39, 0x0000047B }, + { 0x0213F0FE99082084, 0x00003322, 0xFFFFEA7E, 0x000004ED, 0x00001DAD, 0xFFFFF62B, 0x00000355, 0x00001DAD, 0xFFFFF62B, 0x00000355 }, + { 0x0213EA94DE0250E4, 0x00002B7B, 0xFFFFEE4F, 0x0000045B, 0x00001AA2, 0xFFFFF710, 0x0000033E, 0x00001AA2, 0xFFFFF710, 0x0000033E }, + { 0x0213F0FE990420C4, 0x000034CC, 0xFFFFEA79, 0x000004E4, 0x00001B05, 0xFFFFF8B3, 0x000002EC, 0x00001B05, 0xFFFFF8B3, 0x000002EC }, + { 0x0213F0FD42DC2864, 0x00003837, 0xFFFFE5ED, 0x000005C3, 0x00001ACB, 0xFFFFF7B2, 0x00000314, 0x00001ACB, 0xFFFFF7B2, 0x00000314 }, + { 0x0213F0FE99044164, 0x0000352D, 0xFFFFE88F, 0x00000548, 0x000021E6, 0xFFFFF3B5, 0x000003AA, 0x000021E6, 0xFFFFF3B5, 0x000003AA }, + { 0x0213F0FE990A4884, 0x00003300, 0xFFFFE835, 0x0000057B, 0x00001A85, 0xFFFFF715, 0x00000336, 0x00001A85, 0xFFFFF715, 0x00000336 }, + { 0x0213EA94DE0448A4, 0x000033FA, 0xFFFFE851, 0x00000565, 0x00001A8E, 0xFFFFF727, 0x0000033B, 0x00001A8E, 0xFFFFF727, 0x0000033B }, + { 0x0213F0FD42DA3924, 0x000039D3, 0xFFFFE5D3, 0x000005B0, 0x00001888, 0xFFFFF978, 0x000002C8, 0x00001888, 0xFFFFF978, 0x000002C8 }, + { 0x0213F0FE990E4864, 0x00002F6B, 0xFFFFEC53, 0x000004B9, 0x00001C15, 0xFFFFF71B, 0x00000337, 0x00001C15, 0xFFFFF71B, 0x00000337 }, + { 0x0213F0FE99064144, 0x0000384D, 0xFFFFE737, 0x00000569, 0x00001D2D, 0xFFFFF673, 0x00000343, 0x00001D2D, 0xFFFFF673, 0x00000343 }, + { 0x0213F0FE990620A4, 0x00003A49, 0xFFFFE70B, 0x0000055F, 0x00001A63, 0xFFFFF8CD, 0x000002E2, 0x00001A63, 0xFFFFF8CD, 0x000002E2 }, + { 0x0213F0FE99042984, 0x0000311E, 0xFFFFEB97, 0x000004C6, 0x00001EAE, 0xFFFFF5A9, 0x00000367, 0x00001EAE, 0xFFFFF5A9, 0x00000367 }, + { 0x0213F0FE990E1124, 0x000027D3, 0xFFFFF075, 0x00000417, 0x00002001, 0xFFFFF44A, 0x000003A2, 0x00002001, 0xFFFFF44A, 0x000003A2 }, + { 0x0213F0FE99064904, 0x00003B72, 0xFFFFE4BD, 0x000005DC, 0x00001D76, 0xFFFFF606, 0x0000035A, 0x00001D76, 0xFFFFF606, 0x0000035A }, + { 0x0213F0FE99101124, 0x00002E0F, 0xFFFFECA7, 0x000004AE, 0x00001DC6, 0xFFFFF5BF, 0x0000036A, 0x00001DC6, 0xFFFFF5BF, 0x0000036A }, + { 0x0213F0FE990238A4, 0x000032C7, 0xFFFFEA7A, 0x000004F0, 0x00001A7B, 0xFFFFF827, 0x00000301, 0x00001A7B, 0xFFFFF827, 0x00000301 }, + { 0x0213EA94DE044884, 0x0000312D, 0xFFFFEA39, 0x00000515, 0x00001948, 0xFFFFF800, 0x00000318, 0x00001948, 0xFFFFF800, 0x00000318 }, + { 0x0213EA94DE062084, 0x00003611, 0xFFFFE8D7, 0x00000533, 0x00001929, 0xFFFFF965, 0x000002D2, 0x00001929, 0xFFFFF965, 0x000002D2 }, + { 0x0213F0FE992C30E4, 0x00002FE2, 0xFFFFED89, 0x00000470, 0x00001A3C, 0xFFFFF955, 0x000002D5, 0x00001A3C, 0xFFFFF955, 0x000002D5 }, + { 0x0213EA94DE0208A4, 0x000035FF, 0xFFFFE884, 0x00000548, 0x0000182A, 0xFFFFF9AB, 0x000002CF, 0x0000182A, 0xFFFFF9AB, 0x000002CF }, + { 0x0213F0FE990220E4, 0x00003597, 0xFFFFE904, 0x00000528, 0x00001A94, 0xFFFFF840, 0x00000300, 0x00001A94, 0xFFFFF840, 0x00000300 }, + { 0x0213F0FE99181944, 0x000026CB, 0xFFFFF1FB, 0x000003E4, 0x000017CC, 0xFFFFFA25, 0x000002C8, 0x000017CC, 0xFFFFFA25, 0x000002C8 }, + { 0x0213EA94DE0608C4, 0x00003274, 0xFFFFEA39, 0x0000050C, 0x00001B20, 0xFFFFF7C1, 0x00000314, 0x00001B20, 0xFFFFF7C1, 0x00000314 }, + { 0x0213F0FD42D82924, 0x0000280B, 0xFFFFF283, 0x000003B5, 0x000018D0, 0xFFFFF992, 0x000002EC, 0x000018D0, 0xFFFFF992, 0x000002EC }, + { 0x0213F0FE99062104, 0x000033AB, 0xFFFFEB1B, 0x000004C4, 0x00001FEE, 0xFFFFF53A, 0x00000378, 0x00001FEE, 0xFFFFF53A, 0x00000378 }, + { 0x0213F0FE990A3964, 0x00002F79, 0xFFFFEB0C, 0x000004FA, 0x00001E57, 0xFFFFF4BF, 0x0000039B, 0x00001E57, 0xFFFFF4BF, 0x0000039B }, + { 0x0213F0FE990448E4, 0x00003487, 0xFFFFE8F2, 0x00000539, 0x0000185B, 0xFFFFF9AE, 0x000002BA, 0x0000185B, 0xFFFFF9AE, 0x000002BA }, + { 0x0213F0FE990A18A4, 0x00003500, 0xFFFFE793, 0x0000058A, 0x00001AA2, 0xFFFFF792, 0x0000031D, 0x00001AA2, 0xFFFFF792, 0x0000031D }, + { 0x0213F0FE99081164, 0x00003943, 0xFFFFE54D, 0x000005D9, 0x00001BC8, 0xFFFFF6E0, 0x00000339, 0x00001BC8, 0xFFFFF6E0, 0x00000339 }, + { 0x0213EA94DE0430A4, 0x0000306D, 0xFFFFEC5E, 0x000004A5, 0x00001A3A, 0xFFFFF85F, 0x00000304, 0x00001A3A, 0xFFFFF85F, 0x00000304 }, + { 0x0213F0FD42D83084, 0x00002BA4, 0xFFFFEE8D, 0x0000046A, 0x0000198C, 0xFFFFF88E, 0x00000307, 0x0000198C, 0xFFFFF88E, 0x00000307 }, + { 0x0213F0FD42D218E4, 0x00003D30, 0xFFFFE2F6, 0x0000062A, 0x000025DC, 0xFFFFF074, 0x00000435, 0x000025DC, 0xFFFFF074, 0x00000435 }, + { 0x0213F0FD42D83964, 0x00002CD6, 0xFFFFED79, 0x0000049B, 0x000016D0, 0xFFFFFA53, 0x000002BB, 0x000016D0, 0xFFFFFA53, 0x000002BB }, + { 0x0213F0FE99163164, 0x00002484, 0xFFFFF3BD, 0x000003A0, 0x000015B8, 0xFFFFFB6B, 0x000002A4, 0x000015B8, 0xFFFFFB6B, 0x000002A4 }, + { 0x0213F0FE990E3944, 0x000038AE, 0xFFFFE6D1, 0x00000587, 0x00001A2A, 0xFFFFF8F1, 0x000002D4, 0x00001A2A, 0xFFFFF8F1, 0x000002D4 }, + { 0x0213F0FE99044944, 0x000036FD, 0xFFFFE76C, 0x00000576, 0x00001EE4, 0xFFFFF58D, 0x00000361, 0x00001EE4, 0xFFFFF58D, 0x00000361 }, + { 0x0213F0FD42D830A4, 0x00002BCF, 0xFFFFEF28, 0x00000448, 0x00001B93, 0xFFFFF7BA, 0x00000327, 0x00001B93, 0xFFFFF7BA, 0x00000327 }, + { 0x0213F0FE99062884, 0x00003834, 0xFFFFE818, 0x0000053B, 0x00001AFE, 0xFFFFF85C, 0x000002F3, 0x00001AFE, 0xFFFFF85C, 0x000002F3 }, + { 0x0213F0FE993231A4, 0x00002EF7, 0xFFFFEBFC, 0x000004CE, 0x00001897, 0xFFFFF8EF, 0x000002EC, 0x00001897, 0xFFFFF8EF, 0x000002EC }, + { 0x0213F0FE992C18C4, 0x000035BD, 0xFFFFE8BB, 0x0000053B, 0x00001F22, 0xFFFFF561, 0x00000373, 0x00001F22, 0xFFFFF561, 0x00000373 }, + { 0x0213F0FE99183984, 0x00002D42, 0xFFFFEE1D, 0x00000478, 0x000016F0, 0xFFFFFAAE, 0x000002B3, 0x000016F0, 0xFFFFFAAE, 0x000002B3 }, + { 0x0213EA94DE045124, 0x00002F98, 0xFFFFEB3C, 0x000004F0, 0x00001903, 0xFFFFF818, 0x00000319, 0x00001903, 0xFFFFF818, 0x00000319 }, + { 0x0213F0FD42D42144, 0x00004081, 0xFFFFDF13, 0x000006F3, 0x00002A6D, 0xFFFFEC1B, 0x00000509, 0x00002A6D, 0xFFFFEC1B, 0x00000509 }, + { 0x0213EA94DE040904, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001FF6, 0xFFFFF427, 0x000003B0, 0x00001FF6, 0xFFFFF427, 0x000003B0 }, + { 0x0213F0FE99023884, 0x00003243, 0xFFFFEA5C, 0x000004FD, 0x000020FB, 0xFFFFF39E, 0x000003C0, 0x000020FB, 0xFFFFF39E, 0x000003C0 }, + { 0x0213F0FD42D848A4, 0x00002F20, 0xFFFFEC19, 0x000004C6, 0x00001748, 0xFFFFF99F, 0x000002DA, 0x00001748, 0xFFFFF99F, 0x000002DA }, + { 0x0213F0FE99103984, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001A43, 0xFFFFF843, 0x000002F9, 0x00001A43, 0xFFFFF843, 0x000002F9 }, + { 0x0213F0FE990220A4, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x00001A51, 0xFFFFF850, 0x000002FA, 0x00001A51, 0xFFFFF850, 0x000002FA }, + { 0x0213F0FE99043144, 0x0000305C, 0xFFFFED4B, 0x0000046C, 0x00001CF9, 0xFFFFF7BA, 0x00000304, 0x00001CF9, 0xFFFFF7BA, 0x00000304 }, + { 0x0213F0FD42DA4164, 0x0000343C, 0xFFFFE869, 0x00000559, 0x00001CE2, 0xFFFFF614, 0x00000359, 0x00001CE2, 0xFFFFF614, 0x00000359 }, + { 0x0213F0FE99183964, 0x00002782, 0xFFFFF1FE, 0x000003D9, 0x000015DC, 0xFFFFFB8B, 0x00000290, 0x000015DC, 0xFFFFFB8B, 0x00000290 }, + { 0x0213F0FE991818C4, 0x00002B9C, 0xFFFFEF63, 0x00000443, 0x00001369, 0xFFFFFD51, 0x00000244, 0x00001369, 0xFFFFFD51, 0x00000244 }, + { 0x0213F0FE990A2084, 0x000035F8, 0xFFFFE743, 0x00000592, 0x000018D8, 0xFFFFF8EE, 0x000002E4, 0x000018D8, 0xFFFFF8EE, 0x000002E4 }, + { 0x0213EA94DE062844, 0x00002B72, 0xFFFFEF1E, 0x0000043C, 0x00002647, 0xFFFFF092, 0x0000043E, 0x00002647, 0xFFFFF092, 0x0000043E }, + { 0x0213F0FE99102184, 0x00002EC9, 0xFFFFEC5F, 0x000004B8, 0x000018B6, 0xFFFFF936, 0x000002D8, 0x000018B6, 0xFFFFF936, 0x000002D8 }, + { 0x0213F0FE99064084, 0x000038A7, 0xFFFFE6AC, 0x00000589, 0x00001C42, 0xFFFFF70B, 0x00000329, 0x00001C42, 0xFFFFF70B, 0x00000329 }, + { 0x0213F0FE993008A4, 0x00002F6B, 0xFFFFEBF6, 0x000004CF, 0x000018AE, 0xFFFFF928, 0x000002E3, 0x000018AE, 0xFFFFF928, 0x000002E3 }, + { 0x0213F0FD42DA5104, 0x000029CD, 0xFFFFEEE1, 0x00000459, 0x00001AB5, 0xFFFFF76F, 0x00000324, 0x00001AB5, 0xFFFFF76F, 0x00000324 }, + { 0x0213EA94DE0638C4, 0x00003921, 0xFFFFE71D, 0x00000577, 0x00001646, 0xFFFFFB24, 0x00000293, 0x00001646, 0xFFFFFB24, 0x00000293 }, + { 0x0213EA94DE044164, 0x00003940, 0xFFFFE521, 0x000005E8, 0x00001947, 0xFFFFF839, 0x0000030D, 0x00001947, 0xFFFFF839, 0x0000030D }, + { 0x0213F0FD42D24164, 0x00003DCA, 0xFFFFE211, 0x00000659, 0x0000250E, 0xFFFFF072, 0x00000443, 0x0000250E, 0xFFFFF072, 0x00000443 }, + { 0x0213F0FE990C0904, 0x00002E95, 0xFFFFEC20, 0x000004C9, 0x000015B4, 0xFFFFFAD3, 0x0000029D, 0x000015B4, 0xFFFFFAD3, 0x0000029D }, + { 0x0213F0FE99041084, 0x00002C11, 0xFFFFEE6E, 0x00000468, 0x00001901, 0xFFFFF924, 0x000002E7, 0x00001901, 0xFFFFF924, 0x000002E7 }, + { 0x0213EA94DE062104, 0x0000293F, 0xFFFFF158, 0x000003E6, 0x0000183F, 0xFFFFF9F6, 0x000002D2, 0x0000183F, 0xFFFFF9F6, 0x000002D2 }, + { 0x0213F0FE990E1104, 0x00002A67, 0xFFFFEF34, 0x0000043E, 0x00001C6F, 0xFFFFF6F1, 0x0000032B, 0x00001C6F, 0xFFFFF6F1, 0x0000032B }, + { 0x0213EA94DE065124, 0x00002F8D, 0xFFFFEB77, 0x000004DA, 0x00001C0D, 0xFFFFF627, 0x00000365, 0x00001C0D, 0xFFFFF627, 0x00000365 }, + { 0x0213F0FE990C38C4, 0x00003476, 0xFFFFEA5B, 0x000004E7, 0x00001DBF, 0xFFFFF6C7, 0x00000333, 0x00001DBF, 0xFFFFF6C7, 0x00000333 }, + { 0x0213F0FE990E0944, 0x00003336, 0xFFFFE92F, 0x00000546, 0x00001614, 0xFFFFFAE0, 0x00000296, 0x00001614, 0xFFFFFAE0, 0x00000296 }, + { 0x0213F0FE99162164, 0x00002513, 0xFFFFF323, 0x000003BC, 0x000016DB, 0xFFFFFA79, 0x000002CD, 0x000016DB, 0xFFFFFA79, 0x000002CD }, + { 0x0213F0FE990A2944, 0x000035A7, 0xFFFFE78E, 0x00000584, 0x00001B0D, 0xFFFFF77D, 0x0000031F, 0x00001B0D, 0xFFFFF77D, 0x0000031F }, + { 0x0213F0FE993238E4, 0x00003171, 0xFFFFEB98, 0x000004C6, 0x00001C76, 0xFFFFF71F, 0x0000032F, 0x00001C76, 0xFFFFF71F, 0x0000032F }, + { 0x0213F0FD42DA1084, 0x00002C52, 0xFFFFED2E, 0x000004A7, 0x00002182, 0xFFFFF2F4, 0x000003E4, 0x00002182, 0xFFFFF2F4, 0x000003E4 }, + { 0x0213F0FE99102924, 0x000032E1, 0xFFFFEB39, 0x000004D0, 0x00001B55, 0xFFFFF859, 0x000002FA, 0x00001B55, 0xFFFFF859, 0x000002FA }, + { 0x0213F0FE991848A4, 0x000029B6, 0xFFFFEFF7, 0x00000430, 0x0000151B, 0xFFFFFBC6, 0x0000027F, 0x0000151B, 0xFFFFFBC6, 0x0000027F }, + { 0x0213F0FD42DA1964, 0x00002FF7, 0xFFFFEB67, 0x000004DA, 0x000020E9, 0xFFFFF363, 0x000003CE, 0x000020E9, 0xFFFFF363, 0x000003CE }, + { 0x0213F0FD42DA5124, 0x00003CDD, 0xFFFFE2B2, 0x00000649, 0x00001B18, 0xFFFFF739, 0x00000329, 0x00001B18, 0xFFFFF739, 0x00000329 }, + { 0x0213F0FE990628A4, 0x00003C82, 0xFFFFE5C6, 0x0000058E, 0x00001F3F, 0xFFFFF5AD, 0x00000361, 0x00001F3F, 0xFFFFF5AD, 0x00000361 }, + { 0x0213F0FD42DC4084, 0x0000319B, 0xFFFFEA15, 0x0000051B, 0x00001CC9, 0xFFFFF62E, 0x00000358, 0x00001CC9, 0xFFFFF62E, 0x00000358 }, + { 0x0213EA94DE0638E4, 0x000032B6, 0xFFFFEB2B, 0x000004D6, 0x000018E0, 0xFFFFF966, 0x000002DE, 0x000018E0, 0xFFFFF966, 0x000002DE }, + { 0x0213EA94DE023984, 0x0000300A, 0xFFFFEBA6, 0x000004D1, 0x00001CFD, 0xFFFFF5F6, 0x0000036D, 0x00001CFD, 0xFFFFF5F6, 0x0000036D }, + { 0x0213F0FD42D82984, 0x000026A9, 0xFFFFF15D, 0x00000400, 0x00001561, 0xFFFFFB1F, 0x000002A0, 0x00001561, 0xFFFFFB1F, 0x000002A0 }, + { 0x0213F0FE990E5124, 0x00003123, 0xFFFFEAD2, 0x000004FA, 0x000018CB, 0xFFFFF8F5, 0x000002EC, 0x000018CB, 0xFFFFF8F5, 0x000002EC }, + { 0x0213F0FE991840C4, 0x00003577, 0xFFFFE935, 0x00000533, 0x000016CD, 0xFFFFFB44, 0x00000289, 0x000016CD, 0xFFFFFB44, 0x00000289 }, + { 0x0213F0FE99282184, 0x00002875, 0xFFFFF170, 0x000003F3, 0x00001567, 0xFFFFFBD5, 0x00000289, 0x00001567, 0xFFFFFBD5, 0x00000289 }, + { 0x0213F0FE99084084, 0x00003AE2, 0xFFFFE538, 0x000005C1, 0x00001CB4, 0xFFFFF6A3, 0x0000033C, 0x00001CB4, 0xFFFFF6A3, 0x0000033C }, + { 0x0213F0FE990C38E4, 0x000031DF, 0xFFFFEC2A, 0x000004A3, 0x00001EF0, 0xFFFFF626, 0x00000352, 0x00001EF0, 0xFFFFF626, 0x00000352 }, + { 0x0213F0FD42D25144, 0x00004A6A, 0xFFFFDB15, 0x00000758, 0x000027F3, 0xFFFFEEEE, 0x00000479, 0x000027F3, 0xFFFFEEEE, 0x00000479 }, + { 0x0213EA94DE063904, 0x00002BB9, 0xFFFFEF5D, 0x00000433, 0x00001589, 0xFFFFFB57, 0x00000295, 0x00001589, 0xFFFFFB57, 0x00000295 }, + { 0x0213F0FE99042164, 0x000033A0, 0xFFFFE98F, 0x00000528, 0x00001CB4, 0xFFFFF706, 0x0000032D, 0x00001CB4, 0xFFFFF706, 0x0000032D }, + { 0x0213F0FE99163064, 0x0000248E, 0xFFFFF380, 0x000003AC, 0x000016EA, 0xFFFFFA6C, 0x000002CE, 0x000016EA, 0xFFFFFA6C, 0x000002CE }, + { 0x0213F0FE990221A4, 0x00002FE2, 0xFFFFEB2F, 0x000004E9, 0x00001D4E, 0xFFFFF56B, 0x00000380, 0x00001D4E, 0xFFFFF56B, 0x00000380 }, + { 0x0213F0FE990A2884, 0x00003283, 0xFFFFE9E7, 0x0000051D, 0x00000694, 0xFFFFFD32, 0x000003C3, 0x00000694, 0xFFFFFD32, 0x000003C3 }, + { 0x0213F0FD42D850C4, 0x00002EE4, 0xFFFFEBFD, 0x000004D3, 0x0000151A, 0xFFFFFAF6, 0x000002A4, 0x0000151A, 0xFFFFFAF6, 0x000002A4 }, + { 0x0213F0FD42DC18E4, 0x0000302D, 0xFFFFEB7F, 0x000004DA, 0x00001E6D, 0xFFFFF54B, 0x00000380, 0x00001E6D, 0xFFFFF54B, 0x00000380 }, + { 0x0213F0FD42DA50C4, 0x000033DA, 0xFFFFE7FB, 0x0000057F, 0x00001DED, 0xFFFFF50E, 0x0000038D, 0x00001DED, 0xFFFFF50E, 0x0000038D }, + { 0x0213F0FE992C4084, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001C3F, 0xFFFFF726, 0x0000032A, 0x00001C3F, 0xFFFFF726, 0x0000032A }, + { 0x0213F0FE990831C4, 0x00003BBD, 0xFFFFE55C, 0x000005B8, 0x000019DB, 0xFFFFF8BB, 0x000002EF, 0x000019DB, 0xFFFFF8BB, 0x000002EF }, + { 0x0213F0FE990E3884, 0x00002964, 0xFFFFF051, 0x0000040E, 0x000025CD, 0xFFFFF11B, 0x0000041F, 0x000025CD, 0xFFFFF11B, 0x0000041F }, + { 0x0213F0FD42DC4884, 0x000033F5, 0xFFFFE863, 0x00000560, 0x00001BCE, 0xFFFFF689, 0x0000034B, 0x00001BCE, 0xFFFFF689, 0x0000034B }, + { 0x0213F0FE990A2864, 0x00003294, 0xFFFFE924, 0x00000548, 0x00001D41, 0xFFFFF580, 0x0000037D, 0x00001D41, 0xFFFFF580, 0x0000037D }, + { 0x0213F0FD42DC39A4, 0x000034FB, 0xFFFFE7FE, 0x0000056D, 0x00001CB1, 0xFFFFF635, 0x00000357, 0x00001CB1, 0xFFFFF635, 0x00000357 }, + { 0x0213F0FE990A10A4, 0x00002E28, 0xFFFFEBB9, 0x000004E0, 0x00001B20, 0xFFFFF6E3, 0x0000033C, 0x00001B20, 0xFFFFF6E3, 0x0000033C }, + { 0x0213F0FD42DA1904, 0x00002799, 0xFFFFF0F4, 0x000003FC, 0x00001C9D, 0xFFFFF6A1, 0x00000345, 0x00001C9D, 0xFFFFF6A1, 0x00000345 }, + { 0x0213F0FE99064104, 0x00003AEA, 0xFFFFE5DB, 0x0000059D, 0x00001B61, 0xFFFFF7F0, 0x00000301, 0x00001B61, 0xFFFFF7F0, 0x00000301 }, + { 0x0213EA94DE041984, 0x000031F6, 0xFFFFEAB8, 0x000004F3, 0x00001D90, 0xFFFFF622, 0x00000359, 0x00001D90, 0xFFFFF622, 0x00000359 }, + { 0x0213F0FE990C4064, 0x000031B8, 0xFFFFEA61, 0x0000050F, 0x0000199D, 0xFFFFF87C, 0x000002FD, 0x0000199D, 0xFFFFF87C, 0x000002FD }, + { 0x0213F0FD42D23144, 0x00004514, 0xFFFFDDFF, 0x000006F6, 0x000022CD, 0xFFFFF29F, 0x000003D9, 0x000022CD, 0xFFFFF29F, 0x000003D9 }, + { 0x0213EA94DE043164, 0x00002F30, 0xFFFFECB8, 0x000004A0, 0x00001B07, 0xFFFFF7E2, 0x00000313, 0x00001B07, 0xFFFFF7E2, 0x00000313 }, + { 0x0213F0FD42DC30A4, 0x0000383B, 0xFFFFE702, 0x00000581, 0x00001A08, 0xFFFFF8CA, 0x000002E2, 0x00001A08, 0xFFFFF8CA, 0x000002E2 }, + { 0x0213F0FE99022164, 0x00002CC5, 0xFFFFEDF8, 0x00000465, 0x00001F47, 0xFFFFF4B2, 0x00000393, 0x00001F47, 0xFFFFF4B2, 0x00000393 }, + { 0x0213F0FE991621C4, 0x00002304, 0xFFFFF453, 0x00000384, 0x0000170A, 0xFFFFFA3F, 0x000002CE, 0x0000170A, 0xFFFFFA3F, 0x000002CE }, + { 0x0213F0FE990A5124, 0x0000337E, 0xFFFFE850, 0x0000056E, 0x00001BDD, 0xFFFFF668, 0x00000353, 0x00001BDD, 0xFFFFF668, 0x00000353 }, + { 0x0213F0FE990E4924, 0x00002E2F, 0xFFFFEC9B, 0x000004AE, 0x00001C4D, 0xFFFFF6D3, 0x00000338, 0x00001C4D, 0xFFFFF6D3, 0x00000338 }, + { 0x0213EA94DE061124, 0x00002DDD, 0xFFFFEDA4, 0x00000477, 0x00002010, 0xFFFFF4BB, 0x00000390, 0x00002010, 0xFFFFF4BB, 0x00000390 }, + { 0x0213F0FD42DA48E4, 0x0000290C, 0xFFFFEF61, 0x00000445, 0x00002133, 0xFFFFF324, 0x000003D8, 0x00002133, 0xFFFFF324, 0x000003D8 }, + { 0x0213F0FE99062924, 0x0000371E, 0xFFFFE8D5, 0x00000524, 0x00001C3A, 0xFFFFF7AE, 0x00000314, 0x00001C3A, 0xFFFFF7AE, 0x00000314 }, + { 0x0213F0FD42D838E4, 0x00002A58, 0xFFFFF007, 0x00000429, 0x000018A6, 0xFFFFF98F, 0x000002E1, 0x000018A6, 0xFFFFF98F, 0x000002E1 }, + { 0x0213F0FE99023084, 0x00002FED, 0xFFFFEC48, 0x000004AA, 0x00001E9D, 0xFFFFF584, 0x00000370, 0x00001E9D, 0xFFFFF584, 0x00000370 }, + { 0x0213F0FE99181884, 0x00002829, 0xFFFFF15F, 0x000003F7, 0x0000157E, 0xFFFFFBD4, 0x00000282, 0x0000157E, 0xFFFFFBD4, 0x00000282 }, + { 0x0213F0FE99101924, 0x000030CF, 0xFFFFEB8D, 0x000004CE, 0x00001A4C, 0xFFFFF868, 0x000002F7, 0x00001A4C, 0xFFFFF868, 0x000002F7 }, + { 0x0213F0FD42DA2084, 0x00002C8F, 0xFFFFEDD2, 0x0000047D, 0x00001CCE, 0xFFFFF6A1, 0x00000343, 0x00001CCE, 0xFFFFF6A1, 0x00000343 }, + { 0x0213F0FE99182164, 0x00002A84, 0xFFFFEFBA, 0x0000043E, 0x000015EF, 0xFFFFFB4B, 0x0000029E, 0x000015EF, 0xFFFFFB4B, 0x0000029E }, + { 0x0213F0FE990C28A4, 0x000034CA, 0xFFFFEA08, 0x000004FF, 0x00001C19, 0xFFFFF7ED, 0x00000309, 0x00001C19, 0xFFFFF7ED, 0x00000309 }, + { 0x0213F0FE991639A4, 0x00002187, 0xFFFFF4B0, 0x0000037E, 0x0000154A, 0xFFFFFB0C, 0x000002AE, 0x0000154A, 0xFFFFFB0C, 0x000002AE }, + { 0x0213F0FD42DA3844, 0x00002F4F, 0xFFFFEB3C, 0x000004F8, 0x0000181F, 0xFFFFF92D, 0x000002DF, 0x0000181F, 0xFFFFF92D, 0x000002DF }, + { 0x0213F0FE990410E4, 0x0000290C, 0xFFFFF0B1, 0x000003FC, 0x00001DB0, 0xFFFFF636, 0x00000355, 0x00001DB0, 0xFFFFF636, 0x00000355 }, + { 0x0213F0FE990A1064, 0x000034C1, 0xFFFFE888, 0x0000055A, 0x000019BF, 0xFFFFF881, 0x000002FB, 0x000019BF, 0xFFFFF881, 0x000002FB }, + { 0x0213F0FD42DC18C4, 0x00003139, 0xFFFFEA98, 0x00000504, 0x000019F2, 0xFFFFF820, 0x0000030B, 0x000019F2, 0xFFFFF820, 0x0000030B }, + { 0x0213F0FD42D83144, 0x00002CAC, 0xFFFFEEB2, 0x00000458, 0x0000152C, 0xFFFFFBEF, 0x0000027B, 0x0000152C, 0xFFFFFBEF, 0x0000027B }, + { 0x0213F0FE992C38E4, 0x00003577, 0xFFFFE99C, 0x0000050D, 0x00001E64, 0xFFFFF679, 0x0000033F, 0x00001E64, 0xFFFFF679, 0x0000033F }, + { 0x0213F0FD42DA4104, 0x0000263A, 0xFFFFF1E4, 0x000003D4, 0x00001F68, 0xFFFFF4ED, 0x00000386, 0x00001F68, 0xFFFFF4ED, 0x00000386 }, + { 0x0213F0FD42D81984, 0x00002CE9, 0xFFFFED63, 0x00000497, 0x00001810, 0xFFFFF94D, 0x000002E3, 0x00001810, 0xFFFFF94D, 0x000002E3 }, + { 0x0213EA94DE044104, 0x0000318A, 0xFFFFEAC8, 0x000004F5, 0x0000195C, 0xFFFFF896, 0x000002FB, 0x0000195C, 0xFFFFF896, 0x000002FB }, + { 0x0213F0FD42D83904, 0x00002C41, 0xFFFFEEC6, 0x0000045D, 0x000017DD, 0xFFFFFA16, 0x000002CB, 0x000017DD, 0xFFFFFA16, 0x000002CB }, + { 0x0213F0FE990231A4, 0x00002DD4, 0xFFFFEC98, 0x000004AD, 0x00001BD7, 0xFFFFF69F, 0x00000347, 0x00001BD7, 0xFFFFF69F, 0x00000347 }, + { 0x0213F0FD42DA3944, 0x00003351, 0xFFFFE9B2, 0x0000051A, 0x00001CA1, 0xFFFFF6A4, 0x00000341, 0x00001CA1, 0xFFFFF6A4, 0x00000341 }, + { 0x0213F0FE99021104, 0x0000322D, 0xFFFFE9BE, 0x00000527, 0x00001CF9, 0xFFFFF5EB, 0x00000366, 0x00001CF9, 0xFFFFF5EB, 0x00000366 }, + { 0x0213F0FE990C28C4, 0x00003678, 0xFFFFE9A8, 0x00000503, 0x00001AD4, 0xFFFFF8F6, 0x000002E3, 0x00001AD4, 0xFFFFF8F6, 0x000002E3 }, + { 0x0213F0FE99161924, 0x0000260E, 0xFFFFF2C1, 0x000003CA, 0x00001139, 0xFFFFFE48, 0x00000236, 0x00001139, 0xFFFFFE48, 0x00000236 }, + { 0x0213F0FE990A2164, 0x000033D3, 0xFFFFE872, 0x00000565, 0x00001B72, 0xFFFFF713, 0x00000332, 0x00001B72, 0xFFFFF713, 0x00000332 }, + { 0x0213F0FE99323844, 0x0000309B, 0xFFFFEB42, 0x000004E4, 0x00001918, 0xFFFFF8C8, 0x000002F2, 0x00001918, 0xFFFFF8C8, 0x000002F2 }, + { 0x0213F0FE99182864, 0x000028B8, 0xFFFFF105, 0x00000402, 0x000018BB, 0xFFFFF9BC, 0x000002D3, 0x000018BB, 0xFFFFF9BC, 0x000002D3 }, + { 0x0213F0FE990A1884, 0x00003123, 0xFFFFE9D1, 0x00000534, 0x00001B19, 0xFFFFF6FE, 0x0000033C, 0x00001B19, 0xFFFFF6FE, 0x0000033C }, + { 0x0213F0FE99022144, 0x00003216, 0xFFFFEA8E, 0x000004F6, 0x00001F72, 0xFFFFF4CE, 0x0000038B, 0x00001F72, 0xFFFFF4CE, 0x0000038B }, + { 0x0213F0FE99162964, 0x00002564, 0xFFFFF32D, 0x000003B6, 0x00001685, 0xFFFFFADB, 0x000002BB, 0x00001685, 0xFFFFFADB, 0x000002BB }, + { 0x0213F0FD42DA2924, 0x00002E60, 0xFFFFED13, 0x00000497, 0x00001CA5, 0xFFFFF6B9, 0x00000346, 0x00001CA5, 0xFFFFF6B9, 0x00000346 }, + { 0x0213F0FE990E39A4, 0x0000336D, 0xFFFFE934, 0x0000053B, 0x00001B3E, 0xFFFFF763, 0x00000327, 0x00001B3E, 0xFFFFF763, 0x00000327 }, + { 0x0213F0FE99101084, 0x0000274A, 0xFFFFF119, 0x000003FA, 0x00001D75, 0xFFFFF5CD, 0x0000036F, 0x00001D75, 0xFFFFF5CD, 0x0000036F }, + { 0x0213F0FD42DA2164, 0x0000366B, 0xFFFFE70A, 0x0000059A, 0x00001ED8, 0xFFFFF501, 0x00000389, 0x00001ED8, 0xFFFFF501, 0x00000389 }, + { 0x0213F0FE99223964, 0x00003164, 0xFFFFEAB4, 0x000004FA, 0x00001C52, 0xFFFFF6E0, 0x00000336, 0x00001C52, 0xFFFFF6E0, 0x00000336 }, + { 0x0213F0FD42D23064, 0x00004224, 0xFFFFDF7F, 0x000006C1, 0x00002A52, 0xFFFFED5E, 0x000004BB, 0x00002A52, 0xFFFFED5E, 0x000004BB }, + { 0x0213F0FE99102864, 0x000030E3, 0xFFFFEB07, 0x000004ED, 0x00001FD3, 0xFFFFF46D, 0x000003A1, 0x00001FD3, 0xFFFFF46D, 0x000003A1 }, + { 0x0213F0FD42D82884, 0x00002AEB, 0xFFFFEF1B, 0x00000454, 0x00001829, 0xFFFFF995, 0x000002DD, 0x00001829, 0xFFFFF995, 0x000002DD }, + { 0x0213F0FD42DC50E4, 0x0000346B, 0xFFFFE7A2, 0x0000058B, 0x000020C5, 0xFFFFF2E8, 0x000003EC, 0x000020C5, 0xFFFFF2E8, 0x000003EC }, + { 0x0213F0FD42DC4164, 0x000039CF, 0xFFFFE5D7, 0x000005A9, 0x00001D66, 0xFFFFF5D6, 0x00000366, 0x00001D66, 0xFFFFF5D6, 0x00000366 }, + { 0x0213F0FE990418E4, 0x000034AC, 0xFFFFE9AE, 0x00000515, 0x00001A28, 0xFFFFF904, 0x000002DC, 0x00001A28, 0xFFFFF904, 0x000002DC }, + { 0x0213F0FD42DC2084, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001C6F, 0xFFFFF686, 0x0000034C, 0x00001C6F, 0xFFFFF686, 0x0000034C }, + { 0x0213F0FE990820C4, 0x0000328B, 0xFFFFEBA1, 0x000004B4, 0x00001DA3, 0xFFFFF683, 0x00000349, 0x00001DA3, 0xFFFFF683, 0x00000349 }, + { 0x0213F0FE991828C4, 0x000027DC, 0xFFFFF295, 0x000003BF, 0x000019C1, 0xFFFFF98E, 0x000002E8, 0x000019C1, 0xFFFFF98E, 0x000002E8 }, + { 0x0213F0FE99184084, 0x00002756, 0xFFFFF1D7, 0x000003DF, 0x000015D9, 0xFFFFFB51, 0x00000298, 0x000015D9, 0xFFFFFB51, 0x00000298 }, + { 0x0213F0FE99083884, 0x00003526, 0xFFFFE907, 0x00000526, 0x000017AB, 0xFFFFFA12, 0x000002AB, 0x000017AB, 0xFFFFFA12, 0x000002AB }, + { 0x0213F0FD42DA18E4, 0x0000351B, 0xFFFFE8B7, 0x00000540, 0x00001A86, 0xFFFFF821, 0x00000303, 0x00001A86, 0xFFFFF821, 0x00000303 }, + { 0x0213F0FE99164144, 0x000024B2, 0xFFFFF34E, 0x000003B1, 0x000018E2, 0xFFFFF926, 0x000002FC, 0x000018E2, 0xFFFFF926, 0x000002FC }, + { 0x0213F0FD42D828A4, 0x00002F36, 0xFFFFED5D, 0x00000486, 0x0000157A, 0xFFFFFB85, 0x00000293, 0x0000157A, 0xFFFFFB85, 0x00000293 }, + { 0x0213F0FD42DC50C4, 0x00003A6E, 0xFFFFE456, 0x000005FD, 0x00001F68, 0xFFFFF3D1, 0x000003C3, 0x00001F68, 0xFFFFF3D1, 0x000003C3 }, + { 0x0213F0FE990A31A4, 0x00002BC3, 0xFFFFED2D, 0x000004A7, 0x00001C3F, 0xFFFFF609, 0x00000364, 0x00001C3F, 0xFFFFF609, 0x00000364 }, + { 0x0213F0FE990E2084, 0x000032E1, 0xFFFFEA83, 0x000004F6, 0x00001B37, 0xFFFFF842, 0x000002F5, 0x00001B37, 0xFFFFF842, 0x000002F5 }, + { 0x0213F0FD42D83184, 0x000028E3, 0xFFFFF07F, 0x00000412, 0x00001676, 0xFFFFFA68, 0x000002BE, 0x00001676, 0xFFFFFA68, 0x000002BE }, + { 0x0213F0FD42D21104, 0x0000444C, 0xFFFFDDAD, 0x00000712, 0x00002634, 0xFFFFEF89, 0x0000046C, 0x00002634, 0xFFFFEF89, 0x0000046C }, + { 0x0213F0FE990418C4, 0x00003121, 0xFFFFEBBB, 0x000004C6, 0x00001C98, 0xFFFFF72B, 0x0000032D, 0x00001C98, 0xFFFFF72B, 0x0000032D }, + { 0x0213F0FD42D840A4, 0x00002C31, 0xFFFFEDC4, 0x00000490, 0x0000162D, 0xFFFFFA8E, 0x000002B4, 0x0000162D, 0xFFFFFA8E, 0x000002B4 }, + { 0x0213F0FD42DA18C4, 0x00002749, 0xFFFFF112, 0x000003FC, 0x00001C85, 0xFFFFF6B8, 0x00000342, 0x00001C85, 0xFFFFF6B8, 0x00000342 }, + { 0x0213F0FE99044104, 0x00003159, 0xFFFFEB99, 0x000004C2, 0x00001BD0, 0xFFFFF7CA, 0x00000307, 0x00001BD0, 0xFFFFF7CA, 0x00000307 }, + { 0x0213F0FE99164164, 0x00002610, 0xFFFFF1FD, 0x000003EC, 0x000016BE, 0xFFFFFA53, 0x000002CB, 0x000016BE, 0xFFFFFA53, 0x000002CB }, + { 0x0213F0FE99023184, 0x000037B5, 0xFFFFE63D, 0x000005B5, 0x00002285, 0xFFFFF25D, 0x000003F7, 0x00002285, 0xFFFFF25D, 0x000003F7 }, + { 0x0213F0FE990A28A4, 0x00002FEE, 0xFFFFEB47, 0x000004EF, 0x00001CBE, 0xFFFFF64E, 0x00000358, 0x00001CBE, 0xFFFFF64E, 0x00000358 }, + { 0x0213F0FE99105104, 0x00002E90, 0xFFFFEC48, 0x000004C0, 0x00001A47, 0xFFFFF7D1, 0x0000031A, 0x00001A47, 0xFFFFF7D1, 0x0000031A }, + { 0x0213F0FD42DA4084, 0x000034AB, 0xFFFFE84A, 0x00000559, 0x00001A72, 0xFFFFF79A, 0x0000031C, 0x00001A72, 0xFFFFF79A, 0x0000031C }, + { 0x0213F0FE99183884, 0x00002F7B, 0xFFFFECFC, 0x0000049C, 0x00001814, 0xFFFFFA22, 0x000002C2, 0x00001814, 0xFFFFFA22, 0x000002C2 }, + { 0x0213F0FE99021964, 0x00003618, 0xFFFFE709, 0x00000596, 0x00001EBF, 0xFFFFF482, 0x000003A5, 0x00001EBF, 0xFFFFF482, 0x000003A5 }, + { 0x0213EA94DE024904, 0x0000341B, 0xFFFFE8B2, 0x0000054F, 0x00001D26, 0xFFFFF578, 0x00000388, 0x00001D26, 0xFFFFF578, 0x00000388 }, + { 0x0213F0FE99102144, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x000019C0, 0xFFFFF8CC, 0x000002E6, 0x000019C0, 0xFFFFF8CC, 0x000002E6 }, + { 0x0213F0FE992841A4, 0x00002B76, 0xFFFFEF6C, 0x00000444, 0x00001563, 0xFFFFFBBE, 0x0000028D, 0x00001563, 0xFFFFFBBE, 0x0000028D }, + { 0x0213F0FD42D81864, 0x00002BA2, 0xFFFFEE31, 0x0000047F, 0x00001A3D, 0xFFFFF7F3, 0x00000320, 0x00001A3D, 0xFFFFF7F3, 0x00000320 }, + { 0x0213F0FE992C48E4, 0x00003545, 0xFFFFE87A, 0x0000054A, 0x00001B5A, 0xFFFFF7B0, 0x0000030C, 0x00001B5A, 0xFFFFF7B0, 0x0000030C }, + { 0x0213EA94DE042944, 0x00003879, 0xFFFFE73F, 0x00000578, 0x00001649, 0xFFFFFB57, 0x00000283, 0x00001649, 0xFFFFFB57, 0x00000283 }, + { 0x0213F0FD42D840C4, 0x00002772, 0xFFFFF0F1, 0x00000410, 0x0000142F, 0xFFFFFBCF, 0x00000287, 0x0000142F, 0xFFFFFBCF, 0x00000287 }, + { 0x0213F0FD42DA3184, 0x00003228, 0xFFFFE98E, 0x00000535, 0x00001F48, 0xFFFFF495, 0x00000399, 0x00001F48, 0xFFFFF495, 0x00000399 }, + { 0x0213F0FE990E40E4, 0x00002887, 0xFFFFF119, 0x000003E8, 0x000021AA, 0xFFFFF3F5, 0x000003A5, 0x000021AA, 0xFFFFF3F5, 0x000003A5 }, + { 0x0213F0FD42DA28A4, 0x0000301F, 0xFFFFEBB2, 0x000004D2, 0x00001C02, 0xFFFFF736, 0x0000032B, 0x00001C02, 0xFFFFF736, 0x0000032B }, + { 0x0213F0FE991820A4, 0x00002E13, 0xFFFFEE3F, 0x00000468, 0x000016AC, 0xFFFFFB32, 0x0000029E, 0x000016AC, 0xFFFFFB32, 0x0000029E }, + { 0x0213F0FE99044924, 0x00003478, 0xFFFFE8F9, 0x00000538, 0x00001DAB, 0xFFFFF645, 0x00000345, 0x00001DAB, 0xFFFFF645, 0x00000345 }, + { 0x0213F0FE990608C4, 0x000030C6, 0xFFFFEB6C, 0x000004D4, 0x0000184A, 0xFFFFF934, 0x000002E1, 0x0000184A, 0xFFFFF934, 0x000002E1 }, + { 0x0213F0FE990A2044, 0x00002F1B, 0xFFFFEBD3, 0x000004D3, 0x000019E7, 0xFFFFF813, 0x0000030D, 0x000019E7, 0xFFFFF813, 0x0000030D }, + { 0x0213F0FE99023904, 0x00003214, 0xFFFFEAE9, 0x000004E0, 0x0000178F, 0xFFFFFA1C, 0x000002B1, 0x0000178F, 0xFFFFFA1C, 0x000002B1 }, + { 0x0213F0FD42DC3144, 0x0000399C, 0xFFFFE738, 0x0000055E, 0x00001EA1, 0xFFFFF5E7, 0x0000035A, 0x00001EA1, 0xFFFFF5E7, 0x0000035A }, + { 0x0213F0FE990650C4, 0x00003A01, 0xFFFFE5B2, 0x000005B6, 0x00001D95, 0xFFFFF5D2, 0x0000036A, 0x00001D95, 0xFFFFF5D2, 0x0000036A }, + { 0x0213F0FE99043884, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001C06, 0xFFFFF76E, 0x0000031A, 0x00001C06, 0xFFFFF76E, 0x0000031A }, + { 0x0213F0FE99063864, 0x00003CD1, 0xFFFFE42F, 0x000005EB, 0x00001933, 0xFFFFF91F, 0x000002D4, 0x00001933, 0xFFFFF91F, 0x000002D4 }, + { 0x0213F0FD42DA3164, 0x00003119, 0xFFFFEB1B, 0x000004E1, 0x00001FC7, 0xFFFFF46A, 0x000003A2, 0x00001FC7, 0xFFFFF46A, 0x000003A2 }, + { 0x0213EA94DE0648A4, 0x0000390D, 0xFFFFE566, 0x000005D8, 0x00001EC6, 0xFFFFF4DC, 0x00000391, 0x00001EC6, 0xFFFFF4DC, 0x00000391 }, + { 0x0213F0FD42DA10C4, 0x00003446, 0xFFFFE858, 0x00000561, 0x00001FDB, 0xFFFFF3FF, 0x000003B9, 0x00001FDB, 0xFFFFF3FF, 0x000003B9 }, + { 0x0213F0FE99044904, 0x000032BA, 0xFFFFEA07, 0x00000511, 0x00001B25, 0xFFFFF7C9, 0x0000030D, 0x00001B25, 0xFFFFF7C9, 0x0000030D }, + { 0x0213F0FE990E1864, 0x00002CCF, 0xFFFFEDE5, 0x00000478, 0x00001BC8, 0xFFFFF761, 0x00000326, 0x00001BC8, 0xFFFFF761, 0x00000326 }, + { 0x0213F0FE99062984, 0x0000400E, 0xFFFFE1CB, 0x00000652, 0x00001AF8, 0xFFFFF7B9, 0x00000312, 0x00001AF8, 0xFFFFF7B9, 0x00000312 }, + { 0x0213F0FE990408E4, 0x00002F24, 0xFFFFEC2A, 0x000004C7, 0x00001B94, 0xFFFFF748, 0x00000333, 0x00001B94, 0xFFFFF748, 0x00000333 }, + { 0x0213F0FD42D21924, 0x00003FDA, 0xFFFFE1C1, 0x0000064B, 0x00002427, 0xFFFFF180, 0x0000040C, 0x00002427, 0xFFFFF180, 0x0000040C }, + { 0x0213F0FE990A18C4, 0x00002F6B, 0xFFFFEBA7, 0x000004DD, 0x00001C25, 0xFFFFF6C1, 0x00000344, 0x00001C25, 0xFFFFF6C1, 0x00000344 }, + { 0x0213F0FE99182104, 0x00002A53, 0xFFFFF0EE, 0x00000402, 0x000017C6, 0xFFFFFAA0, 0x000002BF, 0x000017C6, 0xFFFFFAA0, 0x000002BF }, + { 0x0213F0FE99105144, 0x000031F4, 0xFFFFEA34, 0x00000517, 0x000016FF, 0xFFFFFA4E, 0x000002AC, 0x000016FF, 0xFFFFFA4E, 0x000002AC }, + { 0x0213F0FE99322144, 0x00002E24, 0xFFFFED46, 0x00000489, 0x00001712, 0xFFFFFA5D, 0x000002AC, 0x00001712, 0xFFFFFA5D, 0x000002AC }, + { 0x0213F0FE99182824, 0x000028CD, 0xFFFFF0E3, 0x0000040E, 0x00001606, 0xFFFFFB37, 0x000002A4, 0x00001606, 0xFFFFFB37, 0x000002A4 }, + { 0x0213F0FE990220C4, 0x00003184, 0xFFFFEB88, 0x000004C3, 0x000018DA, 0xFFFFF939, 0x000002DB, 0x000018DA, 0xFFFFF939, 0x000002DB }, + { 0x0213F0FE99162124, 0x0000239B, 0xFFFFF470, 0x00000386, 0x00001714, 0xFFFFFA9F, 0x000002C8, 0x00001714, 0xFFFFFA9F, 0x000002C8 }, + { 0x0213F0FD42DC38E4, 0x00003641, 0xFFFFE92B, 0x00000515, 0x00001BE2, 0xFFFFF795, 0x0000031B, 0x00001BE2, 0xFFFFF795, 0x0000031B }, + { 0x0213F0FE992C1144, 0x00003278, 0xFFFFEA17, 0x00000510, 0x00001B71, 0xFFFFF778, 0x0000031D, 0x00001B71, 0xFFFFF778, 0x0000031D }, + { 0x0213F0FE99062844, 0x000035B9, 0xFFFFE8DA, 0x0000052D, 0x00001A6A, 0xFFFFF83B, 0x000002FF, 0x00001A6A, 0xFFFFF83B, 0x000002FF }, + { 0x0213F0FE990E18C4, 0x00002E5E, 0xFFFFED32, 0x0000048B, 0x00001E7D, 0xFFFFF60E, 0x0000034E, 0x00001E7D, 0xFFFFF60E, 0x0000034E }, + { 0x0213F0FE991019A4, 0x00003178, 0xFFFFEA52, 0x00000513, 0x00001AD0, 0xFFFFF793, 0x0000031F, 0x00001AD0, 0xFFFFF793, 0x0000031F }, + { 0x0213F0FD42D44104, 0x00003A2C, 0xFFFFE346, 0x00000641, 0x000023D0, 0xFFFFF0CE, 0x00000433, 0x000023D0, 0xFFFFF0CE, 0x00000433 }, + { 0x0213F0FD42D818C4, 0x000028FD, 0xFFFFF02A, 0x0000042B, 0x0000152B, 0xFFFFFB90, 0x00000289, 0x0000152B, 0xFFFFFB90, 0x00000289 }, + { 0x0213F0FE990E3084, 0x000030DE, 0xFFFFEBDF, 0x000004BE, 0x00001CDC, 0xFFFFF747, 0x0000031C, 0x00001CDC, 0xFFFFF747, 0x0000031C }, + { 0x0213F0FE99021944, 0x000036CB, 0xFFFFE6EE, 0x00000596, 0x00002096, 0xFFFFF3C2, 0x000003BB, 0x00002096, 0xFFFFF3C2, 0x000003BB }, + { 0x0213F0FE990C48C4, 0x00003172, 0xFFFFEAC1, 0x000004F4, 0x00001C87, 0xFFFFF6CD, 0x00000337, 0x00001C87, 0xFFFFF6CD, 0x00000337 }, + { 0x0213F0FD42D24864, 0x00004A18, 0xFFFFDB34, 0x00000758, 0x0000213C, 0xFFFFF3A2, 0x000003AC, 0x0000213C, 0xFFFFF3A2, 0x000003AC }, + { 0x0213F0FE99022104, 0x000031F3, 0xFFFFEB73, 0x000004C6, 0x00001B23, 0xFFFFF7CB, 0x0000031A, 0x00001B23, 0xFFFFF7CB, 0x0000031A }, + { 0x0213F0FE990A2924, 0x000031C0, 0xFFFFEABA, 0x000004F7, 0x00001A5A, 0xFFFFF845, 0x000002FF, 0x00001A5A, 0xFFFFF845, 0x000002FF }, + { 0x0213F0FE99104944, 0x00003B77, 0xFFFFE3B3, 0x00000623, 0x00001BCA, 0xFFFFF6F8, 0x00000333, 0x00001BCA, 0xFFFFF6F8, 0x00000333 }, + { 0x0213F0FE990A3944, 0x000035AF, 0xFFFFE76D, 0x00000588, 0x00001C16, 0xFFFFF6AB, 0x00000341, 0x00001C16, 0xFFFFF6AB, 0x00000341 }, + { 0x0213EA94DE0438C4, 0x000032AD, 0xFFFFEA8E, 0x000004F8, 0x00001A3A, 0xFFFFF832, 0x0000030E, 0x00001A3A, 0xFFFFF832, 0x0000030E }, + { 0x0213F0FE99104884, 0x00002E92, 0xFFFFEBD2, 0x000004DA, 0x00001E04, 0xFFFFF51E, 0x0000038A, 0x00001E04, 0xFFFFF51E, 0x0000038A }, + { 0x0213F0FD42D440A4, 0x00003E57, 0xFFFFE0F7, 0x0000068F, 0x000021F1, 0xFFFFF1C6, 0x00000411, 0x000021F1, 0xFFFFF1C6, 0x00000411 }, + { 0x0213F0FE990821A4, 0x00003598, 0xFFFFE8BB, 0x00000535, 0x00001B62, 0xFFFFF764, 0x00000326, 0x00001B62, 0xFFFFF764, 0x00000326 }, + { 0x0213F0FE990A3884, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x00001E8B, 0xFFFFF4AB, 0x0000039F, 0x00001E8B, 0xFFFFF4AB, 0x0000039F }, + { 0x0213EA94DE060904, 0x0000267E, 0xFFFFF1A7, 0x000003E1, 0x000021C1, 0xFFFFF2E9, 0x000003EA, 0x000021C1, 0xFFFFF2E9, 0x000003EA }, + { 0x0213EA94DE0239A4, 0x00002ED7, 0xFFFFEC88, 0x000004A6, 0x00001DEC, 0xFFFFF57C, 0x00000378, 0x00001DEC, 0xFFFFF57C, 0x00000378 }, + { 0x0213EA94DE0441A4, 0x00003365, 0xFFFFE946, 0x00000536, 0x000019E9, 0xFFFFF7E0, 0x0000031D, 0x000019E9, 0xFFFFF7E0, 0x0000031D }, + { 0x0213F0FE991818E4, 0x000029A4, 0xFFFFF0FD, 0x000003FE, 0x0000163F, 0xFFFFFB68, 0x00000299, 0x0000163F, 0xFFFFFB68, 0x00000299 }, + { 0x0213EA94DE021904, 0x0000348D, 0xFFFFE9F7, 0x00000509, 0x000017A0, 0xFFFFFA59, 0x000002B6, 0x000017A0, 0xFFFFFA59, 0x000002B6 }, + { 0x0213F0FE990610C4, 0x00003144, 0xFFFFEB23, 0x000004D9, 0x00001C9B, 0xFFFFF664, 0x00000351, 0x00001C9B, 0xFFFFF664, 0x00000351 }, + { 0x0213EA94DE0620E4, 0x00002E95, 0xFFFFEE1A, 0x00000463, 0x00001707, 0xFFFFFAB7, 0x000002B3, 0x00001707, 0xFFFFFAB7, 0x000002B3 }, + { 0x0213F0FD42D41864, 0x0000489C, 0xFFFFDA43, 0x000007AC, 0x00002866, 0xFFFFED6B, 0x000004D0, 0x00002866, 0xFFFFED6B, 0x000004D0 }, + { 0x0213F0FE99161844, 0x00002895, 0xFFFFF10A, 0x0000040A, 0x000013E9, 0xFFFFFC9F, 0x0000026E, 0x000013E9, 0xFFFFFC9F, 0x0000026E }, + { 0x0213F0FE99061964, 0x000033A0, 0xFFFFE9B1, 0x00000510, 0x00001D96, 0xFFFFF5AE, 0x0000036F, 0x00001D96, 0xFFFFF5AE, 0x0000036F }, + { 0x0213F0FE99083984, 0x0000327C, 0xFFFFEAEA, 0x000004DD, 0x00001D45, 0xFFFFF649, 0x00000356, 0x00001D45, 0xFFFFF649, 0x00000356 }, + { 0x0213EA94DE0248A4, 0x000031DF, 0xFFFFE9AB, 0x0000052F, 0x000019C8, 0xFFFFF7B7, 0x00000321, 0x000019C8, 0xFFFFF7B7, 0x00000321 }, + { 0x0213F0FE991640A4, 0x00002BCC, 0xFFFFEEF4, 0x0000045C, 0x000015CD, 0xFFFFFB58, 0x0000029E, 0x000015CD, 0xFFFFFB58, 0x0000029E }, + { 0x0213F0FE990638E4, 0x00003534, 0xFFFFEA10, 0x000004EB, 0x00001BB6, 0xFFFFF7B9, 0x00000314, 0x00001BB6, 0xFFFFF7B9, 0x00000314 }, + { 0x0213F0FE99041984, 0x00002F4F, 0xFFFFEC35, 0x000004B9, 0x0000205D, 0xFFFFF47F, 0x00000392, 0x0000205D, 0xFFFFF47F, 0x00000392 }, + { 0x0213F0FE990C20A4, 0x00003295, 0xFFFFEB1C, 0x000004D6, 0x000019C1, 0xFFFFF931, 0x000002D5, 0x000019C1, 0xFFFFF931, 0x000002D5 }, + { 0x0213F0FE99024144, 0x00003557, 0xFFFFE7F7, 0x00000568, 0x00002342, 0xFFFFF1F9, 0x00000405, 0x00002342, 0xFFFFF1F9, 0x00000405 }, + { 0x0213F0FE990450C4, 0x00003487, 0xFFFFE872, 0x0000055D, 0x000019D7, 0xFFFFF823, 0x0000030C, 0x000019D7, 0xFFFFF823, 0x0000030C }, + { 0x0213F0FE992C3944, 0x0000378F, 0xFFFFE7A6, 0x00000566, 0x00001875, 0xFFFFFA04, 0x000002AF, 0x00001875, 0xFFFFFA04, 0x000002AF }, + { 0x0213EA94DE0230E4, 0x00002A67, 0xFFFFF157, 0x000003DD, 0x000017BD, 0xFFFFFA53, 0x000002D1, 0x000017BD, 0xFFFFFA53, 0x000002D1 }, + { 0x0213F0FD42D220E4, 0x000030B5, 0xFFFFEB32, 0x000004D9, 0x00002129, 0xFFFFF38A, 0x000003BB, 0x00002129, 0xFFFFF38A, 0x000003BB }, + { 0x0213F0FE990610A4, 0x00003786, 0xFFFFE703, 0x00000584, 0x00001D63, 0xFFFFF5DC, 0x00000367, 0x00001D63, 0xFFFFF5DC, 0x00000367 }, + { 0x0213F0FD42DA20C4, 0x0000346A, 0xFFFFE93E, 0x0000052C, 0x00001B27, 0xFFFFF79D, 0x0000031F, 0x00001B27, 0xFFFFF79D, 0x0000031F }, + { 0x0213F0FE990E3024, 0x0000294E, 0xFFFFF0A5, 0x00000409, 0x00001928, 0xFFFFF93B, 0x000002E6, 0x00001928, 0xFFFFF93B, 0x000002E6 }, + { 0x0213F0FD42D410C4, 0x00003E09, 0xFFFFE0FF, 0x00000694, 0x000025A0, 0xFFFFEF0F, 0x0000048F, 0x000025A0, 0xFFFFEF0F, 0x0000048F }, + { 0x0213F0FE990A2964, 0x00003197, 0xFFFFEA06, 0x00000520, 0x00001B42, 0xFFFFF73B, 0x0000032A, 0x00001B42, 0xFFFFF73B, 0x0000032A }, + { 0x0213F0FE99161864, 0x000022CB, 0xFFFFF3FC, 0x000003A3, 0x00001449, 0xFFFFFBD0, 0x00000297, 0x00001449, 0xFFFFFBD0, 0x00000297 }, + { 0x0213F0FD42D82944, 0x00002A79, 0xFFFFEFD2, 0x00000433, 0x00001585, 0xFFFFFB92, 0x0000028E, 0x00001585, 0xFFFFFB92, 0x0000028E }, + { 0x0213F0FE990C4184, 0x00003249, 0xFFFFEA92, 0x000004F4, 0x000019CB, 0xFFFFF8CF, 0x000002E1, 0x000019CB, 0xFFFFF8CF, 0x000002E1 }, + { 0x0213EA94DE0218A4, 0x00002CEA, 0xFFFFEE46, 0x00000463, 0x00001A5E, 0xFFFFF83C, 0x0000030D, 0x00001A5E, 0xFFFFF83C, 0x0000030D }, + { 0x0213F0FD42DC5144, 0x00003AE2, 0xFFFFE422, 0x00000600, 0x00001C65, 0xFFFFF62F, 0x0000034B, 0x00001C65, 0xFFFFF62F, 0x0000034B }, + { 0x0213F0FE99181184, 0x000026A0, 0xFFFFF1C2, 0x000003F8, 0x000010E5, 0xFFFFFE56, 0x0000022A, 0x000010E5, 0xFFFFFE56, 0x0000022A }, + { 0x0213F0FE992829A4, 0x00002A7B, 0xFFFFF063, 0x00000417, 0x000016FC, 0xFFFFFAD7, 0x000002B1, 0x000016FC, 0xFFFFFAD7, 0x000002B1 }, + { 0x0213F0FE993210C4, 0x00003092, 0xFFFFEAB9, 0x00000507, 0x00001AE3, 0xFFFFF783, 0x00000323, 0x00001AE3, 0xFFFFF783, 0x00000323 }, + { 0x0213F0FE990438E4, 0x00003265, 0xFFFFEBE8, 0x000004AA, 0x00001D65, 0xFFFFF73F, 0x00000321, 0x00001D65, 0xFFFFF73F, 0x00000321 }, + { 0x0213EA94DE023084, 0x00002F14, 0xFFFFECC2, 0x000004A4, 0x00001A8D, 0xFFFFF7F3, 0x0000031D, 0x00001A8D, 0xFFFFF7F3, 0x0000031D }, + { 0x0213F0FD42DC10E4, 0x000035FB, 0xFFFFE6D3, 0x000005AC, 0x00001B19, 0xFFFFF712, 0x00000338, 0x00001B19, 0xFFFFF712, 0x00000338 }, + { 0x0213F0FD42DA2124, 0x00003519, 0xFFFFE8CC, 0x0000053A, 0x00001A0F, 0xFFFFF86E, 0x000002F5, 0x00001A0F, 0xFFFFF86E, 0x000002F5 }, + { 0x0213F0FE992C2144, 0x0000364C, 0xFFFFE879, 0x00000541, 0x00001A42, 0xFFFFF8BA, 0x000002E2, 0x00001A42, 0xFFFFF8BA, 0x000002E2 }, + { 0x0213EA94DE0218C4, 0x000029BA, 0xFFFFF09A, 0x00000408, 0x00001986, 0xFFFFF8D9, 0x000002FE, 0x00001986, 0xFFFFF8D9, 0x000002FE }, + { 0x0213F0FD42DA38E4, 0x00003507, 0xFFFFE961, 0x00000518, 0x00001B79, 0xFFFFF775, 0x00000325, 0x00001B79, 0xFFFFF775, 0x00000325 }, + { 0x0213F0FD42DC3184, 0x00003AD5, 0xFFFFE415, 0x00000613, 0x00001CB4, 0xFFFFF66D, 0x00000348, 0x00001CB4, 0xFFFFF66D, 0x00000348 }, + { 0x0213F0FE991640E4, 0x000023D1, 0xFFFFF42B, 0x0000038F, 0x00001546, 0xFFFFFBA0, 0x0000029F, 0x00001546, 0xFFFFFBA0, 0x0000029F }, + { 0x0213F0FE990A1924, 0x0000399E, 0xFFFFE518, 0x000005E7, 0x00001990, 0xFFFFF871, 0x000002FB, 0x00001990, 0xFFFFF871, 0x000002FB }, + { 0x0213F0FD42D82964, 0x00002EDE, 0xFFFFEC93, 0x000004B8, 0x0000152C, 0xFFFFFBB3, 0x0000027E, 0x0000152C, 0xFFFFFBB3, 0x0000027E }, + { 0x0213EA94DE042964, 0x00003140, 0xFFFFEBC9, 0x000004BB, 0x000016BE, 0xFFFFFB0A, 0x00000288, 0x000016BE, 0xFFFFFB0A, 0x00000288 }, + { 0x0213F0FE99064064, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x0000185D, 0xFFFFF95A, 0x000002D9, 0x0000185D, 0xFFFFF95A, 0x000002D9 }, + { 0x0213F0FE99023844, 0x0000389C, 0xFFFFE65A, 0x000005A2, 0x0000195D, 0xFFFFF8C8, 0x000002E8, 0x0000195D, 0xFFFFF8C8, 0x000002E8 }, + { 0x0213F0FE99042104, 0x0000362B, 0xFFFFE9EC, 0x000004F6, 0x00001605, 0xFFFFFC1C, 0x00000263, 0x00001605, 0xFFFFFC1C, 0x00000263 }, + { 0x0213F0FE992A1964, 0x00002946, 0xFFFFF04F, 0x00000426, 0x000015BA, 0xFFFFFB2F, 0x000002A3, 0x000015BA, 0xFFFFFB2F, 0x000002A3 }, + { 0x0213F0FE99082184, 0x0000368E, 0xFFFFE837, 0x0000054A, 0x000017D7, 0xFFFFF9EB, 0x000002BA, 0x000017D7, 0xFFFFF9EB, 0x000002BA }, + { 0x0213F0FD42DA2844, 0x00002E74, 0xFFFFEBE8, 0x000004DA, 0x00001DD6, 0xFFFFF57E, 0x00000379, 0x00001DD6, 0xFFFFF57E, 0x00000379 }, + { 0x0213F0FE99041944, 0x0000322D, 0xFFFFEAA8, 0x000004F5, 0x00001B55, 0xFFFFF7DD, 0x0000030B, 0x00001B55, 0xFFFFF7DD, 0x0000030B }, + { 0x0213F0FE99181904, 0x00002A29, 0xFFFFF07B, 0x00000416, 0x00001671, 0xFFFFFB3E, 0x0000029F, 0x00001671, 0xFFFFFB3E, 0x0000029F }, + { 0x0213F0FD42DA2104, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x00001815, 0xFFFFF9AE, 0x000002C9, 0x00001815, 0xFFFFF9AE, 0x000002C9 }, + { 0x0213F0FE990E10E4, 0x0000265F, 0xFFFFF1CB, 0x000003D5, 0x00001ED2, 0xFFFFF539, 0x0000037A, 0x00001ED2, 0xFFFFF539, 0x0000037A }, + { 0x0213F0FE99162184, 0x000027A8, 0xFFFFF10D, 0x00000413, 0x000014B5, 0xFFFFFBA1, 0x00000299, 0x000014B5, 0xFFFFFBA1, 0x00000299 }, + { 0x0213F0FE99043064, 0x00002CEE, 0xFFFFEDF6, 0x00000476, 0x00001A99, 0xFFFFF83E, 0x00000305, 0x00001A99, 0xFFFFF83E, 0x00000305 }, + { 0x0213F0FE990640C4, 0x0000346C, 0xFFFFEA17, 0x000004EF, 0x00001D38, 0xFFFFF69F, 0x0000033D, 0x00001D38, 0xFFFFF69F, 0x0000033D }, + { 0x0213F0FD42DA2944, 0x00002DBB, 0xFFFFED35, 0x00000490, 0x000018C1, 0xFFFFF930, 0x000002DA, 0x000018C1, 0xFFFFF930, 0x000002DA }, + { 0x0213F0FE99042924, 0x000038DF, 0xFFFFE8A7, 0x0000051E, 0x00001B59, 0xFFFFF915, 0x000002D3, 0x00001B59, 0xFFFFF915, 0x000002D3 }, + { 0x0213F0FE99080944, 0x00003384, 0xFFFFE979, 0x00000524, 0x00001AF3, 0xFFFFF74C, 0x0000032F, 0x00001AF3, 0xFFFFF74C, 0x0000032F }, + { 0x0213F0FE99181864, 0x0000258B, 0xFFFFF2AE, 0x000003CB, 0x0000190C, 0xFFFFF93E, 0x000002EF, 0x0000190C, 0xFFFFF93E, 0x000002EF }, + { 0x0213F0FE99103884, 0x000034F1, 0xFFFFE84B, 0x0000055E, 0x00001CB8, 0xFFFFF670, 0x0000034A, 0x00001CB8, 0xFFFFF670, 0x0000034A }, + { 0x0213F0FE990C2104, 0x000030FB, 0xFFFFECD2, 0x00000488, 0x00001BF4, 0xFFFFF821, 0x00000302, 0x00001BF4, 0xFFFFF821, 0x00000302 }, + { 0x0213F0FE99063044, 0x000036A6, 0xFFFFE815, 0x00000556, 0x000018FD, 0xFFFFF925, 0x000002DF, 0x000018FD, 0xFFFFF925, 0x000002DF }, + { 0x0213EA94DE023044, 0x0000302A, 0xFFFFEB79, 0x000004E0, 0x00001C11, 0xFFFFF694, 0x00000358, 0x00001C11, 0xFFFFF694, 0x00000358 }, + { 0x0213F0FE99181124, 0x00002555, 0xFFFFF2C4, 0x000003CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB }, + { 0x0213F0FE990A3164, 0x000032A3, 0xFFFFE933, 0x00000544, 0x000019D3, 0xFFFFF81A, 0x00000306, 0x000019D3, 0xFFFFF81A, 0x00000306 }, + { 0x0213F0FD42D85104, 0x00002B91, 0xFFFFED81, 0x000004A9, 0x0000158B, 0xFFFFFAB9, 0x000002AC, 0x0000158B, 0xFFFFFAB9, 0x000002AC }, + { 0x0213F0FE990E20C4, 0x00003537, 0xFFFFE912, 0x0000052C, 0x00001C8A, 0xFFFFF754, 0x0000031B, 0x00001C8A, 0xFFFFF754, 0x0000031B }, + { 0x0213EA94DE063184, 0x000032E1, 0xFFFFEA5A, 0x000004F9, 0x000017B4, 0xFFFFF9D9, 0x000002C2, 0x000017B4, 0xFFFFF9D9, 0x000002C2 }, + { 0x0213F0FD42D210C4, 0x00003B76, 0xFFFFE330, 0x00000636, 0x000026FB, 0xFFFFEF06, 0x00000481, 0x000026FB, 0xFFFFEF06, 0x00000481 }, + { 0x0213F0FE99042144, 0x0000320C, 0xFFFFEB84, 0x000004C3, 0x00001A3A, 0xFFFFF8E9, 0x000002DF, 0x00001A3A, 0xFFFFF8E9, 0x000002DF }, + { 0x0213F0FE99023984, 0x0000317D, 0xFFFFEA1F, 0x00000515, 0x00002100, 0xFFFFF31B, 0x000003DD, 0x00002100, 0xFFFFF31B, 0x000003DD }, + { 0x0213F0FD42D43164, 0x00003DCB, 0xFFFFE0B4, 0x000006B4, 0x00002160, 0xFFFFF269, 0x000003F0, 0x00002160, 0xFFFFF269, 0x000003F0 }, + { 0x0213F0FE991618C4, 0x00002737, 0xFFFFF218, 0x000003E1, 0x000015B5, 0xFFFFFB8F, 0x0000029C, 0x000015B5, 0xFFFFFB8F, 0x0000029C }, + { 0x0213EA94DE023184, 0x0000318F, 0xFFFFEB3F, 0x000004D8, 0x00001938, 0xFFFFF8E9, 0x000002EB, 0x00001938, 0xFFFFF8E9, 0x000002EB }, + { 0x0213F0FE991048C4, 0x000031BD, 0xFFFFE9DE, 0x00000527, 0x000018A7, 0xFFFFF8CA, 0x000002ED, 0x000018A7, 0xFFFFF8CA, 0x000002ED }, + { 0x0213F0FD42DA3884, 0x00002F77, 0xFFFFEC2F, 0x000004B4, 0x00001D25, 0xFFFFF61B, 0x0000035D, 0x00001D25, 0xFFFFF61B, 0x0000035D }, + { 0x0213F0FE990E4904, 0x00002CCA, 0xFFFFEDB3, 0x0000047C, 0x00001FBD, 0xFFFFF4A7, 0x00000391, 0x00001FBD, 0xFFFFF4A7, 0x00000391 }, + { 0x0213F0FD42D438A4, 0x00003FF6, 0xFFFFE058, 0x000006A2, 0x000024CD, 0xFFFFF026, 0x00000452, 0x000024CD, 0xFFFFF026, 0x00000452 }, + { 0x0213F0FE990A38E4, 0x00003161, 0xFFFFEAC8, 0x000004F3, 0x00001BB6, 0xFFFFF72A, 0x0000032B, 0x00001BB6, 0xFFFFF72A, 0x0000032B }, + { 0x0213F0FD42D838A4, 0x00002EA0, 0xFFFFECA6, 0x000004B7, 0x000018C2, 0xFFFFF94E, 0x000002E1, 0x000018C2, 0xFFFFF94E, 0x000002E1 }, + { 0x0213F0FE99182184, 0x00002F62, 0xFFFFEC9E, 0x000004B8, 0x00001531, 0xFFFFFBCD, 0x00000285, 0x00001531, 0xFFFFFBCD, 0x00000285 }, + { 0x0213F0FE990440A4, 0x00003013, 0xFFFFEBD6, 0x000004C2, 0x00001B01, 0xFFFFF802, 0x000002FF, 0x00001B01, 0xFFFFF802, 0x000002FF }, + { 0x0213F0FE99183064, 0x00002972, 0xFFFFF08D, 0x00000417, 0x00001A32, 0xFFFFF8A4, 0x00000305, 0x00001A32, 0xFFFFF8A4, 0x00000305 }, + { 0x0213F0FD42D820E4, 0x00002E95, 0xFFFFED94, 0x00000487, 0x00001529, 0xFFFFFC26, 0x00000271, 0x00001529, 0xFFFFFC26, 0x00000271 }, + { 0x0213F0FE990A1084, 0x00002D6A, 0xFFFFEC79, 0x000004C1, 0x00001AE2, 0xFFFFF725, 0x00000337, 0x00001AE2, 0xFFFFF725, 0x00000337 }, + { 0x0213F0FE99021884, 0x000036B4, 0xFFFFE704, 0x00000591, 0x00001E7E, 0xFFFFF51C, 0x00000383, 0x00001E7E, 0xFFFFF51C, 0x00000383 }, + { 0x0213F0FE99041844, 0x00002A6F, 0xFFFFEF70, 0x00000443, 0x00001BAA, 0xFFFFF752, 0x00000336, 0x00001BAA, 0xFFFFF752, 0x00000336 }, + { 0x0213F0FE99183944, 0x00002C66, 0xFFFFEF5F, 0x0000043A, 0x000019F7, 0xFFFFF931, 0x000002EC, 0x000019F7, 0xFFFFF931, 0x000002EC }, + { 0x0213EA94DE0631C4, 0x00003852, 0xFFFFE6AB, 0x00000590, 0x000019C1, 0xFFFFF8B1, 0x000002E5, 0x000019C1, 0xFFFFF8B1, 0x000002E5 }, + { 0x0213F0FD42DA3124, 0x00003521, 0xFFFFE932, 0x00000523, 0x000018A9, 0xFFFFF96B, 0x000002D0, 0x000018A9, 0xFFFFF96B, 0x000002D0 }, + { 0x0213F0FE99062164, 0x000031B9, 0xFFFFEB36, 0x000004D0, 0x00001D65, 0xFFFFF612, 0x0000035D, 0x00001D65, 0xFFFFF612, 0x0000035D }, + { 0x0213F0FD42D41064, 0x00003ED0, 0xFFFFE135, 0x00000679, 0x00002351, 0xFFFFF0FE, 0x00000433, 0x00002351, 0xFFFFF0FE, 0x00000433 }, + { 0x0213F0FE990A20E4, 0x000033ED, 0xFFFFE91A, 0x00000541, 0x00001C93, 0xFFFFF6A0, 0x0000034A, 0x00001C93, 0xFFFFF6A0, 0x0000034A }, + { 0x0213EA94DE021844, 0x0000356F, 0xFFFFE8F7, 0x00000530, 0x000016BF, 0xFFFFFA85, 0x000002AB, 0x000016BF, 0xFFFFFA85, 0x000002AB }, + { 0x0213F0FE991840E4, 0x00002304, 0xFFFFF4F3, 0x00000364, 0x000017CC, 0xFFFFFA41, 0x000002CA, 0x000017CC, 0xFFFFFA41, 0x000002CA }, + { 0x0213F0FE99161164, 0x00002887, 0xFFFFEFD7, 0x00000450, 0x00001474, 0xFFFFFB94, 0x00000299, 0x00001474, 0xFFFFFB94, 0x00000299 }, + { 0x0213F0FE99063064, 0x00003D0B, 0xFFFFE416, 0x000005EF, 0x00001C7E, 0xFFFFF71D, 0x00000325, 0x00001C7E, 0xFFFFF71D, 0x00000325 }, + { 0x0213F0FE990810E4, 0x00003185, 0xFFFFEAFA, 0x000004E4, 0x00001A12, 0xFFFFF83C, 0x00000303, 0x00001A12, 0xFFFFF83C, 0x00000303 }, + { 0x0213F0FE990A1944, 0x00003032, 0xFFFFEAE6, 0x000004FC, 0x00001B2A, 0xFFFFF73F, 0x0000032B, 0x00001B2A, 0xFFFFF73F, 0x0000032B }, + { 0x0213F0FD42D838C4, 0x00002691, 0xFFFFF22D, 0x000003D6, 0x00001700, 0xFFFFFA6E, 0x000002C0, 0x00001700, 0xFFFFFA6E, 0x000002C0 }, + { 0x0213F0FE990218A4, 0x00002B2F, 0xFFFFEEC4, 0x0000044B, 0x0000215F, 0xFFFFF33F, 0x000003D2, 0x0000215F, 0xFFFFF33F, 0x000003D2 }, + { 0x0213F0FE990A4184, 0x000034AA, 0xFFFFE706, 0x000005B1, 0x00001B28, 0xFFFFF6B5, 0x00000349, 0x00001B28, 0xFFFFF6B5, 0x00000349 }, + { 0x0213F0FD42DA2964, 0x0000307E, 0xFFFFEB38, 0x000004E6, 0x00001A22, 0xFFFFF83F, 0x00000300, 0x00001A22, 0xFFFFF83F, 0x00000300 }, + { 0x0213F0FE990618A4, 0x000038D6, 0xFFFFE6D8, 0x0000057C, 0x00001B24, 0xFFFFF7E4, 0x00000307, 0x00001B24, 0xFFFFF7E4, 0x00000307 }, + { 0x0213F0FE99183044, 0x00002757, 0xFFFFF1E8, 0x000003DD, 0x000017F5, 0xFFFFFA15, 0x000002C8, 0x000017F5, 0xFFFFFA15, 0x000002C8 }, + { 0x0213F0FE99083184, 0x000031FC, 0xFFFFEB3E, 0x000004CE, 0x00001B4C, 0xFFFFF7AD, 0x00000319, 0x00001B4C, 0xFFFFF7AD, 0x00000319 }, + { 0x0213F0FE99301864, 0x00002933, 0xFFFFF073, 0x0000040E, 0x00001C3C, 0xFFFFF701, 0x0000033C, 0x00001C3C, 0xFFFFF701, 0x0000033C }, + { 0x0213F0FD42D218A4, 0x000040BB, 0xFFFFE066, 0x0000069A, 0x0000257F, 0xFFFFF08A, 0x00000435, 0x0000257F, 0xFFFFF08A, 0x00000435 }, + { 0x0213F0FE991010A4, 0x0000305B, 0xFFFFEB9B, 0x000004CB, 0x00001996, 0xFFFFF846, 0x00000308, 0x00001996, 0xFFFFF846, 0x00000308 }, + { 0x0213F0FE99064884, 0x000039C0, 0xFFFFE5D3, 0x000005B0, 0x00001A8D, 0xFFFFF7DA, 0x00000313, 0x00001A8D, 0xFFFFF7DA, 0x00000313 }, + { 0x0213EA94DE0210A4, 0x00002E23, 0xFFFFED3F, 0x0000048F, 0x0000189D, 0xFFFFF94C, 0x000002DE, 0x0000189D, 0xFFFFF94C, 0x000002DE }, + { 0x0213EA94DE021984, 0x0000332B, 0xFFFFE9F1, 0x00000516, 0x000018E6, 0xFFFFF8FE, 0x000002EC, 0x000018E6, 0xFFFFF8FE, 0x000002EC }, + { 0x0213F0FE990838C4, 0x000034A0, 0xFFFFEA44, 0x000004E4, 0x00001ECD, 0xFFFFF5B4, 0x00000364, 0x00001ECD, 0xFFFFF5B4, 0x00000364 }, + { 0x0213F0FD42D24104, 0x0000448C, 0xFFFFDF34, 0x000006A8, 0x0000231C, 0xFFFFF286, 0x000003D9, 0x0000231C, 0xFFFFF286, 0x000003D9 }, + { 0x0213EA94DE062144, 0x00002D8C, 0xFFFFEE65, 0x00000456, 0x000018B1, 0xFFFFF9C8, 0x000002C8, 0x000018B1, 0xFFFFF9C8, 0x000002C8 }, + { 0x0213F0FE99061904, 0x00003527, 0xFFFFE9BF, 0x000004FD, 0x00001D23, 0xFFFFF69F, 0x00000342, 0x00001D23, 0xFFFFF69F, 0x00000342 }, + { 0x0213F0FD42DC38A4, 0x00002C51, 0xFFFFEDC3, 0x00000483, 0x00001BE0, 0xFFFFF720, 0x0000032D, 0x00001BE0, 0xFFFFF720, 0x0000032D }, + { 0x0213F0FE990A3044, 0x00002C6C, 0xFFFFECEB, 0x000004B7, 0x00001C86, 0xFFFFF5E7, 0x00000371, 0x00001C86, 0xFFFFF5E7, 0x00000371 }, + { 0x0213F0FE99045144, 0x000037CF, 0xFFFFE6BE, 0x00000599, 0x000018CD, 0xFFFFF967, 0x000002C7, 0x000018CD, 0xFFFFF967, 0x000002C7 }, + { 0x0213F0FE99103164, 0x00002E6F, 0xFFFFED1D, 0x0000048E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E }, + { 0x0213F0FD42D42984, 0x00003FF3, 0xFFFFDF13, 0x000006F9, 0x000025BF, 0xFFFFEEEE, 0x00000497, 0x000025BF, 0xFFFFEEEE, 0x00000497 }, + { 0x0213F0FD42DC5104, 0x00004135, 0xFFFFDF97, 0x000006CC, 0x00001D52, 0xFFFFF541, 0x00000383, 0x00001D52, 0xFFFFF541, 0x00000383 }, + { 0x0213F0FD42DC20E4, 0x00002EA9, 0xFFFFEDDB, 0x0000045F, 0x0000197C, 0xFFFFF8E1, 0x000002F0, 0x0000197C, 0xFFFFF8E1, 0x000002F0 }, + { 0x0213EA94DE043084, 0x0000345C, 0xFFFFE922, 0x00000532, 0x00001922, 0xFFFFF8C7, 0x000002F1, 0x00001922, 0xFFFFF8C7, 0x000002F1 }, + { 0x0213F0FE99064124, 0x000035C4, 0xFFFFE8FE, 0x00000521, 0x00001C87, 0xFFFFF6F3, 0x00000330, 0x00001C87, 0xFFFFF6F3, 0x00000330 }, + { 0x0213F0FD42D83164, 0x00002888, 0xFFFFF08A, 0x0000041E, 0x0000150F, 0xFFFFFB87, 0x00000291, 0x0000150F, 0xFFFFFB87, 0x00000291 }, + { 0x0213F0FE990A1124, 0x000035E9, 0xFFFFE657, 0x000005CC, 0x00001BD6, 0xFFFFF664, 0x00000355, 0x00001BD6, 0xFFFFF664, 0x00000355 }, + { 0x0213F0FE991648E4, 0x00002F94, 0xFFFFEBD0, 0x000004E5, 0x00001333, 0xFFFFFCA7, 0x00000266, 0x00001333, 0xFFFFFCA7, 0x00000266 }, + { 0x0213F0FE99181964, 0x000029E7, 0xFFFFF009, 0x00000433, 0x0000144A, 0xFFFFFC37, 0x0000027D, 0x0000144A, 0xFFFFFC37, 0x0000027D }, + { 0x0213F0FE992C1944, 0x00003418, 0xFFFFE979, 0x00000521, 0x00001D33, 0xFFFFF66B, 0x0000034A, 0x00001D33, 0xFFFFF66B, 0x0000034A }, + { 0x0213EA94DE0440E4, 0x00003656, 0xFFFFE79D, 0x0000057A, 0x000017C2, 0xFFFFF992, 0x000002D4, 0x000017C2, 0xFFFFF992, 0x000002D4 }, + { 0x0213F0FE990C40C4, 0x00002EB2, 0xFFFFECFE, 0x00000493, 0x00001F2A, 0xFFFFF543, 0x0000037B, 0x00001F2A, 0xFFFFF543, 0x0000037B }, + { 0x0213F0FE99021124, 0x00002FC1, 0xFFFFEB3F, 0x000004E8, 0x00001CD0, 0xFFFFF5F7, 0x00000364, 0x00001CD0, 0xFFFFF5F7, 0x00000364 }, + { 0x0213F0FE990C1124, 0x0000307B, 0xFFFFEB66, 0x000004DE, 0x00001953, 0xFFFFF8ED, 0x000002E4, 0x00001953, 0xFFFFF8ED, 0x000002E4 }, + { 0x0213F0FD42DA1884, 0x00002CAA, 0xFFFFED07, 0x000004AC, 0x0000251C, 0xFFFFF086, 0x0000044D, 0x0000251C, 0xFFFFF086, 0x0000044D }, + { 0x0213EA94DE043944, 0x00002C94, 0xFFFFEE5F, 0x0000045B, 0x000018D7, 0xFFFFF900, 0x000002EB, 0x000018D7, 0xFFFFF900, 0x000002EB }, + { 0x0213F0FE99021864, 0x000031F1, 0xFFFFE9BE, 0x0000052E, 0x00001DDF, 0xFFFFF558, 0x00000380, 0x00001DDF, 0xFFFFF558, 0x00000380 }, + { 0x0213F0FE990E50C4, 0x00002603, 0xFFFFF1E9, 0x000003DA, 0x00001B37, 0xFFFFF75A, 0x0000032F, 0x00001B37, 0xFFFFF75A, 0x0000032F }, + { 0x0213F0FD42DA3044, 0x00003992, 0xFFFFE4F9, 0x000005EB, 0x00001775, 0xFFFFF9B8, 0x000002C2, 0x00001775, 0xFFFFF9B8, 0x000002C2 }, + { 0x0213F0FE99184964, 0x000029DA, 0xFFFFF052, 0x0000041F, 0x000016E2, 0xFFFFFA99, 0x000002BB, 0x000016E2, 0xFFFFFA99, 0x000002BB }, + { 0x0213F0FE99101064, 0x00002FF2, 0xFFFFEB8F, 0x000004DF, 0x00001AF6, 0xFFFFF7A1, 0x00000321, 0x00001AF6, 0xFFFFF7A1, 0x00000321 }, + { 0x0213F0FE991608E4, 0x00002590, 0xFFFFF222, 0x000003EE, 0x0000130B, 0xFFFFFCC9, 0x00000268, 0x0000130B, 0xFFFFFCC9, 0x00000268 }, + { 0x0213F0FE99024064, 0x000038A2, 0xFFFFE65F, 0x000005A2, 0x000018B1, 0xFFFFF917, 0x000002E1, 0x000018B1, 0xFFFFF917, 0x000002E1 }, + { 0x0213F0FD42DC48E4, 0x000035FD, 0xFFFFE73C, 0x0000058D, 0x00001BB3, 0xFFFFF6E1, 0x00000337, 0x00001BB3, 0xFFFFF6E1, 0x00000337 }, + { 0x0213F0FE991038C4, 0x00002AB7, 0xFFFFEF98, 0x00000429, 0x00001F35, 0xFFFFF539, 0x0000037C, 0x00001F35, 0xFFFFF539, 0x0000037C }, + { 0x0213F0FE990A0944, 0x000034BA, 0xFFFFE73D, 0x000005A6, 0x000018A6, 0xFFFFF888, 0x000002FB, 0x000018A6, 0xFFFFF888, 0x000002FB }, + { 0x0213F0FE99063844, 0x000032EA, 0xFFFFEA78, 0x000004F4, 0x00001AB6, 0xFFFFF812, 0x00000308, 0x00001AB6, 0xFFFFF812, 0x00000308 }, + { 0x0213F0FE990C3044, 0x00002BE9, 0xFFFFEE9A, 0x00000457, 0x00001942, 0xFFFFF8D2, 0x000002F2, 0x00001942, 0xFFFFF8D2, 0x000002F2 }, + { 0x0213F0FE99105124, 0x00002FAB, 0xFFFFEB76, 0x000004E1, 0x00001DCA, 0xFFFFF57D, 0x00000378, 0x00001DCA, 0xFFFFF57D, 0x00000378 }, + { 0x0213F0FE992E2844, 0x0000330A, 0xFFFFE9E1, 0x0000051B, 0x00001CC4, 0xFFFFF6DF, 0x00000335, 0x00001CC4, 0xFFFFF6DF, 0x00000335 }, + { 0x0213F0FE991828A4, 0x000027D8, 0xFFFFF276, 0x000003BF, 0x0000178A, 0xFFFFFABF, 0x000002B5, 0x0000178A, 0xFFFFFABF, 0x000002B5 }, + { 0x0213F0FD42DC3864, 0x0000340A, 0xFFFFE86D, 0x00000562, 0x00001B85, 0xFFFFF719, 0x0000032F, 0x00001B85, 0xFFFFF719, 0x0000032F }, + { 0x0213EA94DE063084, 0x00003879, 0xFFFFE73F, 0x00000578, 0x0000161C, 0xFFFFFB6B, 0x00000281, 0x0000161C, 0xFFFFFB6B, 0x00000281 }, + { 0x0213F0FE99184064, 0x00002879, 0xFFFFF0F8, 0x0000040A, 0x00001749, 0xFFFFFA37, 0x000002CC, 0x00001749, 0xFFFFFA37, 0x000002CC }, + { 0x0213F0FE99043964, 0x00002C3A, 0xFFFFEEA0, 0x0000044F, 0x00001D57, 0xFFFFF6C2, 0x00000332, 0x00001D57, 0xFFFFF6C2, 0x00000332 }, + { 0x0213EA94DE021964, 0x000035BB, 0xFFFFE90D, 0x0000052A, 0x000017D9, 0xFFFFF9F5, 0x000002C3, 0x000017D9, 0xFFFFF9F5, 0x000002C3 }, + { 0x0213EA94DE041124, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x00001F10, 0xFFFFF539, 0x0000037D, 0x00001F10, 0xFFFFF539, 0x0000037D }, + { 0x0213F0FE99102824, 0x00002A1A, 0xFFFFEFAD, 0x00000430, 0x00001D47, 0xFFFFF62F, 0x0000035E, 0x00001D47, 0xFFFFF62F, 0x0000035E }, + { 0x0213F0FE99164924, 0x00002AF0, 0xFFFFEEDC, 0x00000465, 0x0000145F, 0xFFFFFBEB, 0x00000281, 0x0000145F, 0xFFFFFBEB, 0x00000281 }, + { 0x0213F0FE99183164, 0x00002657, 0xFFFFF2E0, 0x000003B6, 0x00001664, 0xFFFFFB37, 0x000002A2, 0x00001664, 0xFFFFFB37, 0x000002A2 }, + { 0x0213F0FD42D03864, 0x00003183, 0xFFFFE9F1, 0x0000052B, 0x00002020, 0xFFFFF3CE, 0x000003C1, 0x00002020, 0xFFFFF3CE, 0x000003C1 }, + { 0x0213F0FD42C628E4, 0x00003240, 0xFFFFEB65, 0x000004C7, 0x00002425, 0xFFFFF245, 0x000003F3, 0x00002425, 0xFFFFF245, 0x000003F3 }, + { 0x0213EA94DE321104, 0x000023D0, 0xFFFFF400, 0x00000397, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, + { 0x0213F0FD42CE38A4, 0x00003440, 0xFFFFE872, 0x0000055B, 0x00002247, 0xFFFFF296, 0x000003E8, 0x00002247, 0xFFFFF296, 0x000003E8 }, + { 0x0213F0FD42D04904, 0x00003275, 0xFFFFE970, 0x00000538, 0x00001F94, 0xFFFFF429, 0x000003AD, 0x00001F94, 0xFFFFF429, 0x000003AD }, + { 0x0213F0FD42C640A4, 0x00003918, 0xFFFFE5DA, 0x000005B6, 0x000024FC, 0xFFFFF106, 0x00000426, 0x000024FC, 0xFFFFF106, 0x00000426 }, + { 0x0213EA94DE062044, 0x0000334B, 0xFFFFEA39, 0x000004FD, 0x00001983, 0xFFFFF8F6, 0x000002E2, 0x00001983, 0xFFFFF8F6, 0x000002E2 }, + { 0x0213F0FD42C64984, 0x00003B59, 0xFFFFE4D0, 0x000005DA, 0x00002605, 0xFFFFF090, 0x00000439, 0x00002605, 0xFFFFF090, 0x00000439 }, + { 0x0213F0FD42D03124, 0x00003251, 0xFFFFEA46, 0x00000511, 0x00002781, 0xFFFFEF84, 0x00000470, 0x00002781, 0xFFFFEF84, 0x00000470 }, + { 0x0213F0FD42CA3164, 0x00003304, 0xFFFFE926, 0x00000542, 0x00001EE9, 0xFFFFF4E4, 0x0000038B, 0x00001EE9, 0xFFFFF4E4, 0x0000038B }, + { 0x0213F0FD42CC38C4, 0x00002F4C, 0xFFFFEC0C, 0x000004C4, 0x00001E49, 0xFFFFF578, 0x00000374, 0x00001E49, 0xFFFFF578, 0x00000374 }, + { 0x0213EA94DE1C2164, 0x00002034, 0xFFFFF692, 0x0000034C, 0x000014B8, 0xFFFFFC5B, 0x00000294, 0x000014B8, 0xFFFFFC5B, 0x00000294 }, + { 0x0213F0FD42CE4924, 0x0000385F, 0xFFFFE513, 0x000005F3, 0x000024E7, 0xFFFFF053, 0x00000450, 0x000024E7, 0xFFFFF053, 0x00000450 }, + { 0x0213EA94DE1C40E4, 0x00001D70, 0xFFFFF821, 0x0000030F, 0x00001541, 0xFFFFFBB4, 0x000002B0, 0x00001541, 0xFFFFFBB4, 0x000002B0 }, + { 0x0213F0FD42D02084, 0x000034EB, 0xFFFFE7FF, 0x00000575, 0x000019B4, 0xFFFFF836, 0x00000308, 0x000019B4, 0xFFFFF836, 0x00000308 }, + { 0x0213F0FD42D050E4, 0x000037C9, 0xFFFFE5D4, 0x000005CD, 0x000026A1, 0xFFFFEF0C, 0x00000491, 0x000026A1, 0xFFFFEF0C, 0x00000491 }, + { 0x0213EA94DE121944, 0x00002918, 0xFFFFF148, 0x000003E9, 0x00001A49, 0xFFFFF94C, 0x000002CF, 0x00001A49, 0xFFFFF94C, 0x000002CF }, + { 0x0213F0FD42CA4064, 0x00002F90, 0xFFFFEAB5, 0x00000514, 0x00001707, 0xFFFFF9C7, 0x000002C4, 0x00001707, 0xFFFFF9C7, 0x000002C4 }, + { 0x0213EA94DE062064, 0x0000327E, 0xFFFFEA99, 0x000004F4, 0x0000194F, 0xFFFFF929, 0x000002DC, 0x0000194F, 0xFFFFF929, 0x000002DC }, + { 0x0213F0FD42C64084, 0x0000326F, 0xFFFFE9CF, 0x00000519, 0x00002240, 0xFFFFF299, 0x000003E7, 0x00002240, 0xFFFFF299, 0x000003E7 }, + { 0x0213EA94DE321124, 0x000022FB, 0xFFFFF4C6, 0x00000371, 0x00001506, 0xFFFFFC73, 0x00000265, 0x00001506, 0xFFFFFC73, 0x00000265 }, + { 0x0213F0FD42CA3924, 0x00003AD6, 0xFFFFE470, 0x000005FE, 0x00001F03, 0xFFFFF4F3, 0x00000387, 0x00001F03, 0xFFFFF4F3, 0x00000387 }, + { 0x0213EA94DE201124, 0x00001F11, 0xFFFFF756, 0x00000332, 0x00001666, 0xFFFFFB8A, 0x000002B2, 0x00001666, 0xFFFFFB8A, 0x000002B2 }, + { 0x0213EA94DE0238A4, 0x00002A5F, 0xFFFFEFA7, 0x00000430, 0x00001943, 0xFFFFF8C6, 0x000002F7, 0x00001943, 0xFFFFF8C6, 0x000002F7 }, + { 0x0213EA94DE1650E4, 0x0000235E, 0xFFFFF3B4, 0x000003B3, 0x00001489, 0xFFFFFBCF, 0x0000029B, 0x00001489, 0xFFFFFBCF, 0x0000029B }, + { 0x0213F0FD42CC38A4, 0x00003570, 0xFFFFE780, 0x0000058D, 0x00001B1D, 0xFFFFF767, 0x00000325, 0x00001B1D, 0xFFFFF767, 0x00000325 }, + { 0x0213EA94DE042064, 0x00003678, 0xFFFFE7C3, 0x00000569, 0x00001831, 0xFFFFF98E, 0x000002C8, 0x00001831, 0xFFFFF98E, 0x000002C8 }, + { 0x0213EA94DE201864, 0x000020B9, 0xFFFFF625, 0x0000035A, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, + { 0x0213F0FD42C63184, 0x00003985, 0xFFFFE529, 0x000005DD, 0x00002165, 0xFFFFF351, 0x000003C5, 0x00002165, 0xFFFFF351, 0x000003C5 }, + { 0x0213F0FD42D02064, 0x0000322A, 0xFFFFE99D, 0x00000535, 0x000019A1, 0xFFFFF844, 0x00000305, 0x000019A1, 0xFFFFF844, 0x00000305 }, + { 0x0213F0FD42D05104, 0x000033ED, 0xFFFFE834, 0x00000571, 0x00002094, 0xFFFFF33A, 0x000003DB, 0x00002094, 0xFFFFF33A, 0x000003DB }, + { 0x0213EA94DE2040C4, 0x00001D10, 0xFFFFF84D, 0x0000030B, 0x00001659, 0xFFFFFB0A, 0x000002CB, 0x00001659, 0xFFFFFB0A, 0x000002CB }, + { 0x0213EA94DE1C1124, 0x0000210F, 0xFFFFF644, 0x00000355, 0x00001A4A, 0xFFFFF90F, 0x00000310, 0x00001A4A, 0xFFFFF90F, 0x00000310 }, + { 0x0213EA94DE164164, 0x00001CA8, 0xFFFFF813, 0x00000316, 0x00001440, 0xFFFFFC1C, 0x0000029D, 0x00001440, 0xFFFFFC1C, 0x0000029D }, + { 0x0213EA94DE3210C4, 0x00002864, 0xFFFFF15A, 0x000003FA, 0x0000137F, 0xFFFFFD43, 0x00000248, 0x0000137F, 0xFFFFFD43, 0x00000248 }, + { 0x0213F0FD42D04184, 0x00002CDB, 0xFFFFECFD, 0x000004A7, 0x00002472, 0xFFFFF0E1, 0x00000437, 0x00002472, 0xFFFFF0E1, 0x00000437 }, + { 0x0213F0FD42CC5104, 0x00003348, 0xFFFFE8CA, 0x00000554, 0x00001E91, 0xFFFFF4D4, 0x00000392, 0x00001E91, 0xFFFFF4D4, 0x00000392 }, + { 0x0213F0FD42C64944, 0x00003989, 0xFFFFE4BB, 0x000005F8, 0x00001ACB, 0xFFFFF780, 0x00000319, 0x00001ACB, 0xFFFFF780, 0x00000319 }, + { 0x0213F0FD42CA2104, 0x00003238, 0xFFFFEA09, 0x0000051E, 0x00001F08, 0xFFFFF4F4, 0x0000038C, 0x00001F08, 0xFFFFF4F4, 0x0000038C }, + { 0x0213EA94DE120904, 0x00002453, 0xFFFFF3B0, 0x0000038D, 0x00001AED, 0xFFFFF8A2, 0x000002EA, 0x00001AED, 0xFFFFF8A2, 0x000002EA }, + { 0x0213EA94DE1C3024, 0x00002459, 0xFFFFF409, 0x000003A8, 0x000017B5, 0xFFFFFA53, 0x000002E1, 0x000017B5, 0xFFFFFA53, 0x000002E1 }, + { 0x0213EA94DE021184, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001DC9, 0xFFFFF5D5, 0x00000368, 0x00001DC9, 0xFFFFF5D5, 0x00000368 }, + { 0x0213EA94DE023104, 0x000031BF, 0xFFFFECA3, 0x00000498, 0x00001DC9, 0xFFFFF717, 0x00000336, 0x00001DC9, 0xFFFFF717, 0x00000336 }, + { 0x0213F0FD42CE2104, 0x00003896, 0xFFFFE5DD, 0x000005C5, 0x000023E2, 0xFFFFF1A1, 0x00000416, 0x000023E2, 0xFFFFF1A1, 0x00000416 }, + { 0x0213EA94DE323904, 0x000023CB, 0xFFFFF4C8, 0x00000372, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, + { 0x0213F0FD42D020C4, 0x00002F6B, 0xFFFFEBF0, 0x000004CE, 0x00001C89, 0xFFFFF689, 0x0000034D, 0x00001C89, 0xFFFFF689, 0x0000034D }, + { 0x0213F0FD42CE3904, 0x00003E72, 0xFFFFE211, 0x0000065D, 0x0000218D, 0xFFFFF309, 0x000003DC, 0x0000218D, 0xFFFFF309, 0x000003DC }, + { 0x0213EA94DE022084, 0x00002612, 0xFFFFF2C3, 0x000003AD, 0x000019F7, 0xFFFFF891, 0x000002FE, 0x000019F7, 0xFFFFF891, 0x000002FE }, + { 0x0213EA94DE164184, 0x0000205D, 0xFFFFF59F, 0x00000372, 0x000012E6, 0xFFFFFD0A, 0x00000270, 0x000012E6, 0xFFFFFD0A, 0x00000270 }, + { 0x0213F0FD42CA2124, 0x00002ECB, 0xFFFFEC47, 0x000004BD, 0x00001936, 0xFFFFF8D9, 0x000002E4, 0x00001936, 0xFFFFF8D9, 0x000002E4 }, + { 0x0213EA94DE064904, 0x00002BDB, 0xFFFFEE6D, 0x00000458, 0x00001852, 0xFFFFF943, 0x000002D9, 0x00001852, 0xFFFFF943, 0x000002D9 }, + { 0x0213EA94DE124904, 0x00003387, 0xFFFFE958, 0x00000534, 0x00001932, 0xFFFFF8FA, 0x000002E4, 0x00001932, 0xFFFFF8FA, 0x000002E4 }, + { 0x0213EA94DE0208C4, 0x00002E3C, 0xFFFFED26, 0x00000495, 0x00001858, 0xFFFFF990, 0x000002D1, 0x00001858, 0xFFFFF990, 0x000002D1 }, + { 0x0213EA94DE022964, 0x000033B8, 0xFFFFEA5C, 0x000004F9, 0x00001BD1, 0xFFFFF76A, 0x0000032E, 0x00001BD1, 0xFFFFF76A, 0x0000032E }, + { 0x0213EA94DE062984, 0x00002BCE, 0xFFFFEEE9, 0x00000443, 0x00001982, 0xFFFFF90D, 0x000002DF, 0x00001982, 0xFFFFF90D, 0x000002DF }, + { 0x0213F0FD42D048E4, 0x00003495, 0xFFFFE7D9, 0x0000057B, 0x00001D2A, 0xFFFFF5A5, 0x00000372, 0x00001D2A, 0xFFFFF5A5, 0x00000372 }, + { 0x0213F0FD42CA38E4, 0x000034B1, 0xFFFFE88D, 0x00000556, 0x00002014, 0xFFFFF43A, 0x000003AA, 0x00002014, 0xFFFFF43A, 0x000003AA }, + { 0x0213F0FD42CC3124, 0x00002F96, 0xFFFFEC84, 0x000004AD, 0x000024A2, 0xFFFFF1CE, 0x0000040A, 0x000024A2, 0xFFFFF1CE, 0x0000040A }, + { 0x0213EA94DE161064, 0x0000203B, 0xFFFFF640, 0x00000359, 0x000014EC, 0xFFFFFC14, 0x0000029C, 0x000014EC, 0xFFFFFC14, 0x0000029C }, + { 0x0213F0FD42D02984, 0x000034E2, 0xFFFFE7B8, 0x00000582, 0x00001938, 0xFFFFF872, 0x000002FA, 0x00001938, 0xFFFFF872, 0x000002FA }, + { 0x0213EA94DE063124, 0x00002AC7, 0xFFFFF0C1, 0x000003F5, 0x00002268, 0xFFFFF39C, 0x000003C9, 0x00002268, 0xFFFFF39C, 0x000003C9 }, + { 0x0213F0FD42C63144, 0x000036F6, 0xFFFFE77F, 0x00000571, 0x000027D9, 0xFFFFEF6F, 0x00000461, 0x000027D9, 0xFFFFEF6F, 0x00000461 }, + { 0x0213EA94DE123124, 0x00002BAB, 0xFFFFF018, 0x00000419, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, + { 0x0213EA94DE323924, 0x000028C4, 0xFFFFF161, 0x000003F8, 0x0000180C, 0xFFFFFA4B, 0x000002C8, 0x0000180C, 0xFFFFFA4B, 0x000002C8 }, + { 0x0213F0FD42CA2864, 0x00002F48, 0xFFFFEB62, 0x000004EE, 0x00001912, 0xFFFFF8C8, 0x000002EA, 0x00001912, 0xFFFFF8C8, 0x000002EA }, + { 0x0213F0FD42CE2864, 0x000032DF, 0xFFFFE911, 0x00000545, 0x00001F06, 0xFFFFF485, 0x0000039C, 0x00001F06, 0xFFFFF485, 0x0000039C }, + { 0x0213F0FD42D04144, 0x000035B8, 0xFFFFE74F, 0x00000590, 0x00001FD7, 0xFFFFF410, 0x000003AF, 0x00001FD7, 0xFFFFF410, 0x000003AF }, + { 0x0213F0FD42D050C4, 0x00003608, 0xFFFFE6D7, 0x000005A9, 0x000024A6, 0xFFFFF075, 0x00000450, 0x000024A6, 0xFFFFF075, 0x00000450 }, + { 0x0213F0FD42CA3884, 0x000030AB, 0xFFFFEAED, 0x000004F5, 0x000019EE, 0xFFFFF84E, 0x000002FC, 0x000019EE, 0xFFFFF84E, 0x000002FC }, + { 0x0213EA94DE0620C4, 0x000030C6, 0xFFFFEC92, 0x0000049E, 0x000019BB, 0xFFFFF8F1, 0x000002F3, 0x000019BB, 0xFFFFF8F1, 0x000002F3 }, + { 0x0213F0FD42C630A4, 0x00003B27, 0xFFFFE544, 0x000005C1, 0x00002697, 0xFFFFF072, 0x00000438, 0x00002697, 0xFFFFF072, 0x00000438 }, + { 0x0213EA94DE1248E4, 0x00002F23, 0xFFFFEC48, 0x000004B9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, + { 0x0213EA94DE0629A4, 0x00002BD7, 0xFFFFEEAC, 0x00000450, 0x00001991, 0xFFFFF8F4, 0x000002E2, 0x00001991, 0xFFFFF8F4, 0x000002E2 }, + { 0x0213EA94DE022024, 0x00003210, 0xFFFFEB24, 0x000004DE, 0x00001BDF, 0xFFFFF744, 0x00000333, 0x00001BDF, 0xFFFFF744, 0x00000333 }, + { 0x0213EA94DE244144, 0x00002DDC, 0xFFFFED0D, 0x000004AC, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, + { 0x0213EA94DE203964, 0x000023E6, 0xFFFFF40C, 0x000003A9, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, + { 0x0213F0FD42CA29A4, 0x000030CE, 0xFFFFE9A5, 0x0000053C, 0x00001C45, 0xFFFFF60E, 0x0000035D, 0x00001C45, 0xFFFFF60E, 0x0000035D }, + { 0x0213EA94DE161084, 0x00001E89, 0xFFFFF73A, 0x00000337, 0x0000157C, 0xFFFFFBC0, 0x000002AA, 0x0000157C, 0xFFFFFBC0, 0x000002AA }, + { 0x0213F0FD42D04124, 0x000036C6, 0xFFFFE6CF, 0x000005A1, 0x00002457, 0xFFFFF11D, 0x0000042D, 0x00002457, 0xFFFFF11D, 0x0000042D }, + { 0x0213EA94DE321944, 0x00002815, 0xFFFFF19A, 0x000003F2, 0x000016D2, 0xFFFFFB40, 0x00000299, 0x000016D2, 0xFFFFFB40, 0x00000299 }, + { 0x0213EA94DE1C19A4, 0x00001FE2, 0xFFFFF660, 0x00000354, 0x000015A7, 0xFFFFFB47, 0x000002C1, 0x000015A7, 0xFFFFFB47, 0x000002C1 }, + { 0x0213EA94DE161964, 0x00002114, 0xFFFFF634, 0x00000356, 0x000016C1, 0xFFFFFB43, 0x000002B8, 0x000016C1, 0xFFFFFB43, 0x000002B8 }, + { 0x0213F0FD42CC28C4, 0x000028E3, 0xFFFFF075, 0x00000414, 0x0000203C, 0xFFFFF438, 0x000003B3, 0x0000203C, 0xFFFFF438, 0x000003B3 }, + { 0x0213EA94DE1C3924, 0x00001EEB, 0xFFFFF7BB, 0x0000031A, 0x00001580, 0xFFFFFBD7, 0x000002AD, 0x00001580, 0xFFFFFBD7, 0x000002AD }, + { 0x0213EA94DE2408C4, 0x00002BB2, 0xFFFFEE72, 0x00000470, 0x0000192C, 0xFFFFF91E, 0x000002E7, 0x0000192C, 0xFFFFF91E, 0x000002E7 }, + { 0x0213EA94DE0650E4, 0x00003A3D, 0xFFFFE49D, 0x000005F5, 0x00001A3B, 0xFFFFF7B1, 0x00000320, 0x00001A3B, 0xFFFFF7B1, 0x00000320 }, + { 0x0213F0FD42CE3164, 0x00002E93, 0xFFFFEC5A, 0x000004B4, 0x000025EB, 0xFFFFF03C, 0x0000044A, 0x000025EB, 0xFFFFF03C, 0x0000044A }, + { 0x0213F0FD42CA20C4, 0x0000331F, 0xFFFFE97A, 0x00000531, 0x00001A06, 0xFFFFF850, 0x000002FD, 0x00001A06, 0xFFFFF850, 0x000002FD }, + { 0x0213F0FD42C63964, 0x00003937, 0xFFFFE5A0, 0x000005C7, 0x0000235E, 0xFFFFF234, 0x000003F2, 0x0000235E, 0xFFFFF234, 0x000003F2 }, + { 0x0213EA94DE1E3924, 0x00001DD0, 0xFFFFF80E, 0x00000319, 0x000015C7, 0xFFFFFB91, 0x000002BC, 0x000015C7, 0xFFFFFB91, 0x000002BC }, + { 0x0213F0FD42D03964, 0x00003328, 0xFFFFE905, 0x0000054A, 0x00002054, 0xFFFFF3BF, 0x000003C0, 0x00002054, 0xFFFFF3BF, 0x000003C0 }, + { 0x0213F0FD42CC1104, 0x00002FE5, 0xFFFFEA65, 0x00000520, 0x0000188B, 0xFFFFF8A7, 0x000002F5, 0x0000188B, 0xFFFFF8A7, 0x000002F5 }, + { 0x0213F0FD42CA38A4, 0x00002ED3, 0xFFFFEC51, 0x000004B9, 0x00001888, 0xFFFFF96A, 0x000002CA, 0x00001888, 0xFFFFF96A, 0x000002CA }, + { 0x0213F0FD42D03084, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001F8D, 0xFFFFF436, 0x000003B4, 0x00001F8D, 0xFFFFF436, 0x000003B4 }, + { 0x0213F0FD42CE4084, 0x0000329F, 0xFFFFE8F7, 0x0000054F, 0x000023DB, 0xFFFFF0EE, 0x0000043A, 0x000023DB, 0xFFFFF0EE, 0x0000043A }, + { 0x0213EA94DE0438A4, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001AFD, 0xFFFFF781, 0x00000329, 0x00001AFD, 0xFFFFF781, 0x00000329 }, + { 0x0213EA94DE1E19A4, 0x00001BBF, 0xFFFFF8E2, 0x000002F7, 0x00001722, 0xFFFFFA85, 0x000002DB, 0x00001722, 0xFFFFFA85, 0x000002DB }, + { 0x0213EA94DE022044, 0x000030E4, 0xFFFFEBE6, 0x000004BB, 0x00001C80, 0xFFFFF6E1, 0x0000033E, 0x00001C80, 0xFFFFF6E1, 0x0000033E }, + { 0x0213EA94DE122944, 0x000030E2, 0xFFFFECD0, 0x00000492, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, + { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, + { 0x0213EA94DE1610A4, 0x00002147, 0xFFFFF585, 0x0000037A, 0x000014CC, 0xFFFFFC3B, 0x00000296, 0x000014CC, 0xFFFFFC3B, 0x00000296 }, + { 0x0213EA94DE322124, 0x00002507, 0xFFFFF432, 0x0000038A, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, + { 0x0213EA94DE0638A4, 0x0000339B, 0xFFFFEA7D, 0x000004F0, 0x0000191E, 0xFFFFF944, 0x000002DF, 0x0000191E, 0xFFFFF944, 0x000002DF }, + { 0x0213F0FD42CC28A4, 0x00002842, 0xFFFFF043, 0x00000427, 0x00001988, 0xFFFFF892, 0x000002F7, 0x00001988, 0xFFFFF892, 0x000002F7 }, + { 0x0213F0FD42C618A4, 0x0000389D, 0xFFFFE5D8, 0x000005BF, 0x00001EE1, 0xFFFFF4EF, 0x00000387, 0x00001EE1, 0xFFFFF4EF, 0x00000387 }, + { 0x0213F0FD42CE3184, 0x0000396D, 0xFFFFE4D7, 0x000005F2, 0x000020DA, 0xFFFFF34E, 0x000003CD, 0x000020DA, 0xFFFFF34E, 0x000003CD }, + { 0x0213F0FD42CA3104, 0x0000355F, 0xFFFFE85A, 0x0000055F, 0x0000281F, 0xFFFFEF28, 0x0000047D, 0x0000281F, 0xFFFFEF28, 0x0000047D }, + { 0x0213EA94DE1C50E4, 0x00002284, 0xFFFFF46E, 0x00000399, 0x00001498, 0xFFFFFBE3, 0x0000029C, 0x00001498, 0xFFFFFBE3, 0x0000029C }, + { 0x0213EA94DE023944, 0x000031B6, 0xFFFFEB42, 0x000004D9, 0x00001F54, 0xFFFFF4D2, 0x00000399, 0x00001F54, 0xFFFFF4D2, 0x00000399 }, + { 0x0213F0FD42C63064, 0x000035CE, 0xFFFFE79D, 0x00000578, 0x00001C78, 0xFFFFF68C, 0x00000344, 0x00001C78, 0xFFFFF68C, 0x00000344 }, + { 0x0213EA94DE1E4964, 0x00001C0A, 0xFFFFF81B, 0x00000318, 0x00001492, 0xFFFFFBCC, 0x000002A5, 0x00001492, 0xFFFFFBCC, 0x000002A5 }, + { 0x0213EA94DE022184, 0x00003492, 0xFFFFE95C, 0x00000526, 0x00001A97, 0xFFFFF81B, 0x0000030B, 0x00001A97, 0xFFFFF81B, 0x0000030B }, + { 0x0213EA94DE163164, 0x00001E89, 0xFFFFF7D0, 0x0000031A, 0x000017A5, 0xFFFFFA99, 0x000002D9, 0x000017A5, 0xFFFFFA99, 0x000002D9 }, + { 0x0213F0FD42CA48C4, 0x00002DCC, 0xFFFFEBE0, 0x000004DE, 0x000019BA, 0xFFFFF7F5, 0x0000030D, 0x000019BA, 0xFFFFF7F5, 0x0000030D }, + { 0x0213EA94DE042984, 0x000030EF, 0xFFFFEBC1, 0x000004C0, 0x00001AA9, 0xFFFFF814, 0x0000030A, 0x00001AA9, 0xFFFFF814, 0x0000030A }, + { 0x0213EA94DE245124, 0x00002EA3, 0xFFFFEBF6, 0x000004D8, 0x00001DCF, 0xFFFFF521, 0x00000399, 0x00001DCF, 0xFFFFF521, 0x00000399 }, + { 0x0213EA94DE324164, 0x00002B5F, 0xFFFFEEA1, 0x0000046C, 0x000017EB, 0xFFFFF9C9, 0x000002D4, 0x000017EB, 0xFFFFF9C9, 0x000002D4 }, + { 0x0213EA94DE024104, 0x00002C63, 0xFFFFEE82, 0x00000455, 0x00002268, 0xFFFFF29D, 0x000003F6, 0x00002268, 0xFFFFF29D, 0x000003F6 }, + { 0x0213EA94DE121904, 0x00002B1A, 0xFFFFF016, 0x0000041C, 0x000019AA, 0xFFFFF988, 0x000002D2, 0x000019AA, 0xFFFFF988, 0x000002D2 }, + { 0x0213F0FD42CA2964, 0x0000332F, 0xFFFFE934, 0x0000053B, 0x00001E47, 0xFFFFF566, 0x00000374, 0x00001E47, 0xFFFFF566, 0x00000374 }, + { 0x0213F0FD42CA48E4, 0x00002995, 0xFFFFEEC1, 0x00000465, 0x0000178F, 0xFFFFF995, 0x000002C5, 0x0000178F, 0xFFFFF995, 0x000002C5 }, + { 0x0213EA94DE201884, 0x00001C2E, 0xFFFFF932, 0x000002E9, 0x000015C2, 0xFFFFFBC5, 0x000002AD, 0x000015C2, 0xFFFFFBC5, 0x000002AD }, + { 0x0213F0FD42C640E4, 0x00003B08, 0xFFFFE4E8, 0x000005D8, 0x0000209D, 0xFFFFF444, 0x00000398, 0x0000209D, 0xFFFFF444, 0x00000398 }, + { 0x0213EA94DE0450E4, 0x00002F1F, 0xFFFFEB74, 0x000004EB, 0x00001F4C, 0xFFFFF3D4, 0x000003CE, 0x00001F4C, 0xFFFFF3D4, 0x000003CE }, + { 0x0213EA94DE043884, 0x00003415, 0xFFFFE89F, 0x00000553, 0x0000186B, 0xFFFFF8E1, 0x000002EF, 0x0000186B, 0xFFFFF8E1, 0x000002EF }, + { 0x0213F0FD42CC10C4, 0x00003441, 0xFFFFE779, 0x0000059D, 0x000019EA, 0xFFFFF7B2, 0x0000031F, 0x000019EA, 0xFFFFF7B2, 0x0000031F }, + { 0x0213EA94DE164064, 0x00002174, 0xFFFFF546, 0x00000378, 0x00001456, 0xFFFFFC5F, 0x00000284, 0x00001456, 0xFFFFFC5F, 0x00000284 }, + { 0x0213F0FD42CE40C4, 0x00003788, 0xFFFFE61E, 0x000005BF, 0x00001DF4, 0xFFFFF562, 0x00000374, 0x00001DF4, 0xFFFFF562, 0x00000374 }, + { 0x0213EA94DE1E1844, 0x00001C41, 0xFFFFF8C1, 0x000002FC, 0x0000171E, 0xFFFFFA93, 0x000002DE, 0x0000171E, 0xFFFFFA93, 0x000002DE }, + { 0x0213F0FD42CA3864, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x000017E4, 0xFFFFF934, 0x000002DF, 0x000017E4, 0xFFFFF934, 0x000002DF }, + { 0x0213F0FD42CC3144, 0x0000327A, 0xFFFFEA71, 0x000004FF, 0x00001D96, 0xFFFFF63B, 0x00000351, 0x00001D96, 0xFFFFF63B, 0x00000351 }, + { 0x0213EA94DE1E4064, 0x000023C6, 0xFFFFF3E5, 0x000003B6, 0x000014DE, 0xFFFFFC29, 0x00000294, 0x000014DE, 0xFFFFFC29, 0x00000294 }, + { 0x0213EA94DE164944, 0x00001F96, 0xFFFFF5FA, 0x00000364, 0x00001397, 0xFFFFFC9D, 0x0000027D, 0x00001397, 0xFFFFFC9D, 0x0000027D }, + { 0x0213EA94DE063144, 0x00002B51, 0xFFFFEFB5, 0x00000420, 0x00001ACA, 0xFFFFF824, 0x0000030D, 0x00001ACA, 0xFFFFF824, 0x0000030D }, + { 0x0213EA94DE1E4944, 0x000020DB, 0xFFFFF55B, 0x0000037C, 0x0000153D, 0xFFFFFB5F, 0x000002BA, 0x0000153D, 0xFFFFFB5F, 0x000002BA }, + { 0x0213EA94DE0221A4, 0x000030BB, 0xFFFFEBDA, 0x000004BC, 0x00001B0E, 0xFFFFF7A8, 0x0000031E, 0x00001B0E, 0xFFFFF7A8, 0x0000031E }, + { 0x0213F0FD42C62904, 0x000033C4, 0xFFFFEA41, 0x000004FA, 0x000022C6, 0xFFFFF363, 0x000003BC, 0x000022C6, 0xFFFFF363, 0x000003BC }, + { 0x0213EA94DE240924, 0x00002D47, 0xFFFFEE01, 0x00000477, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, + { 0x0213EA94DE1E31A4, 0x00001E7B, 0xFFFFF733, 0x00000339, 0x00001668, 0xFFFFFB29, 0x000002BF, 0x00001668, 0xFFFFFB29, 0x000002BF }, + { 0x0213F0FD42CA2984, 0x00002F7E, 0xFFFFEAFF, 0x000004FC, 0x000018D4, 0xFFFFF8BE, 0x000002E8, 0x000018D4, 0xFFFFF8BE, 0x000002E8 }, + { 0x0213EA94DE3238A4, 0x00002635, 0xFFFFF2E1, 0x000003BC, 0x000017A4, 0xFFFFFA67, 0x000002C3, 0x000017A4, 0xFFFFFA67, 0x000002C3 }, + { 0x0213EA94DE1230A4, 0x000026CA, 0xFFFFF2C1, 0x000003B2, 0x00001C3E, 0xFFFFF7AE, 0x0000031F, 0x00001C3E, 0xFFFFF7AE, 0x0000031F }, + { 0x0213EA94DE1C1064, 0x00002550, 0xFFFFF380, 0x000003B5, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, + { 0x0213F0FD42CA4904, 0x00002FBC, 0xFFFFEAF8, 0x000004FA, 0x000018CC, 0xFFFFF8C6, 0x000002E8, 0x000018CC, 0xFFFFF8C6, 0x000002E8 }, + { 0x0213F0FD42D018E4, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001EFF, 0xFFFFF4DA, 0x0000038F, 0x00001EFF, 0xFFFFF4DA, 0x0000038F }, + { 0x0213EA94DE164084, 0x000023E6, 0xFFFFF413, 0x000003A1, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, + { 0x0213F0FD42CE3024, 0x00003251, 0xFFFFEAA2, 0x000004F5, 0x000025B0, 0xFFFFF0DF, 0x00000431, 0x000025B0, 0xFFFFF0DF, 0x00000431 }, + { 0x0213F0FD42D03984, 0x00002F6F, 0xFFFFEB67, 0x000004E6, 0x00002275, 0xFFFFF249, 0x000003FB, 0x00002275, 0xFFFFF249, 0x000003FB }, + { 0x0213EA94DE322964, 0x00002597, 0xFFFFF34A, 0x000003B1, 0x00001BCC, 0xFFFFF822, 0x0000031A, 0x00001BCC, 0xFFFFF822, 0x0000031A }, + { 0x0213F0FD42C63864, 0x00003B1D, 0xFFFFE40E, 0x0000060D, 0x00001F61, 0xFFFFF470, 0x0000039F, 0x00001F61, 0xFFFFF470, 0x0000039F }, + { 0x0213F0FD42C64144, 0x0000379F, 0xFFFFE6DB, 0x0000058C, 0x00002460, 0xFFFFF170, 0x00000415, 0x00002460, 0xFFFFF170, 0x00000415 }, + { 0x0213EA94DE165144, 0x00002442, 0xFFFFF2FB, 0x000003D9, 0x00001414, 0xFFFFFBDC, 0x000002A2, 0x00001414, 0xFFFFFBDC, 0x000002A2 }, + { 0x0213EA94DE0240C4, 0x00003270, 0xFFFFEA0D, 0x0000051C, 0x00001AFD, 0xFFFFF783, 0x00000328, 0x00001AFD, 0xFFFFF783, 0x00000328 }, + { 0x0213EA94DE161104, 0x00001B23, 0xFFFFF94B, 0x000002EB, 0x000015F1, 0xFFFFFB82, 0x000002B4, 0x000015F1, 0xFFFFFB82, 0x000002B4 }, + { 0x0213EA94DE323844, 0x000026AE, 0xFFFFF21A, 0x000003DB, 0x00001827, 0xFFFFFA10, 0x000002C8, 0x00001827, 0xFFFFFA10, 0x000002C8 }, + { 0x0213F0FD42CA4884, 0x00002DCF, 0xFFFFEBD8, 0x000004DB, 0x00001A75, 0xFFFFF719, 0x0000033A, 0x00001A75, 0xFFFFF719, 0x0000033A }, + { 0x0213F0FD42CE40E4, 0x00003983, 0xFFFFE500, 0x000005EA, 0x000022A6, 0xFFFFF25F, 0x000003F1, 0x000022A6, 0xFFFFF25F, 0x000003F1 }, + { 0x0213EA94DE1218C4, 0x00002AD5, 0xFFFFF07A, 0x00000406, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, + { 0x0213F0FD42CA39A4, 0x00002A43, 0xFFFFEE43, 0x00000474, 0x00001D65, 0xFFFFF538, 0x00000387, 0x00001D65, 0xFFFFF538, 0x00000387 }, + { 0x0213F0FD42C62084, 0x0000311E, 0xFFFFEAF8, 0x000004E8, 0x00001959, 0xFFFFF8E4, 0x000002DC, 0x00001959, 0xFFFFF8E4, 0x000002DC }, + { 0x0213F0FD42D031A4, 0x0000339A, 0xFFFFE8A7, 0x00000559, 0x00001A04, 0xFFFFF7E5, 0x00000311, 0x00001A04, 0xFFFFF7E5, 0x00000311 }, + { 0x0213EA94DE204144, 0x000021B3, 0xFFFFF50F, 0x00000389, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, + { 0x0213EA94DE021884, 0x00003417, 0xFFFFE9A6, 0x0000051D, 0x000018A4, 0xFFFFF984, 0x000002CF, 0x000018A4, 0xFFFFF984, 0x000002CF }, + { 0x0213EA94DE202984, 0x00001FED, 0xFFFFF6A2, 0x00000347, 0x00001639, 0xFFFFFB59, 0x000002BB, 0x00001639, 0xFFFFFB59, 0x000002BB }, + { 0x0213EA94DE1218A4, 0x000032D2, 0xFFFFEB18, 0x000004DC, 0x00001A01, 0xFFFFF95E, 0x000002CF, 0x00001A01, 0xFFFFF95E, 0x000002CF }, + { 0x0213F0FD42D04084, 0x00003147, 0xFFFFEA3B, 0x00000518, 0x0000241D, 0xFFFFF11C, 0x00000431, 0x0000241D, 0xFFFFF11C, 0x00000431 }, + { 0x0213EA94DE1C0904, 0x00001D44, 0xFFFFF7E7, 0x0000031A, 0x0000153F, 0xFFFFFBBC, 0x000002A9, 0x0000153F, 0xFFFFFBBC, 0x000002A9 }, + { 0x0213F0FD42CC4104, 0x00003690, 0xFFFFE6E3, 0x000005A4, 0x000018DE, 0xFFFFF908, 0x000002DD, 0x000018DE, 0xFFFFF908, 0x000002DD }, + { 0x0213F0FD42CC2184, 0x00003561, 0xFFFFE6F8, 0x000005AB, 0x000018B5, 0xFFFFF8A0, 0x000002F3, 0x000018B5, 0xFFFFF8A0, 0x000002F3 }, + { 0x0213EA94DE323124, 0x000028F4, 0xFFFFF23A, 0x000003CE, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, + { 0x0213F0FD42D03184, 0x000035D7, 0xFFFFE71C, 0x0000059B, 0x00001D49, 0xFFFFF5C8, 0x00000368, 0x00001D49, 0xFFFFF5C8, 0x00000368 }, + { 0x0213F0FD42CE18A4, 0x0000397E, 0xFFFFE4CB, 0x000005F4, 0x00001989, 0xFFFFF844, 0x000002FD, 0x00001989, 0xFFFFF844, 0x000002FD }, + { 0x0213F0FD42C62064, 0x00003BAB, 0xFFFFE332, 0x0000063F, 0x00001A69, 0xFFFFF7B9, 0x00000312, 0x00001A69, 0xFFFFF7B9, 0x00000312 }, + { 0x0213F0FD42D03064, 0x00002F26, 0xFFFFEB82, 0x000004E8, 0x00001D7D, 0xFFFFF590, 0x00000379, 0x00001D7D, 0xFFFFF590, 0x00000379 }, + { 0x0213EA94DE0631A4, 0x00002FDC, 0xFFFFEBE0, 0x000004C3, 0x00001940, 0xFFFFF8CC, 0x000002EE, 0x00001940, 0xFFFFF8CC, 0x000002EE }, + { 0x0213EA94DE1C08E4, 0x000021B2, 0xFFFFF558, 0x00000379, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, + { 0x0213EA94DE321904, 0x00002897, 0xFFFFF181, 0x000003F7, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, + { 0x0213EA94DE1E0924, 0x00001D19, 0xFFFFF829, 0x0000031A, 0x00001558, 0xFFFFFBCA, 0x000002AF, 0x00001558, 0xFFFFFBCA, 0x000002AF }, + { 0x0213EA94DE043144, 0x00003311, 0xFFFFEAD9, 0x000004E1, 0x00001BDC, 0xFFFFF79E, 0x0000031D, 0x00001BDC, 0xFFFFF79E, 0x0000031D }, + { 0x0213EA94DE1E29C4, 0x00001E54, 0xFFFFF740, 0x00000333, 0x000016A1, 0xFFFFFAF0, 0x000002C4, 0x000016A1, 0xFFFFFAF0, 0x000002C4 }, + { 0x0213F0FD42CE3964, 0x00003266, 0xFFFFE9A8, 0x00000527, 0x00002307, 0xFFFFF219, 0x000003FC, 0x00002307, 0xFFFFF219, 0x000003FC }, + { 0x0213EA94DE321144, 0x00001D1F, 0xFFFFF82B, 0x000002F0, 0x000013F0, 0xFFFFFD0B, 0x0000024E, 0x000013F0, 0xFFFFFD0B, 0x0000024E }, + { 0x0213F0FD42C648A4, 0x0000312E, 0xFFFFEA67, 0x00000502, 0x0000222A, 0xFFFFF253, 0x000003F9, 0x0000222A, 0xFFFFF253, 0x000003F9 }, + { 0x0213F0FD42CA4124, 0x000032B2, 0xFFFFE9AD, 0x00000523, 0x00001E97, 0xFFFFF527, 0x0000037F, 0x00001E97, 0xFFFFF527, 0x0000037F }, + { 0x0213EA94DE1640E4, 0x00001F6A, 0xFFFFF6FC, 0x00000338, 0x0000164B, 0xFFFFFB2C, 0x000002C2, 0x0000164B, 0xFFFFFB2C, 0x000002C2 }, + { 0x0213EA94DE0228C4, 0x00002603, 0xFFFFF386, 0x00000392, 0x00001EE0, 0xFFFFF601, 0x00000369, 0x00001EE0, 0xFFFFF601, 0x00000369 }, + { 0x0213EA94DE201164, 0x00001D0C, 0xFFFFF803, 0x00000317, 0x00001345, 0xFFFFFD52, 0x00000260, 0x00001345, 0xFFFFFD52, 0x00000260 }, + { 0x0213F0FD42CC1884, 0x0000327A, 0xFFFFE8E5, 0x0000055C, 0x00001680, 0xFFFFFA2D, 0x000002B2, 0x00001680, 0xFFFFFA2D, 0x000002B2 }, + { 0x0213F0FD42CA3964, 0x000032B8, 0xFFFFE91A, 0x0000054A, 0x00001BAB, 0xFFFFF6EC, 0x00000338, 0x00001BAB, 0xFFFFF6EC, 0x00000338 }, + { 0x0213F0FD42CC3044, 0x00002F79, 0xFFFFEB63, 0x000004EF, 0x000017BB, 0xFFFFF9B1, 0x000002CA, 0x000017BB, 0xFFFFF9B1, 0x000002CA }, + { 0x0213EA94DE0438E4, 0x00002AE5, 0xFFFFEFCB, 0x0000041D, 0x0000214A, 0xFFFFF3A7, 0x000003C7, 0x0000214A, 0xFFFFF3A7, 0x000003C7 }, + { 0x0213EA94DE322064, 0x0000212C, 0xFFFFF5BC, 0x0000034F, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, + { 0x0213EA94DE121124, 0x00002BE7, 0xFFFFEF40, 0x0000043C, 0x00001AE2, 0xFFFFF8CF, 0x000002E3, 0x00001AE2, 0xFFFFF8CF, 0x000002E3 }, + { 0x0213F0FD42D05144, 0x000032DC, 0xFFFFE90F, 0x00000549, 0x00002A2D, 0xFFFFECC9, 0x000004ED, 0x00002A2D, 0xFFFFECC9, 0x000004ED }, + { 0x0213EA94DE1618A4, 0x00001DE3, 0xFFFFF80D, 0x00000319, 0x000016FA, 0xFFFFFB42, 0x000002BC, 0x000016FA, 0xFFFFFB42, 0x000002BC }, + { 0x0213EA94DE1E2844, 0x00001F1B, 0xFFFFF6DE, 0x00000346, 0x00001502, 0xFFFFFC23, 0x00000298, 0x00001502, 0xFFFFFC23, 0x00000298 }, + { 0x0213EA94DE061864, 0x00003203, 0xFFFFEA87, 0x000004FE, 0x0000194E, 0xFFFFF8E3, 0x000002EC, 0x0000194E, 0xFFFFF8E3, 0x000002EC }, + { 0x0213F0FD42D02144, 0x0000337A, 0xFFFFE8DD, 0x00000551, 0x00001E3C, 0xFFFFF534, 0x00000385, 0x00001E3C, 0xFFFFF534, 0x00000385 }, + { 0x0213F0FD42CA4864, 0x000036F6, 0xFFFFE62A, 0x000005C5, 0x000023C0, 0xFFFFF117, 0x00000435, 0x000023C0, 0xFFFFF117, 0x00000435 }, + { 0x0213F0FD42CC2144, 0x00003125, 0xFFFFEA4E, 0x0000051A, 0x00001E6C, 0xFFFFF503, 0x0000038E, 0x00001E6C, 0xFFFFF503, 0x0000038E }, + { 0x0213EA94DE1C08A4, 0x00001CD4, 0xFFFFF82D, 0x0000030E, 0x0000156D, 0xFFFFFB64, 0x000002B8, 0x0000156D, 0xFFFFFB64, 0x000002B8 }, + { 0x0213EA94DE0240A4, 0x00002F14, 0xFFFFEC46, 0x000004B8, 0x000017F1, 0xFFFFF977, 0x000002D2, 0x000017F1, 0xFFFFF977, 0x000002D2 }, + { 0x0213EA94DE0640A4, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x0000184C, 0xFFFFF983, 0x000002D4, 0x0000184C, 0xFFFFF983, 0x000002D4 }, + { 0x0213F0FD42D04984, 0x00002EA9, 0xFFFFEBD7, 0x000004D5, 0x0000288D, 0xFFFFEDDB, 0x000004C0, 0x0000288D, 0xFFFFEDDB, 0x000004C0 }, + { 0x0213F0FD42CA3984, 0x0000335F, 0xFFFFE82C, 0x00000579, 0x00001DBF, 0xFFFFF512, 0x0000038C, 0x00001DBF, 0xFFFFF512, 0x0000038C }, + { 0x0213EA94DE201184, 0x0000224F, 0xFFFFF4B5, 0x00000391, 0x0000138C, 0xFFFFFCC3, 0x0000027A, 0x0000138C, 0xFFFFFCC3, 0x0000027A }, + { 0x0213EA94DE1240A4, 0x0000320D, 0xFFFFEACD, 0x000004F5, 0x00001976, 0xFFFFF913, 0x000002E2, 0x00001976, 0xFFFFF913, 0x000002E2 }, + { 0x0213EA94DE202104, 0x00001BEB, 0xFFFFF99C, 0x000002E4, 0x000016A4, 0xFFFFFB77, 0x000002C3, 0x000016A4, 0xFFFFFB77, 0x000002C3 }, + { 0x0213EA94DE063044, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x000018F4, 0xFFFFF91A, 0x000002E3, 0x000018F4, 0xFFFFF91A, 0x000002E3 }, + { 0x0213EA94DE022864, 0x00003251, 0xFFFFEA8E, 0x000004FA, 0x000018EF, 0xFFFFF910, 0x000002E4, 0x000018EF, 0xFFFFF910, 0x000002E4 }, + { 0x0213EA94DE1C1924, 0x00001DAF, 0xFFFFF857, 0x0000030D, 0x00001915, 0xFFFFF9D8, 0x000002F7, 0x00001915, 0xFFFFF9D8, 0x000002F7 }, + { 0x0213EA94DE2041A4, 0x000025B6, 0xFFFFF26B, 0x000003E5, 0x00001531, 0xFFFFFB68, 0x000002AF, 0x00001531, 0xFFFFFB68, 0x000002AF }, + { 0x0213EA94DE061884, 0x00002B2E, 0xFFFFEF2E, 0x00000440, 0x00001968, 0xFFFFF91A, 0x000002DF, 0x00001968, 0xFFFFF91A, 0x000002DF }, + { 0x0213EA94DE1C2064, 0x00002305, 0xFFFFF528, 0x00000377, 0x000018A4, 0xFFFFF9EB, 0x000002F0, 0x000018A4, 0xFFFFF9EB, 0x000002F0 }, + { 0x0213F0FD42CA40C4, 0x000032A1, 0xFFFFE992, 0x0000052E, 0x00001A55, 0xFFFFF826, 0x000002FE, 0x00001A55, 0xFFFFF826, 0x000002FE }, + { 0x0213EA94DE042184, 0x00002CCD, 0xFFFFEE35, 0x00000462, 0x00001B09, 0xFFFFF7E6, 0x0000030F, 0x00001B09, 0xFFFFF7E6, 0x0000030F }, + { 0x0213EA94DE323084, 0x00002602, 0xFFFFF2CF, 0x000003C5, 0x000016EE, 0xFFFFFAD4, 0x000002B4, 0x000016EE, 0xFFFFFAD4, 0x000002B4 }, + { 0x0213F0FD42D01964, 0x00003370, 0xFFFFE891, 0x00000560, 0x000017F0, 0xFFFFF930, 0x000002DF, 0x000017F0, 0xFFFFF930, 0x000002DF }, + { 0x0213F0FD42CA1884, 0x00002EDC, 0xFFFFEB6D, 0x000004EC, 0x000016E6, 0xFFFFF9ED, 0x000002BC, 0x000016E6, 0xFFFFF9ED, 0x000002BC }, + { 0x0213EA94DE1228C4, 0x00002A05, 0xFFFFF13D, 0x000003F0, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, + { 0x0213F0FD42CE2044, 0x00002F8A, 0xFFFFEB6E, 0x000004E4, 0x00001E3E, 0xFFFFF50E, 0x0000038D, 0x00001E3E, 0xFFFFF50E, 0x0000038D }, + { 0x0213F0FD42CA3044, 0x00002BB5, 0xFFFFED6A, 0x000004A1, 0x000017BF, 0xFFFFF937, 0x000002E5, 0x000017BF, 0xFFFFF937, 0x000002E5 }, + { 0x0213EA94DE201964, 0x0000202C, 0xFFFFF6CE, 0x0000033F, 0x000015EE, 0xFFFFFB83, 0x000002B9, 0x000015EE, 0xFFFFFB83, 0x000002B9 }, + { 0x0213EA94DE022884, 0x00002C0C, 0xFFFFEF10, 0x0000043F, 0x00001A73, 0xFFFFF83E, 0x0000030C, 0x00001A73, 0xFFFFF83E, 0x0000030C }, + { 0x0213EA94DE324104, 0x0000234F, 0xFFFFF460, 0x00000385, 0x000018C3, 0xFFFFF9A5, 0x000002DD, 0x000018C3, 0xFFFFF9A5, 0x000002DD }, + { 0x0213F0FD42CE1904, 0x00003679, 0xFFFFE704, 0x00000595, 0x00002177, 0xFFFFF31A, 0x000003D7, 0x00002177, 0xFFFFF31A, 0x000003D7 }, + { 0x0213F0FD42CA2924, 0x00003008, 0xFFFFEBB8, 0x000004D5, 0x000024FF, 0xFFFFF112, 0x00000430, 0x000024FF, 0xFFFFF112, 0x00000430 }, + { 0x0213F0FD42C641A4, 0x00003848, 0xFFFFE6A3, 0x00000594, 0x00002958, 0xFFFFEE37, 0x000004A0, 0x00002958, 0xFFFFEE37, 0x000004A0 }, + { 0x0213F0FD42CC1924, 0x00002FDF, 0xFFFFEB08, 0x000004FD, 0x00001D77, 0xFFFFF58B, 0x0000037A, 0x00001D77, 0xFFFFF58B, 0x0000037A }, + { 0x0213EA94DE063064, 0x00002EC8, 0xFFFFED41, 0x00000481, 0x00001949, 0xFFFFF91C, 0x000002DF, 0x00001949, 0xFFFFF91C, 0x000002DF }, + { 0x0213F0FD42D041A4, 0x000037C1, 0xFFFFE5BA, 0x000005D7, 0x0000252C, 0xFFFFF023, 0x00000460, 0x0000252C, 0xFFFFF023, 0x00000460 }, + { 0x0213F0FD42CE2944, 0x00003716, 0xFFFFE70C, 0x0000058A, 0x000028CC, 0xFFFFEE57, 0x0000049D, 0x000028CC, 0xFFFFEE57, 0x0000049D }, + { 0x0213F0FD42CA40E4, 0x000033D1, 0xFFFFE8E8, 0x00000547, 0x00001AB1, 0xFFFFF7E5, 0x00000309, 0x00001AB1, 0xFFFFF7E5, 0x00000309 }, + { 0x0213F0FD42CC2944, 0x00002D72, 0xFFFFED65, 0x0000048E, 0x00001E0D, 0xFFFFF5A7, 0x00000370, 0x00001E0D, 0xFFFFF5A7, 0x00000370 }, + { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, + { 0x0213EA94DE243044, 0x000026EE, 0xFFFFF18C, 0x000003F7, 0x000018A7, 0xFFFFF95A, 0x000002E5, 0x000018A7, 0xFFFFF95A, 0x000002E5 }, + { 0x0213EA94DE042164, 0x00002F62, 0xFFFFEC9B, 0x000004A4, 0x0000194E, 0xFFFFF932, 0x000002D9, 0x0000194E, 0xFFFFF932, 0x000002D9 }, + { 0x0213EA94DE1E3984, 0x00001CE8, 0xFFFFF7FA, 0x0000031C, 0x000014CE, 0xFFFFFBD4, 0x000002AB, 0x000014CE, 0xFFFFFBD4, 0x000002AB }, + { 0x0213EA94DE1210E4, 0x00002E5A, 0xFFFFEDAB, 0x0000047C, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, + { 0x0213F0FD42CC30E4, 0x00003057, 0xFFFFEC34, 0x000004B9, 0x00002296, 0xFFFFF342, 0x000003D0, 0x00002296, 0xFFFFF342, 0x000003D0 }, + { 0x0213EA94DE0418A4, 0x00002B0F, 0xFFFFEF58, 0x00000434, 0x00001BFD, 0xFFFFF721, 0x00000330, 0x00001BFD, 0xFFFFF721, 0x00000330 }, + { 0x0213EA94DE2010A4, 0x00001F01, 0xFFFFF751, 0x0000032F, 0x00001502, 0xFFFFFC3E, 0x00000296, 0x00001502, 0xFFFFFC3E, 0x00000296 }, + { 0x0213F0FD42CA3064, 0x00002FF4, 0xFFFFEAE2, 0x00000503, 0x00001B36, 0xFFFFF736, 0x00000330, 0x00001B36, 0xFFFFF736, 0x00000330 }, + { 0x0213F0FD42CE2064, 0x00003762, 0xFFFFE5AB, 0x000005DE, 0x000018CB, 0xFFFFF896, 0x000002F4, 0x000018CB, 0xFFFFF896, 0x000002F4 }, + { 0x0213F0FD42CC2064, 0x00002890, 0xFFFFEF92, 0x00000445, 0x0000191D, 0xFFFFF86F, 0x00000302, 0x0000191D, 0xFFFFF86F, 0x00000302 }, + { 0x0213EA94DE043064, 0x00002F76, 0xFFFFEC0E, 0x000004BF, 0x00001F7D, 0xFFFFF41A, 0x000003C0, 0x00001F7D, 0xFFFFF41A, 0x000003C0 }, + { 0x0213EA94DE1E08A4, 0x00001D55, 0xFFFFF7F8, 0x0000031E, 0x000015DF, 0xFFFFFB79, 0x000002B7, 0x000015DF, 0xFFFFFB79, 0x000002B7 }, + { 0x0213EA94DE204924, 0x00001FE9, 0xFFFFF64A, 0x00000353, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, + { 0x0213EA94DE063964, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001857, 0xFFFFF968, 0x000002D8, 0x00001857, 0xFFFFF968, 0x000002D8 }, + { 0x0213F0FD42CA28C4, 0x00003398, 0xFFFFE9A3, 0x00000524, 0x00001FF9, 0xFFFFF458, 0x000003AD, 0x00001FF9, 0xFFFFF458, 0x000003AD }, + { 0x0213F0FD42CE2964, 0x00003897, 0xFFFFE5BD, 0x000005C8, 0x00002519, 0xFFFFF0BA, 0x00000438, 0x00002519, 0xFFFFF0BA, 0x00000438 }, + { 0x0213F0FD42D04064, 0x00003234, 0xFFFFE9B1, 0x00000530, 0x000022CC, 0xFFFFF20E, 0x00000409, 0x000022CC, 0xFFFFF20E, 0x00000409 }, + { 0x0213EA94DE205104, 0x00001FD2, 0xFFFFF641, 0x00000354, 0x000017C9, 0xFFFFF9C0, 0x000002FB, 0x000017C9, 0xFFFFF9C0, 0x000002FB }, + { 0x0213F0FD42CE48E4, 0x00003234, 0xFFFFE946, 0x0000053D, 0x00002267, 0xFFFFF1F5, 0x0000040D, 0x00002267, 0xFFFFF1F5, 0x0000040D }, + { 0x0213EA94DE2029A4, 0x00002330, 0xFFFFF474, 0x00000399, 0x00001490, 0xFFFFFC67, 0x00000288, 0x00001490, 0xFFFFFC67, 0x00000288 }, + { 0x0213F0FD42D03924, 0x000032A3, 0xFFFFE9EB, 0x0000051B, 0x0000234D, 0xFFFFF23C, 0x000003F7, 0x0000234D, 0xFFFFF23C, 0x000003F7 }, + { 0x0213EA94DE200904, 0x0000217E, 0xFFFFF53A, 0x00000384, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, + { 0x0213F0FD42CE50E4, 0x0000384F, 0xFFFFE562, 0x000005E2, 0x0000295A, 0xFFFFED53, 0x000004D3, 0x0000295A, 0xFFFFED53, 0x000004D3 }, + { 0x0213F0FD42D05124, 0x00003315, 0xFFFFE8D1, 0x00000552, 0x000025D1, 0xFFFFEFAF, 0x00000471, 0x000025D1, 0xFFFFEFAF, 0x00000471 }, + { 0x0213F0FD42C64924, 0x00004183, 0xFFFFDF61, 0x000006DA, 0x0000193C, 0xFFFFF88F, 0x000002EC, 0x0000193C, 0xFFFFF88F, 0x000002EC }, + { 0x0213EA94DE242164, 0x00002DFC, 0xFFFFEDF2, 0x0000047A, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, + { 0x0213F0FD42CA31A4, 0x000033FE, 0xFFFFE774, 0x0000059F, 0x00001E70, 0xFFFFF492, 0x000003A0, 0x00001E70, 0xFFFFF492, 0x000003A0 }, + { 0x0213F0FD42C629A4, 0x000040D7, 0xFFFFDFB8, 0x000006CE, 0x00001AC8, 0xFFFFF773, 0x0000031D, 0x00001AC8, 0xFFFFF773, 0x0000031D }, + { 0x0213EA94DE1E1164, 0x00001D02, 0xFFFFF803, 0x00000322, 0x000015FE, 0xFFFFFB71, 0x000002BB, 0x000015FE, 0xFFFFFB71, 0x000002BB }, + { 0x0213F0FD42D02884, 0x00002EB0, 0xFFFFEC31, 0x000004C4, 0x00001B3C, 0xFFFFF73B, 0x00000330, 0x00001B3C, 0xFFFFF73B, 0x00000330 }, + { 0x0213F0FD42CA4984, 0x00002D9F, 0xFFFFECBF, 0x000004A8, 0x000022B0, 0xFFFFF23C, 0x000003F9, 0x000022B0, 0xFFFFF23C, 0x000003F9 }, + { 0x0213F0FD42CC18E4, 0x00002C6A, 0xFFFFEDAC, 0x00000488, 0x00002419, 0xFFFFF159, 0x00000427, 0x00002419, 0xFFFFF159, 0x00000427 }, + { 0x0213EA94DE1210A4, 0x00002991, 0xFFFFF06C, 0x0000040E, 0x00001AA9, 0xFFFFF8D0, 0x000002E1, 0x00001AA9, 0xFFFFF8D0, 0x000002E1 }, + { 0x0213EA94DE123904, 0x00002F8E, 0xFFFFED1B, 0x00000493, 0x00001DE4, 0xFFFFF69C, 0x00000347, 0x00001DE4, 0xFFFFF69C, 0x00000347 }, + { 0x0213EA94DE204184, 0x00002136, 0xFFFFF540, 0x0000037C, 0x000014FF, 0xFFFFFB83, 0x000002B2, 0x000014FF, 0xFFFFFB83, 0x000002B2 }, + { 0x0213EA94DE0618E4, 0x0000354C, 0xFFFFE97D, 0x0000051A, 0x00001906, 0xFFFFF965, 0x000002DD, 0x00001906, 0xFFFFF965, 0x000002DD }, + { 0x0213F0FD42C620C4, 0x0000348B, 0xFFFFE94D, 0x0000051F, 0x0000285B, 0xFFFFEF1A, 0x00000473, 0x0000285B, 0xFFFFEF1A, 0x00000473 }, + { 0x0213EA94DE3218A4, 0x000026E6, 0xFFFFF24E, 0x000003D6, 0x0000141F, 0xFFFFFCCE, 0x00000260, 0x0000141F, 0xFFFFFCCE, 0x00000260 }, + { 0x0213F0FD42C64164, 0x00003CED, 0xFFFFE2A5, 0x0000064E, 0x00002060, 0xFFFFF3E0, 0x000003B0, 0x00002060, 0xFFFFF3E0, 0x000003B0 }, + { 0x0213EA94DE021084, 0x000029D4, 0xFFFFEFF7, 0x00000426, 0x00001976, 0xFFFFF8E1, 0x000002EE, 0x00001976, 0xFFFFF8E1, 0x000002EE }, + { 0x0213F0FD42CA40A4, 0x00003767, 0xFFFFE601, 0x000005CC, 0x00001D22, 0xFFFFF5F4, 0x00000361, 0x00001D22, 0xFFFFF5F4, 0x00000361 }, + { 0x0213F0FD42C650C4, 0x00003CE8, 0xFFFFE2E8, 0x00000637, 0x0000232C, 0xFFFFF1E7, 0x00000405, 0x0000232C, 0xFFFFF1E7, 0x00000405 }, + { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, + { 0x0213F0FD42CC30A4, 0x00003451, 0xFFFFE8B9, 0x00000551, 0x00001AD7, 0xFFFFF7BF, 0x00000318, 0x00001AD7, 0xFFFFF7BF, 0x00000318 }, + { 0x0213F0FD42CE2984, 0x0000381B, 0xFFFFE5A0, 0x000005D0, 0x00001E0F, 0xFFFFF521, 0x00000382, 0x00001E0F, 0xFFFFF521, 0x00000382 }, + { 0x0213EA94DE2038C4, 0x000023A4, 0xFFFFF4A6, 0x00000394, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, + { 0x0213F0FD42C620A4, 0x00003C2B, 0xFFFFE447, 0x000005F0, 0x0000207F, 0xFFFFF44E, 0x0000039A, 0x0000207F, 0xFFFFF44E, 0x0000039A }, + { 0x0213F0FD42CC3984, 0x00002F07, 0xFFFFEB70, 0x000004E9, 0x00001765, 0xFFFFF9A5, 0x000002C6, 0x00001765, 0xFFFFF9A5, 0x000002C6 }, + { 0x0213F0FD42C62984, 0x00003A01, 0xFFFFE4E0, 0x000005E7, 0x0000227A, 0xFFFFF292, 0x000003E5, 0x0000227A, 0xFFFFF292, 0x000003E5 }, + { 0x0213F0FD42CE20A4, 0x0000376E, 0xFFFFE686, 0x000005A6, 0x00001FCF, 0xFFFFF43B, 0x000003A8, 0x00001FCF, 0xFFFFF43B, 0x000003A8 }, + { 0x0213F0FFEF5A4984, 0x0000485F, 0xFFFFDCC1, 0x00000713, 0x00002CF8, 0xFFFFEC45, 0x000004DA, 0x00002CF8, 0xFFFFEC45, 0x000004DA }, + { 0x0213F0FFEF5C3184, 0x0000331C, 0xFFFFE8FF, 0x00000541, 0x00002366, 0xFFFFF19D, 0x00000411, 0x00002366, 0xFFFFF19D, 0x00000411 }, + { 0x0213F0FFEF643864, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002FB3, 0xFFFFE827, 0x000005B9, 0x00002FB3, 0xFFFFE827, 0x000005B9 }, + { 0x0213EA94DE321104, 0x000023F3, 0xFFFFF3EA, 0x0000039A, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, + { 0x0213F0FFEF5C28A4, 0x000038C0, 0xFFFFE58A, 0x000005CC, 0x000023CA, 0xFFFFF1AA, 0x00000408, 0x000023CA, 0xFFFFF1AA, 0x00000408 }, + { 0x0213F0FFEF662944, 0x00004976, 0xFFFFDD6A, 0x000006D7, 0x000033C6, 0xFFFFE8EB, 0x0000054D, 0x000033C6, 0xFFFFE8EB, 0x0000054D }, + { 0x0213F0FFEF644904, 0x00004049, 0xFFFFDF6D, 0x000006D8, 0x00003129, 0xFFFFE716, 0x000005E9, 0x00003129, 0xFFFFE716, 0x000005E9 }, + { 0x0213F0FFEF661164, 0x000046C2, 0xFFFFDCEB, 0x0000071C, 0x00002E6D, 0xFFFFEA8F, 0x0000052E, 0x00002E6D, 0xFFFFEA8F, 0x0000052E }, + { 0x0213F0FFEF6238A4, 0x00004080, 0xFFFFE1E1, 0x0000063A, 0x0000396D, 0xFFFFE40A, 0x0000062C, 0x0000396D, 0xFFFFE40A, 0x0000062C }, + { 0x0213F0FFEF5E2124, 0x00003DE0, 0xFFFFE358, 0x0000060C, 0x00002AA2, 0xFFFFEDBF, 0x000004A0, 0x00002AA2, 0xFFFFEDBF, 0x000004A0 }, + { 0x0213F0FFEF5E3144, 0x00003FC0, 0xFFFFE2A1, 0x0000061A, 0x000027D8, 0xFFFFEFEC, 0x0000043A, 0x000027D8, 0xFFFFEFEC, 0x0000043A }, + { 0x0213F0FFEF661924, 0x00003FBF, 0xFFFFE2F5, 0x00000603, 0x000032D7, 0xFFFFE900, 0x00000552, 0x000032D7, 0xFFFFE900, 0x00000552 }, + { 0x0213F0FFEF5C10E4, 0x000035EE, 0xFFFFE6CA, 0x000005A2, 0x0000247C, 0xFFFFF088, 0x00000446, 0x0000247C, 0xFFFFF088, 0x00000446 }, + { 0x0213F0FFEF643884, 0x000039C8, 0xFFFFE3AE, 0x0000062A, 0x000028AF, 0xFFFFED24, 0x000004DF, 0x000028AF, 0xFFFFED24, 0x000004DF }, + { 0x0213F0FFEF5C2884, 0x00003BDE, 0xFFFFE33B, 0x00000632, 0x00001B6C, 0xFFFFF720, 0x00000326, 0x00001B6C, 0xFFFFF720, 0x00000326 }, + { 0x0213F0FFEF7210A4, 0x00003818, 0xFFFFE57D, 0x000005D4, 0x000020EF, 0xFFFFF327, 0x000003CE, 0x000020EF, 0xFFFFF327, 0x000003CE }, + { 0x0213F0FFEF5E19A4, 0x000038DA, 0xFFFFE561, 0x000005D3, 0x0000297D, 0xFFFFED6D, 0x000004C5, 0x0000297D, 0xFFFFED6D, 0x000004C5 }, + { 0x0213F0FFEF684884, 0x000027AC, 0xFFFFF0CE, 0x00000417, 0x00001F5F, 0xFFFFF484, 0x000003B2, 0x00001F5F, 0xFFFFF484, 0x000003B2 }, + { 0x0213F0FFEF6648A4, 0x00003F02, 0xFFFFE222, 0x00000643, 0x000026D4, 0xFFFFF000, 0x00000443, 0x000026D4, 0xFFFFF000, 0x00000443 }, + { 0x0213F0FFEF624164, 0x00004303, 0xFFFFDFE3, 0x00000690, 0x0000312C, 0xFFFFE912, 0x00000561, 0x0000312C, 0xFFFFE912, 0x00000561 }, + { 0x0213F0FFEF600904, 0x000039E5, 0xFFFFE31F, 0x00000657, 0x00001D23, 0xFFFFF51F, 0x00000386, 0x00001D23, 0xFFFFF51F, 0x00000386 }, + { 0x0213F0FFEF661144, 0x000041FA, 0xFFFFE01B, 0x00000697, 0x00002767, 0xFFFFEF90, 0x00000455, 0x00002767, 0xFFFFEF90, 0x00000455 }, + { 0x0213F0FFEF6830A4, 0x00002888, 0xFFFFF11C, 0x00000403, 0x00001864, 0xFFFFF9D8, 0x000002D3, 0x00001864, 0xFFFFF9D8, 0x000002D3 }, + { 0x0213EA94DE201864, 0x0000215C, 0xFFFFF5B6, 0x0000036D, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, + { 0x0213F0FFEF683984, 0x00002FAF, 0xFFFFEC27, 0x000004CA, 0x00002184, 0xFFFFF39C, 0x000003CD, 0x00002184, 0xFFFFF39C, 0x000003CD }, + { 0x0213F0FFEF5E10C4, 0x00004ACE, 0xFFFFD9A3, 0x000007BC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC }, + { 0x0213F0FFEF5A3044, 0x00003763, 0xFFFFE797, 0x0000055F, 0x000029B5, 0xFFFFEEA1, 0x00000474, 0x000029B5, 0xFFFFEEA1, 0x00000474 }, + { 0x0213F0FFEF5E3164, 0x00003832, 0xFFFFE6F9, 0x00000575, 0x00002C99, 0xFFFFEC42, 0x000004E3, 0x00002C99, 0xFFFFEC42, 0x000004E3 }, + { 0x0213F0FFEF604164, 0x000041C9, 0xFFFFDE33, 0x0000071E, 0x0000199D, 0xFFFFF808, 0x000002F9, 0x0000199D, 0xFFFFF808, 0x000002F9 }, + { 0x0213F0FFEF641164, 0x0000474A, 0xFFFFD96E, 0x00000802, 0x00002A30, 0xFFFFEB57, 0x0000053F, 0x00002A30, 0xFFFFEB57, 0x0000053F }, + { 0x0213F0FFEF5C31C4, 0x0000312F, 0xFFFFEA6A, 0x00000508, 0x000029D3, 0xFFFFED38, 0x000004D3, 0x000029D3, 0xFFFFED38, 0x000004D3 }, + { 0x0213F0FFEF7210C4, 0x00003BD6, 0xFFFFE2E7, 0x00000644, 0x00002093, 0xFFFFF37B, 0x000003BD, 0x00002093, 0xFFFFF37B, 0x000003BD }, + { 0x0213F0FFEF6840E4, 0x00002F94, 0xFFFFECD4, 0x000004A3, 0x00002196, 0xFFFFF40B, 0x000003B5, 0x00002196, 0xFFFFF40B, 0x000003B5 }, + { 0x0213F0FFEF5E1944, 0x0000369B, 0xFFFFE762, 0x00000571, 0x00002726, 0xFFFFEF99, 0x00000459, 0x00002726, 0xFFFFEF99, 0x00000459 }, + { 0x0213F0FFEF642064, 0x00003F57, 0xFFFFDF47, 0x000006F4, 0x00002E5F, 0xFFFFE8AE, 0x000005AB, 0x00002E5F, 0xFFFFE8AE, 0x000005AB }, + { 0x0213EA94DE0A40C4, 0x00004313, 0xFFFFDD81, 0x0000072D, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, + { 0x0213F0FFEF683044, 0x00002A35, 0xFFFFEFA8, 0x00000441, 0x00001F3F, 0xFFFFF4F3, 0x000003A0, 0x00001F3F, 0xFFFFF4F3, 0x000003A0 }, + { 0x0213F0FFEF6630A4, 0x00003E33, 0xFFFFE4B0, 0x000005AF, 0x00002802, 0xFFFFF092, 0x00000412, 0x00002802, 0xFFFFF092, 0x00000412 }, + { 0x0213EA94DE323904, 0x00002815, 0xFFFFF20E, 0x000003DD, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, + { 0x0213F0FFEF5A2184, 0x00003CC2, 0xFFFFE43E, 0x000005DE, 0x00002C16, 0xFFFFECED, 0x000004BA, 0x00002C16, 0xFFFFECED, 0x000004BA }, + { 0x0213F0FFEF5C4084, 0x00003CFA, 0xFFFFE1EE, 0x00000673, 0x00001F7D, 0xFFFFF402, 0x000003AE, 0x00001F7D, 0xFFFFF402, 0x000003AE }, + { 0x0213F0FFEF622104, 0x0000486E, 0xFFFFDD43, 0x000006EE, 0x000036F0, 0xFFFFE609, 0x000005D5, 0x000036F0, 0xFFFFE609, 0x000005D5 }, + { 0x0213F0FFEF5C4964, 0x000039FE, 0xFFFFE41F, 0x00000613, 0x0000266C, 0xFFFFEF35, 0x0000047D, 0x0000266C, 0xFFFFEF35, 0x0000047D }, + { 0x0213EA94DE123124, 0x00002EA4, 0xFFFFEE3B, 0x00000462, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, + { 0x0213F0FFEF683944, 0x00002D2E, 0xFFFFEE7B, 0x00000462, 0x0000229D, 0xFFFFF363, 0x000003D4, 0x0000229D, 0xFFFFF363, 0x000003D4 }, + { 0x0213F0FFEF5E2844, 0x0000375C, 0xFFFFE695, 0x0000059D, 0x00002319, 0xFFFFF237, 0x000003EE, 0x00002319, 0xFFFFF237, 0x000003EE }, + { 0x0213F0FFEF7250C4, 0x00004522, 0xFFFFDC71, 0x0000075E, 0x0000247E, 0xFFFFF0A0, 0x0000043C, 0x0000247E, 0xFFFFF0A0, 0x0000043C }, + { 0x0213EA94DE1248E4, 0x00002E58, 0xFFFFECB9, 0x000004A9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, + { 0x0213F0FFEF6438E4, 0x00003791, 0xFFFFE5FE, 0x000005B6, 0x000029F5, 0xFFFFED0D, 0x000004CD, 0x000029F5, 0xFFFFED0D, 0x000004CD }, + { 0x0213EA94DE244144, 0x00002E9E, 0xFFFFEC8D, 0x000004C1, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, + { 0x0213EA94DE203964, 0x0000237C, 0xFFFFF435, 0x000003A6, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, + { 0x0213F0FFEF662924, 0x00003FE5, 0xFFFFE4A2, 0x000005A0, 0x00003416, 0xFFFFE995, 0x00000523, 0x00003416, 0xFFFFE995, 0x00000523 }, + { 0x0213F0FFEF5C0924, 0x00002B27, 0xFFFFED51, 0x000004A5, 0x000025D1, 0xFFFFEF18, 0x00000492, 0x000025D1, 0xFFFFEF18, 0x00000492 }, + { 0x0213F0FFEF684904, 0x00002D77, 0xFFFFED79, 0x00000494, 0x00002196, 0xFFFFF352, 0x000003DE, 0x00002196, 0xFFFFF352, 0x000003DE }, + { 0x0213F0FFEF5C20C4, 0x00003750, 0xFFFFE6AC, 0x00000596, 0x00002524, 0xFFFFF0B5, 0x00000431, 0x00002524, 0xFFFFF0B5, 0x00000431 }, + { 0x0213EA94DE122944, 0x00002896, 0xFFFFF1BB, 0x000003D9, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, + { 0x0213F0FFEF641984, 0x00003CA7, 0xFFFFE0F7, 0x000006B1, 0x00002CB8, 0xFFFFE9AB, 0x00000587, 0x00002CB8, 0xFFFFE9AB, 0x00000587 }, + { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, + { 0x0213F0FFEF662164, 0x00003914, 0xFFFFE683, 0x00000586, 0x00003120, 0xFFFFE9A6, 0x00000543, 0x00003120, 0xFFFFE9A6, 0x00000543 }, + { 0x0213F0FFEF643904, 0x000040D0, 0xFFFFE007, 0x000006AC, 0x00002B9E, 0xFFFFEBF5, 0x000004FB, 0x00002B9E, 0xFFFFEBF5, 0x000004FB }, + { 0x0213F0FFEF5A4884, 0x00004412, 0xFFFFDF5F, 0x000006A9, 0x00002A9E, 0xFFFFEDCE, 0x00000498, 0x00002A9E, 0xFFFFEDCE, 0x00000498 }, + { 0x0213F0FFEF624884, 0x000042A6, 0xFFFFDFEF, 0x00000696, 0x00002E65, 0xFFFFEAAE, 0x00000529, 0x00002E65, 0xFFFFEAAE, 0x00000529 }, + { 0x0213EA94DE322124, 0x000022E8, 0xFFFFF565, 0x0000035F, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, + { 0x0213F0FFEF6239A4, 0x00004637, 0xFFFFDDD8, 0x000006E9, 0x0000349D, 0xFFFFE6C8, 0x000005C7, 0x0000349D, 0xFFFFE6C8, 0x000005C7 }, + { 0x0213EA94DE263904, 0x00004686, 0xFFFFDC58, 0x0000073D, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, + { 0x0213F0FFEF6808E4, 0x00002B35, 0xFFFFEE9C, 0x0000046C, 0x00001F5B, 0xFFFFF4A3, 0x000003A9, 0x00001F5B, 0xFFFFF4A3, 0x000003A9 }, + { 0x0213F0FFEF724144, 0x00003AC9, 0xFFFFE3B2, 0x0000061B, 0x000023A1, 0xFFFFF170, 0x0000040F, 0x000023A1, 0xFFFFF170, 0x0000040F }, + { 0x0213F0FFEF5E1884, 0x00003C50, 0xFFFFE37E, 0x00000617, 0x0000218F, 0xFFFFF339, 0x000003C4, 0x0000218F, 0xFFFFF339, 0x000003C4 }, + { 0x0213F0FFEF663044, 0x00003793, 0xFFFFE761, 0x0000055D, 0x000029C7, 0xFFFFEE03, 0x00000496, 0x000029C7, 0xFFFFEE03, 0x00000496 }, + { 0x0213F0FFEF6438A4, 0x000040B5, 0xFFFFDF78, 0x000006DA, 0x00002DED, 0xFFFFEA20, 0x00000551, 0x00002DED, 0xFFFFEA20, 0x00000551 }, + { 0x0213F0FFEF601144, 0x000039D6, 0xFFFFE37D, 0x0000063C, 0x00001AED, 0xFFFFF6E2, 0x00000331, 0x00001AED, 0xFFFFF6E2, 0x00000331 }, + { 0x0213F0FFEF662144, 0x0000431F, 0xFFFFE09B, 0x0000066A, 0x00002BDF, 0xFFFFED93, 0x00000496, 0x00002BDF, 0xFFFFED93, 0x00000496 }, + { 0x0213F0FFEF623864, 0x00004887, 0xFFFFDC65, 0x00000721, 0x00003669, 0xFFFFE5C4, 0x000005E9, 0x00003669, 0xFFFFE5C4, 0x000005E9 }, + { 0x0213F0FFEF640924, 0x00004120, 0xFFFFDDAE, 0x00000748, 0x0000303B, 0xFFFFE70D, 0x000005FC, 0x0000303B, 0xFFFFE70D, 0x000005FC }, + { 0x0213F0FFEF5E28A4, 0x0000415D, 0xFFFFE0BE, 0x0000067B, 0x00002FA7, 0xFFFFEA28, 0x00000538, 0x00002FA7, 0xFFFFEA28, 0x00000538 }, + { 0x0213F0FFEF681904, 0x00002B12, 0xFFFFEFF9, 0x00000428, 0x00001DDA, 0xFFFFF693, 0x00000356, 0x00001DDA, 0xFFFFF693, 0x00000356 }, + { 0x0213F0FFEF5E3184, 0x00003ED3, 0xFFFFE28D, 0x0000062D, 0x00002B00, 0xFFFFED4E, 0x000004B3, 0x00002B00, 0xFFFFED4E, 0x000004B3 }, + { 0x0213F0FFEF6250A4, 0x00004218, 0xFFFFE039, 0x0000068F, 0x00002F84, 0xFFFFEA0C, 0x00000541, 0x00002F84, 0xFFFFEA0C, 0x00000541 }, + { 0x0213F0FFEF5A3844, 0x00003FF5, 0xFFFFE2A3, 0x00000617, 0x00003017, 0xFFFFEA7A, 0x00000520, 0x00003017, 0xFFFFEA7A, 0x00000520 }, + { 0x0213F0FFEF5A08A4, 0x00004304, 0xFFFFDFCC, 0x0000069E, 0x00002E0C, 0xFFFFEB51, 0x00000505, 0x00002E0C, 0xFFFFEB51, 0x00000505 }, + { 0x0213F0FFEF641944, 0x00003D3A, 0xFFFFE17F, 0x00000687, 0x0000284C, 0xFFFFED83, 0x000004CD, 0x0000284C, 0xFFFFED83, 0x000004CD }, + { 0x0213F0FFEF5E40A4, 0x000042F5, 0xFFFFDF76, 0x000006B2, 0x000027B6, 0xFFFFEF72, 0x00000455, 0x000027B6, 0xFFFFEF72, 0x00000455 }, + { 0x0213F0FFEF5C38C4, 0x00004267, 0xFFFFDF29, 0x000006D5, 0x0000298F, 0xFFFFEDBD, 0x000004AC, 0x0000298F, 0xFFFFEDBD, 0x000004AC }, + { 0x0213EA94DE240924, 0x0000303E, 0xFFFFEC00, 0x000004CB, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, + { 0x0213F0FFEF5E28C4, 0x00003127, 0xFFFFEBDB, 0x000004A6, 0x00002E95, 0xFFFFEB78, 0x000004F3, 0x00002E95, 0xFFFFEB78, 0x000004F3 }, + { 0x0213EA94DE1C1064, 0x00002655, 0xFFFFF2D9, 0x000003CF, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, + { 0x0213EA94DE164084, 0x00002372, 0xFFFFF449, 0x0000039B, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, + { 0x0213F0FFEF6628C4, 0x0000348E, 0xFFFFEB20, 0x000004B2, 0x00002BE8, 0xFFFFEE80, 0x00000467, 0x00002BE8, 0xFFFFEE80, 0x00000467 }, + { 0x0213F0FFEF5E1104, 0x00004092, 0xFFFFE073, 0x0000069B, 0x00002061, 0xFFFFF403, 0x000003A0, 0x00002061, 0xFFFFF403, 0x000003A0 }, + { 0x0213F0FFEF7220E4, 0x000039D1, 0xFFFFE55D, 0x000005CC, 0x000025CB, 0xFFFFF0C0, 0x00000428, 0x000025CB, 0xFFFFF0C0, 0x00000428 }, + { 0x0213F0FFEF5E4884, 0x000042AA, 0xFFFFDF68, 0x000006C2, 0x0000290B, 0xFFFFEE78, 0x00000485, 0x0000290B, 0xFFFFEE78, 0x00000485 }, + { 0x0213F0FFEF7218C4, 0x0000356F, 0xFFFFE7AC, 0x0000056E, 0x00001BE8, 0xFFFFF6E3, 0x0000032A, 0x00001BE8, 0xFFFFF6E3, 0x0000032A }, + { 0x0213F0FFEF5E1144, 0x00003525, 0xFFFFE7FF, 0x0000055D, 0x0000242C, 0xFFFFF12E, 0x0000041D, 0x0000242C, 0xFFFFF12E, 0x0000041D }, + { 0x0213F0FFEF5C48C4, 0x00003360, 0xFFFFE895, 0x00000550, 0x00002175, 0xFFFFF29E, 0x000003E9, 0x00002175, 0xFFFFF29E, 0x000003E9 }, + { 0x0213F0FFEF6440A4, 0x00003C94, 0xFFFFE1C4, 0x0000067E, 0x00002E28, 0xFFFFE964, 0x0000057F, 0x00002E28, 0xFFFFE964, 0x0000057F }, + { 0x0213F0FFEF724124, 0x0000431C, 0xFFFFDE4B, 0x000006FF, 0x00002270, 0xFFFFF268, 0x000003E5, 0x00002270, 0xFFFFF268, 0x000003E5 }, + { 0x0213EA94DE1218C4, 0x00002B67, 0xFFFFF01D, 0x00000414, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, + { 0x0213F0FFEF5E3984, 0x0000400B, 0xFFFFE13D, 0x0000066F, 0x000024F3, 0xFFFFF125, 0x00000417, 0x000024F3, 0xFFFFF125, 0x00000417 }, + { 0x0213F0FFEF5A20A4, 0x00004460, 0xFFFFE00E, 0x0000067B, 0x000023DF, 0xFFFFF2E6, 0x000003BB, 0x000023DF, 0xFFFFF2E6, 0x000003BB }, + { 0x0213F0FFEF641864, 0x00003AFB, 0xFFFFE2C5, 0x00000650, 0x00002D46, 0xFFFFE9C4, 0x00000571, 0x00002D46, 0xFFFFE9C4, 0x00000571 }, + { 0x0213F0FFEF622924, 0x00005482, 0xFFFFD5BC, 0x0000081A, 0x00003250, 0xFFFFE961, 0x00000541, 0x00003250, 0xFFFFE961, 0x00000541 }, + { 0x0213F0FFEF5C2944, 0x00003D27, 0xFFFFE2FA, 0x00000632, 0x00002A4D, 0xFFFFED6A, 0x000004BB, 0x00002A4D, 0xFFFFED6A, 0x000004BB }, + { 0x0213F0FFEF6018A4, 0x00003E03, 0xFFFFE142, 0x00000690, 0x00001E08, 0xFFFFF555, 0x0000036C, 0x00001E08, 0xFFFFF555, 0x0000036C }, + { 0x0213F0FFEF5C2064, 0x000031B5, 0xFFFFE97D, 0x00000535, 0x0000232E, 0xFFFFF166, 0x00000422, 0x0000232E, 0xFFFFF166, 0x00000422 }, + { 0x0213F0FFEF5E18E4, 0x00003753, 0xFFFFE724, 0x00000575, 0x0000281A, 0xFFFFEF1A, 0x0000046B, 0x0000281A, 0xFFFFEF1A, 0x0000046B }, + { 0x0213EA94DE204144, 0x00002071, 0xFFFFF5C9, 0x0000036F, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, + { 0x0213F0FFEF683144, 0x00002799, 0xFFFFF223, 0x000003CF, 0x00001CD3, 0xFFFFF74A, 0x00000333, 0x00001CD3, 0xFFFFF74A, 0x00000333 }, + { 0x0213F0FFEF6610C4, 0x000040DF, 0xFFFFE11C, 0x00000664, 0x000031D4, 0xFFFFE8BC, 0x0000056F, 0x000031D4, 0xFFFFE8BC, 0x0000056F }, + { 0x0213F0FFEF6440C4, 0x00003A4D, 0xFFFFE3A6, 0x00000627, 0x00002871, 0xFFFFEDA0, 0x000004C0, 0x00002871, 0xFFFFEDA0, 0x000004C0 }, + { 0x0213F0FFEF681984, 0x00002AF9, 0xFFFFEED7, 0x00000464, 0x0000219B, 0xFFFFF368, 0x000003D6, 0x0000219B, 0xFFFFF368, 0x000003D6 }, + { 0x0213EA94DE323124, 0x000026D5, 0xFFFFF36C, 0x000003A3, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, + { 0x0213F0FFEF5E2044, 0x0000325D, 0xFFFFEA07, 0x0000050B, 0x000026D1, 0xFFFFEFB3, 0x0000045A, 0x000026D1, 0xFFFFEFB3, 0x0000045A }, + { 0x0213F0FFEF682864, 0x00002F75, 0xFFFFEC64, 0x000004BE, 0x00001EEB, 0xFFFFF559, 0x00000386, 0x00001EEB, 0xFFFFF559, 0x00000386 }, + { 0x0213F0FFEF5A38A4, 0x00003C2F, 0xFFFFE541, 0x000005A3, 0x000025B6, 0xFFFFF16F, 0x000003FA, 0x000025B6, 0xFFFFF16F, 0x000003FA }, + { 0x0213F0FFEF684924, 0x00002BC2, 0xFFFFEE89, 0x0000046A, 0x00001D04, 0xFFFFF651, 0x00000361, 0x00001D04, 0xFFFFF651, 0x00000361 }, + { 0x0213F0FFEF6829A4, 0x00002DD0, 0xFFFFED40, 0x0000049F, 0x00001C8C, 0xFFFFF6B3, 0x00000353, 0x00001C8C, 0xFFFFF6B3, 0x00000353 }, + { 0x0213EA94DE1C08E4, 0x000021ED, 0xFFFFF530, 0x00000380, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, + { 0x0213EA94DE321904, 0x000028C7, 0xFFFFF160, 0x000003FD, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, + { 0x0213F0FFEF6610A4, 0x0000431C, 0xFFFFDF9D, 0x000006A3, 0x000034A6, 0xFFFFE6B0, 0x000005C9, 0x000034A6, 0xFFFFE6B0, 0x000005C9 }, + { 0x0213EA94DE2630A4, 0x00004115, 0xFFFFE0D6, 0x00000667, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, + { 0x0213F0FFEF643924, 0x0000424A, 0xFFFFDEEC, 0x000006E1, 0x0000346A, 0xFFFFE5EA, 0x00000602, 0x0000346A, 0xFFFFE5EA, 0x00000602 }, + { 0x0213F0FFEF661984, 0x00004990, 0xFFFFDAFA, 0x00000771, 0x00002A9C, 0xFFFFED37, 0x000004BC, 0x00002A9C, 0xFFFFED37, 0x000004BC }, + { 0x0213F0FFEF6428A4, 0x00003858, 0xFFFFE568, 0x000005D2, 0x00003030, 0xFFFFE8B0, 0x0000058E, 0x00003030, 0xFFFFE8B0, 0x0000058E }, + { 0x0213F0FFEF684164, 0x00001EDC, 0xFFFFF6CD, 0x00000322, 0x00001FCA, 0xFFFFF4BD, 0x0000039E, 0x00001FCA, 0xFFFFF4BD, 0x0000039E }, + { 0x0213F0FFEF662124, 0x00004C88, 0xFFFFDBA3, 0x0000071B, 0x000030C4, 0xFFFFEAFD, 0x000004F7, 0x000030C4, 0xFFFFEAFD, 0x000004F7 }, + { 0x0213F0FFEF680904, 0x00002B9A, 0xFFFFEE41, 0x0000047D, 0x00002131, 0xFFFFF344, 0x000003E5, 0x00002131, 0xFFFFF344, 0x000003E5 }, + { 0x0213F0FFEF623984, 0x00003E4B, 0xFFFFE33C, 0x000005FA, 0x00003877, 0xFFFFE437, 0x0000062E, 0x00003877, 0xFFFFE437, 0x0000062E }, + { 0x0213EA94DE322064, 0x00002376, 0xFFFFF444, 0x0000038A, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, + { 0x0213F0FFEF661084, 0x00004517, 0xFFFFDDF4, 0x000006F2, 0x000030DC, 0xFFFFE8EF, 0x00000571, 0x000030DC, 0xFFFFE8EF, 0x00000571 }, + { 0x0213F0FFEF681944, 0x0000270C, 0xFFFFF1F3, 0x000003DF, 0x0000207B, 0xFFFFF474, 0x000003AD, 0x0000207B, 0xFFFFF474, 0x000003AD }, + { 0x0213F0FFEF645144, 0x00004086, 0xFFFFDF39, 0x000006E3, 0x00002A24, 0xFFFFEC2B, 0x000004FF, 0x00002A24, 0xFFFFEC2B, 0x000004FF }, + { 0x0213F0FFEF5C3124, 0x00003BDE, 0xFFFFE45E, 0x000005EB, 0x00002CD5, 0xFFFFEC45, 0x000004DD, 0x00002CD5, 0xFFFFEC45, 0x000004DD }, + { 0x0213F0FFEF7230E4, 0x00003803, 0xFFFFE714, 0x00000579, 0x0000288A, 0xFFFFEF21, 0x0000046B, 0x0000288A, 0xFFFFEF21, 0x0000046B }, + { 0x0213F0FFEF601104, 0x00003F50, 0xFFFFE002, 0x000006CD, 0x00001AD4, 0xFFFFF72E, 0x0000031F, 0x00001AD4, 0xFFFFF72E, 0x0000031F }, + { 0x0213F0FFEF6820E4, 0x00002968, 0xFFFFF100, 0x00000402, 0x00001FB5, 0xFFFFF57C, 0x0000037F, 0x00001FB5, 0xFFFFF57C, 0x0000037F }, + { 0x0213F0FFEF662104, 0x00004283, 0xFFFFE2A7, 0x000005F5, 0x00003165, 0xFFFFEB0C, 0x000004EC, 0x00003165, 0xFFFFEB0C, 0x000004EC }, + { 0x0213F0FFEF6431A4, 0x00004253, 0xFFFFDDA8, 0x00000732, 0x00002E5C, 0xFFFFE90A, 0x00000593, 0x00002E5C, 0xFFFFE90A, 0x00000593 }, + { 0x0213F0FFEF5C50A4, 0x00003551, 0xFFFFE756, 0x0000058D, 0x000029A7, 0xFFFFED0C, 0x000004DE, 0x000029A7, 0xFFFFED0C, 0x000004DE }, + { 0x0213F0FFEF6428C4, 0x00003728, 0xFFFFE604, 0x000005C4, 0x00002832, 0xFFFFEE64, 0x00000493, 0x00002832, 0xFFFFEE64, 0x00000493 }, + { 0x0213F0FFEF623964, 0x00004796, 0xFFFFDCC8, 0x00000715, 0x000032AB, 0xFFFFE848, 0x0000057C, 0x000032AB, 0xFFFFE848, 0x0000057C }, + { 0x0213F0FFEF6210C4, 0x000049DF, 0xFFFFDB24, 0x0000075F, 0x00003076, 0xFFFFE967, 0x0000055C, 0x00003076, 0xFFFFE967, 0x0000055C }, + { 0x0213F0FFEF721104, 0x00003F13, 0xFFFFE099, 0x000006A8, 0x00002279, 0xFFFFF226, 0x000003F3, 0x00002279, 0xFFFFF226, 0x000003F3 }, + { 0x0213F0FFEF6430A4, 0x00003E03, 0xFFFFE19F, 0x00000674, 0x00002D66, 0xFFFFEAA7, 0x00000537, 0x00002D66, 0xFFFFEAA7, 0x00000537 }, + { 0x0213F0FFEF5C4104, 0x000037DA, 0xFFFFE63F, 0x000005A7, 0x00002543, 0xFFFFF0A0, 0x00000431, 0x00002543, 0xFFFFF0A0, 0x00000431 }, + { 0x0213F0FFEF624944, 0x00003D82, 0xFFFFE3F5, 0x000005D9, 0x0000332F, 0xFFFFE834, 0x00000577, 0x0000332F, 0xFFFFE834, 0x00000577 }, + { 0x0213EA94DE1228C4, 0x00002915, 0xFFFFF1E0, 0x000003D4, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, + { 0x0213F0FFEF5E4904, 0x000036FC, 0xFFFFE72D, 0x00000577, 0x00002811, 0xFFFFEF30, 0x00000464, 0x00002811, 0xFFFFEF30, 0x00000464 }, + { 0x0213F0FFEF623184, 0x00004767, 0xFFFFDD30, 0x000006FD, 0x00003703, 0xFFFFE564, 0x000005F8, 0x00003703, 0xFFFFE564, 0x000005F8 }, + { 0x0213F0FFEF603184, 0x00003094, 0xFFFFEAA9, 0x000004F5, 0x000022E7, 0xFFFFF200, 0x000003FB, 0x000022E7, 0xFFFFF200, 0x000003FB }, + { 0x0213F0FFEF641144, 0x00003EF0, 0xFFFFDF83, 0x000006ED, 0x00002A27, 0xFFFFEB7C, 0x00000537, 0x00002A27, 0xFFFFEB7C, 0x00000537 }, + { 0x0213F0FFEF681124, 0x0000243C, 0xFFFFF358, 0x000003AC, 0x00001DC4, 0xFFFFF5E9, 0x00000372, 0x00001DC4, 0xFFFFF5E9, 0x00000372 }, + { 0x0213F0FFEF722144, 0x0000284B, 0xFFFFF036, 0x0000040F, 0x00001FCD, 0xFFFFF445, 0x00000395, 0x00001FCD, 0xFFFFF445, 0x00000395 }, + { 0x0213F0FFEF6840C4, 0x00002611, 0xFFFFF285, 0x000003C7, 0x00001CFE, 0xFFFFF6A0, 0x00000355, 0x00001CFE, 0xFFFFF6A0, 0x00000355 }, + { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, + { 0x0213F0FFEF5E38A4, 0x000037F3, 0xFFFFE68D, 0x00000590, 0x00002443, 0xFFFFF1AD, 0x000003FA, 0x00002443, 0xFFFFF1AD, 0x000003FA }, + { 0x0213F0FFEF682144, 0x00002C01, 0xFFFFEF3F, 0x00000444, 0x0000210A, 0xFFFFF475, 0x000003A7, 0x0000210A, 0xFFFFF475, 0x000003A7 }, + { 0x0213EA94DE1210E4, 0x00002C0E, 0xFFFFEF0F, 0x00000446, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, + { 0x0213F0FFEF5E20C4, 0x00003FA6, 0xFFFFE20A, 0x0000063F, 0x00002E29, 0xFFFFEB21, 0x00000510, 0x00002E29, 0xFFFFEB21, 0x00000510 }, + { 0x0213F0FFEF5C2164, 0x00003BCD, 0xFFFFE31B, 0x0000063C, 0x000019AF, 0xFFFFF83D, 0x000002F8, 0x000019AF, 0xFFFFF83D, 0x000002F8 }, + { 0x0213F0FFEF664164, 0x000044C8, 0xFFFFDF08, 0x000006B0, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, + { 0x0213F0FFEF5C1884, 0x00003790, 0xFFFFE571, 0x000005E3, 0x00002042, 0xFFFFF35D, 0x000003CF, 0x00002042, 0xFFFFF35D, 0x000003CF }, + { 0x0213F0FFEF6050E4, 0x000038AC, 0xFFFFE46C, 0x00000609, 0x0000215E, 0xFFFFF22D, 0x00000403, 0x0000215E, 0xFFFFF22D, 0x00000403 }, + { 0x0213F0FFEF5E29A4, 0x00003A1E, 0xFFFFE536, 0x000005C9, 0x000024F3, 0xFFFFF11A, 0x0000041B, 0x000024F3, 0xFFFFF11A, 0x0000041B }, + { 0x0213F0FFEF6650E4, 0x0000431A, 0xFFFFDF1B, 0x000006C5, 0x00002F34, 0xFFFFEA02, 0x00000545, 0x00002F34, 0xFFFFEA02, 0x00000545 }, + { 0x0213F0FFEF641904, 0x000042DC, 0xFFFFDE28, 0x0000070C, 0x00003B53, 0xFFFFE0EA, 0x000006E2, 0x00003B53, 0xFFFFE0EA, 0x000006E2 }, + { 0x0213F0FFEF683164, 0x0000264B, 0xFFFFF29A, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4 }, + { 0x0213F0FFEF5A4064, 0x00004225, 0xFFFFE0E8, 0x00000665, 0x00002B53, 0xFFFFED89, 0x0000049F, 0x00002B53, 0xFFFFED89, 0x0000049F }, + { 0x0213EA94DE204924, 0x00001FCC, 0xFFFFF63F, 0x00000358, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, + { 0x0213F0FFEF6240A4, 0x000045E0, 0xFFFFDDD0, 0x000006ED, 0x00003193, 0xFFFFE8BD, 0x00000572, 0x00003193, 0xFFFFE8BD, 0x00000572 }, + { 0x0213F0FFEF683924, 0x000024FC, 0xFFFFF366, 0x000003A6, 0x00001FE8, 0xFFFFF509, 0x00000394, 0x00001FE8, 0xFFFFF509, 0x00000394 }, + { 0x0213F0FFEF5C4884, 0x0000378F, 0xFFFFE54B, 0x000005F1, 0x00001C9B, 0xFFFFF5C7, 0x00000368, 0x00001C9B, 0xFFFFF5C7, 0x00000368 }, + { 0x0213F0FFEF6418A4, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002CDD, 0xFFFFEA44, 0x00000557, 0x00002CDD, 0xFFFFEA44, 0x00000557 }, + { 0x0213EA94DE200904, 0x000021EC, 0xFFFFF4F4, 0x0000038F, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, + { 0x0213F0FFEF6010A4, 0x00003C8A, 0xFFFFE1C1, 0x00000685, 0x000019C7, 0xFFFFF7E2, 0x00000301, 0x000019C7, 0xFFFFF7E2, 0x00000301 }, + { 0x0213F0FFEF5E2064, 0x00003908, 0xFFFFE5C7, 0x000005B3, 0x00002793, 0xFFFFEF46, 0x00000465, 0x00002793, 0xFFFFEF46, 0x00000465 }, + { 0x0213F0FFEF605104, 0x000040A3, 0xFFFFDE61, 0x00000725, 0x00002077, 0xFFFFF2CE, 0x000003E8, 0x00002077, 0xFFFFF2CE, 0x000003E8 }, + { 0x0213F0FFEF664144, 0x00003DCA, 0xFFFFE34D, 0x00000608, 0x00002D66, 0xFFFFEBDF, 0x000004E8, 0x00002D66, 0xFFFFEBDF, 0x000004E8 }, + { 0x0213F0FFEF5E50C4, 0x00003085, 0xFFFFEB70, 0x000004C8, 0x000029B1, 0xFFFFEDD9, 0x000004A5, 0x000029B1, 0xFFFFEDD9, 0x000004A5 }, + { 0x0213EA94DE083884, 0x00004C73, 0xFFFFD676, 0x0000086C, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, + { 0x0213EA94DE242164, 0x00002CE5, 0xFFFFEE8C, 0x00000466, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, + { 0x0213F0FFEF621124, 0x0000489F, 0xFFFFDBF1, 0x0000073E, 0x0000332D, 0xFFFFE786, 0x000005AD, 0x0000332D, 0xFFFFE786, 0x000005AD }, + { 0x0213F0FFEF602864, 0x00003D09, 0xFFFFE193, 0x00000689, 0x00001E82, 0xFFFFF4C0, 0x00000386, 0x00001E82, 0xFFFFF4C0, 0x00000386 }, + { 0x0213F0FFEF644104, 0x00003E4C, 0xFFFFE131, 0x00000689, 0x00002F4E, 0xFFFFE925, 0x0000057B, 0x00002F4E, 0xFFFFE925, 0x0000057B }, + { 0x0213F0FFEF5A4084, 0x00003B31, 0xFFFFE53F, 0x000005B3, 0x0000248A, 0xFFFFF211, 0x000003DF, 0x0000248A, 0xFFFFF211, 0x000003DF }, + { 0x0213F0FFEF644124, 0x000038DD, 0xFFFFE54A, 0x000005C9, 0x00002B6D, 0xFFFFEBDF, 0x00000502, 0x00002B6D, 0xFFFFEBDF, 0x00000502 }, + { 0x0213F0FFEF684064, 0x00002698, 0xFFFFF1A8, 0x000003F2, 0x00002163, 0xFFFFF34B, 0x000003E3, 0x00002163, 0xFFFFF34B, 0x000003E3 }, + { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, + { 0x0213F0FFEF6418C4, 0x00003EAF, 0xFFFFE0C3, 0x000006A0, 0x000030AB, 0xFFFFE829, 0x000005A6, 0x000030AB, 0xFFFFE829, 0x000005A6 }, + { 0x0213F0FFEF684944, 0x00002E89, 0xFFFFECA6, 0x000004B6, 0x00001FA0, 0xFFFFF4A8, 0x000003A3, 0x00001FA0, 0xFFFFF4A8, 0x000003A3 }, + { 0x0213F0FFEF6828A4, 0x000028A4, 0xFFFFF112, 0x00000402, 0x00001F7C, 0xFFFFF545, 0x0000038A, 0x00001F7C, 0xFFFFF545, 0x0000038A }, + { 0x0213F0FFEF6650A4, 0x00004135, 0xFFFFDFA2, 0x000006C5, 0x0000324C, 0xFFFFE7AA, 0x000005AF, 0x0000324C, 0xFFFFE7AA, 0x000005AF }, + { 0x0213EA94DE2038C4, 0x00002012, 0xFFFFF693, 0x00000352, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, + { 0x0213F0FFEF643084, 0x00003D7C, 0xFFFFE1BC, 0x00000671, 0x00002A45, 0xFFFFEC84, 0x000004EC, 0x00002A45, 0xFFFFEC84, 0x000004EC }, + { 0x0213F0FFEF723064, 0x00004172, 0xFFFFDF58, 0x000006DA, 0x00002504, 0xFFFFF0A6, 0x00000431, 0x00002504, 0xFFFFF0A6, 0x00000431 }, + { 0x0213F0FE99281944, 0x000029C7, 0xFFFFF087, 0x00000414, 0x00001DCB, 0xFFFFF675, 0x0000035F, 0x00001DCB, 0xFFFFF675, 0x0000035F }, + { 0x0213F0FE992A29A4, 0x000027F0, 0xFFFFF05A, 0x00000432, 0x00001707, 0xFFFFFA0E, 0x000002D1, 0x00001707, 0xFFFFFA0E, 0x000002D1 }, + { 0x0213F0FE99222144, 0x00003279, 0xFFFFE9F7, 0x00000511, 0x00001B5E, 0xFFFFF787, 0x00000317, 0x00001B5E, 0xFFFFF787, 0x00000317 }, + { 0x0213F0FE99322184, 0x000030A5, 0xFFFFEABC, 0x000004FF, 0x000019D1, 0xFFFFF83C, 0x00000304, 0x000019D1, 0xFFFFF83C, 0x00000304 }, + { 0x0213F0FE99282844, 0x0000283B, 0xFFFFF122, 0x00000402, 0x000019C2, 0xFFFFF8E9, 0x000002FB, 0x000019C2, 0xFFFFF8E9, 0x000002FB }, + { 0x0213F0FE992C2084, 0x00003376, 0xFFFFE9E1, 0x00000510, 0x000021A7, 0xFFFFF39F, 0x000003BF, 0x000021A7, 0xFFFFF39F, 0x000003BF }, + { 0x0213F0FE993218C4, 0x000031D2, 0xFFFFEA9C, 0x000004FC, 0x00001F66, 0xFFFFF4E4, 0x00000390, 0x00001F66, 0xFFFFF4E4, 0x00000390 }, + { 0x0213F0FE991A3864, 0x00003006, 0xFFFFEB18, 0x000004F2, 0x000019B3, 0xFFFFF84E, 0x00000301, 0x000019B3, 0xFFFFF84E, 0x00000301 }, + { 0x0213F0FE993039A4, 0x0000364F, 0xFFFFE81F, 0x00000556, 0x00002AC9, 0xFFFFED87, 0x000004BD, 0x00002AC9, 0xFFFFED87, 0x000004BD }, + { 0x0213F0FE992E3844, 0x00003043, 0xFFFFEBAE, 0x000004CD, 0x00001B0C, 0xFFFFF7ED, 0x0000030C, 0x00001B0C, 0xFFFFF7ED, 0x0000030C }, + { 0x0213F0FE993048A4, 0x000037CE, 0xFFFFE69E, 0x00000596, 0x0000276B, 0xFFFFEF65, 0x0000046E, 0x0000276B, 0xFFFFEF65, 0x0000046E }, + { 0x0213F0FE992C3104, 0x00003063, 0xFFFFED5E, 0x0000046F, 0x000024AE, 0xFFFFF2C4, 0x000003D8, 0x000024AE, 0xFFFFF2C4, 0x000003D8 }, + { 0x0213F0FE992E08A4, 0x00002F5D, 0xFFFFEBDC, 0x000004D3, 0x00001EDB, 0xFFFFF50F, 0x0000038E, 0x00001EDB, 0xFFFFF50F, 0x0000038E }, + { 0x0213F0FE992E48A4, 0x00003148, 0xFFFFEA9A, 0x000004FB, 0x0000192D, 0xFFFFF8E9, 0x000002DF, 0x0000192D, 0xFFFFF8E9, 0x000002DF }, + { 0x0213F0FE992C2064, 0x00003682, 0xFFFFE7E4, 0x0000055C, 0x0000250E, 0xFFFFF150, 0x0000041A, 0x0000250E, 0xFFFFF150, 0x0000041A }, + { 0x0213F0FE992A2084, 0x0000284E, 0xFFFFF15A, 0x000003F8, 0x00001CE2, 0xFFFFF6F9, 0x0000034F, 0x00001CE2, 0xFFFFF6F9, 0x0000034F }, + { 0x0213F0FE993018A4, 0x00003171, 0xFFFFEAE9, 0x000004ED, 0x00001F40, 0xFFFFF513, 0x00000384, 0x00001F40, 0xFFFFF513, 0x00000384 }, + { 0x0213F0FE99323044, 0x000031BD, 0xFFFFEA64, 0x0000050A, 0x00001EFD, 0xFFFFF4F7, 0x00000390, 0x00001EFD, 0xFFFFF4F7, 0x00000390 }, + { 0x0213F0FE992E50E4, 0x00003050, 0xFFFFEB29, 0x000004EA, 0x000019B3, 0xFFFFF878, 0x000002F9, 0x000019B3, 0xFFFFF878, 0x000002F9 }, + { 0x0213F0FE992C1904, 0x00003400, 0xFFFFE9A0, 0x0000051A, 0x00002460, 0xFFFFF1DA, 0x00000409, 0x00002460, 0xFFFFF1DA, 0x00000409 }, + { 0x0213F0FE992C4884, 0x000034A1, 0xFFFFE86F, 0x00000558, 0x0000255D, 0xFFFFF09E, 0x00000443, 0x0000255D, 0xFFFFF09E, 0x00000443 }, + { 0x0213F0FE992E48E4, 0x00003103, 0xFFFFEAD7, 0x000004F0, 0x00001896, 0xFFFFF95A, 0x000002CC, 0x00001896, 0xFFFFF95A, 0x000002CC }, + { 0x0213F0FE993018E4, 0x00003120, 0xFFFFEB9E, 0x000004CB, 0x000021E8, 0xFFFFF3A2, 0x000003C1, 0x000021E8, 0xFFFFF3A2, 0x000003C1 }, + { 0x0213F0FE991C50E4, 0x00003558, 0xFFFFE812, 0x00000565, 0x0000256E, 0xFFFFF097, 0x00000447, 0x0000256E, 0xFFFFF097, 0x00000447 }, + { 0x0213F0FE991A2844, 0x00002DA8, 0xFFFFECA8, 0x000004B7, 0x0000180B, 0xFFFFF96D, 0x000002D8, 0x0000180B, 0xFFFFF96D, 0x000002D8 }, + { 0x0213F0FE992E3064, 0x00003232, 0xFFFFEA66, 0x000004FF, 0x00001DDE, 0xFFFFF5FE, 0x0000035A, 0x00001DDE, 0xFFFFF5FE, 0x0000035A }, + { 0x0213F0FE993050E4, 0x000034D2, 0xFFFFE89F, 0x00000548, 0x0000246C, 0xFFFFF17F, 0x00000418, 0x0000246C, 0xFFFFF17F, 0x00000418 }, + { 0x0213F0FE99304904, 0x000033EC, 0xFFFFE954, 0x0000052A, 0x00002323, 0xFFFFF279, 0x000003EE, 0x00002323, 0xFFFFF279, 0x000003EE }, + { 0x0213F0FE99303884, 0x000033AA, 0xFFFFE955, 0x0000052D, 0x0000229F, 0xFFFFF2B2, 0x000003E7, 0x0000229F, 0xFFFFF2B2, 0x000003E7 }, + { 0x0213F0FE99324964, 0x00003258, 0xFFFFE9AA, 0x0000052A, 0x00001D5F, 0xFFFFF5D1, 0x0000036B, 0x00001D5F, 0xFFFFF5D1, 0x0000036B }, + { 0x0213F0FE993029A4, 0x0000323A, 0xFFFFEA5F, 0x00000504, 0x00002108, 0xFFFFF3D5, 0x000003BA, 0x00002108, 0xFFFFF3D5, 0x000003BA }, + { 0x0213F0FE992C2184, 0x00003216, 0xFFFFEA6B, 0x000004FF, 0x00001D6E, 0xFFFFF640, 0x00000350, 0x00001D6E, 0xFFFFF640, 0x00000350 }, + { 0x0213F0FE993210E4, 0x000030C5, 0xFFFFEAC4, 0x000004FC, 0x00001924, 0xFFFFF8C2, 0x000002EE, 0x00001924, 0xFFFFF8C2, 0x000002EE }, + { 0x0213F0FE99305104, 0x000032BB, 0xFFFFE9F1, 0x00000515, 0x00002211, 0xFFFFF31B, 0x000003D5, 0x00002211, 0xFFFFF31B, 0x000003D5 }, + { 0x0213F0FE993048C4, 0x0000352C, 0xFFFFE85B, 0x00000553, 0x00002410, 0xFFFFF1B4, 0x0000040F, 0x00002410, 0xFFFFF1B4, 0x0000040F }, + { 0x0213F0FE992238C4, 0x000036A0, 0xFFFFE7E8, 0x0000055D, 0x00002901, 0xFFFFEEB8, 0x00000489, 0x00002901, 0xFFFFEEB8, 0x00000489 }, + { 0x0213F0FE992C3044, 0x00003340, 0xFFFFE9D9, 0x00000516, 0x00002332, 0xFFFFF27A, 0x000003F0, 0x00002332, 0xFFFFF27A, 0x000003F0 }, + { 0x0213F0FE991A38A4, 0x00003564, 0xFFFFE86D, 0x0000054E, 0x00002613, 0xFFFFF07C, 0x00000444, 0x00002613, 0xFFFFF07C, 0x00000444 }, + { 0x0213F0FE99280904, 0x00002AD1, 0xFFFFEF0B, 0x0000045C, 0x00001DEA, 0xFFFFF5C8, 0x00000381, 0x00001DEA, 0xFFFFF5C8, 0x00000381 }, + { 0x0213F0FE992220E4, 0x000035B0, 0xFFFFE846, 0x00000555, 0x000027BE, 0xFFFFEF5D, 0x00000474, 0x000027BE, 0xFFFFEF5D, 0x00000474 }, + { 0x0213F0FE992238A4, 0x000032C4, 0xFFFFEA48, 0x00000502, 0x000022C6, 0xFFFFF2DF, 0x000003DE, 0x000022C6, 0xFFFFF2DF, 0x000003DE }, + { 0x0213F0FE993008C4, 0x00003036, 0xFFFFEB0D, 0x000004F9, 0x00001FE8, 0xFFFFF41A, 0x000003BC, 0x00001FE8, 0xFFFFF41A, 0x000003BC }, + { 0x0213F0FE991A0904, 0x000030F8, 0xFFFFEA13, 0x00000524, 0x00001B6A, 0xFFFFF6C9, 0x0000034A, 0x00001B6A, 0xFFFFF6C9, 0x0000034A }, + { 0x0213F0FE993010A4, 0x00002EE2, 0xFFFFEC0C, 0x000004CB, 0x00001A39, 0xFFFFF814, 0x0000030F, 0x00001A39, 0xFFFFF814, 0x0000030F }, + { 0x0213F0FE991C3184, 0x00003457, 0xFFFFE924, 0x0000052A, 0x00001E9D, 0xFFFFF59C, 0x00000363, 0x00001E9D, 0xFFFFF59C, 0x00000363 }, + { 0x0213F0FE99322844, 0x000030BF, 0xFFFFEB18, 0x000004ED, 0x00001D37, 0xFFFFF636, 0x0000035C, 0x00001D37, 0xFFFFF636, 0x0000035C }, + { 0x0213F0FE992E4084, 0x000031AF, 0xFFFFEA75, 0x000004FE, 0x000019F2, 0xFFFFF87A, 0x000002F0, 0x000019F2, 0xFFFFF87A, 0x000002F0 }, + { 0x0213F0FE99302884, 0x00003642, 0xFFFFE85B, 0x00000547, 0x00002975, 0xFFFFEE98, 0x0000048B, 0x00002975, 0xFFFFEE98, 0x0000048B }, + { 0x0213F0FE992E2884, 0x00002E8B, 0xFFFFED1E, 0x0000048E, 0x000019C1, 0xFFFFF917, 0x000002D6, 0x000019C1, 0xFFFFF917, 0x000002D6 }, + { 0x0213F0FE993241A4, 0x000033D9, 0xFFFFE8E1, 0x00000548, 0x0000224B, 0xFFFFF298, 0x000003F4, 0x0000224B, 0xFFFFF298, 0x000003F4 }, + { 0x0213F0FE992E28C4, 0x000032BC, 0xFFFFEB0F, 0x000004D6, 0x00002488, 0xFFFFF240, 0x000003F2, 0x00002488, 0xFFFFF240, 0x000003F2 }, + { 0x0213F0FE99304944, 0x000035FD, 0xFFFFE838, 0x00000553, 0x00002762, 0xFFFFEFBC, 0x00000460, 0x00002762, 0xFFFFEFBC, 0x00000460 }, + { 0x0213F0FE992818A4, 0x0000268B, 0xFFFFF263, 0x000003D1, 0x00001914, 0xFFFFF977, 0x000002E8, 0x00001914, 0xFFFFF977, 0x000002E8 }, + { 0x0213F0FE992C3184, 0x0000330B, 0xFFFFEA1E, 0x00000505, 0x000020B1, 0xFFFFF44D, 0x0000039E, 0x000020B1, 0xFFFFF44D, 0x0000039E }, + { 0x0213F0FE99222084, 0x0000326E, 0xFFFFEA26, 0x00000508, 0x00001C17, 0xFFFFF722, 0x00000328, 0x00001C17, 0xFFFFF722, 0x00000328 }, + { 0x0213F0FE992A31A4, 0x00002A3F, 0xFFFFEEE8, 0x0000046D, 0x00001B2B, 0xFFFFF737, 0x0000034D, 0x00001B2B, 0xFFFFF737, 0x0000034D }, + { 0x0213F0FE992C4064, 0x00003732, 0xFFFFE765, 0x00000574, 0x00002A6D, 0xFFFFEDA8, 0x000004B7, 0x00002A6D, 0xFFFFEDA8, 0x000004B7 }, + { 0x0213F0FE99300924, 0x000034D3, 0xFFFFE827, 0x00000569, 0x000027AA, 0xFFFFEEE7, 0x00000492, 0x000027AA, 0xFFFFEEE7, 0x00000492 }, + { 0x0213F0FE992E40C4, 0x00003306, 0xFFFFEA39, 0x000004FC, 0x00001DCC, 0xFFFFF655, 0x00000344, 0x00001DCC, 0xFFFFF655, 0x00000344 }, + { 0x0213F0FE99282044, 0x00002A48, 0xFFFFEFCA, 0x00000439, 0x00001DED, 0xFFFFF60D, 0x00000375, 0x00001DED, 0xFFFFF60D, 0x00000375 }, + { 0x0213F0FE993038C4, 0x000033A3, 0xFFFFEA36, 0x000004F9, 0x0000247C, 0xFFFFF21F, 0x000003F4, 0x0000247C, 0xFFFFF21F, 0x000003F4 }, + { 0x0213F0FE992C3164, 0x0000311B, 0xFFFFEB76, 0x000004D1, 0x00001EB1, 0xFFFFF5B6, 0x00000366, 0x00001EB1, 0xFFFFF5B6, 0x00000366 }, + { 0x0213F0FE99324164, 0x00003307, 0xFFFFE97F, 0x0000052A, 0x00001E76, 0xFFFFF54D, 0x0000037C, 0x00001E76, 0xFFFFF54D, 0x0000037C }, + { 0x0213F0FE991C2144, 0x0000344B, 0xFFFFE9C5, 0x00000509, 0x000020D6, 0xFFFFF486, 0x0000038F, 0x000020D6, 0xFFFFF486, 0x0000038F }, + { 0x0213F0FE992C3144, 0x000034B9, 0xFFFFEA0B, 0x000004F7, 0x000027B3, 0xFFFFF057, 0x0000043A, 0x000027B3, 0xFFFFF057, 0x0000043A }, + { 0x0213F0FE99301964, 0x00003360, 0xFFFFE984, 0x00000527, 0x00002238, 0xFFFFF2EE, 0x000003E0, 0x00002238, 0xFFFFF2EE, 0x000003E0 }, + { 0x0213F0FE99302124, 0x0000315C, 0xFFFFEC05, 0x000004B1, 0x000023C8, 0xFFFFF2CC, 0x000003DE, 0x000023C8, 0xFFFFF2CC, 0x000003DE }, + { 0x0213F0FE992C2864, 0x0000389B, 0xFFFFE6D5, 0x00000582, 0x00002C6C, 0xFFFFEC92, 0x000004DE, 0x00002C6C, 0xFFFFEC92, 0x000004DE }, + { 0x0213F0FE992E1124, 0x00003058, 0xFFFFEB30, 0x000004E6, 0x000019B5, 0xFFFFF88B, 0x000002F1, 0x000019B5, 0xFFFFF88B, 0x000002F1 }, + { 0x0213F0FE992E0904, 0x00002F69, 0xFFFFEB4A, 0x000004F1, 0x00001B82, 0xFFFFF6EC, 0x00000341, 0x00001B82, 0xFFFFF6EC, 0x00000341 }, + { 0x0213F0FE991A18E4, 0x000031EB, 0xFFFFEA64, 0x00000508, 0x00002059, 0xFFFFF427, 0x000003B0, 0x00002059, 0xFFFFF427, 0x000003B0 }, + { 0x0213F0FE99224124, 0x000033E2, 0xFFFFE94D, 0x0000052A, 0x000020BF, 0xFFFFF40B, 0x000003AB, 0x000020BF, 0xFFFFF40B, 0x000003AB }, + { 0x0213F0FE99283184, 0x00002AF9, 0xFFFFEFE9, 0x00000427, 0x00001F72, 0xFFFFF57A, 0x00000383, 0x00001F72, 0xFFFFF57A, 0x00000383 }, + { 0x0213F0FE992C2824, 0x00003282, 0xFFFFEA88, 0x000004FA, 0x00002561, 0xFFFFF126, 0x0000042B, 0x00002561, 0xFFFFF126, 0x0000042B }, + { 0x0213F0FE993010E4, 0x0000308A, 0xFFFFEB5D, 0x000004E0, 0x00001E83, 0xFFFFF577, 0x00000378, 0x00001E83, 0xFFFFF577, 0x00000378 }, + { 0x0213F0FE99324884, 0x0000336E, 0xFFFFE8C8, 0x00000553, 0x0000217C, 0xFFFFF2E1, 0x000003EB, 0x0000217C, 0xFFFFF2E1, 0x000003EB }, + { 0x0213F0FE991A2164, 0x000034A9, 0xFFFFE838, 0x00000561, 0x000020CE, 0xFFFFF38A, 0x000003C7, 0x000020CE, 0xFFFFF38A, 0x000003C7 }, + { 0x0213F0FE99222184, 0x00003152, 0xFFFFE9EB, 0x00000522, 0x00001755, 0xFFFFF9A9, 0x000002C6, 0x00001755, 0xFFFFF9A9, 0x000002C6 }, + { 0x0213F0FE99281884, 0x0000286E, 0xFFFFF136, 0x000003FD, 0x00001BAB, 0xFFFFF7C3, 0x0000032C, 0x00001BAB, 0xFFFFF7C3, 0x0000032C }, + { 0x0213F0FE99300944, 0x0000316B, 0xFFFFEA02, 0x00000528, 0x00002247, 0xFFFFF24E, 0x00000408, 0x00002247, 0xFFFFF24E, 0x00000408 }, + { 0x0213F0FE992C08E4, 0x000034CF, 0xFFFFE83D, 0x00000562, 0x00002458, 0xFFFFF130, 0x00000430, 0x00002458, 0xFFFFF130, 0x00000430 }, + { 0x0213F0FE992C2984, 0x00003352, 0xFFFFE9D1, 0x00000515, 0x0000212A, 0xFFFFF3DC, 0x000003B4, 0x0000212A, 0xFFFFF3DC, 0x000003B4 }, + { 0x0213F0FE992840A4, 0x00002946, 0xFFFFF09B, 0x00000415, 0x00001DC9, 0xFFFFF650, 0x00000366, 0x00001DC9, 0xFFFFF650, 0x00000366 }, + { 0x0213F0FE99301124, 0x00003080, 0xFFFFEB47, 0x000004E1, 0x00001BD5, 0xFFFFF73B, 0x00000329, 0x00001BD5, 0xFFFFF73B, 0x00000329 }, + { 0x0213F0FE991A1884, 0x00002FBD, 0xFFFFEB7B, 0x000004DD, 0x000017FC, 0xFFFFF99E, 0x000002C7, 0x000017FC, 0xFFFFF99E, 0x000002C7 }, + { 0x0213F0FE99281124, 0x00002A28, 0xFFFFF032, 0x0000041F, 0x00001B19, 0xFFFFF83A, 0x00000312, 0x00001B19, 0xFFFFF83A, 0x00000312 }, + { 0x0213F0FE992240C4, 0x00003420, 0xFFFFE936, 0x00000530, 0x000023C2, 0xFFFFF203, 0x00000406, 0x000023C2, 0xFFFFF203, 0x00000406 }, + { 0x0213F0FE99301144, 0x00002F7C, 0xFFFFEBBA, 0x000004D1, 0x0000185D, 0xFFFFF975, 0x000002CA, 0x0000185D, 0xFFFFF975, 0x000002CA }, + { 0x0213F0FE992E2044, 0x00002C51, 0xFFFFEE3B, 0x0000046F, 0x000019AA, 0xFFFFF8DD, 0x000002ED, 0x000019AA, 0xFFFFF8DD, 0x000002ED }, + { 0x0213F0FE991A4144, 0x000033D6, 0xFFFFE8F2, 0x0000053D, 0x00001D73, 0xFFFFF5FB, 0x0000035B, 0x00001D73, 0xFFFFF5FB, 0x0000035B }, + { 0x0213F0FE99323084, 0x000031D9, 0xFFFFEAF7, 0x000004E4, 0x00001EBD, 0xFFFFF5A6, 0x00000368, 0x00001EBD, 0xFFFFF5A6, 0x00000368 }, + { 0x0213F0FE991A20A4, 0x00003386, 0xFFFFE9CE, 0x00000515, 0x00002422, 0xFFFFF1F3, 0x00000405, 0x00002422, 0xFFFFF1F3, 0x00000405 }, + { 0x0213F0FE992C50E4, 0x000032FB, 0xFFFFE9BC, 0x00000520, 0x00002301, 0xFFFFF267, 0x000003F7, 0x00002301, 0xFFFFF267, 0x000003F7 }, + { 0x0213F0FE99322924, 0x000032C2, 0xFFFFEAC0, 0x000004EA, 0x0000250F, 0xFFFFF1A2, 0x00000413, 0x0000250F, 0xFFFFF1A2, 0x00000413 }, + { 0x0213F0FE991C2944, 0x00003722, 0xFFFFE8A6, 0x00000527, 0x000026E4, 0xFFFFF0F5, 0x0000041C, 0x000026E4, 0xFFFFF0F5, 0x0000041C }, + { 0x0213F0FE992C48C4, 0x000035A4, 0xFFFFE822, 0x00000558, 0x000022F2, 0xFFFFF288, 0x000003E8, 0x000022F2, 0xFFFFF288, 0x000003E8 }, + { 0x0213F0FE99280924, 0x00002CD1, 0xFFFFEDC6, 0x0000048C, 0x00001EAF, 0xFFFFF53D, 0x00000396, 0x00001EAF, 0xFFFFF53D, 0x00000396 }, + { 0x0213F0FE99301164, 0x00003156, 0xFFFFEA60, 0x0000050B, 0x00001BBC, 0xFFFFF704, 0x00000335, 0x00001BBC, 0xFFFFF704, 0x00000335 }, + { 0x0213F0FE992C5104, 0x000034A1, 0xFFFFE8C0, 0x00000544, 0x00002528, 0xFFFFF105, 0x0000042C, 0x00002528, 0xFFFFF105, 0x0000042C }, + { 0x0213F0FE99323064, 0x000032CE, 0xFFFFE9D3, 0x00000520, 0x000021FF, 0xFFFFF2FD, 0x000003E4, 0x000021FF, 0xFFFFF2FD, 0x000003E4 }, + { 0x0213F0FE991A50A4, 0x000034A0, 0xFFFFE823, 0x0000056D, 0x0000256F, 0xFFFFF047, 0x0000045A, 0x0000256F, 0xFFFFF047, 0x0000045A }, + { 0x0213F0FE99303944, 0x00003109, 0xFFFFEBD6, 0x000004BF, 0x000022D4, 0xFFFFF32D, 0x000003D0, 0x000022D4, 0xFFFFF32D, 0x000003D0 }, + { 0x0213F0FE992C1164, 0x000030B7, 0xFFFFEAF0, 0x000004F3, 0x00001AEC, 0xFFFFF7A9, 0x0000031B, 0x00001AEC, 0xFFFFF7A9, 0x0000031B }, + { 0x0213F0FE992C39A4, 0x00003078, 0xFFFFEBA4, 0x000004CF, 0x00001E7A, 0xFFFFF5AF, 0x0000036B, 0x00001E7A, 0xFFFFF5AF, 0x0000036B }, + { 0x0213F0FE99304124, 0x00003442, 0xFFFFE998, 0x00000518, 0x000025EA, 0xFFFFF0F3, 0x0000042B, 0x000025EA, 0xFFFFF0F3, 0x0000042B }, + { 0x0213F0FE993021A4, 0x000031CB, 0xFFFFEA80, 0x00000501, 0x000020A3, 0xFFFFF403, 0x000003B2, 0x000020A3, 0xFFFFF403, 0x000003B2 }, + { 0x0213F0FE992A2984, 0x00002947, 0xFFFFF018, 0x00000433, 0x00001BA5, 0xFFFFF75C, 0x00000340, 0x00001BA5, 0xFFFFF75C, 0x00000340 }, + { 0x0213F0FE992C3984, 0x000033F9, 0xFFFFE99D, 0x00000518, 0x00002231, 0xFFFFF358, 0x000003C5, 0x00002231, 0xFFFFF358, 0x000003C5 }, + { 0x0213F0FE99321124, 0x00003131, 0xFFFFEA45, 0x00000513, 0x00001973, 0xFFFFF85E, 0x00000301, 0x00001973, 0xFFFFF85E, 0x00000301 }, + { 0x0213F0FE991C29A4, 0x00003571, 0xFFFFE8AC, 0x00000539, 0x00002049, 0xFFFFF49C, 0x0000038D, 0x00002049, 0xFFFFF49C, 0x0000038D }, + { 0x0213F0FE992E3864, 0x0000309E, 0xFFFFEB1D, 0x000004E8, 0x000019ED, 0xFFFFF86E, 0x000002F8, 0x000019ED, 0xFFFFF86E, 0x000002F8 }, + { 0x0213F0FE99302984, 0x00003091, 0xFFFFEB9B, 0x000004CC, 0x00001D2C, 0xFFFFF6A2, 0x0000033D, 0x00001D2C, 0xFFFFF6A2, 0x0000033D }, + { 0x0213F0FE993008E4, 0x00003069, 0xFFFFEAFD, 0x000004F8, 0x00001E82, 0xFFFFF51C, 0x0000038D, 0x00001E82, 0xFFFFF51C, 0x0000038D }, + { 0x0213F0FE992210A4, 0x00003459, 0xFFFFE7F2, 0x00000572, 0x00001DA7, 0xFFFFF552, 0x0000037F, 0x00001DA7, 0xFFFFF552, 0x0000037F }, + { 0x0213F0FE99321104, 0x0000304B, 0xFFFFEAFB, 0x000004F4, 0x0000191E, 0xFFFFF8BD, 0x000002EE, 0x0000191E, 0xFFFFF8BD, 0x000002EE }, + { 0x0213F0FE993020C4, 0x0000346E, 0xFFFFEA07, 0x000004FD, 0x00002767, 0xFFFFF058, 0x00000440, 0x00002767, 0xFFFFF058, 0x00000440 }, + { 0x0213F0FE992E3084, 0x000030B5, 0xFFFFEBC1, 0x000004C1, 0x00001B3C, 0xFFFFF818, 0x000002FD, 0x00001B3C, 0xFFFFF818, 0x000002FD }, + { 0x0213F0FE99300904, 0x0000321F, 0xFFFFE9EA, 0x00000524, 0x00002380, 0xFFFFF1C2, 0x0000041A, 0x00002380, 0xFFFFF1C2, 0x0000041A }, + { 0x0213F0FE992E3044, 0x000030DF, 0xFFFFEB37, 0x000004E2, 0x00001E3C, 0xFFFFF5BB, 0x00000369, 0x00001E3C, 0xFFFFF5BB, 0x00000369 }, + { 0x0213F0FE992848A4, 0x000027E0, 0xFFFFF0E2, 0x00000416, 0x00001A6A, 0xFFFFF820, 0x00000321, 0x00001A6A, 0xFFFFF820, 0x00000321 }, + { 0x0213F0FE991A1084, 0x00002FA1, 0xFFFFEB63, 0x000004E7, 0x0000196B, 0xFFFFF880, 0x000002FB, 0x0000196B, 0xFFFFF880, 0x000002FB }, + { 0x0213F0FE991C1084, 0x0000310C, 0xFFFFEAAF, 0x000004FC, 0x000019EF, 0xFFFFF850, 0x000002FD, 0x000019EF, 0xFFFFF850, 0x000002FD }, + { 0x0213F0FE99323904, 0x0000334A, 0xFFFFEA07, 0x0000050B, 0x00002380, 0xFFFFF26F, 0x000003F0, 0x00002380, 0xFFFFF26F, 0x000003F0 }, + { 0x0213F0FE99302944, 0x00002FF9, 0xFFFFECDC, 0x00000492, 0x00002297, 0xFFFFF394, 0x000003BF, 0x00002297, 0xFFFFF394, 0x000003BF }, + { 0x0213F0FE992C2164, 0x0000354B, 0xFFFFE894, 0x00000546, 0x000024C4, 0xFFFFF16C, 0x0000041B, 0x000024C4, 0xFFFFF16C, 0x0000041B }, + { 0x0213F0FE99220924, 0x00003245, 0xFFFFE92F, 0x00000544, 0x00001829, 0xFFFFF8F1, 0x000002EA, 0x00001829, 0xFFFFF8F1, 0x000002EA }, + { 0x0213F0FE992E4884, 0x0000302F, 0xFFFFEB51, 0x000004E3, 0x0000199F, 0xFFFFF894, 0x000002F4, 0x0000199F, 0xFFFFF894, 0x000002F4 }, + { 0x0213F0FE992E18C4, 0x00002F54, 0xFFFFEC86, 0x000004A6, 0x00001A6F, 0xFFFFF891, 0x000002EC, 0x00001A6F, 0xFFFFF891, 0x000002EC }, + { 0x0213F0FE99284164, 0x00002908, 0xFFFFF0D8, 0x0000040A, 0x00001C9B, 0xFFFFF729, 0x00000342, 0x00001C9B, 0xFFFFF729, 0x00000342 }, + { 0x0213F0FE99302964, 0x000031D9, 0xFFFFEB40, 0x000004D7, 0x000023F5, 0xFFFFF259, 0x000003F4, 0x000023F5, 0xFFFFF259, 0x000003F4 }, + { 0x0213F0FE993048E4, 0x000034C8, 0xFFFFE8C6, 0x0000053F, 0x00002313, 0xFFFFF280, 0x000003EC, 0x00002313, 0xFFFFF280, 0x000003EC }, + { 0x0213F0FE993050C4, 0x000037D1, 0xFFFFE6A1, 0x0000059C, 0x00002C6A, 0xFFFFEBFF, 0x00000504, 0x00002C6A, 0xFFFFEBFF, 0x00000504 }, + { 0x0213F0FE99321964, 0x000030E9, 0xFFFFEA6B, 0x0000050F, 0x00001A2D, 0xFFFFF7DF, 0x00000316, 0x00001A2D, 0xFFFFF7DF, 0x00000316 }, + { 0x0213F0FE99302084, 0x0000323D, 0xFFFFEA95, 0x000004F4, 0x00001ED2, 0xFFFFF584, 0x0000036C, 0x00001ED2, 0xFFFFF584, 0x0000036C }, + { 0x0213F0FE992C3024, 0x000033D6, 0xFFFFE9DB, 0x00000510, 0x000027A7, 0xFFFFEFC7, 0x0000045E, 0x000027A7, 0xFFFFEFC7, 0x0000045E }, + { 0x0213F0FE991C3164, 0x00003444, 0xFFFFE98A, 0x00000517, 0x000020FD, 0xFFFFF43F, 0x0000039D, 0x000020FD, 0xFFFFF43F, 0x0000039D }, + { 0x0213F0FE992808E4, 0x00002987, 0xFFFFEFA1, 0x0000044B, 0x00001B06, 0xFFFFF788, 0x0000033C, 0x00001B06, 0xFFFFF788, 0x0000033C }, + { 0x0213F0FE992C28E4, 0x0000311D, 0xFFFFED20, 0x00000474, 0x000025DA, 0xFFFFF223, 0x000003F0, 0x000025DA, 0xFFFFF223, 0x000003F0 }, + { 0x0213F0FE992C1124, 0x000032A2, 0xFFFFEA0A, 0x0000050D, 0x00001D48, 0xFFFFF659, 0x0000034A, 0x00001D48, 0xFFFFF659, 0x0000034A }, + { 0x0213F0FE992208E4, 0x00003110, 0xFFFFE9EA, 0x00000529, 0x00001786, 0xFFFFF958, 0x000002DB, 0x00001786, 0xFFFFF958, 0x000002DB }, + { 0x0213F0FE992821A4, 0x000027F2, 0xFFFFF174, 0x000003F7, 0x00001C7A, 0xFFFFF72A, 0x00000348, 0x00001C7A, 0xFFFFF72A, 0x00000348 }, + { 0x0213F0FE991C10E4, 0x000031DB, 0xFFFFEA7D, 0x000004FB, 0x000019C4, 0xFFFFF8B1, 0x000002E6, 0x000019C4, 0xFFFFF8B1, 0x000002E6 }, + { 0x0213F0FE992C1104, 0x00003158, 0xFFFFEAAC, 0x000004FA, 0x00001BC1, 0xFFFFF737, 0x0000032B, 0x00001BC1, 0xFFFFF737, 0x0000032B }, + { 0x0213F0FE993010C4, 0x00002F36, 0xFFFFEBF9, 0x000004CA, 0x00001A2A, 0xFFFFF83F, 0x00000303, 0x00001A2A, 0xFFFFF83F, 0x00000303 }, + { 0x0213F0FE993238A4, 0x000032B4, 0xFFFFEA72, 0x000004FA, 0x000021FF, 0xFFFFF378, 0x000003C5, 0x000021FF, 0xFFFFF378, 0x000003C5 }, + { 0x0213F0FE99303164, 0x00003262, 0xFFFFEAFA, 0x000004DF, 0x00002441, 0xFFFFF237, 0x000003F6, 0x00002441, 0xFFFFF237, 0x000003F6 }, + { 0x0213F0FE99303924, 0x0000336A, 0xFFFFEAFB, 0x000004D1, 0x00002746, 0xFFFFF0B8, 0x0000042B, 0x00002746, 0xFFFFF0B8, 0x0000042B }, + { 0x0213F0FE991A4084, 0x000032E5, 0xFFFFE923, 0x00000541, 0x00001DF0, 0xFFFFF552, 0x00000380, 0x00001DF0, 0xFFFFF552, 0x00000380 }, + { 0x0213F0FE99304064, 0x000035D1, 0xFFFFE80B, 0x0000055F, 0x00002780, 0xFFFFEF74, 0x0000046F, 0x00002780, 0xFFFFEF74, 0x0000046F }, + { 0x0213F0FE993028A4, 0x000033EC, 0xFFFFEA48, 0x000004F4, 0x0000269F, 0xFFFFF0D8, 0x0000042A, 0x0000269F, 0xFFFFF0D8, 0x0000042A }, + { 0x0213F0FE99323884, 0x000030C4, 0xFFFFEB39, 0x000004E2, 0x00001B44, 0xFFFFF7AA, 0x00000318, 0x00001B44, 0xFFFFF7AA, 0x00000318 }, + { 0x0213F0FE99281144, 0x00002926, 0xFFFFF0AF, 0x0000040E, 0x0000194E, 0xFFFFF959, 0x000002E2, 0x0000194E, 0xFFFFF959, 0x000002E2 }, + { 0x0213F0FE992C10C4, 0x00003141, 0xFFFFEAAF, 0x000004F6, 0x00001864, 0xFFFFF97C, 0x000002C6, 0x00001864, 0xFFFFF97C, 0x000002C6 }, + { 0x0213F0FE99301064, 0x000030B2, 0xFFFFEB7C, 0x000004DB, 0x000022CE, 0xFFFFF2B5, 0x000003F0, 0x000022CE, 0xFFFFF2B5, 0x000003F0 }, + { 0x0213F0FE99301944, 0x0000318C, 0xFFFFEAC7, 0x000004F6, 0x00002113, 0xFFFFF3CA, 0x000003BD, 0x00002113, 0xFFFFF3CA, 0x000003BD }, + { 0x0213F0FE992E1104, 0x00002FD2, 0xFFFFEB8F, 0x000004D9, 0x00001996, 0xFFFFF89F, 0x000002F1, 0x00001996, 0xFFFFF89F, 0x000002F1 }, + { 0x0213F0FE991A28A4, 0x0000310D, 0xFFFFEB25, 0x000004E7, 0x00001F67, 0xFFFFF4EF, 0x0000038E, 0x00001F67, 0xFFFFF4EF, 0x0000038E }, + { 0x0213F0FE992A4964, 0x00002BBC, 0xFFFFEE68, 0x00000477, 0x00002050, 0xFFFFF41D, 0x000003C8, 0x00002050, 0xFFFFF41D, 0x000003C8 }, + { 0x0213F0FE99302104, 0x00003096, 0xFFFFECED, 0x00000486, 0x000024C9, 0xFFFFF278, 0x000003E7, 0x000024C9, 0xFFFFF278, 0x000003E7 }, + { 0x0213F0FE992C10A4, 0x00003401, 0xFFFFE8F1, 0x0000053C, 0x00001E75, 0xFFFFF55C, 0x00000376, 0x00001E75, 0xFFFFF55C, 0x00000376 }, + { 0x0213F0FE99302844, 0x0000319E, 0xFFFFEAB1, 0x000004F8, 0x00001EA3, 0xFFFFF567, 0x00000378, 0x00001EA3, 0xFFFFF567, 0x00000378 }, + { 0x0213F0FE99322964, 0x000030FD, 0xFFFFEB4C, 0x000004DB, 0x00001CA6, 0xFFFFF6E8, 0x00000335, 0x00001CA6, 0xFFFFF6E8, 0x00000335 }, + { 0x0213F0FE992E40A4, 0x000030D6, 0xFFFFEB1A, 0x000004E4, 0x00001A0D, 0xFFFFF87D, 0x000002EF, 0x00001A0D, 0xFFFFF87D, 0x000002EF }, + { 0x0213F0FE992C2124, 0x0000324B, 0xFFFFEB17, 0x000004D9, 0x00002225, 0xFFFFF3A8, 0x000003BA, 0x00002225, 0xFFFFF3A8, 0x000003BA }, + { 0x0213F0FE99284084, 0x00002A00, 0xFFFFF02E, 0x00000424, 0x00001E21, 0xFFFFF61D, 0x0000036C, 0x00001E21, 0xFFFFF61D, 0x0000036C }, + { 0x0213F0FE992A48A4, 0x000029CF, 0xFFFFEF53, 0x00000457, 0x00001B11, 0xFFFFF772, 0x0000033D, 0x00001B11, 0xFFFFF772, 0x0000033D }, + { 0x0213F0FE991A30A4, 0x000032A1, 0xFFFFEA63, 0x000004FB, 0x00001F83, 0xFFFFF516, 0x0000037E, 0x00001F83, 0xFFFFF516, 0x0000037E }, + { 0x0213F0FE992E20C4, 0x0000305C, 0xFFFFEC14, 0x000004B5, 0x00001D0B, 0xFFFFF6ED, 0x00000332, 0x00001D0B, 0xFFFFF6ED, 0x00000332 }, + { 0x0213F0FE992C1064, 0x00003467, 0xFFFFE8D5, 0x00000543, 0x0000243F, 0xFFFFF190, 0x00000418, 0x0000243F, 0xFFFFF190, 0x00000418 }, + { 0x0213F0FE992A2064, 0x00002796, 0xFFFFF133, 0x00000409, 0x00001903, 0xFFFFF91C, 0x000002FC, 0x00001903, 0xFFFFF91C, 0x000002FC }, + { 0x0213F0FE99302164, 0x000031F6, 0xFFFFEAB7, 0x000004F5, 0x000022B9, 0xFFFFF2D0, 0x000003E6, 0x000022B9, 0xFFFFF2D0, 0x000003E6 }, + { 0x0213F0FE992E5104, 0x00003196, 0xFFFFEA76, 0x00000503, 0x00001CC5, 0xFFFFF67D, 0x0000034A, 0x00001CC5, 0xFFFFF67D, 0x0000034A }, + { 0x0213F0FE99321144, 0x00002F9E, 0xFFFFEAD9, 0x00000505, 0x000017C1, 0xFFFFF93D, 0x000002DF, 0x000017C1, 0xFFFFF93D, 0x000002DF }, + { 0x0213F0FE992E2124, 0x00002FBC, 0xFFFFEC75, 0x000004A8, 0x00001D6D, 0xFFFFF6AC, 0x0000033D, 0x00001D6D, 0xFFFFF6AC, 0x0000033D }, + { 0x0213F0FE992C38A4, 0x00003541, 0xFFFFE921, 0x00000524, 0x00002662, 0xFFFFF0CB, 0x0000042B, 0x00002662, 0xFFFFF0CB, 0x0000042B }, + { 0x0213F0FE992A21A4, 0x00002953, 0xFFFFEF76, 0x00000459, 0x00001C05, 0xFFFFF6A0, 0x00000368, 0x00001C05, 0xFFFFF6A0, 0x00000368 }, + { 0x0213F0FE992C4924, 0x000034BC, 0xFFFFE8DD, 0x00000536, 0x0000210E, 0xFFFFF3F4, 0x000003A8, 0x0000210E, 0xFFFFF3F4, 0x000003A8 }, + { 0x0213F0FE992C29A4, 0x000034BE, 0xFFFFE916, 0x0000052F, 0x000024A1, 0xFFFFF1A6, 0x00000410, 0x000024A1, 0xFFFFF1A6, 0x00000410 }, + { 0x0213F0FE99304964, 0x000037B5, 0xFFFFE7A9, 0x0000055B, 0x000028A1, 0xFFFFEF51, 0x00000467, 0x000028A1, 0xFFFFEF51, 0x00000467 }, + { 0x0213F0FE99301104, 0x00002FC5, 0xFFFFEBBE, 0x000004D1, 0x00001BA5, 0xFFFFF757, 0x00000328, 0x00001BA5, 0xFFFFF757, 0x00000328 }, + { 0x0213F0FE993040A4, 0x000033CB, 0xFFFFE944, 0x0000052B, 0x00001FBE, 0xFFFFF4B1, 0x0000038C, 0x00001FBE, 0xFFFFF4B1, 0x0000038C }, + { 0x0213F0FE99301844, 0x000030AE, 0xFFFFEBA0, 0x000004D3, 0x00002268, 0xFFFFF316, 0x000003DD, 0x00002268, 0xFFFFF316, 0x000003DD }, + { 0x0213F0FE992C20A4, 0x00002F90, 0xFFFFEC5A, 0x000004B0, 0x00001C3A, 0xFFFFF752, 0x00000323, 0x00001C3A, 0xFFFFF752, 0x00000323 }, + { 0x0213F0FE992E38E4, 0x00003113, 0xFFFFEB91, 0x000004C8, 0x00001E3C, 0xFFFFF623, 0x0000034E, 0x00001E3C, 0xFFFFF623, 0x0000034E }, + { 0x0213F0FE99323984, 0x0000330B, 0xFFFFE94B, 0x00000539, 0x000020E7, 0xFFFFF37E, 0x000003CD, 0x000020E7, 0xFFFFF37E, 0x000003CD }, + { 0x0213F0FE992E2864, 0x000031D1, 0xFFFFEACB, 0x000004ED, 0x00001E82, 0xFFFFF5B2, 0x00000365, 0x00001E82, 0xFFFFF5B2, 0x00000365 }, + { 0x0213F0FE992A3984, 0x00002CD5, 0xFFFFEDC1, 0x0000048D, 0x000020F8, 0xFFFFF3C1, 0x000003D1, 0x000020F8, 0xFFFFF3C1, 0x000003D1 }, + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } +}; + +int pp_override_get_default_fuse_value(uint64_t key, + struct phm_fuses_default *result) +{ + const struct phm_fuses_default *list = vega10_fuses_default; + uint32_t i; + + for (i = 0; list[i].key != 0; i++) { + if (key == list[i].key) { + result->key = list[i].key; + result->VFT2_m1 = list[i].VFT2_m1; + result->VFT2_m2 = list[i].VFT2_m2; + result->VFT2_b = list[i].VFT2_b; + result->VFT1_m1 = list[i].VFT1_m1; + result->VFT1_m2 = list[i].VFT1_m2; + result->VFT1_b = list[i].VFT1_b; + result->VFT0_m1 = list[i].VFT0_m1; + result->VFT0_m2 = list[i].VFT0_m2; + result->VFT0_b = list[i].VFT0_b; + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h new file mode 100644 index 000000000000..4112a9398163 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_overdriver.h @@ -0,0 +1,46 @@ +/* + * Copyright 2015 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 _PP_OVERDRIVER_H_ +#define _PP_OVERDRIVER_H_ + +#include +#include + +struct phm_fuses_default { + uint64_t key; + uint32_t VFT2_m1; + uint32_t VFT2_m2; + uint32_t VFT2_b; + uint32_t VFT1_m1; + uint32_t VFT1_m2; + uint32_t VFT1_b; + uint32_t VFT0_m1; + uint32_t VFT0_m2; + uint32_t VFT0_b; +}; + +extern int pp_override_get_default_fuse_value(uint64_t key, + struct phm_fuses_default *result); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c new file mode 100644 index 000000000000..31a32a79cfc2 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c @@ -0,0 +1,296 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include "pp_psm.h" + +int psm_init_power_state_table(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned int i; + unsigned int table_entries; + struct pp_power_state *state; + int size; + + if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) + return 0; + + if (hwmgr->hwmgr_func->get_power_state_size == NULL) + return 0; + + hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); + + hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + + sizeof(struct pp_power_state); + + if (table_entries == 0 || size == 0) { + pr_warn("Please check whether power state management is supported on this asic\n"); + return 0; + } + + hwmgr->ps = kcalloc(table_entries, size, GFP_KERNEL); + if (hwmgr->ps == NULL) + return -ENOMEM; + + hwmgr->request_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->request_ps == NULL) { + kfree(hwmgr->ps); + hwmgr->ps = NULL; + return -ENOMEM; + } + + hwmgr->current_ps = kzalloc(size, GFP_KERNEL); + if (hwmgr->current_ps == NULL) { + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + return -ENOMEM; + } + + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + + if (state->classification.flags & PP_StateClassificationFlag_Boot) { + hwmgr->boot_ps = state; + memcpy(hwmgr->current_ps, state, size); + memcpy(hwmgr->request_ps, state, size); + } + + state->id = i + 1; /* assigned unique num for every power state id */ + + if (state->classification.flags & PP_StateClassificationFlag_Uvd) + hwmgr->uvd_ps = state; + state = (struct pp_power_state *)((unsigned long)state + size); + } + + return 0; +} + +int psm_fini_power_state_table(struct pp_hwmgr *hwmgr) +{ + if (hwmgr == NULL) + return -EINVAL; + + if (!hwmgr->ps) + return 0; + + kfree(hwmgr->current_ps); + kfree(hwmgr->request_ps); + kfree(hwmgr->ps); + hwmgr->request_ps = NULL; + hwmgr->ps = NULL; + hwmgr->current_ps = NULL; + return 0; +} + +static int psm_get_ui_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel ui_label, + unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.ui_label & ui_label) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +static int psm_get_state_by_classification(struct pp_hwmgr *hwmgr, + enum PP_StateClassificationFlag flag, + unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.flags & flag) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +static int psm_set_states(struct pp_hwmgr *hwmgr, unsigned long state_id) +{ + struct pp_power_state *state; + int table_entries; + int i; + + table_entries = hwmgr->num_ps; + + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->id == state_id) { + memcpy(hwmgr->request_ps, state, hwmgr->ps_size); + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -EINVAL; +} + +int psm_set_boot_states(struct pp_hwmgr *hwmgr) +{ + unsigned long state_id; + int ret = -EINVAL; + + if (!hwmgr->ps) + return 0; + + if (!psm_get_state_by_classification(hwmgr, PP_StateClassificationFlag_Boot, + &state_id)) + ret = psm_set_states(hwmgr, state_id); + + return ret; +} + +int psm_set_performance_states(struct pp_hwmgr *hwmgr) +{ + unsigned long state_id; + int ret = -EINVAL; + + if (!hwmgr->ps) + return 0; + + if (!psm_get_ui_state(hwmgr, PP_StateUILabel_Performance, + &state_id)) + ret = psm_set_states(hwmgr, state_id); + + return ret; +} + +int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel label_id, + struct pp_power_state **state) +{ + int table_entries; + int i; + + if (!hwmgr->ps) + return 0; + + table_entries = hwmgr->num_ps; + *state = hwmgr->ps; + +restart_search: + for (i = 0; i < table_entries; i++) { + if ((*state)->classification.ui_label & label_id) + return 0; + *state = (struct pp_power_state *)((uintptr_t)*state + hwmgr->ps_size); + } + + switch (label_id) { + case PP_StateUILabel_Battery: + case PP_StateUILabel_Balanced: + label_id = PP_StateUILabel_Performance; + goto restart_search; + default: + break; + } + return -EINVAL; +} + +static void power_state_management(struct pp_hwmgr *hwmgr, + struct pp_power_state *new_ps) +{ + struct pp_power_state *pcurrent; + struct pp_power_state *requested; + bool equal; + + if (new_ps != NULL) + requested = new_ps; + else + requested = hwmgr->request_ps; + + pcurrent = hwmgr->current_ps; + + phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); + if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, + &pcurrent->hardware, &requested->hardware, &equal))) + equal = false; + + if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { + phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); + memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); + } +} + +int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_settings, + struct pp_power_state *new_ps) +{ + uint32_t index; + long workload; + + if (hwmgr->not_vf) { + if (!skip_display_settings) + phm_display_configuration_changed(hwmgr); + + if (hwmgr->ps) + power_state_management(hwmgr, new_ps); + else + /* + * for vega12/vega20 which does not support power state manager + * DAL clock limits should also be honoured + */ + phm_apply_clock_adjust_rules(hwmgr); + + if (!skip_display_settings) + phm_notify_smc_display_config_after_ps_adjustment(hwmgr); + } + + if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level)) + hwmgr->dpm_level = hwmgr->request_dpm_level; + + if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + index = fls(hwmgr->workload_mask); + index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; + workload = hwmgr->workload_setting[index]; + + if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode) + hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); + } + + return 0; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h new file mode 100644 index 000000000000..b62d55f1f289 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef PP_PSM_H +#define PP_PSM_H + +#include "hwmgr.h" + +int psm_init_power_state_table(struct pp_hwmgr *hwmgr); +int psm_fini_power_state_table(struct pp_hwmgr *hwmgr); +int psm_set_boot_states(struct pp_hwmgr *hwmgr); +int psm_set_performance_states(struct pp_hwmgr *hwmgr); +int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, + enum PP_StateUILabel label_id, + struct pp_power_state **state); +int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, + bool skip_display_settings, + struct pp_power_state *new_ps); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c new file mode 100644 index 000000000000..01dc46dc9c8a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.c @@ -0,0 +1,1562 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include "atom.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "cgs_common.h" +#include "ppevvmath.h" + +#define MEM_ID_MASK 0xff000000 +#define MEM_ID_SHIFT 24 +#define CLOCK_RANGE_MASK 0x00ffffff +#define CLOCK_RANGE_SHIFT 0 +#define LOW_NIBBLE_MASK 0xf +#define DATA_EQU_PREV 0 +#define DATA_FROM_TABLE 4 + +union voltage_object_info { + struct _ATOM_VOLTAGE_OBJECT_INFO v1; + struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; + struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3; +}; + +static int atomctrl_retrieve_ac_timing( + uint8_t index, + ATOM_INIT_REG_BLOCK *reg_block, + pp_atomctrl_mc_reg_table *table) +{ + uint32_t i, j; + uint8_t tmem_id; + ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) + ((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize)); + + uint8_t num_ranges = 0; + + while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK && + num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) { + tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT); + + if (index == tmem_id) { + table->mc_reg_table_entry[num_ranges].mclk_max = + (uint32_t)((*(uint32_t *)reg_data & CLOCK_RANGE_MASK) >> + CLOCK_RANGE_SHIFT); + + for (i = 0, j = 1; i < table->last; i++) { + if ((table->mc_reg_address[i].uc_pre_reg_data & + LOW_NIBBLE_MASK) == DATA_FROM_TABLE) { + table->mc_reg_table_entry[num_ranges].mc_data[i] = + (uint32_t)*((uint32_t *)reg_data + j); + j++; + } else if ((table->mc_reg_address[i].uc_pre_reg_data & + LOW_NIBBLE_MASK) == DATA_EQU_PREV) { + table->mc_reg_table_entry[num_ranges].mc_data[i] = + table->mc_reg_table_entry[num_ranges].mc_data[i-1]; + } + } + num_ranges++; + } + + reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) + ((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ; + } + + PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK), + "Invalid VramInfo table.", return -1); + table->num_entries = num_ranges; + + return 0; +} + +/** + * Get memory clock AC timing registers index from VBIOS table + * VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 1 + * @param reg_block the address ATOM_INIT_REG_BLOCK + * @param table the address of MCRegTable + * @return 0 + */ +static int atomctrl_set_mc_reg_address_table( + ATOM_INIT_REG_BLOCK *reg_block, + pp_atomctrl_mc_reg_table *table) +{ + uint8_t i = 0; + uint8_t num_entries = (uint8_t)((le16_to_cpu(reg_block->usRegIndexTblSize)) + / sizeof(ATOM_INIT_REG_INDEX_FORMAT)); + ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0]; + + num_entries--; /* subtract 1 data end mark entry */ + + PP_ASSERT_WITH_CODE((num_entries <= VBIOS_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + + /* ucPreRegDataLength bit6 = 1 is the end of memory clock AC timing registers */ + while ((!(format->ucPreRegDataLength & ACCESS_PLACEHOLDER)) && + (i < num_entries)) { + table->mc_reg_address[i].s1 = + (uint16_t)(le16_to_cpu(format->usRegIndex)); + table->mc_reg_address[i].uc_pre_reg_data = + format->ucPreRegDataLength; + + i++; + format = (ATOM_INIT_REG_INDEX_FORMAT *) + ((uint8_t *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT)); + } + + table->last = i; + return 0; +} + +int atomctrl_initialize_mc_reg_table( + struct pp_hwmgr *hwmgr, + uint8_t module_index, + pp_atomctrl_mc_reg_table *table) +{ + ATOM_VRAM_INFO_HEADER_V2_1 *vram_info; + ATOM_INIT_REG_BLOCK *reg_block; + int result = 0; + u8 frev, crev; + u16 size; + + vram_info = (ATOM_VRAM_INFO_HEADER_V2_1 *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev); + + if (module_index >= vram_info->ucNumOfVRAMModule) { + pr_err("Invalid VramInfo table."); + result = -1; + } else if (vram_info->sHeader.ucTableFormatRevision < 2) { + pr_err("Invalid VramInfo table."); + result = -1; + } + + if (0 == result) { + reg_block = (ATOM_INIT_REG_BLOCK *) + ((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset)); + result = atomctrl_set_mc_reg_address_table(reg_block, table); + } + + if (0 == result) { + result = atomctrl_retrieve_ac_timing(module_index, + reg_block, table); + } + + return result; +} + +/** + * Set DRAM timings based on engine clock and memory clock. + */ +int atomctrl_set_engine_dram_timings_rv770( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock) +{ + struct amdgpu_device *adev = hwmgr->adev; + + SET_ENGINE_CLOCK_PS_ALLOCATION engine_clock_parameters; + + /* They are both in 10KHz Units. */ + engine_clock_parameters.ulTargetEngineClock = + cpu_to_le32((engine_clock & SET_CLOCK_FREQ_MASK) | + ((COMPUTE_ENGINE_PLL_PARAM << 24))); + + /* in 10 khz units.*/ + engine_clock_parameters.sReserved.ulClock = + cpu_to_le32(memory_clock & SET_CLOCK_FREQ_MASK); + + return amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings), + (uint32_t *)&engine_clock_parameters); +} + +/** + * Private Function to get the PowerPlay Table Address. + * WARNING: The tabled returned by this function is in + * dynamically allocated memory. + * The caller has to release if by calling kfree. + */ +static ATOM_VOLTAGE_OBJECT_INFO *get_voltage_info_table(void *device) +{ + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); + u8 frev, crev; + u16 size; + union voltage_object_info *voltage_info; + + voltage_info = (union voltage_object_info *) + smu_atom_get_data_table(device, index, + &size, &frev, &crev); + + if (voltage_info != NULL) + return (ATOM_VOLTAGE_OBJECT_INFO *) &(voltage_info->v3); + else + return NULL; +} + +static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3( + const ATOM_VOLTAGE_OBJECT_INFO_V3_1 * voltage_object_info_table, + uint8_t voltage_type, uint8_t voltage_mode) +{ + unsigned int size = le16_to_cpu(voltage_object_info_table->sHeader.usStructureSize); + unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]); + uint8_t *start = (uint8_t *)voltage_object_info_table; + + while (offset < size) { + const ATOM_VOLTAGE_OBJECT_V3 *voltage_object = + (const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset); + + if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType && + voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode) + return voltage_object; + + offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize); + } + + return NULL; +} + +/** atomctrl_get_memory_pll_dividers_si(). + * + * @param hwmgr input parameter: pointer to HwMgr + * @param clock_value input parameter: memory clock + * @param dividers output parameter: memory PLL dividers + * @param strobe_mode input parameter: 1 for strobe mode, 0 for performance mode + */ +int atomctrl_get_memory_pll_dividers_si( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_memory_clock_param *mpll_param, + bool strobe_mode) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 mpll_parameters; + int result; + + mpll_parameters.ulClock = cpu_to_le32(clock_value); + mpll_parameters.ucInputFlag = (uint8_t)((strobe_mode) ? 1 : 0); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), + (uint32_t *)&mpll_parameters); + + if (0 == result) { + mpll_param->mpll_fb_divider.clk_frac = + le16_to_cpu(mpll_parameters.ulFbDiv.usFbDivFrac); + mpll_param->mpll_fb_divider.cl_kf = + le16_to_cpu(mpll_parameters.ulFbDiv.usFbDiv); + mpll_param->mpll_post_divider = + (uint32_t)mpll_parameters.ucPostDiv; + mpll_param->vco_mode = + (uint32_t)(mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_VCO_MODE_MASK); + mpll_param->yclk_sel = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0); + mpll_param->qdr = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0); + mpll_param->half_rate = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0); + mpll_param->dll_speed = + (uint32_t)(mpll_parameters.ucDllSpeed); + mpll_param->bw_ctrl = + (uint32_t)(mpll_parameters.ucBWCntl); + } + + return result; +} + +/** atomctrl_get_memory_pll_dividers_vi(). + * + * @param hwmgr input parameter: pointer to HwMgr + * @param clock_value input parameter: memory clock + * @param dividers output parameter: memory PLL dividers + */ +int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, + uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 mpll_parameters; + int result; + + mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), + (uint32_t *)&mpll_parameters); + + if (!result) + mpll_param->mpll_post_divider = + (uint32_t)mpll_parameters.ulClock.ucPostDiv; + + return result; +} + +int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_memory_clock_param_ai *mpll_param) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_3 mpll_parameters = {{0}, 0, 0}; + int result; + + mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), + (uint32_t *)&mpll_parameters); + + /* VEGAM's mpll takes sometime to finish computing */ + udelay(10); + + if (!result) { + mpll_param->ulMclk_fcw_int = + le16_to_cpu(mpll_parameters.usMclk_fcw_int); + mpll_param->ulMclk_fcw_frac = + le16_to_cpu(mpll_parameters.usMclk_fcw_frac); + mpll_param->ulClock = + le32_to_cpu(mpll_parameters.ulClock.ulClock); + mpll_param->ulPostDiv = mpll_parameters.ulClock.ucPostDiv; + } + + return result; +} + +int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_kong *dividers) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 pll_parameters; + int result; + + pll_parameters.ulClock = cpu_to_le32(clock_value); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + (uint32_t *)&pll_parameters); + + if (0 == result) { + dividers->pll_post_divider = pll_parameters.ucPostDiv; + dividers->real_clock = le32_to_cpu(pll_parameters.ulClock); + } + + return result; +} + +int atomctrl_get_engine_pll_dividers_vi( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_vi *dividers) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; + int result; + + pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); + pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + (uint32_t *)&pll_patameters); + + if (0 == result) { + dividers->pll_post_divider = + pll_patameters.ulClock.ucPostDiv; + dividers->real_clock = + le32_to_cpu(pll_patameters.ulClock.ulClock); + + dividers->ul_fb_div.ul_fb_div_frac = + le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac); + dividers->ul_fb_div.ul_fb_div = + le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv); + + dividers->uc_pll_ref_div = + pll_patameters.ucPllRefDiv; + dividers->uc_pll_post_div = + pll_patameters.ucPllPostDiv; + dividers->uc_pll_cntl_flag = + pll_patameters.ucPllCntlFlag; + } + + return result; +} + +int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_ai *dividers) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7 pll_patameters; + int result; + + pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); + pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + (uint32_t *)&pll_patameters); + + if (0 == result) { + dividers->usSclk_fcw_frac = le16_to_cpu(pll_patameters.usSclk_fcw_frac); + dividers->usSclk_fcw_int = le16_to_cpu(pll_patameters.usSclk_fcw_int); + dividers->ucSclkPostDiv = pll_patameters.ucSclkPostDiv; + dividers->ucSclkVcoMode = pll_patameters.ucSclkVcoMode; + dividers->ucSclkPllRange = pll_patameters.ucSclkPllRange; + dividers->ucSscEnable = pll_patameters.ucSscEnable; + dividers->usSsc_fcw1_frac = le16_to_cpu(pll_patameters.usSsc_fcw1_frac); + dividers->usSsc_fcw1_int = le16_to_cpu(pll_patameters.usSsc_fcw1_int); + dividers->usPcc_fcw_int = le16_to_cpu(pll_patameters.usPcc_fcw_int); + dividers->usSsc_fcw_slew_frac = le16_to_cpu(pll_patameters.usSsc_fcw_slew_frac); + dividers->usPcc_fcw_slew_frac = le16_to_cpu(pll_patameters.usPcc_fcw_slew_frac); + } + return result; +} + +int atomctrl_get_dfs_pll_dividers_vi( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_vi *dividers) +{ + struct amdgpu_device *adev = hwmgr->adev; + COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; + int result; + + pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); + pll_patameters.ulClock.ucPostDiv = + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + (uint32_t *)&pll_patameters); + + if (0 == result) { + dividers->pll_post_divider = + pll_patameters.ulClock.ucPostDiv; + dividers->real_clock = + le32_to_cpu(pll_patameters.ulClock.ulClock); + + dividers->ul_fb_div.ul_fb_div_frac = + le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac); + dividers->ul_fb_div.ul_fb_div = + le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv); + + dividers->uc_pll_ref_div = + pll_patameters.ucPllRefDiv; + dividers->uc_pll_post_div = + pll_patameters.ucPllPostDiv; + dividers->uc_pll_cntl_flag = + pll_patameters.ucPllCntlFlag; + } + + return result; +} + +/** + * Get the reference clock in 10KHz + */ +uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) +{ + ATOM_FIRMWARE_INFO *fw_info; + u8 frev, crev; + u16 size; + uint32_t clock; + + fw_info = (ATOM_FIRMWARE_INFO *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if (fw_info == NULL) + clock = 2700; + else + clock = (uint32_t)(le16_to_cpu(fw_info->usReferenceClock)); + + return clock; +} + +/** + * Returns true if the given voltage type is controlled by GPIO pins. + * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, + * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. + * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE + */ +bool atomctrl_is_voltage_controlled_by_gpio_v3( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint8_t voltage_mode) +{ + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); + bool ret; + + PP_ASSERT_WITH_CODE((NULL != voltage_info), + "Could not find Voltage Table in BIOS.", return false;); + + ret = (NULL != atomctrl_lookup_voltage_type_v3 + (voltage_info, voltage_type, voltage_mode)) ? true : false; + + return ret; +} + +int atomctrl_get_voltage_table_v3( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint8_t voltage_mode, + pp_atomctrl_voltage_table *voltage_table) +{ + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); + const ATOM_VOLTAGE_OBJECT_V3 *voltage_object; + unsigned int i; + + PP_ASSERT_WITH_CODE((NULL != voltage_info), + "Could not find Voltage Table in BIOS.", return -1;); + + voltage_object = atomctrl_lookup_voltage_type_v3 + (voltage_info, voltage_type, voltage_mode); + + if (voltage_object == NULL) + return -1; + + PP_ASSERT_WITH_CODE( + (voltage_object->asGpioVoltageObj.ucGpioEntryNum <= + PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES), + "Too many voltage entries!", + return -1; + ); + + for (i = 0; i < voltage_object->asGpioVoltageObj.ucGpioEntryNum; i++) { + voltage_table->entries[i].value = + le16_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].usVoltageValue); + voltage_table->entries[i].smio_low = + le32_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].ulVoltageId); + } + + voltage_table->mask_low = + le32_to_cpu(voltage_object->asGpioVoltageObj.ulGpioMaskVal); + voltage_table->count = + voltage_object->asGpioVoltageObj.ucGpioEntryNum; + voltage_table->phase_delay = + voltage_object->asGpioVoltageObj.ucPhaseDelay; + + return 0; +} + +static bool atomctrl_lookup_gpio_pin( + ATOM_GPIO_PIN_LUT * gpio_lookup_table, + const uint32_t pinId, + pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + unsigned int size = le16_to_cpu(gpio_lookup_table->sHeader.usStructureSize); + unsigned int offset = offsetof(ATOM_GPIO_PIN_LUT, asGPIO_Pin[0]); + uint8_t *start = (uint8_t *)gpio_lookup_table; + + while (offset < size) { + const ATOM_GPIO_PIN_ASSIGNMENT *pin_assignment = + (const ATOM_GPIO_PIN_ASSIGNMENT *)(start + offset); + + if (pinId == pin_assignment->ucGPIO_ID) { + gpio_pin_assignment->uc_gpio_pin_bit_shift = + pin_assignment->ucGpioPinBitShift; + gpio_pin_assignment->us_gpio_pin_aindex = + le16_to_cpu(pin_assignment->usGpioPin_AIndex); + return true; + } + + offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1; + } + + return false; +} + +/** + * Private Function to get the PowerPlay Table Address. + * WARNING: The tabled returned by this function is in + * dynamically allocated memory. + * The caller has to release if by calling kfree. + */ +static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device) +{ + u8 frev, crev; + u16 size; + void *table_address; + + table_address = (ATOM_GPIO_PIN_LUT *) + smu_atom_get_data_table(device, + GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT), + &size, &frev, &crev); + + PP_ASSERT_WITH_CODE((NULL != table_address), + "Error retrieving BIOS Table Address!", return NULL;); + + return (ATOM_GPIO_PIN_LUT *)table_address; +} + +/** + * Returns 1 if the given pin id find in lookup table. + */ +bool atomctrl_get_pp_assign_pin( + struct pp_hwmgr *hwmgr, + const uint32_t pinId, + pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + bool bRet = false; + ATOM_GPIO_PIN_LUT *gpio_lookup_table = + get_gpio_lookup_table(hwmgr->adev); + + PP_ASSERT_WITH_CODE((NULL != gpio_lookup_table), + "Could not find GPIO lookup Table in BIOS.", return false); + + bRet = atomctrl_lookup_gpio_pin(gpio_lookup_table, pinId, + gpio_pin_assignment); + + return bRet; +} + +int atomctrl_calculate_voltage_evv_on_sclk( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint32_t sclk, + uint16_t virtual_voltage_Id, + uint16_t *voltage, + uint16_t dpm_level, + bool debug) +{ + ATOM_ASIC_PROFILING_INFO_V3_4 *getASICProfilingInfo; + struct amdgpu_device *adev = hwmgr->adev; + EFUSE_LINEAR_FUNC_PARAM sRO_fuse; + EFUSE_LINEAR_FUNC_PARAM sCACm_fuse; + EFUSE_LINEAR_FUNC_PARAM sCACb_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKt_Beta_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKv_m_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKv_b_fuse; + EFUSE_INPUT_PARAMETER sInput_FuseValues; + READ_EFUSE_VALUE_PARAMETER sOutput_FuseValues; + + uint32_t ul_RO_fused, ul_CACb_fused, ul_CACm_fused, ul_Kt_Beta_fused, ul_Kv_m_fused, ul_Kv_b_fused; + fInt fSM_A0, fSM_A1, fSM_A2, fSM_A3, fSM_A4, fSM_A5, fSM_A6, fSM_A7; + fInt fMargin_RO_a, fMargin_RO_b, fMargin_RO_c, fMargin_fixed, fMargin_FMAX_mean, fMargin_Plat_mean, fMargin_FMAX_sigma, fMargin_Plat_sigma, fMargin_DC_sigma; + fInt fLkg_FT, repeat; + fInt fMicro_FMAX, fMicro_CR, fSigma_FMAX, fSigma_CR, fSigma_DC, fDC_SCLK, fSquared_Sigma_DC, fSquared_Sigma_CR, fSquared_Sigma_FMAX; + fInt fRLL_LoadLine, fPowerDPMx, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin; + fInt fRO_fused, fCACm_fused, fCACb_fused, fKv_m_fused, fKv_b_fused, fKt_Beta_fused, fFT_Lkg_V0NORM; + fInt fSclk_margin, fSclk, fEVV_V; + fInt fV_min, fV_max, fT_prod, fLKG_Factor, fT_FT, fV_FT, fV_x, fTDP_Power, fTDP_Power_right, fTDP_Power_left, fTDP_Current, fV_NL; + uint32_t ul_FT_Lkg_V0NORM; + fInt fLn_MaxDivMin, fMin, fAverage, fRange; + fInt fRoots[2]; + fInt fStepSize = GetScaledFraction(625, 100000); + + int result; + + getASICProfilingInfo = (ATOM_ASIC_PROFILING_INFO_V3_4 *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), + NULL, NULL, NULL); + + if (!getASICProfilingInfo) + return -1; + + if (getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 || + (getASICProfilingInfo->asHeader.ucTableFormatRevision == 3 && + getASICProfilingInfo->asHeader.ucTableContentRevision < 4)) + return -1; + + /*----------------------------------------------------------- + *GETTING MULTI-STEP PARAMETERS RELATED TO CURRENT DPM LEVEL + *----------------------------------------------------------- + */ + fRLL_LoadLine = Divide(getASICProfilingInfo->ulLoadLineSlop, 1000); + + switch (dpm_level) { + case 1: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm1)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM1), 1000); + break; + case 2: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm2)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM2), 1000); + break; + case 3: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm3)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM3), 1000); + break; + case 4: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm4)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM4), 1000); + break; + case 5: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm5)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM5), 1000); + break; + case 6: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm6)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM6), 1000); + break; + case 7: + fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm7)); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM7), 1000); + break; + default: + pr_err("DPM Level not supported\n"); + fPowerDPMx = Convert_ULONG_ToFraction(1); + fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM0), 1000); + } + + /*------------------------- + * DECODING FUSE VALUES + * ------------------------ + */ + /*Decode RO_Fused*/ + sRO_fuse = getASICProfilingInfo->sRoFuse; + + sInput_FuseValues.usEfuseIndex = sRO_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sRO_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sRO_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + /* Finally, the actual fuse value */ + ul_RO_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fMin = GetScaledFraction(le32_to_cpu(sRO_fuse.ulEfuseMin), 1); + fRange = GetScaledFraction(le32_to_cpu(sRO_fuse.ulEfuseEncodeRange), 1); + fRO_fused = fDecodeLinearFuse(ul_RO_fused, fMin, fRange, sRO_fuse.ucEfuseLength); + + sCACm_fuse = getASICProfilingInfo->sCACm; + + sInput_FuseValues.usEfuseIndex = sCACm_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sCACm_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sCACm_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + ul_CACm_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fMin = GetScaledFraction(le32_to_cpu(sCACm_fuse.ulEfuseMin), 1000); + fRange = GetScaledFraction(le32_to_cpu(sCACm_fuse.ulEfuseEncodeRange), 1000); + + fCACm_fused = fDecodeLinearFuse(ul_CACm_fused, fMin, fRange, sCACm_fuse.ucEfuseLength); + + sCACb_fuse = getASICProfilingInfo->sCACb; + + sInput_FuseValues.usEfuseIndex = sCACb_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sCACb_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sCACb_fuse.ucEfuseLength; + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + ul_CACb_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fMin = GetScaledFraction(le32_to_cpu(sCACb_fuse.ulEfuseMin), 1000); + fRange = GetScaledFraction(le32_to_cpu(sCACb_fuse.ulEfuseEncodeRange), 1000); + + fCACb_fused = fDecodeLinearFuse(ul_CACb_fused, fMin, fRange, sCACb_fuse.ucEfuseLength); + + sKt_Beta_fuse = getASICProfilingInfo->sKt_b; + + sInput_FuseValues.usEfuseIndex = sKt_Beta_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKt_Beta_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKt_Beta_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + ul_Kt_Beta_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fAverage = GetScaledFraction(le32_to_cpu(sKt_Beta_fuse.ulEfuseEncodeAverage), 1000); + fRange = GetScaledFraction(le32_to_cpu(sKt_Beta_fuse.ulEfuseEncodeRange), 1000); + + fKt_Beta_fused = fDecodeLogisticFuse(ul_Kt_Beta_fused, + fAverage, fRange, sKt_Beta_fuse.ucEfuseLength); + + sKv_m_fuse = getASICProfilingInfo->sKv_m; + + sInput_FuseValues.usEfuseIndex = sKv_m_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKv_m_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKv_m_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + if (result) + return result; + + ul_Kv_m_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fAverage = GetScaledFraction(le32_to_cpu(sKv_m_fuse.ulEfuseEncodeAverage), 1000); + fRange = GetScaledFraction((le32_to_cpu(sKv_m_fuse.ulEfuseEncodeRange) & 0x7fffffff), 1000); + fRange = fMultiply(fRange, ConvertToFraction(-1)); + + fKv_m_fused = fDecodeLogisticFuse(ul_Kv_m_fused, + fAverage, fRange, sKv_m_fuse.ucEfuseLength); + + sKv_b_fuse = getASICProfilingInfo->sKv_b; + + sInput_FuseValues.usEfuseIndex = sKv_b_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKv_b_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKv_b_fuse.ucEfuseLength; + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + ul_Kv_b_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fAverage = GetScaledFraction(le32_to_cpu(sKv_b_fuse.ulEfuseEncodeAverage), 1000); + fRange = GetScaledFraction(le32_to_cpu(sKv_b_fuse.ulEfuseEncodeRange), 1000); + + fKv_b_fused = fDecodeLogisticFuse(ul_Kv_b_fused, + fAverage, fRange, sKv_b_fuse.ucEfuseLength); + + /* Decoding the Leakage - No special struct container */ + /* + * usLkgEuseIndex=56 + * ucLkgEfuseBitLSB=6 + * ucLkgEfuseLength=10 + * ulLkgEncodeLn_MaxDivMin=69077 + * ulLkgEncodeMax=1000000 + * ulLkgEncodeMin=1000 + * ulEfuseLogisticAlpha=13 + */ + + sInput_FuseValues.usEfuseIndex = getASICProfilingInfo->usLkgEuseIndex; + sInput_FuseValues.ucBitShift = getASICProfilingInfo->ucLkgEfuseBitLSB; + sInput_FuseValues.ucBitLength = getASICProfilingInfo->ucLkgEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&sOutput_FuseValues); + + if (result) + return result; + + ul_FT_Lkg_V0NORM = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); + fLn_MaxDivMin = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLkgEncodeLn_MaxDivMin), 10000); + fMin = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLkgEncodeMin), 10000); + + fFT_Lkg_V0NORM = fDecodeLeakageID(ul_FT_Lkg_V0NORM, + fLn_MaxDivMin, fMin, getASICProfilingInfo->ucLkgEfuseLength); + fLkg_FT = fFT_Lkg_V0NORM; + + /*------------------------------------------- + * PART 2 - Grabbing all required values + *------------------------------------------- + */ + fSM_A0 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A0), 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A0_sign))); + fSM_A1 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A1), 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A1_sign))); + fSM_A2 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A2), 100000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A2_sign))); + fSM_A3 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A3), 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A3_sign))); + fSM_A4 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A4), 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A4_sign))); + fSM_A5 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A5), 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A5_sign))); + fSM_A6 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A6), 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A6_sign))); + fSM_A7 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A7), 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A7_sign))); + + fMargin_RO_a = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_a)); + fMargin_RO_b = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_b)); + fMargin_RO_c = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_c)); + + fMargin_fixed = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_fixed)); + + fMargin_FMAX_mean = GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMargin_Fmax_mean), 10000); + fMargin_Plat_mean = GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMargin_plat_mean), 10000); + fMargin_FMAX_sigma = GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMargin_Fmax_sigma), 10000); + fMargin_Plat_sigma = GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMargin_plat_sigma), 10000); + + fMargin_DC_sigma = GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMargin_DC_sigma), 100); + fMargin_DC_sigma = fDivide(fMargin_DC_sigma, ConvertToFraction(1000)); + + fCACm_fused = fDivide(fCACm_fused, ConvertToFraction(100)); + fCACb_fused = fDivide(fCACb_fused, ConvertToFraction(100)); + fKt_Beta_fused = fDivide(fKt_Beta_fused, ConvertToFraction(100)); + fKv_m_fused = fNegate(fDivide(fKv_m_fused, ConvertToFraction(100))); + fKv_b_fused = fDivide(fKv_b_fused, ConvertToFraction(10)); + + fSclk = GetScaledFraction(sclk, 100); + + fV_max = fDivide(GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMaxVddc), 1000), ConvertToFraction(4)); + fT_prod = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulBoardCoreTemp), 10); + fLKG_Factor = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulEvvLkgFactor), 100); + fT_FT = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLeakageTemp), 10); + fV_FT = fDivide(GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulLeakageVoltage), 1000), ConvertToFraction(4)); + fV_min = fDivide(GetScaledFraction( + le32_to_cpu(getASICProfilingInfo->ulMinVddc), 1000), ConvertToFraction(4)); + + /*----------------------- + * PART 3 + *----------------------- + */ + + fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4, fSclk), fSM_A5)); + fB_Term = fAdd(fAdd(fMultiply(fSM_A2, fSclk), fSM_A6), fMargin_RO_b); + fC_Term = fAdd(fMargin_RO_c, + fAdd(fMultiply(fSM_A0, fLkg_FT), + fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT, fSclk)), + fAdd(fMultiply(fSM_A3, fSclk), + fSubtract(fSM_A7, fRO_fused))))); + + fVDDC_base = fSubtract(fRO_fused, + fSubtract(fMargin_RO_c, + fSubtract(fSM_A3, fMultiply(fSM_A1, fSclk)))); + fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0, fSclk), fSM_A2)); + + repeat = fSubtract(fVDDC_base, + fDivide(fMargin_DC_sigma, ConvertToFraction(1000))); + + fRO_DC_margin = fAdd(fMultiply(fMargin_RO_a, + fGetSquare(repeat)), + fAdd(fMultiply(fMargin_RO_b, repeat), + fMargin_RO_c)); + + fDC_SCLK = fSubtract(fRO_fused, + fSubtract(fRO_DC_margin, + fSubtract(fSM_A3, + fMultiply(fSM_A2, repeat)))); + fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0, repeat), fSM_A1)); + + fSigma_DC = fSubtract(fSclk, fDC_SCLK); + + fMicro_FMAX = fMultiply(fSclk, fMargin_FMAX_mean); + fMicro_CR = fMultiply(fSclk, fMargin_Plat_mean); + fSigma_FMAX = fMultiply(fSclk, fMargin_FMAX_sigma); + fSigma_CR = fMultiply(fSclk, fMargin_Plat_sigma); + + fSquared_Sigma_DC = fGetSquare(fSigma_DC); + fSquared_Sigma_CR = fGetSquare(fSigma_CR); + fSquared_Sigma_FMAX = fGetSquare(fSigma_FMAX); + + fSclk_margin = fAdd(fMicro_FMAX, + fAdd(fMicro_CR, + fAdd(fMargin_fixed, + fSqrt(fAdd(fSquared_Sigma_FMAX, + fAdd(fSquared_Sigma_DC, fSquared_Sigma_CR)))))); + /* + fA_Term = fSM_A4 * (fSclk + fSclk_margin) + fSM_A5; + fB_Term = fSM_A2 * (fSclk + fSclk_margin) + fSM_A6; + fC_Term = fRO_DC_margin + fSM_A0 * fLkg_FT + fSM_A1 * fLkg_FT * (fSclk + fSclk_margin) + fSM_A3 * (fSclk + fSclk_margin) + fSM_A7 - fRO_fused; + */ + + fA_Term = fAdd(fMultiply(fSM_A4, fAdd(fSclk, fSclk_margin)), fSM_A5); + fB_Term = fAdd(fMultiply(fSM_A2, fAdd(fSclk, fSclk_margin)), fSM_A6); + fC_Term = fAdd(fRO_DC_margin, + fAdd(fMultiply(fSM_A0, fLkg_FT), + fAdd(fMultiply(fMultiply(fSM_A1, fLkg_FT), + fAdd(fSclk, fSclk_margin)), + fAdd(fMultiply(fSM_A3, + fAdd(fSclk, fSclk_margin)), + fSubtract(fSM_A7, fRO_fused))))); + + SolveQuadracticEqn(fA_Term, fB_Term, fC_Term, fRoots); + + if (GreaterThan(fRoots[0], fRoots[1])) + fEVV_V = fRoots[1]; + else + fEVV_V = fRoots[0]; + + if (GreaterThan(fV_min, fEVV_V)) + fEVV_V = fV_min; + else if (GreaterThan(fEVV_V, fV_max)) + fEVV_V = fSubtract(fV_max, fStepSize); + + fEVV_V = fRoundUpByStepSize(fEVV_V, fStepSize, 0); + + /*----------------- + * PART 4 + *----------------- + */ + + fV_x = fV_min; + + while (GreaterThan(fAdd(fV_max, fStepSize), fV_x)) { + fTDP_Power_left = fMultiply(fMultiply(fMultiply(fAdd( + fMultiply(fCACm_fused, fV_x), fCACb_fused), fSclk), + fGetSquare(fV_x)), fDerateTDP); + + fTDP_Power_right = fMultiply(fFT_Lkg_V0NORM, fMultiply(fLKG_Factor, + fMultiply(fExponential(fMultiply(fAdd(fMultiply(fKv_m_fused, + fT_prod), fKv_b_fused), fV_x)), fV_x))); + fTDP_Power_right = fMultiply(fTDP_Power_right, fExponential(fMultiply( + fKt_Beta_fused, fT_prod))); + fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( + fAdd(fMultiply(fKv_m_fused, fT_prod), fKv_b_fused), fV_FT))); + fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( + fKt_Beta_fused, fT_FT))); + + fTDP_Power = fAdd(fTDP_Power_left, fTDP_Power_right); + + fTDP_Current = fDivide(fTDP_Power, fV_x); + + fV_NL = fAdd(fV_x, fDivide(fMultiply(fTDP_Current, fRLL_LoadLine), + ConvertToFraction(10))); + + fV_NL = fRoundUpByStepSize(fV_NL, fStepSize, 0); + + if (GreaterThan(fV_max, fV_NL) && + (GreaterThan(fV_NL, fEVV_V) || + Equal(fV_NL, fEVV_V))) { + fV_NL = fMultiply(fV_NL, ConvertToFraction(1000)); + + *voltage = (uint16_t)fV_NL.partial.real; + break; + } else + fV_x = fAdd(fV_x, fStepSize); + } + + return result; +} + +/** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table. + * @param hwmgr input: pointer to hwManager + * @param voltage_type input: type of EVV voltage VDDC or VDDGFX + * @param sclk input: in 10Khz unit. DPM state SCLK frequency + * which is define in PPTable SCLK/VDDC dependence + * table associated with this virtual_voltage_Id + * @param virtual_voltage_Id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 + * @param voltage output: real voltage level in unit of mv + */ +int atomctrl_get_voltage_evv_on_sclk( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, + uint16_t *voltage) +{ + struct amdgpu_device *adev = hwmgr->adev; + GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space; + int result; + + get_voltage_info_param_space.ucVoltageType = + voltage_type; + get_voltage_info_param_space.ucVoltageMode = + ATOM_GET_VOLTAGE_EVV_VOLTAGE; + get_voltage_info_param_space.usVoltageLevel = + cpu_to_le16(virtual_voltage_Id); + get_voltage_info_param_space.ulSCLKFreq = + cpu_to_le32(sclk); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), + (uint32_t *)&get_voltage_info_param_space); + + *voltage = result ? 0 : + le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *) + (&get_voltage_info_param_space))->usVoltageLevel); + + return result; +} + +/** + * atomctrl_get_voltage_evv gets voltage via call to ATOM COMMAND table. + * @param hwmgr input: pointer to hwManager + * @param virtual_voltage_id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 + * @param voltage output: real voltage level in unit of mv + */ +int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, + uint16_t virtual_voltage_id, + uint16_t *voltage) +{ + struct amdgpu_device *adev = hwmgr->adev; + GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space; + int result; + int entry_id; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ + for (entry_id = 0; entry_id < hwmgr->dyn_state.vddc_dependency_on_sclk->count; entry_id++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].v == virtual_voltage_id) { + /* found */ + break; + } + } + + if (entry_id >= hwmgr->dyn_state.vddc_dependency_on_sclk->count) { + pr_debug("Can't find requested voltage id in vddc_dependency_on_sclk table!\n"); + return -EINVAL; + } + + get_voltage_info_param_space.ucVoltageType = VOLTAGE_TYPE_VDDC; + get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; + get_voltage_info_param_space.usVoltageLevel = virtual_voltage_id; + get_voltage_info_param_space.ulSCLKFreq = + cpu_to_le32(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].clk); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), + (uint32_t *)&get_voltage_info_param_space); + + if (0 != result) + return result; + + *voltage = le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *) + (&get_voltage_info_param_space))->usVoltageLevel); + + return result; +} + +/** + * Get the mpll reference clock in 10KHz + */ +uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr) +{ + ATOM_COMMON_TABLE_HEADER *fw_info; + uint32_t clock; + u8 frev, crev; + u16 size; + + fw_info = (ATOM_COMMON_TABLE_HEADER *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if (fw_info == NULL) + clock = 2700; + else { + if ((fw_info->ucTableFormatRevision == 2) && + (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) { + ATOM_FIRMWARE_INFO_V2_1 *fwInfo_2_1 = + (ATOM_FIRMWARE_INFO_V2_1 *)fw_info; + clock = (uint32_t)(le16_to_cpu(fwInfo_2_1->usMemoryReferenceClock)); + } else { + ATOM_FIRMWARE_INFO *fwInfo_0_0 = + (ATOM_FIRMWARE_INFO *)fw_info; + clock = (uint32_t)(le16_to_cpu(fwInfo_0_0->usReferenceClock)); + } + } + + return clock; +} + +/** + * Get the asic internal spread spectrum table + */ +static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device) +{ + ATOM_ASIC_INTERNAL_SS_INFO *table = NULL; + u8 frev, crev; + u16 size; + + table = (ATOM_ASIC_INTERNAL_SS_INFO *) + smu_atom_get_data_table(device, + GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info), + &size, &frev, &crev); + + return table; +} + +/** + * Get the asic internal spread spectrum assignment + */ +static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr, + const uint8_t clockSource, + const uint32_t clockSpeed, + pp_atomctrl_internal_ss_info *ssEntry) +{ + ATOM_ASIC_INTERNAL_SS_INFO *table; + ATOM_ASIC_SS_ASSIGNMENT *ssInfo; + int entry_found = 0; + + memset(ssEntry, 0x00, sizeof(pp_atomctrl_internal_ss_info)); + + table = asic_internal_ss_get_ss_table(hwmgr->adev); + + if (NULL == table) + return -1; + + ssInfo = &table->asSpreadSpectrum[0]; + + while (((uint8_t *)ssInfo - (uint8_t *)table) < + le16_to_cpu(table->sHeader.usStructureSize)) { + if ((clockSource == ssInfo->ucClockIndication) && + ((uint32_t)clockSpeed <= le32_to_cpu(ssInfo->ulTargetClockRange))) { + entry_found = 1; + break; + } + + ssInfo = (ATOM_ASIC_SS_ASSIGNMENT *)((uint8_t *)ssInfo + + sizeof(ATOM_ASIC_SS_ASSIGNMENT)); + } + + if (entry_found) { + ssEntry->speed_spectrum_percentage = + le16_to_cpu(ssInfo->usSpreadSpectrumPercentage); + ssEntry->speed_spectrum_rate = le16_to_cpu(ssInfo->usSpreadRateInKhz); + + if (((GET_DATA_TABLE_MAJOR_REVISION(table) == 2) && + (GET_DATA_TABLE_MINOR_REVISION(table) >= 2)) || + (GET_DATA_TABLE_MAJOR_REVISION(table) == 3)) { + ssEntry->speed_spectrum_rate /= 100; + } + + switch (ssInfo->ucSpreadSpectrumMode) { + case 0: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_down; + break; + case 1: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_center; + break; + default: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_down; + break; + } + } + + return entry_found ? 0 : 1; +} + +/** + * Get the memory clock spread spectrum info + */ +int atomctrl_get_memory_clock_spread_spectrum( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + pp_atomctrl_internal_ss_info *ssInfo) +{ + return asic_internal_ss_get_ss_asignment(hwmgr, + ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo); +} +/** + * Get the engine clock spread spectrum info + */ +int atomctrl_get_engine_clock_spread_spectrum( + struct pp_hwmgr *hwmgr, + const uint32_t engine_clock, + pp_atomctrl_internal_ss_info *ssInfo) +{ + return asic_internal_ss_get_ss_asignment(hwmgr, + ASIC_INTERNAL_ENGINE_SS, engine_clock, ssInfo); +} + +int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, + uint16_t end_index, uint32_t mask, uint32_t *efuse) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + READ_EFUSE_VALUE_PARAMETER efuse_param; + + efuse_param.sEfuse.usEfuseIndex = cpu_to_le16((start_index / 32) * 4); + efuse_param.sEfuse.ucBitShift = (uint8_t) + (start_index - ((start_index / 32) * 32)); + efuse_param.sEfuse.ucBitLength = (uint8_t) + ((end_index - start_index) + 1); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + (uint32_t *)&efuse_param); + *efuse = result ? 0 : le32_to_cpu(efuse_param.ulEfuseValue) & mask; + + return result; +} + +int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock, + uint8_t level) +{ + struct amdgpu_device *adev = hwmgr->adev; + DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1 memory_clock_parameters; + int result; + + memory_clock_parameters.asDPMMCReg.ulClock.ulClockFreq = + memory_clock & SET_CLOCK_FREQ_MASK; + memory_clock_parameters.asDPMMCReg.ulClock.ulComputeClockFlag = + ADJUST_MC_SETTING_PARAM; + memory_clock_parameters.asDPMMCReg.ucMclkDPMState = level; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings), + (uint32_t *)&memory_clock_parameters); + + return result; +} + +int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3 get_voltage_info_param_space; + + get_voltage_info_param_space.ucVoltageType = voltage_type; + get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; + get_voltage_info_param_space.usVoltageLevel = cpu_to_le16(virtual_voltage_Id); + get_voltage_info_param_space.ulSCLKFreq = cpu_to_le32(sclk); + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), + (uint32_t *)&get_voltage_info_param_space); + + *voltage = result ? 0 : + le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel); + + return result; +} + +int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table) +{ + + int i; + u8 frev, crev; + u16 size; + + ATOM_SMU_INFO_V2_1 *psmu_info = + (ATOM_SMU_INFO_V2_1 *)smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, SMU_Info), + &size, &frev, &crev); + + + for (i = 0; i < psmu_info->ucSclkEntryNum; i++) { + table->entry[i].ucVco_setting = psmu_info->asSclkFcwRangeEntry[i].ucVco_setting; + table->entry[i].ucPostdiv = psmu_info->asSclkFcwRangeEntry[i].ucPostdiv; + table->entry[i].usFcw_pcc = + le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_pcc); + table->entry[i].usFcw_trans_upper = + le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_trans_upper); + table->entry[i].usRcw_trans_lower = + le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucRcw_trans_lower); + } + + return 0; +} + +int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, + struct pp_atom_ctrl__avfs_parameters *param) +{ + ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL; + + if (param == NULL) + return -EINVAL; + + profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *) + smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), + NULL, NULL, NULL); + if (!profile) + return -1; + + param->ulAVFS_meanNsigma_Acontant0 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant0); + param->ulAVFS_meanNsigma_Acontant1 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant1); + param->ulAVFS_meanNsigma_Acontant2 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant2); + param->usAVFS_meanNsigma_DC_tol_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_DC_tol_sigma); + param->usAVFS_meanNsigma_Platform_mean = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_mean); + param->usAVFS_meanNsigma_Platform_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_sigma); + param->ulGB_VDROOP_TABLE_CKSOFF_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a0); + param->ulGB_VDROOP_TABLE_CKSOFF_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a1); + param->ulGB_VDROOP_TABLE_CKSOFF_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a2); + param->ulGB_VDROOP_TABLE_CKSON_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a0); + param->ulGB_VDROOP_TABLE_CKSON_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a1); + param->ulGB_VDROOP_TABLE_CKSON_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a2); + param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1); + param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2); + param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b); + param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_m1); + param->usAVFSGB_FUSE_TABLE_CKSON_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSON_m2); + param->ulAVFSGB_FUSE_TABLE_CKSON_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_b); + param->usMaxVoltage_0_25mv = le16_to_cpu(profile->usMaxVoltage_0_25mv); + param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF; + param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON; + param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF; + param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON; + param->usPSM_Age_ComFactor = le16_to_cpu(profile->usPSM_Age_ComFactor); + param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage; + + return 0; +} + +int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint8_t *svd_gpio_id, uint8_t *svc_gpio_id, + uint16_t *load_line) +{ + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); + + const ATOM_VOLTAGE_OBJECT_V3 *voltage_object; + + PP_ASSERT_WITH_CODE((NULL != voltage_info), + "Could not find Voltage Table in BIOS.", return -EINVAL); + + voltage_object = atomctrl_lookup_voltage_type_v3 + (voltage_info, voltage_type, VOLTAGE_OBJ_SVID2); + + *svd_gpio_id = voltage_object->asSVID2Obj.ucSVDGpioId; + *svc_gpio_id = voltage_object->asSVID2Obj.ucSVCGpioId; + *load_line = voltage_object->asSVID2Obj.usLoadLine_PSI; + + return 0; +} + +int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id) +{ + struct amdgpu_device *adev = hwmgr->adev; + SET_VOLTAGE_PS_ALLOCATION allocation; + SET_VOLTAGE_PARAMETERS_V1_3 *voltage_parameters = + (SET_VOLTAGE_PARAMETERS_V1_3 *)&allocation.sASICSetVoltage; + int result; + + voltage_parameters->ucVoltageMode = ATOM_GET_LEAKAGE_ID; + + result = amdgpu_atom_execute_table(adev->mode_info.atom_context, + GetIndexIntoMasterTable(COMMAND, SetVoltage), + (uint32_t *)voltage_parameters); + + *virtual_voltage_id = voltage_parameters->usVoltageLevel; + + return result; +} + +int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, + uint16_t *vddc, uint16_t *vddci, + uint16_t virtual_voltage_id, + uint16_t efuse_voltage_id) +{ + int i, j; + int ix; + u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf; + ATOM_ASIC_PROFILING_INFO_V2_1 *profile; + + *vddc = 0; + *vddci = 0; + + ix = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo); + + profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *) + smu_atom_get_data_table(hwmgr->adev, + ix, + NULL, NULL, NULL); + if (!profile) + return -EINVAL; + + if ((profile->asHeader.ucTableFormatRevision >= 2) && + (profile->asHeader.ucTableContentRevision >= 1) && + (profile->asHeader.usStructureSize >= sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))) { + leakage_bin = (u16 *)((char *)profile + profile->usLeakageBinArrayOffset); + vddc_id_buf = (u16 *)((char *)profile + profile->usElbVDDC_IdArrayOffset); + vddc_buf = (u16 *)((char *)profile + profile->usElbVDDC_LevelArrayOffset); + if (profile->ucElbVDDC_Num > 0) { + for (i = 0; i < profile->ucElbVDDC_Num; i++) { + if (vddc_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { + if (efuse_voltage_id <= leakage_bin[j]) { + *vddc = vddc_buf[j * profile->ucElbVDDC_Num + i]; + break; + } + } + break; + } + } + } + + vddci_id_buf = (u16 *)((char *)profile + profile->usElbVDDCI_IdArrayOffset); + vddci_buf = (u16 *)((char *)profile + profile->usElbVDDCI_LevelArrayOffset); + if (profile->ucElbVDDCI_Num > 0) { + for (i = 0; i < profile->ucElbVDDCI_Num; i++) { + if (vddci_id_buf[i] == virtual_voltage_id) { + for (j = 0; j < profile->ucLeakageBinNum; j++) { + if (efuse_voltage_id <= leakage_bin[j]) { + *vddci = vddci_buf[j * profile->ucElbVDDCI_Num + i]; + break; + } + } + break; + } + } + } + } + + return 0; +} + +void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, + uint32_t *min_vddc) +{ + void *profile; + + profile = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), + NULL, NULL, NULL); + + if (profile) { + switch (hwmgr->chip_id) { + case CHIP_TONGA: + case CHIP_FIJI: + *max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMaxVddc) / 4; + *min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMinVddc) / 4; + return; + case CHIP_POLARIS11: + case CHIP_POLARIS10: + case CHIP_POLARIS12: + *max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMaxVddc) / 100; + *min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMinVddc) / 100; + return; + default: + break; + } + } + *max_vddc = 0; + *min_vddc = 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h new file mode 100644 index 000000000000..76ed2e413594 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomctrl.h @@ -0,0 +1,328 @@ +/* + * Copyright 2015 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 PP_ATOMVOLTAGECTRL_H +#define PP_ATOMVOLTAGECTRL_H + +#include "hwmgr.h" + +/* As returned from PowerConnectorDetectionTable. */ +#define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80 +#define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40 +#define PP_ATOM_POWER_BUDGET_SHOW_WAIVER 0x20 +#define PP_ATOM_POWER_POWER_BUDGET_BEHAVIOUR 0x0F + +/* New functions for Evergreen and beyond. */ +#define PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES 32 + +struct pp_atomctrl_clock_dividers { + uint32_t pll_post_divider; + uint32_t pll_feedback_divider; + uint32_t pll_ref_divider; + bool enable_post_divider; +}; + +typedef struct pp_atomctrl_clock_dividers pp_atomctrl_clock_dividers; + +union pp_atomctrl_tcipll_fb_divider { + struct { + uint32_t ul_fb_div_frac : 14; + uint32_t ul_fb_div : 12; + uint32_t un_used : 6; + }; + uint32_t ul_fb_divider; +}; + +typedef union pp_atomctrl_tcipll_fb_divider pp_atomctrl_tcipll_fb_divider; + +struct pp_atomctrl_clock_dividers_rv730 { + uint32_t pll_post_divider; + pp_atomctrl_tcipll_fb_divider mpll_feedback_divider; + uint32_t pll_ref_divider; + bool enable_post_divider; + bool enable_dithen; + uint32_t vco_mode; +}; +typedef struct pp_atomctrl_clock_dividers_rv730 pp_atomctrl_clock_dividers_rv730; + + +struct pp_atomctrl_clock_dividers_kong { + uint32_t pll_post_divider; + uint32_t real_clock; +}; +typedef struct pp_atomctrl_clock_dividers_kong pp_atomctrl_clock_dividers_kong; + +struct pp_atomctrl_clock_dividers_ci { + uint32_t pll_post_divider; /* post divider value */ + uint32_t real_clock; + pp_atomctrl_tcipll_fb_divider ul_fb_div; /* Output Parameter: PLL FB divider */ + uint8_t uc_pll_ref_div; /* Output Parameter: PLL ref divider */ + uint8_t uc_pll_post_div; /* Output Parameter: PLL post divider */ + uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ +}; +typedef struct pp_atomctrl_clock_dividers_ci pp_atomctrl_clock_dividers_ci; + +struct pp_atomctrl_clock_dividers_vi { + uint32_t pll_post_divider; /* post divider value */ + uint32_t real_clock; + pp_atomctrl_tcipll_fb_divider ul_fb_div; /*Output Parameter: PLL FB divider */ + uint8_t uc_pll_ref_div; /*Output Parameter: PLL ref divider */ + uint8_t uc_pll_post_div; /*Output Parameter: PLL post divider */ + uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ +}; +typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi; + +struct pp_atomctrl_clock_dividers_ai { + u16 usSclk_fcw_frac; + u16 usSclk_fcw_int; + u8 ucSclkPostDiv; + u8 ucSclkVcoMode; + u8 ucSclkPllRange; + u8 ucSscEnable; + u16 usSsc_fcw1_frac; + u16 usSsc_fcw1_int; + u16 usReserved; + u16 usPcc_fcw_int; + u16 usSsc_fcw_slew_frac; + u16 usPcc_fcw_slew_frac; +}; +typedef struct pp_atomctrl_clock_dividers_ai pp_atomctrl_clock_dividers_ai; + + +union pp_atomctrl_s_mpll_fb_divider { + struct { + uint32_t cl_kf : 12; + uint32_t clk_frac : 12; + uint32_t un_used : 8; + }; + uint32_t ul_fb_divider; +}; +typedef union pp_atomctrl_s_mpll_fb_divider pp_atomctrl_s_mpll_fb_divider; + +enum pp_atomctrl_spread_spectrum_mode { + pp_atomctrl_spread_spectrum_mode_down = 0, + pp_atomctrl_spread_spectrum_mode_center +}; +typedef enum pp_atomctrl_spread_spectrum_mode pp_atomctrl_spread_spectrum_mode; + +struct pp_atomctrl_memory_clock_param { + pp_atomctrl_s_mpll_fb_divider mpll_fb_divider; + uint32_t mpll_post_divider; + uint32_t bw_ctrl; + uint32_t dll_speed; + uint32_t vco_mode; + uint32_t yclk_sel; + uint32_t qdr; + uint32_t half_rate; +}; +typedef struct pp_atomctrl_memory_clock_param pp_atomctrl_memory_clock_param; + +struct pp_atomctrl_memory_clock_param_ai { + uint32_t ulClock; + uint32_t ulPostDiv; + uint16_t ulMclk_fcw_frac; + uint16_t ulMclk_fcw_int; +}; +typedef struct pp_atomctrl_memory_clock_param_ai pp_atomctrl_memory_clock_param_ai; + +struct pp_atomctrl_internal_ss_info { + uint32_t speed_spectrum_percentage; /* in 1/100 percentage */ + uint32_t speed_spectrum_rate; /* in KHz */ + pp_atomctrl_spread_spectrum_mode speed_spectrum_mode; +}; +typedef struct pp_atomctrl_internal_ss_info pp_atomctrl_internal_ss_info; + +#ifndef NUMBER_OF_M3ARB_PARAMS +#define NUMBER_OF_M3ARB_PARAMS 3 +#endif + +#ifndef NUMBER_OF_M3ARB_PARAM_SETS +#define NUMBER_OF_M3ARB_PARAM_SETS 10 +#endif + +struct pp_atomctrl_kong_system_info { + uint32_t ul_bootup_uma_clock; /* in 10kHz unit */ + uint16_t us_max_nb_voltage; /* high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ + uint16_t us_min_nb_voltage; /* low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ + uint16_t us_bootup_nb_voltage; /* boot up NB voltage */ + uint8_t uc_htc_tmp_lmt; /* bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD */ + uint8_t uc_tj_offset; /* bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD */ + /* 0: default 1: uvd 2: fs-3d */ + uint32_t ul_csr_m3_srb_cntl[NUMBER_OF_M3ARB_PARAM_SETS][NUMBER_OF_M3ARB_PARAMS];/* arrays with values for CSR M3 arbiter for default */ +}; +typedef struct pp_atomctrl_kong_system_info pp_atomctrl_kong_system_info; + +struct pp_atomctrl_memory_info { + uint8_t memory_vendor; + uint8_t memory_type; +}; +typedef struct pp_atomctrl_memory_info pp_atomctrl_memory_info; + +#define MAX_AC_TIMING_ENTRIES 16 + +struct pp_atomctrl_memory_clock_range_table { + uint8_t num_entries; + uint8_t rsv[3]; + + uint32_t mclk[MAX_AC_TIMING_ENTRIES]; +}; +typedef struct pp_atomctrl_memory_clock_range_table pp_atomctrl_memory_clock_range_table; + +struct pp_atomctrl_voltage_table_entry { + uint16_t value; + uint32_t smio_low; +}; + +typedef struct pp_atomctrl_voltage_table_entry pp_atomctrl_voltage_table_entry; + +struct pp_atomctrl_voltage_table { + uint32_t count; + uint32_t mask_low; + uint32_t phase_delay; /* Used for ATOM_GPIO_VOLTAGE_OBJECT_V3 and later */ + pp_atomctrl_voltage_table_entry entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES]; +}; + +typedef struct pp_atomctrl_voltage_table pp_atomctrl_voltage_table; + +#define VBIOS_MC_REGISTER_ARRAY_SIZE 32 +#define VBIOS_MAX_AC_TIMING_ENTRIES 20 + +struct pp_atomctrl_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct pp_atomctrl_mc_reg_entry pp_atomctrl_mc_reg_entry; + +struct pp_atomctrl_mc_register_address { + uint16_t s1; + uint8_t uc_pre_reg_data; +}; + +typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address; + +#define MAX_SCLK_RANGE 8 + +struct pp_atom_ctrl_sclk_range_table_entry{ + uint8_t ucVco_setting; + uint8_t ucPostdiv; + uint16_t usFcw_pcc; + uint16_t usFcw_trans_upper; + uint16_t usRcw_trans_lower; +}; + + +struct pp_atom_ctrl_sclk_range_table{ + struct pp_atom_ctrl_sclk_range_table_entry entry[MAX_SCLK_RANGE]; +}; + +struct pp_atomctrl_mc_reg_table { + uint8_t last; /* number of registers */ + uint8_t num_entries; /* number of AC timing entries */ + pp_atomctrl_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES]; + pp_atomctrl_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct pp_atomctrl_mc_reg_table pp_atomctrl_mc_reg_table; + +struct pp_atomctrl_gpio_pin_assignment { + uint16_t us_gpio_pin_aindex; + uint8_t uc_gpio_pin_bit_shift; +}; +typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment; + +struct pp_atom_ctrl__avfs_parameters { + uint32_t ulAVFS_meanNsigma_Acontant0; + uint32_t ulAVFS_meanNsigma_Acontant1; + uint32_t ulAVFS_meanNsigma_Acontant2; + uint16_t usAVFS_meanNsigma_DC_tol_sigma; + uint16_t usAVFS_meanNsigma_Platform_mean; + uint16_t usAVFS_meanNsigma_Platform_sigma; + uint32_t ulGB_VDROOP_TABLE_CKSOFF_a0; + uint32_t ulGB_VDROOP_TABLE_CKSOFF_a1; + uint32_t ulGB_VDROOP_TABLE_CKSOFF_a2; + uint32_t ulGB_VDROOP_TABLE_CKSON_a0; + uint32_t ulGB_VDROOP_TABLE_CKSON_a1; + uint32_t ulGB_VDROOP_TABLE_CKSON_a2; + uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_m1; + uint16_t usAVFSGB_FUSE_TABLE_CKSOFF_m2; + uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_b; + uint32_t ulAVFSGB_FUSE_TABLE_CKSON_m1; + uint16_t usAVFSGB_FUSE_TABLE_CKSON_m2; + uint32_t ulAVFSGB_FUSE_TABLE_CKSON_b; + uint16_t usMaxVoltage_0_25mv; + uint8_t ucEnableGB_VDROOP_TABLE_CKSOFF; + uint8_t ucEnableGB_VDROOP_TABLE_CKSON; + uint8_t ucEnableGB_FUSE_TABLE_CKSOFF; + uint8_t ucEnableGB_FUSE_TABLE_CKSON; + uint16_t usPSM_Age_ComFactor; + uint8_t ucEnableApplyAVFS_CKS_OFF_Voltage; + uint8_t ucReserved; +}; + +extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); +extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); +extern int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, uint16_t *voltage); +extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr); +extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo); +extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo); +extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table); +extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock); +extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr); +extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode); +extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); +extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); +extern bool atomctrl_is_voltage_controlled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode); +extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table); +extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, + uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param); +extern int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr, + uint32_t clock_value, pp_atomctrl_memory_clock_param_ai *mpll_param); +extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_kong *dividers); +extern int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, + uint16_t end_index, uint32_t mask, uint32_t *efuse); +extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug); +extern int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_ai *dividers); +extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock, + uint8_t level); +extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage); +extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table); + +extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param); + +extern int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint8_t *svd_gpio_id, uint8_t *svc_gpio_id, + uint16_t *load_line); + +extern int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, + uint16_t *vddc, uint16_t *vddci, + uint16_t virtual_voltage_id, + uint16_t efuse_voltage_id); +extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id); + +extern void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, + uint32_t *min_vddc); +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c new file mode 100644 index 000000000000..615cf2c09e54 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.c @@ -0,0 +1,710 @@ +/* + * Copyright 2016 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 "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "atom.h" +#include "pp_debug.h" + +static const union atom_voltage_object_v4 *pp_atomfwctrl_lookup_voltage_type_v4( + const struct atom_voltage_objects_info_v4_1 *voltage_object_info_table, + uint8_t voltage_type, uint8_t voltage_mode) +{ + unsigned int size = le16_to_cpu( + voltage_object_info_table->table_header.structuresize); + unsigned int offset = + offsetof(struct atom_voltage_objects_info_v4_1, voltage_object[0]); + unsigned long start = (unsigned long)voltage_object_info_table; + + while (offset < size) { + const union atom_voltage_object_v4 *voltage_object = + (const union atom_voltage_object_v4 *)(start + offset); + + if (voltage_type == voltage_object->gpio_voltage_obj.header.voltage_type && + voltage_mode == voltage_object->gpio_voltage_obj.header.voltage_mode) + return voltage_object; + + offset += le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size); + + } + + return NULL; +} + +static struct atom_voltage_objects_info_v4_1 *pp_atomfwctrl_get_voltage_info_table( + struct pp_hwmgr *hwmgr) +{ + const void *table_address; + uint16_t idx; + + idx = GetIndexIntoMasterDataTable(voltageobject_info); + table_address = smu_atom_get_data_table(hwmgr->adev, + idx, NULL, NULL, NULL); + + PP_ASSERT_WITH_CODE(table_address, + "Error retrieving BIOS Table Address!", + return NULL); + + return (struct atom_voltage_objects_info_v4_1 *)table_address; +} + +/** +* Returns TRUE if the given voltage type is controlled by GPIO pins. +* voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. +* voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE +*/ +bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, + uint8_t voltage_type, uint8_t voltage_mode) +{ + struct atom_voltage_objects_info_v4_1 *voltage_info = + (struct atom_voltage_objects_info_v4_1 *) + pp_atomfwctrl_get_voltage_info_table(hwmgr); + bool ret; + + /* If we cannot find the table do NOT try to control this voltage. */ + PP_ASSERT_WITH_CODE(voltage_info, + "Could not find Voltage Table in BIOS.", + return false); + + ret = (pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, + voltage_type, voltage_mode)) ? true : false; + + return ret; +} + +int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, + uint8_t voltage_type, uint8_t voltage_mode, + struct pp_atomfwctrl_voltage_table *voltage_table) +{ + struct atom_voltage_objects_info_v4_1 *voltage_info = + (struct atom_voltage_objects_info_v4_1 *) + pp_atomfwctrl_get_voltage_info_table(hwmgr); + const union atom_voltage_object_v4 *voltage_object; + unsigned int i; + int result = 0; + + PP_ASSERT_WITH_CODE(voltage_info, + "Could not find Voltage Table in BIOS.", + return -1); + + voltage_object = pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, + voltage_type, voltage_mode); + + if (!voltage_object) + return -1; + + voltage_table->count = 0; + if (voltage_mode == VOLTAGE_OBJ_GPIO_LUT) { + PP_ASSERT_WITH_CODE( + (voltage_object->gpio_voltage_obj.gpio_entry_num <= + PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES), + "Too many voltage entries!", + result = -1); + + if (!result) { + for (i = 0; i < voltage_object->gpio_voltage_obj. + gpio_entry_num; i++) { + voltage_table->entries[i].value = + le16_to_cpu(voltage_object->gpio_voltage_obj. + voltage_gpio_lut[i].voltage_level_mv); + voltage_table->entries[i].smio_low = + le32_to_cpu(voltage_object->gpio_voltage_obj. + voltage_gpio_lut[i].voltage_gpio_reg_val); + } + voltage_table->count = + voltage_object->gpio_voltage_obj.gpio_entry_num; + voltage_table->mask_low = + le32_to_cpu( + voltage_object->gpio_voltage_obj.gpio_mask_val); + voltage_table->phase_delay = + voltage_object->gpio_voltage_obj.phase_delay_us; + } + } else if (voltage_mode == VOLTAGE_OBJ_SVID2) { + voltage_table->psi1_enable = + (voltage_object->svid2_voltage_obj.loadline_psi1 & 0x20) >> 5; + voltage_table->psi0_enable = + voltage_object->svid2_voltage_obj.psi0_enable & 0x1; + voltage_table->max_vid_step = + voltage_object->svid2_voltage_obj.maxvstep; + voltage_table->telemetry_offset = + voltage_object->svid2_voltage_obj.telemetry_offset; + voltage_table->telemetry_slope = + voltage_object->svid2_voltage_obj.telemetry_gain; + } else + PP_ASSERT_WITH_CODE(false, + "Unsupported Voltage Object Mode!", + result = -1); + + return result; +} + + +static struct atom_gpio_pin_lut_v2_1 *pp_atomfwctrl_get_gpio_lookup_table( + struct pp_hwmgr *hwmgr) +{ + const void *table_address; + uint16_t idx; + + idx = GetIndexIntoMasterDataTable(gpio_pin_lut); + table_address = smu_atom_get_data_table(hwmgr->adev, + idx, NULL, NULL, NULL); + PP_ASSERT_WITH_CODE(table_address, + "Error retrieving BIOS Table Address!", + return NULL); + + return (struct atom_gpio_pin_lut_v2_1 *)table_address; +} + +static bool pp_atomfwctrl_lookup_gpio_pin( + struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table, + const uint32_t pin_id, + struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + unsigned int size = le16_to_cpu( + gpio_lookup_table->table_header.structuresize); + unsigned int offset = + offsetof(struct atom_gpio_pin_lut_v2_1, gpio_pin[0]); + unsigned long start = (unsigned long)gpio_lookup_table; + + while (offset < size) { + const struct atom_gpio_pin_assignment *pin_assignment = + (const struct atom_gpio_pin_assignment *)(start + offset); + + if (pin_id == pin_assignment->gpio_id) { + gpio_pin_assignment->uc_gpio_pin_bit_shift = + pin_assignment->gpio_bitshift; + gpio_pin_assignment->us_gpio_pin_aindex = + le16_to_cpu(pin_assignment->data_a_reg_index); + return true; + } + offset += offsetof(struct atom_gpio_pin_assignment, gpio_id) + 1; + } + return false; +} + +/** +* Returns TRUE if the given pin id find in lookup table. +*/ +bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, + const uint32_t pin_id, + struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + bool ret = false; + struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table = + pp_atomfwctrl_get_gpio_lookup_table(hwmgr); + + /* If we cannot find the table do NOT try to control this voltage. */ + PP_ASSERT_WITH_CODE(gpio_lookup_table, + "Could not find GPIO lookup Table in BIOS.", + return false); + + ret = pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table, + pin_id, gpio_pin_assignment); + + return ret; +} + +/** +* Enter to SelfRefresh mode. +* @param hwmgr +*/ +int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr) +{ + /* 0 - no action + * 1 - leave power to video memory always on + */ + return 0; +} + +/** pp_atomfwctrl_get_gpu_pll_dividers_vega10(). + * + * @param hwmgr input parameter: pointer to HwMgr + * @param clock_type input parameter: Clock type: 1 - GFXCLK, 2 - UCLK, 0 - All other clocks + * @param clock_value input parameter: Clock + * @param dividers output parameter:Clock dividers + */ +int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, + uint32_t clock_type, uint32_t clock_value, + struct pp_atomfwctrl_clock_dividers_soc15 *dividers) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct compute_gpu_clock_input_parameter_v1_8 pll_parameters; + struct compute_gpu_clock_output_parameter_v1_8 *pll_output; + uint32_t idx; + + pll_parameters.gpuclock_10khz = (uint32_t)clock_value; + pll_parameters.gpu_clock_type = clock_type; + + idx = GetIndexIntoMasterCmdTable(computegpuclockparam); + + if (amdgpu_atom_execute_table( + adev->mode_info.atom_context, idx, (uint32_t *)&pll_parameters)) + return -EINVAL; + + pll_output = (struct compute_gpu_clock_output_parameter_v1_8 *) + &pll_parameters; + dividers->ulClock = le32_to_cpu(pll_output->gpuclock_10khz); + dividers->ulDid = le32_to_cpu(pll_output->dfs_did); + dividers->ulPll_fb_mult = le32_to_cpu(pll_output->pll_fb_mult); + dividers->ulPll_ss_fbsmult = le32_to_cpu(pll_output->pll_ss_fbsmult); + dividers->usPll_ss_slew_frac = le16_to_cpu(pll_output->pll_ss_slew_frac); + dividers->ucPll_ss_enable = pll_output->pll_ss_enable; + + return 0; +} + +int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_avfs_parameters *param) +{ + uint16_t idx; + uint8_t format_revision, content_revision; + + struct atom_asic_profiling_info_v4_1 *profile; + struct atom_asic_profiling_info_v4_2 *profile_v4_2; + + idx = GetIndexIntoMasterDataTable(asic_profiling_info); + profile = (struct atom_asic_profiling_info_v4_1 *) + smu_atom_get_data_table(hwmgr->adev, + idx, NULL, NULL, NULL); + + if (!profile) + return -1; + + format_revision = ((struct atom_common_table_header *)profile)->format_revision; + content_revision = ((struct atom_common_table_header *)profile)->content_revision; + + if (format_revision == 4 && content_revision == 1) { + param->ulMaxVddc = le32_to_cpu(profile->maxvddc); + param->ulMinVddc = le32_to_cpu(profile->minvddc); + param->ulMeanNsigmaAcontant0 = + le32_to_cpu(profile->avfs_meannsigma_acontant0); + param->ulMeanNsigmaAcontant1 = + le32_to_cpu(profile->avfs_meannsigma_acontant1); + param->ulMeanNsigmaAcontant2 = + le32_to_cpu(profile->avfs_meannsigma_acontant2); + param->usMeanNsigmaDcTolSigma = + le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma); + param->usMeanNsigmaPlatformMean = + le16_to_cpu(profile->avfs_meannsigma_platform_mean); + param->usMeanNsigmaPlatformSigma = + le16_to_cpu(profile->avfs_meannsigma_platform_sigma); + param->ulGbVdroopTableCksoffA0 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a0); + param->ulGbVdroopTableCksoffA1 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a1); + param->ulGbVdroopTableCksoffA2 = + le32_to_cpu(profile->gb_vdroop_table_cksoff_a2); + param->ulGbVdroopTableCksonA0 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a0); + param->ulGbVdroopTableCksonA1 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a1); + param->ulGbVdroopTableCksonA2 = + le32_to_cpu(profile->gb_vdroop_table_ckson_a2); + param->ulGbFuseTableCksoffM1 = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); + param->ulGbFuseTableCksoffM2 = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); + param->ulGbFuseTableCksoffB = + le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); + param->ulGbFuseTableCksonM1 = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); + param->ulGbFuseTableCksonM2 = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2); + param->ulGbFuseTableCksonB = + le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); + + param->ucEnableGbVdroopTableCkson = + profile->enable_gb_vdroop_table_ckson; + param->ucEnableGbFuseTableCkson = + profile->enable_gb_fuse_table_ckson; + param->usPsmAgeComfactor = + le16_to_cpu(profile->psm_age_comfactor); + + param->ulDispclk2GfxclkM1 = + le32_to_cpu(profile->dispclk2gfxclk_a); + param->ulDispclk2GfxclkM2 = + le32_to_cpu(profile->dispclk2gfxclk_b); + param->ulDispclk2GfxclkB = + le32_to_cpu(profile->dispclk2gfxclk_c); + param->ulDcefclk2GfxclkM1 = + le32_to_cpu(profile->dcefclk2gfxclk_a); + param->ulDcefclk2GfxclkM2 = + le32_to_cpu(profile->dcefclk2gfxclk_b); + param->ulDcefclk2GfxclkB = + le32_to_cpu(profile->dcefclk2gfxclk_c); + param->ulPixelclk2GfxclkM1 = + le32_to_cpu(profile->pixclk2gfxclk_a); + param->ulPixelclk2GfxclkM2 = + le32_to_cpu(profile->pixclk2gfxclk_b); + param->ulPixelclk2GfxclkB = + le32_to_cpu(profile->pixclk2gfxclk_c); + param->ulPhyclk2GfxclkM1 = + le32_to_cpu(profile->phyclk2gfxclk_a); + param->ulPhyclk2GfxclkM2 = + le32_to_cpu(profile->phyclk2gfxclk_b); + param->ulPhyclk2GfxclkB = + le32_to_cpu(profile->phyclk2gfxclk_c); + param->ulAcgGbVdroopTableA0 = 0; + param->ulAcgGbVdroopTableA1 = 0; + param->ulAcgGbVdroopTableA2 = 0; + param->ulAcgGbFuseTableM1 = 0; + param->ulAcgGbFuseTableM2 = 0; + param->ulAcgGbFuseTableB = 0; + param->ucAcgEnableGbVdroopTable = 0; + param->ucAcgEnableGbFuseTable = 0; + } else if (format_revision == 4 && content_revision == 2) { + profile_v4_2 = (struct atom_asic_profiling_info_v4_2 *)profile; + param->ulMaxVddc = le32_to_cpu(profile_v4_2->maxvddc); + param->ulMinVddc = le32_to_cpu(profile_v4_2->minvddc); + param->ulMeanNsigmaAcontant0 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant0); + param->ulMeanNsigmaAcontant1 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant1); + param->ulMeanNsigmaAcontant2 = + le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant2); + param->usMeanNsigmaDcTolSigma = + le16_to_cpu(profile_v4_2->avfs_meannsigma_dc_tol_sigma); + param->usMeanNsigmaPlatformMean = + le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_mean); + param->usMeanNsigmaPlatformSigma = + le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_sigma); + param->ulGbVdroopTableCksoffA0 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a0); + param->ulGbVdroopTableCksoffA1 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a1); + param->ulGbVdroopTableCksoffA2 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a2); + param->ulGbVdroopTableCksonA0 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a0); + param->ulGbVdroopTableCksonA1 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a1); + param->ulGbVdroopTableCksonA2 = + le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a2); + param->ulGbFuseTableCksoffM1 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m1); + param->ulGbFuseTableCksoffM2 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m2); + param->ulGbFuseTableCksoffB = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_b); + param->ulGbFuseTableCksonM1 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m1); + param->ulGbFuseTableCksonM2 = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m2); + param->ulGbFuseTableCksonB = + le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_b); + + param->ucEnableGbVdroopTableCkson = + profile_v4_2->enable_gb_vdroop_table_ckson; + param->ucEnableGbFuseTableCkson = + profile_v4_2->enable_gb_fuse_table_ckson; + param->usPsmAgeComfactor = + le16_to_cpu(profile_v4_2->psm_age_comfactor); + + param->ulDispclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_a); + param->ulDispclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_b); + param->ulDispclk2GfxclkB = + le32_to_cpu(profile_v4_2->dispclk2gfxclk_c); + param->ulDcefclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_a); + param->ulDcefclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_b); + param->ulDcefclk2GfxclkB = + le32_to_cpu(profile_v4_2->dcefclk2gfxclk_c); + param->ulPixelclk2GfxclkM1 = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_a); + param->ulPixelclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_b); + param->ulPixelclk2GfxclkB = + le32_to_cpu(profile_v4_2->pixclk2gfxclk_c); + param->ulPhyclk2GfxclkM1 = + le32_to_cpu(profile->phyclk2gfxclk_a); + param->ulPhyclk2GfxclkM2 = + le32_to_cpu(profile_v4_2->phyclk2gfxclk_b); + param->ulPhyclk2GfxclkB = + le32_to_cpu(profile_v4_2->phyclk2gfxclk_c); + param->ulAcgGbVdroopTableA0 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a0); + param->ulAcgGbVdroopTableA1 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a1); + param->ulAcgGbVdroopTableA2 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a2); + param->ulAcgGbFuseTableM1 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m1); + param->ulAcgGbFuseTableM2 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m2); + param->ulAcgGbFuseTableB = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_b); + param->ucAcgEnableGbVdroopTable = le32_to_cpu(profile_v4_2->enable_acg_gb_vdroop_table); + param->ucAcgEnableGbFuseTable = le32_to_cpu(profile_v4_2->enable_acg_gb_fuse_table); + } else { + pr_info("Invalid VBIOS AVFS ProfilingInfo Revision!\n"); + return -EINVAL; + } + + return 0; +} + +int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_gpio_parameters *param) +{ + struct atom_smu_info_v3_1 *info; + uint16_t idx; + + idx = GetIndexIntoMasterDataTable(smu_info); + info = (struct atom_smu_info_v3_1 *) + smu_atom_get_data_table(hwmgr->adev, + idx, NULL, NULL, NULL); + + if (!info) { + pr_info("Error retrieving BIOS smu_info Table Address!"); + return -1; + } + + param->ucAcDcGpio = info->ac_dc_gpio_bit; + param->ucAcDcPolarity = info->ac_dc_polarity; + param->ucVR0HotGpio = info->vr0hot_gpio_bit; + param->ucVR0HotPolarity = info->vr0hot_polarity; + param->ucVR1HotGpio = info->vr1hot_gpio_bit; + param->ucVR1HotPolarity = info->vr1hot_polarity; + param->ucFwCtfGpio = info->fw_ctf_gpio_bit; + param->ucFwCtfPolarity = info->fw_ctf_polarity; + + return 0; +} + +int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, + uint8_t clk_id, uint8_t syspll_id, + uint32_t *frequency) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct atom_get_smu_clock_info_parameters_v3_1 parameters; + struct atom_get_smu_clock_info_output_parameters_v3_1 *output; + uint32_t ix; + + parameters.clk_id = clk_id; + parameters.syspll_id = syspll_id; + parameters.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ; + parameters.dfsdid = 0; + + ix = GetIndexIntoMasterCmdTable(getsmuclockinfo); + + if (amdgpu_atom_execute_table( + adev->mode_info.atom_context, ix, (uint32_t *)¶meters)) + return -EINVAL; + + output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)¶meters; + *frequency = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000; + + return 0; +} + +static void pp_atomfwctrl_copy_vbios_bootup_values_3_2(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values, + struct atom_firmware_info_v3_2 *fw_info) +{ + uint32_t frequency = 0; + + boot_values->ulRevision = fw_info->firmware_revision; + boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz; + boot_values->ulUClk = fw_info->bootup_mclk_in10khz; + boot_values->usVddc = fw_info->bootup_vddc_mv; + boot_values->usVddci = fw_info->bootup_vddci_mv; + boot_values->usMvddc = fw_info->bootup_mvddc_mv; + boot_values->usVddGfx = fw_info->bootup_vddgfx_mv; + boot_values->ucCoolingID = fw_info->coolingsolution_id; + boot_values->ulSocClk = 0; + boot_values->ulDCEFClk = 0; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_SOCCLK_ID, SMU11_SYSPLL0_ID, &frequency)) + boot_values->ulSocClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCEFCLK_ID, SMU11_SYSPLL0_ID, &frequency)) + boot_values->ulDCEFClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_ECLK_ID, SMU11_SYSPLL0_ID, &frequency)) + boot_values->ulEClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_VCLK_ID, SMU11_SYSPLL0_ID, &frequency)) + boot_values->ulVClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCLK_ID, SMU11_SYSPLL0_ID, &frequency)) + boot_values->ulDClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL1_0_FCLK_ID, SMU11_SYSPLL1_2_ID, &frequency)) + boot_values->ulFClk = frequency; +} + +static void pp_atomfwctrl_copy_vbios_bootup_values_3_1(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values, + struct atom_firmware_info_v3_1 *fw_info) +{ + uint32_t frequency = 0; + + boot_values->ulRevision = fw_info->firmware_revision; + boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz; + boot_values->ulUClk = fw_info->bootup_mclk_in10khz; + boot_values->usVddc = fw_info->bootup_vddc_mv; + boot_values->usVddci = fw_info->bootup_vddci_mv; + boot_values->usMvddc = fw_info->bootup_mvddc_mv; + boot_values->usVddGfx = fw_info->bootup_vddgfx_mv; + boot_values->ucCoolingID = fw_info->coolingsolution_id; + boot_values->ulSocClk = 0; + boot_values->ulDCEFClk = 0; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_SOCCLK_ID, 0, &frequency)) + boot_values->ulSocClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCEFCLK_ID, 0, &frequency)) + boot_values->ulDCEFClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_ECLK_ID, 0, &frequency)) + boot_values->ulEClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_VCLK_ID, 0, &frequency)) + boot_values->ulVClk = frequency; + + if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCLK_ID, 0, &frequency)) + boot_values->ulDClk = frequency; +} + +int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values) +{ + struct atom_firmware_info_v3_2 *fwinfo_3_2; + struct atom_firmware_info_v3_1 *fwinfo_3_1; + struct atom_common_table_header *info = NULL; + uint16_t ix; + + ix = GetIndexIntoMasterDataTable(firmwareinfo); + info = (struct atom_common_table_header *) + smu_atom_get_data_table(hwmgr->adev, + ix, NULL, NULL, NULL); + + if (!info) { + pr_info("Error retrieving BIOS firmwareinfo!"); + return -EINVAL; + } + + if ((info->format_revision == 3) && (info->content_revision == 2)) { + fwinfo_3_2 = (struct atom_firmware_info_v3_2 *)info; + pp_atomfwctrl_copy_vbios_bootup_values_3_2(hwmgr, + boot_values, fwinfo_3_2); + } else if ((info->format_revision == 3) && (info->content_revision == 1)) { + fwinfo_3_1 = (struct atom_firmware_info_v3_1 *)info; + pp_atomfwctrl_copy_vbios_bootup_values_3_1(hwmgr, + boot_values, fwinfo_3_1); + } else { + pr_info("Fw info table revision does not match!"); + return -EINVAL; + } + + return 0; +} + +int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_smc_dpm_parameters *param) +{ + struct atom_smc_dpm_info_v4_1 *info; + uint16_t ix; + + ix = GetIndexIntoMasterDataTable(smc_dpm_info); + info = (struct atom_smc_dpm_info_v4_1 *) + smu_atom_get_data_table(hwmgr->adev, + ix, NULL, NULL, NULL); + if (!info) { + pr_info("Error retrieving BIOS Table Address!"); + return -EINVAL; + } + + param->liquid1_i2c_address = info->liquid1_i2c_address; + param->liquid2_i2c_address = info->liquid2_i2c_address; + param->vr_i2c_address = info->vr_i2c_address; + param->plx_i2c_address = info->plx_i2c_address; + + param->liquid_i2c_linescl = info->liquid_i2c_linescl; + param->liquid_i2c_linesda = info->liquid_i2c_linesda; + param->vr_i2c_linescl = info->vr_i2c_linescl; + param->vr_i2c_linesda = info->vr_i2c_linesda; + + param->plx_i2c_linescl = info->plx_i2c_linescl; + param->plx_i2c_linesda = info->plx_i2c_linesda; + param->vrsensorpresent = info->vrsensorpresent; + param->liquidsensorpresent = info->liquidsensorpresent; + + param->maxvoltagestepgfx = info->maxvoltagestepgfx; + param->maxvoltagestepsoc = info->maxvoltagestepsoc; + + param->vddgfxvrmapping = info->vddgfxvrmapping; + param->vddsocvrmapping = info->vddsocvrmapping; + param->vddmem0vrmapping = info->vddmem0vrmapping; + param->vddmem1vrmapping = info->vddmem1vrmapping; + + param->gfxulvphasesheddingmask = info->gfxulvphasesheddingmask; + param->soculvphasesheddingmask = info->soculvphasesheddingmask; + + param->gfxmaxcurrent = info->gfxmaxcurrent; + param->gfxoffset = info->gfxoffset; + param->padding_telemetrygfx = info->padding_telemetrygfx; + + param->socmaxcurrent = info->socmaxcurrent; + param->socoffset = info->socoffset; + param->padding_telemetrysoc = info->padding_telemetrysoc; + + param->mem0maxcurrent = info->mem0maxcurrent; + param->mem0offset = info->mem0offset; + param->padding_telemetrymem0 = info->padding_telemetrymem0; + + param->mem1maxcurrent = info->mem1maxcurrent; + param->mem1offset = info->mem1offset; + param->padding_telemetrymem1 = info->padding_telemetrymem1; + + param->acdcgpio = info->acdcgpio; + param->acdcpolarity = info->acdcpolarity; + param->vr0hotgpio = info->vr0hotgpio; + param->vr0hotpolarity = info->vr0hotpolarity; + + param->vr1hotgpio = info->vr1hotgpio; + param->vr1hotpolarity = info->vr1hotpolarity; + param->padding1 = info->padding1; + param->padding2 = info->padding2; + + param->ledpin0 = info->ledpin0; + param->ledpin1 = info->ledpin1; + param->ledpin2 = info->ledpin2; + + param->pllgfxclkspreadenabled = info->pllgfxclkspreadenabled; + param->pllgfxclkspreadpercent = info->pllgfxclkspreadpercent; + param->pllgfxclkspreadfreq = info->pllgfxclkspreadfreq; + + param->uclkspreadenabled = info->uclkspreadenabled; + param->uclkspreadpercent = info->uclkspreadpercent; + param->uclkspreadfreq = info->uclkspreadfreq; + + param->socclkspreadenabled = info->socclkspreadenabled; + param->socclkspreadpercent = info->socclkspreadpercent; + param->socclkspreadfreq = info->socclkspreadfreq; + + param->acggfxclkspreadenabled = info->acggfxclkspreadenabled; + param->acggfxclkspreadpercent = info->acggfxclkspreadpercent; + param->acggfxclkspreadfreq = info->acggfxclkspreadfreq; + + param->Vr2_I2C_address = info->Vr2_I2C_address; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h new file mode 100644 index 000000000000..b7e2651b570b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppatomfwctrl.h @@ -0,0 +1,244 @@ +/* + * Copyright 2016 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 PP_ATOMFWCTRL_H +#define PP_ATOMFWCTRL_H + +#include "hwmgr.h" + +typedef enum atom_smu9_syspll0_clock_id BIOS_CLKID; + +#define GetIndexIntoMasterCmdTable(FieldName) \ + (((char*)(&((struct atom_master_list_of_command_functions_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t)) +#define GetIndexIntoMasterDataTable(FieldName) \ + (((char*)(&((struct atom_master_list_of_data_tables_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t)) + +#define PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES 32 + +struct pp_atomfwctrl_voltage_table_entry { + uint16_t value; + uint32_t smio_low; +}; + +struct pp_atomfwctrl_voltage_table { + uint32_t count; + uint32_t mask_low; + uint32_t phase_delay; + uint8_t psi0_enable; + uint8_t psi1_enable; + uint8_t max_vid_step; + uint8_t telemetry_offset; + uint8_t telemetry_slope; + struct pp_atomfwctrl_voltage_table_entry entries[PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES]; +}; + +struct pp_atomfwctrl_gpio_pin_assignment { + uint16_t us_gpio_pin_aindex; + uint8_t uc_gpio_pin_bit_shift; +}; + +struct pp_atomfwctrl_clock_dividers_soc15 { + uint32_t ulClock; /* the actual clock */ + uint32_t ulDid; /* DFS divider */ + uint32_t ulPll_fb_mult; /* Feedback Multiplier: bit 8:0 int, bit 15:12 post_div, bit 31:16 frac */ + uint32_t ulPll_ss_fbsmult; /* Spread FB Multiplier: bit 8:0 int, bit 31:16 frac */ + uint16_t usPll_ss_slew_frac; + uint8_t ucPll_ss_enable; + uint8_t ucReserve; + uint32_t ulReserve[2]; +}; + +struct pp_atomfwctrl_avfs_parameters { + uint32_t ulMaxVddc; + uint32_t ulMinVddc; + + uint32_t ulMeanNsigmaAcontant0; + uint32_t ulMeanNsigmaAcontant1; + uint32_t ulMeanNsigmaAcontant2; + uint16_t usMeanNsigmaDcTolSigma; + uint16_t usMeanNsigmaPlatformMean; + uint16_t usMeanNsigmaPlatformSigma; + uint32_t ulGbVdroopTableCksoffA0; + uint32_t ulGbVdroopTableCksoffA1; + uint32_t ulGbVdroopTableCksoffA2; + uint32_t ulGbVdroopTableCksonA0; + uint32_t ulGbVdroopTableCksonA1; + uint32_t ulGbVdroopTableCksonA2; + + uint32_t ulGbFuseTableCksoffM1; + uint32_t ulGbFuseTableCksoffM2; + uint32_t ulGbFuseTableCksoffB; + + uint32_t ulGbFuseTableCksonM1; + uint32_t ulGbFuseTableCksonM2; + uint32_t ulGbFuseTableCksonB; + + uint8_t ucEnableGbVdroopTableCkson; + uint8_t ucEnableGbFuseTableCkson; + uint16_t usPsmAgeComfactor; + + uint32_t ulDispclk2GfxclkM1; + uint32_t ulDispclk2GfxclkM2; + uint32_t ulDispclk2GfxclkB; + uint32_t ulDcefclk2GfxclkM1; + uint32_t ulDcefclk2GfxclkM2; + uint32_t ulDcefclk2GfxclkB; + uint32_t ulPixelclk2GfxclkM1; + uint32_t ulPixelclk2GfxclkM2; + uint32_t ulPixelclk2GfxclkB; + uint32_t ulPhyclk2GfxclkM1; + uint32_t ulPhyclk2GfxclkM2; + uint32_t ulPhyclk2GfxclkB; + uint32_t ulAcgGbVdroopTableA0; + uint32_t ulAcgGbVdroopTableA1; + uint32_t ulAcgGbVdroopTableA2; + uint32_t ulAcgGbFuseTableM1; + uint32_t ulAcgGbFuseTableM2; + uint32_t ulAcgGbFuseTableB; + uint32_t ucAcgEnableGbVdroopTable; + uint32_t ucAcgEnableGbFuseTable; +}; + +struct pp_atomfwctrl_gpio_parameters { + uint8_t ucAcDcGpio; + uint8_t ucAcDcPolarity; + uint8_t ucVR0HotGpio; + uint8_t ucVR0HotPolarity; + uint8_t ucVR1HotGpio; + uint8_t ucVR1HotPolarity; + uint8_t ucFwCtfGpio; + uint8_t ucFwCtfPolarity; +}; + +struct pp_atomfwctrl_bios_boot_up_values { + uint32_t ulRevision; + uint32_t ulGfxClk; + uint32_t ulUClk; + uint32_t ulSocClk; + uint32_t ulDCEFClk; + uint32_t ulEClk; + uint32_t ulVClk; + uint32_t ulDClk; + uint32_t ulFClk; + uint16_t usVddc; + uint16_t usVddci; + uint16_t usMvddc; + uint16_t usVddGfx; + uint8_t ucCoolingID; +}; + +struct pp_atomfwctrl_smc_dpm_parameters +{ + uint8_t liquid1_i2c_address; + uint8_t liquid2_i2c_address; + uint8_t vr_i2c_address; + uint8_t plx_i2c_address; + uint8_t liquid_i2c_linescl; + uint8_t liquid_i2c_linesda; + uint8_t vr_i2c_linescl; + uint8_t vr_i2c_linesda; + uint8_t plx_i2c_linescl; + uint8_t plx_i2c_linesda; + uint8_t vrsensorpresent; + uint8_t liquidsensorpresent; + uint16_t maxvoltagestepgfx; + uint16_t maxvoltagestepsoc; + uint8_t vddgfxvrmapping; + uint8_t vddsocvrmapping; + uint8_t vddmem0vrmapping; + uint8_t vddmem1vrmapping; + uint8_t gfxulvphasesheddingmask; + uint8_t soculvphasesheddingmask; + + uint16_t gfxmaxcurrent; + uint8_t gfxoffset; + uint8_t padding_telemetrygfx; + uint16_t socmaxcurrent; + uint8_t socoffset; + uint8_t padding_telemetrysoc; + uint16_t mem0maxcurrent; + uint8_t mem0offset; + uint8_t padding_telemetrymem0; + uint16_t mem1maxcurrent; + uint8_t mem1offset; + uint8_t padding_telemetrymem1; + + uint8_t acdcgpio; + uint8_t acdcpolarity; + uint8_t vr0hotgpio; + uint8_t vr0hotpolarity; + uint8_t vr1hotgpio; + uint8_t vr1hotpolarity; + uint8_t padding1; + uint8_t padding2; + + uint8_t ledpin0; + uint8_t ledpin1; + uint8_t ledpin2; + + uint8_t pllgfxclkspreadenabled; + uint8_t pllgfxclkspreadpercent; + uint16_t pllgfxclkspreadfreq; + + uint8_t uclkspreadenabled; + uint8_t uclkspreadpercent; + uint16_t uclkspreadfreq; + + uint8_t socclkspreadenabled; + uint8_t socclkspreadpercent; + uint16_t socclkspreadfreq; + + uint8_t acggfxclkspreadenabled; + uint8_t acggfxclkspreadpercent; + uint16_t acggfxclkspreadfreq; + + uint8_t Vr2_I2C_address; +}; + +int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, + uint32_t clock_type, uint32_t clock_value, + struct pp_atomfwctrl_clock_dividers_soc15 *dividers); +int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr); +bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pin_id, + struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment); + +int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint8_t voltage_mode, struct pp_atomfwctrl_voltage_table *voltage_table); +bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, + uint8_t voltage_type, uint8_t voltage_mode); + +int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_avfs_parameters *param); +int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_gpio_parameters *param); + +int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_bios_boot_up_values *boot_values); +int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_smc_dpm_parameters *param); +int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, + uint8_t clk_id, uint8_t syspll_id, + uint32_t *frequency); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h new file mode 100644 index 000000000000..8f50a038396c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/ppevvmath.h @@ -0,0 +1,555 @@ +/* + * Copyright 2015 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 + +#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ + +#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */ + +#define SHIFTED_2 (2 << SHIFT_AMOUNT) +#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */ + +/* ------------------------------------------------------------------------------- + * NEW TYPE - fINT + * ------------------------------------------------------------------------------- + * A variable of type fInt can be accessed in 3 ways using the dot (.) operator + * fInt A; + * A.full => The full number as it is. Generally not easy to read + * A.partial.real => Only the integer portion + * A.partial.decimal => Only the fractional portion + */ +typedef union _fInt { + int full; + struct _partial { + unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/ + int real: 32 - SHIFT_AMOUNT; + } partial; +} fInt; + +/* ------------------------------------------------------------------------------- + * Function Declarations + * ------------------------------------------------------------------------------- + */ +static fInt ConvertToFraction(int); /* Use this to convert an INT to a FINT */ +static fInt Convert_ULONG_ToFraction(uint32_t); /* Use this to convert an uint32_t to a FINT */ +static fInt GetScaledFraction(int, int); /* Use this to convert an INT to a FINT after scaling it by a factor */ +static int ConvertBackToInteger(fInt); /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */ + +static fInt fNegate(fInt); /* Returns -1 * input fInt value */ +static fInt fAdd (fInt, fInt); /* Returns the sum of two fInt numbers */ +static fInt fSubtract (fInt A, fInt B); /* Returns A-B - Sometimes easier than Adding negative numbers */ +static fInt fMultiply (fInt, fInt); /* Returns the product of two fInt numbers */ +static fInt fDivide (fInt A, fInt B); /* Returns A/B */ +static fInt fGetSquare(fInt); /* Returns the square of a fInt number */ +static fInt fSqrt(fInt); /* Returns the Square Root of a fInt number */ + +static int uAbs(int); /* Returns the Absolute value of the Int */ +static int uPow(int base, int exponent); /* Returns base^exponent an INT */ + +static void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */ +static bool Equal(fInt, fInt); /* Returns true if two fInts are equal to each other */ +static bool GreaterThan(fInt A, fInt B); /* Returns true if A > B */ + +static fInt fExponential(fInt exponent); /* Can be used to calculate e^exponent */ +static fInt fNaturalLog(fInt value); /* Can be used to calculate ln(value) */ + +/* Fuse decoding functions + * ------------------------------------------------------------------------------------- + */ +static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength); +static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength); +static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength); + +/* Internal Support Functions - Use these ONLY for testing or adding to internal functions + * ------------------------------------------------------------------------------------- + * Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons. + */ +static fInt Divide (int, int); /* Divide two INTs and return result as FINT */ +static fInt fNegate(fInt); + +static int uGetScaledDecimal (fInt); /* Internal function */ +static int GetReal (fInt A); /* Internal function */ + +/* ------------------------------------------------------------------------------------- + * TROUBLESHOOTING INFORMATION + * ------------------------------------------------------------------------------------- + * 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767) + * 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767) + * 3) fMultiply - OutputOutOfRangeException: + * 4) fGetSquare - OutputOutOfRangeException: + * 5) fDivide - DivideByZeroException + * 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number + */ + +/* ------------------------------------------------------------------------------------- + * START OF CODE + * ------------------------------------------------------------------------------------- + */ +static fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/ +{ + uint32_t i; + bool bNegated = false; + + fInt fPositiveOne = ConvertToFraction(1); + fInt fZERO = ConvertToFraction(0); + + fInt lower_bound = Divide(78, 10000); + fInt solution = fPositiveOne; /*Starting off with baseline of 1 */ + fInt error_term; + + static const uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; + static const uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; + + if (GreaterThan(fZERO, exponent)) { + exponent = fNegate(exponent); + bNegated = true; + } + + while (GreaterThan(exponent, lower_bound)) { + for (i = 0; i < 11; i++) { + if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) { + exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000)); + solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000)); + } + } + } + + error_term = fAdd(fPositiveOne, exponent); + + solution = fMultiply(solution, error_term); + + if (bNegated) + solution = fDivide(fPositiveOne, solution); + + return solution; +} + +static fInt fNaturalLog(fInt value) +{ + uint32_t i; + fInt upper_bound = Divide(8, 1000); + fInt fNegativeOne = ConvertToFraction(-1); + fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */ + fInt error_term; + + static const uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; + static const uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; + + while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) { + for (i = 0; i < 10; i++) { + if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) { + value = fDivide(value, GetScaledFraction(k_array[i], 10000)); + solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000)); + } + } + } + + error_term = fAdd(fNegativeOne, value); + + return (fAdd(solution, error_term)); +} + +static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength) +{ + fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fInt f_decoded_value; + + f_decoded_value = fDivide(f_fuse_value, f_bit_max_value); + f_decoded_value = fMultiply(f_decoded_value, f_range); + f_decoded_value = fAdd(f_decoded_value, f_min); + + return f_decoded_value; +} + + +static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength) +{ + fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fInt f_CONSTANT_NEG13 = ConvertToFraction(-13); + fInt f_CONSTANT1 = ConvertToFraction(1); + + fInt f_decoded_value; + + f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1); + f_decoded_value = fNaturalLog(f_decoded_value); + f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13)); + f_decoded_value = fAdd(f_decoded_value, f_average); + + return f_decoded_value; +} + +static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength) +{ + fInt fLeakage; + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse)); + fLeakage = fDivide(fLeakage, f_bit_max_value); + fLeakage = fExponential(fLeakage); + fLeakage = fMultiply(fLeakage, f_min); + + return fLeakage; +} + +static fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */ +{ + fInt temp; + + if (X <= MAX) + temp.full = (X << SHIFT_AMOUNT); + else + temp.full = 0; + + return temp; +} + +static fInt fNegate(fInt X) +{ + fInt CONSTANT_NEGONE = ConvertToFraction(-1); + return (fMultiply(X, CONSTANT_NEGONE)); +} + +static fInt Convert_ULONG_ToFraction(uint32_t X) +{ + fInt temp; + + if (X <= MAX) + temp.full = (X << SHIFT_AMOUNT); + else + temp.full = 0; + + return temp; +} + +static fInt GetScaledFraction(int X, int factor) +{ + int times_shifted, factor_shifted; + bool bNEGATED; + fInt fValue; + + times_shifted = 0; + factor_shifted = 0; + bNEGATED = false; + + if (X < 0) { + X = -1*X; + bNEGATED = true; + } + + if (factor < 0) { + factor = -1*factor; + bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */ + } + + if ((X > MAX) || factor > MAX) { + if ((X/factor) <= MAX) { + while (X > MAX) { + X = X >> 1; + times_shifted++; + } + + while (factor > MAX) { + factor = factor >> 1; + factor_shifted++; + } + } else { + fValue.full = 0; + return fValue; + } + } + + if (factor == 1) + return ConvertToFraction(X); + + fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor)); + + fValue.full = fValue.full << times_shifted; + fValue.full = fValue.full >> factor_shifted; + + return fValue; +} + +/* Addition using two fInts */ +static fInt fAdd (fInt X, fInt Y) +{ + fInt Sum; + + Sum.full = X.full + Y.full; + + return Sum; +} + +/* Addition using two fInts */ +static fInt fSubtract (fInt X, fInt Y) +{ + fInt Difference; + + Difference.full = X.full - Y.full; + + return Difference; +} + +static bool Equal(fInt A, fInt B) +{ + if (A.full == B.full) + return true; + else + return false; +} + +static bool GreaterThan(fInt A, fInt B) +{ + if (A.full > B.full) + return true; + else + return false; +} + +static fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */ +{ + fInt Product; + int64_t tempProduct; + bool X_LessThanOne, Y_LessThanOne; + + X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0); + Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0); + + /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ + /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION + + if (X_LessThanOne && Y_LessThanOne) { + Product.full = X.full * Y.full; + return Product + }*/ + + tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */ + tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */ + Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */ + + return Product; +} + +static fInt fDivide (fInt X, fInt Y) +{ + fInt fZERO, fQuotient; + int64_t longlongX, longlongY; + + fZERO = ConvertToFraction(0); + + if (Equal(Y, fZERO)) + return fZERO; + + longlongX = (int64_t)X.full; + longlongY = (int64_t)Y.full; + + longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */ + + div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */ + + fQuotient.full = (int)longlongX; + return fQuotient; +} + +static int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/ +{ + fInt fullNumber, scaledDecimal, scaledReal; + + scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */ + + scaledDecimal.full = uGetScaledDecimal(A); + + fullNumber = fAdd(scaledDecimal,scaledReal); + + return fullNumber.full; +} + +static fInt fGetSquare(fInt A) +{ + return fMultiply(A,A); +} + +/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */ +static fInt fSqrt(fInt num) +{ + fInt F_divide_Fprime, Fprime; + fInt test; + fInt twoShifted; + int seed, counter, error; + fInt x_new, x_old, C, y; + + fInt fZERO = ConvertToFraction(0); + + /* (0 > num) is the same as (num < 0), i.e., num is negative */ + + if (GreaterThan(fZERO, num) || Equal(fZERO, num)) + return fZERO; + + C = num; + + if (num.partial.real > 3000) + seed = 60; + else if (num.partial.real > 1000) + seed = 30; + else if (num.partial.real > 100) + seed = 10; + else + seed = 2; + + counter = 0; + + if (Equal(num, fZERO)) /*Square Root of Zero is zero */ + return fZERO; + + twoShifted = ConvertToFraction(2); + x_new = ConvertToFraction(seed); + + do { + counter++; + + x_old.full = x_new.full; + + test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */ + y = fSubtract(test, C); /*y = f(x) = x^2 - C; */ + + Fprime = fMultiply(twoShifted, x_old); + F_divide_Fprime = fDivide(y, Fprime); + + x_new = fSubtract(x_old, F_divide_Fprime); + + error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old); + + if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/ + return x_new; + + } while (uAbs(error) > 0); + + return (x_new); +} + +static void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[]) +{ + fInt *pRoots = &Roots[0]; + fInt temp, root_first, root_second; + fInt f_CONSTANT10, f_CONSTANT100; + + f_CONSTANT100 = ConvertToFraction(100); + f_CONSTANT10 = ConvertToFraction(10); + + while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) { + A = fDivide(A, f_CONSTANT10); + B = fDivide(B, f_CONSTANT10); + C = fDivide(C, f_CONSTANT10); + } + + temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */ + temp = fMultiply(temp, C); /* root = 4*A*C */ + temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */ + temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */ + + root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */ + root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */ + + root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ + root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ + + root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ + root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ + + *(pRoots + 0) = root_first; + *(pRoots + 1) = root_second; +} + +/* ----------------------------------------------------------------------------- + * SUPPORT FUNCTIONS + * ----------------------------------------------------------------------------- + */ + +/* Conversion Functions */ +static int GetReal (fInt A) +{ + return (A.full >> SHIFT_AMOUNT); +} + +static fInt Divide (int X, int Y) +{ + fInt A, B, Quotient; + + A.full = X << SHIFT_AMOUNT; + B.full = Y << SHIFT_AMOUNT; + + Quotient = fDivide(A, B); + + return Quotient; +} + +static int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */ +{ + int dec[PRECISION]; + int i, scaledDecimal = 0, tmp = A.partial.decimal; + + for (i = 0; i < PRECISION; i++) { + dec[i] = tmp / (1 << SHIFT_AMOUNT); + tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]); + tmp *= 10; + scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i); + } + + return scaledDecimal; +} + +static int uPow(int base, int power) +{ + if (power == 0) + return 1; + else + return (base)*uPow(base, power - 1); +} + +static int uAbs(int X) +{ + if (X < 0) + return (X * -1); + else + return X; +} + +static fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term) +{ + fInt solution; + + solution = fDivide(A, fStepSize); + solution.partial.decimal = 0; /*All fractional digits changes to 0 */ + + if (error_term) + solution.partial.real += 1; /*Error term of 1 added */ + + solution = fMultiply(solution, fStepSize); + solution = fAdd(solution, fStepSize); + + return solution; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c new file mode 100644 index 000000000000..186496a34cbe --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.c @@ -0,0 +1,64 @@ +/* + * Copyright 2015 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 +#include "atom-types.h" +#include "atombios.h" +#include "pppcielanes.h" + +/** \file + * Functions related to PCIe lane changes. + */ + +/* For converting from number of lanes to lane bits. */ +static const unsigned char pp_r600_encode_lanes[] = { + 0, /* 0 Not Supported */ + 1, /* 1 Lane */ + 2, /* 2 Lanes */ + 0, /* 3 Not Supported */ + 3, /* 4 Lanes */ + 0, /* 5 Not Supported */ + 0, /* 6 Not Supported */ + 0, /* 7 Not Supported */ + 4, /* 8 Lanes */ + 0, /* 9 Not Supported */ + 0, /* 10 Not Supported */ + 0, /* 11 Not Supported */ + 5, /* 12 Lanes (Not actually supported) */ + 0, /* 13 Not Supported */ + 0, /* 14 Not Supported */ + 0, /* 15 Not Supported */ + 6 /* 16 Lanes */ +}; + +static const unsigned char pp_r600_decoded_lanes[8] = { 16, 1, 2, 4, 8, 12, 16, }; + +uint8_t encode_pcie_lane_width(uint32_t num_lanes) +{ + return pp_r600_encode_lanes[num_lanes]; +} + +uint8_t decode_pcie_lane_width(uint32_t num_lanes) +{ + return pp_r600_decoded_lanes[num_lanes]; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h new file mode 100644 index 000000000000..70b163b35570 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pppcielanes.h @@ -0,0 +1,31 @@ +/* + * Copyright 2015 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 PP_PCIELANES_H +#define PP_PCIELANES_H + +extern uint8_t encode_pcie_lane_width(uint32_t num_lanes); +extern uint8_t decode_pcie_lane_width(uint32_t num_lanes); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h new file mode 100644 index 000000000000..1e870f58dd12 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pptable_v1_0.h @@ -0,0 +1,436 @@ +/* + * Copyright 2015 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 TONGA_PPTABLE_H +#define TONGA_PPTABLE_H + +/** \file + * This is a PowerPlay table header file + */ +#pragma pack(push, 1) + +#include "hwmgr.h" + +#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17 +#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21 +#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22 + +/* + * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. + * We probably should reserve the bit 0x80 for this use. + * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). + * The driver can pick the correct internal controller based on the ASIC. + */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */ +#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */ + +/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */ +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */ +#define ____RETIRE16____ 0x10 +#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */ +#define ____RETIRE64____ 0x40 +#define ____RETIRE128____ 0x80 +#define ____RETIRE256____ 0x100 +#define ____RETIRE512____ 0x200 +#define ____RETIRE1024____ 0x400 +#define ____RETIRE2048____ 0x800 +#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */ +#define ____RETIRE2000____ 0x2000 +#define ____RETIRE4000____ 0x4000 +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */ +#define ____RETIRE10000____ 0x10000 +#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */ + +#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */ +#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */ +#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +/* 2, 4, 6, 7 are reserved */ + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 + +#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000 +#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_Tonga_TABLE_REVISION_TONGA 7 + +typedef struct _ATOM_Tonga_POWERPLAYTABLE { + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucTableRevision; + USHORT usTableSize; /*the size of header structure */ + + ULONG ulGoldenPPID; + ULONG ulGoldenRevision; + USHORT usFormatID; + + USHORT usVoltageTime; /*in microseconds */ + ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */ + + ULONG ulMaxODEngineClock; /*For Overdrive. */ + ULONG ulMaxODMemoryClock; /*For Overdrive. */ + + USHORT usPowerControlLimit; + USHORT usUlvVoltageOffset; /*in mv units */ + + USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */ + USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */ + USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */ + USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */ + + USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */ + USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */ + USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + + USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */ + + USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */ + + USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */ + USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */ + + USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */ + + USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */ + + USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */ + + USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */ +} ATOM_Tonga_POWERPLAYTABLE; + +typedef struct _ATOM_Tonga_State { + UCHAR ucEngineClockIndexHigh; + UCHAR ucEngineClockIndexLow; + + UCHAR ucMemoryClockIndexHigh; + UCHAR ucMemoryClockIndexLow; + + UCHAR ucPCIEGenLow; + UCHAR ucPCIEGenHigh; + + UCHAR ucPCIELaneLow; + UCHAR ucPCIELaneHigh; + + USHORT usClassification; + ULONG ulCapsAndSettings; + USHORT usClassification2; + UCHAR ucUnused[4]; +} ATOM_Tonga_State; + +typedef struct _ATOM_Tonga_State_Array { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_State_Array; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Record { + UCHAR ucVddcInd; /* Vddc voltage */ + USHORT usVddci; + USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */ + USHORT usMvdd; + ULONG ulMclk; + USHORT usReserved; +} ATOM_Tonga_MCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Record { + UCHAR ucVddInd; /* Base voltage */ + USHORT usVddcOffset; /* Offset relative to base voltage */ + ULONG ulSclk; + USHORT usEdcCurrent; + UCHAR ucReliabilityTemperature; + UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ +} ATOM_Tonga_SCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_SCLK_Dependency_Table; + +typedef struct _ATOM_Polaris_SCLK_Dependency_Record { + UCHAR ucVddInd; /* Base voltage */ + USHORT usVddcOffset; /* Offset relative to base voltage */ + ULONG ulSclk; + USHORT usEdcCurrent; + UCHAR ucReliabilityTemperature; + UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ + ULONG ulSclkOffset; +} ATOM_Polaris_SCLK_Dependency_Record; + +typedef struct _ATOM_Polaris_SCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Polaris_SCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_PCIE_Record { + UCHAR ucPCIEGenSpeed; + UCHAR usPCIELaneWidth; + UCHAR ucReserved[2]; +} ATOM_Tonga_PCIE_Record; + +typedef struct _ATOM_Tonga_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_PCIE_Table; + +typedef struct _ATOM_Polaris10_PCIE_Record { + UCHAR ucPCIEGenSpeed; + UCHAR usPCIELaneWidth; + UCHAR ucReserved[2]; + ULONG ulPCIE_Sclk; +} ATOM_Polaris10_PCIE_Record; + +typedef struct _ATOM_Polaris10_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Polaris10_PCIE_Table; + + +typedef struct _ATOM_Tonga_MM_Dependency_Record { + UCHAR ucVddcInd; /* VDDC voltage */ + USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ + ULONG ulDClk; /* UVD D-clock */ + ULONG ulVClk; /* UVD V-clock */ + ULONG ulEClk; /* VCE clock */ + ULONG ulAClk; /* ACP clock */ + ULONG ulSAMUClk; /* SAMU clock */ +} ATOM_Tonga_MM_Dependency_Record; + +typedef struct _ATOM_Tonga_MM_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MM_Dependency_Table; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Record { + USHORT usVdd; /* Base voltage */ + USHORT usCACLow; + USHORT usCACMid; + USHORT usCACHigh; +} ATOM_Tonga_Voltage_Lookup_Record; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_Voltage_Lookup_Table; + +typedef struct _ATOM_Tonga_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usReserved; +} ATOM_Tonga_Fan_Table; + +typedef struct _ATOM_Fiji_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + USHORT usReserved; +} ATOM_Fiji_Fan_Table; + +typedef struct _ATOM_Tonga_Thermal_Controller { + UCHAR ucRevId; + UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ + UCHAR ucI2cLine; /* as interpreted by DAL I2C */ + UCHAR ucI2cAddress; + UCHAR ucFanParameters; /* Fan Control Parameters. */ + UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */ + UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */ + UCHAR ucReserved; + UCHAR ucFlags; /* to be defined */ +} ATOM_Tonga_Thermal_Controller; + +typedef struct _ATOM_Tonga_VCE_State_Record { + UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */ + UCHAR ucFlag; /* 2 bits indicates memory p-states */ + UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */ + UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */ +} ATOM_Tonga_VCE_State_Record; + +typedef struct _ATOM_Tonga_VCE_State_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_VCE_State_Record entries[1]; +} ATOM_Tonga_VCE_State_Table; + +typedef struct _ATOM_Tonga_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usReserve[2]; +} ATOM_Tonga_PowerTune_Table; + +typedef struct _ATOM_Fiji_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */ + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */ + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitVrVddc; + USHORT usTemperatureLimitVrMvdd; + USHORT usTemperatureLimitPlx; + UCHAR ucLiquid1_I2C_address; /*Liquid */ + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; /*VR */ + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; /*PLX */ + UCHAR ucPlx_I2C_Line; + USHORT usReserved; +} ATOM_Fiji_PowerTune_Table; + +#define ATOM_PPM_A_A 1 +#define ATOM_PPM_A_I 2 +typedef struct _ATOM_Tonga_PPM_Table { + UCHAR ucRevId; + UCHAR ucPpmDesign; /*A+I or A+A */ + USHORT usCpuCoreNumber; + ULONG ulPlatformTDP; + ULONG ulSmallACPlatformTDP; + ULONG ulPlatformTDC; + ULONG ulSmallACPlatformTDC; + ULONG ulApuTDP; + ULONG ulDGpuTDP; + ULONG ulDGpuUlvPower; + ULONG ulTjmax; +} ATOM_Tonga_PPM_Table; + +typedef struct _ATOM_Tonga_Hard_Limit_Record { + ULONG ulSCLKLimit; + ULONG ulMCLKLimit; + USHORT usVddcLimit; + USHORT usVddciLimit; + USHORT usVddgfxLimit; +} ATOM_Tonga_Hard_Limit_Record; + +typedef struct _ATOM_Tonga_Hard_Limit_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_Hard_Limit_Record entries[1]; +} ATOM_Tonga_Hard_Limit_Table; + +typedef struct _ATOM_Tonga_GPIO_Table { + UCHAR ucRevId; + UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */ + UCHAR ucReserve[5]; +} ATOM_Tonga_GPIO_Table; + +typedef struct _PPTable_Generic_SubTable_Header { + UCHAR ucRevId; +} PPTable_Generic_SubTable_Header; + + +#pragma pack(pop) + + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c new file mode 100644 index 000000000000..b760f95e7fa7 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.c @@ -0,0 +1,1337 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include + +#include "process_pptables_v1_0.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "hwmgr.h" +#include "cgs_common.h" +#include "pptable_v1_0.h" + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). + * @param cap Which capability to set/reset. + */ +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) +{ + if (setIt) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_caps the bit array (from BIOS) of capability bits. + * @exception the current implementation always returns 1. + */ +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), + "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), + "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), + "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), + "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), + "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), + PHM_PlatformCaps_EnableMVDDControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), + PHM_PlatformCaps_ControlVDDCI + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), + PHM_PlatformCaps_ControlVDDGFX + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), + PHM_PlatformCaps_DisableVoltageIsland + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), + PHM_PlatformCaps_LoadPostProductionFirmware + ); + + return 0; +} + +/** + * Private Function to get the PowerPlay Table Address. + */ +static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + + u16 size; + u8 frev, crev; + void *table_address = (void *)hwmgr->soft_pp_table; + + if (!table_address) { + table_address = (ATOM_Tonga_POWERPLAYTABLE *) + smu_atom_get_data_table(hwmgr->adev, + index, &size, &frev, &crev); + hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ + hwmgr->soft_pp_table_size = size; + } + + return table_address; +} + +static int get_vddc_lookup_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table **lookup_table, + const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, + uint32_t max_levels + ) +{ + uint32_t table_size, i; + phm_ppt_v1_voltage_lookup_table *table; + phm_ppt_v1_voltage_lookup_record *record; + ATOM_Tonga_Voltage_Lookup_Record *atom_record; + + PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), + "Invalid CAC Leakage PowerPlay Table!", return 1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; + + table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + table->count = vddc_lookup_pp_tables->ucNumEntries; + + for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { + record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_voltage_lookup_record, + entries, table, i); + atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_Voltage_Lookup_Record, + entries, vddc_lookup_pp_tables, i); + record->us_calculated = 0; + record->us_vdd = le16_to_cpu(atom_record->usVdd); + record->us_cac_low = le16_to_cpu(atom_record->usCACLow); + record->us_cac_mid = le16_to_cpu(atom_record->usCACMid); + record->us_cac_high = le16_to_cpu(atom_record->usCACHigh); + } + + *lookup_table = table; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize Platform Power Management Parameter table + * @param hwmgr Pointer to the hardware manager. + * @param atom_ppm_table Pointer to PPM table in VBIOS + */ +static int get_platform_power_management_table( + struct pp_hwmgr *hwmgr, + ATOM_Tonga_PPM_Table *atom_ppm_table) +{ + struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (NULL == ptr) + return -ENOMEM; + + ptr->ppm_design + = atom_ppm_table->ucPpmDesign; + ptr->cpu_core_number + = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); + ptr->platform_tdp + = le32_to_cpu(atom_ppm_table->ulPlatformTDP); + ptr->small_ac_platform_tdp + = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); + ptr->platform_tdc + = le32_to_cpu(atom_ppm_table->ulPlatformTDC); + ptr->small_ac_platform_tdc + = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); + ptr->apu_tdp + = le32_to_cpu(atom_ppm_table->ulApuTDP); + ptr->dgpu_tdp + = le32_to_cpu(atom_ppm_table->ulDGpuTDP); + ptr->dgpu_ulv_power + = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); + ptr->tj_max + = le32_to_cpu(atom_ppm_table->ulTjmax); + + pp_table_information->ppm_parameter_table = ptr; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize TDP limits for DPM2 + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_dpm_2_parameters( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); + ATOM_Tonga_PPM_Table *atom_ppm_table; + uint32_t disable_ppm = 0; + uint32_t disable_power_control = 0; + + pp_table_information->us_ulv_voltage_offset = + le16_to_cpu(powerplay_table->usUlvVoltageOffset); + + pp_table_information->ppm_parameter_table = NULL; + pp_table_information->vddc_lookup_table = NULL; + pp_table_information->vddgfx_lookup_table = NULL; + /* TDP limits */ + hwmgr->platform_descriptor.TDPODLimit = + le16_to_cpu(powerplay_table->usPowerControlLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + disable_power_control = 0; + if (0 == disable_power_control) { + /* enable TDP overdrive (PowerControl) feature as well if supported */ + if (hwmgr->platform_descriptor.TDPODLimit != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + } + + if (0 != powerplay_table->usVddcLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); + } + + if (0 != powerplay_table->usVddgfxLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); + } + + disable_ppm = 0; + if (0 == disable_ppm) { + atom_ppm_table = (ATOM_Tonga_PPM_Table *) + (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); + + if (0 != powerplay_table->usPPMTableOffset) { + if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnablePlatformPowerManagement); + } + } + } + + return result; +} + +static int get_valid_clk( + struct pp_hwmgr *hwmgr, + struct phm_clock_array **clk_table, + phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table + ) +{ + uint32_t table_size, i; + struct phm_clock_array *table; + phm_ppt_v1_clock_voltage_dependency_record *dep_record; + + PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(uint32_t) * clk_volt_pp_table->count; + + table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + table->count = (uint32_t)clk_volt_pp_table->count; + + for (i = 0; i < table->count; i++) { + dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, clk_volt_pp_table, i); + table->values[i] = (uint32_t)dep_record->clk; + } + *clk_table = table; + + return 0; +} + +static int get_hard_limits( + struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + ATOM_Tonga_Hard_Limit_Table const *limitable + ) +{ + PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); + + /* currently we always take entries[0] parameters */ + limits->sclk = le32_to_cpu(limitable->entries[0].ulSCLKLimit); + limits->mclk = le32_to_cpu(limitable->entries[0].ulMCLKLimit); + limits->vddc = le16_to_cpu(limitable->entries[0].usVddcLimit); + limits->vddci = le16_to_cpu(limitable->entries[0].usVddciLimit); + limits->vddgfx = le16_to_cpu(limitable->entries[0].usVddgfxLimit); + + return 0; +} + +static int get_mclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, + ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table; + phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * mclk_dep_table->ucNumEntries; + + mclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == mclk_table) + return -ENOMEM; + + mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; + + for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { + mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, mclk_table, i); + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, i); + mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; + mclk_table_record->vdd_offset = le16_to_cpu(mclk_dep_record->usVddgfxOffset); + mclk_table_record->vddci = le16_to_cpu(mclk_dep_record->usVddci); + mclk_table_record->mvdd = le16_to_cpu(mclk_dep_record->usMvdd); + mclk_table_record->clk = le32_to_cpu(mclk_dep_record->ulMclk); + } + + *pp_tonga_mclk_dep_table = mclk_table; + + return 0; +} + +static int get_sclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, + PPTable_Generic_SubTable_Header const *sclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *sclk_table; + phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; + + if (sclk_dep_table->ucRevId < 1) { + const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = + (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * tonga_table->ucNumEntries; + + sclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == sclk_table) + return -ENOMEM; + + sclk_table->count = (uint32_t)tonga_table->ucNumEntries; + + for (i = 0; i < tonga_table->ucNumEntries; i++) { + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, tonga_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset); + sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk); + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); + } + } else { + const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = + (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; + ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; + + PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * polaris_table->ucNumEntries; + + sclk_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == sclk_table) + return -ENOMEM; + + sclk_table->count = (uint32_t)polaris_table->ucNumEntries; + + for (i = 0; i < polaris_table->ucNumEntries; i++) { + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris_SCLK_Dependency_Record, + entries, polaris_table, i); + sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_clock_voltage_dependency_record, + entries, sclk_table, i); + sclk_table_record->vddInd = sclk_dep_record->ucVddInd; + sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset); + sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk); + sclk_table_record->cks_enable = + (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); + sclk_table_record->sclk_offset = le32_to_cpu(sclk_dep_record->ulSclkOffset); + } + } + *pp_tonga_sclk_dep_table = sclk_table; + + return 0; +} + +static int get_pcie_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_pcie_table **pp_tonga_pcie_table, + PPTable_Generic_SubTable_Header const *ptable + ) +{ + uint32_t table_size, i, pcie_count; + phm_ppt_v1_pcie_table *pcie_table; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_pcie_record *pcie_record; + + if (ptable->ucRevId < 1) { + const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; + ATOM_Tonga_PCIE_Record *atom_pcie_record; + + PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; + + pcie_table = kzalloc(table_size, GFP_KERNEL); + + if (pcie_table == NULL) + return -ENOMEM; + + /* + * Make sure the number of pcie entries are less than or equal to sclk dpm levels. + * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. + */ + pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; + if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; + else + pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); + + pcie_table->count = pcie_count; + for (i = 0; i < pcie_count; i++) { + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth); + } + + *pp_tonga_pcie_table = pcie_table; + } else { + /* Polaris10/Polaris11 and newer. */ + const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; + ATOM_Polaris10_PCIE_Record *atom_pcie_record; + + PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; + + pcie_table = kzalloc(table_size, GFP_KERNEL); + + if (pcie_table == NULL) + return -ENOMEM; + + /* + * Make sure the number of pcie entries are less than or equal to sclk dpm levels. + * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. + */ + pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; + if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; + else + pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); + + pcie_table->count = pcie_count; + + for (i = 0; i < pcie_count; i++) { + pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_pcie_record, + entries, pcie_table, i); + atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Polaris10_PCIE_Record, + entries, atom_pcie_table, i); + pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; + pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth); + pcie_record->pcie_sclk = le32_to_cpu(atom_pcie_record->ulPCIE_Sclk); + } + + *pp_tonga_pcie_table = pcie_table; + } + + return 0; +} + +static int get_cac_tdp_table( + struct pp_hwmgr *hwmgr, + struct phm_cac_tdp_table **cac_tdp_table, + const PPTable_Generic_SubTable_Header * table + ) +{ + uint32_t table_size; + struct phm_cac_tdp_table *tdp_table; + + table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); + tdp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == tdp_table) + return -ENOMEM; + + hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == hwmgr->dyn_state.cac_dtp_table) { + kfree(tdp_table); + return -ENOMEM; + } + + if (table->ucRevId < 3) { + const ATOM_Tonga_PowerTune_Table *tonga_table = + (ATOM_Tonga_PowerTune_Table *)table; + tdp_table->usTDP = le16_to_cpu(tonga_table->usTDP); + tdp_table->usConfigurableTDP = + le16_to_cpu(tonga_table->usConfigurableTDP); + tdp_table->usTDC = le16_to_cpu(tonga_table->usTDC); + tdp_table->usBatteryPowerLimit = + le16_to_cpu(tonga_table->usBatteryPowerLimit); + tdp_table->usSmallPowerLimit = + le16_to_cpu(tonga_table->usSmallPowerLimit); + tdp_table->usLowCACLeakage = + le16_to_cpu(tonga_table->usLowCACLeakage); + tdp_table->usHighCACLeakage = + le16_to_cpu(tonga_table->usHighCACLeakage); + tdp_table->usMaximumPowerDeliveryLimit = + le16_to_cpu(tonga_table->usMaximumPowerDeliveryLimit); + tdp_table->usDefaultTargetOperatingTemp = + le16_to_cpu(tonga_table->usTjMax); + tdp_table->usTargetOperatingTemp = + le16_to_cpu(tonga_table->usTjMax); /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + le16_to_cpu(tonga_table->usPowerTuneDataSetID); + tdp_table->usSoftwareShutdownTemp = + le16_to_cpu(tonga_table->usSoftwareShutdownTemp); + tdp_table->usClockStretchAmount = + le16_to_cpu(tonga_table->usClockStretchAmount); + } else { /* Fiji and newer */ + const ATOM_Fiji_PowerTune_Table *fijitable = + (ATOM_Fiji_PowerTune_Table *)table; + tdp_table->usTDP = le16_to_cpu(fijitable->usTDP); + tdp_table->usConfigurableTDP = le16_to_cpu(fijitable->usConfigurableTDP); + tdp_table->usTDC = le16_to_cpu(fijitable->usTDC); + tdp_table->usBatteryPowerLimit = le16_to_cpu(fijitable->usBatteryPowerLimit); + tdp_table->usSmallPowerLimit = le16_to_cpu(fijitable->usSmallPowerLimit); + tdp_table->usLowCACLeakage = le16_to_cpu(fijitable->usLowCACLeakage); + tdp_table->usHighCACLeakage = le16_to_cpu(fijitable->usHighCACLeakage); + tdp_table->usMaximumPowerDeliveryLimit = + le16_to_cpu(fijitable->usMaximumPowerDeliveryLimit); + tdp_table->usDefaultTargetOperatingTemp = + le16_to_cpu(fijitable->usTjMax); + tdp_table->usTargetOperatingTemp = + le16_to_cpu(fijitable->usTjMax); /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + le16_to_cpu(fijitable->usPowerTuneDataSetID); + tdp_table->usSoftwareShutdownTemp = + le16_to_cpu(fijitable->usSoftwareShutdownTemp); + tdp_table->usClockStretchAmount = + le16_to_cpu(fijitable->usClockStretchAmount); + tdp_table->usTemperatureLimitHotspot = + le16_to_cpu(fijitable->usTemperatureLimitHotspot); + tdp_table->usTemperatureLimitLiquid1 = + le16_to_cpu(fijitable->usTemperatureLimitLiquid1); + tdp_table->usTemperatureLimitLiquid2 = + le16_to_cpu(fijitable->usTemperatureLimitLiquid2); + tdp_table->usTemperatureLimitVrVddc = + le16_to_cpu(fijitable->usTemperatureLimitVrVddc); + tdp_table->usTemperatureLimitVrMvdd = + le16_to_cpu(fijitable->usTemperatureLimitVrMvdd); + tdp_table->usTemperatureLimitPlx = + le16_to_cpu(fijitable->usTemperatureLimitPlx); + tdp_table->ucLiquid1_I2C_address = + fijitable->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = + fijitable->ucLiquid2_I2C_address; + tdp_table->ucLiquid_I2C_Line = + fijitable->ucLiquid_I2C_Line; + tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; + tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; + tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; + tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; + } + + *cac_tdp_table = tdp_table; + + return 0; +} + +static int get_mm_clock_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, + const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table + ) +{ + uint32_t table_size, i; + const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; + phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; + + PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) + * mm_dependency_table->ucNumEntries; + mm_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == mm_table) + return -ENOMEM; + + mm_table->count = mm_dependency_table->ucNumEntries; + + for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { + mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dependency_table, i); + mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + phm_ppt_v1_mm_clock_voltage_dependency_record, + entries, mm_table, i); + mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; + mm_table_record->vddgfx_offset = le16_to_cpu(mm_dependency_record->usVddgfxOffset); + mm_table_record->aclk = le32_to_cpu(mm_dependency_record->ulAClk); + mm_table_record->samclock = le32_to_cpu(mm_dependency_record->ulSAMUClk); + mm_table_record->eclk = le32_to_cpu(mm_dependency_record->ulEClk); + mm_table_record->vclk = le32_to_cpu(mm_dependency_record->ulVClk); + mm_table_record->dclk = le32_to_cpu(mm_dependency_record->ulDClk); + } + + *tonga_mm_table = mm_table; + + return 0; +} + +static int get_gpio_table(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table, + const ATOM_Tonga_GPIO_Table *atom_gpio_table) +{ + uint32_t table_size; + struct phm_ppt_v1_gpio_table *pp_gpio_table; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + table_size = sizeof(struct phm_ppt_v1_gpio_table); + pp_gpio_table = kzalloc(table_size, GFP_KERNEL); + if (!pp_gpio_table) + return -ENOMEM; + + if (pp_table_information->vdd_dep_on_sclk->count < + atom_gpio_table->ucVRHotTriggeredSclkDpmIndex) + PP_ASSERT_WITH_CODE(false, + "SCLK DPM index for VRHot cannot exceed the total sclk level count!",); + else + pp_gpio_table->vrhot_triggered_sclk_dpm_index = + atom_gpio_table->ucVRHotTriggeredSclkDpmIndex; + + *pp_tonga_gpio_table = pp_gpio_table; + + return 0; +} +/** + * Private Function used during initialization. + * Initialize clock voltage dependency + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_clock_voltage_dependency( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = + (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); + const PPTable_Generic_SubTable_Header *pPowerTuneTable = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + const PPTable_Generic_SubTable_Header *sclk_dep_table = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + const ATOM_Tonga_Hard_Limit_Table *pHardLimits = + (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usHardLimitTableOffset)); + const PPTable_Generic_SubTable_Header *pcie_table = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPCIETableOffset)); + const ATOM_Tonga_GPIO_Table *gpio_table = + (const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usGPIOTableOffset)); + + pp_table_information->vdd_dep_on_sclk = NULL; + pp_table_information->vdd_dep_on_mclk = NULL; + pp_table_information->mm_dep_table = NULL; + pp_table_information->pcie_table = NULL; + pp_table_information->gpio_table = NULL; + + if (powerplay_table->usMMDependencyTableOffset != 0) + result = get_mm_clock_voltage_table(hwmgr, + &pp_table_information->mm_dep_table, mm_dependency_table); + + if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) + result = get_cac_tdp_table(hwmgr, + &pp_table_information->cac_dtp_table, pPowerTuneTable); + + if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) + result = get_sclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); + + if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) + result = get_mclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); + + if (result == 0 && powerplay_table->usPCIETableOffset != 0) + result = get_pcie_table(hwmgr, + &pp_table_information->pcie_table, pcie_table); + + if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) + result = get_hard_limits(hwmgr, + &pp_table_information->max_clock_voltage_on_dc, pHardLimits); + + hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = + pp_table_information->max_clock_voltage_on_dc.sclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = + pp_table_information->max_clock_voltage_on_dc.mclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + pp_table_information->max_clock_voltage_on_dc.vddc; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = + pp_table_information->max_clock_voltage_on_dc.vddci; + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) + && (0 != pp_table_information->vdd_dep_on_mclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, + pp_table_information->vdd_dep_on_mclk); + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) + && (0 != pp_table_information->vdd_dep_on_sclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, + pp_table_information->vdd_dep_on_sclk); + + if (!result && gpio_table) + result = get_gpio_table(hwmgr, &pp_table_information->gpio_table, + gpio_table); + + return result; +} + +/** Retrieves the (signed) Overdrive limits from VBIOS. + * The max engine clock, memory clock and max temperature come from the firmware info table. + * + * The information is placed into the platform descriptor. + * + * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. + * @param powerplay_table the address of the PowerPlay table. + * + * @return 1 as long as the firmware info table was present and of a supported version. + */ +static int init_over_drive_limits( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) +{ + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le32_to_cpu(powerplay_table->ulMaxODEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le32_to_cpu(powerplay_table->ulMaxODMemoryClock); + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception This implementation always returns 1. + */ +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const PPTable_Generic_SubTable_Header *fan_table; + ATOM_Tonga_Thermal_Controller *thermal_controller; + + thermal_controller = (ATOM_Tonga_Thermal_Controller *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usThermalControllerOffset)); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), + "Thermal controller table not set!", return -1); + + hwmgr->thermal_controller.ucType = thermal_controller->ucType; + hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + thermal_controller->ucFanParameters & + ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM + = thermal_controller->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM + = thermal_controller->ucFanMaxRPM * 100UL; + + set_hw_cap( + hwmgr, + ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController + ); + + if (0 == powerplay_table->usFanTableOffset) { + hwmgr->thermal_controller.use_hw_fan_control = 1; + return 0; + } + + fan_table = (const PPTable_Generic_SubTable_Header *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usFanTableOffset)); + + PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), + "Fan table not set!", return -1); + PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), + "Unsupported fan table format!", return -1); + + hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay + = 100000; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + if (fan_table->ucRevId < 8) { + const ATOM_Tonga_Fan_Table *tonga_fan_table = + (ATOM_Tonga_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = tonga_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = le16_to_cpu(tonga_fan_table->usTMin); + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = le16_to_cpu(tonga_fan_table->usTMed); + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = le16_to_cpu(tonga_fan_table->usTHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = le16_to_cpu(tonga_fan_table->usPWMMin); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = le16_to_cpu(tonga_fan_table->usPWMMed); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = le16_to_cpu(tonga_fan_table->usPWMHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = 10900; /* hard coded */ + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = le16_to_cpu(tonga_fan_table->usTMax); + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = tonga_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = le16_to_cpu(tonga_fan_table->usFanPWMMax); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = le16_to_cpu(tonga_fan_table->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = le16_to_cpu(tonga_fan_table->usFanRPMMax); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (le32_to_cpu(tonga_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = tonga_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = tonga_fan_table->ucMinimumPWMLimit; + } else { + const ATOM_Fiji_Fan_Table *fiji_fan_table = + (ATOM_Fiji_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = fiji_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = le16_to_cpu(fiji_fan_table->usTMin); + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = le16_to_cpu(fiji_fan_table->usTMed); + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = le16_to_cpu(fiji_fan_table->usTHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = le16_to_cpu(fiji_fan_table->usPWMMin); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = le16_to_cpu(fiji_fan_table->usPWMMed); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = le16_to_cpu(fiji_fan_table->usPWMHigh); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = le16_to_cpu(fiji_fan_table->usTMax); + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = fiji_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = le16_to_cpu(fiji_fan_table->usFanPWMMax); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = le16_to_cpu(fiji_fan_table->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = le16_to_cpu(fiji_fan_table->usFanRPMMax); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (le32_to_cpu(fiji_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = fiji_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = fiji_fan_table->ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge + = le16_to_cpu(fiji_fan_table->usFanGainEdge); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot + = le16_to_cpu(fiji_fan_table->usFanGainHotspot); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid + = le16_to_cpu(fiji_fan_table->usFanGainLiquid); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc + = le16_to_cpu(fiji_fan_table->usFanGainVrVddc); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd + = le16_to_cpu(fiji_fan_table->usFanGainVrMvdd); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx + = le16_to_cpu(fiji_fan_table->usFanGainPlx); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm + = le16_to_cpu(fiji_fan_table->usFanGainHbm); + } + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception 2 if the powerplay table is incorrect. + */ +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const ATOM_Tonga_State_Array *state_arrays; + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= + powerplay_table->sHeader.ucTableFormatRevision), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), + "State table is not set!", return -1); + PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), + "Invalid PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + return 0; +} + +static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); + + PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), + "Failed to allocate hwmgr->pptable!", return -ENOMEM); + + powerplay_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != powerplay_table), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_over_drive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_over_drive_limits failed", return result); + + result = init_clock_voltage_dependency(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_clock_voltage_dependency failed", return result); + + result = init_dpm_2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm_2_parameters failed", return result); + + return result; +} + +static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + kfree(pp_table_information->vdd_dep_on_sclk); + pp_table_information->vdd_dep_on_sclk = NULL; + + kfree(pp_table_information->vdd_dep_on_mclk); + pp_table_information->vdd_dep_on_mclk = NULL; + + kfree(pp_table_information->valid_mclk_values); + pp_table_information->valid_mclk_values = NULL; + + kfree(pp_table_information->valid_sclk_values); + pp_table_information->valid_sclk_values = NULL; + + kfree(pp_table_information->vddc_lookup_table); + pp_table_information->vddc_lookup_table = NULL; + + kfree(pp_table_information->vddgfx_lookup_table); + pp_table_information->vddgfx_lookup_table = NULL; + + kfree(pp_table_information->mm_dep_table); + pp_table_information->mm_dep_table = NULL; + + kfree(pp_table_information->cac_dtp_table); + pp_table_information->cac_dtp_table = NULL; + + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; + + kfree(pp_table_information->ppm_parameter_table); + pp_table_information->ppm_parameter_table = NULL; + + kfree(pp_table_information->pcie_table); + pp_table_information->pcie_table = NULL; + + kfree(pp_table_information->gpio_table); + pp_table_information->gpio_table = NULL; + + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + + return 0; +} + +const struct pp_table_func pptable_v1_0_funcs = { + .pptable_init = pp_tables_v1_0_initialize, + .pptable_fini = pp_tables_v1_0_uninitialize, +}; + +int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr) +{ + ATOM_Tonga_State_Array const *state_arrays; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != pp_table), + "Missing PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA), + "Incorrect PowerPlay table revision!", return -1); + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + return (uint32_t)(state_arrays->ucNumEntries); +} + +/** +* Private function to convert flags stored in the BIOS to software flags in PowerPlay. +*/ +static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, + uint16_t classification, uint16_t classification2) +{ + uint32_t result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + return result; +} + +static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) +{ + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table; + + + if (pp_table == NULL) + return 0; + + vce_state_table = (void *)pp_table + + le16_to_cpu(pp_table->usVCEStateTableOffset); + + return vce_state_table->ucNumEntries; +} + +static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, + struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag) +{ + const ATOM_Tonga_VCE_State_Record *vce_state_record; + ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; + ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; + ATOM_Tonga_MM_Dependency_Record *mm_dep_record; + const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); + const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usVCEStateTableOffset)); + const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usSclkDependencyTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMclkDependencyTableOffset)); + const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) + + le16_to_cpu(pptable->usMMDependencyTableOffset)); + + PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), + "Requested state entry ID is out of range!", + return -EINVAL); + + vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_VCE_State_Record, + entries, vce_state_table, i); + sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_SCLK_Dependency_Record, + entries, sclk_dep_table, + vce_state_record->ucSCLKIndex); + mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MM_Dependency_Record, + entries, mm_dep_table, + vce_state_record->ucVCEClockIndex); + *flag = vce_state_record->ucFlag; + + vce_state->evclk = le32_to_cpu(mm_dep_record->ulEClk); + vce_state->ecclk = le32_to_cpu(mm_dep_record->ulEClk); + vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk); + + if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + mclk_dep_table->ucNumEntries - 1); + else + mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_MCLK_Dependency_Record, + entries, mclk_dep_table, + vce_state_record->ucMCLKIndex); + + vce_state->mclk = le32_to_cpu(mclk_dep_record->ulMclk); + return 0; +} + +/** +* Create a Power State out of an entry in the PowerPlay table. +* This function is called by the hardware back-end. +* @param hwmgr Pointer to the hardware manager. +* @param entry_index The index of the entry to be extracted from the table. +* @param power_state The address of the PowerState instance being created. +* @return -1 if the entry cannot be retrieved. +*/ +int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, + uint32_t entry_index, struct pp_power_state *power_state, + int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)) +{ + int result = 0; + const ATOM_Tonga_State_Array *state_arrays; + const ATOM_Tonga_State *state_entry; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + int i, j; + uint32_t flags = 0; + + PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); + power_state->classification.bios_index = entry_index; + + if (pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA) { + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), + "Invalid PowerPlay Table State Array Offset.", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array.", return -1); + PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array Entry.", return -1); + + state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( + ATOM_Tonga_State, entries, + state_arrays, entry_index); + + result = call_back_func(hwmgr, (void *)state_entry, power_state, + (void *)pp_table, + make_classification_flags(hwmgr, + le16_to_cpu(state_entry->usClassification), + le16_to_cpu(state_entry->usClassification2))); + } + + if (!result && (power_state->classification.flags & + PP_StateClassificationFlag_Boot)) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + + hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); + + if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) { + for (j = 0; j < i; j++) + ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); + } + + return result; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h new file mode 100644 index 000000000000..b9710abdff01 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/process_pptables_v1_0.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 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 _PROCESSPPTABLES_V1_0_H +#define _PROCESSPPTABLES_V1_0_H + +#include "hwmgr.h" + +extern const struct pp_table_func pptable_v1_0_funcs; +extern int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr); +extern int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t entry_index, + struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c new file mode 100644 index 000000000000..719597c5d27d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.c @@ -0,0 +1,1732 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include +#include "processpptables.h" +#include +#include +#include "pptable.h" +#include "power_state.h" +#include "hwmgr.h" +#include "hardwaremanager.h" + + +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 + +#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 + +static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t vce_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) + vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset); + } + } + + return vce_table_offset; +} + +static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + + return 0; +} + +static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, + powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const VCEClockInfoArray *p = (const VCEClockInfoArray *) + (((unsigned long) powerplay_table) + table_offset); + table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo); + } + + return table_size; +} + +static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + get_vce_clock_info_array_size(hwmgr, + powerplay_table); + + return 0; +} + +static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset); + + table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record); + } + return table_size; +} + +static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + + if (table_offset > 0) + return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table); + + return 0; +} + +static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table); + + if (table_offset > 0) + return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset); + + return NULL; +} + +static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t uvd_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) + uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset); + } + } + return uvd_table_offset; +} + +static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + return 0; +} + +static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, + powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const UVDClockInfoArray *p = (const UVDClockInfoArray *) + (((unsigned long) powerplay_table) + + table_offset); + table_size = sizeof(UCHAR) + + p->ucNumEntries * sizeof(UVDClockInfo); + } + + return table_size; +} + +static uint16_t get_uvd_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + + get_uvd_clock_info_array_size(hwmgr, powerplay_table); + + return 0; +} + +static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t samu_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) + samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset); + } + } + + return samu_table_offset; +} + +static uint16_t get_samu_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_samu_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + + return 0; +} + +static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t acp_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) + acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset); + } + } + + return acp_table_offset; +} + +static uint16_t get_acp_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table); + + if (tableOffset > 0) + return tableOffset + 1; + + return 0; +} + +static uint16_t get_cacp_tdp_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t cacTdpTableOffset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) + cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset); + } + } + + return cacTdpTableOffset; +} + +static int get_cac_tdp_table(struct pp_hwmgr *hwmgr, + struct phm_cac_tdp_table **ptable, + const ATOM_PowerTune_Table *table, + uint16_t us_maximum_power_delivery_limit) +{ + unsigned long table_size; + struct phm_cac_tdp_table *tdp_table; + + table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table); + + tdp_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == tdp_table) + return -ENOMEM; + + tdp_table->usTDP = le16_to_cpu(table->usTDP); + tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP); + tdp_table->usTDC = le16_to_cpu(table->usTDC); + tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit); + tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit); + tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage); + tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage); + tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit; + + *ptable = tdp_table; + + return 0; +} + +static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t sclk_vdd_gfx_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) + sclk_vdd_gfx_table_offset = + le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset); + } + } + + return sclk_vdd_gfx_table_offset; +} + +static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table); + + if (tableOffset > 0) + return tableOffset; + + return 0; +} + + +static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) +{ + + unsigned long table_size, i; + struct phm_clock_voltage_dependency_table *dep_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_clock_voltage_dependency_table) + * table->ucNumEntries; + + dep_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == dep_table) + return -ENOMEM; + + dep_table->count = (unsigned long)table->ucNumEntries; + + for (i = 0; i < dep_table->count; i++) { + dep_table->entries[i].clk = + ((unsigned long)table->entries[i].ucClockHigh << 16) | + le16_to_cpu(table->entries[i].usClockLow); + dep_table->entries[i].v = + (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + } + + *ptable = dep_table; + + return 0; +} + +static int get_valid_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_array **ptable, + const struct phm_clock_voltage_dependency_table *table) +{ + unsigned long table_size, i; + struct phm_clock_array *clock_table; + + table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count; + clock_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == clock_table) + return -ENOMEM; + + clock_table->count = (unsigned long)table->count; + + for (i = 0; i < clock_table->count; i++) + clock_table->values[i] = (unsigned long)table->entries[i].clk; + + *ptable = clock_table; + + return 0; +} + +static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + const ATOM_PPLIB_Clock_Voltage_Limit_Table *table) +{ + limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) | + le16_to_cpu(table->entries[0].usSclkLow); + limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) | + le16_to_cpu(table->entries[0].usMclkLow); + limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc); + limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci); + + return 0; +} + + +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, + enum phm_platform_caps cap) +{ + if (enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + +static int set_platform_caps(struct pp_hwmgr *hwmgr, + unsigned long powerplay_caps) +{ + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s), + PHM_PlatformCaps_EnableASPML0s + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1), + PHM_PlatformCaps_EnableASPML1 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS), + PHM_PlatformCaps_EnableBackbias + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY), + PHM_PlatformCaps_GeminiPrimary + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC), + PHM_PlatformCaps_StepVddc + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL), + PHM_PlatformCaps_EnableVoltageControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL), + PHM_PlatformCaps_EnableSideportControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1), + PHM_PlatformCaps_TurnOffPll_ASPML1 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL), + PHM_PlatformCaps_EnableHTLinkControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL), + PHM_PlatformCaps_EnableMVDDControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL), + PHM_PlatformCaps_ControlVDDCI + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT), + PHM_PlatformCaps_RegulatorHot + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT), + PHM_PlatformCaps_BootStateOnAlert + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT), + PHM_PlatformCaps_DontWaitForVBlankOnAlert + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE), + PHM_PlatformCaps_NewCACVoltage + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY), + PHM_PlatformCaps_RevertGPIO5Polarity + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17), + PHM_PlatformCaps_Thermal2GPIO17 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE), + PHM_PlatformCaps_VRHotGPIOConfigurable + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION), + PHM_PlatformCaps_TempInversion + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV), + PHM_PlatformCaps_EVV + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), + PHM_PlatformCaps_LoadPostProductionFirmware + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC), + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc + ); + + return 0; +} + +static PP_StateClassificationFlags make_classification_flags( + struct pp_hwmgr *hwmgr, + USHORT classification, + USHORT classification2) +{ + PP_StateClassificationFlags result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & + ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + result |= PP_StateClassificationFlag_3DPerformance; + + + if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) + result |= PP_StateClassificationFlag_ACOverdriveTemplate; + + if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + result |= PP_StateClassificationFlag_Uvd; + + if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + result |= PP_StateClassificationFlag_UvdHD; + + if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + result |= PP_StateClassificationFlag_UvdSD; + + if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + result |= PP_StateClassificationFlag_HD2; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + result |= PP_StateClassificationFlag_ULV; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + result |= PP_StateClassificationFlag_UvdMVC; + + return result; +} + +static int init_non_clock_fields(struct pp_hwmgr *hwmgr, + struct pp_power_state *ps, + uint8_t version, + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) { + unsigned long rrr_index; + unsigned long tmp; + + ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + ps->classification.flags = make_classification_flags(hwmgr, + le16_to_cpu(pnon_clock_info->usClassification), + le16_to_cpu(pnon_clock_info->usClassification2)); + + ps->classification.temporary_state = false; + ps->classification.to_be_deleted = false; + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SINGLE_DISPLAY_ONLY; + + ps->validation.singleDisplayOnly = (0 != tmp); + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_DISALLOW_ON_DC; + + ps->validation.disallowOnDC = (0 != tmp); + + ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> + ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + + ps->pcie.lanes = 0; + + ps->display.disableFrameModulation = false; + + rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >> + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT; + + if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) { + static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \ + { 0, 50, 0 }; + + ps->display.refreshrateSource = PP_RefreshrateSource_Explicit; + ps->display.explicitRefreshrate = look_up[rrr_index]; + ps->display.limitRefreshrate = true; + + if (ps->display.explicitRefreshrate == 0) + ps->display.limitRefreshrate = false; + } else + ps->display.limitRefreshrate = false; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_ENABLE_VARIBRIGHT; + + ps->display.enableVariBright = (0 != tmp); + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF; + + ps->memory.dllOff = (0 != tmp); + + ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; + + ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * + pnon_clock_info->ucMinTemperature; + + ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * + pnon_clock_info->ucMaxTemperature; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING; + + ps->software.disableLoadBalancing = tmp; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS; + + ps->software.enableSleepForTimestamps = (0 != tmp); + + ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower; + + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) { + ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK); + ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK); + } else { + ps->uvd_clocks.VCLK = 0; + ps->uvd_clocks.DCLK = 0; + } + + return 0; +} + +static ULONG size_of_entry_v2(ULONG num_dpm_levels) +{ + return (sizeof(UCHAR) + sizeof(UCHAR) + + (num_dpm_levels * sizeof(UCHAR))); +} + +static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( + const StateArray * pstate_arrays, + ULONG entry_index) +{ + ULONG i; + const ATOM_PPLIB_STATE_V2 *pstate; + + pstate = pstate_arrays->states; + if (entry_index <= pstate_arrays->ucNumEntries) { + for (i = 0; i < entry_index; i++) + pstate = (ATOM_PPLIB_STATE_V2 *)( + (unsigned long)pstate + + size_of_entry_v2(pstate->ucNumDPMLevels)); + } + return pstate; +} + +static const unsigned char soft_dummy_pp_table[] = { + 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, + 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00, + 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, + 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59, + 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28, + 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01, + 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, + 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, + 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, + 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c, + 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01, + 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e, + 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70, + 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08, + 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70, + 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00, + 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, + 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00, + 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, + 0x00 +}; + +static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( + struct pp_hwmgr *hwmgr) +{ + const void *table_addr = hwmgr->soft_pp_table; + uint8_t frev, crev; + uint16_t size; + + if (!table_addr) { + if (hwmgr->chip_id == CHIP_RAVEN) { + table_addr = &soft_dummy_pp_table[0]; + hwmgr->soft_pp_table = &soft_dummy_pp_table[0]; + hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table); + } else { + table_addr = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, PowerPlayInfo), + &size, &frev, &crev); + hwmgr->soft_pp_table = table_addr; + hwmgr->soft_pp_table_size = size; + } + } + + return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; +} + +int pp_tables_get_response_times(struct pp_hwmgr *hwmgr, + uint32_t *vol_rep_time, uint32_t *bb_rep_time) +{ + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE(NULL != powerplay_tab, + "Missing PowerPlay Table!", return -EINVAL); + + *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime); + *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime); + + return 0; +} + +int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, + unsigned long *num_of_entries) +{ + const StateArray *pstate_arrays; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + + if (powerplay_table == NULL) + return -1; + + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries); + } else + *num_of_entries = (unsigned long)(powerplay_table->ucNumStates); + + return 0; +} + +int pp_tables_get_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, + struct pp_power_state *ps, + pp_tables_hw_clock_info_callback func) +{ + int i; + const StateArray *pstate_arrays; + const ATOM_PPLIB_STATE_V2 *pstate_entry_v2; + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + int result = 0; + int res = 0; + + const ClockInfoArray *pclock_arrays; + + const NonClockInfoArray *pnon_clock_arrays; + + const ATOM_PPLIB_STATE *pstate_entry; + + if (powerplay_table == NULL) + return -1; + + ps->classification.bios_index = entry_index; + + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + if (entry_index > pstate_arrays->ucNumEntries) + return -1; + + pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index); + pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); + + pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset)); + + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) + + (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize)); + + result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info); + + for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) { + const void *pclock_info = (const void *)( + (unsigned long)(pclock_arrays->clockInfo) + + (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize)); + res = func(hwmgr, &ps->hardware, i, pclock_info); + if ((0 == result) && (0 != res)) + result = res; + } + } else { + if (entry_index > powerplay_table->ucNumStates) + return -1; + + pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + + le16_to_cpu(powerplay_table->usStateArrayOffset) + + entry_index * powerplay_table->ucStateEntrySize); + + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table + + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) + + pstate_entry->ucNonClockStateIndex * + powerplay_table->ucNonClockSize); + + result = init_non_clock_fields(hwmgr, ps, + powerplay_table->ucNonClockSize, + pnon_clock_info); + + for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) { + const void *pclock_info = (const void *)((unsigned long)powerplay_table + + le16_to_cpu(powerplay_table->usClockInfoArrayOffset) + + pstate_entry->ucClockStateIndices[i] * + powerplay_table->ucClockInfoSize); + + int res = func(hwmgr, &ps->hardware, i, pclock_info); + + if ((0 == result) && (0 != res)) + result = res; + } + } + + if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) { + if (hwmgr->chip_family < AMDGPU_FAMILY_RV) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); + } + + return result; +} + +static int init_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table +) +{ + return 0; +} + + +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + hwmgr->thermal_controller.ucType = + powerplay_table->sThermalController.ucType; + hwmgr->thermal_controller.ucI2cLine = + powerplay_table->sThermalController.ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = + powerplay_table->sThermalController.ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (powerplay_table->sThermalController.ucFanParameters & + ATOM_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + powerplay_table->sThermalController.ucFanParameters & + ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM + = powerplay_table->sThermalController.ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM + = powerplay_table->sThermalController.ucFanMaxRPM * 100UL; + + set_hw_cap(hwmgr, + ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController); + + hwmgr->thermal_controller.use_hw_fan_control = 1; + + return 0; +} + +static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, + const ATOM_FIRMWARE_INFO_V1_4 *fw_info) +{ + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le32_to_cpu(fw_info->ulASICMaxEngineClock); + + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le32_to_cpu(fw_info->ulASICMaxMemoryClock); + + hwmgr->platform_descriptor.maxOverdriveVDDC = + le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF; + + hwmgr->platform_descriptor.minOverdriveVDDC = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + + hwmgr->platform_descriptor.maxOverdriveVDDC = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + return 0; +} + +static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, + const ATOM_FIRMWARE_INFO_V2_1 *fw_info) +{ + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3; + const ATOM_PPLIB_EXTENDEDHEADER *header; + + if (le16_to_cpu(powerplay_table->usTableSize) < + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) + return 0; + + powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + + if (0 == powerplay_table3->usExtendendedHeaderOffset) + return 0; + + header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + + hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock); + + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + return 0; +} + +static int init_overdrive_limits(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + int result = 0; + uint8_t frev, crev; + uint16_t size; + + const ATOM_COMMON_TABLE_HEADER *fw_info = NULL; + + hwmgr->platform_descriptor.overdriveLimit.engineClock = 0; + hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0; + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + if (hwmgr->chip_id == CHIP_RAVEN) + return 0; + + /* We assume here that fw_info is unchanged if this call fails.*/ + fw_info = smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if ((fw_info->ucTableFormatRevision == 1) + && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) + result = init_overdrive_limits_V1_4(hwmgr, + powerplay_table, + (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info); + + else if ((fw_info->ucTableFormatRevision == 2) + && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) + result = init_overdrive_limits_V2_1(hwmgr, + powerplay_table, + (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info); + + return result; +} + +static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_uvd_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, + const UVDClockInfoArray *array) +{ + unsigned long table_size, i; + struct phm_uvd_clock_voltage_dependency_table *uvd_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_uvd_clock_voltage_dependency_table) * + table->numEntries; + + uvd_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == uvd_table) + return -ENOMEM; + + uvd_table->count = table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + const UVDClockInfo *entry = + &array->entries[table->entries[i].ucUVDClockInfoIndex]; + uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16) + | le16_to_cpu(entry->usVClkLow); + uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16) + | le16_to_cpu(entry->usDClkLow); + } + + *ptable = uvd_table; + + return 0; +} + +static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_vce_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, + const VCEClockInfoArray *array) +{ + unsigned long table_size, i; + struct phm_vce_clock_voltage_dependency_table *vce_table = NULL; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_vce_clock_voltage_dependency_table) + * table->numEntries; + + vce_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == vce_table) + return -ENOMEM; + + vce_table->count = table->numEntries; + for (i = 0; i < table->numEntries; i++) { + const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex]; + + vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16) + | le16_to_cpu(entry->usEVClkLow); + vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16) + | le16_to_cpu(entry->usECClkLow); + } + + *ptable = vce_table; + + return 0; +} + +static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_samu_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) +{ + unsigned long table_size, i; + struct phm_samu_clock_voltage_dependency_table *samu_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_samu_clock_voltage_dependency_table) * + table->numEntries; + + samu_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == samu_table) + return -ENOMEM; + + samu_table->count = table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16) + | le16_to_cpu(table->entries[i].usSAMClockLow); + } + + *ptable = samu_table; + + return 0; +} + +static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_acp_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) +{ + unsigned table_size, i; + struct phm_acp_clock_voltage_dependency_table *acp_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_acp_clock_voltage_dependency_table) * + table->numEntries; + + acp_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == acp_table) + return -ENOMEM; + + acp_table->count = (unsigned long)table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16) + | le16_to_cpu(table->entries[i].usACPClockLow); + } + + *ptable = acp_table; + + return 0; +} + +static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + ATOM_PPLIB_Clock_Voltage_Dependency_Table *table; + ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table; + int result = 0; + + uint16_t vce_clock_info_array_offset; + uint16_t uvd_clock_info_array_offset; + uint16_t table_offset; + + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; + hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.ppm_parameter_table = NULL; + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; + + vce_clock_info_array_offset = get_vce_clock_info_array_offset( + hwmgr, powerplay_table); + table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + if (vce_clock_info_array_offset > 0 && table_offset > 0) { + const VCEClockInfoArray *array = (const VCEClockInfoArray *) + (((unsigned long) powerplay_table) + + vce_clock_info_array_offset); + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_vce_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.vce_clock_voltage_dependency_table, + table, array); + } + + uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); + table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + + if (uvd_clock_info_array_offset > 0 && table_offset > 0) { + const UVDClockInfoArray *array = (const UVDClockInfoArray *) + (((unsigned long) powerplay_table) + + uvd_clock_info_array_offset); + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_uvd_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array); + } + + table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_samu_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); + } + + table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_acp_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); + } + + table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); + if (table_offset > 0) { + UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); + + if (rev_id > 0) { + const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = + (const ATOM_PPLIB_POWERTUNE_Table_V1 *) + (((unsigned long) powerplay_table) + table_offset); + result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, + &tune_table->power_tune_table, + le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); + hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = + le16_to_cpu(tune_table->usTjMax); + } else { + const ATOM_PPLIB_POWERTUNE_Table *tune_table = + (const ATOM_PPLIB_POWERTUNE_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_cac_tdp_table(hwmgr, + &hwmgr->dyn_state.cac_dtp_table, + &tune_table->power_tune_table, 255); + } + } + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; + if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset)); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddc_dependency_on_sclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset)); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddci_dependency_on_mclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset)); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddc_dependency_on_mclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { + limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table4) + + le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset)); + result = get_clock_voltage_limit(hwmgr, + &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); + } + + if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && + (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) + result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, + hwmgr->dyn_state.vddc_dependency_on_mclk); + + if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && + (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) + result = get_valid_clk(hwmgr, + &hwmgr->dyn_state.valid_sclk_values, + hwmgr->dyn_state.vddc_dependency_on_sclk); + + if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset)); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); + } + } + + table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); + } + + return result; +} + +static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, + struct phm_cac_leakage_table **ptable, + const ATOM_PPLIB_CAC_Leakage_Table *table) +{ + struct phm_cac_leakage_table *cac_leakage_table; + unsigned long table_size, i; + + if (hwmgr == NULL || table == NULL || ptable == NULL) + return -EINVAL; + + table_size = sizeof(ULONG) + + (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); + + cac_leakage_table = kzalloc(table_size, GFP_KERNEL); + + if (cac_leakage_table == NULL) + return -ENOMEM; + + cac_leakage_table->count = (ULONG)table->ucNumEntries; + + for (i = 0; i < cac_leakage_table->count; i++) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV)) { + cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); + cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); + cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); + } else { + cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); + cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); + } + } + + *ptable = cac_leakage_table; + + return 0; +} + +static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, + ATOM_PPLIB_PPM_Table *atom_ppm_table) +{ + struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL); + + if (NULL == ptr) + return -ENOMEM; + + ptr->ppm_design = atom_ppm_table->ucPpmDesign; + ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); + ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); + ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); + ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); + ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); + ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); + ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); + ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); + ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); + hwmgr->dyn_state.ppm_parameter_table = ptr; + + return 0; +} + +static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + int result = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { + const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = + (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; + const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *) + (&ptable5->basicTable4); + const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *) + (&ptable4->basicTable3); + const ATOM_PPLIB_EXTENDEDHEADER *extended_header; + uint16_t table_offset; + ATOM_PPLIB_PPM_Table *atom_ppm_table; + + hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); + hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); + + hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); + + if (hwmgr->platform_descriptor.TDPODLimit != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + + hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); + + hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); + + hwmgr->dyn_state.cac_leakage_table = NULL; + + if (0 != ptable5->usCACLeakageTableOffset) { + const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = + (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + + le16_to_cpu(ptable5->usCACLeakageTableOffset)); + result = get_cac_leakage_table(hwmgr, + &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); + } + + hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); + + hwmgr->dyn_state.ppm_parameter_table = NULL; + + if (0 != ptable3->usExtendendedHeaderOffset) { + extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table) + + le16_to_cpu(ptable3->usExtendendedHeaderOffset)); + if ((extended_header->usPPMTableOffset > 0) && + le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { + table_offset = le16_to_cpu(extended_header->usPPMTableOffset); + atom_ppm_table = (ATOM_PPLIB_PPM_Table *) + (((unsigned long)powerplay_table) + table_offset); + if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnablePlatformPowerManagement); + } + } + } + return result; +} + +static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; + + if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { + const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = + (ATOM_PPLIB_PhaseSheddingLimits_Table *) + (((unsigned long)powerplay_table4) + + le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); + struct phm_phase_shedding_limits_table *table; + unsigned long size, i; + + + size = sizeof(unsigned long) + + (sizeof(struct phm_phase_shedding_limits_table) * + ptable->ucNumEntries); + + table = kzalloc(size, GFP_KERNEL); + + if (table == NULL) + return -ENOMEM; + + table->count = (unsigned long)ptable->ucNumEntries; + + for (i = 0; i < table->count; i++) { + table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); + table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) + | le16_to_cpu(ptable->entries[i].usSclkLow); + table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) + | le16_to_cpu(ptable->entries[i].usMclkLow); + } + hwmgr->dyn_state.vddc_phase_shed_limits_table = table; + } + } + + return 0; +} + +static int get_number_of_vce_state_table_entries( + struct pp_hwmgr *hwmgr) +{ + const ATOM_PPLIB_POWERPLAYTABLE *table = + get_powerplay_table(hwmgr); + const ATOM_PPLIB_VCE_State_Table *vce_table = + get_vce_state_table(hwmgr, table); + + if (vce_table) + return vce_table->numEntries; + + return 0; +} + +static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, + unsigned long i, + struct amd_vce_state *vce_state, + void **clock_info, + unsigned long *flag) +{ + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + + const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); + + unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); + + const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); + + const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); + + const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; + + const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; + + unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; + + *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); + + vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow); + vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow); + + *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); + + return 0; +} + + +static int pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; + + if (hwmgr->chip_id == CHIP_RAVEN) + return 0; + + hwmgr->need_pp_table_upload = true; + + powerplay_table = get_powerplay_table(hwmgr); + + result = init_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_overdrive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_overdrive_limits failed", return result); + + result = init_clock_voltage_dependency(hwmgr, + powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_clock_voltage_dependency failed", return result); + + result = init_dpm2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm2_parameters failed", return result); + + result = init_phase_shedding_table(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_phase_shedding_table failed", return result); + + return result; +} + +static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->chip_id == CHIP_RAVEN) + return 0; + + kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; + + kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; + + kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; + + kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; + + kfree(hwmgr->dyn_state.valid_mclk_values); + hwmgr->dyn_state.valid_mclk_values = NULL; + + kfree(hwmgr->dyn_state.valid_sclk_values); + hwmgr->dyn_state.valid_sclk_values = NULL; + + kfree(hwmgr->dyn_state.cac_leakage_table); + hwmgr->dyn_state.cac_leakage_table = NULL; + + kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); + hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; + + kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); + hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; + + kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); + hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; + + kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; + + kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; + + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; + + kfree(hwmgr->dyn_state.ppm_parameter_table); + hwmgr->dyn_state.ppm_parameter_table = NULL; + + kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; + + return 0; +} + +const struct pp_table_func pptable_funcs = { + .pptable_init = pp_tables_initialize, + .pptable_fini = pp_tables_uninitialize, + .pptable_get_number_of_vce_state_table_entries = + get_number_of_vce_state_table_entries, + .pptable_get_vce_state_table_entry = + get_vce_state_table_entry, +}; + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h new file mode 100644 index 000000000000..baddaa75693b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/processpptables.h @@ -0,0 +1,50 @@ +/* + * Copyright 2015 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. + * Interface Functions related to the BIOS PowerPlay Tables. + * + */ + +#ifndef PROCESSPPTABLES_H +#define PROCESSPPTABLES_H + +struct pp_hwmgr; +struct pp_power_state; +struct pp_hw_power_state; + +extern const struct pp_table_func pptable_funcs; + +typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps, + unsigned int index, + const void *clock_info); + +int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, + unsigned long *num_of_entries); + +int pp_tables_get_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, + struct pp_power_state *ps, + pp_tables_hw_clock_info_callback func); + +int pp_tables_get_response_times(struct pp_hwmgr *hwmgr, + uint32_t *vol_rep_time, uint32_t *bb_rep_time); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c new file mode 100644 index 000000000000..c9cfe90a2947 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -0,0 +1,1404 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include "atom-types.h" +#include "atombios.h" +#include "processpptables.h" +#include "cgs_common.h" +#include "smumgr.h" +#include "hwmgr.h" +#include "hardwaremanager.h" +#include "rv_ppsmc.h" +#include "smu10_hwmgr.h" +#include "power_state.h" +#include "soc15_common.h" +#include "smu10.h" +#include "asic_reg/pwr/pwr_10_0_offset.h" +#include "asic_reg/pwr/pwr_10_0_sh_mask.h" + +#define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define SMU10_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */ +#define SCLK_MIN_DIV_INTV_SHIFT 12 +#define SMU10_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */ +#define SMC_RAM_END 0x40000 + +static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic; + + +static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock_req) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + enum amd_pp_clock_type clk_type = clock_req->clock_type; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + PPSMC_Msg msg; + + switch (clk_type) { + case amd_pp_dcf_clock: + if (clk_freq == smu10_data->dcf_actual_hard_min_freq) + return 0; + msg = PPSMC_MSG_SetHardMinDcefclkByFreq; + smu10_data->dcf_actual_hard_min_freq = clk_freq; + break; + case amd_pp_soc_clock: + msg = PPSMC_MSG_SetHardMinSocclkByFreq; + break; + case amd_pp_f_clock: + if (clk_freq == smu10_data->f_actual_hard_min_freq) + return 0; + smu10_data->f_actual_hard_min_freq = clk_freq; + msg = PPSMC_MSG_SetHardMinFclkByFreq; + break; + default: + pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); + return -EINVAL; + } + smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq, NULL); + + return 0; +} + +static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps) +{ + if (SMU10_Magic != hw_ps->magic) + return NULL; + + return (struct smu10_power_state *)hw_ps; +} + +static const struct smu10_power_state *cast_const_smu10_ps( + const struct pp_hw_power_state *hw_ps) +{ + if (SMU10_Magic != hw_ps->magic) + return NULL; + + return (struct smu10_power_state *)hw_ps; +} + +static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + smu10_data->dce_slow_sclk_threshold = 30000; + smu10_data->thermal_auto_throttling_treshold = 0; + smu10_data->is_nb_dpm_enabled = 1; + smu10_data->dpm_flags = 1; + smu10_data->need_min_deep_sleep_dcefclk = true; + smu10_data->num_active_display = 0; + smu10_data->deep_sleep_dcefclk = 0; + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerPlaySupport); + return 0; +} + +static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *table) +{ + return 0; +} + +static int smu10_init_dynamic_state_adjustment_rule_settings( + struct pp_hwmgr *hwmgr) +{ + struct phm_clock_voltage_dependency_table *table_clk_vlt; + + table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), + GFP_KERNEL); + + if (NULL == table_clk_vlt) { + pr_err("Can not allocate memory!\n"); + return -ENOMEM; + } + + table_clk_vlt->count = 8; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; + table_clk_vlt->entries[1].v = 1; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; + table_clk_vlt->entries[2].v = 2; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; + table_clk_vlt->entries[3].v = 3; + table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; + table_clk_vlt->entries[4].v = 4; + table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; + table_clk_vlt->entries[5].v = 5; + table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; + table_clk_vlt->entries[6].v = 6; + table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; + table_clk_vlt->entries[7].v = 7; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + + return 0; +} + +static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend; + + smu10_data->sys_info.htc_hyst_lmt = 5; + smu10_data->sys_info.htc_tmp_lmt = 203; + + if (smu10_data->thermal_auto_throttling_treshold == 0) + smu10_data->thermal_auto_throttling_treshold = 203; + + smu10_construct_max_power_limits_table (hwmgr, + &hwmgr->dyn_state.max_clock_voltage_on_ac); + + smu10_init_dynamic_state_adjustment_rule_settings(hwmgr); + + return 0; +} + +static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input) +{ + struct PP_Clocks clocks = {0}; + struct pp_display_clock_request clock_req; + + clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; + clock_req.clock_type = amd_pp_dcf_clock; + clock_req.clock_freq_in_khz = clocks.dcefClock * 10; + + PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req), + "Attempt to set DCF Clock Failed!", return -EINVAL); + + return 0; +} + +static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (smu10_data->need_min_deep_sleep_dcefclk && + smu10_data->deep_sleep_dcefclk != clock) { + smu10_data->deep_sleep_dcefclk = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepDcefclk, + smu10_data->deep_sleep_dcefclk, + NULL); + } + return 0; +} + +static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (smu10_data->dcf_actual_hard_min_freq && + smu10_data->dcf_actual_hard_min_freq != clock) { + smu10_data->dcf_actual_hard_min_freq = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinDcefclkByFreq, + smu10_data->dcf_actual_hard_min_freq, + NULL); + } + return 0; +} + +static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (smu10_data->f_actual_hard_min_freq && + smu10_data->f_actual_hard_min_freq != clock) { + smu10_data->f_actual_hard_min_freq = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + smu10_data->f_actual_hard_min_freq, + NULL); + } + return 0; +} + +static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (smu10_data->num_active_display != count) { + smu10_data->num_active_display = count; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDisplayCount, + smu10_data->num_active_display, + NULL); + } + + return 0; +} + +static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + return smu10_set_clock_limit(hwmgr, input); +} + +static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + + smu10_data->vcn_power_gated = true; + smu10_data->isp_tileA_power_gated = true; + smu10_data->isp_tileB_power_gated = true; + + if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetGfxCGPG, + true, + NULL); + else + return 0; +} + + +static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + return smu10_init_power_gate_state(hwmgr); +} + +static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + smu10_data->separation_time = 0; + smu10_data->cc6_disable = false; + smu10_data->pstate_disable = false; + smu10_data->cc6_setting_changed = false; + + return 0; +} + +static int smu10_power_off_asic(struct pp_hwmgr *hwmgr) +{ + return smu10_reset_cc6_data(hwmgr); +} + +static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr) +{ + uint32_t reg; + struct amdgpu_device *adev = hwmgr->adev; + + reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS); + if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) == + (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT)) + return true; + + return false; +} + +static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) { + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff, NULL); + + /* confirm gfx is back to "on" state */ + while (!smu10_is_gfx_on(hwmgr)) + msleep(1); + } + + return 0; +} + +static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff, NULL); + + return 0; +} + +static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) +{ + if (enable) + return smu10_enable_gfx_off(hwmgr); + else + return smu10_disable_gfx_off(hwmgr); +} + +static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps) +{ + return 0; +} + +/* temporary hardcoded clock voltage breakdown tables */ +static const DpmClock_t VddDcfClk[]= { + { 300, 2600}, + { 600, 3200}, + { 600, 3600}, +}; + +static const DpmClock_t VddSocClk[]= { + { 478, 2600}, + { 722, 3200}, + { 722, 3600}, +}; + +static const DpmClock_t VddFClk[]= { + { 400, 2600}, + {1200, 3200}, + {1200, 3600}, +}; + +static const DpmClock_t VddDispClk[]= { + { 435, 2600}, + { 661, 3200}, + {1086, 3600}, +}; + +static const DpmClock_t VddDppClk[]= { + { 435, 2600}, + { 661, 3200}, + { 661, 3600}, +}; + +static const DpmClock_t VddPhyClk[]= { + { 540, 2600}, + { 810, 3200}, + { 810, 3600}, +}; + +static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, + struct smu10_voltage_dependency_table **pptable, + uint32_t num_entry, const DpmClock_t *pclk_dependency_table) +{ + uint32_t i; + struct smu10_voltage_dependency_table *ptable; + + ptable = kzalloc(struct_size(ptable, entries, num_entry), GFP_KERNEL); + if (NULL == ptable) + return -ENOMEM; + + ptable->count = num_entry; + + for (i = 0; i < ptable->count; i++) { + ptable->entries[i].clk = pclk_dependency_table->Freq * 100; + ptable->entries[i].vol = pclk_dependency_table->Vol; + pclk_dependency_table++; + } + + *pptable = ptable; + + return 0; +} + + +static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr) +{ + uint32_t result; + + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + DpmClocks_t *table = &(smu10_data->clock_table); + struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); + + result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true); + + PP_ASSERT_WITH_CODE((0 == result), + "Attempt to copy clock table from smc failed", + return result); + + if (0 == result && table->DcefClocks[0].Freq != 0) { + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, + NUM_DCEFCLK_DPM_LEVELS, + &smu10_data->clock_table.DcefClocks[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, + NUM_SOCCLK_DPM_LEVELS, + &smu10_data->clock_table.SocClocks[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, + NUM_FCLK_DPM_LEVELS, + &smu10_data->clock_table.FClocks[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk, + NUM_MEMCLK_DPM_LEVELS, + &smu10_data->clock_table.MemClocks[0]); + } else { + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, + ARRAY_SIZE(VddDcfClk), + &VddDcfClk[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, + ARRAY_SIZE(VddSocClk), + &VddSocClk[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, + ARRAY_SIZE(VddFClk), + &VddFClk[0]); + } + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk, + ARRAY_SIZE(VddDispClk), + &VddDispClk[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk, + ARRAY_SIZE(VddDppClk), &VddDppClk[0]); + smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk, + ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &result); + smu10_data->gfx_min_freq_limit = result / 10 * 1000; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &result); + smu10_data->gfx_max_freq_limit = result / 10 * 1000; + + return 0; +} + +static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct smu10_hwmgr *data; + + data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + + result = smu10_initialize_dpm_defaults(hwmgr); + if (result != 0) { + pr_err("smu10_initialize_dpm_defaults failed\n"); + return result; + } + + smu10_populate_clock_table(hwmgr); + + result = smu10_get_system_info_data(hwmgr); + if (result != 0) { + pr_err("smu10_get_system_info_data failed\n"); + return result; + } + + smu10_construct_boot_state(hwmgr); + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + SMU10_MAX_HARDWARE_POWERLEVELS; + + hwmgr->platform_descriptor.hardwarePerformanceLevels = + SMU10_MAX_HARDWARE_POWERLEVELS; + + hwmgr->platform_descriptor.vbiosInterruptId = 0; + + hwmgr->platform_descriptor.clockStep.engineClock = 500; + + hwmgr->platform_descriptor.clockStep.memoryClock = 500; + + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100; + hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100; + + return result; +} + +static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); + + kfree(pinfo->vdd_dep_on_dcefclk); + pinfo->vdd_dep_on_dcefclk = NULL; + kfree(pinfo->vdd_dep_on_socclk); + pinfo->vdd_dep_on_socclk = NULL; + kfree(pinfo->vdd_dep_on_fclk); + pinfo->vdd_dep_on_fclk = NULL; + kfree(pinfo->vdd_dep_on_dispclk); + pinfo->vdd_dep_on_dispclk = NULL; + kfree(pinfo->vdd_dep_on_dppclk); + pinfo->vdd_dep_on_dppclk = NULL; + kfree(pinfo->vdd_dep_on_phyclk); + pinfo->vdd_dep_on_phyclk = NULL; + + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + struct smu10_hwmgr *data = hwmgr->backend; + uint32_t min_sclk = hwmgr->display_config->min_core_set_clock; + uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100; + + if (hwmgr->smu_version < 0x1E3700) { + pr_info("smu firmware version too old, can not set dpm level\n"); + return 0; + } + + if (min_sclk < data->gfx_min_freq_limit) + min_sclk = data->gfx_min_freq_limit; + + min_sclk /= 100; /* transfer 10KHz to MHz */ + if (min_mclk < data->clock_table.FClocks[0].Freq) + min_mclk = data->clock_table.FClocks[0].Freq; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + data->gfx_max_freq_limit/100, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + SMU10_UMD_PSTATE_PEAK_FCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinSocclkByFreq, + SMU10_UMD_PSTATE_PEAK_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinVcn, + SMU10_UMD_PSTATE_VCE, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + data->gfx_max_freq_limit/100, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + SMU10_UMD_PSTATE_PEAK_FCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxSocclkByFreq, + SMU10_UMD_PSTATE_PEAK_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxVcn, + SMU10_UMD_PSTATE_VCE, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + min_sclk, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + min_sclk, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + min_mclk, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + min_mclk, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + SMU10_UMD_PSTATE_GFXCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + SMU10_UMD_PSTATE_FCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinSocclkByFreq, + SMU10_UMD_PSTATE_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinVcn, + SMU10_UMD_PSTATE_VCE, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + SMU10_UMD_PSTATE_GFXCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + SMU10_UMD_PSTATE_FCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxSocclkByFreq, + SMU10_UMD_PSTATE_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxVcn, + SMU10_UMD_PSTATE_VCE, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + min_sclk, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + hwmgr->display_config->num_display > 3 ? + SMU10_UMD_PSTATE_PEAK_FCLK : + min_mclk, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinSocclkByFreq, + SMU10_UMD_PSTATE_MIN_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinVcn, + SMU10_UMD_PSTATE_MIN_VCE, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + data->gfx_max_freq_limit/100, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + SMU10_UMD_PSTATE_PEAK_FCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxSocclkByFreq, + SMU10_UMD_PSTATE_PEAK_SOCCLK, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxVcn, + SMU10_UMD_PSTATE_VCE, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + data->gfx_min_freq_limit/100, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + data->gfx_min_freq_limit/100, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + min_mclk, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + min_mclk, + NULL); + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + return 0; +} + +static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct smu10_hwmgr *data; + + if (hwmgr == NULL) + return -EINVAL; + + data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (low) + return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; + else + return data->clock_vol_info.vdd_dep_on_fclk->entries[ + data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; +} + +static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct smu10_hwmgr *data; + + if (hwmgr == NULL) + return -EINVAL; + + data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (low) + return data->gfx_min_freq_limit; + else + return data->gfx_max_freq_limit; +} + +static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + return 0; +} + +static int smu10_dpm_get_pp_table_entry_callback( + struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps, + unsigned int index, + const void *clock_info) +{ + struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps); + + smu10_ps->levels[index].engine_clock = 0; + + smu10_ps->levels[index].vddc_index = 0; + smu10_ps->level = index + 1; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + smu10_ps->levels[index].ds_divider_index = 5; + smu10_ps->levels[index].ss_divider_index = 5; + } + + return 0; +} + +static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned long ret = 0; + + result = pp_tables_get_num_of_entries(hwmgr, &ret); + + return result ? 0 : ret; +} + +static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry, struct pp_power_state *ps) +{ + int result; + struct smu10_power_state *smu10_ps; + + ps->hardware.magic = SMU10_Magic; + + smu10_ps = cast_smu10_ps(&(ps->hardware)); + + result = pp_tables_get_entry(hwmgr, entry, ps, + smu10_dpm_get_pp_table_entry_callback); + + smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; + smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; + + return result; +} + +static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct smu10_power_state); +} + +static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr) +{ + return 0; +} + + +static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) +{ + struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (separation_time != data->separation_time || + cc6_disable != data->cc6_disable || + pstate_disable != data->pstate_disable) { + data->separation_time = separation_time; + data->cc6_disable = cc6_disable; + data->pstate_disable = pstate_disable; + data->cc6_setting_changed = true; + } + return 0; +} + +static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ + return -EINVAL; +} + +static int smu10_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + struct smu10_hwmgr *data = hwmgr->backend; + struct smu10_voltage_dependency_table *mclk_table = + data->clock_vol_info.vdd_dep_on_fclk; + uint32_t low, high; + + low = mask ? (ffs(mask) - 1) : 0; + high = mask ? (fls(mask) - 1) : 0; + + switch (type) { + case PP_SCLK: + if (low > 2 || high > 2) { + pr_info("Currently sclk only support 3 levels on RV\n"); + return -EINVAL; + } + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinGfxClk, + low == 2 ? data->gfx_max_freq_limit/100 : + low == 1 ? SMU10_UMD_PSTATE_GFXCLK : + data->gfx_min_freq_limit/100, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxClk, + high == 0 ? data->gfx_min_freq_limit/100 : + high == 1 ? SMU10_UMD_PSTATE_GFXCLK : + data->gfx_max_freq_limit/100, + NULL); + break; + + case PP_MCLK: + if (low > mclk_table->count - 1 || high > mclk_table->count - 1) + return -EINVAL; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinFclkByFreq, + mclk_table->entries[low].clk/100, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxFclkByFreq, + mclk_table->entries[high].clk/100, + NULL); + break; + + case PP_PCIE: + default: + break; + } + return 0; +} + +static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); + struct smu10_voltage_dependency_table *mclk_table = + data->clock_vol_info.vdd_dep_on_fclk; + uint32_t i, now, size = 0; + + switch (type) { + case PP_SCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &now); + + /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ + if (now == data->gfx_max_freq_limit/100) + i = 2; + else if (now == data->gfx_min_freq_limit/100) + i = 0; + else + i = 1; + + size += sprintf(buf + size, "0: %uMhz %s\n", + data->gfx_min_freq_limit/100, + i == 0 ? "*" : ""); + size += sprintf(buf + size, "1: %uMhz %s\n", + i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK, + i == 1 ? "*" : ""); + size += sprintf(buf + size, "2: %uMhz %s\n", + data->gfx_max_freq_limit/100, + i == 2 ? "*" : ""); + break; + case PP_MCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now); + + for (i = 0; i < mclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, + mclk_table->entries[i].clk / 100, + ((mclk_table->entries[i].clk / 100) + == now) ? "*" : ""); + break; + default: + break; + } + + return size; +} + +static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + struct smu10_hwmgr *data; + + if (level == NULL || hwmgr == NULL || state == NULL) + return -EINVAL; + + data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (index == 0) { + level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; + level->coreClock = data->gfx_min_freq_limit; + } else { + level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[ + data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; + level->coreClock = data->gfx_max_freq_limit; + } + + level->nonLocalMemoryFreq = 0; + level->nonLocalMemoryWidth = 0; + + return 0; +} + +static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) +{ + const struct smu10_power_state *ps = cast_const_smu10_ps(state); + + clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index)); + clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index)); + + return 0; +} + +#define MEM_FREQ_LOW_LATENCY 25000 +#define MEM_FREQ_HIGH_LATENCY 80000 +#define MEM_LATENCY_HIGH 245 +#define MEM_LATENCY_LOW 35 +#define MEM_LATENCY_ERR 0xFFFF + + +static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr, + uint32_t clock) +{ + if (clock >= MEM_FREQ_LOW_LATENCY && + clock < MEM_FREQ_HIGH_LATENCY) + return MEM_LATENCY_HIGH; + else if (clock >= MEM_FREQ_HIGH_LATENCY) + return MEM_LATENCY_LOW; + else + return MEM_LATENCY_ERR; +} + +static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + uint32_t i; + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); + struct smu10_voltage_dependency_table *pclk_vol_table; + bool latency_required = false; + + if (pinfo == NULL) + return -EINVAL; + + switch (type) { + case amd_pp_mem_clock: + pclk_vol_table = pinfo->vdd_dep_on_mclk; + latency_required = true; + break; + case amd_pp_f_clock: + pclk_vol_table = pinfo->vdd_dep_on_fclk; + latency_required = true; + break; + case amd_pp_dcf_clock: + pclk_vol_table = pinfo->vdd_dep_on_dcefclk; + break; + case amd_pp_disp_clock: + pclk_vol_table = pinfo->vdd_dep_on_dispclk; + break; + case amd_pp_phy_clock: + pclk_vol_table = pinfo->vdd_dep_on_phyclk; + break; + case amd_pp_dpp_clock: + pclk_vol_table = pinfo->vdd_dep_on_dppclk; + break; + default: + return -EINVAL; + } + + if (pclk_vol_table == NULL || pclk_vol_table->count == 0) + return -EINVAL; + + clocks->num_levels = 0; + for (i = 0; i < pclk_vol_table->count; i++) { + if (pclk_vol_table->entries[i].clk) { + clocks->data[clocks->num_levels].clocks_in_khz = + pclk_vol_table->entries[i].clk * 10; + clocks->data[clocks->num_levels].latency_in_us = latency_required ? + smu10_get_mem_latency(hwmgr, + pclk_vol_table->entries[i].clk) : + 0; + clocks->num_levels++; + } + } + + return 0; +} + +static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + uint32_t i; + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); + struct smu10_voltage_dependency_table *pclk_vol_table = NULL; + + if (pinfo == NULL) + return -EINVAL; + + switch (type) { + case amd_pp_mem_clock: + pclk_vol_table = pinfo->vdd_dep_on_mclk; + break; + case amd_pp_f_clock: + pclk_vol_table = pinfo->vdd_dep_on_fclk; + break; + case amd_pp_dcf_clock: + pclk_vol_table = pinfo->vdd_dep_on_dcefclk; + break; + case amd_pp_soc_clock: + pclk_vol_table = pinfo->vdd_dep_on_socclk; + break; + case amd_pp_disp_clock: + pclk_vol_table = pinfo->vdd_dep_on_dispclk; + break; + case amd_pp_phy_clock: + pclk_vol_table = pinfo->vdd_dep_on_phyclk; + break; + default: + return -EINVAL; + } + + if (pclk_vol_table == NULL || pclk_vol_table->count == 0) + return -EINVAL; + + clocks->num_levels = 0; + for (i = 0; i < pclk_vol_table->count; i++) { + if (pclk_vol_table->entries[i].clk) { + clocks->data[clocks->num_levels].clocks_in_khz = pclk_vol_table->entries[i].clk * 10; + clocks->data[clocks->num_levels].voltage_in_mv = pclk_vol_table->entries[i].vol; + clocks->num_levels++; + } + } + + return 0; +} + + + +static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) +{ + clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */ + return 0; +} + +static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t reg_value = RREG32_SOC15(THM, 0, mmTHM_TCON_CUR_TMP); + int cur_temp = + (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT; + + if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK) + cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + else + cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return cur_temp; +} + +static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + uint32_t sclk, mclk; + int ret = 0; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &sclk); + /* in units of 10KHZ */ + *((uint32_t *)value) = sclk * 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &mclk); + /* in units of 10KHZ */ + *((uint32_t *)value) = mclk * 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr); + break; + case AMDGPU_PP_SENSOR_VCN_POWER_STATE: + *(uint32_t *)value = smu10_data->vcn_power_gated ? 0 : 1; + *size = 4; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_ranges) +{ + struct smu10_hwmgr *data = hwmgr->backend; + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; + Watermarks_t *table = &(data->water_marks_table); + + smu_set_watermarks_for_clocks_ranges(table,wm_with_clock_ranges); + smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false); + data->water_marks_exist = true; + return 0; +} + +static int smu10_smus_notify_pwe(struct pp_hwmgr *hwmgr) +{ + + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SetRccPfcPmeRestoreRegister, NULL); +} + +static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub, NULL); +} + +static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate) +{ + if (gate) + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma, NULL); + else + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma, NULL); +} + +static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); + + if (bgate) { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCN, + AMD_PG_STATE_GATE); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PowerDownVcn, 0, NULL); + smu10_data->vcn_power_gated = true; + } else { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PowerUpVcn, 0, NULL); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCN, + AMD_PG_STATE_UNGATE); + smu10_data->vcn_power_gated = false; + } +} + +static int conv_power_profile_to_pplib_workload(int power_profile) +{ + int pplib_workload = 0; + + switch (power_profile) { + case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: + pplib_workload = WORKLOAD_DEFAULT_BIT; + break; + case PP_SMC_POWER_PROFILE_FULLSCREEN3D: + pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; + break; + case PP_SMC_POWER_PROFILE_POWERSAVING: + pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; + break; + case PP_SMC_POWER_PROFILE_VIDEO: + pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; + break; + case PP_SMC_POWER_PROFILE_VR: + pplib_workload = WORKLOAD_PPLIB_VR_BIT; + break; + case PP_SMC_POWER_PROFILE_COMPUTE: + pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; + break; + } + + return pplib_workload; +} + +static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) +{ + uint32_t i, size = 0; + static const uint8_t + profile_mode_setting[6][4] = {{70, 60, 0, 0,}, + {70, 60, 1, 3,}, + {90, 60, 0, 0,}, + {70, 60, 0, 0,}, + {70, 90, 0, 0,}, + {30, 60, 0, 6,}, + }; + static const char *profile_name[6] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE"}; + static const char *title[6] = {"NUM", + "MODE_NAME", + "BUSY_SET_POINT", + "FPS", + "USE_RLC_BUSY", + "MIN_ACTIVE_LEVEL"}; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], + title[1], title[2], title[3], title[4], title[5]); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++) + size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", + i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", + profile_mode_setting[i][0], profile_mode_setting[i][1], + profile_mode_setting[i][2], profile_mode_setting[i][3]); + + return size; +} + +static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + if ((adev->apu_flags & AMD_APU_IS_RAVEN) && + (hwmgr->smu_version >= 0x41e2b)) + return true; + else + return false; +} + +static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) +{ + int workload_type = 0; + int result = 0; + + if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) { + pr_err("Invalid power profile mode %ld\n", input[size]); + return -EINVAL; + } + if (hwmgr->power_profile_mode == input[size]) + return 0; + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = + conv_power_profile_to_pplib_workload(input[size]); + if (workload_type && + smu10_is_raven1_refresh(hwmgr) && + !hwmgr->gfxoff_state_changed_by_workload) { + smu10_gfx_off_control(hwmgr, false); + hwmgr->gfxoff_state_changed_by_workload = true; + } + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify, + 1 << workload_type, + NULL); + if (!result) + hwmgr->power_profile_mode = input[size]; + if (workload_type && hwmgr->gfxoff_state_changed_by_workload) { + smu10_gfx_off_control(hwmgr, true); + hwmgr->gfxoff_state_changed_by_workload = false; + } + + return 0; +} + +static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode) +{ + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DeviceDriverReset, + mode, + NULL); +} + +static const struct pp_hwmgr_func smu10_hwmgr_funcs = { + .backend_init = smu10_hwmgr_backend_init, + .backend_fini = smu10_hwmgr_backend_fini, + .apply_state_adjust_rules = smu10_apply_state_adjust_rules, + .force_dpm_level = smu10_dpm_force_dpm_level, + .get_power_state_size = smu10_get_power_state_size, + .powerdown_uvd = NULL, + .powergate_uvd = smu10_powergate_vcn, + .powergate_vce = NULL, + .get_mclk = smu10_dpm_get_mclk, + .get_sclk = smu10_dpm_get_sclk, + .patch_boot_state = smu10_dpm_patch_boot_state, + .get_pp_table_entry = smu10_dpm_get_pp_table_entry, + .get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries, + .set_cpu_power_state = smu10_set_cpu_power_state, + .store_cc6_data = smu10_store_cc6_data, + .force_clock_level = smu10_force_clock_level, + .print_clock_levels = smu10_print_clock_levels, + .get_dal_power_level = smu10_get_dal_power_level, + .get_performance_level = smu10_get_performance_level, + .get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks, + .get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency, + .get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage, + .set_watermarks_for_clocks_ranges = smu10_set_watermarks_for_clocks_ranges, + .get_max_high_clocks = smu10_get_max_high_clocks, + .read_sensor = smu10_read_sensor, + .set_active_display_count = smu10_set_active_display_count, + .set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk, + .dynamic_state_management_enable = smu10_enable_dpm_tasks, + .power_off_asic = smu10_power_off_asic, + .asic_setup = smu10_setup_asic_task, + .power_state_set = smu10_set_power_state_tasks, + .dynamic_state_management_disable = smu10_disable_dpm_tasks, + .powergate_mmhub = smu10_powergate_mmhub, + .smus_notify_pwe = smu10_smus_notify_pwe, + .display_clock_voltage_request = smu10_display_clock_voltage_request, + .powergate_gfx = smu10_gfx_off_control, + .powergate_sdma = smu10_powergate_sdma, + .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, + .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, + .get_power_profile_mode = smu10_get_power_profile_mode, + .set_power_profile_mode = smu10_set_power_profile_mode, + .asic_reset = smu10_asic_reset, +}; + +int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) +{ + hwmgr->hwmgr_func = &smu10_hwmgr_funcs; + hwmgr->pptable_func = &pptable_funcs; + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h new file mode 100644 index 000000000000..0f969de10fab --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.h @@ -0,0 +1,321 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef SMU10_HWMGR_H +#define SMU10_HWMGR_H + +#include "hwmgr.h" +#include "smu10_inc.h" +#include "smu10_driver_if.h" +#include "rv_ppsmc.h" + + +#define SMU10_MAX_HARDWARE_POWERLEVELS 8 +#define SMU10_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15 + +#define DPMFlags_SCLK_Enabled 0x00000001 +#define DPMFlags_UVD_Enabled 0x00000002 +#define DPMFlags_VCE_Enabled 0x00000004 +#define DPMFlags_ACP_Enabled 0x00000008 +#define DPMFlags_ForceHighestValid 0x40000000 + +/* Do not change the following, it is also defined in SMU8.h */ +#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001 +#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000 +#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x01000000 +#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x02000000 + +#define SMU_PHYID_SHIFT 8 + +#define SMU10_PCIE_POWERGATING_TARGET_GFX 0 +#define SMU10_PCIE_POWERGATING_TARGET_DDI 1 +#define SMU10_PCIE_POWERGATING_TARGET_PLLCASCADE 2 +#define SMU10_PCIE_POWERGATING_TARGET_PHY 3 + +enum VQ_TYPE { + CLOCK_TYPE_DCLK = 0L, + CLOCK_TYPE_ECLK, + CLOCK_TYPE_SCLK, + CLOCK_TYPE_CCLK, + VQ_GFX_CU +}; + +#define SUSTAINABLE_SCLK_MASK 0x00ffffff +#define SUSTAINABLE_SCLK_SHIFT 0 +#define SUSTAINABLE_CU_MASK 0xff000000 +#define SUSTAINABLE_CU_SHIFT 24 + +struct smu10_dpm_entry { + uint32_t soft_min_clk; + uint32_t hard_min_clk; + uint32_t soft_max_clk; + uint32_t hard_max_clk; +}; + +struct smu10_power_level { + uint32_t engine_clock; + uint8_t vddc_index; + uint8_t ds_divider_index; + uint8_t ss_divider_index; + uint8_t allow_gnb_slow; + uint8_t force_nbp_state; + uint8_t display_wm; + uint8_t vce_wm; + uint8_t num_simd_to_powerdown; + uint8_t hysteresis_up; + uint8_t rsv[3]; +}; + +/*used for the nbpsFlags field in smu10_power state*/ +#define SMU10_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1<<0) +#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1<<1) +#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1<<2) + +#define SMU10_POWERSTATE_FLAGS_BAPM_DISABLE (1<<0) + +struct smu10_uvd_clocks { + uint32_t vclk; + uint32_t dclk; + uint32_t vclk_low_divider; + uint32_t vclk_high_divider; + uint32_t dclk_low_divider; + uint32_t dclk_high_divider; +}; + +struct pp_disable_nbpslo_flags { + union { + struct { + uint32_t entry : 1; + uint32_t display : 1; + uint32_t driver: 1; + uint32_t vce : 1; + uint32_t uvd : 1; + uint32_t acp : 1; + uint32_t reserved: 26; + } bits; + uint32_t u32All; + }; +}; + + +enum smu10_pstate_previous_action { + DO_NOTHING = 1, + FORCE_HIGH, + CANCEL_FORCE_HIGH +}; + +struct smu10_power_state { + unsigned int magic; + uint32_t level; + struct smu10_uvd_clocks uvd_clocks; + uint32_t evclk; + uint32_t ecclk; + uint32_t samclk; + uint32_t acpclk; + bool need_dfs_bypass; + + uint32_t nbps_flags; + uint32_t bapm_flags; + uint8_t dpm0_pg_nbps_low; + uint8_t dpm0_pg_nbps_high; + uint8_t dpm_x_nbps_low; + uint8_t dpm_x_nbps_high; + + enum smu10_pstate_previous_action action; + + struct smu10_power_level levels[SMU10_MAX_HARDWARE_POWERLEVELS]; + struct pp_disable_nbpslo_flags nbpslo_flags; +}; + +#define SMU10_NUM_NBPSTATES 4 +#define SMU10_NUM_NBPMEMORYCLOCK 2 + + +struct smu10_display_phy_info_entry { + uint8_t phy_present; + uint8_t active_lane_mapping; + uint8_t display_config_type; + uint8_t active_num_of_lanes; +}; + +#define SMU10_MAX_DISPLAYPHY_IDS 10 + +struct smu10_display_phy_info { + bool display_phy_access_initialized; + struct smu10_display_phy_info_entry entries[SMU10_MAX_DISPLAYPHY_IDS]; +}; + +#define MAX_DISPLAY_CLOCK_LEVEL 8 + +struct smu10_system_info{ + uint8_t htc_tmp_lmt; + uint8_t htc_hyst_lmt; +}; + +#define MAX_REGULAR_DPM_NUMBER 8 + +struct smu10_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct smu10_mclk_latency_table { + uint32_t count; + struct smu10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct smu10_clock_voltage_dependency_record { + uint32_t clk; + uint32_t vol; +}; + + +struct smu10_voltage_dependency_table { + uint32_t count; + struct smu10_clock_voltage_dependency_record entries[]; +}; + +struct smu10_clock_voltage_information { + struct smu10_voltage_dependency_table *vdd_dep_on_dcefclk; + struct smu10_voltage_dependency_table *vdd_dep_on_socclk; + struct smu10_voltage_dependency_table *vdd_dep_on_fclk; + struct smu10_voltage_dependency_table *vdd_dep_on_mclk; + struct smu10_voltage_dependency_table *vdd_dep_on_dispclk; + struct smu10_voltage_dependency_table *vdd_dep_on_dppclk; + struct smu10_voltage_dependency_table *vdd_dep_on_phyclk; +}; + +struct smu10_hwmgr { + uint32_t disable_driver_thermal_policy; + uint32_t thermal_auto_throttling_treshold; + struct smu10_system_info sys_info; + struct smu10_mclk_latency_table mclk_latency_table; + + uint32_t ddi_power_gating_disabled; + + struct smu10_display_phy_info_entry display_phy_info; + uint32_t dce_slow_sclk_threshold; + + bool disp_clk_bypass; + bool disp_clk_bypass_pending; + uint32_t bapm_enabled; + + bool video_start; + bool battery_state; + + uint32_t is_nb_dpm_enabled; + uint32_t is_voltage_island_enabled; + uint32_t disable_smu_acp_s3_handshake; + uint32_t disable_notify_smu_vpu_recovery; + bool in_vpu_recovery; + bool pg_acp_init; + uint8_t disp_config; + + /* PowerTune */ + uint32_t power_containment_features; + bool cac_enabled; + bool disable_uvd_power_tune_feature; + bool enable_bapm_feature; + bool enable_tdc_limit_feature; + + + /* SMC SRAM Address of firmware header tables */ + uint32_t sram_end; + uint32_t dpm_table_start; + uint32_t soft_regs_start; + + /* start of SMU7_Fusion_DpmTable */ + + uint8_t uvd_level_count; + uint8_t vce_level_count; + uint8_t acp_level_count; + uint8_t samu_level_count; + + uint32_t fps_high_threshold; + uint32_t fps_low_threshold; + + uint32_t dpm_flags; + struct smu10_dpm_entry sclk_dpm; + struct smu10_dpm_entry uvd_dpm; + struct smu10_dpm_entry vce_dpm; + struct smu10_dpm_entry acp_dpm; + bool acp_power_up_no_dsp; + + uint32_t max_sclk_level; + uint32_t num_of_clk_entries; + + /* CPU Power State */ + uint32_t separation_time; + bool cc6_disable; + bool pstate_disable; + bool cc6_setting_changed; + + uint32_t ulTotalActiveCUs; + + bool isp_tileA_power_gated; + bool isp_tileB_power_gated; + uint32_t isp_actual_hard_min_freq; + uint32_t soc_actual_hard_min_freq; + uint32_t dcf_actual_hard_min_freq; + + uint32_t f_actual_hard_min_freq; + uint32_t fabric_actual_soft_min_freq; + uint32_t vclk_soft_min; + uint32_t dclk_soft_min; + uint32_t gfx_actual_soft_min_freq; + uint32_t gfx_min_freq_limit; + uint32_t gfx_max_freq_limit; + + bool vcn_power_gated; + bool vcn_dpg_mode; + + bool gfx_off_controled_by_driver; + bool water_marks_exist; + Watermarks_t water_marks_table; + struct smu10_clock_voltage_information clock_vol_info; + DpmClocks_t clock_table; + + uint32_t active_process_mask; + bool need_min_deep_sleep_dcefclk; + uint32_t deep_sleep_dcefclk; + uint32_t num_active_display; +}; + +struct pp_hwmgr; + +int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); + +/* UMD PState SMU10 Msg Parameters in MHz */ +#define SMU10_UMD_PSTATE_GFXCLK 700 +#define SMU10_UMD_PSTATE_SOCCLK 626 +#define SMU10_UMD_PSTATE_FCLK 933 +#define SMU10_UMD_PSTATE_VCE 0x03C00320 + +#define SMU10_UMD_PSTATE_PEAK_SOCCLK 757 +#define SMU10_UMD_PSTATE_PEAK_FCLK 1200 + +#define SMU10_UMD_PSTATE_MIN_FCLK 400 +#define SMU10_UMD_PSTATE_MIN_SOCCLK 200 +#define SMU10_UMD_PSTATE_MIN_VCE 0x0190012C + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h new file mode 100644 index 000000000000..edb68e302f6f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_inc.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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 SMU10_INC_H +#define SMU10_INC_H + + +#include "asic_reg/mp/mp_10_0_default.h" +#include "asic_reg/mp/mp_10_0_offset.h" +#include "asic_reg/mp/mp_10_0_sh_mask.h" + +#include "asic_reg/nbio/nbio_7_0_default.h" +#include "asic_reg/nbio/nbio_7_0_offset.h" +#include "asic_reg/nbio/nbio_7_0_sh_mask.h" + +#include "asic_reg/thm/thm_10_0_default.h" +#include "asic_reg/thm/thm_10_0_offset.h" +#include "asic_reg/thm/thm_10_0_sh_mask.h" + + +#define ixDDI_PHY_GEN_STATUS 0x3FCE8 + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c new file mode 100644 index 000000000000..044cda005aed --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.c @@ -0,0 +1,91 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "smu7_baco.h" +#include "tonga_baco.h" +#include "fiji_baco.h" +#include "polaris_baco.h" +#include "ci_baco.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" + +int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + uint32_t reg; + + *cap = false; + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) + return 0; + + reg = RREG32(mmCC_BIF_BX_FUSESTRAP0); + + if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK) + *cap = true; + + return 0; +} + +int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + uint32_t reg; + + reg = RREG32(mmBACO_CNTL); + + if (reg & BACO_CNTL__BACO_MODE_MASK) + /* gfx has already entered BACO state */ + *state = BACO_STATE_IN; + else + *state = BACO_STATE_OUT; + return 0; +} + +int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + + switch (adev->asic_type) { + case CHIP_TOPAZ: + case CHIP_TONGA: + return tonga_baco_set_state(hwmgr, state); + case CHIP_FIJI: + return fiji_baco_set_state(hwmgr, state); + case CHIP_POLARIS10: + case CHIP_POLARIS11: + case CHIP_POLARIS12: + case CHIP_VEGAM: + return polaris_baco_set_state(hwmgr, state); +#ifdef CONFIG_DRM_AMDGPU_CIK + case CHIP_BONAIRE: + case CHIP_HAWAII: + return ci_baco_set_state(hwmgr, state); +#endif + default: + return -EINVAL; + } +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h new file mode 100644 index 000000000000..be0d98abb536 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_baco.h @@ -0,0 +1,32 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SMU7_BACO_H__ +#define __SMU7_BACO_H__ +#include "hwmgr.h" +#include "common_baco.h" + +extern int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); +extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c new file mode 100644 index 000000000000..f2bda3bcbbde --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.c @@ -0,0 +1,437 @@ +/* + * Copyright 2016 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 "smu7_hwmgr.h" +#include "smu7_clockpowergating.h" +#include "smu7_common.h" + +static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr, enable ? + PPSMC_MSG_UVDDPM_Enable : + PPSMC_MSG_UVDDPM_Disable, + NULL); +} + +static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr, enable ? + PPSMC_MSG_VCEDPM_Enable : + PPSMC_MSG_VCEDPM_Disable, + NULL); +} + +static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + if (!bgate) + smum_update_smc_table(hwmgr, SMU_UVD_TABLE); + return smu7_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + if (!bgate) + smum_update_smc_table(hwmgr, SMU_VCE_TABLE); + return smu7_enable_disable_vce_dpm(hwmgr, !bgate); +} + +int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_uvd_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_UVDPowerOFF, + NULL); + return 0; +} + +static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_uvd_power_gating(hwmgr)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDynamicPowerGating)) { + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDPowerON, 1, NULL); + } else { + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDPowerON, 0, NULL); + } + } + + return 0; +} + +static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_vce_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_VCEPowerOFF, + NULL); + return 0; +} + +static int smu7_powerup_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_vce_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_VCEPowerON, + NULL); + return 0; +} + +int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + + smu7_powerup_uvd(hwmgr); + smu7_powerup_vce(hwmgr); + + return 0; +} + +void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = bgate; + + if (bgate) { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_GATE); + smu7_update_uvd_dpm(hwmgr, true); + smu7_powerdown_uvd(hwmgr); + } else { + smu7_powerup_uvd(hwmgr); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); + smu7_update_uvd_dpm(hwmgr, false); + } + +} + +void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->vce_power_gated = bgate; + + if (bgate) { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_GATE); + smu7_update_vce_dpm(hwmgr, true); + smu7_powerdown_vce(hwmgr); + } else { + smu7_powerup_vce(hwmgr); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + smu7_update_vce_dpm(hwmgr, false); + } +} + +int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, + const uint32_t *msg_id) +{ + PPSMC_Msg msg; + uint32_t value; + + if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU)) + return 0; + + switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) { + case PP_GROUP_GFX: + switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { + case PP_BLOCK_GFX_CG: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_CGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_CGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_GFX_3D: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_3DCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_3DLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_GFX_RLC: + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_RLC_LS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_GFX_CP: + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_CP_LS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_GFX_MG: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK | + CG_GFX_OTHERS_MGCG_MASK); + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + default: + return -EINVAL; + } + break; + + case PP_GROUP_SYS: + switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { + case PP_BLOCK_SYS_BIF: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_BIF_MGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_BIF_MGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_SYS_MC: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_MC_MGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_MC_MGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_SYS_DRM: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_DRM_MGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_DRM_MGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_SYS_HDP: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_HDP_MGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_HDP_MGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_SYS_SDMA: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_SDMA_MGCG_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_SDMA_MGLS_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + case PP_BLOCK_SYS_ROM: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? + PPSMC_MSG_EnableClockGatingFeature : + PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_ROM_MASK; + + if (smum_send_msg_to_smc_with_parameter( + hwmgr, msg, value, NULL)) + return -EINVAL; + } + break; + + default: + return -EINVAL; + + } + break; + + default: + return -EINVAL; + + } + + return 0; +} + +/* This function is for Polaris11 only for now, + * Powerplay will only control the static per CU Power Gating. + * Dynamic per CU Power Gating will be done in gfx. + */ +int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (enable) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GFX_CU_PG_ENABLE, + adev->gfx.cu_info.number, + NULL); + else + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GFX_CU_PG_DISABLE, + NULL); +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h new file mode 100644 index 000000000000..fc8f8a6acc72 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_clockpowergating.h @@ -0,0 +1,38 @@ +/* + * Copyright 2016 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 _SMU7_CLOCK_POWER_GATING_H_ +#define _SMU7_CLOCK_POWER_GATING_H_ + +#include "smu7_hwmgr.h" + +void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr); +int smu7_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); +int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr); +int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, + const uint32_t *msg_id); +int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h new file mode 100644 index 000000000000..3477d4dfff70 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_dyn_defaults.h @@ -0,0 +1,55 @@ +/* + * Copyright 2015 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 _SMU7_DYN_DEFAULTS_H +#define _SMU7_DYN_DEFAULTS_H + + +/* We need to fill in the default values */ + + +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT1 0x000400 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT2 0xC00080 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT3 0xC00200 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT4 0xC01680 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT5 0xC00033 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT6 0xC00033 +#define SMU7_VOTINGRIGHTSCLIENTS_DFLT7 0x3FFFC000 + + +#define SMU7_THERMALPROTECTCOUNTER_DFLT 0x200 +#define SMU7_STATICSCREENTHRESHOLDUNIT_DFLT 0 +#define SMU7_STATICSCREENTHRESHOLD_DFLT 0x00C8 +#define SMU7_GFXIDLECLOCKSTOPTHRESHOLD_DFLT 0x200 +#define SMU7_REFERENCEDIVIDER_DFLT 4 + +#define SMU7_ULVVOLTAGECHANGEDELAY_DFLT 1687 + +#define SMU7_CGULVPARAMETER_DFLT 0x00040035 +#define SMU7_CGULVCONTROL_DFLT 0x00007450 +#define SMU7_TARGETACTIVITY_DFLT 50 +#define SMU7_MCLK_TARGETACTIVITY_DFLT 10 +#define SMU7_SCLK_TARGETACTIVITY_DFLT 30 +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c new file mode 100644 index 000000000000..ffe05b7cc1f0 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -0,0 +1,5215 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include +#include +#include +#include +#include "ppatomctrl.h" +#include "atombios.h" +#include "pptable_v1_0.h" +#include "pppcielanes.h" +#include "amd_pcie_helpers.h" +#include "hardwaremanager.h" +#include "process_pptables_v1_0.h" +#include "cgs_common.h" + +#include "smu7_common.h" + +#include "hwmgr.h" +#include "smu7_hwmgr.h" +#include "smu_ucode_xfer_vi.h" +#include "smu7_powertune.h" +#include "smu7_dyn_defaults.h" +#include "smu7_thermal.h" +#include "smu7_clockpowergating.h" +#include "processpptables.h" +#include "pp_thermal.h" +#include "smu7_baco.h" + +#include "ivsrcid/ivsrcid_vislands30.h" + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define MC_CG_SEQ_DRAMCONF_S0 0x05 +#define MC_CG_SEQ_DRAMCONF_S1 0x06 +#define MC_CG_SEQ_YCLK_SUSPEND 0x04 +#define MC_CG_SEQ_YCLK_RESUME 0x0a + +#define SMC_CG_IND_START 0xc0030000 +#define SMC_CG_IND_END 0xc0040000 + +#define MEM_FREQ_LOW_LATENCY 25000 +#define MEM_FREQ_HIGH_LATENCY 80000 + +#define MEM_LATENCY_HIGH 45 +#define MEM_LATENCY_LOW 35 +#define MEM_LATENCY_ERR 0xFFFF + +#define MC_SEQ_MISC0_GDDR5_SHIFT 28 +#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 +#define MC_SEQ_MISC0_GDDR5_VALUE 5 + +#define PCIE_BUS_CLK 10000 +#define TCLK (PCIE_BUS_CLK / 10) + +static struct profile_mode_setting smu7_profiling[7] = + {{0, 0, 0, 0, 0, 0, 0, 0}, + {1, 0, 100, 30, 1, 0, 100, 10}, + {1, 10, 0, 30, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 10, 16, 31}, + {1, 0, 11, 50, 1, 0, 100, 10}, + {1, 0, 5, 30, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 0, 0}, + }; + +#define PPSMC_MSG_SetVBITimeout_VEGAM ((uint16_t) 0x310) + +#define ixPWR_SVI2_PLANE1_LOAD 0xC0200280 +#define PWR_SVI2_PLANE1_LOAD__PSI1_MASK 0x00000020L +#define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK 0x00000040L +#define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT 0x00000005 +#define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT 0x00000006 + +/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ +enum DPM_EVENT_SRC { + DPM_EVENT_SRC_ANALOG = 0, + DPM_EVENT_SRC_EXTERNAL = 1, + DPM_EVENT_SRC_DIGITAL = 2, + DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, + DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 +}; + +static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); +static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask); + +static struct smu7_power_state *cast_phw_smu7_power_state( + struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL); + + return (struct smu7_power_state *)hw_ps; +} + +static const struct smu7_power_state *cast_const_phw_smu7_power_state( + const struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL); + + return (const struct smu7_power_state *)hw_ps; +} + +/** + * Find the MC microcode version and store it in the HwMgr struct + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr) +{ + cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); + + hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); + + return 0; +} + +static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speedCntl = 0; + + /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ + speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE, + ixPCIE_LC_SPEED_CNTL); + return((uint16_t)PHM_GET_FIELD(speedCntl, + PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); +} + +static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) +{ + uint32_t link_width; + + /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ + link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, + PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD); + + PP_ASSERT_WITH_CODE((7 >= link_width), + "Invalid PCIe lane width!", return 0); + + return decode_pcie_lane_width(link_width); +} + +/** +* Enable voltage control +* +* @param pHwMgr the address of the powerplay hardware manager. +* @return always PP_Result_OK +*/ +static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->chip_id == CHIP_VEGAM) { + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0); + } + + if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable, NULL); + + return 0; +} + +/** +* Checks if we want to support voltage control +* +* @param hwmgr the address of the powerplay hardware manager. +*/ +static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr) +{ + const struct smu7_hwmgr *data = + (const struct smu7_hwmgr *)(hwmgr->backend); + + return (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control); +} + +/** +* Enable voltage control +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr) +{ + /* enable voltage control */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1); + + return 0; +} + +static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table, + struct phm_clock_voltage_dependency_table *voltage_dependency_table + ) +{ + uint32_t i; + + PP_ASSERT_WITH_CODE((NULL != voltage_table), + "Voltage Dependency Table empty.", return -EINVAL;); + + voltage_table->mask_low = 0; + voltage_table->phase_delay = 0; + voltage_table->count = voltage_dependency_table->count; + + for (i = 0; i < voltage_dependency_table->count; i++) { + voltage_table->entries[i].value = + voltage_dependency_table->entries[i].v; + voltage_table->entries[i].smio_low = 0; + } + + return 0; +} + + +/** +* Create Voltage Tables. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + int result = 0; + uint32_t tmp; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, + &(data->mvdd_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve MVDD table.", + return result); + } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + if (hwmgr->pp_table_version == PP_TABLE_V1) + result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table), + table_info->vdd_dep_on_mclk); + else if (hwmgr->pp_table_version == PP_TABLE_V0) + result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table), + hwmgr->dyn_state.mvdd_dependency_on_mclk); + + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 MVDD table from dependency table.", + return result;); + } + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, + &(data->vddci_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve VDDCI table.", + return result); + } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + if (hwmgr->pp_table_version == PP_TABLE_V1) + result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table), + table_info->vdd_dep_on_mclk); + else if (hwmgr->pp_table_version == PP_TABLE_V0) + result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table), + hwmgr->dyn_state.vddci_dependency_on_mclk); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDCI table from dependency table.", + return result); + } + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + /* VDDGFX has only SVI2 voltage control */ + result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table), + table_info->vddgfx_lookup_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;); + } + + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT, + &data->vddc_voltage_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve VDDC table.", return result;); + } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + + if (hwmgr->pp_table_version == PP_TABLE_V0) + result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table, + hwmgr->dyn_state.vddc_dependency_on_mclk); + else if (hwmgr->pp_table_version == PP_TABLE_V1) + result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table), + table_info->vddc_lookup_table); + + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDC table from dependency table.", return result;); + } + + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC); + PP_ASSERT_WITH_CODE( + (data->vddc_voltage_table.count <= tmp), + "Too many voltage values for VDDC. Trimming to fit state table.", + phm_trim_voltage_table_to_fit_state_table(tmp, + &(data->vddc_voltage_table))); + + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); + PP_ASSERT_WITH_CODE( + (data->vddgfx_voltage_table.count <= tmp), + "Too many voltage values for VDDC. Trimming to fit state table.", + phm_trim_voltage_table_to_fit_state_table(tmp, + &(data->vddgfx_voltage_table))); + + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI); + PP_ASSERT_WITH_CODE( + (data->vddci_voltage_table.count <= tmp), + "Too many voltage values for VDDCI. Trimming to fit state table.", + phm_trim_voltage_table_to_fit_state_table(tmp, + &(data->vddci_voltage_table))); + + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD); + PP_ASSERT_WITH_CODE( + (data->mvdd_voltage_table.count <= tmp), + "Too many voltage values for MVDD. Trimming to fit state table.", + phm_trim_voltage_table_to_fit_state_table(tmp, + &(data->mvdd_voltage_table))); + + return 0; +} + +/** +* Programs static screed detection parameters +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_program_static_screen_threshold_parameters( + struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /* Set static screen threshold unit */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT, + data->static_screen_threshold_unit); + /* Set static screen threshold */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, + data->static_screen_threshold); + + return 0; +} + +/** +* Setup display gap for glitch free memory clock switching. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) +{ + uint32_t display_gap = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL); + + display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, + DISP_GAP, DISPLAY_GAP_IGNORE); + + display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, + DISP_GAP_MCHG, DISPLAY_GAP_VBLANK); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL, display_gap); + + return 0; +} + +/** +* Programs activity state transition voting clients +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int i; + + /* Clear reset for voting clients before enabling DPM */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); + + for (i = 0; i < 8; i++) + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0 + i * 4, + data->voting_rights_clients[i]); + return 0; +} + +static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr) +{ + int i; + + /* Reset voting clients before disabling DPM */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); + + for (i = 0; i < 8; i++) + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0); + + return 0; +} + +/* Copy one arb setting to another and then switch the active set. + * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants. + */ +static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, + uint32_t arb_src, uint32_t arb_dest) +{ + uint32_t mc_arb_dram_timing; + uint32_t mc_arb_dram_timing2; + uint32_t burst_time; + uint32_t mc_cg_config; + + switch (arb_src) { + case MC_CG_ARB_FREQ_F0: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + break; + case MC_CG_ARB_FREQ_F1: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1); + break; + default: + return -EINVAL; + } + + switch (arb_dest) { + case MC_CG_ARB_FREQ_F0: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time); + break; + case MC_CG_ARB_FREQ_F1: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time); + break; + default: + return -EINVAL; + } + + mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); + mc_cg_config |= 0x0000000F; + cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest); + + return 0; +} + +static int smu7_reset_to_default(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults, NULL); +} + +/** +* Initial switch from ARB F0->F1 +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +* This function is to be called from the SetPowerState table. +*/ +static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) +{ + return smu7_copy_and_switch_arb_sets(hwmgr, + MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); +} + +static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr) +{ + uint32_t tmp; + + tmp = (cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_SCRATCH9) & + 0x0000ff00) >> 8; + + if (tmp == MC_CG_ARB_FREQ_F0) + return 0; + + return smu7_copy_and_switch_arb_sets(hwmgr, + tmp, MC_CG_ARB_FREQ_F0); +} + +static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = NULL; + + uint32_t i, max_entry; + uint32_t tmp; + + PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels || + data->use_pcie_power_saving_levels), "No pcie performance levels!", + return -EINVAL); + + if (table_info != NULL) + pcie_table = table_info->pcie_table; + + if (data->use_pcie_performance_levels && + !data->use_pcie_power_saving_levels) { + data->pcie_gen_power_saving = data->pcie_gen_performance; + data->pcie_lane_power_saving = data->pcie_lane_performance; + } else if (!data->use_pcie_performance_levels && + data->use_pcie_power_saving_levels) { + data->pcie_gen_performance = data->pcie_gen_power_saving; + data->pcie_lane_performance = data->pcie_lane_power_saving; + } + tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK); + phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table, + tmp, + MAX_REGULAR_DPM_NUMBER); + + if (pcie_table != NULL) { + /* max_entry is used to make sure we reserve one PCIE level + * for boot level (fix for A+A PSPP issue). + * If PCIE table from PPTable have ULV entry + 8 entries, + * then ignore the last entry.*/ + max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count; + for (i = 1; i < max_entry; i++) { + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1, + get_pcie_gen_support(data->pcie_gen_cap, + pcie_table->entries[i].gen_speed), + get_pcie_lane_support(data->pcie_lane_cap, + pcie_table->entries[i].lane_width)); + } + data->dpm_table.pcie_speed_table.count = max_entry - 1; + smum_update_smc_table(hwmgr, SMU_BIF_TABLE); + } else { + /* Hardcode Pcie Table */ + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + + data->dpm_table.pcie_speed_table.count = 6; + } + /* Populate last level for boot PCIE level, but do not increment count. */ + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + data->vbios_boot_state.pcie_lane_bootup_value); + } else { + phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, + data->dpm_table.pcie_speed_table.count, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + } + return 0; +} + +static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table)); + + phm_reset_single_dpm_table( + &data->dpm_table.sclk_table, + smum_get_mac_definition(hwmgr, + SMU_MAX_LEVELS_GRAPHICS), + MAX_REGULAR_DPM_NUMBER); + phm_reset_single_dpm_table( + &data->dpm_table.mclk_table, + smum_get_mac_definition(hwmgr, + SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER); + + phm_reset_single_dpm_table( + &data->dpm_table.vddc_table, + smum_get_mac_definition(hwmgr, + SMU_MAX_LEVELS_VDDC), + MAX_REGULAR_DPM_NUMBER); + phm_reset_single_dpm_table( + &data->dpm_table.vddci_table, + smum_get_mac_definition(hwmgr, + SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER); + + phm_reset_single_dpm_table( + &data->dpm_table.mvdd_table, + smum_get_mac_definition(hwmgr, + SMU_MAX_LEVELS_MVDD), + MAX_REGULAR_DPM_NUMBER); + return 0; +} +/* + * This function is to initialize all DPM state tables + * for SMU7 based on the dependency table. + * Dynamic state patching function will then trim these + * state tables to the allowed range based + * on the power policy or external client requests, + * such as UVD request, etc. + */ + +static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table = + hwmgr->dyn_state.vddc_dependency_on_mclk; + struct phm_cac_leakage_table *std_voltage_table = + hwmgr->dyn_state.cac_leakage_table; + uint32_t i; + + PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL, + "SCLK dependency table is missing. This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1, + "SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); + + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, + "MCLK dependency table is missing. This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1, + "VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); + + + /* Initialize Sclk DPM table based on allow Sclk values*/ + data->dpm_table.sclk_table.count = 0; + + for (i = 0; i < allowed_vdd_sclk_table->count; i++) { + if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value != + allowed_vdd_sclk_table->entries[i].clk) { + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = + allowed_vdd_sclk_table->entries[i].clk; + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0; + data->dpm_table.sclk_table.count++; + } + } + + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, + "MCLK dependency table is missing. This table is mandatory", return -EINVAL); + /* Initialize Mclk DPM table based on allow Mclk values */ + data->dpm_table.mclk_table.count = 0; + for (i = 0; i < allowed_vdd_mclk_table->count; i++) { + if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value != + allowed_vdd_mclk_table->entries[i].clk) { + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = + allowed_vdd_mclk_table->entries[i].clk; + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0; + data->dpm_table.mclk_table.count++; + } + } + + /* Initialize Vddc DPM table based on allow Vddc values. And populate corresponding std values. */ + for (i = 0; i < allowed_vdd_sclk_table->count; i++) { + data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; + data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage; + /* param1 is for corresponding std voltage */ + data->dpm_table.vddc_table.dpm_levels[i].enabled = true; + } + + data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count; + allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk; + + if (NULL != allowed_vdd_mclk_table) { + /* Initialize Vddci DPM table based on allow Mclk values */ + for (i = 0; i < allowed_vdd_mclk_table->count; i++) { + data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; + data->dpm_table.vddci_table.dpm_levels[i].enabled = true; + } + data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count; + } + + allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk; + + if (NULL != allowed_vdd_mclk_table) { + /* + * Initialize MVDD DPM table based on allow Mclk + * values + */ + for (i = 0; i < allowed_vdd_mclk_table->count; i++) { + data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; + data->dpm_table.mvdd_table.dpm_levels[i].enabled = true; + } + data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count; + } + + return 0; +} + +static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i; + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; + + if (table_info == NULL) + return -EINVAL; + + dep_sclk_table = table_info->vdd_dep_on_sclk; + dep_mclk_table = table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(dep_sclk_table != NULL, + "SCLK dependency table is missing.", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1, + "SCLK dependency table count is 0.", + return -EINVAL); + + PP_ASSERT_WITH_CODE(dep_mclk_table != NULL, + "MCLK dependency table is missing.", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, + "MCLK dependency table count is 0", + return -EINVAL); + + /* Initialize Sclk DPM table based on allow Sclk values */ + data->dpm_table.sclk_table.count = 0; + for (i = 0; i < dep_sclk_table->count; i++) { + if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value != + dep_sclk_table->entries[i].clk) { + + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = + dep_sclk_table->entries[i].clk; + + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = + (i == 0) ? true : false; + data->dpm_table.sclk_table.count++; + } + } + if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) + hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk; + /* Initialize Mclk DPM table based on allow Mclk values */ + data->dpm_table.mclk_table.count = 0; + for (i = 0; i < dep_mclk_table->count; i++) { + if (i == 0 || data->dpm_table.mclk_table.dpm_levels + [data->dpm_table.mclk_table.count - 1].value != + dep_mclk_table->entries[i].clk) { + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = + dep_mclk_table->entries[i].clk; + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = + (i == 0) ? true : false; + data->dpm_table.mclk_table.count++; + } + } + + if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) + hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk; + return 0; +} + +static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i; + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; + struct phm_odn_performance_level *entries; + + if (table_info == NULL) + return -EINVAL; + + dep_sclk_table = table_info->vdd_dep_on_sclk; + dep_mclk_table = table_info->vdd_dep_on_mclk; + + odn_table->odn_core_clock_dpm_levels.num_of_pl = + data->golden_dpm_table.sclk_table.count; + entries = odn_table->odn_core_clock_dpm_levels.entries; + for (i=0; igolden_dpm_table.sclk_table.count; i++) { + entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value; + entries[i].enabled = true; + entries[i].vddc = dep_sclk_table->entries[i].vddc; + } + + smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table, + (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk)); + + odn_table->odn_memory_clock_dpm_levels.num_of_pl = + data->golden_dpm_table.mclk_table.count; + entries = odn_table->odn_memory_clock_dpm_levels.entries; + for (i=0; igolden_dpm_table.mclk_table.count; i++) { + entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value; + entries[i].enabled = true; + entries[i].vddc = dep_mclk_table->entries[i].vddc; + } + + smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table, + (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk)); + + return 0; +} + +static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t min_vddc = 0; + uint32_t max_vddc = 0; + + if (!table_info) + return; + + dep_sclk_table = table_info->vdd_dep_on_sclk; + + atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc); + + if (min_vddc == 0 || min_vddc > 2000 + || min_vddc > dep_sclk_table->entries[0].vddc) + min_vddc = dep_sclk_table->entries[0].vddc; + + if (max_vddc == 0 || max_vddc > 2000 + || max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc) + max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc; + + data->odn_dpm_table.min_vddc = min_vddc; + data->odn_dpm_table.max_vddc = max_vddc; +} + +static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i; + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; + struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; + + if (table_info == NULL) + return; + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + if (odn_table->odn_core_clock_dpm_levels.entries[i].clock != + data->dpm_table.sclk_table.dpm_levels[i].value) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + break; + } + } + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock != + data->dpm_table.mclk_table.dpm_levels[i].value) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + break; + } + } + + dep_table = table_info->vdd_dep_on_mclk; + odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk); + + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; + return; + } + } + + dep_table = table_info->vdd_dep_on_sclk; + odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk); + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; + return; + } + } + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { + data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC; + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; + } +} + +static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + smu7_reset_dpm_tables(hwmgr); + + if (hwmgr->pp_table_version == PP_TABLE_V1) + smu7_setup_dpm_tables_v1(hwmgr); + else if (hwmgr->pp_table_version == PP_TABLE_V0) + smu7_setup_dpm_tables_v0(hwmgr); + + smu7_setup_default_pcie_table(hwmgr); + + /* save a copy of the default DPM table */ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), + sizeof(struct smu7_dpm_table)); + + /* initialize ODN table */ + if (hwmgr->od_enabled) { + if (data->odn_dpm_table.max_vddc) { + smu7_check_dpm_table_updated(hwmgr); + } else { + smu7_setup_voltage_range_from_vbios(hwmgr); + smu7_odn_initial_default_setting(hwmgr); + } + } + return 0; +} + +static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr) +{ + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_EnableVRHotGPIOInterrupt, + NULL); + + return 0; +} + +static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + SCLK_PWRMGT_OFF, 0); + return 0; +} + +static int smu7_enable_ulv(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->ulv_supported) + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV, NULL); + + return 0; +} + +static int smu7_disable_ulv(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->ulv_supported) + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV, NULL); + + return 0; +} + +static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON, NULL)) + PP_ASSERT_WITH_CODE(false, + "Attempt to enable Master Deep Sleep switch failed!", + return -EINVAL); + } else { + if (smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_MASTER_DeepSleep_OFF, + NULL)) { + PP_ASSERT_WITH_CODE(false, + "Attempt to disable Master Deep Sleep switch failed!", + return -EINVAL); + } + } + + return 0; +} + +static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + if (smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_MASTER_DeepSleep_OFF, + NULL)) { + PP_ASSERT_WITH_CODE(false, + "Attempt to disable Master Deep Sleep switch failed!", + return -EINVAL); + } + } + + return 0; +} + +static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t soft_register_value = 0; + uint32_t handshake_disables_offset = data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, HandshakeDisables); + + soft_register_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, handshake_disables_offset); + soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + handshake_disables_offset, soft_register_value); + return 0; +} + +static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t soft_register_value = 0; + uint32_t handshake_disables_offset = data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, HandshakeDisables); + + soft_register_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, handshake_disables_offset); + soft_register_value |= smum_get_mac_definition(hwmgr, + SMU_UVD_MCLK_HANDSHAKE_DISABLE); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + handshake_disables_offset, soft_register_value); + return 0; +} + +static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /* enable SCLK dpm */ + if (!data->sclk_dpm_key_disabled) { + if (hwmgr->chip_id == CHIP_VEGAM) + smu7_disable_sclk_vce_handshake(hwmgr); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)), + "Failed to enable SCLK DPM during DPM Start Function!", + return -EINVAL); + } + + /* enable MCLK dpm */ + if (0 == data->mclk_dpm_key_disabled) { + if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK)) + smu7_disable_handshake_uvd(hwmgr); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_MCLKDPM_Enable, + NULL)), + "Failed to enable MCLK DPM during DPM Start Function!", + return -EINVAL); + + if (hwmgr->chip_family != CHIP_VEGAM) + PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); + + + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005); + udelay(10); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005); + } else { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005); + udelay(10); + if (hwmgr->chip_id == CHIP_VEGAM) { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009); + } else { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005); + } + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005); + } + } + + return 0; +} + +static int smu7_start_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /*enable general power management */ + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + GLOBAL_PWRMGT_EN, 1); + + /* enable sclk deep sleep */ + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + DYNAMIC_PM_EN, 1); + + /* prepare for PCIE DPM */ + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, SMU_SoftRegisters, + VoltageChangeTimeout), 0x1000); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, + SWRST_COMMAND_1, RESETLC, 0x0); + + if (hwmgr->chip_family == AMDGPU_FAMILY_CI) + cgs_write_register(hwmgr->device, 0x1488, + (cgs_read_register(hwmgr->device, 0x1488) & ~0x1)); + + if (smu7_enable_sclk_mclk_dpm(hwmgr)) { + pr_err("Failed to enable Sclk DPM and Mclk DPM!"); + return -EINVAL; + } + + /* enable PCIE dpm */ + if (0 == data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_PCIeDPM_Enable, + NULL)), + "Failed to enable pcie DPM during DPM Start Function!", + return -EINVAL); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition)) { + PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_EnableACDCGPIOInterrupt, + NULL)), + "Failed to enable AC DC GPIO Interrupt!", + ); + } + + return 0; +} + +static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /* disable SCLK dpm */ + if (!data->sclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to disable SCLK DPM when DPM is disabled", + return 0); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable, NULL); + } + + /* disable MCLK dpm */ + if (!data->mclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to disable MCLK DPM when DPM is disabled", + return 0); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable, NULL); + } + + return 0; +} + +static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /* disable general power management */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + GLOBAL_PWRMGT_EN, 0); + /* disable sclk deep sleep */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + DYNAMIC_PM_EN, 0); + + /* disable PCIE dpm */ + if (!data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_PCIeDPM_Disable, + NULL) == 0), + "Failed to disable pcie DPM during DPM Stop Function!", + return -EINVAL); + } + + smu7_disable_sclk_mclk_dpm(hwmgr); + + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to disable voltage DPM when DPM is disabled", + return 0); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable, NULL); + + return 0; +} + +static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) +{ + bool protection; + enum DPM_EVENT_SRC src; + + switch (sources) { + default: + pr_err("Unknown throttling event sources."); + fallthrough; + case 0: + protection = false; + /* src is unused */ + break; + case (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL; + break; + case (1 << PHM_AutoThrottleSource_External): + protection = true; + src = DPM_EVENT_SRC_EXTERNAL; + break; + case (1 << PHM_AutoThrottleSource_External) | + (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL; + break; + } + /* Order matters - don't enable thermal protection for the wrong source. */ + if (protection) { + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, + DPM_EVENT_SRC, src); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, + !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)); + } else + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, 1); +} + +static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (!(data->active_auto_throttle_sources & (1 << source))) { + data->active_auto_throttle_sources |= 1 << source; + smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + +static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->active_auto_throttle_sources & (1 << source)) { + data->active_auto_throttle_sources &= ~(1 << source); + smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + +static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + data->pcie_performance_request = true; + + return 0; +} + +static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result = 0; + int result = 0; + + if (smu7_voltage_control(hwmgr)) { + tmp_result = smu7_enable_voltage_control(hwmgr); + PP_ASSERT_WITH_CODE(tmp_result == 0, + "Failed to enable voltage control!", + result = tmp_result); + + tmp_result = smu7_construct_voltage_tables(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to construct voltage tables!", + result = tmp_result); + } + smum_initialize_mc_reg_table(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0); + + tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program static screen threshold parameters!", + result = tmp_result); + + tmp_result = smu7_enable_display_gap(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable display gap!", result = tmp_result); + + tmp_result = smu7_program_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program voting clients!", result = tmp_result); + + tmp_result = smum_process_firmware_header(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to process firmware header!", result = tmp_result); + + if (hwmgr->chip_id != CHIP_VEGAM) { + tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize switch from ArbF0 to F1!", + result = tmp_result); + } + + result = smu7_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to setup default DPM tables!", return result); + + tmp_result = smum_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize SMC table!", result = tmp_result); + + tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable VR hot GPIO interrupt!", result = tmp_result); + + smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); + + tmp_result = smu7_enable_sclk_control(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable SCLK control!", result = tmp_result); + + tmp_result = smu7_enable_smc_voltage_controller(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable voltage control!", result = tmp_result); + + tmp_result = smu7_enable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable ULV!", result = tmp_result); + + tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable deep sleep master switch!", result = tmp_result); + + tmp_result = smu7_enable_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to enable deep sleep master switch!", result = tmp_result); + + tmp_result = smu7_start_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to start DPM!", result = tmp_result); + + tmp_result = smu7_enable_smc_cac(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable SMC CAC!", result = tmp_result); + + tmp_result = smu7_enable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable power containment!", result = tmp_result); + + tmp_result = smu7_power_control_set_level(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to power control set level!", result = tmp_result); + + tmp_result = smu7_enable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable thermal auto throttle!", result = tmp_result); + + tmp_result = smu7_pcie_performance_request(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "pcie performance request failed!", result = tmp_result); + + return 0; +} + +static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) +{ + if (!hwmgr->avfs_supported) + return 0; + + if (enable) { + if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( + hwmgr, PPSMC_MSG_EnableAvfs, NULL), + "Failed to enable AVFS!", + return -EINVAL); + } + } else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( + hwmgr, PPSMC_MSG_DisableAvfs, NULL), + "Failed to disable AVFS!", + return -EINVAL); + } + + return 0; +} + +static int smu7_update_avfs(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (!hwmgr->avfs_supported) + return 0; + + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { + smu7_avfs_control(hwmgr, false); + } else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { + smu7_avfs_control(hwmgr, false); + smu7_avfs_control(hwmgr, true); + } else { + smu7_avfs_control(hwmgr, true); + } + + return 0; +} + +static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1); + + tmp_result = smu7_disable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable power containment!", result = tmp_result); + + tmp_result = smu7_disable_smc_cac(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable SMC CAC!", result = tmp_result); + + tmp_result = smu7_disable_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable DIDT!", result = tmp_result); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0); + + tmp_result = smu7_disable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable thermal auto throttle!", result = tmp_result); + + tmp_result = smu7_avfs_control(hwmgr, false); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable AVFS!", result = tmp_result); + + tmp_result = smu7_stop_dpm(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop DPM!", result = tmp_result); + + tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable deep sleep master switch!", result = tmp_result); + + tmp_result = smu7_disable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable ULV!", result = tmp_result); + + tmp_result = smu7_clear_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to clear voting clients!", result = tmp_result); + + tmp_result = smu7_reset_to_default(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to reset to default!", result = tmp_result); + + tmp_result = smu7_force_switch_to_arbf0(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to force to switch arbf0!", result = tmp_result); + + return result; +} + +static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct amdgpu_device *adev = hwmgr->adev; + + data->dll_default_on = false; + data->mclk_dpm0_activity_target = 0xa; + data->vddc_vddgfx_delta = 300; + data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT; + data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT; + data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0; + data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1; + data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2; + data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3; + data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4; + data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5; + data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6; + data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7; + + data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; + data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; + data->pcie_dpm_key_disabled = hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; + /* need to set voltage control types before EVV patching */ + data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE; + data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE; + data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE; + data->enable_tdc_limit_feature = true; + data->enable_pkg_pwr_tracking_feature = true; + data->force_pcie_gen = PP_PCIEGenInvalid; + data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false; + data->current_profile_setting.bupdate_sclk = 1; + data->current_profile_setting.sclk_up_hyst = 0; + data->current_profile_setting.sclk_down_hyst = 100; + data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT; + data->current_profile_setting.bupdate_mclk = 1; + data->current_profile_setting.mclk_up_hyst = 0; + data->current_profile_setting.mclk_down_hyst = 100; + data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT; + hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; + hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + + if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { + uint8_t tmp1, tmp2; + uint16_t tmp3 = 0; + atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, + &tmp3); + tmp3 = (tmp3 >> 5) & 0x3; + data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; + } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { + data->vddc_phase_shed_control = 1; + } else { + data->vddc_phase_shed_control = 0; + } + + if (hwmgr->chip_id == CHIP_HAWAII) { + data->thermal_temp_setting.temperature_low = 94500; + data->thermal_temp_setting.temperature_high = 95000; + data->thermal_temp_setting.temperature_shutdown = 104000; + } else { + data->thermal_temp_setting.temperature_low = 99500; + data->thermal_temp_setting.temperature_high = 100000; + data->thermal_temp_setting.temperature_shutdown = 104000; + } + + data->fast_watermark_threshold = 100; + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) + data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT)) + data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDGFX)) { + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) { + data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; + } + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl)) { + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) + data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) + data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDGFX); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI)) { + if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) + data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; + else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) + data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; + } + + if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl); + + if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK) + && (table_info->cac_dtp_table->usClockStretchAmount != 0)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + + data->pcie_gen_performance.max = PP_PCIEGen1; + data->pcie_gen_performance.min = PP_PCIEGen3; + data->pcie_gen_power_saving.max = PP_PCIEGen1; + data->pcie_gen_power_saving.min = PP_PCIEGen3; + data->pcie_lane_performance.max = 0; + data->pcie_lane_performance.min = 16; + data->pcie_lane_power_saving.max = 0; + data->pcie_lane_power_saving.min = 16; + + + if (adev->pg_flags & AMD_PG_SUPPORT_UVD) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + if (adev->pg_flags & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); +} + +/** +* Get Leakage VDDC based on leakage ID. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t vv_id; + uint16_t vddc = 0; + uint16_t vddgfx = 0; + uint16_t i, j; + uint32_t sclk = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; + + + for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { + vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + if ((hwmgr->pp_table_version == PP_TABLE_V1) + && !phm_get_sclk_for_voltage_evv(hwmgr, + table_info->vddgfx_lookup_table, vv_id, &sclk)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + sclk_table = table_info->vdd_dep_on_sclk; + + for (j = 1; j < sclk_table->count; j++) { + if (sclk_table->entries[j].clk == sclk && + sclk_table->entries[j].cks_enable == 0) { + sclk += 5000; + break; + } + } + } + if (0 == atomctrl_get_voltage_evv_on_sclk + (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk, + vv_id, &vddgfx)) { + /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */ + PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL); + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddgfx != 0 && vddgfx != vv_id) { + data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx; + data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id; + data->vddcgfx_leakage.count++; + } + } else { + pr_info("Error retrieving EVV voltage value!\n"); + } + } + } else { + if ((hwmgr->pp_table_version == PP_TABLE_V0) + || !phm_get_sclk_for_voltage_evv(hwmgr, + table_info->vddc_lookup_table, vv_id, &sclk)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + if (table_info == NULL) + return -EINVAL; + sclk_table = table_info->vdd_dep_on_sclk; + + for (j = 1; j < sclk_table->count; j++) { + if (sclk_table->entries[j].clk == sclk && + sclk_table->entries[j].cks_enable == 0) { + sclk += 5000; + break; + } + } + } + + if (phm_get_voltage_evv_on_sclk(hwmgr, + VOLTAGE_TYPE_VDDC, + sclk, vv_id, &vddc) == 0) { + if (vddc >= 2000 || vddc == 0) + return -EINVAL; + } else { + pr_debug("failed to retrieving EVV voltage!\n"); + continue; + } + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddc != 0 && vddc != vv_id) { + data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc); + data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; + data->vddc_leakage.count++; + } + } + } + } + + return 0; +} + +/** + * Change virtual leakage voltage to actual value. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to changing voltage + * @param pointer to leakage table + */ +static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr, + uint16_t *voltage, struct smu7_leakage_voltage *leakage_table) +{ + uint32_t index; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 */ + for (index = 0; index < leakage_table->count; index++) { + /* if this voltage matches a leakage voltage ID */ + /* patch with actual leakage voltage */ + if (leakage_table->leakage_id[index] == *voltage) { + *voltage = leakage_table->actual_voltage[index]; + break; + } + } + + if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) + pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); +} + +/** +* Patch voltage lookup table by EVV leakages. +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pointer to voltage lookup table +* @param pointer to leakage table +* @return always 0 +*/ +static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + struct smu7_leakage_voltage *leakage_table) +{ + uint32_t i; + + for (i = 0; i < lookup_table->count; i++) + smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, + &lookup_table->entries[i].us_vdd, leakage_table); + + return 0; +} + +static int smu7_patch_clock_voltage_limits_with_vddc_leakage( + struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table, + uint16_t *vddc) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + table_info->max_clock_voltage_on_dc.vddc; + return 0; +} + +static int smu7_patch_voltage_dependency_tables_with_lookup_table( + struct pp_hwmgr *hwmgr) +{ + uint8_t entry_id; + uint8_t voltage_id; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = + table_info->vdd_dep_on_mclk; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { + voltage_id = sclk_table->entries[entry_id].vddInd; + sclk_table->entries[entry_id].vddgfx = + table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd; + } + } else { + for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { + voltage_id = sclk_table->entries[entry_id].vddInd; + sclk_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } + } + + for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { + voltage_id = mclk_table->entries[entry_id].vddInd; + mclk_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } + + for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { + voltage_id = mm_table->entries[entry_id].vddcInd; + mm_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } + + return 0; + +} + +static int phm_add_voltage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *look_up_table, + phm_ppt_v1_voltage_lookup_record *record) +{ + uint32_t i; + + PP_ASSERT_WITH_CODE((NULL != look_up_table), + "Lookup Table empty.", return -EINVAL); + PP_ASSERT_WITH_CODE((0 != look_up_table->count), + "Lookup Table empty.", return -EINVAL); + + i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); + PP_ASSERT_WITH_CODE((i >= look_up_table->count), + "Lookup Table is full.", return -EINVAL); + + /* This is to avoid entering duplicate calculated records. */ + for (i = 0; i < look_up_table->count; i++) { + if (look_up_table->entries[i].us_vdd == record->us_vdd) { + if (look_up_table->entries[i].us_calculated == 1) + return 0; + break; + } + } + + look_up_table->entries[i].us_calculated = 1; + look_up_table->entries[i].us_vdd = record->us_vdd; + look_up_table->entries[i].us_cac_low = record->us_cac_low; + look_up_table->entries[i].us_cac_mid = record->us_cac_mid; + look_up_table->entries[i].us_cac_high = record->us_cac_high; + /* Only increment the count when we're appending, not replacing duplicate entry. */ + if (i == look_up_table->count) + look_up_table->count++; + + return 0; +} + + +static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr) +{ + uint8_t entry_id; + struct phm_ppt_v1_voltage_lookup_record v_record; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk; + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { + if (sclk_table->entries[entry_id].vdd_offset & (1 << 15)) + v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + + sclk_table->entries[entry_id].vdd_offset - 0xFFFF; + else + v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + + sclk_table->entries[entry_id].vdd_offset; + + sclk_table->entries[entry_id].vddc = + v_record.us_cac_low = v_record.us_cac_mid = + v_record.us_cac_high = v_record.us_vdd; + + phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record); + } + + for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { + if (mclk_table->entries[entry_id].vdd_offset & (1 << 15)) + v_record.us_vdd = mclk_table->entries[entry_id].vddc + + mclk_table->entries[entry_id].vdd_offset - 0xFFFF; + else + v_record.us_vdd = mclk_table->entries[entry_id].vddc + + mclk_table->entries[entry_id].vdd_offset; + + mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low = + v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; + phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); + } + } + return 0; +} + +static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr) +{ + uint8_t entry_id; + struct phm_ppt_v1_voltage_lookup_record v_record; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + for (entry_id = 0; entry_id < mm_table->count; entry_id++) { + if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15)) + v_record.us_vdd = mm_table->entries[entry_id].vddc + + mm_table->entries[entry_id].vddgfx_offset - 0xFFFF; + else + v_record.us_vdd = mm_table->entries[entry_id].vddc + + mm_table->entries[entry_id].vddgfx_offset; + + /* Add the calculated VDDGFX to the VDDGFX lookup table */ + mm_table->entries[entry_id].vddgfx = v_record.us_cac_low = + v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; + phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); + } + } + return 0; +} + +static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + uint32_t table_size, i, j; + table_size = lookup_table->count; + + PP_ASSERT_WITH_CODE(0 != lookup_table->count, + "Lookup table is empty", return -EINVAL); + + /* Sorting voltages */ + for (i = 0; i < table_size - 1; i++) { + for (j = i + 1; j > 0; j--) { + if (lookup_table->entries[j].us_vdd < + lookup_table->entries[j - 1].us_vdd) { + swap(lookup_table->entries[j - 1], + lookup_table->entries[j]); + } + } + } + + return 0; +} + +static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr) +{ + int result = 0; + int tmp_result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, + table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage)); + if (tmp_result != 0) + result = tmp_result; + + smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, + &table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage)); + } else { + + tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, + table_info->vddc_lookup_table, &(data->vddc_leakage)); + if (tmp_result) + result = tmp_result; + + tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, + &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); + if (tmp_result) + result = tmp_result; + } + + tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = smu7_calc_voltage_dependency_tables(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table); + if (tmp_result) + result = tmp_result; + + tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); + if (tmp_result) + result = tmp_result; + + return result; +} + +static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = + table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL, + "VDD dependency on SCLK table is missing.", + return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, + "VDD dependency on SCLK table has to have is missing.", + return -EINVAL); + + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL, + "VDD dependency on MCLK table is missing", + return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, + "VDD dependency on MCLK table has to have is missing.", + return -EINVAL); + + table_info->max_clock_voltage_on_ac.sclk = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.mclk = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.vddc = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + table_info->max_clock_voltage_on_ac.vddci = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; + + hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci; + + return 0; +} + +static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; + struct phm_ppt_v1_voltage_lookup_table *lookup_table; + uint32_t i; + uint32_t hw_revision, sub_vendor_id, sub_sys_id; + struct amdgpu_device *adev = hwmgr->adev; + + if (table_info != NULL) { + dep_mclk_table = table_info->vdd_dep_on_mclk; + lookup_table = table_info->vddc_lookup_table; + } else + return 0; + + hw_revision = adev->pdev->revision; + sub_sys_id = adev->pdev->subsystem_device; + sub_vendor_id = adev->pdev->subsystem_vendor; + + if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 && + ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || + (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || + (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { + if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000) + return 0; + + for (i = 0; i < lookup_table->count; i++) { + if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) { + dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i; + return 0; + } + } + } + return 0; +} + +static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr) +{ + struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; + uint32_t temp_reg; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { + temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL); + switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) { + case 0: + temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1); + break; + case 1: + temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2); + break; + case 2: + temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1); + break; + case 3: + temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1); + break; + case 4: + temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1); + break; + default: + break; + } + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg); + } + + if (table_info == NULL) + return 0; + + if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 && + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) { + hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit = + (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit = + (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit = + (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1; + + table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ? + (table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0; + + table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp; + table_info->cac_dtp_table->usOperatingTempStep = 1; + table_info->cac_dtp_table->usOperatingTempHyst = 1; + + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; + + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM; + + hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit = + table_info->cac_dtp_table->usOperatingTempMinLimit; + + hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit = + table_info->cac_dtp_table->usOperatingTempMaxLimit; + + hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = + table_info->cac_dtp_table->usDefaultTargetOperatingTemp; + + hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep = + table_info->cac_dtp_table->usOperatingTempStep; + + hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp = + table_info->cac_dtp_table->usTargetOperatingTemp; + if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport); + } + + return 0; +} + +/** + * Change virtual leakage voltage to actual value. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to changing voltage + * @param pointer to leakage table + */ +static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr, + uint32_t *voltage, struct smu7_leakage_voltage *leakage_table) +{ + uint32_t index; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 */ + for (index = 0; index < leakage_table->count; index++) { + /* if this voltage matches a leakage voltage ID */ + /* patch with actual leakage voltage */ + if (leakage_table->leakage_id[index] == *voltage) { + *voltage = leakage_table->actual_voltage[index]; + break; + } + } + + if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) + pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); +} + + +static int smu7_patch_vddc(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddc_leakage); + + return 0; +} + +static int smu7_patch_vddci(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddci_leakage); + + return 0; +} + +static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr, + struct phm_vce_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddc_leakage); + + return 0; +} + + +static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr, + struct phm_uvd_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddc_leakage); + + return 0; +} + +static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr, + struct phm_phase_shedding_limits_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage, + &data->vddc_leakage); + + return 0; +} + +static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr, + struct phm_samu_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddc_leakage); + + return 0; +} + +static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr, + struct phm_acp_clock_voltage_dependency_table *tab) +{ + uint16_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) + for (i = 0; i < tab->count; i++) + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, + &data->vddc_leakage); + + return 0; +} + +static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *tab) +{ + uint32_t vddc, vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) { + vddc = tab->vddc; + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, + &data->vddc_leakage); + tab->vddc = vddc; + vddci = tab->vddci; + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci, + &data->vddci_leakage); + tab->vddci = vddci; + } + + return 0; +} + +static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab) +{ + uint32_t i; + uint32_t vddc; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (tab) { + for (i = 0; i < tab->count; i++) { + vddc = (uint32_t)(tab->entries[i].Vddc); + smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage); + tab->entries[i].Vddc = (uint16_t)vddc; + } + } + + return 0; +} + +static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr) +{ + int tmp; + + tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc); + if (tmp) + return -EINVAL; + + tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table); + if (tmp) + return -EINVAL; + + return 0; +} + + +static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL, + "VDDC dependency on SCLK table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1, + "VDDC dependency on SCLK table has to have is missing. This table is mandatory", + return -EINVAL); + + PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL, + "VDDC dependency on MCLK table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1, + "VDD dependency on MCLK table has to have is missing. This table is mandatory", + return -EINVAL); + + data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v; + data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; + + hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = + allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk; + hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = + allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = + allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; + + if (allowed_mclk_vddci_table != NULL && allowed_mclk_vddci_table->count >= 1) { + data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v; + data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v; + } + + if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1) + hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v; + + return 0; +} + +static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) +{ + uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int i; + + if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) { + for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { + virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci, + virtual_voltage_id, + efuse_voltage_id) == 0) { + if (vddc != 0 && vddc != virtual_voltage_id) { + data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc; + data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id; + data->vddc_leakage.count++; + } + if (vddci != 0 && vddci != virtual_voltage_id) { + data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci; + data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id; + data->vddci_leakage.count++; + } + } + } + } + return 0; +} + +static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data; + int result = 0; + + data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + smu7_patch_voltage_workaround(hwmgr); + smu7_init_dpm_defaults(hwmgr); + + /* Get leakage voltage based on leakage ID. */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV)) { + result = smu7_get_evv_voltages(hwmgr); + if (result) { + pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); + return -EINVAL; + } + } else { + smu7_get_elb_voltages(hwmgr); + } + + if (hwmgr->pp_table_version == PP_TABLE_V1) { + smu7_complete_dependency_tables(hwmgr); + smu7_set_private_data_based_on_pptable_v1(hwmgr); + } else if (hwmgr->pp_table_version == PP_TABLE_V0) { + smu7_patch_dependency_tables_with_leakage(hwmgr); + smu7_set_private_data_based_on_pptable_v0(hwmgr); + } + + /* Initalize Dynamic State Adjustment Rule Settings */ + result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr); + + if (0 == result) { + struct amdgpu_device *adev = hwmgr->adev; + + data->is_tlu_enabled = false; + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + SMU7_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + data->pcie_gen_cap = adev->pm.pcie_gen_mask; + if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + data->pcie_spc_cap = 20; + data->pcie_lane_cap = adev->pm.pcie_mlw_mask; + + hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ +/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ + hwmgr->platform_descriptor.clockStep.engineClock = 500; + hwmgr->platform_descriptor.clockStep.memoryClock = 500; + smu7_thermal_parameter_init(hwmgr); + } else { + /* Ignore return value in here, we are cleaning up a mess. */ + smu7_hwmgr_backend_fini(hwmgr); + } + + return 0; +} + +static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t level, tmp; + + if (!data->pcie_dpm_key_disabled) { + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask; + while (tmp >>= 1) + level++; + + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PCIeDPM_ForceLevel, level, + NULL); + } + } + + if (!data->sclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; + while (tmp >>= 1) + level++; + + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + (1 << level), + NULL); + } + } + + if (!data->mclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask; + while (tmp >>= 1) + level++; + + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + (1 << level), + NULL); + } + } + + return 0; +} + +static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (hwmgr->pp_table_version == PP_TABLE_V1) + phm_apply_dal_min_voltage_request(hwmgr); +/* TO DO for v0 iceland and Ci*/ + + if (!data->sclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.sclk_dpm_enable_mask, + NULL); + } + + if (!data->mclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.mclk_dpm_enable_mask, + NULL); + } + + return 0; +} + +static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (!smum_is_dpm_running(hwmgr)) + return -EINVAL; + + if (!data->pcie_dpm_key_disabled) { + smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_PCIeDPM_UnForceLevel, + NULL); + } + + return smu7_upload_dpm_level_enable_mask(hwmgr); +} + +static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = + (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t level; + + if (!data->sclk_dpm_key_disabled) + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = phm_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + (1 << level), + NULL); + + } + + if (!data->mclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + level = phm_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.mclk_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + (1 << level), + NULL); + } + } + + if (!data->pcie_dpm_key_disabled) { + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { + level = phm_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.pcie_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PCIeDPM_ForceLevel, + (level), + NULL); + } + } + + return 0; +} + +static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask) +{ + uint32_t percentage; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table; + int32_t tmp_mclk; + int32_t tmp_sclk; + int32_t count; + + if (golden_dpm_table->mclk_table.count < 1) + return -EINVAL; + + percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value / + golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; + + if (golden_dpm_table->mclk_table.count == 1) { + percentage = 70; + tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; + *mclk_mask = golden_dpm_table->mclk_table.count - 1; + } else { + tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value; + *mclk_mask = golden_dpm_table->mclk_table.count - 2; + } + + tmp_sclk = tmp_mclk * percentage / 100; + + if (hwmgr->pp_table_version == PP_TABLE_V0) { + for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; + count >= 0; count--) { + if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) { + tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk; + *sclk_mask = count; + break; + } + } + if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].clk; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; + } else if (hwmgr->pp_table_version == PP_TABLE_V1) { + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) { + if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) { + tmp_sclk = table_info->vdd_dep_on_sclk->entries[count].clk; + *sclk_mask = count; + break; + } + } + if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + tmp_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) + *mclk_mask = 0; + else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + *mclk_mask = golden_dpm_table->mclk_table.count - 1; + + *pcie_mask = data->dpm_table.pcie_speed_table.count - 1; + hwmgr->pstate_sclk = tmp_sclk; + hwmgr->pstate_mclk = tmp_mclk; + + return 0; +} + +static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask = 0; + uint32_t mclk_mask = 0; + uint32_t pcie_mask = 0; + + if (hwmgr->pstate_sclk == 0) + smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = smu7_force_dpm_highest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = smu7_force_dpm_lowest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = smu7_unforce_dpm_levels(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); + if (ret) + return ret; + smu7_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); + } + return ret; +} + +static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct smu7_power_state); +} + +static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, + uint32_t vblank_time_us) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t switch_limit_us; + + switch (hwmgr->chip_id) { + case CHIP_POLARIS10: + case CHIP_POLARIS11: + case CHIP_POLARIS12: + if (hwmgr->is_kicker) + switch_limit_us = data->is_memory_gddr5 ? 450 : 150; + else + switch_limit_us = data->is_memory_gddr5 ? 190 : 150; + break; + case CHIP_VEGAM: + switch_limit_us = 30; + break; + default: + switch_limit_us = data->is_memory_gddr5 ? 450 : 150; + break; + } + + if (vblank_time_us < switch_limit_us) + return true; + else + return false; +} + +static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *request_ps, + const struct pp_power_state *current_ps) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct smu7_power_state *smu7_ps = + cast_phw_smu7_power_state(&request_ps->hardware); + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; + bool disable_mclk_switching; + bool disable_mclk_switching_for_frame_lock; + const struct phm_clock_and_voltage_limits *max_limits; + uint32_t i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int32_t count; + int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + + PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, + "VI should always have 2 performance levels", + ); + + max_limits = adev->pm.ac_power ? + &(hwmgr->dyn_state.max_clock_voltage_on_ac) : + &(hwmgr->dyn_state.max_clock_voltage_on_dc); + + /* Cap clock DPM tables at DC MAX if it is in DC. */ + if (!adev->pm.ac_power) { + for (i = 0; i < smu7_ps->performance_level_count; i++) { + if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk) + smu7_ps->performance_levels[i].memory_clock = max_limits->mclk; + if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk) + smu7_ps->performance_levels[i].engine_clock = max_limits->sclk; + } + } + + minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; + minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); + stable_pstate_sclk = (max_limits->sclk * 75) / 100; + + for (count = table_info->vdd_dep_on_sclk->count - 1; + count >= 0; count--) { + if (stable_pstate_sclk >= + table_info->vdd_dep_on_sclk->entries[count].clk) { + stable_pstate_sclk = + table_info->vdd_dep_on_sclk->entries[count].clk; + break; + } + } + + if (count < 0) + stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; + + stable_pstate_mclk = max_limits->mclk; + + minimum_clocks.engineClock = stable_pstate_sclk; + minimum_clocks.memoryClock = stable_pstate_mclk; + } + + disable_mclk_switching_for_frame_lock = phm_cap_enabled( + hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + + + if (hwmgr->display_config->num_display == 0) + disable_mclk_switching = false; + else + disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + disable_mclk_switching_for_frame_lock || + smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); + + sclk = smu7_ps->performance_levels[0].engine_clock; + mclk = smu7_ps->performance_levels[0].memory_clock; + + if (disable_mclk_switching) + mclk = smu7_ps->performance_levels + [smu7_ps->performance_level_count - 1].memory_clock; + + if (sclk < minimum_clocks.engineClock) + sclk = (minimum_clocks.engineClock > max_limits->sclk) ? + max_limits->sclk : minimum_clocks.engineClock; + + if (mclk < minimum_clocks.memoryClock) + mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? + max_limits->mclk : minimum_clocks.memoryClock; + + smu7_ps->performance_levels[0].engine_clock = sclk; + smu7_ps->performance_levels[0].memory_clock = mclk; + + smu7_ps->performance_levels[1].engine_clock = + (smu7_ps->performance_levels[1].engine_clock >= + smu7_ps->performance_levels[0].engine_clock) ? + smu7_ps->performance_levels[1].engine_clock : + smu7_ps->performance_levels[0].engine_clock; + + if (disable_mclk_switching) { + if (mclk < smu7_ps->performance_levels[1].memory_clock) + mclk = smu7_ps->performance_levels[1].memory_clock; + + smu7_ps->performance_levels[0].memory_clock = mclk; + smu7_ps->performance_levels[1].memory_clock = mclk; + } else { + if (smu7_ps->performance_levels[1].memory_clock < + smu7_ps->performance_levels[0].memory_clock) + smu7_ps->performance_levels[1].memory_clock = + smu7_ps->performance_levels[0].memory_clock; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + for (i = 0; i < smu7_ps->performance_level_count; i++) { + smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk; + smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk; + smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max; + smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max; + } + } + return 0; +} + + +static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct smu7_power_state *smu7_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + smu7_ps = cast_phw_smu7_power_state(&ps->hardware); + + if (low) + return smu7_ps->performance_levels[0].memory_clock; + else + return smu7_ps->performance_levels + [smu7_ps->performance_level_count-1].memory_clock; +} + +static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct smu7_power_state *smu7_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + smu7_ps = cast_phw_smu7_power_state(&ps->hardware); + + if (low) + return smu7_ps->performance_levels[0].engine_clock; + else + return smu7_ps->performance_levels + [smu7_ps->performance_level_count-1].engine_clock; +} + +static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps; + ATOM_FIRMWARE_INFO_V2_2 *fw_info; + uint16_t size; + uint8_t frev, crev; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + + /* First retrieve the Boot clocks and VDDC from the firmware info table. + * We assume here that fw_info is unchanged if this call fails. + */ + fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index, + &size, &frev, &crev); + if (!fw_info) + /* During a test, there is no firmware info table. */ + return 0; + + /* Patch the state. */ + data->vbios_boot_state.sclk_bootup_value = + le32_to_cpu(fw_info->ulDefaultEngineClock); + data->vbios_boot_state.mclk_bootup_value = + le32_to_cpu(fw_info->ulDefaultMemoryClock); + data->vbios_boot_state.mvdd_bootup_value = + le16_to_cpu(fw_info->usBootUpMVDDCVoltage); + data->vbios_boot_state.vddc_bootup_value = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + data->vbios_boot_state.vddci_bootup_value = + le16_to_cpu(fw_info->usBootUpVDDCIVoltage); + data->vbios_boot_state.pcie_gen_bootup_value = + smu7_get_current_pcie_speed(hwmgr); + + data->vbios_boot_state.pcie_lane_bootup_value = + (uint16_t)smu7_get_current_pcie_lane_number(hwmgr); + + /* set boot power state */ + ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value; + ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value; + ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value; + ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value; + + return 0; +} + +static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned long ret = 0; + + if (hwmgr->pp_table_version == PP_TABLE_V0) { + result = pp_tables_get_num_of_entries(hwmgr, &ret); + return result ? 0 : ret; + } else if (hwmgr->pp_table_version == PP_TABLE_V1) { + result = get_number_of_powerplay_table_entries_v1_0(hwmgr); + return result; + } + return 0; +} + +static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr, + void *state, struct pp_power_state *power_state, + void *pp_table, uint32_t classification_flag) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_power_state *smu7_power_state = + (struct smu7_power_state *)(&(power_state->hardware)); + struct smu7_performance_level *performance_level; + ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state; + ATOM_Tonga_POWERPLAYTABLE *powerplay_table = + (ATOM_Tonga_POWERPLAYTABLE *)pp_table; + PPTable_Generic_SubTable_Header *sclk_dep_table = + (PPTable_Generic_SubTable_Header *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + + ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (ATOM_Tonga_MCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + + /* The following fields are not initialized here: id orderedList allStatesList */ + power_state->classification.ui_label = + (le16_to_cpu(state_entry->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> + ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + power_state->classification.flags = classification_flag; + /* NOTE: There is a classification2 flag in BIOS that is not being used right now */ + + power_state->classification.temporary_state = false; + power_state->classification.to_be_deleted = false; + + power_state->validation.disallowOnDC = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Tonga_DISALLOW_ON_DC)); + + power_state->pcie.lanes = 0; + + power_state->display.disableFrameModulation = false; + power_state->display.limitRefreshrate = false; + power_state->display.enableVariBright = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Tonga_ENABLE_VARIBRIGHT)); + + power_state->validation.supportedPowerLevels = 0; + power_state->uvd_clocks.VCLK = 0; + power_state->uvd_clocks.DCLK = 0; + power_state->temperatures.min = 0; + power_state->temperatures.max = 0; + + performance_level = &(smu7_power_state->performance_levels + [smu7_power_state->performance_level_count++]); + + PP_ASSERT_WITH_CODE( + (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), + "Performance levels exceeds SMC limit!", + return -EINVAL); + + PP_ASSERT_WITH_CODE( + (smu7_power_state->performance_level_count <= + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), + "Performance levels exceeds Driver limit!", + return -EINVAL); + + /* Performance levels are arranged from low to high. */ + performance_level->memory_clock = mclk_dep_table->entries + [state_entry->ucMemoryClockIndexLow].ulMclk; + if (sclk_dep_table->ucRevId == 0) + performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries + [state_entry->ucEngineClockIndexLow].ulSclk; + else if (sclk_dep_table->ucRevId == 1) + performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries + [state_entry->ucEngineClockIndexLow].ulSclk; + performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, + state_entry->ucPCIEGenLow); + performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, + state_entry->ucPCIELaneLow); + + performance_level = &(smu7_power_state->performance_levels + [smu7_power_state->performance_level_count++]); + performance_level->memory_clock = mclk_dep_table->entries + [state_entry->ucMemoryClockIndexHigh].ulMclk; + + if (sclk_dep_table->ucRevId == 0) + performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries + [state_entry->ucEngineClockIndexHigh].ulSclk; + else if (sclk_dep_table->ucRevId == 1) + performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries + [state_entry->ucEngineClockIndexHigh].ulSclk; + + performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, + state_entry->ucPCIEGenHigh); + performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, + state_entry->ucPCIELaneHigh); + + return 0; +} + +static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *state) +{ + int result; + struct smu7_power_state *ps; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + + state->hardware.magic = PHM_VIslands_Magic; + + ps = (struct smu7_power_state *)(&state->hardware); + + result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state, + smu7_get_pp_table_entry_callback_func_v1); + + /* This is the earliest time we have all the dependency table and the VBIOS boot state + * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state + * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state + */ + if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { + if (dep_mclk_table->entries[0].clk != + data->vbios_boot_state.mclk_bootup_value) + pr_debug("Single MCLK entry VDDCI/MCLK dependency table " + "does not match VBIOS boot MCLK level"); + if (dep_mclk_table->entries[0].vddci != + data->vbios_boot_state.vddci_bootup_value) + pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " + "does not match VBIOS boot VDDCI level"); + } + + /* set DC compatible flag if this state supports DC */ + if (!state->validation.disallowOnDC) + ps->dc_compatible = true; + + if (state->classification.flags & PP_StateClassificationFlag_ACPI) + data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; + + ps->uvd_clks.vclk = state->uvd_clocks.VCLK; + ps->uvd_clks.dclk = state->uvd_clocks.DCLK; + + if (!result) { + uint32_t i; + + switch (state->classification.ui_label) { + case PP_StateUILabel_Performance: + data->use_pcie_performance_levels = true; + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_performance.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_performance.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_performance.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.max = + ps->performance_levels[i].pcie_lane; + if (data->pcie_lane_performance.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.min = + ps->performance_levels[i].pcie_lane; + } + break; + case PP_StateUILabel_Battery: + data->use_pcie_power_saving_levels = true; + + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_power_saving.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_power_saving.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_power_saving.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.max = + ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_power_saving.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.min = + ps->performance_levels[i].pcie_lane; + } + break; + default: + break; + } + } + return 0; +} + +static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *power_state, + unsigned int index, const void *clock_info) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_power_state *ps = cast_phw_smu7_power_state(power_state); + const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info; + struct smu7_performance_level *performance_level; + uint32_t engine_clock, memory_clock; + uint16_t pcie_gen_from_bios; + + engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow; + memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow; + + if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE) && memory_clock > data->highest_mclk) + data->highest_mclk = memory_clock; + + PP_ASSERT_WITH_CODE( + (ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), + "Performance levels exceeds SMC limit!", + return -EINVAL); + + PP_ASSERT_WITH_CODE( + (ps->performance_level_count < + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), + "Performance levels exceeds Driver limit, Skip!", + return 0); + + performance_level = &(ps->performance_levels + [ps->performance_level_count++]); + + /* Performance levels are arranged from low to high. */ + performance_level->memory_clock = memory_clock; + performance_level->engine_clock = engine_clock; + + pcie_gen_from_bios = visland_clk_info->ucPCIEGen; + + performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios); + performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane); + + return 0; +} + +static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *state) +{ + int result; + struct smu7_power_state *ps; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_clock_voltage_dependency_table *dep_mclk_table = + hwmgr->dyn_state.vddci_dependency_on_mclk; + + memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state)); + + state->hardware.magic = PHM_VIslands_Magic; + + ps = (struct smu7_power_state *)(&state->hardware); + + result = pp_tables_get_entry(hwmgr, entry_index, state, + smu7_get_pp_table_entry_callback_func_v0); + + /* + * This is the earliest time we have all the dependency table + * and the VBIOS boot state as + * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot + * state if there is only one VDDCI/MCLK level, check if it's + * the same as VBIOS boot state + */ + if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { + if (dep_mclk_table->entries[0].clk != + data->vbios_boot_state.mclk_bootup_value) + pr_debug("Single MCLK entry VDDCI/MCLK dependency table " + "does not match VBIOS boot MCLK level"); + if (dep_mclk_table->entries[0].v != + data->vbios_boot_state.vddci_bootup_value) + pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " + "does not match VBIOS boot VDDCI level"); + } + + /* set DC compatible flag if this state supports DC */ + if (!state->validation.disallowOnDC) + ps->dc_compatible = true; + + if (state->classification.flags & PP_StateClassificationFlag_ACPI) + data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; + + ps->uvd_clks.vclk = state->uvd_clocks.VCLK; + ps->uvd_clks.dclk = state->uvd_clocks.DCLK; + + if (!result) { + uint32_t i; + + switch (state->classification.ui_label) { + case PP_StateUILabel_Performance: + data->use_pcie_performance_levels = true; + + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_performance.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_performance.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_performance.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.max = + ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_performance.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.min = + ps->performance_levels[i].pcie_lane; + } + break; + case PP_StateUILabel_Battery: + data->use_pcie_power_saving_levels = true; + + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_power_saving.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_power_saving.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_power_saving.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.max = + ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_power_saving.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.min = + ps->performance_levels[i].pcie_lane; + } + break; + default: + break; + } + } + return 0; +} + +static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *state) +{ + if (hwmgr->pp_table_version == PP_TABLE_V0) + return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state); + else if (hwmgr->pp_table_version == PP_TABLE_V1) + return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state); + + return 0; +} + +static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query) +{ + struct amdgpu_device *adev = hwmgr->adev; + int i; + u32 tmp = 0; + + if (!query) + return -EINVAL; + + /* + * PPSMC_MSG_GetCurrPkgPwr is not supported on: + * - Hawaii + * - Bonaire + * - Fiji + * - Tonga + */ + if ((adev->asic_type != CHIP_HAWAII) && + (adev->asic_type != CHIP_BONAIRE) && + (adev->asic_type != CHIP_FIJI) && + (adev->asic_type != CHIP_TONGA)) { + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0, &tmp); + *query = tmp; + + if (tmp != 0) + return 0; + } + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart, NULL); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_PM_STATUS_95, 0); + + for (i = 0; i < 10; i++) { + msleep(500); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample, NULL); + tmp = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + ixSMU_PM_STATUS_95); + if (tmp != 0) + break; + } + *query = tmp; + + return 0; +} + +static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + uint32_t sclk, mclk, activity_percent; + uint32_t offset, val_vid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &sclk); + *((uint32_t *)value) = sclk; + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &mclk); + *((uint32_t *)value) = mclk; + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + case AMDGPU_PP_SENSOR_MEM_LOAD: + offset = data->soft_regs_start + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, + (idx == AMDGPU_PP_SENSOR_GPU_LOAD) ? + AverageGraphicsActivity: + AverageMemoryActivity); + + activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + activity_percent += 0x80; + activity_percent >>= 8; + *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_UVD_POWER: + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_VCE_POWER: + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + *size = 4; + return 0; + case AMDGPU_PP_SENSOR_GPU_POWER: + return smu7_get_gpu_power(hwmgr, (uint32_t *)value); + case AMDGPU_PP_SENSOR_VDDGFX: + if ((data->vr_config & 0xff) == 0x2) + val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); + else + val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID); + + *((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid); + return 0; + default: + return -EINVAL; + } +} + +static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + const struct smu7_power_state *smu7_ps = + cast_const_phw_smu7_power_state(states->pnew_state); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + uint32_t sclk = smu7_ps->performance_levels + [smu7_ps->performance_level_count - 1].engine_clock; + struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + uint32_t mclk = smu7_ps->performance_levels + [smu7_ps->performance_level_count - 1].memory_clock; + struct PP_Clocks min_clocks = {0}; + uint32_t i; + + for (i = 0; i < sclk_table->count; i++) { + if (sclk == sclk_table->dpm_levels[i].value) + break; + } + + if (i >= sclk_table->count) { + if (sclk > sclk_table->dpm_levels[i-1].value) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + sclk_table->dpm_levels[i-1].value = sclk; + } + } else { + /* TODO: Check SCLK in DAL's minimum clocks + * in case DeepSleep divider update is required. + */ + if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR && + (min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK || + data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK; + } + + for (i = 0; i < mclk_table->count; i++) { + if (mclk == mclk_table->dpm_levels[i].value) + break; + } + + if (i >= mclk_table->count) { + if (mclk > mclk_table->dpm_levels[i-1].value) { + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + mclk_table->dpm_levels[i-1].value = mclk; + } + } + + if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; + + return 0; +} + +static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr, + const struct smu7_power_state *smu7_ps) +{ + uint32_t i; + uint32_t sclk, max_sclk = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + + for (i = 0; i < smu7_ps->performance_level_count; i++) { + sclk = smu7_ps->performance_levels[i].engine_clock; + if (max_sclk < sclk) + max_sclk = sclk; + } + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk) + return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ? + dpm_table->pcie_speed_table.dpm_levels + [dpm_table->pcie_speed_table.count - 1].value : + dpm_table->pcie_speed_table.dpm_levels[i].value); + } + + return 0; +} + +static int smu7_request_link_speed_change_before_state_change( + struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct smu7_power_state *smu7_nps = + cast_const_phw_smu7_power_state(states->pnew_state); + const struct smu7_power_state *polaris10_cps = + cast_const_phw_smu7_power_state(states->pcurrent_state); + + uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps); + uint16_t current_link_speed; + + if (data->force_pcie_gen == PP_PCIEGenInvalid) + current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps); + else + current_link_speed = data->force_pcie_gen; + + data->force_pcie_gen = PP_PCIEGenInvalid; + data->pspp_notify_required = false; + + if (target_link_speed > current_link_speed) { + switch (target_link_speed) { +#ifdef CONFIG_ACPI + case PP_PCIEGen3: + if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN3, false)) + break; + data->force_pcie_gen = PP_PCIEGen2; + if (current_link_speed == PP_PCIEGen2) + break; + fallthrough; + case PP_PCIEGen2: + if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false)) + break; + fallthrough; +#endif + default: + data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr); + break; + } + } else { + if (target_link_speed < current_link_speed) + data->pspp_notify_required = true; + } + + return 0; +} + +static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to freeze SCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_SCLKDPM_FreezeLevel, + NULL), + "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", + return -EINVAL); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + DPMTABLE_OD_UPDATE_MCLK)) { + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to freeze MCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_MCLKDPM_FreezeLevel, + NULL), + "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", + return -EINVAL); + } + + return 0; +} + +static int smu7_populate_and_upload_sclk_mclk_dpm_levels( + struct pp_hwmgr *hwmgr, const void *input) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + uint32_t count; + struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); + struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { + for (count = 0; count < dpm_table->sclk_table.count; count++) { + dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled; + dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock; + } + } + + if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { + for (count = 0; count < dpm_table->mclk_table.count; count++) { + dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled; + dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock; + } + } + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) { + result = smum_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { + /*populate MCLK dpm table to SMU7 */ + result = smum_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + return result; +} + +static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr, + struct smu7_single_dpm_table *dpm_table, + uint32_t low_limit, uint32_t high_limit) +{ + uint32_t i; + + /* force the trim if mclk_switching is disabled to prevent flicker */ + bool force_trim = (low_limit == high_limit); + for (i = 0; i < dpm_table->count; i++) { + /*skip the trim if od is enabled*/ + if ((!hwmgr->od_enabled || force_trim) + && (dpm_table->dpm_levels[i].value < low_limit + || dpm_table->dpm_levels[i].value > high_limit)) + dpm_table->dpm_levels[i].enabled = false; + else + dpm_table->dpm_levels[i].enabled = true; + } + + return 0; +} + +static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr, + const struct smu7_power_state *smu7_ps) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t high_limit_count; + + PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1), + "power state did not have any performance level", + return -EINVAL); + + high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1; + + smu7_trim_single_dpm_states(hwmgr, + &(data->dpm_table.sclk_table), + smu7_ps->performance_levels[0].engine_clock, + smu7_ps->performance_levels[high_limit_count].engine_clock); + + smu7_trim_single_dpm_states(hwmgr, + &(data->dpm_table.mclk_table), + smu7_ps->performance_levels[0].memory_clock, + smu7_ps->performance_levels[high_limit_count].memory_clock); + + return 0; +} + +static int smu7_generate_dpm_level_enable_mask( + struct pp_hwmgr *hwmgr, const void *input) +{ + int result = 0; + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct smu7_power_state *smu7_ps = + cast_const_phw_smu7_power_state(states->pnew_state); + + + result = smu7_trim_dpm_states(hwmgr, smu7_ps); + if (result) + return result; + + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table); + data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table); + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table); + + return 0; +} + +static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to Unfreeze SCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_SCLKDPM_UnfreezeLevel, + NULL), + "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", + return -EINVAL); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { + + PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), + "Trying to Unfreeze MCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_MCLKDPM_UnfreezeLevel, + NULL), + "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", + return -EINVAL); + } + + data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; + + return 0; +} + +static int smu7_notify_link_speed_change_after_state_change( + struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct smu7_power_state *smu7_ps = + cast_const_phw_smu7_power_state(states->pnew_state); + uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps); + uint8_t request; + + if (data->pspp_notify_required) { + if (target_link_speed == PP_PCIEGen3) + request = PCIE_PERF_REQ_GEN3; + else if (target_link_speed == PP_PCIEGen2) + request = PCIE_PERF_REQ_GEN2; + else + request = PCIE_PERF_REQ_GEN1; + + if (request == PCIE_PERF_REQ_GEN1 && + smu7_get_current_pcie_speed(hwmgr) > 0) + return 0; + +#ifdef CONFIG_ACPI + if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false)) { + if (PP_PCIEGen2 == target_link_speed) + pr_info("PSPP request to switch to Gen2 from Gen3 Failed!"); + else + pr_info("PSPP request to switch to Gen1 from Gen2 Failed!"); + } +#endif + } + + return 0; +} + +static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { + if (hwmgr->chip_id == CHIP_VEGAM) + smum_send_msg_to_smc_with_parameter(hwmgr, + (PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM, data->frame_time_x2, + NULL); + else + smum_send_msg_to_smc_with_parameter(hwmgr, + (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2, + NULL); + } + return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ? 0 : -EINVAL; +} + +static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + int tmp_result, result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to find DPM states clocks in DPM table!", + result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = + smu7_request_link_speed_change_before_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to request link speed change before state change!", + result = tmp_result); + } + + tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to freeze SCLK MCLK DPM!", result = tmp_result); + + tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate and upload SCLK MCLK DPM levels!", + result = tmp_result); + + /* + * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. + * That effectively disables AVFS feature. + */ + if (hwmgr->hardcode_pp_table != NULL) + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; + + tmp_result = smu7_update_avfs(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to update avfs voltages!", + result = tmp_result); + + tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to generate DPM level enabled mask!", + result = tmp_result); + + tmp_result = smum_update_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to update SCLK threshold!", + result = tmp_result); + + tmp_result = smu7_notify_smc_display(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify smc display settings!", + result = tmp_result); + + tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to unfreeze SCLK MCLK DPM!", + result = tmp_result); + + tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to upload DPM level enabled mask!", + result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = + smu7_notify_link_speed_change_after_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify link speed change after state change!", + result = tmp_result); + } + data->apply_optimized_settings = false; + return result; +} + +static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm) +{ + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm, + NULL); +} + +static int +smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) +{ + PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; + + return (smum_send_msg_to_smc(hwmgr, msg, NULL) == 0) ? 0 : -1; +} + +static int +smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->display_config->num_display > 1 && + !hwmgr->display_config->multi_monitor_in_sync) + smu7_notify_smc_display_change(hwmgr, false); + + return 0; +} + +/** +* Programs the display gap +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always OK +*/ +static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); + uint32_t display_gap2; + uint32_t pre_vbi_time_in_us; + uint32_t frame_time_in_us; + uint32_t ref_clock, refresh_rate; + + display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap); + + ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + refresh_rate = hwmgr->display_config->vrefresh; + + if (0 == refresh_rate) + refresh_rate = 60; + + frame_time_in_us = 1000000 / refresh_rate; + + pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time; + + data->frame_time_x2 = frame_time_in_us * 2 / 100; + + if (data->frame_time_x2 < 280) { + pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2); + data->frame_time_x2 = 280; + } + + display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, + PreVBlankGap), 0x64); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, + VBlankTimeout), + (frame_time_in_us - pre_vbi_time_in_us)); + + return 0; +} + +static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + return smu7_program_display_gap(hwmgr); +} + +/** +* Set maximum target operating fan output RPM +* +* @param hwmgr: the address of the powerplay hardware manager. +* @param usMaxFanRpm: max operating fan RPM value. +* @return The response that came from the SMC. +*/ +static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm) +{ + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm; + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm, + NULL); +} + +static const struct amdgpu_irq_src_funcs smu7_irq_funcs = { + .process = phm_irq_process, +}; + +static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_irq_src *source = + kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL); + + if (!source) + return -ENOMEM; + + source->funcs = &smu7_irq_funcs; + + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + AMDGPU_IRQ_CLIENTID_LEGACY, + VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH, + source); + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + AMDGPU_IRQ_CLIENTID_LEGACY, + VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW, + source); + + /* Register CTF(GPIO_19) interrupt */ + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + AMDGPU_IRQ_CLIENTID_LEGACY, + VISLANDS30_IV_SRCID_GPIO_19, + source); + + return 0; +} + +static bool +smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + bool is_update_required = false; + + if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) + is_update_required = true; + + if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh) + is_update_required = true; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr && + (data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK || + hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) + is_update_required = true; + } + return is_update_required; +} + +static inline bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1, + const struct smu7_performance_level *pl2) +{ + return ((pl1->memory_clock == pl2->memory_clock) && + (pl1->engine_clock == pl2->engine_clock) && + (pl1->pcie_gen == pl2->pcie_gen) && + (pl1->pcie_lane == pl2->pcie_lane)); +} + +static int smu7_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, bool *equal) +{ + const struct smu7_power_state *psa; + const struct smu7_power_state *psb; + int i; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (pstate1 == NULL || pstate2 == NULL || equal == NULL) + return -EINVAL; + + psa = cast_const_phw_smu7_power_state(pstate1); + psb = cast_const_phw_smu7_power_state(pstate2); + /* If the two states don't even have the same number of performance levels they cannot be the same state. */ + if (psa->performance_level_count != psb->performance_level_count) { + *equal = false; + return 0; + } + + for (i = 0; i < psa->performance_level_count; i++) { + if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { + /* If we have found even one performance level pair that is different the states are different. */ + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); + *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); + *equal &= (psa->sclk_threshold == psb->sclk_threshold); + /* For OD call, set value based on flag */ + *equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | + DPMTABLE_OD_UPDATE_MCLK | + DPMTABLE_OD_UPDATE_VDDC)); + + return 0; +} + +static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t tmp; + + /* Read MC indirect register offset 0x9F bits [3:0] to see + * if VBIOS has already loaded a full version of MC ucode + * or not. + */ + + smu7_get_mc_microcode_version(hwmgr); + + data->need_long_memory_training = false; + + cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, + ixMC_IO_DEBUG_UP_13); + tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); + + if (tmp & (1 << 23)) { + data->mem_latency_high = MEM_LATENCY_HIGH; + data->mem_latency_low = MEM_LATENCY_LOW; + if ((hwmgr->chip_id == CHIP_POLARIS10) || + (hwmgr->chip_id == CHIP_POLARIS11) || + (hwmgr->chip_id == CHIP_POLARIS12)) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC, NULL); + } else { + data->mem_latency_high = 330; + data->mem_latency_low = 330; + if ((hwmgr->chip_id == CHIP_POLARIS10) || + (hwmgr->chip_id == CHIP_POLARIS11) || + (hwmgr->chip_id == CHIP_POLARIS12)) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC, NULL); + } + + return 0; +} + +static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->clock_registers.vCG_SPLL_FUNC_CNTL = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL); + data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2); + data->clock_registers.vCG_SPLL_FUNC_CNTL_3 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3); + data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2); + data->clock_registers.vDLL_CNTL = + cgs_read_register(hwmgr->device, mmDLL_CNTL); + data->clock_registers.vMCLK_PWRMGT_CNTL = + cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL); + data->clock_registers.vMPLL_AD_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL); + data->clock_registers.vMPLL_DQ_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL); + data->clock_registers.vMPLL_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL); + data->clock_registers.vMPLL_FUNC_CNTL_1 = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1); + data->clock_registers.vMPLL_FUNC_CNTL_2 = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2); + data->clock_registers.vMPLL_SS1 = + cgs_read_register(hwmgr->device, mmMPLL_SS1); + data->clock_registers.vMPLL_SS2 = + cgs_read_register(hwmgr->device, mmMPLL_SS2); + return 0; + +} + +/** + * Find out if memory is GDDR5. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int smu7_get_memory_type(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + + data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5); + + return 0; +} + +/** + * Enables Dynamic Power Management by SMC + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, STATIC_PM_EN, 1); + + return 0; +} + +/** + * Initialize PowerGating States for different engines + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + + return 0; +} + +static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + data->low_sclk_interrupt_threshold = 0; + return 0; +} + +static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + smu7_check_mc_firmware(hwmgr); + + tmp_result = smu7_read_clock_registers(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to read clock registers!", result = tmp_result); + + tmp_result = smu7_get_memory_type(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get memory type!", result = tmp_result); + + tmp_result = smu7_enable_acpi_power_management(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable ACPI power management!", result = tmp_result); + + tmp_result = smu7_init_power_gate_state(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init power gate state!", result = tmp_result); + + tmp_result = smu7_get_mc_microcode_version(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get MC microcode version!", result = tmp_result); + + tmp_result = smu7_init_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init sclk threshold!", result = tmp_result); + + return result; +} + +static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (mask == 0) + return -EINVAL; + + switch (type) { + case PP_SCLK: + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask, + NULL); + break; + case PP_MCLK: + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask, + NULL); + break; + case PP_PCIE: + { + uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; + + if (!data->pcie_dpm_key_disabled) { + if (fls(tmp) != ffs(tmp)) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel, + NULL); + else + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PCIeDPM_ForceLevel, + fls(tmp) - 1, + NULL); + } + break; + } + default: + break; + } + + return 0; +} + +static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table); + struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); + struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); + int i, now, size = 0; + uint32_t clock, pcie_speed; + + switch (type) { + case PP_SCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &clock); + + for (i = 0; i < sclk_table->count; i++) { + if (clock > sclk_table->dpm_levels[i].value) + continue; + break; + } + now = i; + + for (i = 0; i < sclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_MCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &clock); + + for (i = 0; i < mclk_table->count; i++) { + if (clock > mclk_table->dpm_levels[i].value) + continue; + break; + } + now = i; + + for (i = 0; i < mclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, mclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_PCIE: + pcie_speed = smu7_get_current_pcie_speed(hwmgr); + for (i = 0; i < pcie_table->count; i++) { + if (pcie_speed != pcie_table->dpm_levels[i].value) + continue; + break; + } + now = i; + + for (i = 0; i < pcie_table->count; i++) + size += sprintf(buf + size, "%d: %s %s\n", i, + (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" : + (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" : + (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "", + (i == now) ? "*" : ""); + break; + case OD_SCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + for (i = 0; i < odn_sclk_table->num_of_pl; i++) + size += sprintf(buf + size, "%d: %10uMHz %10umV\n", + i, odn_sclk_table->entries[i].clock/100, + odn_sclk_table->entries[i].vddc); + } + break; + case OD_MCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_MCLK"); + for (i = 0; i < odn_mclk_table->num_of_pl; i++) + size += sprintf(buf + size, "%d: %10uMHz %10umV\n", + i, odn_mclk_table->entries[i].clock/100, + odn_mclk_table->entries[i].vddc); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_RANGE"); + size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); + size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); + size += sprintf(buf + size, "VDDC: %7umV %11umV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + } + break; + default: + break; + } + return size; +} + +static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + switch (mode) { + case AMD_FAN_CTRL_NONE: + smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + smu7_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode)) + smu7_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } +} + +static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL; +} + +static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct smu7_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + int value = sclk_table->dpm_levels[sclk_table->count - 1].value; + int golden_value = golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.sclk_table); + struct pp_power_state *ps; + struct smu7_power_state *smu7_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + smu7_ps = cast_phw_smu7_power_state(&ps->hardware); + + smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock = + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * + value / 100 + + golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + return 0; +} + +static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + struct smu7_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + int value = mclk_table->dpm_levels[mclk_table->count - 1].value; + int golden_value = golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mclk_table); + struct pp_power_state *ps; + struct smu7_power_state *smu7_ps; + + if (value > 20) + value = 20; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + smu7_ps = cast_phw_smu7_power_state(&ps->hardware); + + smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock = + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * + value / 100 + + golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + return 0; +} + + +static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL; + struct phm_clock_voltage_dependency_table *sclk_table; + int i; + + if (hwmgr->pp_table_version == PP_TABLE_V1) { + if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL) + return -EINVAL; + dep_sclk_table = table_info->vdd_dep_on_sclk; + for (i = 0; i < dep_sclk_table->count; i++) + clocks->clock[i] = dep_sclk_table->entries[i].clk * 10; + clocks->count = dep_sclk_table->count; + } else if (hwmgr->pp_table_version == PP_TABLE_V0) { + sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk; + for (i = 0; i < sclk_table->count; i++) + clocks->clock[i] = sclk_table->entries[i].clk * 10; + clocks->count = sclk_table->count; + } + + return 0; +} + +static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (clk >= MEM_FREQ_LOW_LATENCY && clk < MEM_FREQ_HIGH_LATENCY) + return data->mem_latency_high; + else if (clk >= MEM_FREQ_HIGH_LATENCY) + return data->mem_latency_low; + else + return MEM_LATENCY_ERR; +} + +static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; + int i; + struct phm_clock_voltage_dependency_table *mclk_table; + + if (hwmgr->pp_table_version == PP_TABLE_V1) { + if (table_info == NULL) + return -EINVAL; + dep_mclk_table = table_info->vdd_dep_on_mclk; + for (i = 0; i < dep_mclk_table->count; i++) { + clocks->clock[i] = dep_mclk_table->entries[i].clk * 10; + clocks->latency[i] = smu7_get_mem_latency(hwmgr, + dep_mclk_table->entries[i].clk); + } + clocks->count = dep_mclk_table->count; + } else if (hwmgr->pp_table_version == PP_TABLE_V0) { + mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk; + for (i = 0; i < mclk_table->count; i++) + clocks->clock[i] = mclk_table->entries[i].clk * 10; + clocks->count = mclk_table->count; + } + return 0; +} + +static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks) +{ + switch (type) { + case amd_pp_sys_clock: + smu7_get_sclks(hwmgr, clocks); + break; + case amd_pp_mem_clock: + smu7_get_mclks(hwmgr, clocks); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_ADDR_H), + mc_addr_hi); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_ADDR_L), + mc_addr_low); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H), + virtual_addr_hi); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L), + virtual_addr_low); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE), + size); + return 0; +} + +static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *clocks) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + + if (clocks == NULL) + return -EINVAL; + + clocks->memory_max_clock = mclk_table->count > 1 ? + mclk_table->dpm_levels[mclk_table->count-1].value : + mclk_table->dpm_levels[0].value; + clocks->engine_max_clock = sclk_table->count > 1 ? + sclk_table->dpm_levels[sclk_table->count-1].value : + sclk_table->dpm_levels[0].value; + return 0; +} + +static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *thermal_data) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + + memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); + + if (hwmgr->pp_table_version == PP_TABLE_V1) + thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + else if (hwmgr->pp_table_version == PP_TABLE_V0) + thermal_data->max = data->thermal_temp_setting.temperature_shutdown * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + uint32_t clk, + uint32_t voltage) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) { + pr_info("OD voltage is out of range [%d - %d] mV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + return false; + } + + if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { + if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk || + hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { + pr_info("OD engine clock is out of range [%d - %d] MHz\n", + data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); + return false; + } + } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { + if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk || + hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { + pr_info("OD memory clock is out of range [%d - %d] MHz\n", + data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); + return false; + } + } else { + return false; + } + + return true; +} + +static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + uint32_t i; + struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL; + struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t input_clk; + uint32_t input_vol; + uint32_t input_level; + + PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", + return -EINVAL); + + if (!hwmgr->od_enabled) { + pr_info("OverDrive feature not enabled\n"); + return -EINVAL; + } + + if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { + podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels; + podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk; + PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), + "Failed to get ODN SCLK and Voltage tables", + return -EINVAL); + } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { + podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels; + podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk; + + PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), + "Failed to get ODN MCLK and Voltage tables", + return -EINVAL); + } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { + smu7_odn_initial_default_setting(hwmgr); + return 0; + } else if (PP_OD_COMMIT_DPM_TABLE == type) { + smu7_check_dpm_table_updated(hwmgr); + return 0; + } else { + return -EINVAL; + } + + for (i = 0; i < size; i += 3) { + if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) { + pr_info("invalid clock voltage input \n"); + return 0; + } + input_level = input[i]; + input_clk = input[i+1] * 100; + input_vol = input[i+2]; + + if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { + podn_dpm_table_in_backend->entries[input_level].clock = input_clk; + podn_vdd_dep_in_backend->entries[input_level].clk = input_clk; + podn_dpm_table_in_backend->entries[input_level].vddc = input_vol; + podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol; + podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol; + } else { + return -EINVAL; + } + } + + return 0; +} + +static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t i, size = 0; + uint32_t len; + + static const char *profile_name[7] = {"BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + + static const char *title[8] = {"NUM", + "MODE_NAME", + "SCLK_UP_HYST", + "SCLK_DOWN_HYST", + "SCLK_ACTIVE_LEVEL", + "MCLK_UP_HYST", + "MCLK_DOWN_HYST", + "MCLK_ACTIVE_LEVEL"}; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%s %16s %16s %16s %16s %16s %16s %16s\n", + title[0], title[1], title[2], title[3], + title[4], title[5], title[6], title[7]); + + len = ARRAY_SIZE(smu7_profiling); + + for (i = 0; i < len; i++) { + if (i == hwmgr->power_profile_mode) { + size += sprintf(buf + size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n", + i, profile_name[i], "*", + data->current_profile_setting.sclk_up_hyst, + data->current_profile_setting.sclk_down_hyst, + data->current_profile_setting.sclk_activity, + data->current_profile_setting.mclk_up_hyst, + data->current_profile_setting.mclk_down_hyst, + data->current_profile_setting.mclk_activity); + continue; + } + if (smu7_profiling[i].bupdate_sclk) + size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ", + i, profile_name[i], smu7_profiling[i].sclk_up_hyst, + smu7_profiling[i].sclk_down_hyst, + smu7_profiling[i].sclk_activity); + else + size += sprintf(buf + size, "%3d %16s: %8s %16s %16s ", + i, profile_name[i], "-", "-", "-"); + + if (smu7_profiling[i].bupdate_mclk) + size += sprintf(buf + size, "%16d %16d %16d\n", + smu7_profiling[i].mclk_up_hyst, + smu7_profiling[i].mclk_down_hyst, + smu7_profiling[i].mclk_activity); + else + size += sprintf(buf + size, "%16s %16s %16s\n", + "-", "-", "-"); + } + + return size; +} + +static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr, + enum PP_SMC_POWER_PROFILE requst) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t tmp, level; + + if (requst == PP_SMC_POWER_PROFILE_COMPUTE) { + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; + while (tmp >>= 1) + level++; + if (level > 0) + smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1)); + } + } else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) { + smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask); + } +} + +static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct profile_mode_setting tmp; + enum PP_SMC_POWER_PROFILE mode; + + if (input == NULL) + return -EINVAL; + + mode = input[size]; + switch (mode) { + case PP_SMC_POWER_PROFILE_CUSTOM: + if (size < 8 && size != 0) + return -EINVAL; + /* If only CUSTOM is passed in, use the saved values. Check + * that we actually have a CUSTOM profile by ensuring that + * the "use sclk" or the "use mclk" bits are set + */ + tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM]; + if (size == 0) { + if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0) + return -EINVAL; + } else { + tmp.bupdate_sclk = input[0]; + tmp.sclk_up_hyst = input[1]; + tmp.sclk_down_hyst = input[2]; + tmp.sclk_activity = input[3]; + tmp.bupdate_mclk = input[4]; + tmp.mclk_up_hyst = input[5]; + tmp.mclk_down_hyst = input[6]; + tmp.mclk_activity = input[7]; + smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp; + } + if (!smum_update_dpm_settings(hwmgr, &tmp)) { + memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting)); + hwmgr->power_profile_mode = mode; + } + break; + case PP_SMC_POWER_PROFILE_FULLSCREEN3D: + case PP_SMC_POWER_PROFILE_POWERSAVING: + case PP_SMC_POWER_PROFILE_VIDEO: + case PP_SMC_POWER_PROFILE_VR: + case PP_SMC_POWER_PROFILE_COMPUTE: + if (mode == hwmgr->power_profile_mode) + return 0; + + memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting)); + if (!smum_update_dpm_settings(hwmgr, &tmp)) { + if (tmp.bupdate_sclk) { + data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk; + data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst; + data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst; + data->current_profile_setting.sclk_activity = tmp.sclk_activity; + } + if (tmp.bupdate_mclk) { + data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk; + data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst; + data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst; + data->current_profile_setting.mclk_activity = tmp.mclk_activity; + } + smu7_patch_compute_profile_mode(hwmgr, mode); + hwmgr->power_profile_mode = mode; + } + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + const struct smu7_power_state *ps; + uint32_t i; + + if (level == NULL || hwmgr == NULL || state == NULL) + return -EINVAL; + + ps = cast_const_phw_smu7_power_state(state); + + i = index > ps->performance_level_count - 1 ? + ps->performance_level_count - 1 : index; + + level->coreClock = ps->performance_levels[i].engine_clock; + level->memory_clock = ps->performance_levels[i].memory_clock; + + return 0; +} + +static int smu7_power_off_asic(struct pp_hwmgr *hwmgr) +{ + int result; + + result = smu7_disable_dpm_tasks(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "[disable_dpm_tasks] Failed to disable DPM!", + ); + + return result; +} + +static const struct pp_hwmgr_func smu7_hwmgr_funcs = { + .backend_init = &smu7_hwmgr_backend_init, + .backend_fini = &smu7_hwmgr_backend_fini, + .asic_setup = &smu7_setup_asic_task, + .dynamic_state_management_enable = &smu7_enable_dpm_tasks, + .apply_state_adjust_rules = smu7_apply_state_adjust_rules, + .force_dpm_level = &smu7_force_dpm_level, + .power_state_set = smu7_set_power_state_tasks, + .get_power_state_size = smu7_get_power_state_size, + .get_mclk = smu7_dpm_get_mclk, + .get_sclk = smu7_dpm_get_sclk, + .patch_boot_state = smu7_dpm_patch_boot_state, + .get_pp_table_entry = smu7_get_pp_table_entry, + .get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries, + .powerdown_uvd = smu7_powerdown_uvd, + .powergate_uvd = smu7_powergate_uvd, + .powergate_vce = smu7_powergate_vce, + .disable_clock_power_gating = smu7_disable_clock_power_gating, + .update_clock_gatings = smu7_update_clock_gatings, + .notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment, + .display_config_changed = smu7_display_configuration_changed_task, + .set_max_fan_pwm_output = smu7_set_max_fan_pwm_output, + .set_max_fan_rpm_output = smu7_set_max_fan_rpm_output, + .stop_thermal_controller = smu7_thermal_stop_thermal_controller, + .get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info, + .get_fan_speed_percent = smu7_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = smu7_fan_ctrl_set_fan_speed_percent, + .reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default, + .get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm, + .set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm, + .uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller, + .register_irq_handlers = smu7_register_irq_handlers, + .check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration, + .check_states_equal = smu7_check_states_equal, + .set_fan_control_mode = smu7_set_fan_control_mode, + .get_fan_control_mode = smu7_get_fan_control_mode, + .force_clock_level = smu7_force_clock_level, + .print_clock_levels = smu7_print_clock_levels, + .powergate_gfx = smu7_powergate_gfx, + .get_sclk_od = smu7_get_sclk_od, + .set_sclk_od = smu7_set_sclk_od, + .get_mclk_od = smu7_get_mclk_od, + .set_mclk_od = smu7_set_mclk_od, + .get_clock_by_type = smu7_get_clock_by_type, + .read_sensor = smu7_read_sensor, + .dynamic_state_management_disable = smu7_disable_dpm_tasks, + .avfs_control = smu7_avfs_control, + .disable_smc_firmware_ctf = smu7_thermal_disable_alert, + .start_thermal_controller = smu7_start_thermal_controller, + .notify_cac_buffer_info = smu7_notify_cac_buffer_info, + .get_max_high_clocks = smu7_get_max_high_clocks, + .get_thermal_temperature_range = smu7_get_thermal_temperature_range, + .odn_edit_dpm_table = smu7_odn_edit_dpm_table, + .set_power_limit = smu7_set_power_limit, + .get_power_profile_mode = smu7_get_power_profile_mode, + .set_power_profile_mode = smu7_set_power_profile_mode, + .get_performance_level = smu7_get_performance_level, + .get_asic_baco_capability = smu7_baco_get_capability, + .get_asic_baco_state = smu7_baco_get_state, + .set_asic_baco_state = smu7_baco_set_state, + .power_off_asic = smu7_power_off_asic, +}; + +uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr) +{ + uint8_t i; + uint32_t temp; + uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK); + + PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0); + for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { + temp = clock >> i; + + if (temp >= min || i == 0) + break; + } + return i; +} + +int smu7_init_function_pointers(struct pp_hwmgr *hwmgr) +{ + hwmgr->hwmgr_func = &smu7_hwmgr_funcs; + if (hwmgr->pp_table_version == PP_TABLE_V0) + hwmgr->pptable_func = &pptable_funcs; + else if (hwmgr->pp_table_version == PP_TABLE_V1) + hwmgr->pptable_func = &pptable_v1_0_funcs; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h new file mode 100644 index 000000000000..69d361f8dfca --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.h @@ -0,0 +1,368 @@ +/* + * Copyright 2015 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 _SMU7_HWMGR_H +#define _SMU7_HWMGR_H + +#include "hwmgr.h" +#include "ppatomctrl.h" + +#define SMU7_MAX_HARDWARE_POWERLEVELS 2 + +#define SMU7_VOLTAGE_CONTROL_NONE 0x0 +#define SMU7_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define SMU7_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define SMU7_VOLTAGE_CONTROL_MERGED 0x3 + +enum gpu_pt_config_reg_type { + GPU_CONFIGREG_MMR = 0, + GPU_CONFIGREG_SMC_IND, + GPU_CONFIGREG_DIDT_IND, + GPU_CONFIGREG_GC_CAC_IND, + GPU_CONFIGREG_CACHE, + GPU_CONFIGREG_MAX +}; + +struct gpu_pt_config_reg { + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; + enum gpu_pt_config_reg_type type; +}; + +struct smu7_performance_level { + uint32_t memory_clock; + uint32_t engine_clock; + uint16_t pcie_gen; + uint16_t pcie_lane; +}; + +struct smu7_thermal_temperature_setting { + long temperature_low; + long temperature_high; + long temperature_shutdown; +}; + +struct smu7_uvd_clocks { + uint32_t vclk; + uint32_t dclk; +}; + +struct smu7_vce_clocks { + uint32_t evclk; + uint32_t ecclk; +}; + +struct smu7_power_state { + uint32_t magic; + struct smu7_uvd_clocks uvd_clks; + struct smu7_vce_clocks vce_clks; + uint32_t sam_clk; + uint16_t performance_level_count; + bool dc_compatible; + uint32_t sclk_threshold; + struct smu7_performance_level performance_levels[SMU7_MAX_HARDWARE_POWERLEVELS]; +}; + +struct smu7_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +#define SMU7_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 8 +#define SMU7_MINIMUM_ENGINE_CLOCK 2500 + +struct smu7_single_dpm_table { + uint32_t count; + struct smu7_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct smu7_dpm_table { + struct smu7_single_dpm_table sclk_table; + struct smu7_single_dpm_table mclk_table; + struct smu7_single_dpm_table pcie_speed_table; + struct smu7_single_dpm_table vddc_table; + struct smu7_single_dpm_table vddci_table; + struct smu7_single_dpm_table mvdd_table; +}; + +struct smu7_clock_registers { + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t vDLL_CNTL; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_SS1; + uint32_t vMPLL_SS2; +}; + +#define DISABLE_MC_LOADMICROCODE 1 +#define DISABLE_MC_CFGPROGRAMMING 2 + +struct smu7_voltage_smio_registers { + uint32_t vS0_VID_LOWER_SMIO_CNTL; +}; + +#define SMU7_MAX_LEAKAGE_COUNT 8 + +struct smu7_leakage_voltage { + uint16_t count; + uint16_t leakage_id[SMU7_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[SMU7_MAX_LEAKAGE_COUNT]; +}; + +struct smu7_vbios_boot_state { + uint16_t mvdd_bootup_value; + uint16_t vddc_bootup_value; + uint16_t vddci_bootup_value; + uint16_t vddgfx_bootup_value; + uint32_t sclk_bootup_value; + uint32_t mclk_bootup_value; + uint16_t pcie_gen_bootup_value; + uint16_t pcie_lane_bootup_value; +}; + +struct smu7_display_timing { + uint32_t min_clock_in_sr; + uint32_t num_existing_displays; + uint32_t vrefresh; +}; + +struct smu7_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t acp_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; + uint32_t pcie_dpm_enable_mask; +}; + +struct smu7_pcie_perf_range { + uint16_t max; + uint16_t min; +}; + +struct smu7_odn_clock_voltage_dependency_table { + uint32_t count; + phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct smu7_odn_dpm_table { + struct phm_odn_clock_levels odn_core_clock_dpm_levels; + struct phm_odn_clock_levels odn_memory_clock_dpm_levels; + struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; + struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; + uint32_t odn_mclk_min_limit; + uint32_t min_vddc; + uint32_t max_vddc; +}; + +struct profile_mode_setting { + uint8_t bupdate_sclk; + uint8_t sclk_up_hyst; + uint8_t sclk_down_hyst; + uint16_t sclk_activity; + uint8_t bupdate_mclk; + uint8_t mclk_up_hyst; + uint8_t mclk_down_hyst; + uint16_t mclk_activity; +}; + +struct smu7_hwmgr { + struct smu7_dpm_table dpm_table; + struct smu7_dpm_table golden_dpm_table; + struct smu7_odn_dpm_table odn_dpm_table; + + uint32_t voting_rights_clients[8]; + uint32_t static_screen_threshold_unit; + uint32_t static_screen_threshold; + uint32_t voltage_control; + uint32_t vdd_gfx_control; + uint32_t vddc_vddgfx_delta; + uint32_t active_auto_throttle_sources; + + struct smu7_clock_registers clock_registers; + + bool is_memory_gddr5; + uint16_t acpi_vddc; + bool pspp_notify_required; + uint16_t force_pcie_gen; + uint16_t acpi_pcie_gen; + uint32_t pcie_gen_cap; + uint32_t pcie_lane_cap; + uint32_t pcie_spc_cap; + struct smu7_leakage_voltage vddc_leakage; + struct smu7_leakage_voltage vddci_leakage; + struct smu7_leakage_voltage vddcgfx_leakage; + + uint32_t mvdd_control; + uint32_t vddc_mask_low; + uint32_t mvdd_mask_low; + uint16_t max_vddc_in_pptable; + uint16_t min_vddc_in_pptable; + uint16_t max_vddci_in_pptable; + uint16_t min_vddci_in_pptable; + bool is_uvd_enabled; + struct smu7_vbios_boot_state vbios_boot_state; + + bool pcie_performance_request; + bool battery_state; + bool is_tlu_enabled; + bool disable_handshake; + bool smc_voltage_control_enabled; + bool vbi_time_out_support; + + uint32_t soft_regs_start; + /* ---- Stuff originally coming from Evergreen ---- */ + uint32_t vddci_control; + struct pp_atomctrl_voltage_table vddc_voltage_table; + struct pp_atomctrl_voltage_table vddci_voltage_table; + struct pp_atomctrl_voltage_table mvdd_voltage_table; + struct pp_atomctrl_voltage_table vddgfx_voltage_table; + + uint32_t mgcg_cgtt_local2; + uint32_t mgcg_cgtt_local3; + uint32_t gpio_debug; + uint32_t mc_micro_code_feature; + uint32_t highest_mclk; + uint16_t acpi_vddci; + uint8_t mvdd_high_index; + uint8_t mvdd_low_index; + bool dll_default_on; + bool performance_request_registered; + + /* ---- Low Power Features ---- */ + bool ulv_supported; + + /* ---- CAC Stuff ---- */ + uint32_t cac_table_start; + bool cac_configuration_required; + bool driver_calculate_cac_leakage; + bool cac_enabled; + + /* ---- DPM2 Parameters ---- */ + uint32_t power_containment_features; + bool enable_dte_feature; + bool enable_tdc_limit_feature; + bool enable_pkg_pwr_tracking_feature; + bool disable_uvd_power_tune_feature; + + + uint32_t dte_tj_offset; + uint32_t fast_watermark_threshold; + + /* ---- Phase Shedding ---- */ + uint8_t vddc_phase_shed_control; + + /* ---- DI/DT ---- */ + struct smu7_display_timing display_timing; + + /* ---- Thermal Temperature Setting ---- */ + struct smu7_thermal_temperature_setting thermal_temp_setting; + struct smu7_dpmlevel_enable_mask dpm_level_enable_mask; + uint32_t need_update_smu7_dpm_table; + uint32_t sclk_dpm_key_disabled; + uint32_t mclk_dpm_key_disabled; + uint32_t pcie_dpm_key_disabled; + uint32_t min_engine_clocks; + struct smu7_pcie_perf_range pcie_gen_performance; + struct smu7_pcie_perf_range pcie_lane_performance; + struct smu7_pcie_perf_range pcie_gen_power_saving; + struct smu7_pcie_perf_range pcie_lane_power_saving; + bool use_pcie_performance_levels; + bool use_pcie_power_saving_levels; + uint32_t mclk_dpm0_activity_target; + uint32_t low_sclk_interrupt_threshold; + uint32_t last_mclk_dpm_enable_mask; + bool uvd_enabled; + + /* ---- Power Gating States ---- */ + bool uvd_power_gated; + bool vce_power_gated; + bool need_long_memory_training; + + /* Application power optimization parameters */ + bool update_up_hyst; + bool update_down_hyst; + uint32_t down_hyst; + uint32_t up_hyst; + uint32_t disable_dpm_mask; + bool apply_optimized_settings; + + uint32_t avfs_vdroop_override_setting; + bool apply_avfs_cks_off_voltage; + uint32_t frame_time_x2; + uint16_t mem_latency_high; + uint16_t mem_latency_low; + uint32_t vr_config; + struct profile_mode_setting current_profile_setting; +}; + +/* To convert to Q8.8 format for firmware */ +#define SMU7_Q88_FORMAT_CONVERSION_UNIT 256 + +enum SMU7_I2CLineID { + SMU7_I2CLineID_DDC1 = 0x90, + SMU7_I2CLineID_DDC2 = 0x91, + SMU7_I2CLineID_DDC3 = 0x92, + SMU7_I2CLineID_DDC4 = 0x93, + SMU7_I2CLineID_DDC5 = 0x94, + SMU7_I2CLineID_DDC6 = 0x95, + SMU7_I2CLineID_SCLSDA = 0x96, + SMU7_I2CLineID_DDCVGA = 0x97 +}; + +#define SMU7_I2C_DDC1DATA 0 +#define SMU7_I2C_DDC1CLK 1 +#define SMU7_I2C_DDC2DATA 2 +#define SMU7_I2C_DDC2CLK 3 +#define SMU7_I2C_DDC3DATA 4 +#define SMU7_I2C_DDC3CLK 5 +#define SMU7_I2C_SDA 40 +#define SMU7_I2C_SCL 41 +#define SMU7_I2C_DDC4DATA 65 +#define SMU7_I2C_DDC4CLK 66 +#define SMU7_I2C_DDC5DATA 0x48 +#define SMU7_I2C_DDC5CLK 0x49 +#define SMU7_I2C_DDC6DATA 0x4a +#define SMU7_I2C_DDC6CLK 0x4b +#define SMU7_I2C_DDCVGADATA 0x4c +#define SMU7_I2C_DDCVGACLK 0x4d + +#define SMU7_UNUSED_GPIO_PIN 0x7F +uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr); +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c new file mode 100644 index 000000000000..5d4971576111 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.c @@ -0,0 +1,1239 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include "hwmgr.h" +#include "smumgr.h" +#include "smu7_hwmgr.h" +#include "smu7_powertune.h" +#include "smu7_common.h" + +#define VOLTAGE_SCALE 4 + +static uint32_t DIDTBlock_Info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; + +static uint32_t Polaris11_DIDTBlock_Info = SQ_PCC_MASK | TCP_IR_MASK | TD_PCC_MASK; + +static const struct gpu_pt_config_reg GCCACConfig_Polaris10[] = { +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060013, GPU_CONFIGREG_GC_CAC_IND }, + + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0013, GPU_CONFIGREG_GC_CAC_IND }, + + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900013, GPU_CONFIGREG_GC_CAC_IND }, + + { 0xFFFFFFFF } +}; + +static const struct gpu_pt_config_reg GCCACConfig_Polaris11[] = { +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060011, GPU_CONFIGREG_GC_CAC_IND }, + + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0011, GPU_CONFIGREG_GC_CAC_IND }, + + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100011, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900011, GPU_CONFIGREG_GC_CAC_IND }, + + { 0xFFFFFFFF } +}; + +static const struct gpu_pt_config_reg DIDTConfig_Polaris10[] = { +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { 0xFFFFFFFF } +}; + +static const struct gpu_pt_config_reg DIDTConfig_Polaris11[] = { +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { 0xFFFFFFFF } +}; + +static const struct gpu_pt_config_reg DIDTConfig_Polaris12[] = { +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { 0xFFFFFFFF } +}; + +static const struct gpu_pt_config_reg DIDTConfig_Polaris11_Kicker[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value Type + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x004c, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00d0, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0069, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x0048, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x005f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x007a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x001f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x002d, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x0088, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + /* DIDT_TD */ + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + /* DIDT_TCP */ + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT,0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct gpu_pt_config_reg GCCACConfig_VegaM[] = +{ +// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Offset Mask Shift Value Type +// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + // DIDT_SQ + // + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060013, GPU_CONFIGREG_GC_CAC_IND }, + + // DIDT_TD + // + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0013, GPU_CONFIGREG_GC_CAC_IND }, + + // DIDT_TCP + // + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100013, GPU_CONFIGREG_GC_CAC_IND }, + { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900013, GPU_CONFIGREG_GC_CAC_IND }, + + { 0xFFFFFFFF } // End of list +}; + +static const struct gpu_pt_config_reg DIDTConfig_VegaM[] = +{ +// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +// Offset Mask Shift Value Type +// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + // DIDT_SQ + // + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + // DIDT_TD + // + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + // DIDT_TCP + // + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT,0x01aa, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, + + { 0xFFFFFFFF } // End of list +}; +static int smu7_enable_didt(struct pp_hwmgr *hwmgr, const bool enable) +{ + uint32_t en = enable ? 1 : 0; + uint32_t block_en = 0; + int32_t result = 0; + uint32_t didt_block; + + if (hwmgr->chip_id == CHIP_POLARIS11) + didt_block = Polaris11_DIDTBlock_Info; + else + didt_block = DIDTBlock_Info; + + block_en = PP_CAP(PHM_PlatformCaps_SQRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_SQ_CTRL0, DIDT_CTRL_EN, block_en); + didt_block &= ~SQ_Enable_MASK; + didt_block |= block_en << SQ_Enable_SHIFT; + + block_en = PP_CAP(PHM_PlatformCaps_DBRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DB_CTRL0, DIDT_CTRL_EN, block_en); + didt_block &= ~DB_Enable_MASK; + didt_block |= block_en << DB_Enable_SHIFT; + + block_en = PP_CAP(PHM_PlatformCaps_TDRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TD_CTRL0, DIDT_CTRL_EN, block_en); + didt_block &= ~TD_Enable_MASK; + didt_block |= block_en << TD_Enable_SHIFT; + + block_en = PP_CAP(PHM_PlatformCaps_TCPRamping) ? en : 0; + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TCP_CTRL0, DIDT_CTRL_EN, block_en); + didt_block &= ~TCP_Enable_MASK; + didt_block |= block_en << TCP_Enable_SHIFT; + + if (enable) + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_Didt_Block_Function, + didt_block, + NULL); + + return result; +} + +static int smu7_program_pt_config_registers(struct pp_hwmgr *hwmgr, + const struct gpu_pt_config_reg *cac_config_regs) +{ + const struct gpu_pt_config_reg *config_regs = cac_config_regs; + uint32_t cache = 0; + uint32_t data = 0; + + PP_ASSERT_WITH_CODE((config_regs != NULL), "Invalid config register table.", return -EINVAL); + + while (config_regs->offset != 0xFFFFFFFF) { + if (config_regs->type == GPU_CONFIGREG_CACHE) + cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); + else { + switch (config_regs->type) { + case GPU_CONFIGREG_SMC_IND: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, config_regs->offset); + break; + + case GPU_CONFIGREG_DIDT_IND: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset); + break; + + case GPU_CONFIGREG_GC_CAC_IND: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset); + break; + + default: + data = cgs_read_register(hwmgr->device, config_regs->offset); + break; + } + + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + data |= cache; + + switch (config_regs->type) { + case GPU_CONFIGREG_SMC_IND: + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, config_regs->offset, data); + break; + + case GPU_CONFIGREG_DIDT_IND: + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset, data); + break; + + case GPU_CONFIGREG_GC_CAC_IND: + cgs_write_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset, data); + break; + + default: + cgs_write_register(hwmgr->device, config_regs->offset, data); + break; + } + cache = 0; + } + + config_regs++; + } + + return 0; +} + +int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result; + uint32_t num_se = 0; + uint32_t count, value, value2; + struct amdgpu_device *adev = hwmgr->adev; + + num_se = adev->gfx.config.max_shader_engines; + + if (PP_CAP(PHM_PlatformCaps_SQRamping) || + PP_CAP(PHM_PlatformCaps_DBRamping) || + PP_CAP(PHM_PlatformCaps_TDRamping) || + PP_CAP(PHM_PlatformCaps_TCPRamping)) { + + amdgpu_gfx_rlc_enter_safe_mode(adev); + mutex_lock(&adev->grbm_idx_mutex); + value = 0; + value2 = cgs_read_register(hwmgr->device, mmGRBM_GFX_INDEX); + for (count = 0; count < num_se; count++) { + value = SYS_GRBM_GFX_INDEX_DATA__INSTANCE_BROADCAST_WRITES_MASK + | SYS_GRBM_GFX_INDEX_DATA__SH_BROADCAST_WRITES_MASK + | (count << SYS_GRBM_GFX_INDEX_DATA__SE_INDEX__SHIFT); + cgs_write_register(hwmgr->device, mmGRBM_GFX_INDEX, value); + + if (hwmgr->chip_id == CHIP_POLARIS10) { + result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris10); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + } else if (hwmgr->chip_id == CHIP_POLARIS11) { + result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + if (hwmgr->is_kicker) + result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11_Kicker); + else + result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + } else if (hwmgr->chip_id == CHIP_POLARIS12) { + result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris12); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + } else if (hwmgr->chip_id == CHIP_VEGAM) { + result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_VegaM); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_VegaM); + PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); + } + } + cgs_write_register(hwmgr->device, mmGRBM_GFX_INDEX, value2); + + result = smu7_enable_didt(hwmgr, true); + PP_ASSERT_WITH_CODE((result == 0), "EnableDiDt failed.", goto error); + + if (hwmgr->chip_id == CHIP_POLARIS11) { + result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_EnableDpmDidt), + NULL); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to enable DPM DIDT.", goto error); + } + mutex_unlock(&adev->grbm_idx_mutex); + amdgpu_gfx_rlc_exit_safe_mode(adev); + } + + return 0; +error: + mutex_unlock(&adev->grbm_idx_mutex); + amdgpu_gfx_rlc_exit_safe_mode(adev); + return result; +} + +int smu7_disable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result; + struct amdgpu_device *adev = hwmgr->adev; + + if (PP_CAP(PHM_PlatformCaps_SQRamping) || + PP_CAP(PHM_PlatformCaps_DBRamping) || + PP_CAP(PHM_PlatformCaps_TDRamping) || + PP_CAP(PHM_PlatformCaps_TCPRamping)) { + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + result = smu7_enable_didt(hwmgr, false); + PP_ASSERT_WITH_CODE((result == 0), + "Post DIDT enable clock gating failed.", + goto error); + if (hwmgr->chip_id == CHIP_POLARIS11) { + result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_DisableDpmDidt), + NULL); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to disable DPM DIDT.", goto error); + } + amdgpu_gfx_rlc_exit_safe_mode(adev); + } + + return 0; +error: + amdgpu_gfx_rlc_exit_safe_mode(adev); + return result; +} + +int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + + if (PP_CAP(PHM_PlatformCaps_CAC)) { + int smc_result; + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_EnableCac), + NULL); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable CAC in SMC.", result = -1); + + data->cac_enabled = (0 == smc_result) ? true : false; + } + return result; +} + +int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + + if (PP_CAP(PHM_PlatformCaps_CAC) && data->cac_enabled) { + int smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_DisableCac), + NULL); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable CAC in SMC.", result = -1); + + data->cac_enabled = false; + } + return result; +} + +int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_PkgPwrLimit) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PkgPwrSetLimit, + n<<8, + NULL); + return 0; +} + +static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *hwmgr, + uint32_t target_tdp) +{ + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_OverDriveSetTargetTdp, + target_tdp, + NULL); +} + +int smu7_enable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int smc_result; + int result = 0; + struct phm_cac_tdp_table *cac_table; + + data->power_containment_features = 0; + if (hwmgr->pp_table_version == PP_TABLE_V1) + cac_table = table_info->cac_dtp_table; + else + cac_table = hwmgr->dyn_state.cac_dtp_table; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + if (data->enable_tdc_limit_feature) { + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_TDCLimitEnable), + NULL); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable TDCLimit in SMC.", result = -1;); + if (0 == smc_result) + data->power_containment_features |= + POWERCONTAINMENT_FEATURE_TDCLimit; + } + + if (data->enable_pkg_pwr_tracking_feature) { + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable), + NULL); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable PkgPwrTracking in SMC.", result = -1;); + if (0 == smc_result) { + hwmgr->default_power_limit = hwmgr->power_limit = + cac_table->usMaximumPowerDeliveryLimit; + data->power_containment_features |= + POWERCONTAINMENT_FEATURE_PkgPwrLimit; + + if (smu7_set_power_limit(hwmgr, hwmgr->power_limit)) + pr_err("Failed to set Default Power Limit in SMC!"); + } + } + } + return result; +} + +int smu7_disable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment) && + data->power_containment_features) { + int smc_result; + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_TDCLimit) { + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_TDCLimitDisable), + NULL); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable TDCLimit in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_DTE) { + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_DisableDTE), + NULL); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable DTE in SMC.", + result = smc_result); + } + + if (data->power_containment_features & + POWERCONTAINMENT_FEATURE_PkgPwrLimit) { + smc_result = smum_send_msg_to_smc(hwmgr, + (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable), + NULL); + PP_ASSERT_WITH_CODE((smc_result == 0), + "Failed to disable PkgPwrTracking in SMC.", + result = smc_result); + } + data->power_containment_features = 0; + } + + return result; +} + +int smu7_power_control_set_level(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_table; + + int adjust_percent, target_tdp; + int result = 0; + + if (hwmgr->pp_table_version == PP_TABLE_V1) + cac_table = table_info->cac_dtp_table; + else + cac_table = hwmgr->dyn_state.cac_dtp_table; + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + /* adjustment percentage has already been validated */ + adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? + hwmgr->platform_descriptor.TDPAdjustment : + (-1 * hwmgr->platform_descriptor.TDPAdjustment); + + if (hwmgr->chip_id > CHIP_TONGA) + target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; + else + target_tdp = ((100 + adjust_percent) * (int)(cac_table->usConfigurableTDP * 256)) / 100; + + result = smu7_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); + } + + return result; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h new file mode 100644 index 000000000000..22f86b6bf1be --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_powertune.h @@ -0,0 +1,62 @@ +/* + * Copyright 2015 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 _SMU7_POWERTUNE_H +#define _SMU7_POWERTUNE_H + +#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xfffc0000 +#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x12 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e +#define DIDT_TD_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e +#define DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 +#define DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e + +/* PowerContainment Features */ +#define POWERCONTAINMENT_FEATURE_DTE 0x00000001 +#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 +#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 + +#define ixGC_CAC_CNTL 0x0000 +#define ixDIDT_SQ_STALL_CTRL 0x0004 +#define ixDIDT_SQ_TUNING_CTRL 0x0005 +#define ixDIDT_TD_STALL_CTRL 0x0044 +#define ixDIDT_TD_TUNING_CTRL 0x0045 +#define ixDIDT_TCP_STALL_CTRL 0x0064 +#define ixDIDT_TCP_TUNING_CTRL 0x0065 + + +int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr); +int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr); +int smu7_enable_power_containment(struct pp_hwmgr *hwmgr); +int smu7_disable_power_containment(struct pp_hwmgr *hwmgr); +int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); +int smu7_power_control_set_level(struct pp_hwmgr *hwmgr); +int smu7_enable_didt_config(struct pp_hwmgr *hwmgr); +int smu7_disable_didt_config(struct pp_hwmgr *hwmgr); +#endif /* DGPU_POWERTUNE_H */ + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c new file mode 100644 index 000000000000..0b30f73649a8 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.c @@ -0,0 +1,471 @@ +/* + * Copyright 2016 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 +#include "smu7_thermal.h" +#include "smu7_hwmgr.h" +#include "smu7_common.h" + +int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info) +{ + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -ENODEV; + + fan_speed_info->supports_percent_read = true; + fan_speed_info->supports_percent_write = true; + fan_speed_info->min_percent = 0; + fan_speed_info->max_percent = 100; + + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; + fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM; + } else { + fan_speed_info->min_rpm = 0; + fan_speed_info->max_rpm = 0; + } + + return 0; +} + +int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -ENODEV; + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_STATUS, FDO_PWM_DUTY); + + if (duty100 == 0) + return -EINVAL; + + + tmp64 = (uint64_t)duty * 100; + do_div(tmp64, duty100); + *speed = (uint32_t)tmp64; + + if (*speed > 100) + *speed = 100; + + return 0; +} + +int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + uint32_t tach_period; + uint32_t crystal_clock_freq; + + if (hwmgr->thermal_controller.fanInfo.bNoFan || + !hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) + return -ENODEV; + + tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_STATUS, TACH_PERIOD); + + if (tach_period == 0) + return -EINVAL; + + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + *speed = 60 * crystal_clock_freq * 10000 / tach_period; + + return 0; +} + +/** +* Set Fan Speed Control to static mode, so that the user can decide what speed to use. +* @param hwmgr the address of the powerplay hardware manager. +* mode the fan control mode, 0 default, 1 by percent, 5, by RPM +* @exception Should always succeed. +*/ +int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + if (hwmgr->fan_ctrl_is_in_default_mode) { + hwmgr->fan_ctrl_default_mode = + PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE); + hwmgr->tmin = + PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN); + hwmgr->fan_ctrl_is_in_default_mode = false; + } + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN, 0); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE, mode); + + return 0; +} + +/** +* Reset Fan Speed Control to default mode. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Should always succeed. +*/ +int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->fan_ctrl_is_in_default_mode) { + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN, hwmgr->tmin); + hwmgr->fan_ctrl_is_in_default_mode = true; + } + + return 0; +} + +int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + int result; + + if (PP_CAP(PHM_PlatformCaps_ODFuzzyFanControlSupport)) { + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl, + FAN_CONTROL_FUZZY, NULL); + + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM)) + hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr, + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM); + else + hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr, + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanPWM); + + } else { + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl, + FAN_CONTROL_TABLE, NULL); + } + + if (!result && hwmgr->thermal_controller. + advanceFanControlParameters.ucTargetTemperature) + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanTemperatureTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ucTargetTemperature, + NULL); + hwmgr->fan_ctrl_enabled = true; + + return result; +} + + +int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + hwmgr->fan_ctrl_enabled = false; + return smum_send_msg_to_smc(hwmgr, PPSMC_StopFanControl, NULL); +} + +/** +* Set Fan Speed in percent. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (0% - 100%) to be set. +* @exception Fails is the 100% setting appears to be 0. +*/ +int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (speed > 100) + speed = 100; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + smu7_fan_ctrl_stop_smc_fan_control(hwmgr); + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (uint64_t)speed * duty100; + do_div(tmp64, 100); + duty = (uint32_t)tmp64; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); + + return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +/** +* Reset Fan Speed to default. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Always succeeds. +*/ +int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) +{ + int result; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { + result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + if (!result) + result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); + } else + result = smu7_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set Fan Speed in RPM. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (min - max) to be set. +* @exception Fails is the speed not lie between min and max. +*/ +int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + uint32_t tach_period; + uint32_t crystal_clock_freq; + + if (hwmgr->thermal_controller.fanInfo.bNoFan || + (hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution == 0) || + speed == 0 || + (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || + (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) + return 0; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + smu7_fan_ctrl_stop_smc_fan_control(hwmgr); + + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_CTRL, TARGET_PERIOD, tach_period); + + return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + int temp; + + temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_STATUS, CTF_TEMP); + + /* Bit 9 means the reading is lower than the lowest usable value. */ + if (temp & 0x200) + temp = SMU7_THERMAL_MAXIMUM_TEMP_READING; + else + temp = temp & 0x1ff; + + temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + int low_temp, int high_temp) +{ + int low = SMU7_THERMAL_MINIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + if (low < low_temp) + low = low_temp; + if (high > high_temp) + high = high_temp; + + if (low > high) + return -EINVAL; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, DIG_THERM_INTH, + (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, DIG_THERM_INTL, + (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_CTRL, DIG_THERM_DPM, + (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + + return 0; +} + +/** +* Programs thermal controller one-time setting registers +* +* @param hwmgr The address of the hardware manager. +*/ +static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_CTRL, EDGE_PER_REV, + hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution - 1); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK); + alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to enable internal thermal interrupts */ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Enable, NULL); +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK); + alert |= (SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to disable internal thermal interrupts */ + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Disable, NULL); +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = smu7_thermal_disable_alert(hwmgr); + + if (!hwmgr->thermal_controller.fanInfo.bNoFan) + smu7_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Start the fan control on the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ +/* If the fantable setup has failed we could have disabled + * PHM_PlatformCaps_MicrocodeFanControl even after + * this function was included in the table. + * Make sure that we still think controlling the fan is OK. +*/ + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { + smu7_fan_ctrl_start_smc_fan_control(hwmgr); + smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + } + + return 0; +} + +int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + int ret = 0; + + if (range == NULL) + return -EINVAL; + + smu7_thermal_initialize(hwmgr); + ret = smu7_thermal_set_temperature_range(hwmgr, range->min, range->max); + if (ret) + return -EINVAL; + smu7_thermal_enable_alert(hwmgr); + ret = smum_thermal_avfs_enable(hwmgr); + if (ret) + return -EINVAL; + +/* We should restrict performance levels to low before we halt the SMC. + * On the other hand we are still in boot state when we do this + * so it would be pointless. + * If this assumption changes we have to revisit this table. + */ + smum_thermal_setup_fan_table(hwmgr); + smu7_thermal_start_smc_fan_control(hwmgr); + return 0; +} + + + +int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->thermal_controller.fanInfo.bNoFan) + smu7_fan_ctrl_set_default_mode(hwmgr); + return 0; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h new file mode 100644 index 000000000000..42c1ba0fad78 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_thermal.h @@ -0,0 +1,58 @@ +/* + * Copyright 2016 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 _SMU7_THERMAL_H_ +#define _SMU7_THERMAL_H_ + +#include "hwmgr.h" + +#define SMU7_THERMAL_HIGH_ALERT_MASK 0x1 +#define SMU7_THERMAL_LOW_ALERT_MASK 0x2 + +#define SMU7_THERMAL_MINIMUM_TEMP_READING -256 +#define SMU7_THERMAL_MAXIMUM_TEMP_READING 255 + +#define SMU7_THERMAL_MINIMUM_ALERT_TEMP 0 +#define SMU7_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +extern int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); +extern int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); +extern int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode); +extern int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); +extern int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr); +extern int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr); +extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *temperature_range); +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c new file mode 100644 index 000000000000..35ed47ebaf09 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.c @@ -0,0 +1,2049 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include "atom-types.h" +#include "atombios.h" +#include "processpptables.h" +#include "cgs_common.h" +#include "smu/smu_8_0_d.h" +#include "smu8_fusion.h" +#include "smu/smu_8_0_sh_mask.h" +#include "smumgr.h" +#include "hwmgr.h" +#include "hardwaremanager.h" +#include "cz_ppsmc.h" +#include "smu8_hwmgr.h" +#include "power_state.h" +#include "pp_thermal.h" + +#define ixSMUSVI_NB_CURRENTVID 0xD8230044 +#define CURRENT_NB_VID_MASK 0xff000000 +#define CURRENT_NB_VID__SHIFT 24 +#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 +#define CURRENT_GFX_VID_MASK 0xff000000 +#define CURRENT_GFX_VID__SHIFT 24 + +static const unsigned long smu8_magic = (unsigned long) PHM_Cz_Magic; + +static struct smu8_power_state *cast_smu8_power_state(struct pp_hw_power_state *hw_ps) +{ + if (smu8_magic != hw_ps->magic) + return NULL; + + return (struct smu8_power_state *)hw_ps; +} + +static const struct smu8_power_state *cast_const_smu8_power_state( + const struct pp_hw_power_state *hw_ps) +{ + if (smu8_magic != hw_ps->magic) + return NULL; + + return (struct smu8_power_state *)hw_ps; +} + +static uint32_t smu8_get_eclk_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_vce_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + switch (msg) { + case PPSMC_MSG_SetEclkSoftMin: + case PPSMC_MSG_SetEclkHardMin: + for (i = 0; i < (int)ptable->count; i++) { + if (clock <= ptable->entries[i].ecclk) + break; + } + break; + + case PPSMC_MSG_SetEclkSoftMax: + case PPSMC_MSG_SetEclkHardMax: + for (i = ptable->count - 1; i >= 0; i--) { + if (clock >= ptable->entries[i].ecclk) + break; + } + break; + + default: + break; + } + + return i; +} + +static uint32_t smu8_get_sclk_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + switch (msg) { + case PPSMC_MSG_SetSclkSoftMin: + case PPSMC_MSG_SetSclkHardMin: + for (i = 0; i < (int)table->count; i++) { + if (clock <= table->entries[i].clk) + break; + } + break; + + case PPSMC_MSG_SetSclkSoftMax: + case PPSMC_MSG_SetSclkHardMax: + for (i = table->count - 1; i >= 0; i--) { + if (clock >= table->entries[i].clk) + break; + } + break; + + default: + break; + } + return i; +} + +static uint32_t smu8_get_uvd_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_uvd_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + switch (msg) { + case PPSMC_MSG_SetUvdSoftMin: + case PPSMC_MSG_SetUvdHardMin: + for (i = 0; i < (int)ptable->count; i++) { + if (clock <= ptable->entries[i].vclk) + break; + } + break; + + case PPSMC_MSG_SetUvdSoftMax: + case PPSMC_MSG_SetUvdHardMax: + for (i = ptable->count - 1; i >= 0; i--) { + if (clock >= ptable->entries[i].vclk) + break; + } + break; + + default: + break; + } + + return i; +} + +static uint32_t smu8_get_max_sclk_level(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + if (data->max_sclk_level == 0) { + smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetMaxSclkLevel, + &data->max_sclk_level); + data->max_sclk_level += 1; + } + + return data->max_sclk_level; +} + +static int smu8_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct amdgpu_device *adev = hwmgr->adev; + + data->gfx_ramp_step = 256*25/100; + data->gfx_ramp_delay = 1; /* by default, we delay 1us */ + + data->mgcg_cgtt_local0 = 0x00000000; + data->mgcg_cgtt_local1 = 0x00000000; + data->clock_slow_down_freq = 25000; + data->skip_clock_slow_down = 1; + data->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */ + data->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */ + data->voting_rights_clients = 0x00C00033; + data->static_screen_threshold = 8; + data->ddi_power_gating_disabled = 0; + data->bapm_enabled = 1; + data->voltage_drop_threshold = 0; + data->gfx_power_gating_threshold = 500; + data->vce_slow_sclk_threshold = 20000; + data->dce_slow_sclk_threshold = 30000; + data->disable_driver_thermal_policy = 1; + data->disable_nb_ps3_in_battery = 0; + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ABM); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_NonABMSupportInPPLib); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicM3Arbiter); + + data->override_dynamic_mgpg = 1; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + data->thermal_auto_throttling_treshold = 0; + data->tdr_clock = 0; + data->disable_gfx_power_gating_in_uvd = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEDPM); + + data->cc6_settings.cpu_cc6_disable = false; + data->cc6_settings.cpu_pstate_disable = false; + data->cc6_settings.nb_pstate_switch_disable = false; + data->cc6_settings.cpu_pstate_separation_time = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableVoltageIsland); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + + if (adev->pg_flags & AMD_PG_SUPPORT_UVD) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + if (adev->pg_flags & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + + + return 0; +} + +/* convert form 8bit vid to real voltage in mV*4 */ +static uint32_t smu8_convert_8Bit_index_to_voltage( + struct pp_hwmgr *hwmgr, uint16_t voltage) +{ + return 6200 - (voltage * 25); +} + +static int smu8_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *table) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct smu8_sys_info *sys_info = &data->sys_info; + struct phm_clock_voltage_dependency_table *dep_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + if (dep_table->count > 0) { + table->sclk = dep_table->entries[dep_table->count-1].clk; + table->vddc = smu8_convert_8Bit_index_to_voltage(hwmgr, + (uint16_t)dep_table->entries[dep_table->count-1].v); + } + table->mclk = sys_info->nbp_memory_clock[0]; + return 0; +} + +static int smu8_init_dynamic_state_adjustment_rule_settings( + struct pp_hwmgr *hwmgr, + ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table) +{ + struct phm_clock_voltage_dependency_table *table_clk_vlt; + + table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), + GFP_KERNEL); + + if (NULL == table_clk_vlt) { + pr_err("Can not allocate memory!\n"); + return -ENOMEM; + } + + table_clk_vlt->count = 8; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; + table_clk_vlt->entries[1].v = 1; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; + table_clk_vlt->entries[2].v = 2; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; + table_clk_vlt->entries[3].v = 3; + table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; + table_clk_vlt->entries[4].v = 4; + table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; + table_clk_vlt->entries[5].v = 5; + table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; + table_clk_vlt->entries[6].v = 6; + table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; + table_clk_vlt->entries[7].v = 7; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + + return 0; +} + +static int smu8_get_system_info_data(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL; + uint32_t i; + int result = 0; + uint8_t frev, crev; + uint16_t size; + + info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *)smu_atom_get_data_table(hwmgr->adev, + GetIndexIntoMasterTable(DATA, IntegratedSystemInfo), + &size, &frev, &crev); + + if (info == NULL) { + pr_err("Could not retrieve the Integrated System Info Table!\n"); + return -EINVAL; + } + + if (crev != 9) { + pr_err("Unsupported IGP table: %d %d\n", frev, crev); + return -EINVAL; + } + + data->sys_info.bootup_uma_clock = + le32_to_cpu(info->ulBootUpUMAClock); + + data->sys_info.bootup_engine_clock = + le32_to_cpu(info->ulBootUpEngineClock); + + data->sys_info.dentist_vco_freq = + le32_to_cpu(info->ulDentistVCOFreq); + + data->sys_info.system_config = + le32_to_cpu(info->ulSystemConfig); + + data->sys_info.bootup_nb_voltage_index = + le16_to_cpu(info->usBootUpNBVoltage); + + data->sys_info.htc_hyst_lmt = + (info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt; + + data->sys_info.htc_tmp_lmt = + (info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt; + + if (data->sys_info.htc_tmp_lmt <= + data->sys_info.htc_hyst_lmt) { + pr_err("The htcTmpLmt should be larger than htcHystLmt.\n"); + return -EINVAL; + } + + data->sys_info.nb_dpm_enable = + data->enable_nb_ps_policy && + (le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1); + + for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { + if (i < SMU8_NUM_NBPMEMORYCLOCK) { + data->sys_info.nbp_memory_clock[i] = + le32_to_cpu(info->ulNbpStateMemclkFreq[i]); + } + data->sys_info.nbp_n_clock[i] = + le32_to_cpu(info->ulNbpStateNClkFreq[i]); + } + + for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) { + data->sys_info.display_clock[i] = + le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK); + } + + /* Here use 4 levels, make sure not exceed */ + for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { + data->sys_info.nbp_voltage_index[i] = + le16_to_cpu(info->usNBPStateVoltage[i]); + } + + if (!data->sys_info.nb_dpm_enable) { + for (i = 1; i < SMU8_NUM_NBPSTATES; i++) { + if (i < SMU8_NUM_NBPMEMORYCLOCK) { + data->sys_info.nbp_memory_clock[i] = + data->sys_info.nbp_memory_clock[0]; + } + data->sys_info.nbp_n_clock[i] = + data->sys_info.nbp_n_clock[0]; + data->sys_info.nbp_voltage_index[i] = + data->sys_info.nbp_voltage_index[0]; + } + } + + if (le32_to_cpu(info->ulGPUCapInfo) & + SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableDFSBypass); + } + + data->sys_info.uma_channel_number = info->ucUMAChannelNumber; + + smu8_construct_max_power_limits_table (hwmgr, + &hwmgr->dyn_state.max_clock_voltage_on_ac); + + smu8_init_dynamic_state_adjustment_rule_settings(hwmgr, + &info->sDISPCLK_Voltage[0]); + + return result; +} + +static int smu8_construct_boot_state(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->boot_power_level.engineClock = + data->sys_info.bootup_engine_clock; + + data->boot_power_level.vddcIndex = + (uint8_t)data->sys_info.bootup_nb_voltage_index; + + data->boot_power_level.dsDividerIndex = 0; + data->boot_power_level.ssDividerIndex = 0; + data->boot_power_level.allowGnbSlow = 1; + data->boot_power_level.forceNBPstate = 0; + data->boot_power_level.hysteresis_up = 0; + data->boot_power_level.numSIMDToPowerDown = 0; + data->boot_power_level.display_wm = 0; + data->boot_power_level.vce_wm = 0; + + return 0; +} + +static int smu8_upload_pptable_to_smu(struct pp_hwmgr *hwmgr) +{ + struct SMU8_Fusion_ClkTable *clock_table; + int ret; + uint32_t i; + void *table = NULL; + pp_atomctrl_clock_dividers_kong dividers; + + struct phm_clock_voltage_dependency_table *vddc_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *vdd_gfx_table = + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk; + struct phm_acp_clock_voltage_dependency_table *acp_table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + if (!hwmgr->need_pp_table_upload) + return 0; + + ret = smum_download_powerplay_table(hwmgr, &table); + + PP_ASSERT_WITH_CODE((0 == ret && NULL != table), + "Fail to get clock table from SMU!", return -EINVAL;); + + clock_table = (struct SMU8_Fusion_ClkTable *)table; + + /* patch clock table */ + PP_ASSERT_WITH_CODE((vddc_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((acp_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((uvd_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((vce_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + + for (i = 0; i < SMU8_MAX_HARDWARE_POWERLEVELS; i++) { + + /* vddc_sclk */ + clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid = + (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0; + clock_table->SclkBreakdownTable.ClkLevel[i].Frequency = + (i < vddc_table->count) ? vddc_table->entries[i].clk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + /* vddgfx_sclk */ + clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid = + (i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0; + + /* acp breakdown */ + clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid = + (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0; + clock_table->AclkBreakdownTable.ClkLevel[i].Frequency = + (i < acp_table->count) ? acp_table->entries[i].acpclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->AclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + + /* uvd breakdown */ + clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid = + (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; + clock_table->VclkBreakdownTable.ClkLevel[i].Frequency = + (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->VclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid = + (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; + clock_table->DclkBreakdownTable.ClkLevel[i].Frequency = + (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->DclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + /* vce breakdown */ + clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid = + (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0; + clock_table->EclkBreakdownTable.ClkLevel[i].Frequency = + (i < vce_table->count) ? vce_table->entries[i].ecclk : 0; + + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->EclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + } + ret = smum_upload_powerplay_table(hwmgr); + + return ret; +} + +static int smu8_init_sclk_limit(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + unsigned long clock = 0, level; + + if (NULL == table || table->count <= 0) + return -EINVAL; + + data->sclk_dpm.soft_min_clk = table->entries[0].clk; + data->sclk_dpm.hard_min_clk = table->entries[0].clk; + + level = smu8_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + clock = table->entries[level].clk; + else + clock = table->entries[table->count - 1].clk; + + data->sclk_dpm.soft_max_clk = clock; + data->sclk_dpm.hard_max_clk = clock; + + return 0; +} + +static int smu8_init_uvd_limit(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_uvd_clock_voltage_dependency_table *table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + unsigned long clock = 0; + uint32_t level; + + if (NULL == table || table->count <= 0) + return -EINVAL; + + data->uvd_dpm.soft_min_clk = 0; + data->uvd_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxUvdLevel, &level); + + if (level < table->count) + clock = table->entries[level].vclk; + else + clock = table->entries[table->count - 1].vclk; + + data->uvd_dpm.soft_max_clk = clock; + data->uvd_dpm.hard_max_clk = clock; + + return 0; +} + +static int smu8_init_vce_limit(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_vce_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + unsigned long clock = 0; + uint32_t level; + + if (NULL == table || table->count <= 0) + return -EINVAL; + + data->vce_dpm.soft_min_clk = 0; + data->vce_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxEclkLevel, &level); + + if (level < table->count) + clock = table->entries[level].ecclk; + else + clock = table->entries[table->count - 1].ecclk; + + data->vce_dpm.soft_max_clk = clock; + data->vce_dpm.hard_max_clk = clock; + + return 0; +} + +static int smu8_init_acp_limit(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_acp_clock_voltage_dependency_table *table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + unsigned long clock = 0; + uint32_t level; + + if (NULL == table || table->count <= 0) + return -EINVAL; + + data->acp_dpm.soft_min_clk = 0; + data->acp_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxAclkLevel, &level); + + if (level < table->count) + clock = table->entries[level].acpclk; + else + clock = table->entries[table->count - 1].acpclk; + + data->acp_dpm.soft_max_clk = clock; + data->acp_dpm.hard_max_clk = clock; + return 0; +} + +static void smu8_init_power_gate_state(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->uvd_power_gated = false; + data->vce_power_gated = false; + data->samu_power_gated = false; +#ifdef CONFIG_DRM_AMD_ACP + data->acp_power_gated = false; +#else + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF, NULL); + data->acp_power_gated = true; +#endif + +} + +static void smu8_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->low_sclk_interrupt_threshold = 0; +} + +static int smu8_update_sclk_limit(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + unsigned long clock = 0; + unsigned long level; + unsigned long stable_pstate_sclk; + unsigned long percentage; + + data->sclk_dpm.soft_min_clk = table->entries[0].clk; + level = smu8_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + data->sclk_dpm.soft_max_clk = table->entries[level].clk; + else + data->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk; + + clock = hwmgr->display_config->min_core_set_clock; + if (clock == 0) + pr_debug("min_core_set_clock not set\n"); + + if (data->sclk_dpm.hard_min_clk != clock) { + data->sclk_dpm.hard_min_clk = clock; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkHardMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.hard_min_clk, + PPSMC_MSG_SetSclkHardMin), + NULL); + } + + clock = data->sclk_dpm.soft_min_clk; + + /* update minimum clocks for Stable P-State feature */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + percentage = 75; + /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */ + stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk * + percentage) / 100; + + if (clock < stable_pstate_sclk) + clock = stable_pstate_sclk; + } + + if (data->sclk_dpm.soft_min_clk != clock) { + data->sclk_dpm.soft_min_clk = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin), + NULL); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState) && + data->sclk_dpm.soft_max_clk != clock) { + data->sclk_dpm.soft_max_clk = clock; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax), + NULL); + } + + return 0; +} + +static int smu8_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + uint32_t clks = hwmgr->display_config->min_core_set_clock_in_sr; + if (clks == 0) + clks = SMU8_MIN_DEEP_SLEEP_SCLK; + + PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepSclk, + clks, + NULL); + } + + return 0; +} + +static int smu8_set_watermark_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = + hwmgr->backend; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetWatermarkFrequency, + data->sclk_dpm.soft_max_clk, + NULL); + + return 0; +} + +static int smu8_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + + if (hw_data->is_nb_dpm_enabled) { + if (enable) { + PP_DBG_LOG("enable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableLowMemoryPstate, + (lock ? 1 : 0), + NULL); + } else { + PP_DBG_LOG("disable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableLowMemoryPstate, + (lock ? 1 : 0), + NULL); + } + } + + return 0; +} + +static int smu8_disable_nb_dpm(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + struct smu8_hwmgr *data = hwmgr->backend; + unsigned long dpm_features = 0; + + if (data->is_nb_dpm_enabled) { + smu8_nbdpm_pstate_enable_disable(hwmgr, true, true); + dpm_features |= NB_DPM_MASK; + ret = smum_send_msg_to_smc_with_parameter( + hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + dpm_features, + NULL); + if (ret == 0) + data->is_nb_dpm_enabled = false; + } + + return ret; +} + +static int smu8_enable_nb_dpm(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + struct smu8_hwmgr *data = hwmgr->backend; + unsigned long dpm_features = 0; + + if (!data->is_nb_dpm_enabled) { + PP_DBG_LOG("enabling ALL SMU features.\n"); + dpm_features |= NB_DPM_MASK; + ret = smum_send_msg_to_smc_with_parameter( + hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features, + NULL); + if (ret == 0) + data->is_nb_dpm_enabled = true; + } + + return ret; +} + +static int smu8_update_low_mem_pstate(struct pp_hwmgr *hwmgr, const void *input) +{ + bool disable_switch; + bool enable_low_mem_state; + struct smu8_hwmgr *hw_data = hwmgr->backend; + const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input; + const struct smu8_power_state *pnew_state = cast_const_smu8_power_state(states->pnew_state); + + if (hw_data->sys_info.nb_dpm_enable) { + disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false; + enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true; + + if (pnew_state->action == FORCE_HIGH) + smu8_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch); + else if (pnew_state->action == CANCEL_FORCE_HIGH) + smu8_nbdpm_pstate_enable_disable(hwmgr, true, disable_switch); + else + smu8_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch); + } + return 0; +} + +static int smu8_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + int ret = 0; + + smu8_update_sclk_limit(hwmgr); + smu8_set_deep_sleep_sclk_threshold(hwmgr); + smu8_set_watermark_threshold(hwmgr); + ret = smu8_enable_nb_dpm(hwmgr); + if (ret) + return ret; + smu8_update_low_mem_pstate(hwmgr, input); + + return 0; +} + + +static int smu8_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + int ret; + + ret = smu8_upload_pptable_to_smu(hwmgr); + if (ret) + return ret; + ret = smu8_init_sclk_limit(hwmgr); + if (ret) + return ret; + ret = smu8_init_uvd_limit(hwmgr); + if (ret) + return ret; + ret = smu8_init_vce_limit(hwmgr); + if (ret) + return ret; + ret = smu8_init_acp_limit(hwmgr); + if (ret) + return ret; + + smu8_init_power_gate_state(hwmgr); + smu8_init_sclk_threshold(hwmgr); + + return 0; +} + +static void smu8_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + + hw_data->disp_clk_bypass_pending = false; + hw_data->disp_clk_bypass = false; +} + +static void smu8_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + + hw_data->is_nb_dpm_enabled = false; +} + +static void smu8_reset_cc6_data(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + + hw_data->cc6_settings.cc6_setting_changed = false; + hw_data->cc6_settings.cpu_pstate_separation_time = 0; + hw_data->cc6_settings.cpu_cc6_disable = false; + hw_data->cc6_settings.cpu_pstate_disable = false; +} + +static void smu8_program_voting_clients(struct pp_hwmgr *hwmgr) +{ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, + SMU8_VOTINGRIGHTSCLIENTS_DFLT0); +} + +static void smu8_clear_voting_clients(struct pp_hwmgr *hwmgr) +{ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, 0); +} + +static int smu8_start_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->dpm_flags |= DPMFlags_SCLK_Enabled; + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + SCLK_DPM_MASK, + NULL); +} + +static int smu8_stop_dpm(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + struct smu8_hwmgr *data = hwmgr->backend; + unsigned long dpm_features = 0; + + if (data->dpm_flags & DPMFlags_SCLK_Enabled) { + dpm_features |= SCLK_DPM_MASK; + data->dpm_flags &= ~DPMFlags_SCLK_Enabled; + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + dpm_features, + NULL); + } + return ret; +} + +static int smu8_program_bootup_state(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->sclk_dpm.soft_min_clk = data->sys_info.bootup_engine_clock; + data->sclk_dpm.soft_max_clk = data->sys_info.bootup_engine_clock; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax), + NULL); + + return 0; +} + +static void smu8_reset_acp_boot_level(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->acp_boot_level = 0xff; +} + +static int smu8_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + smu8_program_voting_clients(hwmgr); + if (smu8_start_dpm(hwmgr)) + return -EINVAL; + smu8_program_bootup_state(hwmgr); + smu8_reset_acp_boot_level(hwmgr); + + return 0; +} + +static int smu8_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + smu8_disable_nb_dpm(hwmgr); + + smu8_clear_voting_clients(hwmgr); + if (smu8_stop_dpm(hwmgr)) + return -EINVAL; + + return 0; +} + +static int smu8_power_off_asic(struct pp_hwmgr *hwmgr) +{ + smu8_disable_dpm_tasks(hwmgr); + smu8_power_up_display_clock_sys_pll(hwmgr); + smu8_clear_nb_dpm_flag(hwmgr); + smu8_reset_cc6_data(hwmgr); + return 0; +} + +static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps) +{ + struct smu8_power_state *smu8_ps = + cast_smu8_power_state(&prequest_ps->hardware); + + const struct smu8_power_state *smu8_current_ps = + cast_const_smu8_power_state(&pcurrent_ps->hardware); + + struct smu8_hwmgr *data = hwmgr->backend; + struct PP_Clocks clocks = {0, 0, 0, 0}; + bool force_high; + + smu8_ps->need_dfs_bypass = true; + + data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); + + clocks.memoryClock = hwmgr->display_config->min_mem_set_clock != 0 ? + hwmgr->display_config->min_mem_set_clock : + data->sys_info.nbp_memory_clock[1]; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk; + + force_high = (clocks.memoryClock > data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]) + || (hwmgr->display_config->num_display >= 3); + + smu8_ps->action = smu8_current_ps->action; + + if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + smu8_nbdpm_pstate_enable_disable(hwmgr, false, false); + else if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) + smu8_nbdpm_pstate_enable_disable(hwmgr, false, true); + else if (!force_high && (smu8_ps->action == FORCE_HIGH)) + smu8_ps->action = CANCEL_FORCE_HIGH; + else if (force_high && (smu8_ps->action != FORCE_HIGH)) + smu8_ps->action = FORCE_HIGH; + else + smu8_ps->action = DO_NOTHING; + + return 0; +} + +static int smu8_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct smu8_hwmgr *data; + + data = kzalloc(sizeof(struct smu8_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + + result = smu8_initialize_dpm_defaults(hwmgr); + if (result != 0) { + pr_err("smu8_initialize_dpm_defaults failed\n"); + return result; + } + + result = smu8_get_system_info_data(hwmgr); + if (result != 0) { + pr_err("smu8_get_system_info_data failed\n"); + return result; + } + + smu8_construct_boot_state(hwmgr); + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = SMU8_MAX_HARDWARE_POWERLEVELS; + + return result; +} + +static int smu8_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + if (hwmgr != NULL) { + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + + kfree(hwmgr->backend); + hwmgr->backend = NULL; + } + return 0; +} + +static int smu8_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMin), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax), + NULL); + + return 0; +} + +static int smu8_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + unsigned long clock = 0, level; + + if (NULL == table || table->count <= 0) + return -EINVAL; + + data->sclk_dpm.soft_min_clk = table->entries[0].clk; + data->sclk_dpm.hard_min_clk = table->entries[0].clk; + hwmgr->pstate_sclk = table->entries[0].clk; + hwmgr->pstate_mclk = 0; + + level = smu8_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + clock = table->entries[level].clk; + else + clock = table->entries[table->count - 1].clk; + + data->sclk_dpm.soft_max_clk = clock; + data->sclk_dpm.hard_max_clk = clock; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax), + NULL); + + return 0; +} + +static int smu8_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMax), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + smu8_get_sclk_level(hwmgr, + data->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin), + NULL); + + return 0; +} + +static int smu8_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = smu8_phm_force_dpm_highest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + ret = smu8_phm_force_dpm_lowest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = smu8_phm_unforce_dpm_levels(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + + return ret; +} + +static int smu8_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF, NULL); + return 0; +} + +static int smu8_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) +{ + if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { + return smum_send_msg_to_smc_with_parameter( + hwmgr, + PPSMC_MSG_UVDPowerON, + PP_CAP(PHM_PlatformCaps_UVDDynamicPowerGating) ? 1 : 0, + NULL); + } + + return 0; +} + +static int smu8_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_vce_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ + if (PP_CAP(PHM_PlatformCaps_StablePState) || + hwmgr->en_umd_pstate) { + data->vce_dpm.hard_min_clk = + ptable->entries[ptable->count - 1].ecclk; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetEclkHardMin, + smu8_get_eclk_level(hwmgr, + data->vce_dpm.hard_min_clk, + PPSMC_MSG_SetEclkHardMin), + NULL); + } else { + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetEclkHardMin, + 0, + NULL); + /* disable ECLK DPM 0. Otherwise VCE could hang if + * switching SCLK from DPM 0 to 6/7 */ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetEclkSoftMin, + 1, + NULL); + } + return 0; +} + +static int smu8_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) +{ + if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_VCEPowerOFF, + NULL); + return 0; +} + +static int smu8_dpm_powerup_vce(struct pp_hwmgr *hwmgr) +{ + if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) + return smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_VCEPowerON, + NULL); + return 0; +} + +static uint32_t smu8_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + return data->sys_info.bootup_uma_clock; +} + +static uint32_t smu8_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct smu8_power_state *smu8_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + smu8_ps = cast_smu8_power_state(&ps->hardware); + + if (low) + return smu8_ps->levels[0].engineClock; + else + return smu8_ps->levels[smu8_ps->level-1].engineClock; +} + +static int smu8_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); + + smu8_ps->level = 1; + smu8_ps->nbps_flags = 0; + smu8_ps->bapm_flags = 0; + smu8_ps->levels[0] = data->boot_power_level; + + return 0; +} + +static int smu8_dpm_get_pp_table_entry_callback( + struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps, + unsigned int index, + const void *clock_info) +{ + struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); + + const ATOM_PPLIB_CZ_CLOCK_INFO *smu8_clock_info = clock_info; + + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + uint8_t clock_info_index = smu8_clock_info->index; + + if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1)) + clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1); + + smu8_ps->levels[index].engineClock = table->entries[clock_info_index].clk; + smu8_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v; + + smu8_ps->level = index + 1; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + smu8_ps->levels[index].dsDividerIndex = 5; + smu8_ps->levels[index].ssDividerIndex = 5; + } + + return 0; +} + +static int smu8_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned long ret = 0; + + result = pp_tables_get_num_of_entries(hwmgr, &ret); + + return result ? 0 : ret; +} + +static int smu8_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry, struct pp_power_state *ps) +{ + int result; + struct smu8_power_state *smu8_ps; + + ps->hardware.magic = smu8_magic; + + smu8_ps = cast_smu8_power_state(&(ps->hardware)); + + result = pp_tables_get_entry(hwmgr, entry, ps, + smu8_dpm_get_pp_table_entry_callback); + + smu8_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; + smu8_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; + + return result; +} + +static int smu8_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct smu8_power_state); +} + +static void smu8_hw_print_display_cfg( + const struct cc6_settings *cc6_settings) +{ + PP_DBG_LOG("New Display Configuration:\n"); + + PP_DBG_LOG(" cpu_cc6_disable: %d\n", + cc6_settings->cpu_cc6_disable); + PP_DBG_LOG(" cpu_pstate_disable: %d\n", + cc6_settings->cpu_pstate_disable); + PP_DBG_LOG(" nb_pstate_switch_disable: %d\n", + cc6_settings->nb_pstate_switch_disable); + PP_DBG_LOG(" cpu_pstate_separation_time: %d\n\n", + cc6_settings->cpu_pstate_separation_time); +} + + static int smu8_set_cpu_power_state(struct pp_hwmgr *hwmgr) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + uint32_t data = 0; + + if (hw_data->cc6_settings.cc6_setting_changed) { + + hw_data->cc6_settings.cc6_setting_changed = false; + + smu8_hw_print_display_cfg(&hw_data->cc6_settings); + + data |= (hw_data->cc6_settings.cpu_pstate_separation_time + & PWRMGT_SEPARATION_TIME_MASK) + << PWRMGT_SEPARATION_TIME_SHIFT; + + data |= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0) + << PWRMGT_DISABLE_CPU_CSTATES_SHIFT; + + data |= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0) + << PWRMGT_DISABLE_CPU_PSTATES_SHIFT; + + PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n", + data); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDisplaySizePowerParams, + data, + NULL); + } + + return 0; +} + + +static int smu8_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) +{ + struct smu8_hwmgr *hw_data = hwmgr->backend; + + if (separation_time != + hw_data->cc6_settings.cpu_pstate_separation_time || + cc6_disable != hw_data->cc6_settings.cpu_cc6_disable || + pstate_disable != hw_data->cc6_settings.cpu_pstate_disable || + pstate_switch_disable != hw_data->cc6_settings.nb_pstate_switch_disable) { + + hw_data->cc6_settings.cc6_setting_changed = true; + + hw_data->cc6_settings.cpu_pstate_separation_time = + separation_time; + hw_data->cc6_settings.cpu_cc6_disable = + cc6_disable; + hw_data->cc6_settings.cpu_pstate_disable = + pstate_disable; + hw_data->cc6_settings.nb_pstate_switch_disable = + pstate_switch_disable; + + } + + return 0; +} + +static int smu8_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ + uint32_t i; + const struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dep_on_dal_pwrl; + const struct phm_clock_and_voltage_limits *limits = + &hwmgr->dyn_state.max_clock_voltage_on_ac; + + info->engine_max_clock = limits->sclk; + info->memory_max_clock = limits->mclk; + + for (i = table->count - 1; i > 0; i--) { + if (limits->vddc >= table->entries[i].v) { + info->level = table->entries[i].clk; + return 0; + } + } + return -EINVAL; +} + +static int smu8_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + switch (type) { + case PP_SCLK: + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMin, + mask, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSclkSoftMax, + mask, + NULL); + break; + default: + break; + } + + return 0; +} + +static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_clock_voltage_dependency_table *sclk_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + int i, now, size = 0; + + switch (type) { + case PP_SCLK: + now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, + CURR_SCLK_INDEX); + + for (i = 0; i < sclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->entries[i].clk / 100, + (i == now) ? "*" : ""); + break; + case PP_MCLK: + now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, + CURR_MCLK_INDEX); + + for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--) + size += sprintf(buf + size, "%d: %uMhz %s\n", + SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100, + (SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : ""); + break; + default: + break; + } + return size; +} + +static int smu8_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + const struct smu8_power_state *ps; + struct smu8_hwmgr *data; + uint32_t level_index; + uint32_t i; + + if (level == NULL || hwmgr == NULL || state == NULL) + return -EINVAL; + + data = hwmgr->backend; + ps = cast_const_smu8_power_state(state); + + level_index = index > ps->level - 1 ? ps->level - 1 : index; + level->coreClock = ps->levels[level_index].engineClock; + + if (designation == PHM_PerformanceLevelDesignation_PowerContainment) { + for (i = 1; i < ps->level; i++) { + if (ps->levels[i].engineClock > data->dce_slow_sclk_threshold) { + level->coreClock = ps->levels[i].engineClock; + break; + } + } + } + + if (level_index == 0) + level->memory_clock = data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]; + else + level->memory_clock = data->sys_info.nbp_memory_clock[0]; + + level->vddc = (smu8_convert_8Bit_index_to_voltage(hwmgr, ps->levels[level_index].vddcIndex) + 2) / 4; + level->nonLocalMemoryFreq = 0; + level->nonLocalMemoryWidth = 0; + + return 0; +} + +static int smu8_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) +{ + const struct smu8_power_state *ps = cast_const_smu8_power_state(state); + + clock_info->min_eng_clk = ps->levels[0].engineClock / (1 << (ps->levels[0].ssDividerIndex)); + clock_info->max_eng_clk = ps->levels[ps->level - 1].engineClock / (1 << (ps->levels[ps->level - 1].ssDividerIndex)); + + return 0; +} + +static int smu8_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks) +{ + struct smu8_hwmgr *data = hwmgr->backend; + int i; + struct phm_clock_voltage_dependency_table *table; + + clocks->count = smu8_get_max_sclk_level(hwmgr); + switch (type) { + case amd_pp_disp_clock: + for (i = 0; i < clocks->count; i++) + clocks->clock[i] = data->sys_info.display_clock[i] * 10; + break; + case amd_pp_sys_clock: + table = hwmgr->dyn_state.vddc_dependency_on_sclk; + for (i = 0; i < clocks->count; i++) + clocks->clock[i] = table->entries[i].clk * 10; + break; + case amd_pp_mem_clock: + clocks->count = SMU8_NUM_NBPMEMORYCLOCK; + for (i = 0; i < clocks->count; i++) + clocks->clock[i] = data->sys_info.nbp_memory_clock[clocks->count - 1 - i] * 10; + break; + default: + return -1; + } + + return 0; +} + +static int smu8_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) +{ + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + unsigned long level; + const struct phm_clock_and_voltage_limits *limits = + &hwmgr->dyn_state.max_clock_voltage_on_ac; + + if ((NULL == table) || (table->count <= 0) || (clocks == NULL)) + return -EINVAL; + + level = smu8_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + clocks->engine_max_clock = table->entries[level].clk; + else + clocks->engine_max_clock = table->entries[table->count - 1].clk; + + clocks->memory_max_clock = limits->mclk; + + return 0; +} + +static int smu8_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + int actual_temp = 0; + uint32_t val = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP); + uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); + + if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) + actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + else + actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return actual_temp; +} + +static int smu8_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); + uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); + uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); + + uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent; + uint16_t vddnb, vddgfx; + int result; + + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + *size = 4; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + if (sclk_index < NUM_SCLK_LEVELS) { + sclk = table->entries[sclk_index].clk; + *((uint32_t *)value) = sclk; + return 0; + } + return -EINVAL; + case AMDGPU_PP_SENSOR_VDDNB: + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = smu8_convert_8Bit_index_to_voltage(hwmgr, tmp) / 4; + *((uint32_t *)value) = vddnb; + return 0; + case AMDGPU_PP_SENSOR_VDDGFX: + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = smu8_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp) / 4; + *((uint32_t *)value) = vddgfx; + return 0; + case AMDGPU_PP_SENSOR_UVD_VCLK: + if (!data->uvd_power_gated) { + if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + vclk = uvd_table->entries[uvd_index].vclk; + *((uint32_t *)value) = vclk; + return 0; + } + } + *((uint32_t *)value) = 0; + return 0; + case AMDGPU_PP_SENSOR_UVD_DCLK: + if (!data->uvd_power_gated) { + if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + dclk = uvd_table->entries[uvd_index].dclk; + *((uint32_t *)value) = dclk; + return 0; + } + } + *((uint32_t *)value) = 0; + return 0; + case AMDGPU_PP_SENSOR_VCE_ECCLK: + if (!data->vce_power_gated) { + if (vce_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { + return -EINVAL; + } else { + ecclk = vce_table->entries[vce_index].ecclk; + *((uint32_t *)value) = ecclk; + return 0; + } + } + *((uint32_t *)value) = 0; + return 0; + case AMDGPU_PP_SENSOR_GPU_LOAD: + result = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetAverageGraphicsActivity, + &activity_percent); + if (0 == result) { + activity_percent = activity_percent > 100 ? 100 : activity_percent; + } else { + activity_percent = 50; + } + *((uint32_t *)value) = activity_percent; + return 0; + case AMDGPU_PP_SENSOR_UVD_POWER: + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + return 0; + case AMDGPU_PP_SENSOR_VCE_POWER: + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + return 0; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = smu8_thermal_get_temperature(hwmgr); + return 0; + default: + return -EINVAL; + } +} + +static int smu8_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrHiVirtual, + mc_addr_hi, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrLoVirtual, + mc_addr_low, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrHiPhysical, + virtual_addr_hi, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrLoPhysical, + virtual_addr_low, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramBufferSize, + size, + NULL); + return 0; +} + +static int smu8_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *thermal_data) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); + + thermal_data->max = (data->thermal_auto_throttling_treshold + + data->sys_info.htc_hyst_lmt) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static int smu8_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct smu8_hwmgr *data = hwmgr->backend; + uint32_t dpm_features = 0; + + if (enable && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM)) { + data->dpm_flags |= DPMFlags_UVD_Enabled; + dpm_features |= UVD_DPM_MASK; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features, + NULL); + } else { + dpm_features |= UVD_DPM_MASK; + data->dpm_flags &= ~DPMFlags_UVD_Enabled; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + dpm_features, + NULL); + } + return 0; +} + +static int smu8_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu8_hwmgr *data = hwmgr->backend; + struct phm_uvd_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + if (!bgate) { + /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ + if (PP_CAP(PHM_PlatformCaps_StablePState) || + hwmgr->en_umd_pstate) { + data->uvd_dpm.hard_min_clk = + ptable->entries[ptable->count - 1].vclk; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetUvdHardMin, + smu8_get_uvd_level(hwmgr, + data->uvd_dpm.hard_min_clk, + PPSMC_MSG_SetUvdHardMin), + NULL); + + smu8_enable_disable_uvd_dpm(hwmgr, true); + } else { + smu8_enable_disable_uvd_dpm(hwmgr, true); + } + } else { + smu8_enable_disable_uvd_dpm(hwmgr, false); + } + + return 0; +} + +static int smu8_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct smu8_hwmgr *data = hwmgr->backend; + uint32_t dpm_features = 0; + + if (enable && phm_cap_enabled( + hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEDPM)) { + data->dpm_flags |= DPMFlags_VCE_Enabled; + dpm_features |= VCE_DPM_MASK; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features, + NULL); + } else { + dpm_features |= VCE_DPM_MASK; + data->dpm_flags &= ~DPMFlags_VCE_Enabled; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + dpm_features, + NULL); + } + + return 0; +} + + +static void smu8_dpm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + if (data->acp_power_gated == bgate) + return; + + if (bgate) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF, NULL); + else + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerON, NULL); +} + +static void smu8_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + data->uvd_power_gated = bgate; + + if (bgate) { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_GATE); + smu8_dpm_update_uvd_dpm(hwmgr, true); + smu8_dpm_powerdown_uvd(hwmgr); + } else { + smu8_dpm_powerup_uvd(hwmgr); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); + smu8_dpm_update_uvd_dpm(hwmgr, false); + } + +} + +static void smu8_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct smu8_hwmgr *data = hwmgr->backend; + + if (bgate) { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_GATE); + smu8_enable_disable_vce_dpm(hwmgr, false); + smu8_dpm_powerdown_vce(hwmgr); + data->vce_power_gated = true; + } else { + smu8_dpm_powerup_vce(hwmgr); + data->vce_power_gated = false; + amdgpu_device_ip_set_clockgating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + smu8_dpm_update_vce_dpm(hwmgr); + smu8_enable_disable_vce_dpm(hwmgr, true); + } +} + +static const struct pp_hwmgr_func smu8_hwmgr_funcs = { + .backend_init = smu8_hwmgr_backend_init, + .backend_fini = smu8_hwmgr_backend_fini, + .apply_state_adjust_rules = smu8_apply_state_adjust_rules, + .force_dpm_level = smu8_dpm_force_dpm_level, + .get_power_state_size = smu8_get_power_state_size, + .powerdown_uvd = smu8_dpm_powerdown_uvd, + .powergate_uvd = smu8_dpm_powergate_uvd, + .powergate_vce = smu8_dpm_powergate_vce, + .powergate_acp = smu8_dpm_powergate_acp, + .get_mclk = smu8_dpm_get_mclk, + .get_sclk = smu8_dpm_get_sclk, + .patch_boot_state = smu8_dpm_patch_boot_state, + .get_pp_table_entry = smu8_dpm_get_pp_table_entry, + .get_num_of_pp_table_entries = smu8_dpm_get_num_of_pp_table_entries, + .set_cpu_power_state = smu8_set_cpu_power_state, + .store_cc6_data = smu8_store_cc6_data, + .force_clock_level = smu8_force_clock_level, + .print_clock_levels = smu8_print_clock_levels, + .get_dal_power_level = smu8_get_dal_power_level, + .get_performance_level = smu8_get_performance_level, + .get_current_shallow_sleep_clocks = smu8_get_current_shallow_sleep_clocks, + .get_clock_by_type = smu8_get_clock_by_type, + .get_max_high_clocks = smu8_get_max_high_clocks, + .read_sensor = smu8_read_sensor, + .power_off_asic = smu8_power_off_asic, + .asic_setup = smu8_setup_asic_task, + .dynamic_state_management_enable = smu8_enable_dpm_tasks, + .power_state_set = smu8_set_power_state_tasks, + .dynamic_state_management_disable = smu8_disable_dpm_tasks, + .notify_cac_buffer_info = smu8_notify_cac_buffer_info, + .update_nbdpm_pstate = smu8_nbdpm_pstate_enable_disable, + .get_thermal_temperature_range = smu8_get_thermal_temperature_range, +}; + +int smu8_init_function_pointers(struct pp_hwmgr *hwmgr) +{ + hwmgr->hwmgr_func = &smu8_hwmgr_funcs; + hwmgr->pptable_func = &pptable_funcs; + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h new file mode 100644 index 000000000000..05a06083e1b8 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu8_hwmgr.h @@ -0,0 +1,311 @@ +/* + * Copyright 2015 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 _SMU8_HWMGR_H_ +#define _SMU8_HWMGR_H_ + +#include "cgs_common.h" +#include "ppatomctrl.h" + +#define SMU8_NUM_NBPSTATES 4 +#define SMU8_NUM_NBPMEMORYCLOCK 2 +#define MAX_DISPLAY_CLOCK_LEVEL 8 +#define SMU8_MAX_HARDWARE_POWERLEVELS 8 +#define SMU8_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 +#define SMU8_MIN_DEEP_SLEEP_SCLK 800 + +/* Carrizo device IDs */ +#define DEVICE_ID_CZ_9870 0x9870 +#define DEVICE_ID_CZ_9874 0x9874 +#define DEVICE_ID_CZ_9875 0x9875 +#define DEVICE_ID_CZ_9876 0x9876 +#define DEVICE_ID_CZ_9877 0x9877 + +struct smu8_dpm_entry { + uint32_t soft_min_clk; + uint32_t hard_min_clk; + uint32_t soft_max_clk; + uint32_t hard_max_clk; +}; + +struct smu8_sys_info { + uint32_t bootup_uma_clock; + uint32_t bootup_engine_clock; + uint32_t dentist_vco_freq; + uint32_t nb_dpm_enable; + uint32_t nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK]; + uint32_t nbp_n_clock[SMU8_NUM_NBPSTATES]; + uint16_t nbp_voltage_index[SMU8_NUM_NBPSTATES]; + uint32_t display_clock[MAX_DISPLAY_CLOCK_LEVEL]; + uint16_t bootup_nb_voltage_index; + uint8_t htc_tmp_lmt; + uint8_t htc_hyst_lmt; + uint32_t system_config; + uint32_t uma_channel_number; +}; + +#define MAX_DISPLAYPHY_IDS 0x8 +#define DISPLAYPHY_LANEMASK 0xF +#define UNKNOWN_TRANSMITTER_PHY_ID (-1) + +#define DISPLAYPHY_PHYID_SHIFT 24 +#define DISPLAYPHY_LANESELECT_SHIFT 16 + +#define DISPLAYPHY_RX_SELECT 0x1 +#define DISPLAYPHY_TX_SELECT 0x2 +#define DISPLAYPHY_CORE_SELECT 0x4 + +#define DDI_POWERGATING_ARG(phyID, lanemask, rx, tx, core) \ + (((uint32_t)(phyID))<adev); + uint32_t reg, data; + + *cap = false; + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) + return 0; + + WREG32(0x12074, 0xFFF0003B); + data = RREG32(0x12075); + + if (data == 0x1) { + reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); + + if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) + *cap = true; + } + + return 0; +} + +int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + uint32_t reg; + + reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL); + + if (reg & BACO_CNTL__BACO_MODE_MASK) + /* gfx has already entered BACO state */ + *state = BACO_STATE_IN; + else + *state = BACO_STATE_OUT; + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h new file mode 100644 index 000000000000..84e90f801ac3 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu9_baco.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 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 __SMU9_BACO_H__ +#define __SMU9_BACO_H__ +#include "hwmgr.h" +#include "common_baco.h" + +extern int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c new file mode 100644 index 000000000000..60b5ca974356 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.c @@ -0,0 +1,767 @@ +/* + * Copyright 2018 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 +#include + +#include "hwmgr.h" +#include "pp_debug.h" +#include "ppatomctrl.h" +#include "ppsmc.h" +#include "atom.h" +#include "ivsrcid/thm/irqsrcs_thm_9_0.h" +#include "ivsrcid/smuio/irqsrcs_smuio_9_0.h" +#include "ivsrcid/ivsrcid_vislands30.h" + +uint8_t convert_to_vid(uint16_t vddc) +{ + return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); +} + +uint16_t convert_to_vddc(uint8_t vid) +{ + return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE); +} + +int phm_copy_clock_limits_array( + struct pp_hwmgr *hwmgr, + uint32_t **pptable_info_array, + const uint32_t *pptable_array, + uint32_t power_saving_clock_count) +{ + uint32_t array_size, i; + uint32_t *table; + + array_size = sizeof(uint32_t) * power_saving_clock_count; + table = kzalloc(array_size, GFP_KERNEL); + if (NULL == table) + return -ENOMEM; + + for (i = 0; i < power_saving_clock_count; i++) + table[i] = le32_to_cpu(pptable_array[i]); + + *pptable_info_array = table; + + return 0; +} + +int phm_copy_overdrive_settings_limits_array( + struct pp_hwmgr *hwmgr, + uint32_t **pptable_info_array, + const uint32_t *pptable_array, + uint32_t od_setting_count) +{ + uint32_t array_size, i; + uint32_t *table; + + array_size = sizeof(uint32_t) * od_setting_count; + table = kzalloc(array_size, GFP_KERNEL); + if (NULL == table) + return -ENOMEM; + + for (i = 0; i < od_setting_count; i++) + table[i] = le32_to_cpu(pptable_array[i]); + + *pptable_info_array = table; + + return 0; +} + +uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size) +{ + u32 mask = 0; + u32 shift = 0; + + shift = (offset % 4) << 3; + if (size == sizeof(uint8_t)) + mask = 0xFF << shift; + else if (size == sizeof(uint16_t)) + mask = 0xFFFF << shift; + + original_data &= ~mask; + original_data |= (field << shift); + return original_data; +} + +/** + * Returns once the part of the register indicated by the mask has + * reached the given value. + */ +int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (hwmgr == NULL || hwmgr->device == NULL) { + pr_err("Invalid Hardware Manager!"); + return -EINVAL; + } + + for (i = 0; i < hwmgr->usec_timeout; i++) { + cur_value = cgs_read_register(hwmgr->device, index); + if ((cur_value & mask) == (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic*/ + if (i == hwmgr->usec_timeout) + return -1; + return 0; +} + + +/** + * Returns once the part of the register indicated by the mask has + * reached the given value.The indirect space is described by giving + * the memory-mapped index of the indirect index register. + */ +int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (hwmgr == NULL || hwmgr->device == NULL) { + pr_err("Invalid Hardware Manager!"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, indirect_port, index); + return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); +} + +int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + for (i = 0; i < hwmgr->usec_timeout; i++) { + cur_value = cgs_read_register(hwmgr->device, + index); + if ((cur_value & mask) != (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic */ + if (i == hwmgr->usec_timeout) + return -ETIME; + return 0; +} + +int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + cgs_write_register(hwmgr->device, indirect_port, index); + return phm_wait_for_register_unequal(hwmgr, indirect_port + 1, + value, mask); +} + +bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) +{ + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating); +} + +bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr) +{ + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); +} + + +int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table) +{ + uint32_t i, j; + uint16_t vvalue; + bool found = false; + struct pp_atomctrl_voltage_table *table; + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "Voltage Table empty.", return -EINVAL); + + table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), + GFP_KERNEL); + + if (NULL == table) + return -EINVAL; + + table->mask_low = vol_table->mask_low; + table->phase_delay = vol_table->phase_delay; + + for (i = 0; i < vol_table->count; i++) { + vvalue = vol_table->entries[i].value; + found = false; + + for (j = 0; j < table->count; j++) { + if (vvalue == table->entries[j].value) { + found = true; + break; + } + } + + if (!found) { + table->entries[table->count].value = vvalue; + table->entries[table->count].smio_low = + vol_table->entries[i].smio_low; + table->count++; + } + } + + memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); + kfree(table); + table = NULL; + return 0; +} + +int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].mvdd; + vol_table->entries[i].smio_low = 0; + } + + result = phm_trim_voltage_table(vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim MVDD table.", return result); + + return 0; +} + +int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].vddci; + vol_table->entries[i].smio_low = 0; + } + + result = phm_trim_voltage_table(vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim VDDCI table.", return result); + + return 0; +} + +int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + int i = 0; + + PP_ASSERT_WITH_CODE((0 != lookup_table->count), + "Voltage Lookup Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + + vol_table->count = lookup_table->count; + + for (i = 0; i < vol_table->count; i++) { + vol_table->entries[i].value = lookup_table->entries[i].us_vdd; + vol_table->entries[i].smio_low = 0; + } + + return 0; +} + +void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, + struct pp_atomctrl_voltage_table *vol_table) +{ + unsigned int i, diff; + + if (vol_table->count <= max_vol_steps) + return; + + diff = vol_table->count - max_vol_steps; + + for (i = 0; i < max_vol_steps; i++) + vol_table->entries[i] = vol_table->entries[i + diff]; + + vol_table->count = max_vol_steps; + + return; +} + +int phm_reset_single_dpm_table(void *table, + uint32_t count, int max) +{ + int i; + + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + dpm_table->count = count > max ? max : count; + + for (i = 0; i < dpm_table->count; i++) + dpm_table->dpm_level[i].enabled = false; + + return 0; +} + +void phm_setup_pcie_table_entry( + void *table, + uint32_t index, uint32_t pcie_gen, + uint32_t pcie_lanes) +{ + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + dpm_table->dpm_level[index].value = pcie_gen; + dpm_table->dpm_level[index].param1 = pcie_lanes; + dpm_table->dpm_level[index].enabled = 1; +} + +int32_t phm_get_dpm_level_enable_mask_value(void *table) +{ + int32_t i; + int32_t mask = 0; + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + for (i = dpm_table->count; i > 0; i--) { + mask = mask << 1; + if (dpm_table->dpm_level[i - 1].enabled) + mask |= 0x1; + else + mask &= 0xFFFFFFFE; + } + + return mask; +} + +uint8_t phm_get_voltage_index( + struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) +{ + uint8_t count = (uint8_t) (lookup_table->count); + uint8_t i; + + PP_ASSERT_WITH_CODE((NULL != lookup_table), + "Lookup Table empty.", return 0); + PP_ASSERT_WITH_CODE((0 != count), + "Lookup Table empty.", return 0); + + for (i = 0; i < lookup_table->count; i++) { + /* find first voltage equal or bigger than requested */ + if (lookup_table->entries[i].us_vdd >= voltage) + return i; + } + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + +uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, + uint32_t voltage) +{ + uint8_t count = (uint8_t) (voltage_table->count); + uint8_t i = 0; + + PP_ASSERT_WITH_CODE((NULL != voltage_table), + "Voltage Table empty.", return 0;); + PP_ASSERT_WITH_CODE((0 != count), + "Voltage Table empty.", return 0;); + + for (i = 0; i < count; i++) { + /* find first voltage bigger than requested */ + if (voltage_table->entries[i].value >= voltage) + return i; + } + + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + +uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) +{ + uint32_t i; + + for (i = 0; i < vddci_table->count; i++) { + if (vddci_table->entries[i].value >= vddci) + return vddci_table->entries[i].value; + } + + pr_debug("vddci is larger than max value in vddci_table\n"); + return vddci_table->entries[i-1].value; +} + +int phm_find_boot_level(void *table, + uint32_t value, uint32_t *boot_level) +{ + int result = -EINVAL; + uint32_t i; + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + for (i = 0; i < dpm_table->count; i++) { + if (value == dpm_table->dpm_level[i].value) { + *boot_level = i; + result = 0; + } + } + + return result; +} + +int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *sclk) +{ + uint8_t entry_id; + uint8_t voltage_id; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ + for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { + voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd; + if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) + break; + } + + if (entry_id >= table_info->vdd_dep_on_sclk->count) { + pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n"); + return -EINVAL; + } + + *sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk; + + return 0; +} + +/** + * Initialize Dynamic State Adjustment Rule Settings + * + * @param hwmgr the address of the powerplay hardware manager. + */ +int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) +{ + uint32_t table_size; + struct phm_clock_voltage_dependency_table *table_clk_vlt; + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* initialize vddc_dep_on_dal_pwrl table */ + table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); + table_clk_vlt = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table_clk_vlt) { + pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n"); + return -ENOMEM; + } else { + table_clk_vlt->count = 4; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; + table_clk_vlt->entries[1].v = 720; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; + table_clk_vlt->entries[2].v = 810; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; + table_clk_vlt->entries[3].v = 900; + if (pptable_info != NULL) + pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + } + + return 0; +} + +uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask) +{ + uint32_t level = 0; + + while (0 == (mask & (1 << level))) + level++; + + return level; +} + +void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_clock_voltage_dependency_table *table = + table_info->vddc_dep_on_dal_pwrl; + struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table; + enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level; + uint32_t req_vddc = 0, req_volt, i; + + if (!table || table->count <= 0 + || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW + || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE) + return; + + for (i = 0; i < table->count; i++) { + if (dal_power_level == table->entries[i].clk) { + req_vddc = table->entries[i].v; + break; + } + } + + vddc_table = table_info->vdd_dep_on_sclk; + for (i = 0; i < vddc_table->count; i++) { + if (req_vddc <= vddc_table->entries[i].vddc) { + req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VddC_Request, + req_volt, + NULL); + return; + } + } + pr_err("DAL requested level can not" + " found a available voltage in VDDC DPM Table \n"); +} + +int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t id, uint16_t *voltage) +{ + uint32_t vol; + int ret = 0; + + if (hwmgr->chip_id < CHIP_TONGA) { + ret = atomctrl_get_voltage_evv(hwmgr, id, voltage); + } else if (hwmgr->chip_id < CHIP_POLARIS10) { + ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage); + if (*voltage >= 2000 || *voltage == 0) + *voltage = 1150; + } else { + ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); + *voltage = (uint16_t)(vol/100); + } + return ret; +} + + +int phm_irq_process(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + uint32_t client_id = entry->client_id; + uint32_t src_id = entry->src_id; + + if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) { + if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) { + dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); + /* + * SW CTF just occurred. + * Try to do a graceful shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); + orderly_poweroff(true); + } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) + dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); + else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) { + dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); + /* + * HW CTF just occurred. Shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); + orderly_poweroff(true); + } + } else if (client_id == SOC15_IH_CLIENTID_THM) { + if (src_id == 0) { + dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); + /* + * SW CTF just occurred. + * Try to do a graceful shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); + orderly_poweroff(true); + } else + dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); + } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) { + dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); + /* + * HW CTF just occurred. Shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); + orderly_poweroff(true); + } + + return 0; +} + +static const struct amdgpu_irq_src_funcs smu9_irq_funcs = { + .process = phm_irq_process, +}; + +int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_irq_src *source = + kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL); + + if (!source) + return -ENOMEM; + + source->funcs = &smu9_irq_funcs; + + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + SOC15_IH_CLIENTID_THM, + THM_9_0__SRCID__THM_DIG_THERM_L2H, + source); + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + SOC15_IH_CLIENTID_THM, + THM_9_0__SRCID__THM_DIG_THERM_H2L, + source); + + /* Register CTF(GPIO_19) interrupt */ + amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), + SOC15_IH_CLIENTID_ROM_SMUIO, + SMUIO_9_0__SRCID__SMUIO_GPIO19, + source); + + return 0; +} + +void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, + uint8_t *frev, uint8_t *crev) +{ + struct amdgpu_device *adev = dev; + uint16_t data_start; + + if (amdgpu_atom_parse_data_header( + adev->mode_info.atom_context, table, size, + frev, crev, &data_start)) + return (uint8_t *)adev->mode_info.atom_context->bios + + data_start; + + return NULL; +} + +int smu_get_voltage_dependency_table_ppt_v1( + const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint8_t i = 0; + PP_ASSERT_WITH_CODE((0 != allowed_dep_table->count), + "Voltage Lookup Table empty", + return -EINVAL); + + dep_table->count = allowed_dep_table->count; + for (i=0; icount; i++) { + dep_table->entries[i].clk = allowed_dep_table->entries[i].clk; + dep_table->entries[i].vddInd = allowed_dep_table->entries[i].vddInd; + dep_table->entries[i].vdd_offset = allowed_dep_table->entries[i].vdd_offset; + dep_table->entries[i].vddc = allowed_dep_table->entries[i].vddc; + dep_table->entries[i].vddgfx = allowed_dep_table->entries[i].vddgfx; + dep_table->entries[i].vddci = allowed_dep_table->entries[i].vddci; + dep_table->entries[i].mvdd = allowed_dep_table->entries[i].mvdd; + dep_table->entries[i].phases = allowed_dep_table->entries[i].phases; + dep_table->entries[i].cks_enable = allowed_dep_table->entries[i].cks_enable; + dep_table->entries[i].cks_voffset = allowed_dep_table->entries[i].cks_voffset; + } + + return 0; +} + +int smu_set_watermarks_for_clocks_ranges(void *wt_table, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) +{ + uint32_t i; + struct watermarks *table = wt_table; + + if (!table || !wm_with_clock_ranges) + return -EINVAL; + + if (wm_with_clock_ranges->num_wm_dmif_sets > 4 || wm_with_clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; + + for (i = 0; i < wm_with_clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[1][i].MinClock = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxClock = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MinUclk = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxUclk = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].WmSetting = (uint8_t) + wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } + + for (i = 0; i < wm_with_clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[0][i].MinClock = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxClock = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MinUclk = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxUclk = + cpu_to_le16((uint16_t) + (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].WmSetting = (uint8_t) + wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h new file mode 100644 index 000000000000..ad33983a8064 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu_helper.h @@ -0,0 +1,228 @@ +/* + * Copyright 2018 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _SMU_HELPER_H_ +#define _SMU_HELPER_H_ + +struct pp_atomctrl_voltage_table; +struct pp_hwmgr; +struct phm_ppt_v1_voltage_lookup_table; +struct Watermarks_t; +struct pp_wm_sets_with_clock_ranges_soc15; + +uint8_t convert_to_vid(uint16_t vddc); +uint16_t convert_to_vddc(uint8_t vid); + +struct watermark_row_generic_t { + uint16_t MinClock; + uint16_t MaxClock; + uint16_t MinUclk; + uint16_t MaxUclk; + + uint8_t WmSetting; + uint8_t Padding[3]; +}; + +struct watermarks { + struct watermark_row_generic_t WatermarkRow[2][4]; + uint32_t padding[7]; +}; + +int phm_copy_clock_limits_array( + struct pp_hwmgr *hwmgr, + uint32_t **pptable_info_array, + const uint32_t *pptable_array, + uint32_t power_saving_clock_count); + +int phm_copy_overdrive_settings_limits_array( + struct pp_hwmgr *hwmgr, + uint32_t **pptable_info_array, + const uint32_t *pptable_array, + uint32_t od_setting_count); + +extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, + uint32_t value, uint32_t mask); +extern int phm_wait_for_indirect_register_unequal( + struct pp_hwmgr *hwmgr, + uint32_t indirect_port, uint32_t index, + uint32_t value, uint32_t mask); + + +extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); +extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr); +extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr); + +extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table); +extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); +extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); +extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table); +extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table); +extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); +extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); +extern int32_t phm_get_dpm_level_enable_mask_value(void *table); +extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table, + uint32_t voltage); +extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); +extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); +extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); +extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *sclk); +extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); +extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); +extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); + +extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t id, uint16_t *voltage); + +extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size); + +extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, + uint32_t value, uint32_t mask); + +extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask); + +int phm_irq_process(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry); + +int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr); + +void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, + uint8_t *frev, uint8_t *crev); + +int smu_get_voltage_dependency_table_ppt_v1( + const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table); + +int smu_set_watermarks_for_clocks_ranges(void *wt_table, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); + +#define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT +#define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK + +#define PHM_SET_FIELD(origval, reg, field, fieldval) \ + (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ + (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) + +#define PHM_GET_FIELD(value, reg, field) \ + (((value) & PHM_FIELD_MASK(reg, field)) >> \ + PHM_FIELD_SHIFT(reg, field)) + + +/* Operations on named fields. */ + +#define PHM_READ_FIELD(device, reg, field) \ + PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) + +#define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field) + +#define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field) + +#define PHM_WRITE_FIELD(device, reg, field, fieldval) \ + cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ + cgs_read_register(device, mm##reg), reg, field, fieldval)) + +#define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ + cgs_write_ind_register(device, port, ix##reg, \ + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field, fieldval)) + +#define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ + cgs_write_ind_register(device, port, ix##reg, \ + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field, fieldval)) + +#define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) + + +#define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ + PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, \ + mm##port##_INDEX, index, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field) ) + + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, \ + mm##port##_INDEX_11, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \ + port, index, value, mask) \ + phm_wait_on_indirect_register(hwmgr, \ + mm##port##_INDEX_11, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + index, value, mask) \ + phm_wait_for_register_unequal(hwmgr, \ + index, value, mask) + +#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ + mm##reg, value, mask) + +#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ + PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \ + (fieldval) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + +#endif /* _SMU_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c new file mode 100644 index 000000000000..ea743bea8e29 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.c @@ -0,0 +1,231 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "tonga_baco.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" + + +static const struct baco_cmd_entry gpio_tbl[] = +{ + { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, + { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, + { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, + { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } +}; + +static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, + { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } +}; + +static const struct baco_cmd_entry use_bclk_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, + { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } +}; + +static const struct baco_cmd_entry turn_off_plls_tbl[] = +{ + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 }, + { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 }, + { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 }, + { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, + { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, + { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 } +}; + +static const struct baco_cmd_entry enter_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } +}; + +#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK + +static const struct baco_cmd_entry exit_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } +}; + +static const struct baco_cmd_entry clean_baco_tbl[] = +{ + { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } +}; + +static const struct baco_cmd_entry gpio_tbl_iceland[] = +{ + { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, + { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff } +}; + +static const struct baco_cmd_entry exit_baco_tbl_iceland[] = +{ + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, + { CMD_DELAY_MS, 0, 0, 0, 20, 0 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, + { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, + { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } +}; + +static const struct baco_cmd_entry clean_baco_tbl_iceland[] = +{ + { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } +}; + +int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu7_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + if (hwmgr->chip_id == CHIP_TOPAZ) + baco_program_registers(hwmgr, gpio_tbl_iceland, ARRAY_SIZE(gpio_tbl_iceland)); + else + baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); + baco_program_registers(hwmgr, enable_fb_req_rej_tbl, + ARRAY_SIZE(enable_fb_req_rej_tbl)); + baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); + baco_program_registers(hwmgr, turn_off_plls_tbl, + ARRAY_SIZE(turn_off_plls_tbl)); + if (baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (hwmgr->chip_id == CHIP_TOPAZ) { + if (baco_program_registers(hwmgr, exit_baco_tbl_iceland, + ARRAY_SIZE(exit_baco_tbl_iceland))) { + if (baco_program_registers(hwmgr, clean_baco_tbl_iceland, + ARRAY_SIZE(clean_baco_tbl_iceland))) + return 0; + } + } else { + if (baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h new file mode 100644 index 000000000000..5dc16cc8a295 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/tonga_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __TONGA_BACO_H__ +#define __TONGA_BACO_H__ +#include "smu7_baco.h" + +extern int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c new file mode 100644 index 000000000000..46bb16c29cf6 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.c @@ -0,0 +1,121 @@ +/* + * Copyright 2018 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 "amdgpu.h" +#include "soc15.h" +#include "soc15_hw_ip.h" +#include "vega10_ip_offset.h" +#include "soc15_common.h" +#include "vega10_inc.h" +#include "vega10_ppsmc.h" +#include "vega10_baco.h" + + + +static const struct soc15_baco_cmd_entry pre_baco_tbl[] = +{ + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_DOORBELL_CNTL), BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 1}, + {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_FB_EN), 0, 0, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1} +}; + +static const struct soc15_baco_cmd_entry enter_baco_tbl[] = +{ + {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT,0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1}, + {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 5, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0}, + {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100} +}; + +static const struct soc15_baco_cmd_entry exit_baco_tbl[] = +{ + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0}, + {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10,0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0,0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0}, + {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK ,BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0}, + {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK , BACO_CNTL__BACO_EN__SHIFT, 0,0}, + {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0} + }; + +static const struct soc15_baco_cmd_entry clean_baco_tbl[] = +{ + {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0}, + {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, +}; + +int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu9_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + if (soc15_baco_program_registers(hwmgr, pre_baco_tbl, + ARRAY_SIZE(pre_baco_tbl))) { + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnterBaco, NULL)) + return -EINVAL; + + if (soc15_baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + } + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (soc15_baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (soc15_baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h new file mode 100644 index 000000000000..96d793f026a5 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2018 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 __VEGA10_BACO_H__ +#define __VEGA10_BACO_H__ +#include "smu9_baco.h" + +extern int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c new file mode 100644 index 000000000000..c378a000c934 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -0,0 +1,5482 @@ +/* + * Copyright 2016 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 +#include +#include +#include +#include + +#include "hwmgr.h" +#include "amd_powerplay.h" +#include "hardwaremanager.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "cgs_common.h" +#include "vega10_powertune.h" +#include "smu9.h" +#include "smu9_driver_if.h" +#include "vega10_inc.h" +#include "soc15_common.h" +#include "pppcielanes.h" +#include "vega10_hwmgr.h" +#include "vega10_smumgr.h" +#include "vega10_processpptables.h" +#include "vega10_pptable.h" +#include "vega10_thermal.h" +#include "pp_debug.h" +#include "amd_pcie_helpers.h" +#include "ppinterrupt.h" +#include "pp_overdriver.h" +#include "pp_thermal.h" +#include "vega10_baco.h" + +#include "smuio/smuio_9_0_offset.h" +#include "smuio/smuio_9_0_sh_mask.h" + +#define HBM_MEMORY_CHANNEL_WIDTH 128 + +static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; + +#define mmDF_CS_AON0_DramBaseAddress0 0x0044 +#define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX 0 + +//DF_CS_AON0_DramBaseAddress0 +#define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT 0x0 +#define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT 0x1 +#define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT 0x4 +#define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT 0x8 +#define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT 0xc +#define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK 0x00000001L +#define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK 0x00000002L +#define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x000000F0L +#define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000700L +#define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK 0xFFFFF000L + +typedef enum { + CLK_SMNCLK = 0, + CLK_SOCCLK, + CLK_MP0CLK, + CLK_MP1CLK, + CLK_LCLK, + CLK_DCEFCLK, + CLK_VCLK, + CLK_DCLK, + CLK_ECLK, + CLK_UCLK, + CLK_GFXCLK, + CLK_COUNT, +} CLOCK_ID_e; + +static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); + +static struct vega10_power_state *cast_phw_vega10_power_state( + struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (struct vega10_power_state *)hw_ps; +} + +static const struct vega10_power_state *cast_const_phw_vega10_power_state( + const struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (const struct vega10_power_state *)hw_ps; +} + +static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->registry_data.sclk_dpm_key_disabled = + hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; + data->registry_data.socclk_dpm_key_disabled = + hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true; + data->registry_data.mclk_dpm_key_disabled = + hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; + data->registry_data.pcie_dpm_key_disabled = + hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; + + data->registry_data.dcefclk_dpm_key_disabled = + hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true; + + if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) { + data->registry_data.power_containment_support = 1; + data->registry_data.enable_pkg_pwr_tracking_feature = 1; + data->registry_data.enable_tdc_limit_feature = 1; + } + + data->registry_data.clock_stretcher_support = + hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false; + + data->registry_data.ulv_support = + hwmgr->feature_mask & PP_ULV_MASK ? true : false; + + data->registry_data.sclk_deep_sleep_support = + hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false; + + data->registry_data.disable_water_mark = 0; + + data->registry_data.fan_control_support = 1; + data->registry_data.thermal_support = 1; + data->registry_data.fw_ctf_enabled = 1; + + data->registry_data.avfs_support = + hwmgr->feature_mask & PP_AVFS_MASK ? true : false; + data->registry_data.led_dpm_enabled = 1; + + data->registry_data.vr0hot_enabled = 1; + data->registry_data.vr1hot_enabled = 1; + data->registry_data.regulator_hot_gpio_support = 1; + + data->registry_data.didt_support = 1; + if (data->registry_data.didt_support) { + data->registry_data.didt_mode = 6; + data->registry_data.sq_ramping_support = 1; + data->registry_data.db_ramping_support = 0; + data->registry_data.td_ramping_support = 0; + data->registry_data.tcp_ramping_support = 0; + data->registry_data.dbr_ramping_support = 0; + data->registry_data.edc_didt_support = 1; + data->registry_data.gc_didt_support = 0; + data->registry_data.psm_didt_support = 0; + } + + data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT; + data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; + + data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT; + data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT; + data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT; + data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT; +} + +static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct amdgpu_device *adev = hwmgr->adev; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + + if (adev->pg_flags & AMD_PG_SUPPORT_UVD) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPowerManagement); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMC); + + /* power tune caps */ + /* assume disabled */ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtEDCEnable); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GCEDC); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PSM); + + if (data->registry_data.didt_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); + if (data->registry_data.sq_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); + if (data->registry_data.db_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); + if (data->registry_data.td_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); + if (data->registry_data.tcp_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); + if (data->registry_data.dbr_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); + if (data->registry_data.edc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); + if (data->registry_data.gc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); + if (data->registry_data.psm_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); + } + + if (data->registry_data.power_containment_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC); + + if (table_info->tdp_table->usClockStretchAmount && + data->registry_data.clock_stretcher_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEDPM); + + return 0; +} + +static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct vega10_odn_vddc_lookup_table *od_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table[3]; + struct phm_ppt_v1_clock_voltage_dependency_table *od_table[3]; + struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; + uint32_t i; + int result; + + result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); + if (!result) { + data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc; + data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc; + } + + od_lookup_table = &odn_table->vddc_lookup_table; + vddc_lookup_table = table_info->vddc_lookup_table; + + for (i = 0; i < vddc_lookup_table->count; i++) + od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd; + + od_lookup_table->count = vddc_lookup_table->count; + + dep_table[0] = table_info->vdd_dep_on_sclk; + dep_table[1] = table_info->vdd_dep_on_mclk; + dep_table[2] = table_info->vdd_dep_on_socclk; + od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk; + od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk; + od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk; + + for (i = 0; i < 3; i++) + smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]); + + if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000) + odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc; + if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000) + odn_table->min_vddc = dep_table[0]->entries[0].vddc; + + i = od_table[2]->count - 1; + od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ? + hwmgr->platform_descriptor.overdriveLimit.memoryClock : + od_table[2]->entries[i].clk; + od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ? + odn_table->max_vddc : + od_table[2]->entries[i].vddc; + + return 0; +} + +static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + int i; + uint32_t sub_vendor_id, hw_revision; + uint32_t top32, bottom32; + struct amdgpu_device *adev = hwmgr->adev; + + vega10_initialize_power_tune_defaults(hwmgr); + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + data->smu_features[i].smu_feature_id = 0xffff; + data->smu_features[i].smu_feature_bitmap = 1 << i; + data->smu_features[i].enabled = false; + data->smu_features[i].supported = false; + } + + data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = + FEATURE_DPM_PREFETCHER_BIT; + data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = + FEATURE_DPM_GFXCLK_BIT; + data->smu_features[GNLD_DPM_UCLK].smu_feature_id = + FEATURE_DPM_UCLK_BIT; + data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = + FEATURE_DPM_SOCCLK_BIT; + data->smu_features[GNLD_DPM_UVD].smu_feature_id = + FEATURE_DPM_UVD_BIT; + data->smu_features[GNLD_DPM_VCE].smu_feature_id = + FEATURE_DPM_VCE_BIT; + data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = + FEATURE_DPM_MP0CLK_BIT; + data->smu_features[GNLD_DPM_LINK].smu_feature_id = + FEATURE_DPM_LINK_BIT; + data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = + FEATURE_DPM_DCEFCLK_BIT; + data->smu_features[GNLD_ULV].smu_feature_id = + FEATURE_ULV_BIT; + data->smu_features[GNLD_AVFS].smu_feature_id = + FEATURE_AVFS_BIT; + data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = + FEATURE_DS_GFXCLK_BIT; + data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = + FEATURE_DS_SOCCLK_BIT; + data->smu_features[GNLD_DS_LCLK].smu_feature_id = + FEATURE_DS_LCLK_BIT; + data->smu_features[GNLD_PPT].smu_feature_id = + FEATURE_PPT_BIT; + data->smu_features[GNLD_TDC].smu_feature_id = + FEATURE_TDC_BIT; + data->smu_features[GNLD_THERMAL].smu_feature_id = + FEATURE_THERMAL_BIT; + data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = + FEATURE_GFX_PER_CU_CG_BIT; + data->smu_features[GNLD_RM].smu_feature_id = + FEATURE_RM_BIT; + data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = + FEATURE_DS_DCEFCLK_BIT; + data->smu_features[GNLD_ACDC].smu_feature_id = + FEATURE_ACDC_BIT; + data->smu_features[GNLD_VR0HOT].smu_feature_id = + FEATURE_VR0HOT_BIT; + data->smu_features[GNLD_VR1HOT].smu_feature_id = + FEATURE_VR1HOT_BIT; + data->smu_features[GNLD_FW_CTF].smu_feature_id = + FEATURE_FW_CTF_BIT; + data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = + FEATURE_LED_DISPLAY_BIT; + data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = + FEATURE_FAN_CONTROL_BIT; + data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; + data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; + data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT; + + if (!data->registry_data.prefetcher_dpm_key_disabled) + data->smu_features[GNLD_DPM_PREFETCHER].supported = true; + + if (!data->registry_data.sclk_dpm_key_disabled) + data->smu_features[GNLD_DPM_GFXCLK].supported = true; + + if (!data->registry_data.mclk_dpm_key_disabled) + data->smu_features[GNLD_DPM_UCLK].supported = true; + + if (!data->registry_data.socclk_dpm_key_disabled) + data->smu_features[GNLD_DPM_SOCCLK].supported = true; + + if (PP_CAP(PHM_PlatformCaps_UVDDPM)) + data->smu_features[GNLD_DPM_UVD].supported = true; + + if (PP_CAP(PHM_PlatformCaps_VCEDPM)) + data->smu_features[GNLD_DPM_VCE].supported = true; + + if (!data->registry_data.pcie_dpm_key_disabled) + data->smu_features[GNLD_DPM_LINK].supported = true; + + if (!data->registry_data.dcefclk_dpm_key_disabled) + data->smu_features[GNLD_DPM_DCEFCLK].supported = true; + + if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) && + data->registry_data.sclk_deep_sleep_support) { + data->smu_features[GNLD_DS_GFXCLK].supported = true; + data->smu_features[GNLD_DS_SOCCLK].supported = true; + data->smu_features[GNLD_DS_LCLK].supported = true; + data->smu_features[GNLD_DS_DCEFCLK].supported = true; + } + + if (data->registry_data.enable_pkg_pwr_tracking_feature) + data->smu_features[GNLD_PPT].supported = true; + + if (data->registry_data.enable_tdc_limit_feature) + data->smu_features[GNLD_TDC].supported = true; + + if (data->registry_data.thermal_support) + data->smu_features[GNLD_THERMAL].supported = true; + + if (data->registry_data.fan_control_support) + data->smu_features[GNLD_FAN_CONTROL].supported = true; + + if (data->registry_data.fw_ctf_enabled) + data->smu_features[GNLD_FW_CTF].supported = true; + + if (data->registry_data.avfs_support) + data->smu_features[GNLD_AVFS].supported = true; + + if (data->registry_data.led_dpm_enabled) + data->smu_features[GNLD_LED_DISPLAY].supported = true; + + if (data->registry_data.vr1hot_enabled) + data->smu_features[GNLD_VR1HOT].supported = true; + + if (data->registry_data.vr0hot_enabled) + data->smu_features[GNLD_VR0HOT].supported = true; + + smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetSmuVersion, + &hwmgr->smu_version); + /* ACG firmware has major version 5 */ + if ((hwmgr->smu_version & 0xff000000) == 0x5000000) + data->smu_features[GNLD_ACG].supported = true; + if (data->registry_data.didt_support) + data->smu_features[GNLD_DIDT].supported = true; + + hw_revision = adev->pdev->revision; + sub_vendor_id = adev->pdev->subsystem_vendor; + + if ((hwmgr->chip_id == 0x6862 || + hwmgr->chip_id == 0x6861 || + hwmgr->chip_id == 0x6868) && + (hw_revision == 0) && + (sub_vendor_id != 0x1002)) + data->smu_features[GNLD_PCC_LIMIT].supported = true; + + /* Get the SN to turn into a Unique ID */ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); + + adev->unique_id = ((uint64_t)bottom32 << 32) | top32; +} + +#ifdef PPLIB_VEGA10_EVV_SUPPORT +static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *socclk) +{ + uint8_t entry_id; + uint8_t voltage_id; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + PP_ASSERT_WITH_CODE(lookup_table->count != 0, + "Lookup table is empty", + return -EINVAL); + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */ + for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { + voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd; + if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) + break; + } + + PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count, + "Can't find requested voltage id in vdd_dep_on_socclk table!", + return -EINVAL); + + *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk; + + return 0; +} + +#define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01 +/** +* Get Leakage VDDC based on leakage ID. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0. +*/ +static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint16_t vv_id; + uint32_t vddc = 0; + uint16_t i, j; + uint32_t sclk = 0; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table = + table_info->vdd_dep_on_socclk; + int result; + + for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) { + vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + + if (!vega10_get_socclk_for_voltage_evv(hwmgr, + table_info->vddc_lookup_table, vv_id, &sclk)) { + if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) { + for (j = 1; j < socclk_table->count; j++) { + if (socclk_table->entries[j].clk == sclk && + socclk_table->entries[j].cks_enable == 0) { + sclk += 5000; + break; + } + } + } + + PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, + VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc), + "Error retrieving EVV voltage value!", + continue); + + + /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ + PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0), + "Invalid VDDC value", result = -EINVAL;); + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddc != 0 && vddc != vv_id) { + data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100); + data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; + data->vddc_leakage.count++; + } + } + } + + return 0; +} + +/** + * Change virtual leakage voltage to actual value. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to changing voltage + * @param pointer to leakage table + */ +static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr, + uint16_t *voltage, struct vega10_leakage_voltage *leakage_table) +{ + uint32_t index; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 */ + for (index = 0; index < leakage_table->count; index++) { + /* if this voltage matches a leakage voltage ID */ + /* patch with actual leakage voltage */ + if (leakage_table->leakage_id[index] == *voltage) { + *voltage = leakage_table->actual_voltage[index]; + break; + } + } + + if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) + pr_info("Voltage value looks like a Leakage ID but it's not patched\n"); +} + +/** +* Patch voltage lookup table by EVV leakages. +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pointer to voltage lookup table +* @param pointer to leakage table +* @return always 0 +*/ +static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + struct vega10_leakage_voltage *leakage_table) +{ + uint32_t i; + + for (i = 0; i < lookup_table->count; i++) + vega10_patch_with_vdd_leakage(hwmgr, + &lookup_table->entries[i].us_vdd, leakage_table); + + return 0; +} + +static int vega10_patch_clock_voltage_limits_with_vddc_leakage( + struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table, + uint16_t *vddc) +{ + vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); + + return 0; +} +#endif + +static int vega10_patch_voltage_dependency_tables_with_lookup_table( + struct pp_hwmgr *hwmgr) +{ + uint8_t entry_id, voltage_id; + unsigned i; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = + table_info->vdd_dep_on_mclk; + + for (i = 0; i < 6; i++) { + struct phm_ppt_v1_clock_voltage_dependency_table *vdt; + switch (i) { + case 0: vdt = table_info->vdd_dep_on_socclk; break; + case 1: vdt = table_info->vdd_dep_on_sclk; break; + case 2: vdt = table_info->vdd_dep_on_dcefclk; break; + case 3: vdt = table_info->vdd_dep_on_pixclk; break; + case 4: vdt = table_info->vdd_dep_on_dispclk; break; + case 5: vdt = table_info->vdd_dep_on_phyclk; break; + } + + for (entry_id = 0; entry_id < vdt->count; entry_id++) { + voltage_id = vdt->entries[entry_id].vddInd; + vdt->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } + } + + for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { + voltage_id = mm_table->entries[entry_id].vddcInd; + mm_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + } + + for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { + voltage_id = mclk_table->entries[entry_id].vddInd; + mclk_table->entries[entry_id].vddc = + table_info->vddc_lookup_table->entries[voltage_id].us_vdd; + voltage_id = mclk_table->entries[entry_id].vddciInd; + mclk_table->entries[entry_id].vddci = + table_info->vddci_lookup_table->entries[voltage_id].us_vdd; + voltage_id = mclk_table->entries[entry_id].mvddInd; + mclk_table->entries[entry_id].mvdd = + table_info->vddmem_lookup_table->entries[voltage_id].us_vdd; + } + + + return 0; + +} + +static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + uint32_t table_size, i, j; + + PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count, + "Lookup table is empty", return -EINVAL); + + table_size = lookup_table->count; + + /* Sorting voltages */ + for (i = 0; i < table_size - 1; i++) { + for (j = i + 1; j > 0; j--) { + if (lookup_table->entries[j].us_vdd < + lookup_table->entries[j - 1].us_vdd) { + swap(lookup_table->entries[j - 1], + lookup_table->entries[j]); + } + } + } + + return 0; +} + +static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr) +{ + int result = 0; + int tmp_result; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); +#ifdef PPLIB_VEGA10_EVV_SUPPORT + struct vega10_hwmgr *data = hwmgr->backend; + + tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr, + table_info->vddc_lookup_table, &(data->vddc_leakage)); + if (tmp_result) + result = tmp_result; + + tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, + &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); + if (tmp_result) + result = tmp_result; +#endif + + tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); + if (tmp_result) + result = tmp_result; + + return result; +} + +static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = + table_info->vdd_dep_on_socclk; + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = + table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table, + "VDD dependency on SCLK table is missing. This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, + "VDD dependency on SCLK table is empty. This table is mandatory", return -EINVAL); + + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table, + "VDD dependency on MCLK table is missing. This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, + "VDD dependency on MCLK table is empty. This table is mandatory", return -EINVAL); + + table_info->max_clock_voltage_on_ac.sclk = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.mclk = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.vddc = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + table_info->max_clock_voltage_on_ac.vddci = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; + + hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = + table_info->max_clock_voltage_on_ac.sclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = + table_info->max_clock_voltage_on_ac.mclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = + table_info->max_clock_voltage_on_ac.vddc; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = + table_info->max_clock_voltage_on_ac.vddci; + + return 0; +} + +static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega10_hwmgr *data; + uint32_t config_telemetry = 0; + struct pp_atomfwctrl_voltage_table vol_table; + struct amdgpu_device *adev = hwmgr->adev; + + data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + + hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; + hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + + vega10_set_default_registry_data(hwmgr); + data->disable_dpm_mask = 0xff; + + /* need to set voltage control types before EVV patching */ + data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE; + data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE; + data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE; + + /* VDDCR_SOC */ + if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) { + if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2, + &vol_table)) { + config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) | + (vol_table.telemetry_offset & 0xff); + data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; + } + } else { + kfree(hwmgr->backend); + hwmgr->backend = NULL; + PP_ASSERT_WITH_CODE(false, + "VDDCR_SOC is not SVID2!", + return -1); + } + + /* MVDDC */ + if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) { + if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2, + &vol_table)) { + config_telemetry |= + ((vol_table.telemetry_slope << 24) & 0xff000000) | + ((vol_table.telemetry_offset << 16) & 0xff0000); + data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; + } + } + + /* VDDCI_MEM */ + if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) { + if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) + data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO; + } + + data->config_telemetry = config_telemetry; + + vega10_set_features_platform_caps(hwmgr); + + vega10_init_dpm_defaults(hwmgr); + +#ifdef PPLIB_VEGA10_EVV_SUPPORT + /* Get leakage voltage based on leakage ID. */ + PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr), + "Get EVV Voltage Failed. Abort Driver loading!", + return -1); +#endif + + /* Patch our voltage dependency table with actual leakage voltage + * We need to perform leakage translation before it's used by other functions + */ + vega10_complete_dependency_tables(hwmgr); + + /* Parse pptable data read from VBIOS */ + vega10_set_private_data_based_on_pptable(hwmgr); + + data->is_tlu_enabled = false; + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + VEGA10_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ + /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ + hwmgr->platform_descriptor.clockStep.engineClock = 500; + hwmgr->platform_descriptor.clockStep.memoryClock = 500; + + data->total_active_cus = adev->gfx.cu_info.number; + if (!hwmgr->not_vf) + return result; + + /* Setup default Overdrive Fan control settings */ + data->odn_fan_table.target_fan_speed = + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM; + data->odn_fan_table.target_temperature = + hwmgr->thermal_controller. + advanceFanControlParameters.ucTargetTemperature; + data->odn_fan_table.min_performance_clock = + hwmgr->thermal_controller.advanceFanControlParameters. + ulMinFanSCLKAcousticLimit; + data->odn_fan_table.min_fan_limit = + hwmgr->thermal_controller. + advanceFanControlParameters.usFanPWMMinLimit * + hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100; + + data->mem_channels = (RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0) & + DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >> + DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; + PP_ASSERT_WITH_CODE(data->mem_channels < ARRAY_SIZE(channel_number), + "Mem Channel Index Exceeded maximum!", + return -EINVAL); + + return result; +} + +static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->low_sclk_interrupt_threshold = 0; + + return 0; +} + +static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + + struct pp_atomfwctrl_voltage_table table; + uint8_t i, j; + uint32_t mask = 0; + uint32_t tmp; + int32_t ret = 0; + + ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM, + VOLTAGE_OBJ_GPIO_LUT, &table); + + if (!ret) { + tmp = table.mask_low; + for (i = 0, j = 0; i < 32; i++) { + if (tmp & 1) { + mask |= (uint32_t)(i << (8 * j)); + if (++j >= 3) + break; + } + tmp >>= 1; + } + } + + pp_table->LedPin0 = (uint8_t)(mask & 0xff); + pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff); + pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff); + return 0; +} + +static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->not_vf) + return 0; + + PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr), + "Failed to init sclk threshold!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr), + "Failed to set up led dpm config!", + return -EINVAL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, + 0, + NULL); + + return 0; +} + +/** +* Remove repeated voltage values and create table with unique values. +* +* @param hwmgr the address of the powerplay hardware manager. +* @param vol_table the pointer to changing voltage table +* @return 0 in success +*/ + +static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr, + struct pp_atomfwctrl_voltage_table *vol_table) +{ + uint32_t i, j; + uint16_t vvalue; + bool found = false; + struct pp_atomfwctrl_voltage_table *table; + + PP_ASSERT_WITH_CODE(vol_table, + "Voltage Table empty.", return -EINVAL); + table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table), + GFP_KERNEL); + + if (!table) + return -ENOMEM; + + table->mask_low = vol_table->mask_low; + table->phase_delay = vol_table->phase_delay; + + for (i = 0; i < vol_table->count; i++) { + vvalue = vol_table->entries[i].value; + found = false; + + for (j = 0; j < table->count; j++) { + if (vvalue == table->entries[j].value) { + found = true; + break; + } + } + + if (!found) { + table->entries[table->count].value = vvalue; + table->entries[table->count].smio_low = + vol_table->entries[i].smio_low; + table->count++; + } + } + + memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table)); + kfree(table); + + return 0; +} + +static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *dep_table, + struct pp_atomfwctrl_voltage_table *vol_table) +{ + int i; + + PP_ASSERT_WITH_CODE(dep_table->count, + "Voltage Dependency Table empty.", + return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < vol_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].mvdd; + vol_table->entries[i].smio_low = 0; + } + + PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, + vol_table), + "Failed to trim MVDD Table!", + return -1); + + return 0; +} + +static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *dep_table, + struct pp_atomfwctrl_voltage_table *vol_table) +{ + uint32_t i; + + PP_ASSERT_WITH_CODE(dep_table->count, + "Voltage Dependency Table empty.", + return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].vddci; + vol_table->entries[i].smio_low = 0; + } + + PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table), + "Failed to trim VDDCI table.", + return -1); + + return 0; +} + +static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *dep_table, + struct pp_atomfwctrl_voltage_table *vol_table) +{ + int i; + + PP_ASSERT_WITH_CODE(dep_table->count, + "Voltage Dependency Table empty.", + return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < vol_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].vddc; + vol_table->entries[i].smio_low = 0; + } + + return 0; +} + +/* ---- Voltage Tables ---- + * If the voltage table would be bigger than + * what will fit into the state table on + * the SMC keep only the higher entries. + */ +static void vega10_trim_voltage_table_to_fit_state_table( + struct pp_hwmgr *hwmgr, + uint32_t max_vol_steps, + struct pp_atomfwctrl_voltage_table *vol_table) +{ + unsigned int i, diff; + + if (vol_table->count <= max_vol_steps) + return; + + diff = vol_table->count - max_vol_steps; + + for (i = 0; i < max_vol_steps; i++) + vol_table->entries[i] = vol_table->entries[i + diff]; + + vol_table->count = max_vol_steps; +} + +/** +* Create Voltage Tables. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + int result; + + if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || + data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) { + result = vega10_get_mvdd_voltage_table(hwmgr, + table_info->vdd_dep_on_mclk, + &(data->mvdd_voltage_table)); + PP_ASSERT_WITH_CODE(!result, + "Failed to retrieve MVDDC table!", + return result); + } + + if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) { + result = vega10_get_vddci_voltage_table(hwmgr, + table_info->vdd_dep_on_mclk, + &(data->vddci_voltage_table)); + PP_ASSERT_WITH_CODE(!result, + "Failed to retrieve VDDCI_MEM table!", + return result); + } + + if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || + data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) { + result = vega10_get_vdd_voltage_table(hwmgr, + table_info->vdd_dep_on_sclk, + &(data->vddc_voltage_table)); + PP_ASSERT_WITH_CODE(!result, + "Failed to retrieve VDDCR_SOC table!", + return result); + } + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16, + "Too many voltage values for VDDC. Trimming to fit state table.", + vega10_trim_voltage_table_to_fit_state_table(hwmgr, + 16, &(data->vddc_voltage_table))); + + PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16, + "Too many voltage values for VDDCI. Trimming to fit state table.", + vega10_trim_voltage_table_to_fit_state_table(hwmgr, + 16, &(data->vddci_voltage_table))); + + PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16, + "Too many voltage values for MVDD. Trimming to fit state table.", + vega10_trim_voltage_table_to_fit_state_table(hwmgr, + 16, &(data->mvdd_voltage_table))); + + + return 0; +} + +/* + * @fn vega10_init_dpm_state + * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. + * + * @param dpm_state - the address of the DPM Table to initiailize. + * @return None. + */ +static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state) +{ + dpm_state->soft_min_level = 0xff; + dpm_state->soft_max_level = 0xff; + dpm_state->hard_min_level = 0xff; + dpm_state->hard_max_level = 0xff; +} + +static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr, + struct vega10_single_dpm_table *dpm_table, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + int i; + + dpm_table->count = 0; + + for (i = 0; i < dep_table->count; i++) { + if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <= + dep_table->entries[i].clk) { + dpm_table->dpm_levels[dpm_table->count].value = + dep_table->entries[i].clk; + dpm_table->dpm_levels[dpm_table->count].enabled = true; + dpm_table->count++; + } + } +} +static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *bios_pcie_table = + table_info->pcie_table; + uint32_t i; + + PP_ASSERT_WITH_CODE(bios_pcie_table->count, + "Incorrect number of PCIE States from VBIOS!", + return -1); + + for (i = 0; i < NUM_LINK_LEVELS; i++) { + if (data->registry_data.pcieSpeedOverride) + pcie_table->pcie_gen[i] = + data->registry_data.pcieSpeedOverride; + else + pcie_table->pcie_gen[i] = + bios_pcie_table->entries[i].gen_speed; + + if (data->registry_data.pcieLaneOverride) + pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( + data->registry_data.pcieLaneOverride); + else + pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( + bios_pcie_table->entries[i].lane_width); + if (data->registry_data.pcieClockOverride) + pcie_table->lclk[i] = + data->registry_data.pcieClockOverride; + else + pcie_table->lclk[i] = + bios_pcie_table->entries[i].pcie_sclk; + } + + pcie_table->count = NUM_LINK_LEVELS; + + return 0; +} + +/* + * This function is to initialize all DPM state tables + * for SMU based on the dependency table. + * Dynamic state patching function will then trim these + * state tables to the allowed range based + * on the power policy or external client requests, + * such as UVD request, etc. + */ +static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct vega10_single_dpm_table *dpm_table; + uint32_t i; + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table = + table_info->vdd_dep_on_socclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table = + table_info->mm_dep_table; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table = + table_info->vdd_dep_on_dcefclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table = + table_info->vdd_dep_on_pixclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table = + table_info->vdd_dep_on_dispclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table = + table_info->vdd_dep_on_phyclk; + + PP_ASSERT_WITH_CODE(dep_soc_table, + "SOCCLK dependency table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1, + "SOCCLK dependency table is empty. This table is mandatory", + return -EINVAL); + + PP_ASSERT_WITH_CODE(dep_gfx_table, + "GFXCLK dependency table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1, + "GFXCLK dependency table is empty. This table is mandatory", + return -EINVAL); + + PP_ASSERT_WITH_CODE(dep_mclk_table, + "MCLK dependency table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, + "MCLK dependency table has to have is missing. This table is mandatory", + return -EINVAL); + + /* Initialize Sclk DPM table based on allow Sclk values */ + dpm_table = &(data->dpm_table.soc_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_soc_table); + + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + dpm_table = &(data->dpm_table.gfx_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_gfx_table); + if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) + hwmgr->platform_descriptor.overdriveLimit.engineClock = + dpm_table->dpm_levels[dpm_table->count-1].value; + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + /* Initialize Mclk DPM table based on allow Mclk values */ + data->dpm_table.mem_table.count = 0; + dpm_table = &(data->dpm_table.mem_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_mclk_table); + if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + dpm_table->dpm_levels[dpm_table->count-1].value; + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + data->dpm_table.eclk_table.count = 0; + dpm_table = &(data->dpm_table.eclk_table); + for (i = 0; i < dep_mm_table->count; i++) { + if (i == 0 || dpm_table->dpm_levels + [dpm_table->count - 1].value <= + dep_mm_table->entries[i].eclk) { + dpm_table->dpm_levels[dpm_table->count].value = + dep_mm_table->entries[i].eclk; + dpm_table->dpm_levels[dpm_table->count].enabled = + (i == 0) ? true : false; + dpm_table->count++; + } + } + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + data->dpm_table.vclk_table.count = 0; + data->dpm_table.dclk_table.count = 0; + dpm_table = &(data->dpm_table.vclk_table); + for (i = 0; i < dep_mm_table->count; i++) { + if (i == 0 || dpm_table->dpm_levels + [dpm_table->count - 1].value <= + dep_mm_table->entries[i].vclk) { + dpm_table->dpm_levels[dpm_table->count].value = + dep_mm_table->entries[i].vclk; + dpm_table->dpm_levels[dpm_table->count].enabled = + (i == 0) ? true : false; + dpm_table->count++; + } + } + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + dpm_table = &(data->dpm_table.dclk_table); + for (i = 0; i < dep_mm_table->count; i++) { + if (i == 0 || dpm_table->dpm_levels + [dpm_table->count - 1].value <= + dep_mm_table->entries[i].dclk) { + dpm_table->dpm_levels[dpm_table->count].value = + dep_mm_table->entries[i].dclk; + dpm_table->dpm_levels[dpm_table->count].enabled = + (i == 0) ? true : false; + dpm_table->count++; + } + } + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + /* Assume there is no headless Vega10 for now */ + dpm_table = &(data->dpm_table.dcef_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_dcef_table); + + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + dpm_table = &(data->dpm_table.pixel_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_pix_table); + + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + dpm_table = &(data->dpm_table.display_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_disp_table); + + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + dpm_table = &(data->dpm_table.phy_table); + vega10_setup_default_single_dpm_table(hwmgr, + dpm_table, + dep_phy_table); + + vega10_init_dpm_state(&(dpm_table->dpm_state)); + + vega10_setup_default_pcie_table(hwmgr); + + /* Zero out the saved copy of the CUSTOM profile + * This will be checked when trying to set the profile + * and will require that new values be passed in + */ + data->custom_profile_mode[0] = 0; + data->custom_profile_mode[1] = 0; + data->custom_profile_mode[2] = 0; + data->custom_profile_mode[3] = 0; + + /* save a copy of the default DPM table */ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), + sizeof(struct vega10_dpm_table)); + + return 0; +} + +/* + * @fn vega10_populate_ulv_state + * @brief Function to provide parameters for Utral Low Voltage state to SMC. + * + * @param hwmgr - the address of the hardware manager. + * @return Always 0. + */ +static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + data->smc_state_table.pp_table.UlvOffsetVid = + (uint8_t)table_info->us_ulv_voltage_offset; + + data->smc_state_table.pp_table.UlvSmnclkDid = + (uint8_t)(table_info->us_ulv_smnclk_did); + data->smc_state_table.pp_table.UlvMp1clkDid = + (uint8_t)(table_info->us_ulv_mp1clk_did); + data->smc_state_table.pp_table.UlvGfxclkBypass = + (uint8_t)(table_info->us_ulv_gfxclk_bypass); + data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 = + (uint8_t)(data->vddc_voltage_table.psi0_enable); + data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 = + (uint8_t)(data->vddc_voltage_table.psi1_enable); + + return 0; +} + +static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr, + uint32_t lclock, uint8_t *curr_lclk_did) +{ + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( + hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, + lclock, ÷rs), + "Failed to get LCLK clock settings from VBIOS!", + return -1); + + *curr_lclk_did = dividers.ulDid; + + return 0; +} + +static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr) +{ + int result = -1; + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega10_pcie_table *pcie_table = + &(data->dpm_table.pcie_table); + uint32_t i, j; + + for (i = 0; i < pcie_table->count; i++) { + pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i]; + pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i]; + + result = vega10_populate_single_lclk_level(hwmgr, + pcie_table->lclk[i], &(pp_table->LclkDid[i])); + if (result) { + pr_info("Populate LClock Level %d Failed!\n", i); + return result; + } + } + + j = i - 1; + while (i < NUM_LINK_LEVELS) { + pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j]; + pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j]; + + result = vega10_populate_single_lclk_level(hwmgr, + pcie_table->lclk[j], &(pp_table->LclkDid[i])); + if (result) { + pr_info("Populate LClock Level %d Failed!\n", i); + return result; + } + i++; + } + + return result; +} + +/** +* Populates single SMC GFXSCLK structure using the provided engine clock +* +* @param hwmgr the address of the hardware manager +* @param gfx_clock the GFX clock to use to populate the structure. +* @param current_gfxclk_level location in PPTable for the SMC GFXCLK structure. +*/ + +static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr, + uint32_t gfx_clock, PllSetting_t *current_gfxclk_level, + uint32_t *acg_freq) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk; + struct vega10_hwmgr *data = hwmgr->backend; + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + uint32_t gfx_max_clock = + hwmgr->platform_descriptor.overdriveLimit.engineClock; + uint32_t i = 0; + + if (hwmgr->od_enabled) + dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) + &(data->odn_dpm_table.vdd_dep_on_sclk); + else + dep_on_sclk = table_info->vdd_dep_on_sclk; + + PP_ASSERT_WITH_CODE(dep_on_sclk, + "Invalid SOC_VDD-GFX_CLK Dependency Table!", + return -EINVAL); + + if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) + gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock; + else { + for (i = 0; i < dep_on_sclk->count; i++) { + if (dep_on_sclk->entries[i].clk == gfx_clock) + break; + } + PP_ASSERT_WITH_CODE(dep_on_sclk->count > i, + "Cannot find gfx_clk in SOC_VDD-GFX_CLK!", + return -EINVAL); + } + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK, + gfx_clock, ÷rs), + "Failed to get GFX Clock settings from VBIOS!", + return -EINVAL); + + /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */ + current_gfxclk_level->FbMult = + cpu_to_le32(dividers.ulPll_fb_mult); + /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */ + current_gfxclk_level->SsOn = dividers.ucPll_ss_enable; + current_gfxclk_level->SsFbMult = + cpu_to_le32(dividers.ulPll_ss_fbsmult); + current_gfxclk_level->SsSlewFrac = + cpu_to_le16(dividers.usPll_ss_slew_frac); + current_gfxclk_level->Did = (uint8_t)(dividers.ulDid); + + *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */ + + return 0; +} + +/** + * @brief Populates single SMC SOCCLK structure using the provided clock. + * + * @param hwmgr - the address of the hardware manager. + * @param soc_clock - the SOC clock to use to populate the structure. + * @param current_socclk_level - location in PPTable for the SMC SOCCLK structure. + * @return 0 on success.. + */ +static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr, + uint32_t soc_clock, uint8_t *current_soc_did, + uint8_t *current_vol_index) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc; + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + uint32_t i; + + if (hwmgr->od_enabled) { + dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *) + &data->odn_dpm_table.vdd_dep_on_socclk; + for (i = 0; i < dep_on_soc->count; i++) { + if (dep_on_soc->entries[i].clk >= soc_clock) + break; + } + } else { + dep_on_soc = table_info->vdd_dep_on_socclk; + for (i = 0; i < dep_on_soc->count; i++) { + if (dep_on_soc->entries[i].clk == soc_clock) + break; + } + } + + PP_ASSERT_WITH_CODE(dep_on_soc->count > i, + "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, + soc_clock, ÷rs), + "Failed to get SOC Clock settings from VBIOS!", + return -EINVAL); + + *current_soc_did = (uint8_t)dividers.ulDid; + *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd); + return 0; +} + +/** +* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states +* +* @param hwmgr the address of the hardware manager +*/ +static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); + int result = 0; + uint32_t i, j; + + for (i = 0; i < dpm_table->count; i++) { + result = vega10_populate_single_gfx_level(hwmgr, + dpm_table->dpm_levels[i].value, + &(pp_table->GfxclkLevel[i]), + &(pp_table->AcgFreqTable[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_GFXCLK_DPM_LEVELS) { + result = vega10_populate_single_gfx_level(hwmgr, + dpm_table->dpm_levels[j].value, + &(pp_table->GfxclkLevel[i]), + &(pp_table->AcgFreqTable[i])); + if (result) + return result; + i++; + } + + pp_table->GfxclkSlewRate = + cpu_to_le16(table_info->us_gfxclk_slew_rate); + + dpm_table = &(data->dpm_table.soc_table); + for (i = 0; i < dpm_table->count; i++) { + result = vega10_populate_single_soc_level(hwmgr, + dpm_table->dpm_levels[i].value, + &(pp_table->SocclkDid[i]), + &(pp_table->SocDpmVoltageIndex[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_SOCCLK_DPM_LEVELS) { + result = vega10_populate_single_soc_level(hwmgr, + dpm_table->dpm_levels[j].value, + &(pp_table->SocclkDid[i]), + &(pp_table->SocDpmVoltageIndex[i])); + if (result) + return result; + i++; + } + + return result; +} + +static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct phm_ppt_v2_information *table_info = hwmgr->pptable; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; + + uint8_t soc_vid = 0; + uint32_t i, max_vddc_level; + + if (hwmgr->od_enabled) + vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table; + else + vddc_lookup_table = table_info->vddc_lookup_table; + + max_vddc_level = vddc_lookup_table->count; + for (i = 0; i < max_vddc_level; i++) { + soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd); + pp_table->SocVid[i] = soc_vid; + } + while (i < MAX_REGULAR_DPM_NUMBER) { + pp_table->SocVid[i] = soc_vid; + i++; + } +} + +/** + * @brief Populates single SMC GFXCLK structure using the provided clock. + * + * @param hwmgr - the address of the hardware manager. + * @param mem_clock - the memory clock to use to populate the structure. + * @return 0 on success.. + */ +static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t mem_clock, uint8_t *current_mem_vid, + PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk; + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + uint32_t mem_max_clock = + hwmgr->platform_descriptor.overdriveLimit.memoryClock; + uint32_t i = 0; + + if (hwmgr->od_enabled) + dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) + &data->odn_dpm_table.vdd_dep_on_mclk; + else + dep_on_mclk = table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(dep_on_mclk, + "Invalid SOC_VDD-UCLK Dependency Table!", + return -EINVAL); + + if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { + mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock; + } else { + for (i = 0; i < dep_on_mclk->count; i++) { + if (dep_on_mclk->entries[i].clk == mem_clock) + break; + } + PP_ASSERT_WITH_CODE(dep_on_mclk->count > i, + "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!", + return -EINVAL); + } + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( + hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, ÷rs), + "Failed to get UCLK settings from VBIOS!", + return -1); + + *current_mem_vid = + (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd)); + *current_mem_soc_vind = + (uint8_t)(dep_on_mclk->entries[i].vddInd); + current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult); + current_memclk_level->Did = (uint8_t)(dividers.ulDid); + + PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1, + "Invalid Divider ID!", + return -EINVAL); + + return 0; +} + +/** + * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states. + * + * @param pHwMgr - the address of the hardware manager. + * @return PP_Result_OK on success. + */ +static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega10_single_dpm_table *dpm_table = + &(data->dpm_table.mem_table); + int result = 0; + uint32_t i, j; + + for (i = 0; i < dpm_table->count; i++) { + result = vega10_populate_single_memory_level(hwmgr, + dpm_table->dpm_levels[i].value, + &(pp_table->MemVid[i]), + &(pp_table->UclkLevel[i]), + &(pp_table->MemSocVoltageIndex[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_UCLK_DPM_LEVELS) { + result = vega10_populate_single_memory_level(hwmgr, + dpm_table->dpm_levels[j].value, + &(pp_table->MemVid[i]), + &(pp_table->UclkLevel[i]), + &(pp_table->MemSocVoltageIndex[i])); + if (result) + return result; + i++; + } + + pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels); + pp_table->MemoryChannelWidth = + (uint16_t)(HBM_MEMORY_CHANNEL_WIDTH * + channel_number[data->mem_channels]); + + pp_table->LowestUclkReservedForUlv = + (uint8_t)(data->lowest_uclk_reserved_for_ulv); + + return result; +} + +static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr, + DSPCLK_e disp_clock) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *) + (hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; + uint32_t i; + uint16_t clk = 0, vddc = 0; + uint8_t vid = 0; + + switch (disp_clock) { + case DSPCLK_DCEFCLK: + dep_table = table_info->vdd_dep_on_dcefclk; + break; + case DSPCLK_DISPCLK: + dep_table = table_info->vdd_dep_on_dispclk; + break; + case DSPCLK_PIXCLK: + dep_table = table_info->vdd_dep_on_pixclk; + break; + case DSPCLK_PHYCLK: + dep_table = table_info->vdd_dep_on_phyclk; + break; + default: + return -1; + } + + PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS, + "Number Of Entries Exceeded maximum!", + return -1); + + for (i = 0; i < dep_table->count; i++) { + clk = (uint16_t)(dep_table->entries[i].clk / 100); + vddc = table_info->vddc_lookup_table-> + entries[dep_table->entries[i].vddInd].us_vdd; + vid = (uint8_t)convert_to_vid(vddc); + pp_table->DisplayClockTable[disp_clock][i].Freq = + cpu_to_le16(clk); + pp_table->DisplayClockTable[disp_clock][i].Vid = + cpu_to_le16(vid); + } + + while (i < NUM_DSPCLK_LEVELS) { + pp_table->DisplayClockTable[disp_clock][i].Freq = + cpu_to_le16(clk); + pp_table->DisplayClockTable[disp_clock][i].Vid = + cpu_to_le16(vid); + i++; + } + + return 0; +} + +static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr) +{ + uint32_t i; + + for (i = 0; i < DSPCLK_COUNT; i++) { + PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i), + "Failed to populate Clock in DisplayClockTable!", + return -1); + } + + return 0; +} + +static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr, + uint32_t eclock, uint8_t *current_eclk_did, + uint8_t *current_soc_vol) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = + table_info->mm_dep_table; + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + uint32_t i; + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, + eclock, ÷rs), + "Failed to get ECLK clock settings from VBIOS!", + return -1); + + *current_eclk_did = (uint8_t)dividers.ulDid; + + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].eclk == eclock) + *current_soc_vol = dep_table->entries[i].vddcInd; + } + + return 0; +} + +static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table); + int result = -EINVAL; + uint32_t i, j; + + for (i = 0; i < dpm_table->count; i++) { + result = vega10_populate_single_eclock_level(hwmgr, + dpm_table->dpm_levels[i].value, + &(pp_table->EclkDid[i]), + &(pp_table->VceDpmVoltageIndex[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_VCE_DPM_LEVELS) { + result = vega10_populate_single_eclock_level(hwmgr, + dpm_table->dpm_levels[j].value, + &(pp_table->EclkDid[i]), + &(pp_table->VceDpmVoltageIndex[i])); + if (result) + return result; + i++; + } + + return result; +} + +static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr, + uint32_t vclock, uint8_t *current_vclk_did) +{ + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, + vclock, ÷rs), + "Failed to get VCLK clock settings from VBIOS!", + return -EINVAL); + + *current_vclk_did = (uint8_t)dividers.ulDid; + + return 0; +} + +static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr, + uint32_t dclock, uint8_t *current_dclk_did) +{ + struct pp_atomfwctrl_clock_dividers_soc15 dividers; + + PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, + dclock, ÷rs), + "Failed to get DCLK clock settings from VBIOS!", + return -EINVAL); + + *current_dclk_did = (uint8_t)dividers.ulDid; + + return 0; +} + +static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega10_single_dpm_table *vclk_dpm_table = + &(data->dpm_table.vclk_table); + struct vega10_single_dpm_table *dclk_dpm_table = + &(data->dpm_table.dclk_table); + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = + table_info->mm_dep_table; + int result = -EINVAL; + uint32_t i, j; + + for (i = 0; i < vclk_dpm_table->count; i++) { + result = vega10_populate_single_vclock_level(hwmgr, + vclk_dpm_table->dpm_levels[i].value, + &(pp_table->VclkDid[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_UVD_DPM_LEVELS) { + result = vega10_populate_single_vclock_level(hwmgr, + vclk_dpm_table->dpm_levels[j].value, + &(pp_table->VclkDid[i])); + if (result) + return result; + i++; + } + + for (i = 0; i < dclk_dpm_table->count; i++) { + result = vega10_populate_single_dclock_level(hwmgr, + dclk_dpm_table->dpm_levels[i].value, + &(pp_table->DclkDid[i])); + if (result) + return result; + } + + j = i - 1; + while (i < NUM_UVD_DPM_LEVELS) { + result = vega10_populate_single_dclock_level(hwmgr, + dclk_dpm_table->dpm_levels[j].value, + &(pp_table->DclkDid[i])); + if (result) + return result; + i++; + } + + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vclk == + vclk_dpm_table->dpm_levels[i].value && + dep_table->entries[i].dclk == + dclk_dpm_table->dpm_levels[i].value) + pp_table->UvdDpmVoltageIndex[i] = + dep_table->entries[i].vddcInd; + else + return -1; + } + + j = i - 1; + while (i < NUM_UVD_DPM_LEVELS) { + pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd; + i++; + } + + return 0; +} + +static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_sclk; + uint32_t i; + + for (i = 0; i < dep_table->count; i++) { + pp_table->CksEnable[i] = dep_table->entries[i].cks_enable; + pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset + * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + } + + return 0; +} + +static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_sclk; + struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; + int result = 0; + uint32_t i; + + pp_table->MinVoltageVid = (uint8_t)0xff; + pp_table->MaxVoltageVid = (uint8_t)0; + + if (data->smu_features[GNLD_AVFS].supported) { + result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); + if (!result) { + pp_table->MinVoltageVid = (uint8_t) + convert_to_vid((uint16_t)(avfs_params.ulMinVddc)); + pp_table->MaxVoltageVid = (uint8_t) + convert_to_vid((uint16_t)(avfs_params.ulMaxVddc)); + + pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0); + pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1); + pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2); + pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); + pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean); + pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); + pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor); + + pp_table->BtcGbVdroopTableCksOff.a0 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0); + pp_table->BtcGbVdroopTableCksOff.a0_shift = 20; + pp_table->BtcGbVdroopTableCksOff.a1 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1); + pp_table->BtcGbVdroopTableCksOff.a1_shift = 20; + pp_table->BtcGbVdroopTableCksOff.a2 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2); + pp_table->BtcGbVdroopTableCksOff.a2_shift = 20; + + pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson; + pp_table->BtcGbVdroopTableCksOn.a0 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0); + pp_table->BtcGbVdroopTableCksOn.a0_shift = 20; + pp_table->BtcGbVdroopTableCksOn.a1 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1); + pp_table->BtcGbVdroopTableCksOn.a1_shift = 20; + pp_table->BtcGbVdroopTableCksOn.a2 = + cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2); + pp_table->BtcGbVdroopTableCksOn.a2_shift = 20; + + pp_table->AvfsGbCksOn.m1 = + cpu_to_le32(avfs_params.ulGbFuseTableCksonM1); + pp_table->AvfsGbCksOn.m2 = + cpu_to_le32(avfs_params.ulGbFuseTableCksonM2); + pp_table->AvfsGbCksOn.b = + cpu_to_le32(avfs_params.ulGbFuseTableCksonB); + pp_table->AvfsGbCksOn.m1_shift = 24; + pp_table->AvfsGbCksOn.m2_shift = 12; + pp_table->AvfsGbCksOn.b_shift = 0; + + pp_table->OverrideAvfsGbCksOn = + avfs_params.ucEnableGbFuseTableCkson; + pp_table->AvfsGbCksOff.m1 = + cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1); + pp_table->AvfsGbCksOff.m2 = + cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2); + pp_table->AvfsGbCksOff.b = + cpu_to_le32(avfs_params.ulGbFuseTableCksoffB); + pp_table->AvfsGbCksOff.m1_shift = 24; + pp_table->AvfsGbCksOff.m2_shift = 12; + pp_table->AvfsGbCksOff.b_shift = 0; + + for (i = 0; i < dep_table->count; i++) + pp_table->StaticVoltageOffsetVid[i] = + convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset)); + + if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->disp_clk_quad_eqn_a) && + (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->disp_clk_quad_eqn_b)) { + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = + (int32_t)data->disp_clk_quad_eqn_a; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = + (int32_t)data->disp_clk_quad_eqn_b; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = + (int32_t)data->disp_clk_quad_eqn_c; + } else { + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = + (int32_t)avfs_params.ulDispclk2GfxclkM1; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = + (int32_t)avfs_params.ulDispclk2GfxclkM2; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = + (int32_t)avfs_params.ulDispclk2GfxclkB; + } + + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12; + + if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->dcef_clk_quad_eqn_a) && + (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->dcef_clk_quad_eqn_b)) { + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = + (int32_t)data->dcef_clk_quad_eqn_a; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = + (int32_t)data->dcef_clk_quad_eqn_b; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = + (int32_t)data->dcef_clk_quad_eqn_c; + } else { + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = + (int32_t)avfs_params.ulDcefclk2GfxclkM1; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = + (int32_t)avfs_params.ulDcefclk2GfxclkM2; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = + (int32_t)avfs_params.ulDcefclk2GfxclkB; + } + + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12; + + if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->pixel_clk_quad_eqn_a) && + (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->pixel_clk_quad_eqn_b)) { + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = + (int32_t)data->pixel_clk_quad_eqn_a; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = + (int32_t)data->pixel_clk_quad_eqn_b; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = + (int32_t)data->pixel_clk_quad_eqn_c; + } else { + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = + (int32_t)avfs_params.ulPixelclk2GfxclkM1; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = + (int32_t)avfs_params.ulPixelclk2GfxclkM2; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = + (int32_t)avfs_params.ulPixelclk2GfxclkB; + } + + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12; + if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->phy_clk_quad_eqn_a) && + (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != + data->phy_clk_quad_eqn_b)) { + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = + (int32_t)data->phy_clk_quad_eqn_a; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = + (int32_t)data->phy_clk_quad_eqn_b; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = + (int32_t)data->phy_clk_quad_eqn_c; + } else { + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = + (int32_t)avfs_params.ulPhyclk2GfxclkM1; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = + (int32_t)avfs_params.ulPhyclk2GfxclkM2; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = + (int32_t)avfs_params.ulPhyclk2GfxclkB; + } + + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; + pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12; + + pp_table->AcgBtcGbVdroopTable.a0 = avfs_params.ulAcgGbVdroopTableA0; + pp_table->AcgBtcGbVdroopTable.a0_shift = 20; + pp_table->AcgBtcGbVdroopTable.a1 = avfs_params.ulAcgGbVdroopTableA1; + pp_table->AcgBtcGbVdroopTable.a1_shift = 20; + pp_table->AcgBtcGbVdroopTable.a2 = avfs_params.ulAcgGbVdroopTableA2; + pp_table->AcgBtcGbVdroopTable.a2_shift = 20; + + pp_table->AcgAvfsGb.m1 = avfs_params.ulAcgGbFuseTableM1; + pp_table->AcgAvfsGb.m2 = avfs_params.ulAcgGbFuseTableM2; + pp_table->AcgAvfsGb.b = avfs_params.ulAcgGbFuseTableB; + pp_table->AcgAvfsGb.m1_shift = 24; + pp_table->AcgAvfsGb.m2_shift = 12; + pp_table->AcgAvfsGb.b_shift = 0; + + } else { + data->smu_features[GNLD_AVFS].supported = false; + } + } + + return 0; +} + +static int vega10_acg_enable(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t agc_btc_response; + + if (data->smu_features[GNLD_ACG].supported) { + if (0 == vega10_enable_smc_features(hwmgr, true, + data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap)) + data->smu_features[GNLD_DPM_PREFETCHER].enabled = true; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg, NULL); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &agc_btc_response); + + if (1 == agc_btc_response) { + if (1 == data->acg_loop_state) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop, NULL); + else if (2 == data->acg_loop_state) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop, NULL); + if (0 == vega10_enable_smc_features(hwmgr, true, + data->smu_features[GNLD_ACG].smu_feature_bitmap)) + data->smu_features[GNLD_ACG].enabled = true; + } else { + pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n"); + data->smu_features[GNLD_ACG].enabled = false; + } + } + + return 0; +} + +static int vega10_acg_disable(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_ACG].supported && + data->smu_features[GNLD_ACG].enabled) + if (!vega10_enable_smc_features(hwmgr, false, + data->smu_features[GNLD_ACG].smu_feature_bitmap)) + data->smu_features[GNLD_ACG].enabled = false; + + return 0; +} + +static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct pp_atomfwctrl_gpio_parameters gpio_params = {0}; + int result; + + result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params); + if (!result) { + if (PP_CAP(PHM_PlatformCaps_RegulatorHot) && + data->registry_data.regulator_hot_gpio_support) { + pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio; + pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity; + pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio; + pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity; + } else { + pp_table->VR0HotGpio = 0; + pp_table->VR0HotPolarity = 0; + pp_table->VR1HotGpio = 0; + pp_table->VR1HotPolarity = 0; + } + + if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) && + data->registry_data.ac_dc_switch_gpio_support) { + pp_table->AcDcGpio = gpio_params.ucAcDcGpio; + pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity; + } else { + pp_table->AcDcGpio = 0; + pp_table->AcDcPolarity = 0; + } + } + + return result; +} + +static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_AVFS].supported) { + /* Already enabled or disabled */ + if (!(enable ^ data->smu_features[GNLD_AVFS].enabled)) + return 0; + + if (enable) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, + data->smu_features[GNLD_AVFS].smu_feature_bitmap), + "[avfs_control] Attempt to Enable AVFS feature Failed!", + return -1); + data->smu_features[GNLD_AVFS].enabled = true; + } else { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, + data->smu_features[GNLD_AVFS].smu_feature_bitmap), + "[avfs_control] Attempt to Disable AVFS feature Failed!", + return -1); + data->smu_features[GNLD_AVFS].enabled = false; + } + } + + return 0; +} + +static int vega10_update_avfs(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { + vega10_avfs_enable(hwmgr, false); + } else if (data->need_update_dpm_table) { + vega10_avfs_enable(hwmgr, false); + vega10_avfs_enable(hwmgr, true); + } else { + vega10_avfs_enable(hwmgr, true); + } + + return 0; +} + +static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + uint64_t serial_number = 0; + uint32_t top32, bottom32; + struct phm_fuses_default fuse; + + struct vega10_hwmgr *data = hwmgr->backend; + AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); + + serial_number = ((uint64_t)bottom32 << 32) | top32; + + if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) { + avfs_fuse_table->VFT0_b = fuse.VFT0_b; + avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1; + avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2; + avfs_fuse_table->VFT1_b = fuse.VFT1_b; + avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1; + avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2; + avfs_fuse_table->VFT2_b = fuse.VFT2_b; + avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1; + avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2; + result = smum_smc_table_manager(hwmgr, (uint8_t *)avfs_fuse_table, + AVFSFUSETABLE, false); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload FuseOVerride!", + ); + } + + return result; +} + +static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct phm_ppt_v2_information *table_info = hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; + struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; + uint32_t i; + + dep_table = table_info->vdd_dep_on_mclk; + odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk); + + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; + return; + } + } + + dep_table = table_info->vdd_dep_on_sclk; + odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk); + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; + return; + } + } +} + +/** +* Initializes the SMC table and uploads it +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data (PowerState) +* @return always 0 +*/ +static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct pp_atomfwctrl_voltage_table voltage_table; + struct pp_atomfwctrl_bios_boot_up_values boot_up_values; + struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); + + result = vega10_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to setup default DPM tables!", + return result); + + if (!hwmgr->not_vf) + return 0; + + /* initialize ODN table */ + if (hwmgr->od_enabled) { + if (odn_table->max_vddc) { + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; + vega10_check_dpm_table_updated(hwmgr); + } else { + vega10_odn_initial_default_setting(hwmgr); + } + } + + pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC, + VOLTAGE_OBJ_SVID2, &voltage_table); + pp_table->MaxVidStep = voltage_table.max_vid_step; + + pp_table->GfxDpmVoltageMode = + (uint8_t)(table_info->uc_gfx_dpm_voltage_mode); + pp_table->SocDpmVoltageMode = + (uint8_t)(table_info->uc_soc_dpm_voltage_mode); + pp_table->UclkDpmVoltageMode = + (uint8_t)(table_info->uc_uclk_dpm_voltage_mode); + pp_table->UvdDpmVoltageMode = + (uint8_t)(table_info->uc_uvd_dpm_voltage_mode); + pp_table->VceDpmVoltageMode = + (uint8_t)(table_info->uc_vce_dpm_voltage_mode); + pp_table->Mp0DpmVoltageMode = + (uint8_t)(table_info->uc_mp0_dpm_voltage_mode); + + pp_table->DisplayDpmVoltageMode = + (uint8_t)(table_info->uc_dcef_dpm_voltage_mode); + + data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable; + data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable; + + if (data->registry_data.ulv_support && + table_info->us_ulv_voltage_offset) { + result = vega10_populate_ulv_state(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ULV state!", + return result); + } + + result = vega10_populate_smc_link_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Link Level!", + return result); + + result = vega10_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Graphics Level!", + return result); + + result = vega10_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Memory Level!", + return result); + + vega10_populate_vddc_soc_levels(hwmgr); + + result = vega10_populate_all_display_clock_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Display Level!", + return result); + + result = vega10_populate_smc_vce_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize VCE Level!", + return result); + + result = vega10_populate_smc_uvd_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize UVD Level!", + return result); + + if (data->registry_data.clock_stretcher_support) { + result = vega10_populate_clock_stretcher_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate Clock Stretcher Table!", + return result); + } + + result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); + if (!result) { + data->vbios_boot_state.vddc = boot_up_values.usVddc; + data->vbios_boot_state.vddci = boot_up_values.usVddci; + data->vbios_boot_state.mvddc = boot_up_values.usMvddc; + data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; + data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; + pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, + SMU9_SYSPLL0_SOCCLK_ID, 0, &boot_up_values.ulSocClk); + + pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, + SMU9_SYSPLL0_DCEFCLK_ID, 0, &boot_up_values.ulDCEFClk); + + data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; + data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; + if (0 != boot_up_values.usVddc) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFloorSocVoltage, + (boot_up_values.usVddc * 4), + NULL); + data->vbios_boot_state.bsoc_vddc_lock = true; + } else { + data->vbios_boot_state.bsoc_vddc_lock = false; + } + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepDcefclk, + (uint32_t)(data->vbios_boot_state.dcef_clock / 100), + NULL); + } + + result = vega10_populate_avfs_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize AVFS Parameters!", + return result); + + result = vega10_populate_gpio_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize GPIO Parameters!", + return result); + + pp_table->GfxclkAverageAlpha = (uint8_t) + (data->gfxclk_average_alpha); + pp_table->SocclkAverageAlpha = (uint8_t) + (data->socclk_average_alpha); + pp_table->UclkAverageAlpha = (uint8_t) + (data->uclk_average_alpha); + pp_table->GfxActivityAverageAlpha = (uint8_t) + (data->gfx_activity_average_alpha); + + vega10_populate_and_upload_avfs_fuse_override(hwmgr); + + result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); + + PP_ASSERT_WITH_CODE(!result, + "Failed to upload PPtable!", return result); + + result = vega10_avfs_enable(hwmgr, true); + PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!", + return result); + vega10_acg_enable(hwmgr); + + return 0; +} + +static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_THERMAL].supported) { + if (data->smu_features[GNLD_THERMAL].enabled) + pr_info("THERMAL Feature Already enabled!"); + + PP_ASSERT_WITH_CODE( + !vega10_enable_smc_features(hwmgr, + true, + data->smu_features[GNLD_THERMAL].smu_feature_bitmap), + "Enable THERMAL Feature Failed!", + return -1); + data->smu_features[GNLD_THERMAL].enabled = true; + } + + return 0; +} + +static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_THERMAL].supported) { + if (!data->smu_features[GNLD_THERMAL].enabled) + pr_info("THERMAL Feature Already disabled!"); + + PP_ASSERT_WITH_CODE( + !vega10_enable_smc_features(hwmgr, + false, + data->smu_features[GNLD_THERMAL].smu_feature_bitmap), + "disable THERMAL Feature Failed!", + return -1); + data->smu_features[GNLD_THERMAL].enabled = false; + } + + return 0; +} + +static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) { + if (data->smu_features[GNLD_VR0HOT].supported) { + PP_ASSERT_WITH_CODE( + !vega10_enable_smc_features(hwmgr, + true, + data->smu_features[GNLD_VR0HOT].smu_feature_bitmap), + "Attempt to Enable VR0 Hot feature Failed!", + return -1); + data->smu_features[GNLD_VR0HOT].enabled = true; + } else { + if (data->smu_features[GNLD_VR1HOT].supported) { + PP_ASSERT_WITH_CODE( + !vega10_enable_smc_features(hwmgr, + true, + data->smu_features[GNLD_VR1HOT].smu_feature_bitmap), + "Attempt to Enable VR0 Hot feature Failed!", + return -1); + data->smu_features[GNLD_VR1HOT].enabled = true; + } + } + } + return 0; +} + +static int vega10_enable_ulv(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->registry_data.ulv_support) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_ULV].smu_feature_bitmap), + "Enable ULV Feature Failed!", + return -1); + data->smu_features[GNLD_ULV].enabled = true; + } + + return 0; +} + +static int vega10_disable_ulv(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->registry_data.ulv_support) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_ULV].smu_feature_bitmap), + "disable ULV Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_ULV].enabled = false; + } + + return 0; +} + +static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DS_GFXCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), + "Attempt to Enable DS_GFXCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_GFXCLK].enabled = true; + } + + if (data->smu_features[GNLD_DS_SOCCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), + "Attempt to Enable DS_SOCCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_SOCCLK].enabled = true; + } + + if (data->smu_features[GNLD_DS_LCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), + "Attempt to Enable DS_LCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_LCLK].enabled = true; + } + + if (data->smu_features[GNLD_DS_DCEFCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), + "Attempt to Enable DS_DCEFCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_DCEFCLK].enabled = true; + } + + return 0; +} + +static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DS_GFXCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), + "Attempt to disable DS_GFXCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_GFXCLK].enabled = false; + } + + if (data->smu_features[GNLD_DS_SOCCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), + "Attempt to disable DS_ Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_SOCCLK].enabled = false; + } + + if (data->smu_features[GNLD_DS_LCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), + "Attempt to disable DS_LCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_LCLK].enabled = false; + } + + if (data->smu_features[GNLD_DS_DCEFCLK].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), + "Attempt to disable DS_DCEFCLK Feature Failed!", + return -EINVAL); + data->smu_features[GNLD_DS_DCEFCLK].enabled = false; + } + + return 0; +} + +static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t i, feature_mask = 0; + + if (!hwmgr->not_vf) + return 0; + + if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), + "Attempt to disable LED DPM feature failed!", return -EINVAL); + data->smu_features[GNLD_LED_DISPLAY].enabled = false; + } + + for (i = 0; i < GNLD_DPM_MAX; i++) { + if (data->smu_features[i].smu_feature_bitmap & bitmap) { + if (data->smu_features[i].supported) { + if (data->smu_features[i].enabled) { + feature_mask |= data->smu_features[i]. + smu_feature_bitmap; + data->smu_features[i].enabled = false; + } + } + } + } + + vega10_enable_smc_features(hwmgr, false, feature_mask); + + return 0; +} + +/** + * @brief Tell SMC to enabled the supported DPMs. + * + * @param hwmgr - the address of the powerplay hardware manager. + * @Param bitmap - bitmap for the features to enabled. + * @return 0 on at least one DPM is successfully enabled. + */ +static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t i, feature_mask = 0; + + for (i = 0; i < GNLD_DPM_MAX; i++) { + if (data->smu_features[i].smu_feature_bitmap & bitmap) { + if (data->smu_features[i].supported) { + if (!data->smu_features[i].enabled) { + feature_mask |= data->smu_features[i]. + smu_feature_bitmap; + data->smu_features[i].enabled = true; + } + } + } + } + + if (vega10_enable_smc_features(hwmgr, + true, feature_mask)) { + for (i = 0; i < GNLD_DPM_MAX; i++) { + if (data->smu_features[i].smu_feature_bitmap & + feature_mask) + data->smu_features[i].enabled = false; + } + } + + if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), + "Attempt to Enable LED DPM feature Failed!", return -EINVAL); + data->smu_features[GNLD_LED_DISPLAY].enabled = true; + } + + if (data->vbios_boot_state.bsoc_vddc_lock) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFloorSocVoltage, 0, + NULL); + data->vbios_boot_state.bsoc_vddc_lock = false; + } + + if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) { + if (data->smu_features[GNLD_ACDC].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_ACDC].smu_feature_bitmap), + "Attempt to Enable DS_GFXCLK Feature Failed!", + return -1); + data->smu_features[GNLD_ACDC].enabled = true; + } + } + + return 0; +} + +static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_PCC_LIMIT].supported) { + if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled) + pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled"); + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + enable, data->smu_features[GNLD_PCC_LIMIT].smu_feature_bitmap), + "Attempt to Enable PCC Limit feature Failed!", + return -EINVAL); + data->smu_features[GNLD_PCC_LIMIT].enabled = enable; + } + + return 0; +} + +static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + int tmp_result, result = 0; + + if (hwmgr->not_vf) { + vega10_enable_disable_PCC_limit_feature(hwmgr, true); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_ConfigureTelemetry, data->config_telemetry, + NULL); + + tmp_result = vega10_construct_voltage_tables(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to construct voltage tables!", + result = tmp_result); + } + + if (hwmgr->not_vf || hwmgr->pp_one_vf) { + tmp_result = vega10_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to initialize SMC table!", + result = tmp_result); + } + + if (hwmgr->not_vf) { + if (PP_CAP(PHM_PlatformCaps_ThermalController)) { + tmp_result = vega10_enable_thermal_protection(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to enable thermal protection!", + result = tmp_result); + } + + tmp_result = vega10_enable_vrhot_feature(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to enable VR hot feature!", + result = tmp_result); + + tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to enable deep sleep master switch!", + result = tmp_result); + } + + if (hwmgr->not_vf) { + tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to start DPM!", result = tmp_result); + } + + if (hwmgr->not_vf) { + /* enable didt, do not abort if failed didt */ + tmp_result = vega10_enable_didt_config(hwmgr); + PP_ASSERT(!tmp_result, + "Failed to enable didt config!"); + } + + tmp_result = vega10_enable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to enable power containment!", + result = tmp_result); + + if (hwmgr->not_vf) { + tmp_result = vega10_power_control_set_level(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to power control set level!", + result = tmp_result); + + tmp_result = vega10_enable_ulv(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to enable ULV!", + result = tmp_result); + } + + return result; +} + +static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct vega10_power_state); +} + +static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr, + void *state, struct pp_power_state *power_state, + void *pp_table, uint32_t classification_flag) +{ + ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_V2; + struct vega10_power_state *vega10_power_state = + cast_phw_vega10_power_state(&(power_state->hardware)); + struct vega10_performance_level *performance_level; + ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state; + ATOM_Vega10_POWERPLAYTABLE *powerplay_table = + (ATOM_Vega10_POWERPLAYTABLE *)pp_table; + ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = + (ATOM_Vega10_SOCCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); + ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = + (ATOM_Vega10_GFXCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); + ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = + (ATOM_Vega10_MCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + + + /* The following fields are not initialized here: + * id orderedList allStatesList + */ + power_state->classification.ui_label = + (le16_to_cpu(state_entry->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> + ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + power_state->classification.flags = classification_flag; + /* NOTE: There is a classification2 flag in BIOS + * that is not being used right now + */ + power_state->classification.temporary_state = false; + power_state->classification.to_be_deleted = false; + + power_state->validation.disallowOnDC = + ((le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Vega10_DISALLOW_ON_DC) != 0); + + power_state->display.disableFrameModulation = false; + power_state->display.limitRefreshrate = false; + power_state->display.enableVariBright = + ((le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Vega10_ENABLE_VARIBRIGHT) != 0); + + power_state->validation.supportedPowerLevels = 0; + power_state->uvd_clocks.VCLK = 0; + power_state->uvd_clocks.DCLK = 0; + power_state->temperatures.min = 0; + power_state->temperatures.max = 0; + + performance_level = &(vega10_power_state->performance_levels + [vega10_power_state->performance_level_count++]); + + PP_ASSERT_WITH_CODE( + (vega10_power_state->performance_level_count < + NUM_GFXCLK_DPM_LEVELS), + "Performance levels exceeds SMC limit!", + return -1); + + PP_ASSERT_WITH_CODE( + (vega10_power_state->performance_level_count <= + hwmgr->platform_descriptor. + hardwareActivityPerformanceLevels), + "Performance levels exceeds Driver limit!", + return -1); + + /* Performance levels are arranged from low to high. */ + performance_level->soc_clock = socclk_dep_table->entries + [state_entry->ucSocClockIndexLow].ulClk; + performance_level->gfx_clock = gfxclk_dep_table->entries + [state_entry->ucGfxClockIndexLow].ulClk; + performance_level->mem_clock = mclk_dep_table->entries + [state_entry->ucMemClockIndexLow].ulMemClk; + + performance_level = &(vega10_power_state->performance_levels + [vega10_power_state->performance_level_count++]); + performance_level->soc_clock = socclk_dep_table->entries + [state_entry->ucSocClockIndexHigh].ulClk; + if (gfxclk_dep_table->ucRevId == 0) { + /* under vega10 pp one vf mode, the gfx clk dpm need be lower + * to level-4 due to the limited 110w-power + */ + if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) + performance_level->gfx_clock = + gfxclk_dep_table->entries[4].ulClk; + else + performance_level->gfx_clock = gfxclk_dep_table->entries + [state_entry->ucGfxClockIndexHigh].ulClk; + } else if (gfxclk_dep_table->ucRevId == 1) { + patom_record_V2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; + if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) + performance_level->gfx_clock = patom_record_V2[4].ulClk; + else + performance_level->gfx_clock = + patom_record_V2[state_entry->ucGfxClockIndexHigh].ulClk; + } + + performance_level->mem_clock = mclk_dep_table->entries + [state_entry->ucMemClockIndexHigh].ulMemClk; + return 0; +} + +static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *state) +{ + int result; + struct vega10_power_state *ps; + + state->hardware.magic = PhwVega10_Magic; + + ps = cast_phw_vega10_power_state(&state->hardware); + + result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state, + vega10_get_pp_table_entry_callback_func); + + /* + * This is the earliest time we have all the dependency table + * and the VBIOS boot state + */ + /* set DC compatible flag if this state supports DC */ + if (!state->validation.disallowOnDC) + ps->dc_compatible = true; + + ps->uvd_clks.vclk = state->uvd_clocks.VCLK; + ps->uvd_clks.dclk = state->uvd_clocks.DCLK; + + return 0; +} + +static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + return 0; +} + +static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *request_ps, + const struct pp_power_state *current_ps) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct vega10_power_state *vega10_ps = + cast_phw_vega10_power_state(&request_ps->hardware); + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; + bool disable_mclk_switching; + bool disable_mclk_switching_for_frame_lock; + bool disable_mclk_switching_for_vr; + bool force_mclk_high; + const struct phm_clock_and_voltage_limits *max_limits; + uint32_t i; + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + int32_t count; + uint32_t stable_pstate_sclk_dpm_percentage; + uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + uint32_t latency; + + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + + if (vega10_ps->performance_level_count != 2) + pr_info("VI should always have 2 performance levels"); + + max_limits = adev->pm.ac_power ? + &(hwmgr->dyn_state.max_clock_voltage_on_ac) : + &(hwmgr->dyn_state.max_clock_voltage_on_dc); + + /* Cap clock DPM tables at DC MAX if it is in DC. */ + if (!adev->pm.ac_power) { + for (i = 0; i < vega10_ps->performance_level_count; i++) { + if (vega10_ps->performance_levels[i].mem_clock > + max_limits->mclk) + vega10_ps->performance_levels[i].mem_clock = + max_limits->mclk; + if (vega10_ps->performance_levels[i].gfx_clock > + max_limits->sclk) + vega10_ps->performance_levels[i].gfx_clock = + max_limits->sclk; + } + } + + /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ + minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; + minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; + + if (PP_CAP(PHM_PlatformCaps_StablePState)) { + stable_pstate_sclk_dpm_percentage = + data->registry_data.stable_pstate_sclk_dpm_percentage; + PP_ASSERT_WITH_CODE( + data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && + data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, + "percent sclk value must range from 1% to 100%, setting default value", + stable_pstate_sclk_dpm_percentage = 75); + + max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); + stable_pstate_sclk = (max_limits->sclk * + stable_pstate_sclk_dpm_percentage) / 100; + + for (count = table_info->vdd_dep_on_sclk->count - 1; + count >= 0; count--) { + if (stable_pstate_sclk >= + table_info->vdd_dep_on_sclk->entries[count].clk) { + stable_pstate_sclk = + table_info->vdd_dep_on_sclk->entries[count].clk; + break; + } + } + + if (count < 0) + stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; + + stable_pstate_mclk = max_limits->mclk; + + minimum_clocks.engineClock = stable_pstate_sclk; + minimum_clocks.memoryClock = stable_pstate_mclk; + } + + disable_mclk_switching_for_frame_lock = + PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + disable_mclk_switching_for_vr = + PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR); + force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); + + if (hwmgr->display_config->num_display == 0) + disable_mclk_switching = false; + else + disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + disable_mclk_switching_for_frame_lock || + disable_mclk_switching_for_vr || + force_mclk_high; + + sclk = vega10_ps->performance_levels[0].gfx_clock; + mclk = vega10_ps->performance_levels[0].mem_clock; + + if (sclk < minimum_clocks.engineClock) + sclk = (minimum_clocks.engineClock > max_limits->sclk) ? + max_limits->sclk : minimum_clocks.engineClock; + + if (mclk < minimum_clocks.memoryClock) + mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? + max_limits->mclk : minimum_clocks.memoryClock; + + vega10_ps->performance_levels[0].gfx_clock = sclk; + vega10_ps->performance_levels[0].mem_clock = mclk; + + if (vega10_ps->performance_levels[1].gfx_clock < + vega10_ps->performance_levels[0].gfx_clock) + vega10_ps->performance_levels[0].gfx_clock = + vega10_ps->performance_levels[1].gfx_clock; + + if (disable_mclk_switching) { + /* Set Mclk the max of level 0 and level 1 */ + if (mclk < vega10_ps->performance_levels[1].mem_clock) + mclk = vega10_ps->performance_levels[1].mem_clock; + + /* Find the lowest MCLK frequency that is within + * the tolerable latency defined in DAL + */ + latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; + for (i = 0; i < data->mclk_latency_table.count; i++) { + if ((data->mclk_latency_table.entries[i].latency <= latency) && + (data->mclk_latency_table.entries[i].frequency >= + vega10_ps->performance_levels[0].mem_clock) && + (data->mclk_latency_table.entries[i].frequency <= + vega10_ps->performance_levels[1].mem_clock)) + mclk = data->mclk_latency_table.entries[i].frequency; + } + vega10_ps->performance_levels[0].mem_clock = mclk; + } else { + if (vega10_ps->performance_levels[1].mem_clock < + vega10_ps->performance_levels[0].mem_clock) + vega10_ps->performance_levels[0].mem_clock = + vega10_ps->performance_levels[1].mem_clock; + } + + if (PP_CAP(PHM_PlatformCaps_StablePState)) { + for (i = 0; i < vega10_ps->performance_level_count; i++) { + vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk; + vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk; + } + } + + return 0; +} + +static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) +{ + struct vega10_hwmgr *data = hwmgr->backend; + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + const struct vega10_power_state *vega10_ps = + cast_const_phw_vega10_power_state(states->pnew_state); + struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); + uint32_t sclk = vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock; + struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); + uint32_t mclk = vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].mem_clock; + uint32_t i; + + for (i = 0; i < sclk_table->count; i++) { + if (sclk == sclk_table->dpm_levels[i].value) + break; + } + + if (i >= sclk_table->count) { + if (sclk > sclk_table->dpm_levels[i-1].value) { + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + sclk_table->dpm_levels[i-1].value = sclk; + } + } + + for (i = 0; i < mclk_table->count; i++) { + if (mclk == mclk_table->dpm_levels[i].value) + break; + } + + if (i >= mclk_table->count) { + if (mclk > mclk_table->dpm_levels[i-1].value) { + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + mclk_table->dpm_levels[i-1].value = mclk; + } + } + + if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) + data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; + + return 0; +} + +static int vega10_populate_and_upload_sclk_mclk_dpm_levels( + struct pp_hwmgr *hwmgr, const void *input) +{ + int result = 0; + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_dpm_table *dpm_table = &data->dpm_table; + struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table; + struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk; + int count; + + if (!data->need_update_dpm_table) + return 0; + + if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { + for (count = 0; count < dpm_table->gfx_table.count; count++) + dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; + } + + odn_clk_table = &odn_table->vdd_dep_on_mclk; + if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { + for (count = 0; count < dpm_table->mem_table.count; count++) + dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; + } + + if (data->need_update_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) { + result = vega10_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + if (data->need_update_dpm_table & + (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) { + result = vega10_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + vega10_populate_vddc_soc_levels(hwmgr); + + return result; +} + +static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr, + struct vega10_single_dpm_table *dpm_table, + uint32_t low_limit, uint32_t high_limit) +{ + uint32_t i; + + for (i = 0; i < dpm_table->count; i++) { + if ((dpm_table->dpm_levels[i].value < low_limit) || + (dpm_table->dpm_levels[i].value > high_limit)) + dpm_table->dpm_levels[i].enabled = false; + else + dpm_table->dpm_levels[i].enabled = true; + } + return 0; +} + +static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr, + struct vega10_single_dpm_table *dpm_table, + uint32_t low_limit, uint32_t high_limit, + uint32_t disable_dpm_mask) +{ + uint32_t i; + + for (i = 0; i < dpm_table->count; i++) { + if ((dpm_table->dpm_levels[i].value < low_limit) || + (dpm_table->dpm_levels[i].value > high_limit)) + dpm_table->dpm_levels[i].enabled = false; + else if (!((1 << i) & disable_dpm_mask)) + dpm_table->dpm_levels[i].enabled = false; + else + dpm_table->dpm_levels[i].enabled = true; + } + return 0; +} + +static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr, + const struct vega10_power_state *vega10_ps) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t high_limit_count; + + PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1), + "power state did not have any performance level", + return -1); + + high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1; + + vega10_trim_single_dpm_states(hwmgr, + &(data->dpm_table.soc_table), + vega10_ps->performance_levels[0].soc_clock, + vega10_ps->performance_levels[high_limit_count].soc_clock); + + vega10_trim_single_dpm_states_with_mask(hwmgr, + &(data->dpm_table.gfx_table), + vega10_ps->performance_levels[0].gfx_clock, + vega10_ps->performance_levels[high_limit_count].gfx_clock, + data->disable_dpm_mask); + + vega10_trim_single_dpm_states(hwmgr, + &(data->dpm_table.mem_table), + vega10_ps->performance_levels[0].mem_clock, + vega10_ps->performance_levels[high_limit_count].mem_clock); + + return 0; +} + +static uint32_t vega10_find_lowest_dpm_level( + struct vega10_single_dpm_table *table) +{ + uint32_t i; + + for (i = 0; i < table->count; i++) { + if (table->dpm_levels[i].enabled) + break; + } + + return i; +} + +static uint32_t vega10_find_highest_dpm_level( + struct vega10_single_dpm_table *table) +{ + uint32_t i = 0; + + if (table->count <= MAX_REGULAR_DPM_NUMBER) { + for (i = table->count; i > 0; i--) { + if (table->dpm_levels[i - 1].enabled) + return i - 1; + } + } else { + pr_info("DPM Table Has Too Many Entries!"); + return MAX_REGULAR_DPM_NUMBER - 1; + } + + return i; +} + +static void vega10_apply_dal_minimum_voltage_request( + struct pp_hwmgr *hwmgr) +{ + return; +} + +static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + vdd_dep_table_on_mclk = table_info->vdd_dep_on_mclk; + + return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1; +} + +static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t socclk_idx; + + vega10_apply_dal_minimum_voltage_request(hwmgr); + + if (!data->registry_data.sclk_dpm_key_disabled) { + if (data->smc_state_table.gfx_boot_level != + data->dpm_table.gfx_table.dpm_state.soft_min_level) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMinGfxclkByIndex, + data->smc_state_table.gfx_boot_level, + NULL); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->smc_state_table.gfx_boot_level; + } + } + + if (!data->registry_data.mclk_dpm_key_disabled) { + if (data->smc_state_table.mem_boot_level != + data->dpm_table.mem_table.dpm_state.soft_min_level) { + if ((data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) + && hwmgr->not_vf) { + socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMinSocclkByIndex, + socclk_idx, + NULL); + } else { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMinUclkByIndex, + data->smc_state_table.mem_boot_level, + NULL); + } + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->smc_state_table.mem_boot_level; + } + } + + if (!hwmgr->not_vf) + return 0; + + if (!data->registry_data.socclk_dpm_key_disabled) { + if (data->smc_state_table.soc_boot_level != + data->dpm_table.soc_table.dpm_state.soft_min_level) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMinSocclkByIndex, + data->smc_state_table.soc_boot_level, + NULL); + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->smc_state_table.soc_boot_level; + } + } + + return 0; +} + +static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + vega10_apply_dal_minimum_voltage_request(hwmgr); + + if (!data->registry_data.sclk_dpm_key_disabled) { + if (data->smc_state_table.gfx_max_level != + data->dpm_table.gfx_table.dpm_state.soft_max_level) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxGfxclkByIndex, + data->smc_state_table.gfx_max_level, + NULL); + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->smc_state_table.gfx_max_level; + } + } + + if (!data->registry_data.mclk_dpm_key_disabled) { + if (data->smc_state_table.mem_max_level != + data->dpm_table.mem_table.dpm_state.soft_max_level) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxUclkByIndex, + data->smc_state_table.mem_max_level, + NULL); + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->smc_state_table.mem_max_level; + } + } + + if (!hwmgr->not_vf) + return 0; + + if (!data->registry_data.socclk_dpm_key_disabled) { + if (data->smc_state_table.soc_max_level != + data->dpm_table.soc_table.dpm_state.soft_max_level) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMaxSocclkByIndex, + data->smc_state_table.soc_max_level, + NULL); + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->smc_state_table.soc_max_level; + } + } + + return 0; +} + +static int vega10_generate_dpm_level_enable_mask( + struct pp_hwmgr *hwmgr, const void *input) +{ + struct vega10_hwmgr *data = hwmgr->backend; + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + const struct vega10_power_state *vega10_ps = + cast_const_phw_vega10_power_state(states->pnew_state); + int i; + + PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps), + "Attempt to Trim DPM States Failed!", + return -1); + + data->smc_state_table.gfx_boot_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.gfx_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.mem_boot_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + data->smc_state_table.mem_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); + data->smc_state_table.soc_boot_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table)); + data->smc_state_table.soc_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.soc_table)); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Attempt to upload DPM Bootup Levels Failed!", + return -1); + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Attempt to upload DPM Max Levels Failed!", + return -1); + for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++) + data->dpm_table.gfx_table.dpm_levels[i].enabled = true; + + + for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) + data->dpm_table.mem_table.dpm_levels[i].enabled = true; + + for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++) + data->dpm_table.soc_table.dpm_levels[i].enabled = true; + + return 0; +} + +int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DPM_VCE].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), + "Attempt to Enable/Disable DPM VCE Failed!", + return -1); + data->smu_features[GNLD_DPM_VCE].enabled = enable; + } + + return 0; +} + +static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t low_sclk_interrupt_threshold = 0; + + if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) && + (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + data->smc_state_table.pp_table.LowGfxclkInterruptThreshold = + cpu_to_le32(low_sclk_interrupt_threshold); + + /* This message will also enable SmcToHost Interrupt */ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetLowGfxclkInterruptThreshold, + (uint32_t)low_sclk_interrupt_threshold, + NULL); + } + + return 0; +} + +static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, + const void *input) +{ + int tmp_result, result = 0; + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + + tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to find DPM states clocks in DPM table!", + result = tmp_result); + + tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to populate and upload SCLK MCLK DPM levels!", + result = tmp_result); + + tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to generate DPM level enabled mask!", + result = tmp_result); + + tmp_result = vega10_update_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to update SCLK threshold!", + result = tmp_result); + + result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload PPtable!", return result); + + /* + * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. + * That effectively disables AVFS feature. + */ + if(hwmgr->hardcode_pp_table != NULL) + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; + + vega10_update_avfs(hwmgr); + + /* + * Clear all OD flags except DPMTABLE_OD_UPDATE_VDDC. + * That will help to keep AVFS disabled. + */ + data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; + + return 0; +} + +static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct vega10_power_state *vega10_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + + if (low) + return vega10_ps->performance_levels[0].gfx_clock; + else + return vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock; +} + +static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct vega10_power_state *vega10_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + + if (low) + return vega10_ps->performance_levels[0].mem_clock; + else + return vega10_ps->performance_levels + [vega10_ps->performance_level_count-1].mem_clock; +} + +static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr, + uint32_t *query) +{ + uint32_t value; + + if (!query) + return -EINVAL; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr, &value); + + /* SMC returning actual watts, keep consistent with legacy asics, low 8 bit as 8 fractional bits */ + *query = value << 8; + + return 0; +} + +static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t sclk_mhz, mclk_idx, activity_percent = 0; + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_dpm_table *dpm_table = &data->dpm_table; + int ret = 0; + uint32_t val_vid; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency, &sclk_mhz); + *((uint32_t *)value) = sclk_mhz * 100; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &mclk_idx); + if (mclk_idx < dpm_table->mem_table.count) { + *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value; + *size = 4; + } else { + ret = -EINVAL; + } + break; + case AMDGPU_PP_SENSOR_GPU_LOAD: + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0, + &activity_percent); + *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot, (uint32_t *)value); + *((uint32_t *)value) = *((uint32_t *)value) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM, (uint32_t *)value); + *((uint32_t *)value) = *((uint32_t *)value) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_UVD_POWER: + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VCE_POWER: + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value); + break; + case AMDGPU_PP_SENSOR_VDDGFX: + val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) & + SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >> + SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT; + *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid); + return 0; + case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: + ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value); + if (!ret) + *size = 8; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} + +static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr, + bool has_disp) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetUclkFastSwitch, + has_disp ? 1 : 0, + NULL); +} + +static int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock_req) +{ + int result = 0; + enum amd_pp_clock_type clk_type = clock_req->clock_type; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + DSPCLK_e clk_select = 0; + uint32_t clk_request = 0; + + switch (clk_type) { + case amd_pp_dcef_clock: + clk_select = DSPCLK_DCEFCLK; + break; + case amd_pp_disp_clock: + clk_select = DSPCLK_DISPCLK; + break; + case amd_pp_pixel_clock: + clk_select = DSPCLK_PIXCLK; + break; + case amd_pp_phy_clock: + clk_select = DSPCLK_PHYCLK; + break; + default: + pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); + result = -1; + break; + } + + if (!result) { + clk_request = (clk_freq << 16) | clk_select; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_RequestDisplayClockByFreq, + clk_request, + NULL); + } + + return result; +} + +static uint8_t vega10_get_uclk_index(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table, + uint32_t frequency) +{ + uint8_t count; + uint8_t i; + + if (mclk_table == NULL || mclk_table->count == 0) + return 0; + + count = (uint8_t)(mclk_table->count); + + for(i = 0; i < count; i++) { + if(mclk_table->entries[i].clk >= frequency) + return i; + } + + return i-1; +} + +static int vega10_notify_smc_display_config_after_ps_adjustment( + struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *dpm_table = + &data->dpm_table.dcef_table; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk; + uint32_t idx; + struct PP_Clocks min_clocks = {0}; + uint32_t i; + struct pp_display_clock_request clock_req; + + if ((hwmgr->display_config->num_display > 1) && + !hwmgr->display_config->multi_monitor_in_sync && + !hwmgr->display_config->nb_pstate_switch_disable) + vega10_notify_smc_display_change(hwmgr, false); + else + vega10_notify_smc_display_change(hwmgr, true); + + min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; + min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; + min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; + + for (i = 0; i < dpm_table->count; i++) { + if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock) + break; + } + + if (i < dpm_table->count) { + clock_req.clock_type = amd_pp_dcef_clock; + clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10; + if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) { + smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, + min_clocks.dcefClockInSR / 100, + NULL); + } else { + pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); + } + } else { + pr_debug("Cannot find requested DCEFCLK!"); + } + + if (min_clocks.memoryClock != 0) { + idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock); + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx, + NULL); + data->dpm_table.mem_table.dpm_state.soft_min_level= idx; + } + + return 0; +} + +static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->smc_state_table.gfx_boot_level = + data->smc_state_table.gfx_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.mem_boot_level = + data->smc_state_table.mem_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to highest!", + return -1); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -1); + + return 0; +} + +static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->smc_state_table.gfx_boot_level = + data->smc_state_table.gfx_max_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.mem_boot_level = + data->smc_state_table.mem_max_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to highest!", + return -1); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -1); + + return 0; + +} + +static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->smc_state_table.gfx_boot_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.gfx_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + data->smc_state_table.mem_boot_level = + vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + data->smc_state_table.mem_max_level = + vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload DPM Bootup Levels!", + return -1); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload DPM Max Levels!", + return -1); + return 0; +} + +static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL && + table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL && + table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) { + *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL; + *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL; + *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL; + hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk; + hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + /* under vega10 pp one vf mode, the gfx clk dpm need be lower + * to level-4 due to the limited power + */ + if (hwmgr->pp_one_vf) + *sclk_mask = 4; + else + *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; + *soc_mask = table_info->vdd_dep_on_socclk->count - 1; + *mclk_mask = table_info->vdd_dep_on_mclk->count - 1; + } + + return 0; +} + +static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + if (!hwmgr->not_vf) + return; + + switch (mode) { + case AMD_FAN_CTRL_NONE: + vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega10_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } +} + +static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + switch (type) { + case PP_SCLK: + data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0; + data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0; + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to lowest!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -EINVAL); + break; + + case PP_MCLK: + data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0; + data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0; + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to lowest!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -EINVAL); + + break; + + case PP_SOCCLK: + data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0; + data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0; + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), + "Failed to upload boot level to lowest!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -EINVAL); + + break; + + case PP_DCEFCLK: + pr_info("Setting DCEFCLK min/max dpm level is not supported!\n"); + break; + + case PP_PCIE: + default: + break; + } + + return 0; +} + +static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask = 0; + uint32_t mclk_mask = 0; + uint32_t soc_mask = 0; + + if (hwmgr->pstate_sclk == 0) + vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = vega10_force_dpm_highest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = vega10_force_dpm_lowest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = vega10_unforce_dpm_levels(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); + if (ret) + return ret; + vega10_force_clock_level(hwmgr, PP_SCLK, 1<not_vf) + return ret; + + if (!ret) { + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); + else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) + vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); + } + + return ret; +} + +static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) + return AMD_FAN_CTRL_MANUAL; + else + return AMD_FAN_CTRL_AUTO; +} + +static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_clock_and_voltage_limits *max_limits = + &table_info->max_clock_voltage_on_ac; + + info->engine_max_clock = max_limits->sclk; + info->memory_max_clock = max_limits->mclk; + + return 0; +} + +static void vega10_get_sclks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_sclk; + uint32_t i; + + clocks->num_levels = 0; + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].clk) { + clocks->data[clocks->num_levels].clocks_in_khz = + dep_table->entries[i].clk * 10; + clocks->num_levels++; + } + } + +} + +static void vega10_get_memclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_mclk; + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t j = 0; + uint32_t i; + + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].clk) { + + clocks->data[j].clocks_in_khz = + dep_table->entries[i].clk * 10; + data->mclk_latency_table.entries[j].frequency = + dep_table->entries[i].clk; + clocks->data[j].latency_in_us = + data->mclk_latency_table.entries[j].latency = 25; + j++; + } + } + clocks->num_levels = data->mclk_latency_table.count = j; +} + +static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_dcefclk; + uint32_t i; + + for (i = 0; i < dep_table->count; i++) { + clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; + clocks->data[i].latency_in_us = 0; + clocks->num_levels++; + } +} + +static void vega10_get_socclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = + table_info->vdd_dep_on_socclk; + uint32_t i; + + for (i = 0; i < dep_table->count; i++) { + clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; + clocks->data[i].latency_in_us = 0; + clocks->num_levels++; + } +} + +static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + switch (type) { + case amd_pp_sys_clock: + vega10_get_sclks(hwmgr, clocks); + break; + case amd_pp_mem_clock: + vega10_get_memclocks(hwmgr, clocks); + break; + case amd_pp_dcef_clock: + vega10_get_dcefclocks(hwmgr, clocks); + break; + case amd_pp_soc_clock: + vega10_get_socclocks(hwmgr, clocks); + break; + default: + return -1; + } + + return 0; +} + +static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; + uint32_t i; + + switch (type) { + case amd_pp_mem_clock: + dep_table = table_info->vdd_dep_on_mclk; + break; + case amd_pp_dcef_clock: + dep_table = table_info->vdd_dep_on_dcefclk; + break; + case amd_pp_disp_clock: + dep_table = table_info->vdd_dep_on_dispclk; + break; + case amd_pp_pixel_clock: + dep_table = table_info->vdd_dep_on_pixclk; + break; + case amd_pp_phy_clock: + dep_table = table_info->vdd_dep_on_phyclk; + break; + default: + return -1; + } + + for (i = 0; i < dep_table->count; i++) { + clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; + clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table-> + entries[dep_table->entries[i].vddInd].us_vdd); + clocks->num_levels++; + } + + if (i < dep_table->count) + return -1; + + return 0; +} + +static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_range) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range; + Watermarks_t *table = &(data->smc_state_table.water_marks_table); + + if (!data->registry_data.disable_water_mark) { + smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); + data->water_marks_bitmap = WaterMarksExist; + } + + return 0; +} + +static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) +{ + static const char *ppfeature_name[] = { + "DPM_PREFETCHER", + "GFXCLK_DPM", + "UCLK_DPM", + "SOCCLK_DPM", + "UVD_DPM", + "VCE_DPM", + "ULV", + "MP0CLK_DPM", + "LINK_DPM", + "DCEFCLK_DPM", + "AVFS", + "GFXCLK_DS", + "SOCCLK_DS", + "LCLK_DS", + "PPT", + "TDC", + "THERMAL", + "GFX_PER_CU_CG", + "RM", + "DCEFCLK_DS", + "ACDC", + "VR0HOT", + "VR1HOT", + "FW_CTF", + "LED_DISPLAY", + "FAN_CONTROL", + "FAST_PPT", + "DIDT", + "ACG", + "PCC_LIMIT"}; + static const char *output_title[] = { + "FEATURES", + "BITMASK", + "ENABLEMENT"}; + uint64_t features_enabled; + int i; + int ret = 0; + int size = 0; + + ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", + return ret); + + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); + size += sprintf(buf + size, "%-19s %-22s %s\n", + output_title[0], + output_title[1], + output_title[2]); + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", + ppfeature_name[i], + 1ULL << i, + (features_enabled & (1ULL << i)) ? "Y" : "N"); + } + + return size; +} + +static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) +{ + uint64_t features_enabled; + uint64_t features_to_enable; + uint64_t features_to_disable; + int ret = 0; + + if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) + return -EINVAL; + + ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + features_to_disable = + features_enabled & ~new_ppfeature_masks; + features_to_enable = + ~features_enabled & new_ppfeature_masks; + + pr_debug("features_to_disable 0x%llx\n", features_to_disable); + pr_debug("features_to_enable 0x%llx\n", features_to_enable); + + if (features_to_disable) { + ret = vega10_enable_smc_features(hwmgr, false, features_to_disable); + if (ret) + return ret; + } + + if (features_to_enable) { + ret = vega10_enable_smc_features(hwmgr, true, features_to_enable); + if (ret) + return ret; + } + + return 0; +} + +static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); + struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); + struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table); + struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table); + struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); + struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL; + + int i, now, size = 0, count = 0; + + switch (type) { + case PP_SCLK: + if (data->registry_data.sclk_dpm_key_disabled) + break; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now); + + if (hwmgr->pp_one_vf && + (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) + count = 5; + else + count = sclk_table->count; + for (i = 0; i < count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, sclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_MCLK: + if (data->registry_data.mclk_dpm_key_disabled) + break; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); + + for (i = 0; i < mclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, mclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_SOCCLK: + if (data->registry_data.socclk_dpm_key_disabled) + break; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); + + for (i = 0; i < soc_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, soc_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_DCEFCLK: + if (data->registry_data.dcefclk_dpm_key_disabled) + break; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); + + for (i = 0; i < dcef_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, dcef_table->dpm_levels[i].value / 100, + (dcef_table->dpm_levels[i].value / 100 == now) ? + "*" : ""); + break; + case PP_PCIE: + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex, &now); + + for (i = 0; i < pcie_table->count; i++) + size += sprintf(buf + size, "%d: %s %s\n", i, + (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" : + (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" : + (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "", + (i == now) ? "*" : ""); + break; + case OD_SCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; + for (i = 0; i < podn_vdd_dep->count; i++) + size += sprintf(buf + size, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk / 100, + podn_vdd_dep->entries[i].vddc); + } + break; + case OD_MCLK: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_MCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; + for (i = 0; i < podn_vdd_dep->count; i++) + size += sprintf(buf + size, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk/100, + podn_vdd_dep->entries[i].vddc); + } + break; + case OD_RANGE: + if (hwmgr->od_enabled) { + size = sprintf(buf, "%s:\n", "OD_RANGE"); + size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); + size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.mem_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); + size += sprintf(buf + size, "VDDC: %7umV %11umV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + } + break; + default: + break; + } + return size; +} + +static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); + int result = 0; + + if ((data->water_marks_bitmap & WaterMarksExist) && + !(data->water_marks_bitmap & WaterMarksLoaded)) { + result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false); + PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); + data->water_marks_bitmap |= WaterMarksLoaded; + } + + if (data->water_marks_bitmap & WaterMarksLoaded) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, + NULL); + } + + return result; +} + +static int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DPM_UVD].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), + "Attempt to Enable/Disable DPM UVD Failed!", + return -1); + data->smu_features[GNLD_DPM_UVD].enabled = enable; + } + return 0; +} + +static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->vce_power_gated = bgate; + vega10_enable_disable_vce_dpm(hwmgr, !bgate); +} + +static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + data->uvd_power_gated = bgate; + vega10_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +static inline bool vega10_are_power_levels_equal( + const struct vega10_performance_level *pl1, + const struct vega10_performance_level *pl2) +{ + return ((pl1->soc_clock == pl2->soc_clock) && + (pl1->gfx_clock == pl2->gfx_clock) && + (pl1->mem_clock == pl2->mem_clock)); +} + +static int vega10_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, bool *equal) +{ + const struct vega10_power_state *psa; + const struct vega10_power_state *psb; + int i; + + if (pstate1 == NULL || pstate2 == NULL || equal == NULL) + return -EINVAL; + + psa = cast_const_phw_vega10_power_state(pstate1); + psb = cast_const_phw_vega10_power_state(pstate2); + /* If the two states don't even have the same number of performance levels they cannot be the same state. */ + if (psa->performance_level_count != psb->performance_level_count) { + *equal = false; + return 0; + } + + for (i = 0; i < psa->performance_level_count; i++) { + if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { + /* If we have found even one performance level pair that is different the states are different. */ + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); + *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); + *equal &= (psa->sclk_threshold == psb->sclk_threshold); + + return 0; +} + +static bool +vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + bool is_update_required = false; + + if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) + is_update_required = true; + + if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) { + if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) + is_update_required = true; + } + + return is_update_required; +} + +static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + if (!hwmgr->not_vf) + return 0; + + if (PP_CAP(PHM_PlatformCaps_ThermalController)) + vega10_disable_thermal_protection(hwmgr); + + tmp_result = vega10_disable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable power containment!", result = tmp_result); + + tmp_result = vega10_disable_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable didt config!", result = tmp_result); + + tmp_result = vega10_avfs_enable(hwmgr, false); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable AVFS!", result = tmp_result); + + tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to stop DPM!", result = tmp_result); + + tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable deep sleep!", result = tmp_result); + + tmp_result = vega10_disable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable ulv!", result = tmp_result); + + tmp_result = vega10_acg_disable(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable acg!", result = tmp_result); + + vega10_enable_disable_PCC_limit_feature(hwmgr, false); + return result; +} + +static int vega10_power_off_asic(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + int result; + + result = vega10_disable_dpm_tasks(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "[disable_dpm_tasks] Failed to disable DPM!", + ); + data->water_marks_bitmap &= ~(WaterMarksLoaded); + + return result; +} + +static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); + struct vega10_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.gfx_table); + int value = sclk_table->dpm_levels[sclk_table->count - 1].value; + int golden_value = golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.gfx_table); + struct pp_power_state *ps; + struct vega10_power_state *vega10_ps; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock = + golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value * + value / 100 + + golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value; + + if (vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock > + hwmgr->platform_descriptor.overdriveLimit.engineClock) { + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].gfx_clock = + hwmgr->platform_descriptor.overdriveLimit.engineClock; + pr_warn("max sclk supported by vbios is %d\n", + hwmgr->platform_descriptor.overdriveLimit.engineClock); + } + return 0; +} + +static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); + struct vega10_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mem_table); + int value = mclk_table->dpm_levels[mclk_table->count - 1].value; + int golden_value = golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mem_table); + struct pp_power_state *ps; + struct vega10_power_state *vega10_ps; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].mem_clock = + golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value * + value / 100 + + golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value; + + if (vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].mem_clock > + hwmgr->platform_descriptor.overdriveLimit.memoryClock) { + vega10_ps->performance_levels + [vega10_ps->performance_level_count - 1].mem_clock = + hwmgr->platform_descriptor.overdriveLimit.memoryClock; + pr_warn("max mclk supported by vbios is %d\n", + hwmgr->platform_descriptor.overdriveLimit.memoryClock); + } + + return 0; +} + +static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrHigh, + virtual_addr_hi, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrLow, + virtual_addr_low, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrHigh, + mc_addr_hi, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrLow, + mc_addr_low, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramSize, + size, + NULL); + return 0; +} + +static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *thermal_data) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + + memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); + + thermal_data->max = pp_table->TedgeLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_crit_max = pp_table->ThbmLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t i, size = 0; + static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, + {70, 60, 1, 3,}, + {90, 60, 0, 0,}, + {70, 60, 0, 0,}, + {70, 90, 0, 0,}, + {30, 60, 0, 6,}, + }; + static const char *profile_name[7] = {"BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + static const char *title[6] = {"NUM", + "MODE_NAME", + "BUSY_SET_POINT", + "FPS", + "USE_RLC_BUSY", + "MIN_ACTIVE_LEVEL"}; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], + title[1], title[2], title[3], title[4], title[5]); + + for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++) + size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", + i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", + profile_mode_setting[i][0], profile_mode_setting[i][1], + profile_mode_setting[i][2], profile_mode_setting[i][3]); + size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i, + profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", + data->custom_profile_mode[0], data->custom_profile_mode[1], + data->custom_profile_mode[2], data->custom_profile_mode[3]); + return size; +} + +static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint8_t busy_set_point; + uint8_t FPS; + uint8_t use_rlc_busy; + uint8_t min_active_level; + uint32_t power_profile_mode = input[size]; + + if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + if (size != 0 && size != 4) + return -EINVAL; + + /* If size = 0 and the CUSTOM profile has been set already + * then just apply the profile. The copy stored in the hwmgr + * is zeroed out on init + */ + if (size == 0) { + if (data->custom_profile_mode[0] != 0) + goto out; + else + return -EINVAL; + } + + data->custom_profile_mode[0] = busy_set_point = input[0]; + data->custom_profile_mode[1] = FPS = input[1]; + data->custom_profile_mode[2] = use_rlc_busy = input[2]; + data->custom_profile_mode[3] = min_active_level = input[3]; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetCustomGfxDpmParameters, + busy_set_point | FPS<<8 | + use_rlc_busy << 16 | min_active_level<<24, + NULL); + } + +out: + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, + 1 << power_profile_mode, + NULL); + hwmgr->power_profile_mode = power_profile_mode; + + return 0; +} + + +static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + uint32_t clk, + uint32_t voltage) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); + struct vega10_single_dpm_table *golden_table; + + if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) { + pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc); + return false; + } + + if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { + golden_table = &(data->golden_dpm_table.gfx_table); + if (golden_table->dpm_levels[0].value > clk || + hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { + pr_info("OD engine clock is out of range [%d - %d] MHz\n", + golden_table->dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); + return false; + } + } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { + golden_table = &(data->golden_dpm_table.mem_table); + if (golden_table->dpm_levels[0].value > clk || + hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { + pr_info("OD memory clock is out of range [%d - %d] MHz\n", + golden_table->dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); + return false; + } + } else { + return false; + } + + return true; +} + +static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct pp_power_state *ps = hwmgr->request_ps; + struct vega10_power_state *vega10_ps; + struct vega10_single_dpm_table *gfx_dpm_table = + &data->dpm_table.gfx_table; + struct vega10_single_dpm_table *soc_dpm_table = + &data->dpm_table.soc_table; + struct vega10_single_dpm_table *mem_dpm_table = + &data->dpm_table.mem_table; + int max_level; + + if (!ps) + return; + + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + max_level = vega10_ps->performance_level_count - 1; + + if (vega10_ps->performance_levels[max_level].gfx_clock != + gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].gfx_clock = + gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; + + if (vega10_ps->performance_levels[max_level].soc_clock != + soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].soc_clock = + soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; + + if (vega10_ps->performance_levels[max_level].mem_clock != + mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].mem_clock = + mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; + + if (!hwmgr->ps) + return; + + ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1)); + vega10_ps = cast_phw_vega10_power_state(&ps->hardware); + max_level = vega10_ps->performance_level_count - 1; + + if (vega10_ps->performance_levels[max_level].gfx_clock != + gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].gfx_clock = + gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; + + if (vega10_ps->performance_levels[max_level].soc_clock != + soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].soc_clock = + soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; + + if (vega10_ps->performance_levels[max_level].mem_clock != + mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) + vega10_ps->performance_levels[max_level].mem_clock = + mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; +} + +static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk; + struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table; + + struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk = + &data->odn_dpm_table.vdd_dep_on_socclk; + struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table; + + struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep; + uint8_t i, j; + + if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; + for (i = 0; i < podn_vdd_dep->count; i++) + od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; + } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; + for (i = 0; i < dpm_table->count; i++) { + for (j = 0; j < od_vddc_lookup_table->count; j++) { + if (od_vddc_lookup_table->entries[j].us_vdd > + podn_vdd_dep->entries[i].vddc) + break; + } + if (j == od_vddc_lookup_table->count) { + j = od_vddc_lookup_table->count - 1; + od_vddc_lookup_table->entries[j].us_vdd = + podn_vdd_dep->entries[i].vddc; + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; + } + podn_vdd_dep->entries[i].vddInd = j; + } + dpm_table = &data->dpm_table.soc_table; + for (i = 0; i < dep_table->count; i++) { + if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd && + dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) { + data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; + for (; (i < dep_table->count) && + (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) { + podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk; + dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk; + } + break; + } else { + dpm_table->dpm_levels[i].value = dep_table->entries[i].clk; + podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc; + podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd; + podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk; + } + } + if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk < + podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) { + data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; + podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk = + podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; + dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value = + podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; + } + if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd < + podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) { + data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; + podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd = + podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd; + } + } + vega10_odn_update_power_state(hwmgr); +} + +static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table; + struct vega10_single_dpm_table *dpm_table; + + uint32_t input_clk; + uint32_t input_vol; + uint32_t input_level; + uint32_t i; + + PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", + return -EINVAL); + + if (!hwmgr->od_enabled) { + pr_info("OverDrive feature not enabled\n"); + return -EINVAL; + } + + if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { + dpm_table = &data->dpm_table.gfx_table; + podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk; + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { + dpm_table = &data->dpm_table.mem_table; + podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk; + data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { + memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table)); + vega10_odn_initial_default_setting(hwmgr); + vega10_odn_update_power_state(hwmgr); + /* force to update all clock tables */ + data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK | + DPMTABLE_UPDATE_MCLK | + DPMTABLE_UPDATE_SOCCLK; + return 0; + } else if (PP_OD_COMMIT_DPM_TABLE == type) { + vega10_check_dpm_table_updated(hwmgr); + return 0; + } else { + return -EINVAL; + } + + for (i = 0; i < size; i += 3) { + if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) { + pr_info("invalid clock voltage input\n"); + return 0; + } + input_level = input[i]; + input_clk = input[i+1] * 100; + input_vol = input[i+2]; + + if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { + dpm_table->dpm_levels[input_level].value = input_clk; + podn_vdd_dep_table->entries[input_level].clk = input_clk; + podn_vdd_dep_table->entries[input_level].vddc = input_vol; + } else { + return -EINVAL; + } + } + vega10_odn_update_soc_table(hwmgr, type); + return 0; +} + +static int vega10_set_mp1_state(struct pp_hwmgr *hwmgr, + enum pp_mp1_state mp1_state) +{ + uint16_t msg; + int ret; + + switch (mp1_state) { + case PP_MP1_STATE_UNLOAD: + msg = PPSMC_MSG_PrepareMp1ForUnload; + break; + case PP_MP1_STATE_SHUTDOWN: + case PP_MP1_STATE_RESET: + case PP_MP1_STATE_NONE: + default: + return 0; + } + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, + "[PrepareMp1] Failed!", + return ret); + + return 0; +} + +static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + const struct vega10_power_state *ps; + uint32_t i; + + if (level == NULL || hwmgr == NULL || state == NULL) + return -EINVAL; + + ps = cast_const_phw_vega10_power_state(state); + + i = index > ps->performance_level_count - 1 ? + ps->performance_level_count - 1 : index; + + level->coreClock = ps->performance_levels[i].gfx_clock; + level->memory_clock = ps->performance_levels[i].mem_clock; + + return 0; +} + +static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable) +{ + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t feature_mask = 0; + + if (disable) { + feature_mask |= data->smu_features[GNLD_ULV].enabled ? + data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; + feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ? + data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; + feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ? + data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; + feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ? + data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; + feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ? + data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; + } else { + feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ? + data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; + feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ? + data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; + feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ? + data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; + feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ? + data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; + feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ? + data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; + } + + if (feature_mask) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + !disable, feature_mask), + "enable/disable power features for compute performance Failed!", + return -EINVAL); + + if (disable) { + data->smu_features[GNLD_ULV].enabled = false; + data->smu_features[GNLD_DS_GFXCLK].enabled = false; + data->smu_features[GNLD_DS_SOCCLK].enabled = false; + data->smu_features[GNLD_DS_LCLK].enabled = false; + data->smu_features[GNLD_DS_DCEFCLK].enabled = false; + } else { + data->smu_features[GNLD_ULV].enabled = true; + data->smu_features[GNLD_DS_GFXCLK].enabled = true; + data->smu_features[GNLD_DS_SOCCLK].enabled = true; + data->smu_features[GNLD_DS_LCLK].enabled = true; + data->smu_features[GNLD_DS_DCEFCLK].enabled = true; + } + + return 0; + +} + +static const struct pp_hwmgr_func vega10_hwmgr_funcs = { + .backend_init = vega10_hwmgr_backend_init, + .backend_fini = vega10_hwmgr_backend_fini, + .asic_setup = vega10_setup_asic_task, + .dynamic_state_management_enable = vega10_enable_dpm_tasks, + .dynamic_state_management_disable = vega10_disable_dpm_tasks, + .get_num_of_pp_table_entries = + vega10_get_number_of_powerplay_table_entries, + .get_power_state_size = vega10_get_power_state_size, + .get_pp_table_entry = vega10_get_pp_table_entry, + .patch_boot_state = vega10_patch_boot_state, + .apply_state_adjust_rules = vega10_apply_state_adjust_rules, + .power_state_set = vega10_set_power_state_tasks, + .get_sclk = vega10_dpm_get_sclk, + .get_mclk = vega10_dpm_get_mclk, + .notify_smc_display_config_after_ps_adjustment = + vega10_notify_smc_display_config_after_ps_adjustment, + .force_dpm_level = vega10_dpm_force_dpm_level, + .stop_thermal_controller = vega10_thermal_stop_thermal_controller, + .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info, + .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent, + .reset_fan_speed_to_default = + vega10_fan_ctrl_reset_fan_speed_to_default, + .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm, + .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm, + .uninitialize_thermal_controller = + vega10_thermal_ctrl_uninitialize_thermal_controller, + .set_fan_control_mode = vega10_set_fan_control_mode, + .get_fan_control_mode = vega10_get_fan_control_mode, + .read_sensor = vega10_read_sensor, + .get_dal_power_level = vega10_get_dal_power_level, + .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency, + .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage, + .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges, + .display_clock_voltage_request = vega10_display_clock_voltage_request, + .force_clock_level = vega10_force_clock_level, + .print_clock_levels = vega10_print_clock_levels, + .display_config_changed = vega10_display_configuration_changed_task, + .powergate_uvd = vega10_power_gate_uvd, + .powergate_vce = vega10_power_gate_vce, + .check_states_equal = vega10_check_states_equal, + .check_smc_update_required_for_display_configuration = + vega10_check_smc_update_required_for_display_configuration, + .power_off_asic = vega10_power_off_asic, + .disable_smc_firmware_ctf = vega10_thermal_disable_alert, + .get_sclk_od = vega10_get_sclk_od, + .set_sclk_od = vega10_set_sclk_od, + .get_mclk_od = vega10_get_mclk_od, + .set_mclk_od = vega10_set_mclk_od, + .avfs_control = vega10_avfs_enable, + .notify_cac_buffer_info = vega10_notify_cac_buffer_info, + .get_thermal_temperature_range = vega10_get_thermal_temperature_range, + .register_irq_handlers = smu9_register_irq_handlers, + .start_thermal_controller = vega10_start_thermal_controller, + .get_power_profile_mode = vega10_get_power_profile_mode, + .set_power_profile_mode = vega10_set_power_profile_mode, + .set_power_limit = vega10_set_power_limit, + .odn_edit_dpm_table = vega10_odn_edit_dpm_table, + .get_performance_level = vega10_get_performance_level, + .get_asic_baco_capability = smu9_baco_get_capability, + .get_asic_baco_state = smu9_baco_get_state, + .set_asic_baco_state = vega10_baco_set_state, + .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost, + .get_ppfeature_status = vega10_get_ppfeature_status, + .set_ppfeature_status = vega10_set_ppfeature_status, + .set_mp1_state = vega10_set_mp1_state, + .disable_power_features_for_compute_performance = + vega10_disable_power_features_for_compute_performance, +}; + +int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + hwmgr->hwmgr_func = &vega10_hwmgr_funcs; + hwmgr->pptable_func = &vega10_pptable_funcs; + if (amdgpu_passthrough(adev)) + return vega10_baco_set_cap(hwmgr); + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h new file mode 100644 index 000000000000..f752b4ad0c8a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.h @@ -0,0 +1,446 @@ +/* + * Copyright 2016 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 _VEGA10_HWMGR_H_ +#define _VEGA10_HWMGR_H_ + +#include "hwmgr.h" +#include "smu9_driver_if.h" +#include "ppatomctrl.h" +#include "ppatomfwctrl.h" +#include "vega10_ppsmc.h" +#include "vega10_powertune.h" + +#define VEGA10_MAX_HARDWARE_POWERLEVELS 2 + +#define WaterMarksExist 1 +#define WaterMarksLoaded 2 + +enum { + GNLD_DPM_PREFETCHER = 0, + GNLD_DPM_GFXCLK, + GNLD_DPM_UCLK, + GNLD_DPM_SOCCLK, + GNLD_DPM_UVD, + GNLD_DPM_VCE, + GNLD_ULV, + GNLD_DPM_MP0CLK, + GNLD_DPM_LINK, + GNLD_DPM_DCEFCLK, + GNLD_AVFS, + GNLD_DS_GFXCLK, + GNLD_DS_SOCCLK, + GNLD_DS_LCLK, + GNLD_PPT, + GNLD_TDC, + GNLD_THERMAL, + GNLD_GFX_PER_CU_CG, + GNLD_RM, + GNLD_DS_DCEFCLK, + GNLD_ACDC, + GNLD_VR0HOT, + GNLD_VR1HOT, + GNLD_FW_CTF, + GNLD_LED_DISPLAY, + GNLD_FAN_CONTROL, + GNLD_FEATURE_FAST_PPT_BIT, + GNLD_DIDT, + GNLD_ACG, + GNLD_PCC_LIMIT, + GNLD_FEATURES_MAX +}; + +#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) + +#define SMC_DPM_FEATURES 0x30F + +struct smu_features { + bool supported; + bool enabled; + uint32_t smu_feature_id; + uint32_t smu_feature_bitmap; +}; + +struct vega10_performance_level { + uint32_t soc_clock; + uint32_t gfx_clock; + uint32_t mem_clock; +}; + +struct vega10_bacos { + uint32_t baco_flags; + /* struct vega10_performance_level performance_level; */ +}; + +struct vega10_uvd_clocks { + uint32_t vclk; + uint32_t dclk; +}; + +struct vega10_vce_clocks { + uint32_t evclk; + uint32_t ecclk; +}; + +struct vega10_power_state { + uint32_t magic; + struct vega10_uvd_clocks uvd_clks; + struct vega10_vce_clocks vce_clks; + uint16_t performance_level_count; + bool dc_compatible; + uint32_t sclk_threshold; + struct vega10_performance_level performance_levels[VEGA10_MAX_HARDWARE_POWERLEVELS]; +}; + +struct vega10_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +#define VEGA10_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 8 +#define MAX_PCIE_CONF 2 +#define VEGA10_MINIMUM_ENGINE_CLOCK 2500 + +struct vega10_dpm_state { + uint32_t soft_min_level; + uint32_t soft_max_level; + uint32_t hard_min_level; + uint32_t hard_max_level; +}; + +struct vega10_single_dpm_table { + uint32_t count; + struct vega10_dpm_state dpm_state; + struct vega10_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega10_pcie_table { + uint16_t count; + uint8_t pcie_gen[MAX_PCIE_CONF]; + uint8_t pcie_lane[MAX_PCIE_CONF]; + uint32_t lclk[MAX_PCIE_CONF]; +}; + +struct vega10_dpm_table { + struct vega10_single_dpm_table soc_table; + struct vega10_single_dpm_table gfx_table; + struct vega10_single_dpm_table mem_table; + struct vega10_single_dpm_table eclk_table; + struct vega10_single_dpm_table vclk_table; + struct vega10_single_dpm_table dclk_table; + struct vega10_single_dpm_table dcef_table; + struct vega10_single_dpm_table pixel_table; + struct vega10_single_dpm_table display_table; + struct vega10_single_dpm_table phy_table; + struct vega10_pcie_table pcie_table; +}; + +#define VEGA10_MAX_LEAKAGE_COUNT 8 +struct vega10_leakage_voltage { + uint16_t count; + uint16_t leakage_id[VEGA10_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[VEGA10_MAX_LEAKAGE_COUNT]; +}; + +struct vega10_display_timing { + uint32_t min_clock_in_sr; + uint32_t num_existing_displays; +}; + +struct vega10_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t acp_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; +}; + +struct vega10_vbios_boot_state { + bool bsoc_vddc_lock; + uint16_t vddc; + uint16_t vddci; + uint16_t mvddc; + uint16_t vdd_gfx; + uint32_t gfx_clock; + uint32_t mem_clock; + uint32_t soc_clock; + uint32_t dcef_clock; +}; + +struct vega10_smc_state_table { + uint32_t soc_boot_level; + uint32_t gfx_boot_level; + uint32_t dcef_boot_level; + uint32_t mem_boot_level; + uint32_t uvd_boot_level; + uint32_t vce_boot_level; + uint32_t gfx_max_level; + uint32_t mem_max_level; + uint32_t soc_max_level; + uint8_t vr_hot_gpio; + uint8_t ac_dc_gpio; + uint8_t therm_out_gpio; + uint8_t therm_out_polarity; + uint8_t therm_out_mode; + PPTable_t pp_table; + Watermarks_t water_marks_table; + AvfsTable_t avfs_table; + AvfsFuseOverride_t avfs_fuse_override_table; +}; + +struct vega10_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct vega10_mclk_latency_table { + uint32_t count; + struct vega10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega10_registry_data { + uint8_t ac_dc_switch_gpio_support; + uint8_t avfs_support; + uint8_t cac_support; + uint8_t clock_stretcher_support; + uint8_t db_ramping_support; + uint8_t didt_mode; + uint8_t didt_support; + uint8_t edc_didt_support; + uint8_t dynamic_state_patching_support; + uint8_t enable_pkg_pwr_tracking_feature; + uint8_t enable_tdc_limit_feature; + uint32_t fast_watermark_threshold; + uint8_t force_dpm_high; + uint8_t fuzzy_fan_control_support; + uint8_t long_idle_baco_support; + uint8_t mclk_dpm_key_disabled; + uint8_t od_state_in_dc_support; + uint8_t pcieLaneOverride; + uint8_t pcieSpeedOverride; + uint32_t pcieClockOverride; + uint8_t pcie_dpm_key_disabled; + uint8_t dcefclk_dpm_key_disabled; + uint8_t power_containment_support; + uint8_t ppt_support; + uint8_t prefetcher_dpm_key_disabled; + uint8_t quick_transition_support; + uint8_t regulator_hot_gpio_support; + uint8_t sclk_deep_sleep_support; + uint8_t sclk_dpm_key_disabled; + uint8_t sclk_from_vbios; + uint8_t sclk_throttle_low_notification; + uint8_t show_baco_dbg_info; + uint8_t skip_baco_hardware; + uint8_t socclk_dpm_key_disabled; + uint8_t spll_shutdown_support; + uint8_t sq_ramping_support; + uint32_t stable_pstate_sclk_dpm_percentage; + uint8_t tcp_ramping_support; + uint8_t tdc_support; + uint8_t td_ramping_support; + uint8_t dbr_ramping_support; + uint8_t gc_didt_support; + uint8_t psm_didt_support; + uint8_t thermal_out_gpio_support; + uint8_t thermal_support; + uint8_t fw_ctf_enabled; + uint8_t fan_control_support; + uint8_t ulps_support; + uint8_t ulv_support; + uint32_t vddc_vddci_delta; + uint8_t odn_feature_enable; + uint8_t disable_water_mark; + uint8_t zrpm_stop_temp; + uint8_t zrpm_start_temp; + uint8_t led_dpm_enabled; + uint8_t vr0hot_enabled; + uint8_t vr1hot_enabled; +}; + +struct vega10_odn_clock_voltage_dependency_table { + uint32_t count; + struct phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega10_odn_vddc_lookup_table { + uint32_t count; + struct phm_ppt_v1_voltage_lookup_record entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega10_odn_dpm_table { + struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_sclk; + struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_mclk; + struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_socclk; + struct vega10_odn_vddc_lookup_table vddc_lookup_table; + uint32_t max_vddc; + uint32_t min_vddc; +}; + +struct vega10_odn_fan_table { + uint32_t target_fan_speed; + uint32_t target_temperature; + uint32_t min_performance_clock; + uint32_t min_fan_limit; +}; + +struct vega10_hwmgr { + struct vega10_dpm_table dpm_table; + struct vega10_dpm_table golden_dpm_table; + struct vega10_registry_data registry_data; + struct vega10_vbios_boot_state vbios_boot_state; + struct vega10_mclk_latency_table mclk_latency_table; + + struct vega10_leakage_voltage vddc_leakage; + + uint32_t vddc_control; + struct pp_atomfwctrl_voltage_table vddc_voltage_table; + uint32_t mvdd_control; + struct pp_atomfwctrl_voltage_table mvdd_voltage_table; + uint32_t vddci_control; + struct pp_atomfwctrl_voltage_table vddci_voltage_table; + + uint32_t active_auto_throttle_sources; + uint32_t water_marks_bitmap; + struct vega10_bacos bacos; + + struct vega10_odn_dpm_table odn_dpm_table; + struct vega10_odn_fan_table odn_fan_table; + + /* ---- General data ---- */ + uint8_t need_update_dpm_table; + + bool cac_enabled; + bool battery_state; + bool is_tlu_enabled; + + uint32_t low_sclk_interrupt_threshold; + + uint32_t total_active_cus; + + struct vega10_display_timing display_timing; + + /* ---- Vega10 Dyn Register Settings ---- */ + + uint32_t debug_settings; + uint32_t lowest_uclk_reserved_for_ulv; + uint32_t gfxclk_average_alpha; + uint32_t socclk_average_alpha; + uint32_t uclk_average_alpha; + uint32_t gfx_activity_average_alpha; + uint32_t display_voltage_mode; + uint32_t dcef_clk_quad_eqn_a; + uint32_t dcef_clk_quad_eqn_b; + uint32_t dcef_clk_quad_eqn_c; + uint32_t disp_clk_quad_eqn_a; + uint32_t disp_clk_quad_eqn_b; + uint32_t disp_clk_quad_eqn_c; + uint32_t pixel_clk_quad_eqn_a; + uint32_t pixel_clk_quad_eqn_b; + uint32_t pixel_clk_quad_eqn_c; + uint32_t phy_clk_quad_eqn_a; + uint32_t phy_clk_quad_eqn_b; + uint32_t phy_clk_quad_eqn_c; + + /* ---- Thermal Temperature Setting ---- */ + struct vega10_dpmlevel_enable_mask dpm_level_enable_mask; + + /* ---- Power Gating States ---- */ + bool uvd_power_gated; + bool vce_power_gated; + bool need_long_memory_training; + + /* Internal settings to apply the application power optimization parameters */ + uint32_t disable_dpm_mask; + + /* ---- SMU9 ---- */ + struct smu_features smu_features[GNLD_FEATURES_MAX]; + struct vega10_smc_state_table smc_state_table; + + uint32_t config_telemetry; + uint32_t acg_loop_state; + uint32_t mem_channels; + uint8_t custom_profile_mode[4]; +}; + +#define VEGA10_DPM2_NEAR_TDP_DEC 10 +#define VEGA10_DPM2_ABOVE_SAFE_INC 5 +#define VEGA10_DPM2_BELOW_SAFE_INC 20 + +#define VEGA10_DPM2_LTA_WINDOW_SIZE 7 + +#define VEGA10_DPM2_LTS_TRUNCATE 0 + +#define VEGA10_DPM2_TDP_SAFE_LIMIT_PERCENT 80 + +#define VEGA10_DPM2_MAXPS_PERCENT_M 90 +#define VEGA10_DPM2_MAXPS_PERCENT_H 90 + +#define VEGA10_DPM2_PWREFFICIENCYRATIO_MARGIN 50 + +#define VEGA10_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define VEGA10_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define VEGA10_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define VEGA10_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E +#define VEGA10_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF + +#define VEGA10_VOLTAGE_CONTROL_NONE 0x0 +#define VEGA10_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define VEGA10_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define VEGA10_VOLTAGE_CONTROL_MERGED 0x3 +/* To convert to Q8.8 format for firmware */ +#define VEGA10_Q88_FORMAT_CONVERSION_UNIT 256 + +#define VEGA10_UNUSED_GPIO_PIN 0x7F + +#define VEGA10_THERM_OUT_MODE_DISABLE 0x0 +#define VEGA10_THERM_OUT_MODE_THERM_ONLY 0x1 +#define VEGA10_THERM_OUT_MODE_THERM_VRHOT 0x2 + +#define PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT 0xffffffff +#define PPREGKEY_VEGA10QUADRATICEQUATION_DFLT 0xffffffff + +#define PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ + +#define VEGA10_UMD_PSTATE_GFXCLK_LEVEL 0x3 +#define VEGA10_UMD_PSTATE_SOCCLK_LEVEL 0x3 +#define VEGA10_UMD_PSTATE_MCLK_LEVEL 0x2 + +extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); +extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); +extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr); +extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); +extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display); +int vega10_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input); +int vega10_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int vega10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int vega10_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); + +#endif /* _VEGA10_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h new file mode 100644 index 000000000000..faf7ac044348 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_inc.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016 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 VEGA10_INC_H +#define VEGA10_INC_H + +#include "asic_reg/thm/thm_9_0_default.h" +#include "asic_reg/thm/thm_9_0_offset.h" +#include "asic_reg/thm/thm_9_0_sh_mask.h" + +#include "asic_reg/mp/mp_9_0_offset.h" +#include "asic_reg/mp/mp_9_0_sh_mask.h" + +#include "asic_reg/gc/gc_9_0_default.h" +#include "asic_reg/gc/gc_9_0_offset.h" +#include "asic_reg/gc/gc_9_0_sh_mask.h" + +#include "asic_reg/nbio/nbio_6_1_default.h" +#include "asic_reg/nbio/nbio_6_1_offset.h" +#include "asic_reg/nbio/nbio_6_1_sh_mask.h" + + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c new file mode 100644 index 000000000000..9757d47dd6b8 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.c @@ -0,0 +1,1392 @@ +/* + * Copyright 2016 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 "hwmgr.h" +#include "vega10_hwmgr.h" +#include "vega10_smumgr.h" +#include "vega10_powertune.h" +#include "vega10_ppsmc.h" +#include "vega10_inc.h" +#include "pp_debug.h" +#include "soc15_common.h" + +static const struct vega10_didt_config_reg SEDiDtTuningCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853 }, + { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153 }, + + /* DIDT_TD */ + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde }, + { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde }, + + /* DIDT_TCP */ + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, + { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, + + /* DIDT_DB */ + { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, + { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl3Config_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /*DIDT_SQ_CTRL3 */ + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_SQ_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__THROTTLE_POLICY_MASK, DIDT_SQ_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_SQ_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_SEL_MASK, DIDT_SQ_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_SQ_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_TCP_CTRL3 */ + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TCP_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__THROTTLE_POLICY_MASK, DIDT_TCP_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TCP_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TCP_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TCP_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_TD_CTRL3 */ + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TD_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__THROTTLE_POLICY_MASK, DIDT_TD_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TD_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TD_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TD_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + /*DIDT_DB_CTRL3 */ + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_DB_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__THROTTLE_POLICY_MASK, DIDT_DB_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_DB_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_SEL_MASK, DIDT_DB_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_DB_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl2Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853 }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000 }, + + /* DIDT_TD */ + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + /* DIDT_DB */ + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__MAX_POWER_DELTA_MASK, DIDT_DB_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, + { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl1Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_TD */ + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff }, + /* DIDT_DB */ + { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MIN_POWER_MASK, DIDT_DB_CTRL1__MIN_POWER__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MAX_POWER_MASK, DIDT_DB_CTRL1__MAX_POWER__SHIFT, 0xffff }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEDiDtWeightConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B363B1A }, + { ixDIDT_SQ_WEIGHT4_7, 0xFFFFFFFF, 0, 0x270B2432 }, + { ixDIDT_SQ_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000018 }, + + /* DIDT_TD */ + { ixDIDT_TD_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B1D220F }, + { ixDIDT_TD_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00007558 }, + { ixDIDT_TD_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, + + /* DIDT_TCP */ + { ixDIDT_TCP_WEIGHT0_3, 0xFFFFFFFF, 0, 0x5ACE160D }, + { ixDIDT_TCP_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, + + /* DIDT_DB */ + { ixDIDT_DB_WEIGHT0_3, 0xFFFFFFFF, 0, 0x0E152A0F }, + { ixDIDT_DB_WEIGHT4_7, 0xFFFFFFFF, 0, 0x09061813 }, + { ixDIDT_DB_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000013 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtCtrl0Config_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_TD */ + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_TCP */ + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + /* DIDT_DB */ + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__PHASE_OFFSET_MASK, DIDT_DB_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_RST_MASK, DIDT_DB_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, + { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEDiDtStallCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ */ + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_TD */ + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_TCP */ + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + /* DIDT_DB */ + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, + { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEDiDtStallPatternConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* DIDT_SQ_STALL_PATTERN_1_2 */ + { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_SQ_STALL_PATTERN_3_4 */ + { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_SQ_STALL_PATTERN_5_6 */ + { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_SQ_STALL_PATTERN_7 */ + { ixDIDT_SQ_STALL_PATTERN_7, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_TCP_STALL_PATTERN_1_2 */ + { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_TCP_STALL_PATTERN_3_4 */ + { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_TCP_STALL_PATTERN_5_6 */ + { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_TCP_STALL_PATTERN_7 */ + { ixDIDT_TCP_STALL_PATTERN_7, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_TD_STALL_PATTERN_1_2 */ + { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_TD_STALL_PATTERN_3_4 */ + { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_TD_STALL_PATTERN_5_6 */ + { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_TD_STALL_PATTERN_7 */ + { ixDIDT_TD_STALL_PATTERN_7, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + /* DIDT_DB_STALL_PATTERN_1_2 */ + { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, + { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, + + /* DIDT_DB_STALL_PATTERN_3_4 */ + { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, + { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, + + /* DIDT_DB_STALL_PATTERN_5_6 */ + { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, + { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, + + /* DIDT_DB_STALL_PATTERN_7 */ + { ixDIDT_DB_STALL_PATTERN_7, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SELCacConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860021 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060021 }, + /* TD */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x028E0020 }, + /* TCP */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x001c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x009c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x011c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x019c0020 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x021c0020 }, + /* DB */ + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00200008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00820008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01020008 }, + { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01820008 }, + + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg SEEDCStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00030001 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x000F0007 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x003F001F }, + { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x0000007F }, + /* TD */ + { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* TCP */ + { ixDIDT_TCP_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* DB */ + { ixDIDT_DB_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_DB_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCForceStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + /* TD */ + { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, + { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCStallDelayConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* TD */ + { ixDIDT_TD_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TD_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* TCP */ + { ixDIDT_TCP_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, + { ixDIDT_TCP_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, + /* DB */ + { ixDIDT_DB_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCThresholdConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { ixDIDT_SQ_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0x0000010E }, + { ixDIDT_TD_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + { ixDIDT_TCP_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + { ixDIDT_DB_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlResetConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0004 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0006 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg SEEDCCtrlForceStallConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000C }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + + /* TD */ + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_EN_MASK, DIDT_TD_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK, DIDT_TD_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg GCDiDtDroopCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL_MASK, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL__SHIFT, 0x0000 }, + { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg GCDiDtCtrl0Config_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CTRL_EN_MASK, GC_DIDT_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__PHASE_OFFSET_MASK, GC_DIDT_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_SW_RST_MASK, GC_DIDT_CTRL0__DIDT_SW_RST__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { 0xFFFFFFFF } /* End of list */ +}; + + +static const struct vega10_didt_config_reg PSMSEEDCStallPatternConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC STALL PATTERNs */ + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1__SHIFT, 0x0101 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2__SHIFT, 0x0101 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3__SHIFT, 0x1111 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4__SHIFT, 0x1111 }, + + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5__SHIFT, 0x1515 }, + { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6__SHIFT, 0x1515 }, + + { ixDIDT_SQ_EDC_STALL_PATTERN_7, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7_MASK, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7__SHIFT, 0x5555 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCStallDelayConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC STALL DELAYs */ + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11__SHIFT, 0x0000 }, + + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ13__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCCtrlResetConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC CTRL */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMSEEDCCtrlConfig_Vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + /* SQ EDC CTRL */ + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0003 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, + { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCDroopCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD__SHIFT, 0x0384 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__AVG_PSM_SEL_MASK, GC_EDC_DROOP_CTRL__AVG_PSM_SEL__SHIFT, 0x0001 }, + { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL_MASK, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL__SHIFT, 0x0001 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCCtrlResetConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg PSMGCEDCCtrlConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, + { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg AvfsPSMResetConfig_vega10[]= +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { 0x16A02, 0xFFFFFFFF, 0x0, 0x0000005F }, + { 0x16A05, 0xFFFFFFFF, 0x0, 0x00000001 }, + { 0x16A06, 0x00000001, 0x0, 0x02000000 }, + { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static const struct vega10_didt_config_reg AvfsPSMInitConfig_vega10[] = +{ +/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + * Offset Mask Shift Value + * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + */ + { 0x16A05, 0xFFFFFFFF, 0x18, 0x00000001 }, + { 0x16A05, 0xFFFFFFFF, 0x8, 0x00000003 }, + { 0x16A05, 0xFFFFFFFF, 0xa, 0x00000006 }, + { 0x16A05, 0xFFFFFFFF, 0x7, 0x00000000 }, + { 0x16A06, 0xFFFFFFFF, 0x18, 0x00000001 }, + { 0x16A06, 0xFFFFFFFF, 0x19, 0x00000001 }, + { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, + + { 0xFFFFFFFF } /* End of list */ +}; + +static int vega10_program_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs, enum vega10_didt_config_reg_type reg_type) +{ + uint32_t data; + + PP_ASSERT_WITH_CODE((config_regs != NULL), "[vega10_program_didt_config_registers] Invalid config register table!", return -EINVAL); + + while (config_regs->offset != 0xFFFFFFFF) { + switch (reg_type) { + case VEGA10_CONFIGREG_DIDT: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset, data); + break; + case VEGA10_CONFIGREG_GCCAC: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset, data); + break; + case VEGA10_CONFIGREG_SECAC: + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset, data); + break; + default: + return -EINVAL; + } + + config_regs++; + } + + return 0; +} + +static int vega10_program_gc_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs) +{ + uint32_t data; + + while (config_regs->offset != 0xFFFFFFFF) { + data = cgs_read_register(hwmgr->device, config_regs->offset); + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + cgs_write_register(hwmgr->device, config_regs->offset, data); + config_regs++; + } + + return 0; +} + +static void vega10_didt_set_mask(struct pp_hwmgr *hwmgr, const bool enable) +{ + uint32_t data; + uint32_t en = (enable ? 1 : 0); + uint32_t didt_block_info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; + + if (PP_CAP(PHM_PlatformCaps_SQRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_SQ_CTRL0, DIDT_CTRL_EN, en); + didt_block_info &= ~SQ_Enable_MASK; + didt_block_info |= en << SQ_Enable_SHIFT; + } + + if (PP_CAP(PHM_PlatformCaps_DBRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DB_CTRL0, DIDT_CTRL_EN, en); + didt_block_info &= ~DB_Enable_MASK; + didt_block_info |= en << DB_Enable_SHIFT; + } + + if (PP_CAP(PHM_PlatformCaps_TDRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TD_CTRL0, DIDT_CTRL_EN, en); + didt_block_info &= ~TD_Enable_MASK; + didt_block_info |= en << TD_Enable_SHIFT; + } + + if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_TCP_CTRL0, DIDT_CTRL_EN, en); + didt_block_info &= ~TCP_Enable_MASK; + didt_block_info |= en << TCP_Enable_SHIFT; + } + + if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { + CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, + DIDT_DBR_CTRL0, DIDT_CTRL_EN, en); + } + + if (PP_CAP(PHM_PlatformCaps_DiDtEDCEnable)) { + if (PP_CAP(PHM_PlatformCaps_SQRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL); + data = REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_EN, en); + data = REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_SW_RST, ~en); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL, data); + } + + if (PP_CAP(PHM_PlatformCaps_DBRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL); + data = REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_EN, en); + data = REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_SW_RST, ~en); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL, data); + } + + if (PP_CAP(PHM_PlatformCaps_TDRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL); + data = REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_EN, en); + data = REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_SW_RST, ~en); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL, data); + } + + if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL); + data = REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_EN, en); + data = REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_SW_RST, ~en); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL, data); + } + + if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { + data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL); + data = REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_EN, en); + data = REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_SW_RST, ~en); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL, data); + } + } + + /* For Vega10, SMC does not support any mask yet. */ + if (enable) + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ConfigureGfxDidt, didt_block_info, + NULL); + +} + +static int vega10_enable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + uint32_t num_se = 0, count, data; + + num_se = adev->gfx.config.max_shader_engines; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + mutex_lock(&adev->grbm_idx_mutex); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); + + result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl1Config_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl2Config_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtTuningCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SELCacConfig_Vega10, VEGA10_CONFIGREG_SECAC); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); + mutex_unlock(&adev->grbm_idx_mutex); + + vega10_didt_set_mask(hwmgr, true); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + return 0; +} + +static int vega10_disable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + vega10_didt_set_mask(hwmgr, false); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + return 0; +} + +static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + uint32_t num_se = 0, count, data; + + num_se = adev->gfx.config.max_shader_engines; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + mutex_lock(&adev->grbm_idx_mutex); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); + + result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); + if (0 != result) + break; + } + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); + mutex_unlock(&adev->grbm_idx_mutex); + + vega10_didt_set_mask(hwmgr, true); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + vega10_program_gc_didt_config_registers(hwmgr, GCDiDtDroopCtrlConfig_vega10); + if (PP_CAP(PHM_PlatformCaps_GCEDC)) + vega10_program_gc_didt_config_registers(hwmgr, GCDiDtCtrl0Config_vega10); + + if (PP_CAP(PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); + + return 0; +} + +static int vega10_disable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t data; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + vega10_didt_set_mask(hwmgr, false); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { + data = 0x00000000; + cgs_write_register(hwmgr->device, mmGC_DIDT_CTRL0, data); + } + + if (PP_CAP(PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + return 0; +} + +static int vega10_enable_se_edc_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + uint32_t num_se = 0, count, data; + + num_se = adev->gfx.config.max_shader_engines; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + mutex_lock(&adev->grbm_idx_mutex); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); + result = vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCThresholdConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); + mutex_unlock(&adev->grbm_idx_mutex); + + vega10_didt_set_mask(hwmgr, true); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + return 0; +} + +static int vega10_disable_se_edc_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + vega10_didt_set_mask(hwmgr, false); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + return 0; +} + +static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result = 0; + uint32_t num_se = 0; + uint32_t count, data; + + num_se = adev->gfx.config.max_shader_engines; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + mutex_lock(&adev->grbm_idx_mutex); + for (count = 0; count < num_se; count++) { + data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); + result = vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); + + if (0 != result) + break; + } + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); + mutex_unlock(&adev->grbm_idx_mutex); + + vega10_didt_set_mask(hwmgr, true); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCDroopCtrlConfig_vega10); + + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlResetConfig_vega10); + vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlConfig_vega10); + } + + if (PP_CAP(PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); + + return 0; +} + +static int vega10_disable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t data; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + vega10_didt_set_mask(hwmgr, false); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + if (PP_CAP(PHM_PlatformCaps_GCEDC)) { + data = 0x00000000; + cgs_write_register(hwmgr->device, mmGC_EDC_CTRL, data); + } + + if (PP_CAP(PHM_PlatformCaps_PSM)) + vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); + + return 0; +} + +static int vega10_enable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int result; + + amdgpu_gfx_rlc_enter_safe_mode(adev); + + mutex_lock(&adev->grbm_idx_mutex); + WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); + mutex_unlock(&adev->grbm_idx_mutex); + + result = vega10_program_didt_config_registers(hwmgr, SEEDCForceStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); + result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlForceStallConfig_Vega10, VEGA10_CONFIGREG_DIDT); + if (0 != result) + return result; + + vega10_didt_set_mask(hwmgr, false); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + + return 0; +} + +static int vega10_disable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) +{ + int result; + + result = vega10_disable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Pre DIDT disable clock gating failed!", return result); + + return 0; +} + +int vega10_enable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DIDT].supported) { + if (data->smu_features[GNLD_DIDT].enabled) + PP_DBG_LOG("[EnableDiDtConfig] Feature DiDt Already enabled!\n"); + + switch (data->registry_data.didt_mode) { + case 0: + result = vega10_enable_cac_driving_se_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 0 Failed!", return result); + break; + case 2: + result = vega10_enable_psm_gc_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 2 Failed!", return result); + break; + case 3: + result = vega10_enable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 3 Failed!", return result); + break; + case 1: + case 4: + case 5: + result = vega10_enable_psm_gc_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 5 Failed!", return result); + break; + case 6: + result = vega10_enable_se_edc_force_stall_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 6 Failed!", return result); + break; + default: + result = -EINVAL; + break; + } + + if (0 == result) { + result = vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); + data->smu_features[GNLD_DIDT].enabled = true; + } + } + + return result; +} + +int vega10_disable_didt_config(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_DIDT].supported) { + if (!data->smu_features[GNLD_DIDT].enabled) + PP_DBG_LOG("[DisableDiDtConfig] Feature DiDt Already Disabled!\n"); + + switch (data->registry_data.didt_mode) { + case 0: + result = vega10_disable_cac_driving_se_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 0 Failed!", return result); + break; + case 2: + result = vega10_disable_psm_gc_didt_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 2 Failed!", return result); + break; + case 3: + result = vega10_disable_se_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 3 Failed!", return result); + break; + case 1: + case 4: + case 5: + result = vega10_disable_psm_gc_edc_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 5 Failed!", return result); + break; + case 6: + result = vega10_disable_se_edc_force_stall_config(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 6 Failed!", return result); + break; + default: + result = -EINVAL; + break; + } + + if (0 == result) { + result = vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); + data->smu_features[GNLD_DIDT].enabled = false; + } + } + + return result; +} + +void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = table_info->tdp_table; + PPTable_t *table = &(data->smc_state_table.pp_table); + + table->SocketPowerLimit = cpu_to_le16( + tdp_table->usMaximumPowerDeliveryLimit); + table->TdcLimit = cpu_to_le16(tdp_table->usTDC); + table->EdcLimit = cpu_to_le16(tdp_table->usEDCLimit); + table->TedgeLimit = cpu_to_le16(tdp_table->usTemperatureLimitTedge); + table->ThotspotLimit = cpu_to_le16(tdp_table->usTemperatureLimitHotspot); + table->ThbmLimit = cpu_to_le16(tdp_table->usTemperatureLimitHBM); + table->Tvr_socLimit = cpu_to_le16(tdp_table->usTemperatureLimitVrVddc); + table->Tvr_memLimit = cpu_to_le16(tdp_table->usTemperatureLimitVrMvdd); + table->Tliquid1Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid1); + table->Tliquid2Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid2); + table->TplxLimit = cpu_to_le16(tdp_table->usTemperatureLimitPlx); + table->LoadLineResistance = + hwmgr->platform_descriptor.LoadLineSlope * 256; + table->FitLimit = 0; /* Not used for Vega10 */ + + table->Liquid1_I2C_address = tdp_table->ucLiquid1_I2C_address; + table->Liquid2_I2C_address = tdp_table->ucLiquid2_I2C_address; + table->Vr_I2C_address = tdp_table->ucVr_I2C_address; + table->Plx_I2C_address = tdp_table->ucPlx_I2C_address; + + table->Liquid_I2C_LineSCL = tdp_table->ucLiquid_I2C_Line; + table->Liquid_I2C_LineSDA = tdp_table->ucLiquid_I2C_LineSDA; + + table->Vr_I2C_LineSCL = tdp_table->ucVr_I2C_Line; + table->Vr_I2C_LineSDA = tdp_table->ucVr_I2C_LineSDA; + + table->Plx_I2C_LineSCL = tdp_table->ucPlx_I2C_Line; + table->Plx_I2C_LineSDA = tdp_table->ucPlx_I2C_LineSDA; +} + +int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->registry_data.enable_pkg_pwr_tracking_feature) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetPptLimit, n, + NULL); + + return 0; +} + +int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = table_info->tdp_table; + int result = 0; + + hwmgr->default_power_limit = hwmgr->power_limit = + (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit); + + if (!hwmgr->not_vf) + return 0; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + if (data->smu_features[GNLD_PPT].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_PPT].smu_feature_bitmap), + "Attempt to enable PPT feature Failed!", + data->smu_features[GNLD_PPT].supported = false); + + if (data->smu_features[GNLD_TDC].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, data->smu_features[GNLD_TDC].smu_feature_bitmap), + "Attempt to enable PPT feature Failed!", + data->smu_features[GNLD_TDC].supported = false); + + result = vega10_set_power_limit(hwmgr, hwmgr->power_limit); + PP_ASSERT_WITH_CODE(!result, + "Failed to set Default Power Limit in SMC!", + return result); + } + + return result; +} + +int vega10_disable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + if (data->smu_features[GNLD_PPT].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_PPT].smu_feature_bitmap), + "Attempt to disable PPT feature Failed!", + data->smu_features[GNLD_PPT].supported = false); + + if (data->smu_features[GNLD_TDC].supported) + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, data->smu_features[GNLD_TDC].smu_feature_bitmap), + "Attempt to disable PPT feature Failed!", + data->smu_features[GNLD_TDC].supported = false); + } + + return 0; +} + +static void vega10_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, + uint32_t adjust_percent) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_OverDriveSetPercentage, adjust_percent, + NULL); +} + +int vega10_power_control_set_level(struct pp_hwmgr *hwmgr) +{ + int adjust_percent; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + adjust_percent = + hwmgr->platform_descriptor.TDPAdjustmentPolarity ? + hwmgr->platform_descriptor.TDPAdjustment : + (-1 * hwmgr->platform_descriptor.TDPAdjustment); + vega10_set_overdrive_target_percentage(hwmgr, + (uint32_t)adjust_percent); + } + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h new file mode 100644 index 000000000000..b95771ab89cd --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_powertune.h @@ -0,0 +1,82 @@ +/* + * Copyright 2016 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 _VEGA10_POWERTUNE_H_ +#define _VEGA10_POWERTUNE_H_ + +enum vega10_pt_config_reg_type { + VEGA10_CONFIGREG_MMR = 0, + VEGA10_CONFIGREG_SMC_IND, + VEGA10_CONFIGREG_DIDT_IND, + VEGA10_CONFIGREG_CACHE, + VEGA10_CONFIGREG_MAX +}; + +enum vega10_didt_config_reg_type { + VEGA10_CONFIGREG_DIDT = 0, + VEGA10_CONFIGREG_GCCAC, + VEGA10_CONFIGREG_SECAC +}; + +/* PowerContainment Features */ +#define POWERCONTAINMENT_FEATURE_DTE 0x00000001 +#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 +#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 + +struct vega10_pt_config_reg { + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; + enum vega10_pt_config_reg_type type; +}; + +struct vega10_didt_config_reg { + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; +}; + +struct vega10_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; +}; + +void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); +int vega10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); +int vega10_populate_pm_fuses(struct pp_hwmgr *hwmgr); +int vega10_enable_smc_cac(struct pp_hwmgr *hwmgr); +int vega10_enable_power_containment(struct pp_hwmgr *hwmgr); +int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); +int vega10_power_control_set_level(struct pp_hwmgr *hwmgr); +int vega10_disable_power_containment(struct pp_hwmgr *hwmgr); + +int vega10_enable_didt_config(struct pp_hwmgr *hwmgr); +int vega10_disable_didt_config(struct pp_hwmgr *hwmgr); + +#endif /* _VEGA10_POWERTUNE_H_ */ + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h new file mode 100644 index 000000000000..c934e9612c1b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_pptable.h @@ -0,0 +1,445 @@ +/* + * Copyright 2016 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 _VEGA10_PPTABLE_H_ +#define _VEGA10_PPTABLE_H_ + +#pragma pack(push, 1) + +#define ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_VEGA10_PP_FANPARAMETERS_NOFAN 0x80 + +#define ATOM_VEGA10_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_VEGA10_PP_THERMALCONTROLLER_LM96163 17 +#define ATOM_VEGA10_PP_THERMALCONTROLLER_VEGA10 24 + +#define ATOM_VEGA10_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 +#define ATOM_VEGA10_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D + +#define ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY 0x1 +#define ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 +#define ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC 0x4 +#define ATOM_VEGA10_PP_PLATFORM_CAP_BACO 0x8 +#define ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x10 + + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +/* 2, 4, 6, 7 are reserved */ + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 + +#define ATOM_Vega10_DISALLOW_ON_DC 0x00004000 +#define ATOM_Vega10_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_Vega10_TABLE_REVISION_VEGA10 8 + +#define ATOM_Vega10_VoltageMode_AVFS_Interpolate 0 +#define ATOM_Vega10_VoltageMode_AVFS_WorstCase 1 +#define ATOM_Vega10_VoltageMode_Static 2 + +typedef struct _ATOM_Vega10_POWERPLAYTABLE { + struct atom_common_table_header sHeader; + UCHAR ucTableRevision; + USHORT usTableSize; /* the size of header structure */ + ULONG ulGoldenPPID; /* PPGen use only */ + ULONG ulGoldenRevision; /* PPGen use only */ + USHORT usFormatID; /* PPGen use only */ + ULONG ulPlatformCaps; /* See ATOM_Vega10_CAPS_* */ + ULONG ulMaxODEngineClock; /* For Overdrive. */ + ULONG ulMaxODMemoryClock; /* For Overdrive. */ + USHORT usPowerControlLimit; + USHORT usUlvVoltageOffset; /* in mv units */ + USHORT usUlvSmnclkDid; + USHORT usUlvMp1clkDid; + USHORT usUlvGfxclkBypass; + USHORT usGfxclkSlewRate; + UCHAR ucGfxVoltageMode; + UCHAR ucSocVoltageMode; + UCHAR ucUclkVoltageMode; + UCHAR ucUvdVoltageMode; + UCHAR ucVceVoltageMode; + UCHAR ucMp0VoltageMode; + UCHAR ucDcefVoltageMode; + USHORT usStateArrayOffset; /* points to ATOM_Vega10_State_Array */ + USHORT usFanTableOffset; /* points to ATOM_Vega10_Fan_Table */ + USHORT usThermalControllerOffset; /* points to ATOM_Vega10_Thermal_Controller */ + USHORT usSocclkDependencyTableOffset; /* points to ATOM_Vega10_SOCCLK_Dependency_Table */ + USHORT usMclkDependencyTableOffset; /* points to ATOM_Vega10_MCLK_Dependency_Table */ + USHORT usGfxclkDependencyTableOffset; /* points to ATOM_Vega10_GFXCLK_Dependency_Table */ + USHORT usDcefclkDependencyTableOffset; /* points to ATOM_Vega10_DCEFCLK_Dependency_Table */ + USHORT usVddcLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ + USHORT usVddmemLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ + USHORT usMMDependencyTableOffset; /* points to ATOM_Vega10_MM_Dependency_Table */ + USHORT usVCEStateTableOffset; /* points to ATOM_Vega10_VCE_State_Table */ + USHORT usReserve; /* No PPM Support for Vega10 */ + USHORT usPowerTuneTableOffset; /* points to ATOM_Vega10_PowerTune_Table */ + USHORT usHardLimitTableOffset; /* points to ATOM_Vega10_Hard_Limit_Table */ + USHORT usVddciLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ + USHORT usPCIETableOffset; /* points to ATOM_Vega10_PCIE_Table */ + USHORT usPixclkDependencyTableOffset; /* points to ATOM_Vega10_PIXCLK_Dependency_Table */ + USHORT usDispClkDependencyTableOffset; /* points to ATOM_Vega10_DISPCLK_Dependency_Table */ + USHORT usPhyClkDependencyTableOffset; /* points to ATOM_Vega10_PHYCLK_Dependency_Table */ +} ATOM_Vega10_POWERPLAYTABLE; + +typedef struct _ATOM_Vega10_State { + UCHAR ucSocClockIndexHigh; + UCHAR ucSocClockIndexLow; + UCHAR ucGfxClockIndexHigh; + UCHAR ucGfxClockIndexLow; + UCHAR ucMemClockIndexHigh; + UCHAR ucMemClockIndexLow; + USHORT usClassification; + ULONG ulCapsAndSettings; + USHORT usClassification2; +} ATOM_Vega10_State; + +typedef struct _ATOM_Vega10_State_Array { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_State states[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_State_Array; + +typedef struct _ATOM_Vega10_CLK_Dependency_Record { + ULONG ulClk; /* Frequency of Clock */ + UCHAR ucVddInd; /* Base voltage */ +} ATOM_Vega10_CLK_Dependency_Record; + +typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record { + ULONG ulClk; /* Clock Frequency */ + UCHAR ucVddInd; /* SOC_VDD index */ + USHORT usCKSVOffsetandDisable; /* Bits 0~30: Voltage offset for CKS, Bit 31: Disable/enable for the GFXCLK level. */ + USHORT usAVFSOffset; /* AVFS Voltage offset */ +} ATOM_Vega10_GFXCLK_Dependency_Record; + +typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record_V2 { + ULONG ulClk; + UCHAR ucVddInd; + USHORT usCKSVOffsetandDisable; + USHORT usAVFSOffset; + UCHAR ucACGEnable; + UCHAR ucReserved[3]; +} ATOM_Vega10_GFXCLK_Dependency_Record_V2; + +typedef struct _ATOM_Vega10_MCLK_Dependency_Record { + ULONG ulMemClk; /* Clock Frequency */ + UCHAR ucVddInd; /* SOC_VDD index */ + UCHAR ucVddMemInd; /* MEM_VDD - only non zero for MCLK record */ + UCHAR ucVddciInd; /* VDDCI = only non zero for MCLK record */ +} ATOM_Vega10_MCLK_Dependency_Record; + +typedef struct _ATOM_Vega10_GFXCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_GFXCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_GFXCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_MCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_MCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_SOCCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_SOCCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_DCEFCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_DCEFCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_PIXCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_PIXCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_DISPCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries.*/ + ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_DISPCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_PHYCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_PHYCLK_Dependency_Table; + +typedef struct _ATOM_Vega10_MM_Dependency_Record { + UCHAR ucVddcInd; /* SOC_VDD voltage */ + ULONG ulDClk; /* UVD D-clock */ + ULONG ulVClk; /* UVD V-clock */ + ULONG ulEClk; /* VCE clock */ + ULONG ulPSPClk; /* PSP clock */ +} ATOM_Vega10_MM_Dependency_Record; + +typedef struct _ATOM_Vega10_MM_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries */ + ATOM_Vega10_MM_Dependency_Record entries[1]; /* Dynamically allocate entries */ +} ATOM_Vega10_MM_Dependency_Table; + +typedef struct _ATOM_Vega10_PCIE_Record { + ULONG ulLCLK; /* LClock */ + UCHAR ucPCIEGenSpeed; /* PCIE Speed */ + UCHAR ucPCIELaneWidth; /* PCIE Lane Width */ +} ATOM_Vega10_PCIE_Record; + +typedef struct _ATOM_Vega10_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries */ + ATOM_Vega10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Vega10_PCIE_Table; + +typedef struct _ATOM_Vega10_Voltage_Lookup_Record { + USHORT usVdd; /* Base voltage */ +} ATOM_Vega10_Voltage_Lookup_Record; + +typedef struct _ATOM_Vega10_Voltage_Lookup_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries */ + ATOM_Vega10_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries */ +} ATOM_Vega10_Voltage_Lookup_Table; + +typedef struct _ATOM_Vega10_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes. */ + USHORT usFanRPMMax; /* The default value in RPM. */ + USHORT usThrottlingRPM; + USHORT usFanAcousticLimit; /* Minimum Fan Controller Frequency Acoustic Limit. */ + USHORT usTargetTemperature; /* The default ideal temperature in Celcius. */ + USHORT usMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. */ + USHORT usTargetGfxClk; /* The ideal Fan Controller GFXCLK Frequency Acoustic Limit. */ + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + UCHAR ucEnableZeroRPM; + USHORT usFanStopTemperature; + USHORT usFanStartTemperature; +} ATOM_Vega10_Fan_Table; + +typedef struct _ATOM_Vega10_Fan_Table_V2 { + UCHAR ucRevId; + USHORT usFanOutputSensitivity; + USHORT usFanAcousticLimitRpm; + USHORT usThrottlingRPM; + USHORT usTargetTemperature; + USHORT usMinimumPWMLimit; + USHORT usTargetGfxClk; + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + UCHAR ucEnableZeroRPM; + USHORT usFanStopTemperature; + USHORT usFanStartTemperature; + UCHAR ucFanParameters; + UCHAR ucFanMinRPM; + UCHAR ucFanMaxRPM; +} ATOM_Vega10_Fan_Table_V2; + +typedef struct _ATOM_Vega10_Fan_Table_V3 { + UCHAR ucRevId; + USHORT usFanOutputSensitivity; + USHORT usFanAcousticLimitRpm; + USHORT usThrottlingRPM; + USHORT usTargetTemperature; + USHORT usMinimumPWMLimit; + USHORT usTargetGfxClk; + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + UCHAR ucEnableZeroRPM; + USHORT usFanStopTemperature; + USHORT usFanStartTemperature; + UCHAR ucFanParameters; + UCHAR ucFanMinRPM; + UCHAR ucFanMaxRPM; + USHORT usMGpuThrottlingRPM; +} ATOM_Vega10_Fan_Table_V3; + +typedef struct _ATOM_Vega10_Thermal_Controller { + UCHAR ucRevId; + UCHAR ucType; /* one of ATOM_VEGA10_PP_THERMALCONTROLLER_*/ + UCHAR ucI2cLine; /* as interpreted by DAL I2C */ + UCHAR ucI2cAddress; + UCHAR ucFanParameters; /* Fan Control Parameters. */ + UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only.*/ + UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only.*/ + UCHAR ucFlags; /* to be defined */ +} ATOM_Vega10_Thermal_Controller; + +typedef struct _ATOM_Vega10_VCE_State_Record +{ + UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Vega10_MM_Dependency_Table' type */ + UCHAR ucFlag; /* 2 bits indicates memory p-states */ + UCHAR ucSCLKIndex; /* index into ATOM_Vega10_SCLK_Dependency_Table */ + UCHAR ucMCLKIndex; /* index into ATOM_Vega10_MCLK_Dependency_Table */ +} ATOM_Vega10_VCE_State_Record; + +typedef struct _ATOM_Vega10_VCE_State_Table +{ + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Vega10_VCE_State_Record entries[1]; +} ATOM_Vega10_VCE_State_Table; + +typedef struct _ATOM_Vega10_PowerTune_Table { + UCHAR ucRevId; + USHORT usSocketPowerLimit; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usTdcLimit; + USHORT usEdcLimit; + USHORT usSoftwareShutdownTemp; + USHORT usTemperatureLimitHotSpot; + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitHBM; + USHORT usTemperatureLimitVrSoc; + USHORT usTemperatureLimitVrMem; + USHORT usTemperatureLimitPlx; + USHORT usLoadLineResistance; + UCHAR ucLiquid1_I2C_address; + UCHAR ucLiquid2_I2C_address; + UCHAR ucVr_I2C_address; + UCHAR ucPlx_I2C_address; + UCHAR ucLiquid_I2C_LineSCL; + UCHAR ucLiquid_I2C_LineSDA; + UCHAR ucVr_I2C_LineSCL; + UCHAR ucVr_I2C_LineSDA; + UCHAR ucPlx_I2C_LineSCL; + UCHAR ucPlx_I2C_LineSDA; + USHORT usTemperatureLimitTedge; +} ATOM_Vega10_PowerTune_Table; + +typedef struct _ATOM_Vega10_PowerTune_Table_V2 +{ + UCHAR ucRevId; + USHORT usSocketPowerLimit; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usTdcLimit; + USHORT usEdcLimit; + USHORT usSoftwareShutdownTemp; + USHORT usTemperatureLimitHotSpot; + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitHBM; + USHORT usTemperatureLimitVrSoc; + USHORT usTemperatureLimitVrMem; + USHORT usTemperatureLimitPlx; + USHORT usLoadLineResistance; + UCHAR ucLiquid1_I2C_address; + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; + UCHAR ucPlx_I2C_Line; + USHORT usTemperatureLimitTedge; +} ATOM_Vega10_PowerTune_Table_V2; + +typedef struct _ATOM_Vega10_PowerTune_Table_V3 +{ + UCHAR ucRevId; + USHORT usSocketPowerLimit; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usTdcLimit; + USHORT usEdcLimit; + USHORT usSoftwareShutdownTemp; + USHORT usTemperatureLimitHotSpot; + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitHBM; + USHORT usTemperatureLimitVrSoc; + USHORT usTemperatureLimitVrMem; + USHORT usTemperatureLimitPlx; + USHORT usLoadLineResistance; + UCHAR ucLiquid1_I2C_address; + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; + UCHAR ucPlx_I2C_Line; + USHORT usTemperatureLimitTedge; + USHORT usBoostStartTemperature; + USHORT usBoostStopTemperature; + ULONG ulBoostClock; + ULONG Reserved[2]; +} ATOM_Vega10_PowerTune_Table_V3; + +typedef struct _ATOM_Vega10_Hard_Limit_Record { + ULONG ulSOCCLKLimit; + ULONG ulGFXCLKLimit; + ULONG ulMCLKLimit; + USHORT usVddcLimit; + USHORT usVddciLimit; + USHORT usVddMemLimit; +} ATOM_Vega10_Hard_Limit_Record; + +typedef struct _ATOM_Vega10_Hard_Limit_Table +{ + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Vega10_Hard_Limit_Record entries[1]; +} ATOM_Vega10_Hard_Limit_Table; + +typedef struct _Vega10_PPTable_Generic_SubTable_Header +{ + UCHAR ucRevId; +} Vega10_PPTable_Generic_SubTable_Header; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c new file mode 100644 index 000000000000..f29af5ca0aa0 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.c @@ -0,0 +1,1398 @@ +/* + * Copyright 2016 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 +#include +#include +#include + +#include "vega10_processpptables.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "pp_debug.h" +#include "cgs_common.h" +#include "vega10_pptable.h" + +#define NUM_DSPCLK_LEVELS 8 +#define VEGA10_ENGINECLOCK_HARDMAX 198000 + +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, + enum phm_platform_caps cap) +{ + if (enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + +static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterDataTable(powerplayinfo); + + u16 size; + u8 frev, crev; + const void *table_address = hwmgr->soft_pp_table; + + if (!table_address) { + table_address = (ATOM_Vega10_POWERPLAYTABLE *) + smu_atom_get_data_table(hwmgr->adev, index, + &size, &frev, &crev); + + hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ + hwmgr->soft_pp_table_size = size; + } + + return table_address; +} + +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) +{ + const ATOM_Vega10_State_Array *state_arrays; + + state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= + ATOM_Vega10_TABLE_REVISION_VEGA10), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE(powerplay_table->usStateArrayOffset, + "State table is not set!", return -1); + PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, + "Invalid PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, + "Invalid PowerPlay Table!", return -1); + + return 0; +} + +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal); + + return 0; +} + +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) +{ + const ATOM_Vega10_Thermal_Controller *thermal_controller; + const Vega10_PPTable_Generic_SubTable_Header *header; + const ATOM_Vega10_Fan_Table *fan_table_v1; + const ATOM_Vega10_Fan_Table_V2 *fan_table_v2; + const ATOM_Vega10_Fan_Table_V3 *fan_table_v3; + + thermal_controller = (ATOM_Vega10_Thermal_Controller *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usThermalControllerOffset)); + + PP_ASSERT_WITH_CODE((powerplay_table->usThermalControllerOffset != 0), + "Thermal controller table not set!", return -EINVAL); + + hwmgr->thermal_controller.ucType = thermal_controller->ucType; + hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (thermal_controller->ucFanParameters & + ATOM_VEGA10_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + thermal_controller->ucFanParameters & + ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM = + thermal_controller->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM = + thermal_controller->ucFanMaxRPM * 100UL; + + hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay + = 100000; + + set_hw_cap( + hwmgr, + ATOM_VEGA10_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController); + + if (!powerplay_table->usFanTableOffset) + return 0; + + header = (const Vega10_PPTable_Generic_SubTable_Header *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usFanTableOffset)); + + if (header->ucRevId == 10) { + fan_table_v1 = (ATOM_Vega10_Fan_Table *)header; + + PP_ASSERT_WITH_CODE((fan_table_v1->ucRevId >= 8), + "Invalid Input Fan Table!", return -EINVAL); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + le16_to_cpu(fan_table_v1->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = + le16_to_cpu(fan_table_v1->usFanRPMMax); + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = + le16_to_cpu(fan_table_v1->usThrottlingRPM); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = + le16_to_cpu(fan_table_v1->usFanAcousticLimit); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax = + le16_to_cpu(fan_table_v1->usTargetTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = + le16_to_cpu(fan_table_v1->usMinimumPWMLimit); + hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = + le16_to_cpu(fan_table_v1->usTargetGfxClk); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = + le16_to_cpu(fan_table_v1->usFanGainEdge); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = + le16_to_cpu(fan_table_v1->usFanGainHotspot); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = + le16_to_cpu(fan_table_v1->usFanGainLiquid); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = + le16_to_cpu(fan_table_v1->usFanGainVrVddc); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = + le16_to_cpu(fan_table_v1->usFanGainVrMvdd); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = + le16_to_cpu(fan_table_v1->usFanGainPlx); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = + le16_to_cpu(fan_table_v1->usFanGainHbm); + + hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = + fan_table_v1->ucEnableZeroRPM; + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = + le16_to_cpu(fan_table_v1->usFanStopTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = + le16_to_cpu(fan_table_v1->usFanStartTemperature); + } else if (header->ucRevId == 0xb) { + fan_table_v2 = (ATOM_Vega10_Fan_Table_V2 *)header; + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + fan_table_v2->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v2->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v2->ucFanMaxRPM * 100UL; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + le16_to_cpu(fan_table_v2->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = + fan_table_v2->ucFanMaxRPM * 100UL; + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = + le16_to_cpu(fan_table_v2->usThrottlingRPM); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = + le16_to_cpu(fan_table_v2->usFanAcousticLimitRpm); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax = + le16_to_cpu(fan_table_v2->usTargetTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = + le16_to_cpu(fan_table_v2->usMinimumPWMLimit); + hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = + le16_to_cpu(fan_table_v2->usTargetGfxClk); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = + le16_to_cpu(fan_table_v2->usFanGainEdge); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = + le16_to_cpu(fan_table_v2->usFanGainHotspot); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = + le16_to_cpu(fan_table_v2->usFanGainLiquid); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = + le16_to_cpu(fan_table_v2->usFanGainVrVddc); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = + le16_to_cpu(fan_table_v2->usFanGainVrMvdd); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = + le16_to_cpu(fan_table_v2->usFanGainPlx); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = + le16_to_cpu(fan_table_v2->usFanGainHbm); + + hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = + fan_table_v2->ucEnableZeroRPM; + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = + le16_to_cpu(fan_table_v2->usFanStopTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = + le16_to_cpu(fan_table_v2->usFanStartTemperature); + } else if (header->ucRevId > 0xb) { + fan_table_v3 = (ATOM_Vega10_Fan_Table_V3 *)header; + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + fan_table_v3->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v3->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v3->ucFanMaxRPM * 100UL; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + le16_to_cpu(fan_table_v3->usFanOutputSensitivity); + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = + fan_table_v3->ucFanMaxRPM * 100UL; + hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = + le16_to_cpu(fan_table_v3->usThrottlingRPM); + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = + le16_to_cpu(fan_table_v3->usFanAcousticLimitRpm); + hwmgr->thermal_controller.advanceFanControlParameters.usTMax = + le16_to_cpu(fan_table_v3->usTargetTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = + le16_to_cpu(fan_table_v3->usMinimumPWMLimit); + hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = + le16_to_cpu(fan_table_v3->usTargetGfxClk); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = + le16_to_cpu(fan_table_v3->usFanGainEdge); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = + le16_to_cpu(fan_table_v3->usFanGainHotspot); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = + le16_to_cpu(fan_table_v3->usFanGainLiquid); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = + le16_to_cpu(fan_table_v3->usFanGainVrVddc); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = + le16_to_cpu(fan_table_v3->usFanGainVrMvdd); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = + le16_to_cpu(fan_table_v3->usFanGainPlx); + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = + le16_to_cpu(fan_table_v3->usFanGainHbm); + + hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = + fan_table_v3->ucEnableZeroRPM; + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = + le16_to_cpu(fan_table_v3->usFanStopTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = + le16_to_cpu(fan_table_v3->usFanStartTemperature); + hwmgr->thermal_controller.advanceFanControlParameters.usMGpuThrottlingRPMLimit = + le16_to_cpu(fan_table_v3->usMGpuThrottlingRPM); + } + + return 0; +} + +static int init_over_drive_limits( + struct pp_hwmgr *hwmgr, + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) +{ + const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = + (const ATOM_Vega10_GFXCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); + bool is_acg_enabled = false; + ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; + + if (gfxclk_dep_table->ucRevId == 1) { + patom_record_v2 = + (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; + is_acg_enabled = + (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable; + } + + if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX && + !is_acg_enabled) + hwmgr->platform_descriptor.overdriveLimit.engineClock = + VEGA10_ENGINECLOCK_HARDMAX; + else + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le32_to_cpu(powerplay_table->ulMaxODEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le32_to_cpu(powerplay_table->ulMaxODMemoryClock); + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + return 0; +} + +static int get_mm_clock_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table, + const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table) +{ + uint32_t table_size, i; + const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record; + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; + + PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) * + mm_dependency_table->ucNumEntries; + mm_table = kzalloc(table_size, GFP_KERNEL); + + if (!mm_table) + return -ENOMEM; + + mm_table->count = mm_dependency_table->ucNumEntries; + + for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { + mm_dependency_record = &mm_dependency_table->entries[i]; + mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd; + mm_table->entries[i].samclock = + le32_to_cpu(mm_dependency_record->ulPSPClk); + mm_table->entries[i].eclk = le32_to_cpu(mm_dependency_record->ulEClk); + mm_table->entries[i].vclk = le32_to_cpu(mm_dependency_record->ulVClk); + mm_table->entries[i].dclk = le32_to_cpu(mm_dependency_record->ulDClk); + } + + *vega10_mm_table = mm_table; + + return 0; +} + +static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) +{ + switch(line){ + case Vega10_I2CLineID_DDC1: + *scl = Vega10_I2C_DDC1CLK; + *sda = Vega10_I2C_DDC1DATA; + break; + case Vega10_I2CLineID_DDC2: + *scl = Vega10_I2C_DDC2CLK; + *sda = Vega10_I2C_DDC2DATA; + break; + case Vega10_I2CLineID_DDC3: + *scl = Vega10_I2C_DDC3CLK; + *sda = Vega10_I2C_DDC3DATA; + break; + case Vega10_I2CLineID_DDC4: + *scl = Vega10_I2C_DDC4CLK; + *sda = Vega10_I2C_DDC4DATA; + break; + case Vega10_I2CLineID_DDC5: + *scl = Vega10_I2C_DDC5CLK; + *sda = Vega10_I2C_DDC5DATA; + break; + case Vega10_I2CLineID_DDC6: + *scl = Vega10_I2C_DDC6CLK; + *sda = Vega10_I2C_DDC6DATA; + break; + case Vega10_I2CLineID_SCLSDA: + *scl = Vega10_I2C_SCL; + *sda = Vega10_I2C_SDA; + break; + case Vega10_I2CLineID_DDCVGA: + *scl = Vega10_I2C_DDCVGACLK; + *sda = Vega10_I2C_DDCVGADATA; + break; + default: + *scl = 0; + *sda = 0; + break; + } +} + +static int get_tdp_table( + struct pp_hwmgr *hwmgr, + struct phm_tdp_table **info_tdp_table, + const Vega10_PPTable_Generic_SubTable_Header *table) +{ + uint32_t table_size; + struct phm_tdp_table *tdp_table; + uint8_t scl; + uint8_t sda; + const ATOM_Vega10_PowerTune_Table *power_tune_table; + const ATOM_Vega10_PowerTune_Table_V2 *power_tune_table_v2; + const ATOM_Vega10_PowerTune_Table_V3 *power_tune_table_v3; + + table_size = sizeof(uint32_t) + sizeof(struct phm_tdp_table); + + tdp_table = kzalloc(table_size, GFP_KERNEL); + + if (!tdp_table) + return -ENOMEM; + + if (table->ucRevId == 5) { + power_tune_table = (ATOM_Vega10_PowerTune_Table *)table; + tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table->usSocketPowerLimit); + tdp_table->usTDC = le16_to_cpu(power_tune_table->usTdcLimit); + tdp_table->usEDCLimit = le16_to_cpu(power_tune_table->usEdcLimit); + tdp_table->usSoftwareShutdownTemp = + le16_to_cpu(power_tune_table->usSoftwareShutdownTemp); + tdp_table->usTemperatureLimitTedge = + le16_to_cpu(power_tune_table->usTemperatureLimitTedge); + tdp_table->usTemperatureLimitHotspot = + le16_to_cpu(power_tune_table->usTemperatureLimitHotSpot); + tdp_table->usTemperatureLimitLiquid1 = + le16_to_cpu(power_tune_table->usTemperatureLimitLiquid1); + tdp_table->usTemperatureLimitLiquid2 = + le16_to_cpu(power_tune_table->usTemperatureLimitLiquid2); + tdp_table->usTemperatureLimitHBM = + le16_to_cpu(power_tune_table->usTemperatureLimitHBM); + tdp_table->usTemperatureLimitVrVddc = + le16_to_cpu(power_tune_table->usTemperatureLimitVrSoc); + tdp_table->usTemperatureLimitVrMvdd = + le16_to_cpu(power_tune_table->usTemperatureLimitVrMem); + tdp_table->usTemperatureLimitPlx = + le16_to_cpu(power_tune_table->usTemperatureLimitPlx); + tdp_table->ucLiquid1_I2C_address = power_tune_table->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = power_tune_table->ucLiquid2_I2C_address; + tdp_table->ucLiquid_I2C_Line = power_tune_table->ucLiquid_I2C_LineSCL; + tdp_table->ucLiquid_I2C_LineSDA = power_tune_table->ucLiquid_I2C_LineSDA; + tdp_table->ucVr_I2C_address = power_tune_table->ucVr_I2C_address; + tdp_table->ucVr_I2C_Line = power_tune_table->ucVr_I2C_LineSCL; + tdp_table->ucVr_I2C_LineSDA = power_tune_table->ucVr_I2C_LineSDA; + tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address; + tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL; + tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA; + hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(power_tune_table->usLoadLineResistance); + } else if (table->ucRevId == 6) { + power_tune_table_v2 = (ATOM_Vega10_PowerTune_Table_V2 *)table; + tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit); + tdp_table->usTDC = le16_to_cpu(power_tune_table_v2->usTdcLimit); + tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v2->usEdcLimit); + tdp_table->usSoftwareShutdownTemp = + le16_to_cpu(power_tune_table_v2->usSoftwareShutdownTemp); + tdp_table->usTemperatureLimitTedge = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitTedge); + tdp_table->usTemperatureLimitHotspot = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitHotSpot); + tdp_table->usTemperatureLimitLiquid1 = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid1); + tdp_table->usTemperatureLimitLiquid2 = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid2); + tdp_table->usTemperatureLimitHBM = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitHBM); + tdp_table->usTemperatureLimitVrVddc = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrSoc); + tdp_table->usTemperatureLimitVrMvdd = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrMem); + tdp_table->usTemperatureLimitPlx = + le16_to_cpu(power_tune_table_v2->usTemperatureLimitPlx); + tdp_table->ucLiquid1_I2C_address = power_tune_table_v2->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = power_tune_table_v2->ucLiquid2_I2C_address; + + get_scl_sda_value(power_tune_table_v2->ucLiquid_I2C_Line, &scl, &sda); + + tdp_table->ucLiquid_I2C_Line = scl; + tdp_table->ucLiquid_I2C_LineSDA = sda; + + tdp_table->ucVr_I2C_address = power_tune_table_v2->ucVr_I2C_address; + + get_scl_sda_value(power_tune_table_v2->ucVr_I2C_Line, &scl, &sda); + + tdp_table->ucVr_I2C_Line = scl; + tdp_table->ucVr_I2C_LineSDA = sda; + tdp_table->ucPlx_I2C_address = power_tune_table_v2->ucPlx_I2C_address; + + get_scl_sda_value(power_tune_table_v2->ucPlx_I2C_Line, &scl, &sda); + + tdp_table->ucPlx_I2C_Line = scl; + tdp_table->ucPlx_I2C_LineSDA = sda; + + hwmgr->platform_descriptor.LoadLineSlope = + le16_to_cpu(power_tune_table_v2->usLoadLineResistance); + } else { + power_tune_table_v3 = (ATOM_Vega10_PowerTune_Table_V3 *)table; + tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v3->usSocketPowerLimit); + tdp_table->usTDC = le16_to_cpu(power_tune_table_v3->usTdcLimit); + tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v3->usEdcLimit); + tdp_table->usSoftwareShutdownTemp = le16_to_cpu(power_tune_table_v3->usSoftwareShutdownTemp); + tdp_table->usTemperatureLimitTedge = le16_to_cpu(power_tune_table_v3->usTemperatureLimitTedge); + tdp_table->usTemperatureLimitHotspot = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHotSpot); + tdp_table->usTemperatureLimitLiquid1 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid1); + tdp_table->usTemperatureLimitLiquid2 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid2); + tdp_table->usTemperatureLimitHBM = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHBM); + tdp_table->usTemperatureLimitVrVddc = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrSoc); + tdp_table->usTemperatureLimitVrMvdd = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrMem); + tdp_table->usTemperatureLimitPlx = le16_to_cpu(power_tune_table_v3->usTemperatureLimitPlx); + tdp_table->ucLiquid1_I2C_address = power_tune_table_v3->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = power_tune_table_v3->ucLiquid2_I2C_address; + tdp_table->usBoostStartTemperature = le16_to_cpu(power_tune_table_v3->usBoostStartTemperature); + tdp_table->usBoostStopTemperature = le16_to_cpu(power_tune_table_v3->usBoostStopTemperature); + tdp_table->ulBoostClock = le32_to_cpu(power_tune_table_v3->ulBoostClock); + + get_scl_sda_value(power_tune_table_v3->ucLiquid_I2C_Line, &scl, &sda); + + tdp_table->ucLiquid_I2C_Line = scl; + tdp_table->ucLiquid_I2C_LineSDA = sda; + + tdp_table->ucVr_I2C_address = power_tune_table_v3->ucVr_I2C_address; + + get_scl_sda_value(power_tune_table_v3->ucVr_I2C_Line, &scl, &sda); + + tdp_table->ucVr_I2C_Line = scl; + tdp_table->ucVr_I2C_LineSDA = sda; + + tdp_table->ucPlx_I2C_address = power_tune_table_v3->ucPlx_I2C_address; + + get_scl_sda_value(power_tune_table_v3->ucPlx_I2C_Line, &scl, &sda); + + tdp_table->ucPlx_I2C_Line = scl; + tdp_table->ucPlx_I2C_LineSDA = sda; + + hwmgr->platform_descriptor.LoadLineSlope = + le16_to_cpu(power_tune_table_v3->usLoadLineResistance); + } + + *info_tdp_table = tdp_table; + + return 0; +} + +static int get_socclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table, + const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *clk_table; + + PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries, + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_clock_voltage_dependency_record) * + clk_dep_table->ucNumEntries; + + clk_table = kzalloc(table_size, GFP_KERNEL); + + if (!clk_table) + return -ENOMEM; + + clk_table->count = (uint32_t)clk_dep_table->ucNumEntries; + + for (i = 0; i < clk_dep_table->ucNumEntries; i++) { + clk_table->entries[i].vddInd = + clk_dep_table->entries[i].ucVddInd; + clk_table->entries[i].clk = + le32_to_cpu(clk_dep_table->entries[i].ulClk); + } + + *pp_vega10_clk_dep_table = clk_table; + + return 0; +} + +static int get_mclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table, + const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table; + + PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries, + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_clock_voltage_dependency_record) * + mclk_dep_table->ucNumEntries; + + mclk_table = kzalloc(table_size, GFP_KERNEL); + + if (!mclk_table) + return -ENOMEM; + + mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; + + for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { + mclk_table->entries[i].vddInd = + mclk_dep_table->entries[i].ucVddInd; + mclk_table->entries[i].vddciInd = + mclk_dep_table->entries[i].ucVddciInd; + mclk_table->entries[i].mvddInd = + mclk_dep_table->entries[i].ucVddMemInd; + mclk_table->entries[i].clk = + le32_to_cpu(mclk_dep_table->entries[i].ulMemClk); + } + + *pp_vega10_mclk_dep_table = mclk_table; + + return 0; +} + +static int get_gfxclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table + **pp_vega10_clk_dep_table, + const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table) +{ + uint32_t table_size, i; + struct phm_ppt_v1_clock_voltage_dependency_table + *clk_table; + ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; + + PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_clock_voltage_dependency_record) * + clk_dep_table->ucNumEntries; + + clk_table = kzalloc(table_size, GFP_KERNEL); + + if (!clk_table) + return -ENOMEM; + + clk_table->count = clk_dep_table->ucNumEntries; + + if (clk_dep_table->ucRevId == 0) { + for (i = 0; i < clk_table->count; i++) { + clk_table->entries[i].vddInd = + clk_dep_table->entries[i].ucVddInd; + clk_table->entries[i].clk = + le32_to_cpu(clk_dep_table->entries[i].ulClk); + clk_table->entries[i].cks_enable = + (((le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x8000) + >> 15) == 0) ? 1 : 0; + clk_table->entries[i].cks_voffset = + le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x7F; + clk_table->entries[i].sclk_offset = + le16_to_cpu(clk_dep_table->entries[i].usAVFSOffset); + } + } else if (clk_dep_table->ucRevId == 1) { + patom_record_v2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)clk_dep_table->entries; + for (i = 0; i < clk_table->count; i++) { + clk_table->entries[i].vddInd = + patom_record_v2->ucVddInd; + clk_table->entries[i].clk = + le32_to_cpu(patom_record_v2->ulClk); + clk_table->entries[i].cks_enable = + (((le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x8000) + >> 15) == 0) ? 1 : 0; + clk_table->entries[i].cks_voffset = + le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x7F; + clk_table->entries[i].sclk_offset = + le16_to_cpu(patom_record_v2->usAVFSOffset); + patom_record_v2++; + } + } else { + kfree(clk_table); + PP_ASSERT_WITH_CODE(false, + "Unsupported GFXClockDependencyTable Revision!", + return -EINVAL); + } + + *pp_vega10_clk_dep_table = clk_table; + + return 0; +} + +static int get_pix_clk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table + **pp_vega10_clk_dep_table, + const ATOM_Vega10_PIXCLK_Dependency_Table *clk_dep_table) +{ + uint32_t table_size, i; + struct phm_ppt_v1_clock_voltage_dependency_table + *clk_table; + + PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_clock_voltage_dependency_record) * + clk_dep_table->ucNumEntries; + + clk_table = kzalloc(table_size, GFP_KERNEL); + + if (!clk_table) + return -ENOMEM; + + clk_table->count = clk_dep_table->ucNumEntries; + + for (i = 0; i < clk_table->count; i++) { + clk_table->entries[i].vddInd = + clk_dep_table->entries[i].ucVddInd; + clk_table->entries[i].clk = + le32_to_cpu(clk_dep_table->entries[i].ulClk); + } + + *pp_vega10_clk_dep_table = clk_table; + + return 0; +} + +static int get_dcefclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table + **pp_vega10_clk_dep_table, + const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table) +{ + uint32_t table_size, i; + uint8_t num_entries; + struct phm_ppt_v1_clock_voltage_dependency_table + *clk_table; + uint32_t dev_id; + uint32_t rev_id; + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), + "Invalid PowerPlay Table!", return -1); + +/* + * workaround needed to add another DPM level for pioneer cards + * as VBIOS is locked down. + * This DPM level was added to support 3DPM monitors @ 4K120Hz + * + */ + dev_id = adev->pdev->device; + rev_id = adev->pdev->revision; + + if (dev_id == 0x6863 && rev_id == 0 && + clk_dep_table->entries[clk_dep_table->ucNumEntries - 1].ulClk < 90000) + num_entries = clk_dep_table->ucNumEntries + 1 > NUM_DSPCLK_LEVELS ? + NUM_DSPCLK_LEVELS : clk_dep_table->ucNumEntries + 1; + else + num_entries = clk_dep_table->ucNumEntries; + + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_clock_voltage_dependency_record) * + num_entries; + + clk_table = kzalloc(table_size, GFP_KERNEL); + + if (!clk_table) + return -ENOMEM; + + clk_table->count = (uint32_t)num_entries; + + for (i = 0; i < clk_dep_table->ucNumEntries; i++) { + clk_table->entries[i].vddInd = + clk_dep_table->entries[i].ucVddInd; + clk_table->entries[i].clk = + le32_to_cpu(clk_dep_table->entries[i].ulClk); + } + + if (i < num_entries) { + clk_table->entries[i].vddInd = clk_dep_table->entries[i-1].ucVddInd; + clk_table->entries[i].clk = 90000; + } + + *pp_vega10_clk_dep_table = clk_table; + + return 0; +} + +static int get_pcie_table(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_pcie_table **vega10_pcie_table, + const Vega10_PPTable_Generic_SubTable_Header *table) +{ + uint32_t table_size, i, pcie_count; + struct phm_ppt_v1_pcie_table *pcie_table; + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + const ATOM_Vega10_PCIE_Table *atom_pcie_table = + (ATOM_Vega10_PCIE_Table *)table; + + PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries, + "Invalid PowerPlay Table!", + return 0); + + table_size = sizeof(uint32_t) + + sizeof(struct phm_ppt_v1_pcie_record) * + atom_pcie_table->ucNumEntries; + + pcie_table = kzalloc(table_size, GFP_KERNEL); + + if (!pcie_table) + return -ENOMEM; + + pcie_count = table_info->vdd_dep_on_sclk->count; + if (atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = atom_pcie_table->ucNumEntries; + else + pr_info("Number of Pcie Entries exceed the number of" + " GFXCLK Dpm Levels!" + " Disregarding the excess entries...\n"); + + pcie_table->count = pcie_count; + + for (i = 0; i < pcie_count; i++) { + pcie_table->entries[i].gen_speed = + atom_pcie_table->entries[i].ucPCIEGenSpeed; + pcie_table->entries[i].lane_width = + atom_pcie_table->entries[i].ucPCIELaneWidth; + pcie_table->entries[i].pcie_sclk = + atom_pcie_table->entries[i].ulLCLK; + } + + *vega10_pcie_table = pcie_table; + + return 0; +} + +static int get_hard_limits( + struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + const ATOM_Vega10_Hard_Limit_Table *limit_table) +{ + PP_ASSERT_WITH_CODE(limit_table->ucNumEntries, + "Invalid PowerPlay Table!", return -1); + + /* currently we always take entries[0] parameters */ + limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit); + limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit); + limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit); + limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit); + limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit); + limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit); + + return 0; +} + +static int get_valid_clk( + struct pp_hwmgr *hwmgr, + struct phm_clock_array **clk_table, + const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table) +{ + uint32_t table_size, i; + struct phm_clock_array *table; + + PP_ASSERT_WITH_CODE(clk_volt_pp_table->count, + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(uint32_t) * clk_volt_pp_table->count; + + table = kzalloc(table_size, GFP_KERNEL); + + if (!table) + return -ENOMEM; + + table->count = (uint32_t)clk_volt_pp_table->count; + + for (i = 0; i < table->count; i++) + table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; + + *clk_table = table; + + return 0; +} + +static int init_powerplay_extended_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) +{ + int result = 0; + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table = + (const ATOM_Vega10_MM_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); + const Vega10_PPTable_Generic_SubTable_Header *power_tune_table = + (const Vega10_PPTable_Generic_SubTable_Header *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); + const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = + (const ATOM_Vega10_SOCCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); + const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = + (const ATOM_Vega10_GFXCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); + const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table = + (const ATOM_Vega10_DCEFCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset)); + const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = + (const ATOM_Vega10_MCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + const ATOM_Vega10_Hard_Limit_Table *hard_limits = + (const ATOM_Vega10_Hard_Limit_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usHardLimitTableOffset)); + const Vega10_PPTable_Generic_SubTable_Header *pcie_table = + (const Vega10_PPTable_Generic_SubTable_Header *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPCIETableOffset)); + const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table = + (const ATOM_Vega10_PIXCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset)); + const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table = + (const ATOM_Vega10_PHYCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset)); + const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table = + (const ATOM_Vega10_DISPCLK_Dependency_Table *) + (((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset)); + + pp_table_info->vdd_dep_on_socclk = NULL; + pp_table_info->vdd_dep_on_sclk = NULL; + pp_table_info->vdd_dep_on_mclk = NULL; + pp_table_info->vdd_dep_on_dcefclk = NULL; + pp_table_info->mm_dep_table = NULL; + pp_table_info->tdp_table = NULL; + pp_table_info->vdd_dep_on_pixclk = NULL; + pp_table_info->vdd_dep_on_phyclk = NULL; + pp_table_info->vdd_dep_on_dispclk = NULL; + + if (powerplay_table->usMMDependencyTableOffset) + result = get_mm_clock_voltage_table(hwmgr, + &pp_table_info->mm_dep_table, + mm_dependency_table); + + if (!result && powerplay_table->usPowerTuneTableOffset) + result = get_tdp_table(hwmgr, + &pp_table_info->tdp_table, + power_tune_table); + + if (!result && powerplay_table->usSocclkDependencyTableOffset) + result = get_socclk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_socclk, + socclk_dep_table); + + if (!result && powerplay_table->usGfxclkDependencyTableOffset) + result = get_gfxclk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_sclk, + gfxclk_dep_table); + + if (!result && powerplay_table->usPixclkDependencyTableOffset) + result = get_pix_clk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_pixclk, + (const ATOM_Vega10_PIXCLK_Dependency_Table*) + pixclk_dep_table); + + if (!result && powerplay_table->usPhyClkDependencyTableOffset) + result = get_pix_clk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_phyclk, + (const ATOM_Vega10_PIXCLK_Dependency_Table *) + phyclk_dep_table); + + if (!result && powerplay_table->usDispClkDependencyTableOffset) + result = get_pix_clk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_dispclk, + (const ATOM_Vega10_PIXCLK_Dependency_Table *) + dispclk_dep_table); + + if (!result && powerplay_table->usDcefclkDependencyTableOffset) + result = get_dcefclk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_dcefclk, + dcefclk_dep_table); + + if (!result && powerplay_table->usMclkDependencyTableOffset) + result = get_mclk_voltage_dependency_table(hwmgr, + &pp_table_info->vdd_dep_on_mclk, + mclk_dep_table); + + if (!result && powerplay_table->usPCIETableOffset) + result = get_pcie_table(hwmgr, + &pp_table_info->pcie_table, + pcie_table); + + if (!result && powerplay_table->usHardLimitTableOffset) + result = get_hard_limits(hwmgr, + &pp_table_info->max_clock_voltage_on_dc, + hard_limits); + + hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = + pp_table_info->max_clock_voltage_on_dc.sclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = + pp_table_info->max_clock_voltage_on_dc.mclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + pp_table_info->max_clock_voltage_on_dc.vddc; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = + pp_table_info->max_clock_voltage_on_dc.vddci; + + if (!result && + pp_table_info->vdd_dep_on_socclk && + pp_table_info->vdd_dep_on_socclk->count) + result = get_valid_clk(hwmgr, + &pp_table_info->valid_socclk_values, + pp_table_info->vdd_dep_on_socclk); + + if (!result && + pp_table_info->vdd_dep_on_sclk && + pp_table_info->vdd_dep_on_sclk->count) + result = get_valid_clk(hwmgr, + &pp_table_info->valid_sclk_values, + pp_table_info->vdd_dep_on_sclk); + + if (!result && + pp_table_info->vdd_dep_on_dcefclk && + pp_table_info->vdd_dep_on_dcefclk->count) + result = get_valid_clk(hwmgr, + &pp_table_info->valid_dcefclk_values, + pp_table_info->vdd_dep_on_dcefclk); + + if (!result && + pp_table_info->vdd_dep_on_mclk && + pp_table_info->vdd_dep_on_mclk->count) + result = get_valid_clk(hwmgr, + &pp_table_info->valid_mclk_values, + pp_table_info->vdd_dep_on_mclk); + + return result; +} + +static int get_vddc_lookup_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table **lookup_table, + const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, + uint32_t max_levels) +{ + uint32_t table_size, i; + phm_ppt_v1_voltage_lookup_table *table; + + PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), + "Invalid SOC_VDDD Lookup Table!", return 1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; + + table = kzalloc(table_size, GFP_KERNEL); + + if (table == NULL) + return -ENOMEM; + + table->count = vddc_lookup_pp_tables->ucNumEntries; + + for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) + table->entries[i].us_vdd = + le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd); + + *lookup_table = table; + + return 0; +} + +static int init_dpm_2_parameters( + struct pp_hwmgr *hwmgr, + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) +{ + int result = 0; + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + uint32_t disable_power_control = 0; + + pp_table_info->us_ulv_voltage_offset = + le16_to_cpu(powerplay_table->usUlvVoltageOffset); + + pp_table_info->us_ulv_smnclk_did = + le16_to_cpu(powerplay_table->usUlvSmnclkDid); + pp_table_info->us_ulv_mp1clk_did = + le16_to_cpu(powerplay_table->usUlvMp1clkDid); + pp_table_info->us_ulv_gfxclk_bypass = + le16_to_cpu(powerplay_table->usUlvGfxclkBypass); + pp_table_info->us_gfxclk_slew_rate = + le16_to_cpu(powerplay_table->usGfxclkSlewRate); + pp_table_info->uc_gfx_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucGfxVoltageMode); + pp_table_info->uc_soc_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucSocVoltageMode); + pp_table_info->uc_uclk_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucUclkVoltageMode); + pp_table_info->uc_uvd_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucUvdVoltageMode); + pp_table_info->uc_vce_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucVceVoltageMode); + pp_table_info->uc_mp0_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucMp0VoltageMode); + pp_table_info->uc_dcef_dpm_voltage_mode = + le16_to_cpu(powerplay_table->ucDcefVoltageMode); + + pp_table_info->ppm_parameter_table = NULL; + pp_table_info->vddc_lookup_table = NULL; + pp_table_info->vddmem_lookup_table = NULL; + pp_table_info->vddci_lookup_table = NULL; + + /* TDP limits */ + hwmgr->platform_descriptor.TDPODLimit = + le16_to_cpu(powerplay_table->usPowerControlLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + disable_power_control = 0; + if (!disable_power_control) { + /* enable TDP overdrive (PowerControl) feature as well if supported */ + if (hwmgr->platform_descriptor.TDPODLimit) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + } + + if (powerplay_table->usVddcLookupTableOffset) { + const ATOM_Vega10_Voltage_Lookup_Table *vddc_table = + (ATOM_Vega10_Voltage_Lookup_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); + result = get_vddc_lookup_table(hwmgr, + &pp_table_info->vddc_lookup_table, vddc_table, 8); + } + + if (powerplay_table->usVddmemLookupTableOffset) { + const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table = + (ATOM_Vega10_Voltage_Lookup_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddmemLookupTableOffset)); + result = get_vddc_lookup_table(hwmgr, + &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4); + } + + if (powerplay_table->usVddciLookupTableOffset) { + const ATOM_Vega10_Voltage_Lookup_Table *vddci_table = + (ATOM_Vega10_Voltage_Lookup_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddciLookupTableOffset)); + result = get_vddc_lookup_table(hwmgr, + &pp_table_info->vddci_lookup_table, vddci_table, 4); + } + + return result; +} + +int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); + + PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), + "Failed to allocate hwmgr->pptable!", return -ENOMEM); + + powerplay_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((powerplay_table != NULL), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_over_drive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_over_drive_limits failed", return result); + + result = init_powerplay_extended_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_powerplay_extended_tables failed", return result); + + result = init_dpm_2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm_2_parameters failed", return result); + + return result; +} + +static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + + kfree(pp_table_info->vdd_dep_on_sclk); + pp_table_info->vdd_dep_on_sclk = NULL; + + kfree(pp_table_info->vdd_dep_on_mclk); + pp_table_info->vdd_dep_on_mclk = NULL; + + kfree(pp_table_info->valid_mclk_values); + pp_table_info->valid_mclk_values = NULL; + + kfree(pp_table_info->valid_sclk_values); + pp_table_info->valid_sclk_values = NULL; + + kfree(pp_table_info->vddc_lookup_table); + pp_table_info->vddc_lookup_table = NULL; + + kfree(pp_table_info->vddmem_lookup_table); + pp_table_info->vddmem_lookup_table = NULL; + + kfree(pp_table_info->vddci_lookup_table); + pp_table_info->vddci_lookup_table = NULL; + + kfree(pp_table_info->ppm_parameter_table); + pp_table_info->ppm_parameter_table = NULL; + + kfree(pp_table_info->mm_dep_table); + pp_table_info->mm_dep_table = NULL; + + kfree(pp_table_info->cac_dtp_table); + pp_table_info->cac_dtp_table = NULL; + + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; + + kfree(pp_table_info->tdp_table); + pp_table_info->tdp_table = NULL; + + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + + return 0; +} + +const struct pp_table_func vega10_pptable_funcs = { + .pptable_init = vega10_pp_tables_initialize, + .pptable_fini = vega10_pp_tables_uninitialize, +}; + +int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) +{ + const ATOM_Vega10_State_Array *state_arrays; + const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((pp_table != NULL), + "Missing PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= + ATOM_Vega10_TABLE_REVISION_VEGA10), + "Incorrect PowerPlay table revision!", return -1); + + state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + return (uint32_t)(state_arrays->ucNumEntries); +} + +static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, + uint16_t classification, uint16_t classification2) +{ + uint32_t result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + return result; +} + +int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, + uint32_t entry_index, struct pp_power_state *power_state, + int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)) +{ + int result = 0; + const ATOM_Vega10_State_Array *state_arrays; + const ATOM_Vega10_State *state_entry; + const ATOM_Vega10_POWERPLAYTABLE *pp_table = + get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", + return -1;); + power_state->classification.bios_index = entry_index; + + if (pp_table->sHeader.format_revision >= + ATOM_Vega10_TABLE_REVISION_VEGA10) { + state_arrays = (ATOM_Vega10_State_Array *) + (((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, + "Invalid PowerPlay Table State Array Offset.", + return -1); + PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, + "Invalid PowerPlay Table State Array.", + return -1); + PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array Entry.", + return -1); + + state_entry = &(state_arrays->states[entry_index]); + + result = call_back_func(hwmgr, (void *)state_entry, power_state, + (void *)pp_table, + make_classification_flags(hwmgr, + le16_to_cpu(state_entry->usClassification), + le16_to_cpu(state_entry->usClassification2))); + } + + if (!result && (power_state->classification.flags & + PP_StateClassificationFlag_Boot)) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + + return result; +} + +int vega10_baco_set_cap(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; + + powerplay_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((powerplay_table != NULL), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + set_hw_cap( + hwmgr, + 0 != (le32_to_cpu(powerplay_table->ulPlatformCaps) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO); + return result; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h new file mode 100644 index 000000000000..da5fbec9b0cd --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_processpptables.h @@ -0,0 +1,63 @@ +/* + * Copyright 2016 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 VEGA10_PROCESSPPTABLES_H +#define VEGA10_PROCESSPPTABLES_H + +#include "hwmgr.h" + +enum Vega10_I2CLineID { + Vega10_I2CLineID_DDC1 = 0x90, + Vega10_I2CLineID_DDC2 = 0x91, + Vega10_I2CLineID_DDC3 = 0x92, + Vega10_I2CLineID_DDC4 = 0x93, + Vega10_I2CLineID_DDC5 = 0x94, + Vega10_I2CLineID_DDC6 = 0x95, + Vega10_I2CLineID_SCLSDA = 0x96, + Vega10_I2CLineID_DDCVGA = 0x97 +}; + +#define Vega10_I2C_DDC1DATA 0 +#define Vega10_I2C_DDC1CLK 1 +#define Vega10_I2C_DDC2DATA 2 +#define Vega10_I2C_DDC2CLK 3 +#define Vega10_I2C_DDC3DATA 4 +#define Vega10_I2C_DDC3CLK 5 +#define Vega10_I2C_SDA 40 +#define Vega10_I2C_SCL 41 +#define Vega10_I2C_DDC4DATA 65 +#define Vega10_I2C_DDC4CLK 66 +#define Vega10_I2C_DDC5DATA 0x48 +#define Vega10_I2C_DDC5CLK 0x49 +#define Vega10_I2C_DDC6DATA 0x4a +#define Vega10_I2C_DDC6CLK 0x4b +#define Vega10_I2C_DDCVGADATA 0x4c +#define Vega10_I2C_DDCVGACLK 0x4d + +extern const struct pp_table_func vega10_pptable_funcs; +extern int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr); +extern int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index, + struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)); +extern int vega10_baco_set_cap(struct pp_hwmgr *hwmgr); +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c new file mode 100644 index 000000000000..468bdd6f6697 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -0,0 +1,657 @@ +/* + * Copyright 2016 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 "vega10_thermal.h" +#include "vega10_hwmgr.h" +#include "vega10_smumgr.h" +#include "vega10_ppsmc.h" +#include "vega10_inc.h" +#include "soc15_common.h" +#include "pp_debug.h" + +static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) +{ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm, current_rpm); + return 0; +} + +int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info) +{ + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + fan_speed_info->supports_percent_read = true; + fan_speed_info->supports_percent_write = true; + fan_speed_info->min_percent = 0; + fan_speed_info->max_percent = 100; + + if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && + hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution) { + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + fan_speed_info->min_rpm = + hwmgr->thermal_controller.fanInfo.ulMinRPM; + fan_speed_info->max_rpm = + hwmgr->thermal_controller.fanInfo.ulMaxRPM; + } else { + fan_speed_info->min_rpm = 0; + fan_speed_info->max_rpm = 0; + } + + return 0; +} + +int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed) +{ + uint32_t current_rpm; + uint32_t percent = 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) + return -1; + + if (hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM != 0) + percent = current_rpm * 100 / + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM; + + *speed = percent > 100 ? 100 : percent; + + return 0; +} + +int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t tach_period; + uint32_t crystal_clock_freq; + int result = 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -1; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + result = vega10_get_current_rpm(hwmgr, speed); + } else { + tach_period = + REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_STATUS), + CG_TACH_STATUS, + TACH_PERIOD); + + if (tach_period == 0) + return -EINVAL; + + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + *speed = 60 * crystal_clock_freq * 10000 / tach_period; + } + + return result; +} + +/** +* Set Fan Speed Control to static mode, +* so that the user can decide what speed to use. +* @param hwmgr the address of the powerplay hardware manager. +* mode the fan control mode, 0 default, 1 by percent, 5, by RPM +* @exception Should always succeed. +*/ +int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (hwmgr->fan_ctrl_is_in_default_mode) { + hwmgr->fan_ctrl_default_mode = + REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, FDO_PWM_MODE); + hwmgr->tmin = + REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TMIN); + hwmgr->fan_ctrl_is_in_default_mode = false; + } + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TMIN, 0)); + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, FDO_PWM_MODE, mode)); + + return 0; +} + +/** +* Reset Fan Speed Control to default mode. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Should always succeed. +*/ +int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (!hwmgr->fan_ctrl_is_in_default_mode) { + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, FDO_PWM_MODE, + hwmgr->fan_ctrl_default_mode)); + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TMIN, + hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT)); + hwmgr->fan_ctrl_is_in_default_mode = true; + } + + return 0; +} + +/** + * @fn vega10_enable_fan_control_feature + * @brief Enables the SMC Fan Control Feature. + * + * @param hwmgr - the address of the powerplay hardware manager. + * @return 0 on success. -1 otherwise. + */ +static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( + hwmgr, true, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap), + "Attempt to Enable FAN CONTROL feature Failed!", + return -1); + data->smu_features[GNLD_FAN_CONTROL].enabled = true; + } + + return 0; +} + +static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( + hwmgr, false, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap), + "Attempt to Enable FAN CONTROL feature Failed!", + return -1); + data->smu_features[GNLD_FAN_CONTROL].enabled = false; + } + + return 0; +} + +int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -1; + + PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr), + "Attempt to Enable SMC FAN CONTROL Feature Failed!", + return -1); + + return 0; +} + + +int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -1; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr), + "Attempt to Disable SMC FAN CONTROL Feature Failed!", + return -1); + } + return 0; +} + +/** +* Set Fan Speed in percent. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (0% - 100%) to be set. +* @exception Fails is the 100% setting appears to be 0. +*/ +int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (speed > 100) + speed = 100; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (uint64_t)speed * duty100; + do_div(tmp64, 100); + duty = (uint32_t)tmp64; + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); + + return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +/** +* Reset Fan Speed to default. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Always succeeds. +*/ +int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + return vega10_fan_ctrl_start_smc_fan_control(hwmgr); + else + return vega10_fan_ctrl_set_default_mode(hwmgr); +} + +/** +* Set Fan Speed in RPM. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (min - max) to be set. +* @exception Fails is the speed not lie between min and max. +*/ +int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t tach_period; + uint32_t crystal_clock_freq; + int result = 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan || + speed == 0 || + (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || + (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) + return -1; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + + if (!result) { + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); + WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, TARGET_PERIOD, + tach_period)); + } + return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int temp; + + temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); + + temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> + CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; + + temp = temp & 0x1ff; + + temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for +* high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + struct amdgpu_device *adev = hwmgr->adev; + int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + uint32_t val; + + if (low < range->min) + low = range->min; + if (high > range->max) + high = range->max; + + if (low > high) + return -EINVAL; + + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) & + (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) & + (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); + + return 0; +} + +/** +* Programs thermal controller one-time setting registers +* +* @param hwmgr The address of the hardware manager. +*/ +static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { + WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, EDGE_PER_REV, + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1)); + } + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28)); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct vega10_hwmgr *data = hwmgr->backend; + uint32_t val = 0; + + if (data->smu_features[GNLD_FW_CTF].supported) { + if (data->smu_features[GNLD_FW_CTF].enabled) + printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n"); + + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + true, + data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), + "Attempt to Enable FW CTF feature Failed!", + return -1); + data->smu_features[GNLD_FW_CTF].enabled = true; + } + + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); + + return 0; +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct vega10_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FW_CTF].supported) { + if (!data->smu_features[GNLD_FW_CTF].enabled) + printk("[Thermal_EnableAlert] FW CTF Already disabled!\n"); + + + PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, + false, + data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), + "Attempt to disable FW CTF feature Failed!", + return -1); + data->smu_features[GNLD_FW_CTF].enabled = false; + } + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); + + return 0; +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = vega10_thermal_disable_alert(hwmgr); + + if (!hwmgr->thermal_controller.fanInfo.bNoFan) + vega10_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set up the fan table to control the fan using the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + int ret; + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *table = &(data->smc_state_table.pp_table); + + if (!data->smu_features[GNLD_FAN_CONTROL].supported) + return 0; + + table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM; + table->FanThrottlingRpm = hwmgr->thermal_controller. + advanceFanControlParameters.usFanRPMMaxLimit; + table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit); + table->FanTargetTemperature = hwmgr->thermal_controller. + advanceFanControlParameters.usTMax; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanTemperatureTarget, + (uint32_t)table->FanTargetTemperature, + NULL); + + table->FanPwmMin = hwmgr->thermal_controller. + advanceFanControlParameters.usPWMMin * 255 / 100; + table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller. + advanceFanControlParameters.ulTargetGfxClk); + table->FanGainEdge = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainEdge; + table->FanGainHotspot = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainHotspot; + table->FanGainLiquid = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainLiquid; + table->FanGainVrVddc = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainVrVddc; + table->FanGainVrMvdd = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainVrMvdd; + table->FanGainPlx = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainPlx; + table->FanGainHbm = hwmgr->thermal_controller. + advanceFanControlParameters.usFanGainHbm; + table->FanZeroRpmEnable = hwmgr->thermal_controller. + advanceFanControlParameters.ucEnableZeroRPM; + table->FanStopTemp = hwmgr->thermal_controller. + advanceFanControlParameters.usZeroRPMStopTemperature; + table->FanStartTemp = hwmgr->thermal_controller. + advanceFanControlParameters.usZeroRPMStartTemperature; + + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&(data->smc_state_table.pp_table)), + PPTABLE, false); + if (ret) + pr_info("Failed to update Fan Control Table in PPTable!"); + + return ret; +} + +int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) +{ + struct vega10_hwmgr *data = hwmgr->backend; + PPTable_t *table = &(data->smc_state_table.pp_table); + int ret; + + if (!data->smu_features[GNLD_FAN_CONTROL].supported) + return 0; + + if (!hwmgr->thermal_controller.advanceFanControlParameters. + usMGpuThrottlingRPMLimit) + return 0; + + table->FanThrottlingRpm = hwmgr->thermal_controller. + advanceFanControlParameters.usMGpuThrottlingRPMLimit; + + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&(data->smc_state_table.pp_table)), + PPTABLE, false); + if (ret) { + pr_info("Failed to update fan control table in pptable!"); + return ret; + } + + ret = vega10_disable_fan_control_feature(hwmgr); + if (ret) { + pr_info("Attempt to disable SMC fan control feature failed!"); + return ret; + } + + ret = vega10_enable_fan_control_feature(hwmgr); + if (ret) + pr_info("Attempt to enable SMC fan control feature failed!"); + + return ret; +} + +/** +* Start the fan control on the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ +/* If the fantable setup has failed we could have disabled + * PHM_PlatformCaps_MicrocodeFanControl even after + * this function was included in the table. + * Make sure that we still think controlling the fan is OK. +*/ + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega10_fan_ctrl_start_smc_fan_control(hwmgr); + + return 0; +} + + +int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + int ret = 0; + + if (range == NULL) + return -EINVAL; + + vega10_thermal_initialize(hwmgr); + ret = vega10_thermal_set_temperature_range(hwmgr, range); + if (ret) + return -EINVAL; + + vega10_thermal_enable_alert(hwmgr); +/* We should restrict performance levels to low before we halt the SMC. + * On the other hand we are still in boot state when we do this + * so it would be pointless. + * If this assumption changes we have to revisit this table. + */ + ret = vega10_thermal_setup_fan_table(hwmgr); + if (ret) + return -EINVAL; + + vega10_thermal_start_smc_fan_control(hwmgr); + + return 0; +}; + + + + +int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->thermal_controller.fanInfo.bNoFan) { + vega10_fan_ctrl_set_default_mode(hwmgr); + vega10_fan_ctrl_stop_smc_fan_control(hwmgr); + } + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h new file mode 100644 index 000000000000..4a0ede7c1f07 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.h @@ -0,0 +1,80 @@ +/* + * Copyright 2015 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 VEGA10_THERMAL_H +#define VEGA10_THERMAL_H + +#include "hwmgr.h" + +struct vega10_temperature { + uint16_t edge_temp; + uint16_t hot_spot_temp; + uint16_t hbm_temp; + uint16_t vr_soc_temp; + uint16_t vr_mem_temp; + uint16_t liquid1_temp; + uint16_t liquid2_temp; + uint16_t plx_temp; +}; + +#define VEGA10_THERMAL_HIGH_ALERT_MASK 0x1 +#define VEGA10_THERMAL_LOW_ALERT_MASK 0x2 + +#define VEGA10_THERMAL_MINIMUM_TEMP_READING -256 +#define VEGA10_THERMAL_MAXIMUM_TEMP_READING 255 + +#define VEGA10_THERMAL_MINIMUM_ALERT_TEMP 0 +#define VEGA10_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + + +extern int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info); +extern int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed); +extern int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); +extern int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, + uint32_t mode); +extern int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed); +extern int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); +extern int vega10_thermal_ctrl_uninitialize_thermal_controller( + struct pp_hwmgr *hwmgr); +extern int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, + uint32_t speed); +extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, + uint32_t *speed); +extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); +extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range); +extern int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr); + + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c new file mode 100644 index 000000000000..bc53cce4f32d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.c @@ -0,0 +1,119 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "amdgpu.h" +#include "soc15.h" +#include "soc15_hw_ip.h" +#include "vega10_ip_offset.h" +#include "soc15_common.h" +#include "vega12_inc.h" +#include "vega12_ppsmc.h" +#include "vega12_baco.h" + +static const struct soc15_baco_cmd_entry pre_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmBIF_DOORBELL_CNTL_BASE_IDX, mmBIF_DOORBELL_CNTL, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 0 }, + { CMD_WRITE, NBIF_HWID, 0, mmBIF_FB_EN_BASE_IDX, mmBIF_FB_EN, 0, 0, 0, 0 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1 } +}; + +static const struct soc15_baco_cmd_entry enter_baco_tbl[] = +{ + { CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1 }, + { CMD_DELAY_MS, 0, 0, 0, 5, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0 }, + { CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100 } +}; + +static const struct soc15_baco_cmd_entry exit_baco_tbl[] = +{ + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0 }, + { CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0 }, + { CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0 }, + { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0 }, + { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0 }, + { CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0 } +}; + +static const struct soc15_baco_cmd_entry clean_baco_tbl[] = +{ + { CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_6_BASE_IDX, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, + { CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_7_BASE_IDX, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } +}; + +int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + enum BACO_STATE cur_state; + + smu9_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + if (soc15_baco_program_registers(hwmgr, pre_baco_tbl, + ARRAY_SIZE(pre_baco_tbl))) { + if (smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnterBaco, 0, NULL)) + return -EINVAL; + + if (soc15_baco_program_registers(hwmgr, enter_baco_tbl, + ARRAY_SIZE(enter_baco_tbl))) + return 0; + } + } else if (state == BACO_STATE_OUT) { + /* HW requires at least 20ms between regulator off and on */ + msleep(20); + /* Execute Hardware BACO exit sequence */ + if (soc15_baco_program_registers(hwmgr, exit_baco_tbl, + ARRAY_SIZE(exit_baco_tbl))) { + if (soc15_baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return 0; + } + } + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h new file mode 100644 index 000000000000..57b72e5a95ae --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_baco.h @@ -0,0 +1,29 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __VEGA12_BACO_H__ +#define __VEGA12_BACO_H__ +#include "smu9_baco.h" + +extern int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c new file mode 100644 index 000000000000..f0680dd58508 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.c @@ -0,0 +1,2868 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include +#include +#include + +#include "hwmgr.h" +#include "amd_powerplay.h" +#include "vega12_smumgr.h" +#include "hardwaremanager.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "cgs_common.h" +#include "vega12_inc.h" +#include "pppcielanes.h" +#include "vega12_hwmgr.h" +#include "vega12_processpptables.h" +#include "vega12_pptable.h" +#include "vega12_thermal.h" +#include "vega12_ppsmc.h" +#include "pp_debug.h" +#include "amd_pcie_helpers.h" +#include "ppinterrupt.h" +#include "pp_overdriver.h" +#include "pp_thermal.h" +#include "vega12_baco.h" + +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 + +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + +static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask); +static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr, + uint32_t *clock, + PPCLK_e clock_select, + bool max); + +static void vega12_set_default_registry_data(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + data->gfxclk_average_alpha = PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT; + data->socclk_average_alpha = PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT; + data->uclk_average_alpha = PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT; + data->gfx_activity_average_alpha = PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT; + data->lowest_uclk_reserved_for_ulv = PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT; + + data->display_voltage_mode = PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT; + data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; + + data->registry_data.disallowed_features = 0x0; + data->registry_data.od_state_in_dc_support = 0; + data->registry_data.thermal_support = 1; + data->registry_data.skip_baco_hardware = 0; + + data->registry_data.log_avfs_param = 0; + data->registry_data.sclk_throttle_low_notification = 1; + data->registry_data.force_dpm_high = 0; + data->registry_data.stable_pstate_sclk_dpm_percentage = 75; + + data->registry_data.didt_support = 0; + if (data->registry_data.didt_support) { + data->registry_data.didt_mode = 6; + data->registry_data.sq_ramping_support = 1; + data->registry_data.db_ramping_support = 0; + data->registry_data.td_ramping_support = 0; + data->registry_data.tcp_ramping_support = 0; + data->registry_data.dbr_ramping_support = 0; + data->registry_data.edc_didt_support = 1; + data->registry_data.gc_didt_support = 0; + data->registry_data.psm_didt_support = 0; + } + + data->registry_data.pcie_lane_override = 0xff; + data->registry_data.pcie_speed_override = 0xff; + data->registry_data.pcie_clock_override = 0xffffffff; + data->registry_data.regulator_hot_gpio_support = 1; + data->registry_data.ac_dc_switch_gpio_support = 0; + data->registry_data.quick_transition_support = 0; + data->registry_data.zrpm_start_temp = 0xffff; + data->registry_data.zrpm_stop_temp = 0xffff; + data->registry_data.odn_feature_enable = 1; + data->registry_data.disable_water_mark = 0; + data->registry_data.disable_pp_tuning = 0; + data->registry_data.disable_xlpp_tuning = 0; + data->registry_data.disable_workload_policy = 0; + data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F; + data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919; + data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A; + data->registry_data.force_workload_policy_mask = 0; + data->registry_data.disable_3d_fs_detection = 0; + data->registry_data.fps_support = 1; + data->registry_data.disable_auto_wattman = 1; + data->registry_data.auto_wattman_debug = 0; + data->registry_data.auto_wattman_sample_period = 100; + data->registry_data.auto_wattman_threshold = 50; +} + +static int vega12_set_features_platform_caps(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + + if (data->vddci_control == VEGA12_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + + if (adev->pg_flags & AMD_PG_SUPPORT_UVD) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDynamicPowerGating); + } + + if (adev->pg_flags & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + + if (data->registry_data.odn_feature_enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODNinACSupport); + else { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6inACSupport); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinACSupport); + } + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ActivityReporting); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + if (data->registry_data.od_state_in_dc_support) { + if (data->registry_data.odn_feature_enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODNinDCSupport); + else { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6inDCSupport); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinDCSupport); + } + } + + if (data->registry_data.thermal_support + && data->registry_data.fuzzy_fan_control_support + && hwmgr->thermal_controller.advanceFanControlParameters.usTMax) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPowerManagement); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMC); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalPolicyDelay); + + if (data->registry_data.force_dpm_high) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ExclusiveModeAlwaysHigh); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + if (data->registry_data.sclk_throttle_low_notification) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification); + + /* power tune caps */ + /* assume disabled */ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtEDCEnable); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GCEDC); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PSM); + + if (data->registry_data.didt_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); + if (data->registry_data.sq_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); + if (data->registry_data.db_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); + if (data->registry_data.td_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); + if (data->registry_data.tcp_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); + if (data->registry_data.dbr_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); + if (data->registry_data.edc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); + if (data->registry_data.gc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); + if (data->registry_data.psm_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); + } + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + + if (data->registry_data.ac_dc_switch_gpio_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); + } + + if (data->registry_data.quick_transition_support) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + } + + if (data->lowest_uclk_reserved_for_ulv != PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_LowestUclkReservedForUlv); + if (data->lowest_uclk_reserved_for_ulv == 1) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_LowestUclkReservedForUlv); + } + + if (data->registry_data.custom_fan_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CustomFanControlSupport); + + return 0; +} + +static void vega12_init_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + uint32_t top32, bottom32; + int i; + + data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = + FEATURE_DPM_PREFETCHER_BIT; + data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = + FEATURE_DPM_GFXCLK_BIT; + data->smu_features[GNLD_DPM_UCLK].smu_feature_id = + FEATURE_DPM_UCLK_BIT; + data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = + FEATURE_DPM_SOCCLK_BIT; + data->smu_features[GNLD_DPM_UVD].smu_feature_id = + FEATURE_DPM_UVD_BIT; + data->smu_features[GNLD_DPM_VCE].smu_feature_id = + FEATURE_DPM_VCE_BIT; + data->smu_features[GNLD_ULV].smu_feature_id = + FEATURE_ULV_BIT; + data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = + FEATURE_DPM_MP0CLK_BIT; + data->smu_features[GNLD_DPM_LINK].smu_feature_id = + FEATURE_DPM_LINK_BIT; + data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = + FEATURE_DPM_DCEFCLK_BIT; + data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = + FEATURE_DS_GFXCLK_BIT; + data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = + FEATURE_DS_SOCCLK_BIT; + data->smu_features[GNLD_DS_LCLK].smu_feature_id = + FEATURE_DS_LCLK_BIT; + data->smu_features[GNLD_PPT].smu_feature_id = + FEATURE_PPT_BIT; + data->smu_features[GNLD_TDC].smu_feature_id = + FEATURE_TDC_BIT; + data->smu_features[GNLD_THERMAL].smu_feature_id = + FEATURE_THERMAL_BIT; + data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = + FEATURE_GFX_PER_CU_CG_BIT; + data->smu_features[GNLD_RM].smu_feature_id = + FEATURE_RM_BIT; + data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = + FEATURE_DS_DCEFCLK_BIT; + data->smu_features[GNLD_ACDC].smu_feature_id = + FEATURE_ACDC_BIT; + data->smu_features[GNLD_VR0HOT].smu_feature_id = + FEATURE_VR0HOT_BIT; + data->smu_features[GNLD_VR1HOT].smu_feature_id = + FEATURE_VR1HOT_BIT; + data->smu_features[GNLD_FW_CTF].smu_feature_id = + FEATURE_FW_CTF_BIT; + data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = + FEATURE_LED_DISPLAY_BIT; + data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = + FEATURE_FAN_CONTROL_BIT; + data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; + data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT; + data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT; + data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + data->smu_features[i].smu_feature_bitmap = + (uint64_t)(1ULL << data->smu_features[i].smu_feature_id); + data->smu_features[i].allowed = + ((data->registry_data.disallowed_features >> i) & 1) ? + false : true; + } + + /* Get the SN to turn into a Unique ID */ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); + + adev->unique_id = ((uint64_t)bottom32 << 32) | top32; +} + +static int vega12_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int vega12_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int vega12_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vega12_hwmgr *data; + struct amdgpu_device *adev = hwmgr->adev; + + data = kzalloc(sizeof(struct vega12_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + + vega12_set_default_registry_data(hwmgr); + + data->disable_dpm_mask = 0xff; + data->workload_mask = 0xff; + + /* need to set voltage control types before EVV patching */ + data->vddc_control = VEGA12_VOLTAGE_CONTROL_NONE; + data->mvdd_control = VEGA12_VOLTAGE_CONTROL_NONE; + data->vddci_control = VEGA12_VOLTAGE_CONTROL_NONE; + + data->water_marks_bitmap = 0; + data->avfs_exist = false; + + vega12_set_features_platform_caps(hwmgr); + + vega12_init_dpm_defaults(hwmgr); + + /* Parse pptable data read from VBIOS */ + vega12_set_private_data_based_on_pptable(hwmgr); + + data->is_tlu_enabled = false; + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + VEGA12_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ + /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ + hwmgr->platform_descriptor.clockStep.engineClock = 500; + hwmgr->platform_descriptor.clockStep.memoryClock = 500; + + data->total_active_cus = adev->gfx.cu_info.number; + /* Setup default Overdrive Fan control settings */ + data->odn_fan_table.target_fan_speed = + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM; + data->odn_fan_table.target_temperature = + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature; + data->odn_fan_table.min_performance_clock = + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit; + data->odn_fan_table.min_fan_limit = + hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit * + hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100; + + if (hwmgr->feature_mask & PP_GFXOFF_MASK) + data->gfxoff_controlled_by_driver = true; + else + data->gfxoff_controlled_by_driver = false; + + return result; +} + +static int vega12_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + data->low_sclk_interrupt_threshold = 0; + + return 0; +} + +static int vega12_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + PP_ASSERT_WITH_CODE(!vega12_init_sclk_threshold(hwmgr), + "Failed to init sclk threshold!", + return -EINVAL); + + return 0; +} + +/* + * @fn vega12_init_dpm_state + * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. + * + * @param dpm_state - the address of the DPM Table to initiailize. + * @return None. + */ +static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state) +{ + dpm_state->soft_min_level = 0x0; + dpm_state->soft_max_level = 0xffff; + dpm_state->hard_min_level = 0x0; + dpm_state->hard_max_level = 0xffff; +} + +static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr, + PPCLK_e clk_id, uint32_t *num_of_levels) +{ + int ret = 0; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmFreqByIndex, + (clk_id << 16 | 0xFF), + num_of_levels); + PP_ASSERT_WITH_CODE(!ret, + "[GetNumOfDpmLevel] failed to get dpm levels!", + return ret); + + return ret; +} + +static int vega12_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr, + PPCLK_e clkID, uint32_t index, uint32_t *clock) +{ + /* + *SMU expects the Clock ID to be in the top 16 bits. + *Lower 16 bits specify the level + */ + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmFreqByIndex, (clkID << 16 | index), + clock) == 0, + "[GetDpmFrequencyByIndex] Failed to get dpm frequency from SMU!", + return -EINVAL); + + return 0; +} + +static int vega12_setup_single_dpm_table(struct pp_hwmgr *hwmgr, + struct vega12_single_dpm_table *dpm_table, PPCLK_e clk_id) +{ + int ret = 0; + uint32_t i, num_of_levels, clk; + + ret = vega12_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels); + PP_ASSERT_WITH_CODE(!ret, + "[SetupSingleDpmTable] failed to get clk levels!", + return ret); + + dpm_table->count = num_of_levels; + + for (i = 0; i < num_of_levels; i++) { + ret = vega12_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk); + PP_ASSERT_WITH_CODE(!ret, + "[SetupSingleDpmTable] failed to get clk of specific level!", + return ret); + dpm_table->dpm_levels[i].value = clk; + dpm_table->dpm_levels[i].enabled = true; + } + + return ret; +} + +/* + * This function is to initialize all DPM state tables + * for SMU based on the dependency table. + * Dynamic state patching function will then trim these + * state tables to the allowed range based + * on the power policy or external client requests, + * such as UVD request, etc. + */ +static int vega12_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *dpm_table; + int ret = 0; + + memset(&data->dpm_table, 0, sizeof(data->dpm_table)); + + /* socclk */ + dpm_table = &(data->dpm_table.soc_table); + if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get socclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* gfxclk */ + dpm_table = &(data->dpm_table.gfx_table); + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* memclk */ + dpm_table = &(data->dpm_table.mem_table); + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get memclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* eclk */ + dpm_table = &(data->dpm_table.eclk_table); + if (data->smu_features[GNLD_DPM_VCE].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get eclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* vclk */ + dpm_table = &(data->dpm_table.vclk_table); + if (data->smu_features[GNLD_DPM_UVD].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get vclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* dclk */ + dpm_table = &(data->dpm_table.dclk_table); + if (data->smu_features[GNLD_DPM_UVD].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* dcefclk */ + dpm_table = &(data->dpm_table.dcef_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100; + } + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* pixclk */ + dpm_table = &(data->dpm_table.pixel_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get pixclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* dispclk */ + dpm_table = &(data->dpm_table.display_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dispclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* phyclk */ + dpm_table = &(data->dpm_table.phy_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get phyclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega12_init_dpm_state(&(dpm_table->dpm_state)); + + /* save a copy of the default DPM table */ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), + sizeof(struct vega12_dpm_table)); + + return 0; +} + +#if 0 +static int vega12_save_default_power_profile(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); + uint32_t min_level; + + hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; + hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; + + /* Optimize compute power profile: Use only highest + * 2 power levels (if more than 2 are available) + */ + if (dpm_table->count > 2) + min_level = dpm_table->count - 2; + else if (dpm_table->count == 2) + min_level = 1; + else + min_level = 0; + + hwmgr->default_compute_power_profile.min_sclk = + dpm_table->dpm_levels[min_level].value; + + hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; + + return 0; +} +#endif + +/** +* Initializes the SMC table and uploads it +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data (PowerState) +* @return always 0 +*/ +static int vega12_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct pp_atomfwctrl_bios_boot_up_values boot_up_values; + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + + result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); + if (!result) { + data->vbios_boot_state.vddc = boot_up_values.usVddc; + data->vbios_boot_state.vddci = boot_up_values.usVddci; + data->vbios_boot_state.mvddc = boot_up_values.usMvddc; + data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; + data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; + data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; + data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; + data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID; + data->vbios_boot_state.eclock = boot_up_values.ulEClk; + data->vbios_boot_state.dclock = boot_up_values.ulDClk; + data->vbios_boot_state.vclock = boot_up_values.ulVClk; + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepDcefclk, + (uint32_t)(data->vbios_boot_state.dcef_clock / 100), + NULL); + } + + memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t)); + + result = smum_smc_table_manager(hwmgr, + (uint8_t *)pp_table, TABLE_PPTABLE, false); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload PPtable!", return result); + + return 0; +} + +static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr) +{ + uint32_t result; + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &result) == 0, + "[Run_ACG_BTC] Attempt to run ACG BTC failed!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(result == 1, + "Failed to run ACG BTC!", return -EINVAL); + + return 0; +} + +static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + int i; + uint32_t allowed_features_low = 0, allowed_features_high = 0; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) + if (data->smu_features[i].allowed) + data->smu_features[i].smu_feature_id > 31 ? + (allowed_features_high |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) & 0xFFFFFFFF)) : + (allowed_features_low |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) & 0xFFFFFFFF)); + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, + NULL) == 0, + "[SetAllowedFeaturesMask] Attempt to set allowed features mask (high) failed!", + return -1); + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, + NULL) == 0, + "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!", + return -1); + + return 0; +} + +static void vega12_init_powergate_state(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = true; + data->vce_power_gated = true; + + if (data->smu_features[GNLD_DPM_UVD].enabled) + data->uvd_power_gated = false; + + if (data->smu_features[GNLD_DPM_VCE].enabled) + data->vce_power_gated = false; +} + +static int vega12_enable_all_smu_features(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint64_t features_enabled; + int i; + bool enabled; + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, NULL) == 0, + "[EnableAllSMUFeatures] Failed to enable all smu features!", + return -1); + + if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) { + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false; + data->smu_features[i].enabled = enabled; + data->smu_features[i].supported = enabled; + } + } + + vega12_init_powergate_state(hwmgr); + + return 0; +} + +static int vega12_disable_all_smu_features(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint64_t features_enabled; + int i; + bool enabled; + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, NULL) == 0, + "[DisableAllSMUFeatures] Failed to disable all smu features!", + return -1); + + if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) { + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false; + data->smu_features[i].enabled = enabled; + data->smu_features[i].supported = enabled; + } + } + + return 0; +} + +static int vega12_odn_initialize_default_settings( + struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int vega12_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, + uint32_t adjust_percent) +{ + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_OverDriveSetPercentage, adjust_percent, + NULL); +} + +static int vega12_power_control_set_level(struct pp_hwmgr *hwmgr) +{ + int adjust_percent, result = 0; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + adjust_percent = + hwmgr->platform_descriptor.TDPAdjustmentPolarity ? + hwmgr->platform_descriptor.TDPAdjustment : + (-1 * hwmgr->platform_descriptor.TDPAdjustment); + result = vega12_set_overdrive_target_percentage(hwmgr, + (uint32_t)adjust_percent); + } + return result; +} + +static int vega12_get_all_clock_ranges_helper(struct pp_hwmgr *hwmgr, + PPCLK_e clkid, struct vega12_clock_range *clock) +{ + /* AC Max */ + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMaxDpmFreq, (clkid << 16), + &(clock->ACMax)) == 0, + "[GetClockRanges] Failed to get max ac clock from SMC!", + return -EINVAL); + + /* AC Min */ + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMinDpmFreq, (clkid << 16), + &(clock->ACMin)) == 0, + "[GetClockRanges] Failed to get min ac clock from SMC!", + return -EINVAL); + + /* DC Max */ + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDcModeMaxDpmFreq, (clkid << 16), + &(clock->DCMax)) == 0, + "[GetClockRanges] Failed to get max dc clock from SMC!", + return -EINVAL); + + return 0; +} + +static int vega12_get_all_clock_ranges(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t i; + + for (i = 0; i < PPCLK_COUNT; i++) + PP_ASSERT_WITH_CODE(!vega12_get_all_clock_ranges_helper(hwmgr, + i, &(data->clk_range[i])), + "Failed to get clk range from SMC!", + return -EINVAL); + + return 0; +} + +static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, 0, NULL); + + result = vega12_set_allowed_featuresmask(hwmgr); + PP_ASSERT_WITH_CODE(result == 0, + "[EnableDPMTasks] Failed to set allowed featuresmask!\n", + return result); + + tmp_result = vega12_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to initialize SMC table!", + result = tmp_result); + + tmp_result = vega12_run_acg_btc(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to run ACG BTC!", + result = tmp_result); + + result = vega12_enable_all_smu_features(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to enable all smu features!", + return result); + + tmp_result = vega12_power_control_set_level(hwmgr); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to power control set level!", + result = tmp_result); + + result = vega12_get_all_clock_ranges(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to get all clock ranges!", + return result); + + result = vega12_odn_initialize_default_settings(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to power control set level!", + return result); + + result = vega12_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to setup default DPM tables!", + return result); + return result; +} + +static int vega12_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + return 0; +} + +static uint32_t vega12_find_lowest_dpm_level( + struct vega12_single_dpm_table *table) +{ + uint32_t i; + + for (i = 0; i < table->count; i++) { + if (table->dpm_levels[i].enabled) + break; + } + + if (i >= table->count) { + i = 0; + table->dpm_levels[i].enabled = true; + } + + return i; +} + +static uint32_t vega12_find_highest_dpm_level( + struct vega12_single_dpm_table *table) +{ + int32_t i = 0; + PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, + "[FindHighestDPMLevel] DPM Table has too many entries!", + return MAX_REGULAR_DPM_NUMBER - 1); + + for (i = table->count - 1; i >= 0; i--) { + if (table->dpm_levels[i].enabled) + break; + } + + if (i < 0) { + i = 0; + table->dpm_levels[i].enabled = true; + } + + return (uint32_t)i; +} + +static int vega12_upload_dpm_min_level(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = hwmgr->backend; + uint32_t min_freq; + int ret = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min gfxclk !", + return ret); + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_UCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min memclk !", + return ret); + + min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetHardMinByFreq, + (PPCLK_UCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set hard min memclk !", + return ret); + } + + if (data->smu_features[GNLD_DPM_UVD].enabled) { + min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_VCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min vclk!", + return ret); + + min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_DCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min dclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_VCE].enabled) { + min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_ECLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min eclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { + min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min socclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetHardMinByFreq, + (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set hard min dcefclk!", + return ret); + } + + return ret; + +} + +static int vega12_upload_dpm_max_level(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = hwmgr->backend; + uint32_t max_freq; + int ret = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max gfxclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_UCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max memclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_UVD].enabled) { + max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_VCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max vclk!", + return ret); + + max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_DCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max dclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_VCE].enabled) { + max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_ECLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max eclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { + max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max socclk!", + return ret); + } + + return ret; +} + +int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DPM_VCE].supported) { + PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), + "Attempt to Enable/Disable DPM VCE Failed!", + return -1); + data->smu_features[GNLD_DPM_VCE].enabled = enable; + } + + return 0; +} + +static uint32_t vega12_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t gfx_clk; + + if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) + return -1; + + if (low) + PP_ASSERT_WITH_CODE( + vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false) == 0, + "[GetSclks]: fail to get min PPCLK_GFXCLK\n", + return -1); + else + PP_ASSERT_WITH_CODE( + vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true) == 0, + "[GetSclks]: fail to get max PPCLK_GFXCLK\n", + return -1); + + return (gfx_clk * 100); +} + +static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t mem_clk; + + if (!data->smu_features[GNLD_DPM_UCLK].enabled) + return -1; + + if (low) + PP_ASSERT_WITH_CODE( + vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false) == 0, + "[GetMclks]: fail to get min PPCLK_UCLK\n", + return -1); + else + PP_ASSERT_WITH_CODE( + vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true) == 0, + "[GetMclks]: fail to get max PPCLK_UCLK\n", + return -1); + + return (mem_clk * 100); +} + +static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); + if (ret) { + pr_info("Failed to export SMU metrics table!\n"); + return ret; + } + data->metrics_time = jiffies; + } + + if (metrics_table) + memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); + + return ret; +} + +static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr, uint32_t *query) +{ + SmuMetrics_t metrics_table; + int ret = 0; + + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *query = metrics_table.CurrSocketPower << 8; + + return ret; +} + +static int vega12_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq) +{ + uint32_t gfx_clk = 0; + + *gfx_freq = 0; + + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16), + &gfx_clk) == 0, + "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!", + return -EINVAL); + + *gfx_freq = gfx_clk * 100; + + return 0; +} + +static int vega12_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq) +{ + uint32_t mem_clk = 0; + + *mclk_freq = 0; + + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16), + &mem_clk) == 0, + "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!", + return -EINVAL); + + *mclk_freq = mem_clk * 100; + + return 0; +} + +static int vega12_get_current_activity_percent( + struct pp_hwmgr *hwmgr, + int idx, + uint32_t *activity_percent) +{ + SmuMetrics_t metrics_table; + int ret = 0; + + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + switch (idx) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + *activity_percent = metrics_table.AverageGfxActivity; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + *activity_percent = metrics_table.AverageUclkActivity; + break; + default: + pr_err("Invalid index for retrieving clock activity\n"); + return -EINVAL; + } + + return ret; +} + +static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + SmuMetrics_t metrics_table; + int ret = 0; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = vega12_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = vega12_get_current_mclk_freq(hwmgr, (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_LOAD: + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = vega12_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = vega12_thermal_get_temperature(hwmgr); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *((uint32_t *)value) = metrics_table.TemperatureHotspot * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *((uint32_t *)value) = metrics_table.TemperatureHBM * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_UVD_POWER: + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VCE_POWER: + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = vega12_get_gpu_power(hwmgr, (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: + ret = vega12_get_enabled_smc_features(hwmgr, (uint64_t *)value); + if (!ret) + *size = 8; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int vega12_notify_smc_display_change(struct pp_hwmgr *hwmgr, + bool has_disp) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DPM_UCLK].enabled) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetUclkFastSwitch, + has_disp ? 1 : 0, + NULL); + + return 0; +} + +static int vega12_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock_req) +{ + int result = 0; + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + enum amd_pp_clock_type clk_type = clock_req->clock_type; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + PPCLK_e clk_select = 0; + uint32_t clk_request = 0; + + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + switch (clk_type) { + case amd_pp_dcef_clock: + clk_select = PPCLK_DCEFCLK; + break; + case amd_pp_disp_clock: + clk_select = PPCLK_DISPCLK; + break; + case amd_pp_pixel_clock: + clk_select = PPCLK_PIXCLK; + break; + case amd_pp_phy_clock: + clk_select = PPCLK_PHYCLK; + break; + default: + pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); + result = -1; + break; + } + + if (!result) { + clk_request = (clk_select << 16) | clk_freq; + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinByFreq, + clk_request, + NULL); + } + } + + return result; +} + +static int vega12_notify_smc_display_config_after_ps_adjustment( + struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct PP_Clocks min_clocks = {0}; + struct pp_display_clock_request clock_req; + + if ((hwmgr->display_config->num_display > 1) && + !hwmgr->display_config->multi_monitor_in_sync && + !hwmgr->display_config->nb_pstate_switch_disable) + vega12_notify_smc_display_change(hwmgr, false); + else + vega12_notify_smc_display_change(hwmgr, true); + + min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; + min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; + min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; + + if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { + clock_req.clock_type = amd_pp_dcef_clock; + clock_req.clock_freq_in_khz = min_clocks.dcefClock/10; + if (!vega12_display_clock_voltage_request(hwmgr, &clock_req)) { + if (data->smu_features[GNLD_DS_DCEFCLK].supported) + PP_ASSERT_WITH_CODE( + !smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, + min_clocks.dcefClockInSR /100, + NULL), + "Attempt to set divider for DCEFCLK Failed!", + return -1); + } else { + pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); + } + } + + return 0; +} + +static int vega12_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + uint32_t soft_level; + + soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_level].value; + + soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.mem_table)); + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_level].value; + + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), + "Failed to upload boot level to highest!", + return -1); + + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -1); + + return 0; +} + +static int vega12_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t soft_level; + + soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_level].value; + + soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_level].value; + + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), + "Failed to upload boot level to highest!", + return -1); + + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), + "Failed to upload dpm max level to highest!", + return -1); + + return 0; + +} + +static int vega12_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), + "Failed to upload DPM Bootup Levels!", + return -1); + + PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), + "Failed to upload DPM Max Levels!", + return -1); + + return 0; +} + +static int vega12_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); + struct vega12_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); + struct vega12_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); + + *sclk_mask = 0; + *mclk_mask = 0; + *soc_mask = 0; + + if (gfx_dpm_table->count > VEGA12_UMD_PSTATE_GFXCLK_LEVEL && + mem_dpm_table->count > VEGA12_UMD_PSTATE_MCLK_LEVEL && + soc_dpm_table->count > VEGA12_UMD_PSTATE_SOCCLK_LEVEL) { + *sclk_mask = VEGA12_UMD_PSTATE_GFXCLK_LEVEL; + *mclk_mask = VEGA12_UMD_PSTATE_MCLK_LEVEL; + *soc_mask = VEGA12_UMD_PSTATE_SOCCLK_LEVEL; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + *sclk_mask = gfx_dpm_table->count - 1; + *mclk_mask = mem_dpm_table->count - 1; + *soc_mask = soc_dpm_table->count - 1; + } + + return 0; +} + +static void vega12_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + switch (mode) { + case AMD_FAN_CTRL_NONE: + break; + case AMD_FAN_CTRL_MANUAL: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega12_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega12_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } +} + +static int vega12_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask = 0; + uint32_t mclk_mask = 0; + uint32_t soc_mask = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = vega12_force_dpm_highest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = vega12_force_dpm_lowest(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = vega12_unforce_dpm_levels(hwmgr); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = vega12_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); + if (ret) + return ret; + vega12_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); + vega12_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + + return ret; +} + +static uint32_t vega12_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) + return AMD_FAN_CTRL_MANUAL; + else + return AMD_FAN_CTRL_AUTO; +} + +static int vega12_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ +#if 0 + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_clock_and_voltage_limits *max_limits = + &table_info->max_clock_voltage_on_ac; + + info->engine_max_clock = max_limits->sclk; + info->memory_max_clock = max_limits->mclk; +#endif + return 0; +} + +static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr, + uint32_t *clock, + PPCLK_e clock_select, + bool max) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (max) + *clock = data->clk_range[clock_select].ACMax; + else + *clock = data->clk_range[clock_select].ACMin; + + return 0; +} + +static int vega12_get_sclks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t ucount; + int i; + struct vega12_single_dpm_table *dpm_table; + + if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) + return -1; + + dpm_table = &(data->dpm_table.gfx_table); + ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? + MAX_NUM_CLOCKS : dpm_table->count; + + for (i = 0; i < ucount; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + + clocks->data[i].latency_in_us = 0; + } + + clocks->num_levels = ucount; + + return 0; +} + +static uint32_t vega12_get_mem_latency(struct pp_hwmgr *hwmgr, + uint32_t clock) +{ + return 25; +} + +static int vega12_get_memclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t ucount; + int i; + struct vega12_single_dpm_table *dpm_table; + if (!data->smu_features[GNLD_DPM_UCLK].enabled) + return -1; + + dpm_table = &(data->dpm_table.mem_table); + ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? + MAX_NUM_CLOCKS : dpm_table->count; + + for (i = 0; i < ucount; i++) { + clocks->data[i].clocks_in_khz = dpm_table->dpm_levels[i].value * 1000; + data->mclk_latency_table.entries[i].frequency = dpm_table->dpm_levels[i].value * 100; + clocks->data[i].latency_in_us = + data->mclk_latency_table.entries[i].latency = + vega12_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); + } + + clocks->num_levels = data->mclk_latency_table.count = ucount; + + return 0; +} + +static int vega12_get_dcefclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t ucount; + int i; + struct vega12_single_dpm_table *dpm_table; + + if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) + return -1; + + + dpm_table = &(data->dpm_table.dcef_table); + ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? + MAX_NUM_CLOCKS : dpm_table->count; + + for (i = 0; i < ucount; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + + clocks->data[i].latency_in_us = 0; + } + + clocks->num_levels = ucount; + + return 0; +} + +static int vega12_get_socclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t ucount; + int i; + struct vega12_single_dpm_table *dpm_table; + + if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) + return -1; + + + dpm_table = &(data->dpm_table.soc_table); + ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? + MAX_NUM_CLOCKS : dpm_table->count; + + for (i = 0; i < ucount; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + + clocks->data[i].latency_in_us = 0; + } + + clocks->num_levels = ucount; + + return 0; + +} + +static int vega12_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + int ret; + + switch (type) { + case amd_pp_sys_clock: + ret = vega12_get_sclks(hwmgr, clocks); + break; + case amd_pp_mem_clock: + ret = vega12_get_memclocks(hwmgr, clocks); + break; + case amd_pp_dcef_clock: + ret = vega12_get_dcefclocks(hwmgr, clocks); + break; + case amd_pp_soc_clock: + ret = vega12_get_socclocks(hwmgr, clocks); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int vega12_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + clocks->num_levels = 0; + + return 0; +} + +static int vega12_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_ranges) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + Watermarks_t *table = &(data->smc_state_table.water_marks_table); + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; + + if (!data->registry_data.disable_water_mark && + data->smu_features[GNLD_DPM_DCEFCLK].supported && + data->smu_features[GNLD_DPM_SOCCLK].supported) { + smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); + data->water_marks_bitmap |= WaterMarksExist; + data->water_marks_bitmap &= ~WaterMarksLoaded; + } + + return 0; +} + +static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + uint32_t soft_min_level, soft_max_level, hard_min_level; + int ret = 0; + + switch (type) { + case PP_SCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; + + ret = vega12_upload_dpm_min_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega12_upload_dpm_max_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + break; + + case PP_MCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_levels[soft_min_level].value; + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_max_level].value; + + ret = vega12_upload_dpm_min_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega12_upload_dpm_max_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + break; + + case PP_SOCCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if (soft_max_level >= data->dpm_table.soc_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.soc_table.count - 1); + return -EINVAL; + } + + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->dpm_table.soc_table.dpm_levels[soft_min_level].value; + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->dpm_table.soc_table.dpm_levels[soft_max_level].value; + + ret = vega12_upload_dpm_min_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega12_upload_dpm_max_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + break; + + case PP_DCEFCLK: + hard_min_level = mask ? (ffs(mask) - 1) : 0; + + if (hard_min_level >= data->dpm_table.dcef_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + hard_min_level, + data->dpm_table.dcef_table.count - 1); + return -EINVAL; + } + + data->dpm_table.dcef_table.dpm_state.hard_min_level = + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; + + ret = vega12_upload_dpm_min_level(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + //TODO: Setting DCEFCLK max dpm level is not supported + + break; + + case PP_PCIE: + break; + + default: + break; + } + + return 0; +} + +static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) +{ + static const char *ppfeature_name[] = { + "DPM_PREFETCHER", + "GFXCLK_DPM", + "UCLK_DPM", + "SOCCLK_DPM", + "UVD_DPM", + "VCE_DPM", + "ULV", + "MP0CLK_DPM", + "LINK_DPM", + "DCEFCLK_DPM", + "GFXCLK_DS", + "SOCCLK_DS", + "LCLK_DS", + "PPT", + "TDC", + "THERMAL", + "GFX_PER_CU_CG", + "RM", + "DCEFCLK_DS", + "ACDC", + "VR0HOT", + "VR1HOT", + "FW_CTF", + "LED_DISPLAY", + "FAN_CONTROL", + "DIDT", + "GFXOFF", + "CG", + "ACG"}; + static const char *output_title[] = { + "FEATURES", + "BITMASK", + "ENABLEMENT"}; + uint64_t features_enabled; + int i; + int ret = 0; + int size = 0; + + ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", + return ret); + + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); + size += sprintf(buf + size, "%-19s %-22s %s\n", + output_title[0], + output_title[1], + output_title[2]); + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", + ppfeature_name[i], + 1ULL << i, + (features_enabled & (1ULL << i)) ? "Y" : "N"); + } + + return size; +} + +static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) +{ + uint64_t features_enabled; + uint64_t features_to_enable; + uint64_t features_to_disable; + int ret = 0; + + if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) + return -EINVAL; + + ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + features_to_disable = + features_enabled & ~new_ppfeature_masks; + features_to_enable = + ~features_enabled & new_ppfeature_masks; + + pr_debug("features_to_disable 0x%llx\n", features_to_disable); + pr_debug("features_to_enable 0x%llx\n", features_to_enable); + + if (features_to_disable) { + ret = vega12_enable_smc_features(hwmgr, false, features_to_disable); + if (ret) + return ret; + } + + if (features_to_enable) { + ret = vega12_enable_smc_features(hwmgr, true, features_to_enable); + if (ret) + return ret; + } + + return 0; +} + +static int vega12_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega12_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega12_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega12_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega12_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega12_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + +static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + int i, now, size = 0; + struct pp_clock_levels_with_latency clocks; + + switch (type) { + case PP_SCLK: + PP_ASSERT_WITH_CODE( + vega12_get_current_gfx_clk_freq(hwmgr, &now) == 0, + "Attempt to get current gfx clk Failed!", + return -1); + + PP_ASSERT_WITH_CODE( + vega12_get_sclks(hwmgr, &clocks) == 0, + "Attempt to get gfx clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); + break; + + case PP_MCLK: + PP_ASSERT_WITH_CODE( + vega12_get_current_mclk_freq(hwmgr, &now) == 0, + "Attempt to get current mclk freq Failed!", + return -1); + + PP_ASSERT_WITH_CODE( + vega12_get_memclocks(hwmgr, &clocks) == 0, + "Attempt to get memory clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); + break; + + case PP_SOCCLK: + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmClockFreq, (PPCLK_SOCCLK << 16), + &now) == 0, + "Attempt to get Current SOCCLK Frequency Failed!", + return -EINVAL); + + PP_ASSERT_WITH_CODE( + vega12_get_socclocks(hwmgr, &clocks) == 0, + "Attempt to get soc clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); + break; + + case PP_DCEFCLK: + PP_ASSERT_WITH_CODE( + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmClockFreq, (PPCLK_DCEFCLK << 16), + &now) == 0, + "Attempt to get Current DCEFCLK Frequency Failed!", + return -EINVAL); + + PP_ASSERT_WITH_CODE( + vega12_get_dcefclocks(hwmgr, &clocks) == 0, + "Attempt to get dcef clk levels Failed!", + return -1); + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); + break; + + case PP_PCIE: + break; + + default: + break; + } + return size; +} + +static int vega12_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *dpm_table; + bool vblank_too_short = false; + bool disable_mclk_switching; + uint32_t i, latency; + + disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + vblank_too_short; + latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; + + /* gfxclk */ + dpm_table = &(data->dpm_table.gfx_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* memclk */ + dpm_table = &(data->dpm_table.mem_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* honour DAL's UCLK Hardmin */ + if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) + dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; + + /* Hardmin is dependent on displayconfig */ + if (disable_mclk_switching) { + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + for (i = 0; i < data->mclk_latency_table.count - 1; i++) { + if (data->mclk_latency_table.entries[i].latency <= latency) { + if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; + break; + } + } + } + } + + if (hwmgr->display_config->nb_pstate_switch_disable) + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + /* vclk */ + dpm_table = &(data->dpm_table.vclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* dclk */ + dpm_table = &(data->dpm_table.dclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* socclk */ + dpm_table = &(data->dpm_table.soc_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* eclk */ + dpm_table = &(data->dpm_table.eclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA12_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + return 0; +} + +static int vega12_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, + struct vega12_single_dpm_table *dpm_table) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + PP_ASSERT_WITH_CODE(dpm_table->count > 0, + "[SetUclkToHightestDpmLevel] Dpm table has no entry!", + return -EINVAL); + PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, + "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", + return -EINVAL); + + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinByFreq, + (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, + NULL)), + "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", + return ret); + } + + return ret; +} + +static int vega12_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + int ret = 0; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, 0, + NULL); + + ret = vega12_set_uclk_to_highest_dpm_level(hwmgr, + &data->dpm_table.mem_table); + + return ret; +} + +static int vega12_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + int result = 0; + Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); + + if ((data->water_marks_bitmap & WaterMarksExist) && + !(data->water_marks_bitmap & WaterMarksLoaded)) { + result = smum_smc_table_manager(hwmgr, + (uint8_t *)wm_table, TABLE_WATERMARKS, false); + PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); + data->water_marks_bitmap |= WaterMarksLoaded; + } + + if ((data->water_marks_bitmap & WaterMarksExist) && + data->smu_features[GNLD_DPM_DCEFCLK].supported && + data->smu_features[GNLD_DPM_SOCCLK].supported) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, + NULL); + + return result; +} + +static int vega12_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DPM_UVD].supported) { + PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), + "Attempt to Enable/Disable DPM UVD Failed!", + return -1); + data->smu_features[GNLD_DPM_UVD].enabled = enable; + } + + return 0; +} + +static void vega12_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->vce_power_gated == bgate) + return; + + data->vce_power_gated = bgate; + vega12_enable_disable_vce_dpm(hwmgr, !bgate); +} + +static void vega12_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->uvd_power_gated == bgate) + return; + + data->uvd_power_gated = bgate; + vega12_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +static bool +vega12_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + bool is_update_required = false; + + if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) + is_update_required = true; + + if (data->registry_data.gfx_clk_deep_sleep_support) { + if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) + is_update_required = true; + } + + return is_update_required; +} + +static int vega12_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = vega12_disable_all_smu_features(hwmgr); + PP_ASSERT_WITH_CODE((tmp_result == 0), + "Failed to disable all smu features!", result = tmp_result); + + return result; +} + +static int vega12_power_off_asic(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + int result; + + result = vega12_disable_dpm_tasks(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "[disable_dpm_tasks] Failed to disable DPM!", + ); + data->water_marks_bitmap &= ~(WaterMarksLoaded); + + return result; +} + +#if 0 +static void vega12_find_min_clock_index(struct pp_hwmgr *hwmgr, + uint32_t *sclk_idx, uint32_t *mclk_idx, + uint32_t min_sclk, uint32_t min_mclk) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_dpm_table *dpm_table = &(data->dpm_table); + uint32_t i; + + for (i = 0; i < dpm_table->gfx_table.count; i++) { + if (dpm_table->gfx_table.dpm_levels[i].enabled && + dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) { + *sclk_idx = i; + break; + } + } + + for (i = 0; i < dpm_table->mem_table.count; i++) { + if (dpm_table->mem_table.dpm_levels[i].enabled && + dpm_table->mem_table.dpm_levels[i].value >= min_mclk) { + *mclk_idx = i; + break; + } + } +} +#endif + +#if 0 +static int vega12_set_power_profile_state(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + return 0; +} + +static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); + struct vega12_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.gfx_table); + int value = sclk_table->dpm_levels[sclk_table->count - 1].value; + int golden_value = golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega12_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + return 0; +} + +static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); + struct vega12_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mem_table); + int value = mclk_table->dpm_levels[mclk_table->count - 1].value; + int golden_value = golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value; + + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega12_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) +{ + return 0; +} +#endif + +static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrHigh, + virtual_addr_hi, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrLow, + virtual_addr_low, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrHigh, + mc_addr_hi, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrLow, + mc_addr_low, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramSize, + size, + NULL); + return 0; +} + +static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *thermal_data) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + + memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); + + thermal_data->max = pp_table->TedgeLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_crit_max = pp_table->ThbmLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static int vega12_enable_gfx_off(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->gfxoff_controlled_by_driver) + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_AllowGfxOff, NULL); + + return ret; +} + +static int vega12_disable_gfx_off(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->gfxoff_controlled_by_driver) + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisallowGfxOff, NULL); + + return ret; +} + +static int vega12_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) +{ + if (enable) + return vega12_enable_gfx_off(hwmgr); + else + return vega12_disable_gfx_off(hwmgr); +} + +static int vega12_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + return 0; +} + +static int vega12_set_mp1_state(struct pp_hwmgr *hwmgr, + enum pp_mp1_state mp1_state) +{ + uint16_t msg; + int ret; + + switch (mp1_state) { + case PP_MP1_STATE_UNLOAD: + msg = PPSMC_MSG_PrepareMp1ForUnload; + break; + case PP_MP1_STATE_SHUTDOWN: + case PP_MP1_STATE_RESET: + case PP_MP1_STATE_NONE: + default: + return 0; + } + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, + "[PrepareMp1] Failed!", + return ret); + + return 0; +} + +static void vega12_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega12_hwmgr *data = + (struct vega12_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega12_get_metrics_table(hwmgr, &metrics, true); + if (ret) + return ret; + + vega12_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega12_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega12_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega12_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + +static const struct pp_hwmgr_func vega12_hwmgr_funcs = { + .backend_init = vega12_hwmgr_backend_init, + .backend_fini = vega12_hwmgr_backend_fini, + .asic_setup = vega12_setup_asic_task, + .dynamic_state_management_enable = vega12_enable_dpm_tasks, + .dynamic_state_management_disable = vega12_disable_dpm_tasks, + .patch_boot_state = vega12_patch_boot_state, + .get_sclk = vega12_dpm_get_sclk, + .get_mclk = vega12_dpm_get_mclk, + .notify_smc_display_config_after_ps_adjustment = + vega12_notify_smc_display_config_after_ps_adjustment, + .force_dpm_level = vega12_dpm_force_dpm_level, + .stop_thermal_controller = vega12_thermal_stop_thermal_controller, + .get_fan_speed_info = vega12_fan_ctrl_get_fan_speed_info, + .reset_fan_speed_to_default = + vega12_fan_ctrl_reset_fan_speed_to_default, + .get_fan_speed_rpm = vega12_fan_ctrl_get_fan_speed_rpm, + .set_fan_control_mode = vega12_set_fan_control_mode, + .get_fan_control_mode = vega12_get_fan_control_mode, + .read_sensor = vega12_read_sensor, + .get_dal_power_level = vega12_get_dal_power_level, + .get_clock_by_type_with_latency = vega12_get_clock_by_type_with_latency, + .get_clock_by_type_with_voltage = vega12_get_clock_by_type_with_voltage, + .set_watermarks_for_clocks_ranges = vega12_set_watermarks_for_clocks_ranges, + .display_clock_voltage_request = vega12_display_clock_voltage_request, + .force_clock_level = vega12_force_clock_level, + .print_clock_levels = vega12_print_clock_levels, + .apply_clocks_adjust_rules = + vega12_apply_clocks_adjust_rules, + .pre_display_config_changed = + vega12_pre_display_configuration_changed_task, + .display_config_changed = vega12_display_configuration_changed_task, + .powergate_uvd = vega12_power_gate_uvd, + .powergate_vce = vega12_power_gate_vce, + .check_smc_update_required_for_display_configuration = + vega12_check_smc_update_required_for_display_configuration, + .power_off_asic = vega12_power_off_asic, + .disable_smc_firmware_ctf = vega12_thermal_disable_alert, +#if 0 + .set_power_profile_state = vega12_set_power_profile_state, + .get_sclk_od = vega12_get_sclk_od, + .set_sclk_od = vega12_set_sclk_od, + .get_mclk_od = vega12_get_mclk_od, + .set_mclk_od = vega12_set_mclk_od, +#endif + .notify_cac_buffer_info = vega12_notify_cac_buffer_info, + .get_thermal_temperature_range = vega12_get_thermal_temperature_range, + .register_irq_handlers = smu9_register_irq_handlers, + .start_thermal_controller = vega12_start_thermal_controller, + .powergate_gfx = vega12_gfx_off_control, + .get_performance_level = vega12_get_performance_level, + .get_asic_baco_capability = smu9_baco_get_capability, + .get_asic_baco_state = smu9_baco_get_state, + .set_asic_baco_state = vega12_baco_set_state, + .get_ppfeature_status = vega12_get_ppfeature_status, + .set_ppfeature_status = vega12_set_ppfeature_status, + .set_mp1_state = vega12_set_mp1_state, + .get_gpu_metrics = vega12_get_gpu_metrics, +}; + +int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + hwmgr->hwmgr_func = &vega12_hwmgr_funcs; + hwmgr->pptable_func = &vega12_pptable_funcs; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h new file mode 100644 index 000000000000..aa63ae41942d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_hwmgr.h @@ -0,0 +1,458 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _VEGA12_HWMGR_H_ +#define _VEGA12_HWMGR_H_ + +#include "hwmgr.h" +#include "vega12/smu9_driver_if.h" +#include "ppatomfwctrl.h" + +#define VEGA12_MAX_HARDWARE_POWERLEVELS 2 + +#define WaterMarksExist 1 +#define WaterMarksLoaded 2 + +#define VG12_PSUEDO_NUM_GFXCLK_DPM_LEVELS 16 +#define VG12_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8 +#define VG12_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8 +#define VG12_PSUEDO_NUM_UCLK_DPM_LEVELS 4 + +enum +{ + GNLD_DPM_PREFETCHER = 0, + GNLD_DPM_GFXCLK, + GNLD_DPM_UCLK, + GNLD_DPM_SOCCLK, + GNLD_DPM_UVD, + GNLD_DPM_VCE, + GNLD_ULV, + GNLD_DPM_MP0CLK, + GNLD_DPM_LINK, + GNLD_DPM_DCEFCLK, + GNLD_DS_GFXCLK, + GNLD_DS_SOCCLK, + GNLD_DS_LCLK, + GNLD_PPT, + GNLD_TDC, + GNLD_THERMAL, + GNLD_GFX_PER_CU_CG, + GNLD_RM, + GNLD_DS_DCEFCLK, + GNLD_ACDC, + GNLD_VR0HOT, + GNLD_VR1HOT, + GNLD_FW_CTF, + GNLD_LED_DISPLAY, + GNLD_FAN_CONTROL, + GNLD_DIDT, + GNLD_GFXOFF, + GNLD_CG, + GNLD_ACG, + + GNLD_FEATURES_MAX +}; + + +#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) + +#define SMC_DPM_FEATURES 0x30F + +struct smu_features { + bool supported; + bool enabled; + bool allowed; + uint32_t smu_feature_id; + uint64_t smu_feature_bitmap; +}; + +struct vega12_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +#define VEGA12_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 16 +#define MAX_PCIE_CONF 2 +#define VEGA12_MINIMUM_ENGINE_CLOCK 2500 + +struct vega12_dpm_state { + uint32_t soft_min_level; + uint32_t soft_max_level; + uint32_t hard_min_level; + uint32_t hard_max_level; +}; + +struct vega12_single_dpm_table { + uint32_t count; + struct vega12_dpm_state dpm_state; + struct vega12_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega12_odn_dpm_control { + uint32_t count; + uint32_t entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega12_pcie_table { + uint16_t count; + uint8_t pcie_gen[MAX_PCIE_CONF]; + uint8_t pcie_lane[MAX_PCIE_CONF]; + uint32_t lclk[MAX_PCIE_CONF]; +}; + +struct vega12_dpm_table { + struct vega12_single_dpm_table soc_table; + struct vega12_single_dpm_table gfx_table; + struct vega12_single_dpm_table mem_table; + struct vega12_single_dpm_table eclk_table; + struct vega12_single_dpm_table vclk_table; + struct vega12_single_dpm_table dclk_table; + struct vega12_single_dpm_table dcef_table; + struct vega12_single_dpm_table pixel_table; + struct vega12_single_dpm_table display_table; + struct vega12_single_dpm_table phy_table; + struct vega12_pcie_table pcie_table; +}; + +#define VEGA12_MAX_LEAKAGE_COUNT 8 +struct vega12_leakage_voltage { + uint16_t count; + uint16_t leakage_id[VEGA12_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[VEGA12_MAX_LEAKAGE_COUNT]; +}; + +struct vega12_display_timing { + uint32_t min_clock_in_sr; + uint32_t num_existing_displays; +}; + +struct vega12_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; +}; + +struct vega12_vbios_boot_state { + bool bsoc_vddc_lock; + uint8_t uc_cooling_id; + uint16_t vddc; + uint16_t vddci; + uint16_t mvddc; + uint16_t vdd_gfx; + uint32_t gfx_clock; + uint32_t mem_clock; + uint32_t soc_clock; + uint32_t dcef_clock; + uint32_t eclock; + uint32_t dclock; + uint32_t vclock; +}; + +#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 +#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 +#define DPMTABLE_UPDATE_SCLK 0x00000004 +#define DPMTABLE_UPDATE_MCLK 0x00000008 +#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 + +struct vega12_smc_state_table { + uint32_t soc_boot_level; + uint32_t gfx_boot_level; + uint32_t dcef_boot_level; + uint32_t mem_boot_level; + uint32_t uvd_boot_level; + uint32_t vce_boot_level; + uint32_t gfx_max_level; + uint32_t mem_max_level; + uint8_t vr_hot_gpio; + uint8_t ac_dc_gpio; + uint8_t therm_out_gpio; + uint8_t therm_out_polarity; + uint8_t therm_out_mode; + PPTable_t pp_table; + Watermarks_t water_marks_table; + AvfsDebugTable_t avfs_debug_table; + AvfsFuseOverride_t avfs_fuse_override_table; + SmuMetrics_t smu_metrics; + DriverSmuConfig_t driver_smu_config; + DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint; + OverDriveTable_t overdrive_table; +}; + +struct vega12_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct vega12_mclk_latency_table { + uint32_t count; + struct vega12_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega12_registry_data { + uint64_t disallowed_features; + uint8_t ac_dc_switch_gpio_support; + uint8_t acg_loop_support; + uint8_t clock_stretcher_support; + uint8_t db_ramping_support; + uint8_t didt_mode; + uint8_t didt_support; + uint8_t edc_didt_support; + uint8_t force_dpm_high; + uint8_t fuzzy_fan_control_support; + uint8_t mclk_dpm_key_disabled; + uint8_t od_state_in_dc_support; + uint8_t pcie_lane_override; + uint8_t pcie_speed_override; + uint32_t pcie_clock_override; + uint8_t pcie_dpm_key_disabled; + uint8_t dcefclk_dpm_key_disabled; + uint8_t prefetcher_dpm_key_disabled; + uint8_t quick_transition_support; + uint8_t regulator_hot_gpio_support; + uint8_t master_deep_sleep_support; + uint8_t gfx_clk_deep_sleep_support; + uint8_t sclk_deep_sleep_support; + uint8_t lclk_deep_sleep_support; + uint8_t dce_fclk_deep_sleep_support; + uint8_t sclk_dpm_key_disabled; + uint8_t sclk_throttle_low_notification; + uint8_t skip_baco_hardware; + uint8_t socclk_dpm_key_disabled; + uint8_t sq_ramping_support; + uint8_t tcp_ramping_support; + uint8_t td_ramping_support; + uint8_t dbr_ramping_support; + uint8_t gc_didt_support; + uint8_t psm_didt_support; + uint8_t thermal_support; + uint8_t fw_ctf_enabled; + uint8_t led_dpm_enabled; + uint8_t fan_control_support; + uint8_t ulv_support; + uint8_t odn_feature_enable; + uint8_t disable_water_mark; + uint8_t disable_workload_policy; + uint32_t force_workload_policy_mask; + uint8_t disable_3d_fs_detection; + uint8_t disable_pp_tuning; + uint8_t disable_xlpp_tuning; + uint32_t perf_ui_tuning_profile_turbo; + uint32_t perf_ui_tuning_profile_powerSave; + uint32_t perf_ui_tuning_profile_xl; + uint16_t zrpm_stop_temp; + uint16_t zrpm_start_temp; + uint32_t stable_pstate_sclk_dpm_percentage; + uint8_t fps_support; + uint8_t vr0hot; + uint8_t vr1hot; + uint8_t disable_auto_wattman; + uint32_t auto_wattman_debug; + uint32_t auto_wattman_sample_period; + uint8_t auto_wattman_threshold; + uint8_t log_avfs_param; + uint8_t enable_enginess; + uint8_t custom_fan_support; + uint8_t disable_pcc_limit_control; +}; + +struct vega12_odn_clock_voltage_dependency_table { + uint32_t count; + struct phm_ppt_v1_clock_voltage_dependency_record + entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega12_odn_dpm_table { + struct vega12_odn_dpm_control control_gfxclk_state; + struct vega12_odn_dpm_control control_memclk_state; + struct phm_odn_clock_levels odn_core_clock_dpm_levels; + struct phm_odn_clock_levels odn_memory_clock_dpm_levels; + struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; + struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; + struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_socclk; + uint32_t odn_mclk_min_limit; +}; + +struct vega12_odn_fan_table { + uint32_t target_fan_speed; + uint32_t target_temperature; + uint32_t min_performance_clock; + uint32_t min_fan_limit; + bool force_fan_pwm; +}; + +struct vega12_clock_range { + uint32_t ACMax; + uint32_t ACMin; + uint32_t DCMax; +}; + +struct vega12_hwmgr { + struct vega12_dpm_table dpm_table; + struct vega12_dpm_table golden_dpm_table; + struct vega12_registry_data registry_data; + struct vega12_vbios_boot_state vbios_boot_state; + struct vega12_mclk_latency_table mclk_latency_table; + + struct vega12_leakage_voltage vddc_leakage; + + uint32_t vddc_control; + struct pp_atomfwctrl_voltage_table vddc_voltage_table; + uint32_t mvdd_control; + struct pp_atomfwctrl_voltage_table mvdd_voltage_table; + uint32_t vddci_control; + struct pp_atomfwctrl_voltage_table vddci_voltage_table; + + uint32_t active_auto_throttle_sources; + uint32_t water_marks_bitmap; + + struct vega12_odn_dpm_table odn_dpm_table; + struct vega12_odn_fan_table odn_fan_table; + + /* ---- General data ---- */ + uint8_t need_update_dpm_table; + + bool cac_enabled; + bool battery_state; + bool is_tlu_enabled; + bool avfs_exist; + + uint32_t low_sclk_interrupt_threshold; + + uint32_t total_active_cus; + + struct vega12_display_timing display_timing; + + /* ---- Vega12 Dyn Register Settings ---- */ + + uint32_t debug_settings; + uint32_t lowest_uclk_reserved_for_ulv; + uint32_t gfxclk_average_alpha; + uint32_t socclk_average_alpha; + uint32_t uclk_average_alpha; + uint32_t gfx_activity_average_alpha; + uint32_t display_voltage_mode; + uint32_t dcef_clk_quad_eqn_a; + uint32_t dcef_clk_quad_eqn_b; + uint32_t dcef_clk_quad_eqn_c; + uint32_t disp_clk_quad_eqn_a; + uint32_t disp_clk_quad_eqn_b; + uint32_t disp_clk_quad_eqn_c; + uint32_t pixel_clk_quad_eqn_a; + uint32_t pixel_clk_quad_eqn_b; + uint32_t pixel_clk_quad_eqn_c; + uint32_t phy_clk_quad_eqn_a; + uint32_t phy_clk_quad_eqn_b; + uint32_t phy_clk_quad_eqn_c; + + /* ---- Thermal Temperature Setting ---- */ + struct vega12_dpmlevel_enable_mask dpm_level_enable_mask; + + /* ---- Power Gating States ---- */ + bool uvd_power_gated; + bool vce_power_gated; + bool samu_power_gated; + bool need_long_memory_training; + + /* Internal settings to apply the application power optimization parameters */ + bool apply_optimized_settings; + uint32_t disable_dpm_mask; + + /* ---- Overdrive next setting ---- */ + uint32_t apply_overdrive_next_settings_mask; + + /* ---- Workload Mask ---- */ + uint32_t workload_mask; + + /* ---- SMU9 ---- */ + uint32_t smu_version; + struct smu_features smu_features[GNLD_FEATURES_MAX]; + struct vega12_smc_state_table smc_state_table; + + struct vega12_clock_range clk_range[PPCLK_COUNT]; + + /* ---- Gfxoff ---- */ + bool gfxoff_controlled_by_driver; + + unsigned long metrics_time; + SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; +}; + +#define VEGA12_DPM2_NEAR_TDP_DEC 10 +#define VEGA12_DPM2_ABOVE_SAFE_INC 5 +#define VEGA12_DPM2_BELOW_SAFE_INC 20 + +#define VEGA12_DPM2_LTA_WINDOW_SIZE 7 + +#define VEGA12_DPM2_LTS_TRUNCATE 0 + +#define VEGA12_DPM2_TDP_SAFE_LIMIT_PERCENT 80 + +#define VEGA12_DPM2_MAXPS_PERCENT_M 90 +#define VEGA12_DPM2_MAXPS_PERCENT_H 90 + +#define VEGA12_DPM2_PWREFFICIENCYRATIO_MARGIN 50 + +#define VEGA12_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define VEGA12_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define VEGA12_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define VEGA12_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E +#define VEGA12_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF + +#define VEGA12_VOLTAGE_CONTROL_NONE 0x0 +#define VEGA12_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define VEGA12_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define VEGA12_VOLTAGE_CONTROL_MERGED 0x3 +/* To convert to Q8.8 format for firmware */ +#define VEGA12_Q88_FORMAT_CONVERSION_UNIT 256 + +#define VEGA12_UNUSED_GPIO_PIN 0x7F + +#define VEGA12_THERM_OUT_MODE_DISABLE 0x0 +#define VEGA12_THERM_OUT_MODE_THERM_ONLY 0x1 +#define VEGA12_THERM_OUT_MODE_THERM_VRHOT 0x2 + +#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff +#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff + +#define PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff +#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff +#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff + +#define VEGA12_UMD_PSTATE_GFXCLK_LEVEL 0x3 +#define VEGA12_UMD_PSTATE_SOCCLK_LEVEL 0x3 +#define VEGA12_UMD_PSTATE_MCLK_LEVEL 0x2 +#define VEGA12_UMD_PSTATE_UVDCLK_LEVEL 0x3 +#define VEGA12_UMD_PSTATE_VCEMCLK_LEVEL 0x3 + +int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); + +#endif /* _VEGA12_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h new file mode 100644 index 000000000000..e6d9e84059e1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h @@ -0,0 +1,41 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef VEGA12_INC_H +#define VEGA12_INC_H + +#include "asic_reg/thm/thm_9_0_default.h" +#include "asic_reg/thm/thm_9_0_offset.h" +#include "asic_reg/thm/thm_9_0_sh_mask.h" + +#include "asic_reg/mp/mp_9_0_offset.h" +#include "asic_reg/mp/mp_9_0_sh_mask.h" + +#include "asic_reg/gc/gc_9_2_1_offset.h" +#include "asic_reg/gc/gc_9_2_1_sh_mask.h" + +#include "asic_reg/nbio/nbio_6_1_offset.h" +#include "asic_reg/nbio/nbio_6_1_offset.h" +#include "asic_reg/nbio/nbio_6_1_sh_mask.h" + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h new file mode 100644 index 000000000000..bf4f5095b80d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_pptable.h @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _VEGA12_PPTABLE_H_ +#define _VEGA12_PPTABLE_H_ + +#pragma pack(push, 1) + +#define ATOM_VEGA12_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_VEGA12_PP_THERMALCONTROLLER_VEGA12 25 + +#define ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY 0x1 +#define ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 +#define ATOM_VEGA12_PP_PLATFORM_CAP_HARDWAREDC 0x4 +#define ATOM_VEGA12_PP_PLATFORM_CAP_BACO 0x8 +#define ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO 0x10 +#define ATOM_VEGA12_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20 + +#define ATOM_VEGA12_TABLE_REVISION_VEGA12 9 + +enum ATOM_VEGA12_ODSETTING_ID { + ATOM_VEGA12_ODSETTING_GFXCLKFMAX = 0, + ATOM_VEGA12_ODSETTING_GFXCLKFMIN, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P1, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P2, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P3, + ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3, + ATOM_VEGA12_ODSETTING_UCLKFMAX, + ATOM_VEGA12_ODSETTING_POWERPERCENTAGE, + ATOM_VEGA12_ODSETTING_FANRPMMIN, + ATOM_VEGA12_ODSETTING_FANRPMACOUSTICLIMIT, + ATOM_VEGA12_ODSETTING_FANTARGETTEMPERATURE, + ATOM_VEGA12_ODSETTING_OPERATINGTEMPMAX, + ATOM_VEGA12_ODSETTING_COUNT, +}; +typedef enum ATOM_VEGA12_ODSETTING_ID ATOM_VEGA12_ODSETTING_ID; + +enum ATOM_VEGA12_PPCLOCK_ID { + ATOM_VEGA12_PPCLOCK_GFXCLK = 0, + ATOM_VEGA12_PPCLOCK_VCLK, + ATOM_VEGA12_PPCLOCK_DCLK, + ATOM_VEGA12_PPCLOCK_ECLK, + ATOM_VEGA12_PPCLOCK_SOCCLK, + ATOM_VEGA12_PPCLOCK_UCLK, + ATOM_VEGA12_PPCLOCK_DCEFCLK, + ATOM_VEGA12_PPCLOCK_DISPCLK, + ATOM_VEGA12_PPCLOCK_PIXCLK, + ATOM_VEGA12_PPCLOCK_PHYCLK, + ATOM_VEGA12_PPCLOCK_COUNT, +}; +typedef enum ATOM_VEGA12_PPCLOCK_ID ATOM_VEGA12_PPCLOCK_ID; + + +typedef struct _ATOM_VEGA12_POWERPLAYTABLE +{ + struct atom_common_table_header sHeader; + UCHAR ucTableRevision; + USHORT usTableSize; + ULONG ulGoldenPPID; + ULONG ulGoldenRevision; + USHORT usFormatID; + + ULONG ulPlatformCaps; + + UCHAR ucThermalControllerType; + + USHORT usSmallPowerLimit1; + USHORT usSmallPowerLimit2; + USHORT usBoostPowerLimit; + USHORT usODTurboPowerLimit; + USHORT usODPowerSavePowerLimit; + USHORT usSoftwareShutdownTemp; + + ULONG PowerSavingClockMax [ATOM_VEGA12_PPCLOCK_COUNT]; + ULONG PowerSavingClockMin [ATOM_VEGA12_PPCLOCK_COUNT]; + + ULONG ODSettingsMax [ATOM_VEGA12_ODSETTING_COUNT]; + ULONG ODSettingsMin [ATOM_VEGA12_ODSETTING_COUNT]; + + USHORT usReserve[5]; + + PPTable_t smcPPTable; + +} ATOM_Vega12_POWERPLAYTABLE; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c new file mode 100644 index 000000000000..195d8539fbb4 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c @@ -0,0 +1,402 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include +#include + +#include "vega12/smu9_driver_if.h" +#include "vega12_processpptables.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "pp_debug.h" +#include "cgs_common.h" +#include "vega12_pptable.h" + +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, + enum phm_platform_caps cap) +{ + if (enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + +static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterDataTable(powerplayinfo); + + u16 size; + u8 frev, crev; + const void *table_address = hwmgr->soft_pp_table; + + if (!table_address) { + table_address = (ATOM_Vega12_POWERPLAYTABLE *) + smu_atom_get_data_table(hwmgr->adev, index, + &size, &frev, &crev); + + hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ + hwmgr->soft_pp_table_size = size; + } + + return table_address; +} + +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Vega12_POWERPLAYTABLE *powerplay_table) +{ + PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= + ATOM_VEGA12_TABLE_REVISION_VEGA12), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, + "Invalid PowerPlay Table!", return -1); + + return 0; +} + +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO), + PHM_PlatformCaps_BAMACO); + + return 0; +} + +static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable) +{ + struct pp_atomfwctrl_smc_dpm_parameters smc_dpm_table; + + PP_ASSERT_WITH_CODE( + pp_atomfwctrl_get_smc_dpm_information(hwmgr, &smc_dpm_table) == 0, + "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", + return -1); + + ppsmc_pptable->Liquid1_I2C_address = smc_dpm_table.liquid1_i2c_address; + ppsmc_pptable->Liquid2_I2C_address = smc_dpm_table.liquid2_i2c_address; + ppsmc_pptable->Vr_I2C_address = smc_dpm_table.vr_i2c_address; + ppsmc_pptable->Plx_I2C_address = smc_dpm_table.plx_i2c_address; + + ppsmc_pptable->Liquid_I2C_LineSCL = smc_dpm_table.liquid_i2c_linescl; + ppsmc_pptable->Liquid_I2C_LineSDA = smc_dpm_table.liquid_i2c_linesda; + ppsmc_pptable->Vr_I2C_LineSCL = smc_dpm_table.vr_i2c_linescl; + ppsmc_pptable->Vr_I2C_LineSDA = smc_dpm_table.vr_i2c_linesda; + + ppsmc_pptable->Plx_I2C_LineSCL = smc_dpm_table.plx_i2c_linescl; + ppsmc_pptable->Plx_I2C_LineSDA = smc_dpm_table.plx_i2c_linesda; + ppsmc_pptable->VrSensorPresent = smc_dpm_table.vrsensorpresent; + ppsmc_pptable->LiquidSensorPresent = smc_dpm_table.liquidsensorpresent; + + ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table.maxvoltagestepgfx; + ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table.maxvoltagestepsoc; + + ppsmc_pptable->VddGfxVrMapping = smc_dpm_table.vddgfxvrmapping; + ppsmc_pptable->VddSocVrMapping = smc_dpm_table.vddsocvrmapping; + ppsmc_pptable->VddMem0VrMapping = smc_dpm_table.vddmem0vrmapping; + ppsmc_pptable->VddMem1VrMapping = smc_dpm_table.vddmem1vrmapping; + + ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table.gfxulvphasesheddingmask; + ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table.soculvphasesheddingmask; + + ppsmc_pptable->GfxMaxCurrent = smc_dpm_table.gfxmaxcurrent; + ppsmc_pptable->GfxOffset = smc_dpm_table.gfxoffset; + ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table.padding_telemetrygfx; + + ppsmc_pptable->SocMaxCurrent = smc_dpm_table.socmaxcurrent; + ppsmc_pptable->SocOffset = smc_dpm_table.socoffset; + ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table.padding_telemetrysoc; + + ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table.mem0maxcurrent; + ppsmc_pptable->Mem0Offset = smc_dpm_table.mem0offset; + ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table.padding_telemetrymem0; + + ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table.mem1maxcurrent; + ppsmc_pptable->Mem1Offset = smc_dpm_table.mem1offset; + ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table.padding_telemetrymem1; + + ppsmc_pptable->AcDcGpio = smc_dpm_table.acdcgpio; + ppsmc_pptable->AcDcPolarity = smc_dpm_table.acdcpolarity; + ppsmc_pptable->VR0HotGpio = smc_dpm_table.vr0hotgpio; + ppsmc_pptable->VR0HotPolarity = smc_dpm_table.vr0hotpolarity; + + ppsmc_pptable->VR1HotGpio = smc_dpm_table.vr1hotgpio; + ppsmc_pptable->VR1HotPolarity = smc_dpm_table.vr1hotpolarity; + ppsmc_pptable->Padding1 = smc_dpm_table.padding1; + ppsmc_pptable->Padding2 = smc_dpm_table.padding2; + + ppsmc_pptable->LedPin0 = smc_dpm_table.ledpin0; + ppsmc_pptable->LedPin1 = smc_dpm_table.ledpin1; + ppsmc_pptable->LedPin2 = smc_dpm_table.ledpin2; + + ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table.pllgfxclkspreadenabled; + ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table.pllgfxclkspreadpercent; + ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table.pllgfxclkspreadfreq; + + ppsmc_pptable->UclkSpreadEnabled = 0; + ppsmc_pptable->UclkSpreadPercent = smc_dpm_table.uclkspreadpercent; + ppsmc_pptable->UclkSpreadFreq = smc_dpm_table.uclkspreadfreq; + + ppsmc_pptable->SocclkSpreadEnabled = 0; + ppsmc_pptable->SocclkSpreadPercent = smc_dpm_table.socclkspreadpercent; + ppsmc_pptable->SocclkSpreadFreq = smc_dpm_table.socclkspreadfreq; + + ppsmc_pptable->AcgGfxclkSpreadEnabled = smc_dpm_table.acggfxclkspreadenabled; + ppsmc_pptable->AcgGfxclkSpreadPercent = smc_dpm_table.acggfxclkspreadpercent; + ppsmc_pptable->AcgGfxclkSpreadFreq = smc_dpm_table.acggfxclkspreadfreq; + + ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; + + ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; + + return 0; +} + +#define VEGA12_ENGINECLOCK_HARDMAX 198000 +static int init_powerplay_table_information( + struct pp_hwmgr *hwmgr, + const ATOM_Vega12_POWERPLAYTABLE *powerplay_table) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + uint32_t disable_power_control = 0; + int result; + + hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType; + pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType; + + set_hw_cap(hwmgr, + ATOM_VEGA12_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + + if (le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]) > VEGA12_ENGINECLOCK_HARDMAX) + hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA12_ENGINECLOCK_HARDMAX; + else + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX]); + + phm_copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_max, + powerplay_table->ODSettingsMax, + ATOM_VEGA12_ODSETTING_COUNT); + phm_copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_min, + powerplay_table->ODSettingsMin, + ATOM_VEGA12_ODSETTING_COUNT); + + /* hwmgr->platformDescriptor.minOverdriveVDDC = 0; + hwmgr->platformDescriptor.maxOverdriveVDDC = 0; + hwmgr->platformDescriptor.overdriveVDDCStep = 0; */ + + if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 + && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport); + + pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1); + pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2); + pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit); + pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit); + pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit); + + pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp); + + hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE]); + + disable_power_control = 0; + if (!disable_power_control) { + /* enable TDP overdrive (PowerControl) feature as well if supported */ + if (hwmgr->platform_descriptor.TDPODLimit) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + } + + phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT); + phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT); + + pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); + if (pptable_information->smc_pptable == NULL) + return -ENOMEM; + + memcpy(pptable_information->smc_pptable, &(powerplay_table->smcPPTable), sizeof(PPTable_t)); + + result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); + + return result; +} + +static int vega12_pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Vega12_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL); + PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), + "Failed to allocate hwmgr->pptable!", return -ENOMEM); + + powerplay_table = get_powerplay_table(hwmgr); + PP_ASSERT_WITH_CODE((powerplay_table != NULL), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_powerplay_table_information(hwmgr, powerplay_table); + PP_ASSERT_WITH_CODE((result == 0), + "init_powerplay_table_information failed", return result); + + return result; +} + +static int vega12_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pp_table_info = + (struct phm_ppt_v3_information *)(hwmgr->pptable); + + kfree(pp_table_info->power_saving_clock_max); + pp_table_info->power_saving_clock_max = NULL; + + kfree(pp_table_info->power_saving_clock_min); + pp_table_info->power_saving_clock_min = NULL; + + kfree(pp_table_info->od_settings_max); + pp_table_info->od_settings_max = NULL; + + kfree(pp_table_info->od_settings_min); + pp_table_info->od_settings_min = NULL; + + kfree(pp_table_info->smc_pptable); + pp_table_info->smc_pptable = NULL; + + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + + return 0; +} + +const struct pp_table_func vega12_pptable_funcs = { + .pptable_init = vega12_pp_tables_initialize, + .pptable_fini = vega12_pp_tables_uninitialize, +}; + +#if 0 +static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, + uint16_t classification, uint16_t classification2) +{ + uint32_t result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + return result; +} + +int vega12_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, + uint32_t entry_index, struct pp_power_state *power_state, + int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)) +{ + int result = 0; + const ATOM_Vega12_State_Array *state_arrays; + const ATOM_Vega12_State *state_entry; + const ATOM_Vega12_POWERPLAYTABLE *pp_table = + get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", + return -1;); + power_state->classification.bios_index = entry_index; + + if (pp_table->sHeader.format_revision >= + ATOM_Vega12_TABLE_REVISION_VEGA12) { + state_arrays = (ATOM_Vega12_State_Array *) + (((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, + "Invalid PowerPlay Table State Array Offset.", + return -1); + PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, + "Invalid PowerPlay Table State Array.", + return -1); + PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array Entry.", + return -1); + + state_entry = &(state_arrays->states[entry_index]); + + result = call_back_func(hwmgr, (void *)state_entry, power_state, + (void *)pp_table, + make_classification_flags(hwmgr, + le16_to_cpu(state_entry->usClassification), + le16_to_cpu(state_entry->usClassification2))); + } + + if (!result && (power_state->classification.flags & + PP_StateClassificationFlag_Boot)) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + + return result; +} +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h new file mode 100644 index 000000000000..65652ae65929 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.h @@ -0,0 +1,58 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef VEGA12_PROCESSPPTABLES_H +#define VEGA12_PROCESSPPTABLES_H + +#include "hwmgr.h" + +enum Vega12_I2CLineID { + Vega12_I2CLineID_DDC1 = 0x90, + Vega12_I2CLineID_DDC2 = 0x91, + Vega12_I2CLineID_DDC3 = 0x92, + Vega12_I2CLineID_DDC4 = 0x93, + Vega12_I2CLineID_DDC5 = 0x94, + Vega12_I2CLineID_DDC6 = 0x95, + Vega12_I2CLineID_SCLSDA = 0x96, + Vega12_I2CLineID_DDCVGA = 0x97 +}; + +#define Vega12_I2C_DDC1DATA 0 +#define Vega12_I2C_DDC1CLK 1 +#define Vega12_I2C_DDC2DATA 2 +#define Vega12_I2C_DDC2CLK 3 +#define Vega12_I2C_DDC3DATA 4 +#define Vega12_I2C_DDC3CLK 5 +#define Vega12_I2C_SDA 40 +#define Vega12_I2C_SCL 41 +#define Vega12_I2C_DDC4DATA 65 +#define Vega12_I2C_DDC4CLK 66 +#define Vega12_I2C_DDC5DATA 0x48 +#define Vega12_I2C_DDC5CLK 0x49 +#define Vega12_I2C_DDC6DATA 0x4a +#define Vega12_I2C_DDC6CLK 0x4b +#define Vega12_I2C_DDCVGADATA 0x4c +#define Vega12_I2C_DDCVGACLK 0x4d + +extern const struct pp_table_func vega12_pptable_funcs; +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c new file mode 100644 index 000000000000..c15b9756025d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -0,0 +1,316 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "vega12_thermal.h" +#include "vega12_hwmgr.h" +#include "vega12_smumgr.h" +#include "vega12_ppsmc.h" +#include "vega12_inc.h" +#include "soc15_common.h" +#include "pp_debug.h" + +static int vega12_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) +{ + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetCurrentRpm, + current_rpm), + "Attempt to get current RPM from SMC Failed!", + return -EINVAL); + + return 0; +} + +int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info) +{ + memset(fan_speed_info, 0, sizeof(*fan_speed_info)); + fan_speed_info->supports_percent_read = false; + fan_speed_info->supports_percent_write = false; + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + + return 0; +} + +int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + *speed = 0; + + return vega12_get_current_rpm(hwmgr, speed); +} + +/** + * @fn vega12_enable_fan_control_feature + * @brief Enables the SMC Fan Control Feature. + * + * @param hwmgr - the address of the powerplay hardware manager. + * @return 0 on success. -1 otherwise. + */ +static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ +#if 0 + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + PP_ASSERT_WITH_CODE(!vega12_enable_smc_features( + hwmgr, true, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap), + "Attempt to Enable FAN CONTROL feature Failed!", + return -1); + data->smu_features[GNLD_FAN_CONTROL].enabled = true; + } +#endif + return 0; +} + +static int vega12_disable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ +#if 0 + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + PP_ASSERT_WITH_CODE(!vega12_enable_smc_features( + hwmgr, false, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap), + "Attempt to Enable FAN CONTROL feature Failed!", + return -1); + data->smu_features[GNLD_FAN_CONTROL].enabled = false; + } +#endif + return 0; +} + +int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].supported) + PP_ASSERT_WITH_CODE( + !vega12_enable_fan_control_feature(hwmgr), + "Attempt to Enable SMC FAN CONTROL Feature Failed!", + return -1); + + return 0; +} + + +int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].supported) + PP_ASSERT_WITH_CODE(!vega12_disable_fan_control_feature(hwmgr), + "Attempt to Disable SMC FAN CONTROL Feature Failed!", + return -1); + + return 0; +} + +/** +* Reset Fan Speed to default. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Always succeeds. +*/ +int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) +{ + return vega12_fan_ctrl_start_smc_fan_control(hwmgr); +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int temp = 0; + + temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); + + temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> + CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; + + temp = temp & 0x1ff; + + temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for +* high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + struct amdgpu_device *adev = hwmgr->adev; + int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + uint32_t val; + + if (low < range->min) + low = range->min; + if (high > range->max) + high = range->max; + + if (low > high) + return -EINVAL; + + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t val = 0; + + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); + + return 0; +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); + + return 0; +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = vega12_thermal_disable_alert(hwmgr); + + return result; +} + +/** +* Set up the fan table to control the fan using the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + int ret; + struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); + PPTable_t *table = &(data->smc_state_table.pp_table); + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanTemperatureTarget, + (uint32_t)table->FanTargetTemperature, + NULL); + + return ret; +} + +/** +* Start the fan control on the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + /* If the fantable setup has failed we could have disabled + * PHM_PlatformCaps_MicrocodeFanControl even after + * this function was included in the table. + * Make sure that we still think controlling the fan is OK. + */ + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega12_fan_ctrl_start_smc_fan_control(hwmgr); + + return 0; +} + + +int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + int ret = 0; + + if (range == NULL) + return -EINVAL; + + ret = vega12_thermal_set_temperature_range(hwmgr, range); + if (ret) + return -EINVAL; + + vega12_thermal_enable_alert(hwmgr); + /* We should restrict performance levels to low before we halt the SMC. + * On the other hand we are still in boot state when we do this + * so it would be pointless. + * If this assumption changes we have to revisit this table. + */ + ret = vega12_thermal_setup_fan_table(hwmgr); + if (ret) + return -EINVAL; + + vega12_thermal_start_smc_fan_control(hwmgr); + + return 0; +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h new file mode 100644 index 000000000000..0d8ed039ab12 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.h @@ -0,0 +1,66 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef VEGA12_THERMAL_H +#define VEGA12_THERMAL_H + +#include "hwmgr.h" + +struct vega12_temperature { + uint16_t edge_temp; + uint16_t hot_spot_temp; + uint16_t hbm_temp; + uint16_t vr_soc_temp; + uint16_t vr_mem_temp; + uint16_t liquid1_temp; + uint16_t liquid2_temp; + uint16_t plx_temp; +}; + +#define VEGA12_THERMAL_HIGH_ALERT_MASK 0x1 +#define VEGA12_THERMAL_LOW_ALERT_MASK 0x2 + +#define VEGA12_THERMAL_MINIMUM_TEMP_READING -256 +#define VEGA12_THERMAL_MAXIMUM_TEMP_READING 255 + +#define VEGA12_THERMAL_MINIMUM_ALERT_TEMP 0 +#define VEGA12_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +extern int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info); +extern int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); +extern int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, + uint32_t *speed); +extern int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr); +extern int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c new file mode 100644 index 000000000000..2a28c9df15a0 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.c @@ -0,0 +1,122 @@ +/* + * Copyright 2018 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 "amdgpu.h" +#include "soc15.h" +#include "soc15_hw_ip.h" +#include "soc15_common.h" +#include "vega20_inc.h" +#include "vega20_ppsmc.h" +#include "vega20_baco.h" +#include "vega20_smumgr.h" + +#include "amdgpu_ras.h" + +static const struct soc15_baco_cmd_entry clean_baco_tbl[] = +{ + {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0}, + {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, +}; + +int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + uint32_t reg; + + *cap = false; + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) + return 0; + + if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) { + reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); + + if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) + *cap = true; + } + + return 0; +} + +int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + uint32_t reg; + + reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL); + + if (reg & BACO_CNTL__BACO_MODE_MASK) + /* gfx has already entered BACO state */ + *state = BACO_STATE_IN; + else + *state = BACO_STATE_OUT; + return 0; +} + +int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + enum BACO_STATE cur_state; + uint32_t data; + + vega20_baco_get_state(hwmgr, &cur_state); + + if (cur_state == state) + /* aisc already in the target state */ + return 0; + + if (state == BACO_STATE_IN) { + if (!ras || !ras->supported) { + data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); + data |= 0x80000000; + WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); + + if(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnterBaco, 0, NULL)) + return -EINVAL; + } else { + if(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnterBaco, 1, NULL)) + return -EINVAL; + } + + } else if (state == BACO_STATE_OUT) { + if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ExitBaco, NULL)) + return -EINVAL; + if (!soc15_baco_program_registers(hwmgr, clean_baco_tbl, + ARRAY_SIZE(clean_baco_tbl))) + return -EINVAL; + } + + return 0; +} + +int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + ret = vega20_set_pptable_driver_address(hwmgr); + if (ret) + return ret; + + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_BacoWorkAroundFlushVDCI, NULL); +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h new file mode 100644 index 000000000000..f06471e712dc --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_baco.h @@ -0,0 +1,33 @@ +/* + * Copyright 2018 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 __VEGA20_BACO_H__ +#define __VEGA20_BACO_H__ +#include "hwmgr.h" +#include "common_baco.h" + +extern int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); +extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); +extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); +extern int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c new file mode 100644 index 000000000000..c7216362b68d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c @@ -0,0 +1,4409 @@ +/* + * Copyright 2018 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 +#include +#include +#include + +#include "hwmgr.h" +#include "amd_powerplay.h" +#include "vega20_smumgr.h" +#include "hardwaremanager.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "cgs_common.h" +#include "vega20_powertune.h" +#include "vega20_inc.h" +#include "pppcielanes.h" +#include "vega20_hwmgr.h" +#include "vega20_processpptables.h" +#include "vega20_pptable.h" +#include "vega20_thermal.h" +#include "vega20_ppsmc.h" +#include "pp_debug.h" +#include "amd_pcie_helpers.h" +#include "ppinterrupt.h" +#include "pp_overdriver.h" +#include "pp_thermal.h" +#include "soc15_common.h" +#include "vega20_baco.h" +#include "smuio/smuio_9_0_offset.h" +#include "smuio/smuio_9_0_sh_mask.h" +#include "nbio/nbio_7_4_sh_mask.h" + +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 + +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + +static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + + data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT; + data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT; + data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT; + data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT; + data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT; + + data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT; + data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; + + /* + * Disable the following features for now: + * GFXCLK DS + * SOCLK DS + * LCLK DS + * DCEFCLK DS + * FCLK DS + * MP1CLK DS + * MP0CLK DS + */ + data->registry_data.disallowed_features = 0xE0041C00; + /* ECC feature should be disabled on old SMUs */ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version); + if (hwmgr->smu_version < 0x282100) + data->registry_data.disallowed_features |= FEATURE_ECC_MASK; + + if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK)) + data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK; + + if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK)) + data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK; + + if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK)) + data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK; + + if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK)) + data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK; + + if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK)) + data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK; + + if (!(hwmgr->feature_mask & PP_ULV_MASK)) + data->registry_data.disallowed_features |= FEATURE_ULV_MASK; + + if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)) + data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK; + + data->registry_data.od_state_in_dc_support = 0; + data->registry_data.thermal_support = 1; + data->registry_data.skip_baco_hardware = 0; + + data->registry_data.log_avfs_param = 0; + data->registry_data.sclk_throttle_low_notification = 1; + data->registry_data.force_dpm_high = 0; + data->registry_data.stable_pstate_sclk_dpm_percentage = 75; + + data->registry_data.didt_support = 0; + if (data->registry_data.didt_support) { + data->registry_data.didt_mode = 6; + data->registry_data.sq_ramping_support = 1; + data->registry_data.db_ramping_support = 0; + data->registry_data.td_ramping_support = 0; + data->registry_data.tcp_ramping_support = 0; + data->registry_data.dbr_ramping_support = 0; + data->registry_data.edc_didt_support = 1; + data->registry_data.gc_didt_support = 0; + data->registry_data.psm_didt_support = 0; + } + + data->registry_data.pcie_lane_override = 0xff; + data->registry_data.pcie_speed_override = 0xff; + data->registry_data.pcie_clock_override = 0xffffffff; + data->registry_data.regulator_hot_gpio_support = 1; + data->registry_data.ac_dc_switch_gpio_support = 0; + data->registry_data.quick_transition_support = 0; + data->registry_data.zrpm_start_temp = 0xffff; + data->registry_data.zrpm_stop_temp = 0xffff; + data->registry_data.od8_feature_enable = 1; + data->registry_data.disable_water_mark = 0; + data->registry_data.disable_pp_tuning = 0; + data->registry_data.disable_xlpp_tuning = 0; + data->registry_data.disable_workload_policy = 0; + data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F; + data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919; + data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A; + data->registry_data.force_workload_policy_mask = 0; + data->registry_data.disable_3d_fs_detection = 0; + data->registry_data.fps_support = 1; + data->registry_data.disable_auto_wattman = 1; + data->registry_data.auto_wattman_debug = 0; + data->registry_data.auto_wattman_sample_period = 100; + data->registry_data.fclk_gfxclk_ratio = 0; + data->registry_data.auto_wattman_threshold = 50; + data->registry_data.gfxoff_controlled_by_driver = 1; + data->gfxoff_allowed = false; + data->counter_gfxoff = 0; +} + +static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + + if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_BACO); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + + if (adev->pg_flags & AMD_PG_SUPPORT_UVD) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating); + + if (adev->pg_flags & AMD_PG_SUPPORT_VCE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + + if (data->registry_data.od8_feature_enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD8inACSupport); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ActivityReporting); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + if (data->registry_data.od_state_in_dc_support) { + if (data->registry_data.od8_feature_enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD8inDCSupport); + } + + if (data->registry_data.thermal_support && + data->registry_data.fuzzy_fan_control_support && + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPowerManagement); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMC); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalPolicyDelay); + + if (data->registry_data.force_dpm_high) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ExclusiveModeAlwaysHigh); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + if (data->registry_data.sclk_throttle_low_notification) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification); + + /* power tune caps */ + /* assume disabled */ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtEDCEnable); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GCEDC); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PSM); + + if (data->registry_data.didt_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtSupport); + if (data->registry_data.sq_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + if (data->registry_data.db_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + if (data->registry_data.td_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + if (data->registry_data.tcp_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + if (data->registry_data.dbr_ramping_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRRamping); + if (data->registry_data.edc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DiDtEDCEnable); + if (data->registry_data.gc_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_GCEDC); + if (data->registry_data.psm_didt_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PSM); + } + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + + if (data->registry_data.ac_dc_switch_gpio_support) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); + } + + if (data->registry_data.quick_transition_support) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + } + + if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_LowestUclkReservedForUlv); + if (data->lowest_uclk_reserved_for_ulv == 1) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_LowestUclkReservedForUlv); + } + + if (data->registry_data.custom_fan_support) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CustomFanControlSupport); + + return 0; +} + +static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + uint32_t top32, bottom32; + int i; + + data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = + FEATURE_DPM_PREFETCHER_BIT; + data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = + FEATURE_DPM_GFXCLK_BIT; + data->smu_features[GNLD_DPM_UCLK].smu_feature_id = + FEATURE_DPM_UCLK_BIT; + data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = + FEATURE_DPM_SOCCLK_BIT; + data->smu_features[GNLD_DPM_UVD].smu_feature_id = + FEATURE_DPM_UVD_BIT; + data->smu_features[GNLD_DPM_VCE].smu_feature_id = + FEATURE_DPM_VCE_BIT; + data->smu_features[GNLD_ULV].smu_feature_id = + FEATURE_ULV_BIT; + data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = + FEATURE_DPM_MP0CLK_BIT; + data->smu_features[GNLD_DPM_LINK].smu_feature_id = + FEATURE_DPM_LINK_BIT; + data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = + FEATURE_DPM_DCEFCLK_BIT; + data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = + FEATURE_DS_GFXCLK_BIT; + data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = + FEATURE_DS_SOCCLK_BIT; + data->smu_features[GNLD_DS_LCLK].smu_feature_id = + FEATURE_DS_LCLK_BIT; + data->smu_features[GNLD_PPT].smu_feature_id = + FEATURE_PPT_BIT; + data->smu_features[GNLD_TDC].smu_feature_id = + FEATURE_TDC_BIT; + data->smu_features[GNLD_THERMAL].smu_feature_id = + FEATURE_THERMAL_BIT; + data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = + FEATURE_GFX_PER_CU_CG_BIT; + data->smu_features[GNLD_RM].smu_feature_id = + FEATURE_RM_BIT; + data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = + FEATURE_DS_DCEFCLK_BIT; + data->smu_features[GNLD_ACDC].smu_feature_id = + FEATURE_ACDC_BIT; + data->smu_features[GNLD_VR0HOT].smu_feature_id = + FEATURE_VR0HOT_BIT; + data->smu_features[GNLD_VR1HOT].smu_feature_id = + FEATURE_VR1HOT_BIT; + data->smu_features[GNLD_FW_CTF].smu_feature_id = + FEATURE_FW_CTF_BIT; + data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = + FEATURE_LED_DISPLAY_BIT; + data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = + FEATURE_FAN_CONTROL_BIT; + data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; + data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT; + data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT; + data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT; + data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT; + data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT; + data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT; + data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT; + data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + data->smu_features[i].smu_feature_bitmap = + (uint64_t)(1ULL << data->smu_features[i].smu_feature_id); + data->smu_features[i].allowed = + ((data->registry_data.disallowed_features >> i) & 1) ? + false : true; + } + + /* Get the SN to turn into a Unique ID */ + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); + + adev->unique_id = ((uint64_t)bottom32 << 32) | top32; +} + +static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->backend); + hwmgr->backend = NULL; + + return 0; +} + +static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data; + struct amdgpu_device *adev = hwmgr->adev; + + data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + + hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; + hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + + vega20_set_default_registry_data(hwmgr); + + data->disable_dpm_mask = 0xff; + + /* need to set voltage control types before EVV patching */ + data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE; + data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE; + data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE; + + data->water_marks_bitmap = 0; + data->avfs_exist = false; + + vega20_set_features_platform_caps(hwmgr); + + vega20_init_dpm_defaults(hwmgr); + + /* Parse pptable data read from VBIOS */ + vega20_set_private_data_based_on_pptable(hwmgr); + + data->is_tlu_enabled = false; + + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + VEGA20_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ + /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ + hwmgr->platform_descriptor.clockStep.engineClock = 500; + hwmgr->platform_descriptor.clockStep.memoryClock = 500; + + data->total_active_cus = adev->gfx.cu_info.number; + data->is_custom_profile_set = false; + + return 0; +} + +static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + + data->low_sclk_interrupt_threshold = 0; + + return 0; +} + +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 && + (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || + (adev->in_runpm && amdgpu_asic_supports_baco(adev)); + + ret = vega20_init_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "Failed to init sclk threshold!", + return ret); + + if (use_baco) { + ret = vega20_baco_apply_vdci_flush_workaround(hwmgr); + if (ret) + pr_err("Failed to apply vega20 baco workaround!\n"); + } + + return ret; +} + +/* + * @fn vega20_init_dpm_state + * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. + * + * @param dpm_state - the address of the DPM Table to initiailize. + * @return None. + */ +static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state) +{ + dpm_state->soft_min_level = 0x0; + dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_state->hard_min_level = 0x0; + dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT; +} + +static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr, + PPCLK_e clk_id, uint32_t *num_of_levels) +{ + int ret = 0; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmFreqByIndex, + (clk_id << 16 | 0xFF), + num_of_levels); + PP_ASSERT_WITH_CODE(!ret, + "[GetNumOfDpmLevel] failed to get dpm levels!", + return ret); + + return ret; +} + +static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr, + PPCLK_e clk_id, uint32_t index, uint32_t *clk) +{ + int ret = 0; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmFreqByIndex, + (clk_id << 16 | index), + clk); + PP_ASSERT_WITH_CODE(!ret, + "[GetDpmFreqByIndex] failed to get dpm freq by index!", + return ret); + + return ret; +} + +static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr, + struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id) +{ + int ret = 0; + uint32_t i, num_of_levels, clk; + + ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels); + PP_ASSERT_WITH_CODE(!ret, + "[SetupSingleDpmTable] failed to get clk levels!", + return ret); + + dpm_table->count = num_of_levels; + + for (i = 0; i < num_of_levels; i++) { + ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk); + PP_ASSERT_WITH_CODE(!ret, + "[SetupSingleDpmTable] failed to get clk of specific level!", + return ret); + dpm_table->dpm_levels[i].value = clk; + dpm_table->dpm_levels[i].enabled = true; + } + + return ret; +} + +static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table; + int ret = 0; + + dpm_table = &(data->dpm_table.gfx_table); + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100; + } + + return ret; +} + +static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table; + int ret = 0; + + dpm_table = &(data->dpm_table.mem_table); + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get memclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100; + } + + return ret; +} + +/* + * This function is to initialize all DPM state tables + * for SMU based on the dependency table. + * Dynamic state patching function will then trim these + * state tables to the allowed range based + * on the power policy or external client requests, + * such as UVD request, etc. + */ +static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table; + int ret = 0; + + memset(&data->dpm_table, 0, sizeof(data->dpm_table)); + + /* socclk */ + dpm_table = &(data->dpm_table.soc_table); + if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get socclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* gfxclk */ + dpm_table = &(data->dpm_table.gfx_table); + ret = vega20_setup_gfxclk_dpm_table(hwmgr); + if (ret) + return ret; + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* memclk */ + dpm_table = &(data->dpm_table.mem_table); + ret = vega20_setup_memclk_dpm_table(hwmgr); + if (ret) + return ret; + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* eclk */ + dpm_table = &(data->dpm_table.eclk_table); + if (data->smu_features[GNLD_DPM_VCE].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get eclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* vclk */ + dpm_table = &(data->dpm_table.vclk_table); + if (data->smu_features[GNLD_DPM_UVD].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get vclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* dclk */ + dpm_table = &(data->dpm_table.dclk_table); + if (data->smu_features[GNLD_DPM_UVD].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* dcefclk */ + dpm_table = &(data->dpm_table.dcef_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* pixclk */ + dpm_table = &(data->dpm_table.pixel_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get pixclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* dispclk */ + dpm_table = &(data->dpm_table.display_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get dispclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* phyclk */ + dpm_table = &(data->dpm_table.phy_table); + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get phyclk dpm levels!", + return ret); + } else + dpm_table->count = 0; + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* fclk */ + dpm_table = &(data->dpm_table.fclk_table); + if (data->smu_features[GNLD_DPM_FCLK].enabled) { + ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK); + PP_ASSERT_WITH_CODE(!ret, + "[SetupDefaultDpmTable] failed to get fclk dpm levels!", + return ret); + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100; + } + vega20_init_dpm_state(&(dpm_table->dpm_state)); + + /* save a copy of the default DPM table */ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), + sizeof(struct vega20_dpm_table)); + + return 0; +} + +/** +* Initializes the SMC table and uploads it +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data (PowerState) +* @return always 0 +*/ +static int vega20_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct pp_atomfwctrl_bios_boot_up_values boot_up_values; + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + + result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); + PP_ASSERT_WITH_CODE(!result, + "[InitSMCTable] Failed to get vbios bootup values!", + return result); + + data->vbios_boot_state.vddc = boot_up_values.usVddc; + data->vbios_boot_state.vddci = boot_up_values.usVddci; + data->vbios_boot_state.mvddc = boot_up_values.usMvddc; + data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; + data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; + data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; + data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; + data->vbios_boot_state.eclock = boot_up_values.ulEClk; + data->vbios_boot_state.vclock = boot_up_values.ulVClk; + data->vbios_boot_state.dclock = boot_up_values.ulDClk; + data->vbios_boot_state.fclock = boot_up_values.ulFClk; + data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinDeepSleepDcefclk, + (uint32_t)(data->vbios_boot_state.dcef_clock / 100), + NULL); + + memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t)); + + result = smum_smc_table_manager(hwmgr, + (uint8_t *)pp_table, TABLE_PPTABLE, false); + PP_ASSERT_WITH_CODE(!result, + "[InitSMCTable] Failed to upload PPtable!", + return result); + + return 0; +} + +/* + * Override PCIe link speed and link width for DPM Level 1. PPTable entries + * reflect the ASIC capabilities and not the system capabilities. For e.g. + * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch + * to DPM1, it fails as system doesn't support Gen4. + */ +static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg; + int ret; + + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) + pcie_gen = 3; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + pcie_gen = 2; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) + pcie_gen = 1; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) + pcie_gen = 0; + + if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) + pcie_width = 6; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) + pcie_width = 5; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) + pcie_width = 4; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) + pcie_width = 3; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) + pcie_width = 2; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) + pcie_width = 1; + + /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 + * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 + * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 + */ + smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width; + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_OverridePcieParameters, smu_pcie_arg, + NULL); + PP_ASSERT_WITH_CODE(!ret, + "[OverridePcieParameters] Attempt to override pcie params failed!", + return ret); + + data->pcie_parameters_override = true; + data->pcie_gen_level1 = pcie_gen; + data->pcie_width_level1 = pcie_width; + + return 0; +} + +static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t allowed_features_low = 0, allowed_features_high = 0; + int i; + int ret = 0; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) + if (data->smu_features[i].allowed) + data->smu_features[i].smu_feature_id > 31 ? + (allowed_features_high |= + ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) + & 0xFFFFFFFF)) : + (allowed_features_low |= + ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) + & 0xFFFFFFFF)); + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, NULL); + PP_ASSERT_WITH_CODE(!ret, + "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!", + return ret); + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, NULL); + PP_ASSERT_WITH_CODE(!ret, + "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!", + return ret); + + return 0; +} + +static int vega20_run_btc(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc, NULL); +} + +static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc, NULL); +} + +static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint64_t features_enabled; + int i; + bool enabled; + int ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_EnableAllSmuFeatures, + NULL)) == 0, + "[EnableAllSMUFeatures] Failed to enable all smu features!", + return ret); + + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", + return ret); + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? + true : false; + data->smu_features[i].enabled = enabled; + data->smu_features[i].supported = enabled; + +#if 0 + if (data->smu_features[i].allowed && !enabled) + pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i); + else if (!data->smu_features[i].allowed && enabled) + pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i); +#endif + } + + return 0; +} + +static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_DPM_UCLK].enabled) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetUclkFastSwitch, + 1, + NULL); + + return 0; +} + +static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFclkGfxClkRatio, + data->registry_data.fclk_gfxclk_ratio, + NULL); +} + +static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + int i, ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_DisableAllSmuFeatures, + NULL)) == 0, + "[DisableAllSMUFeatures] Failed to disable all smu features!", + return ret); + + for (i = 0; i < GNLD_FEATURES_MAX; i++) + data->smu_features[i].enabled = 0; + + return 0; +} + +static int vega20_od8_set_feature_capabilities( + struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + struct vega20_od8_settings *od_settings = &(data->od8_settings); + + od_settings->overdrive8_capabilities = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] && + pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && + pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= + pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) + od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS; + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] && + (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= + pp_table->MinVoltageGfx / VOLTAGE_SCALE) && + (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= + pp_table->MaxVoltageGfx / VOLTAGE_SCALE) && + (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >= + pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1])) + od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE; + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] = + data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value; + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && + pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && + pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >= + pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX])) + od_settings->overdrive8_capabilities |= OD8_UCLK_MAX; + } + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] && + pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && + pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 && + pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && + pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100) + od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT; + + if (data->smu_features[GNLD_FAN_CONTROL].enabled) { + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] && + pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && + pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= + pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) + od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK; + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] && + (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >= + (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) && + pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= + pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) + od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN; + } + + if (data->smu_features[GNLD_THERMAL].enabled) { + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] && + pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && + pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= + pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) + od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN; + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] && + pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && + pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && + (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= + pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) + od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM; + } + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE]) + od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE; + + if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] && + pp_table->FanZeroRpmEnable) + od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL; + + if (!od_settings->overdrive8_capabilities) + hwmgr->od_enabled = false; + + return 0; +} + +static int vega20_od8_set_feature_id( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_settings *od_settings = &(data->od8_settings); + + if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = + OD8_GFXCLK_LIMITS; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = + OD8_GFXCLK_LIMITS; + } else { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = + 0; + } + + if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = + OD8_GFXCLK_CURVE; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = + OD8_GFXCLK_CURVE; + } else { + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = + 0; + od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = + 0; + } + + if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX) + od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX; + else + od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0; + + if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT) + od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT; + else + od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0; + + if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) + od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = + OD8_ACOUSTIC_LIMIT_SCLK; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) + od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = + OD8_FAN_SPEED_MIN; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) + od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = + OD8_TEMPERATURE_FAN; + else + od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = + 0; + + if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) + od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = + OD8_TEMPERATURE_SYSTEM; + else + od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = + 0; + + return 0; +} + +static int vega20_od8_get_gfx_clock_base_voltage( + struct pp_hwmgr *hwmgr, + uint32_t *voltage, + uint32_t freq) +{ + int ret = 0; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetAVFSVoltageByDpm, + ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq), + voltage); + PP_ASSERT_WITH_CODE(!ret, + "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!", + return ret); + + *voltage = *voltage / VOLTAGE_SCALE; + + return 0; +} + +static int vega20_od8_initialize_default_settings( + struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_settings *od8_settings = &(data->od8_settings); + OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table); + int i, ret = 0; + + /* Set Feature Capabilities */ + vega20_od8_set_feature_capabilities(hwmgr); + + /* Map FeatureID to individual settings */ + vega20_od8_set_feature_id(hwmgr); + + /* Set default values */ + ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true); + PP_ASSERT_WITH_CODE(!ret, + "Failed to export over drive table!", + return ret); + + if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = + od_table->GfxclkFmin; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = + od_table->GfxclkFmax; + } else { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = + 0; + } + + if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { + od_table->GfxclkFreq1 = od_table->GfxclkFmin; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = + od_table->GfxclkFreq1; + + od_table->GfxclkFreq3 = od_table->GfxclkFmax; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = + od_table->GfxclkFreq3; + + od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = + od_table->GfxclkFreq2; + + PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, + &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value), + od_table->GfxclkFreq1), + "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0); + od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value + * VOLTAGE_SCALE; + + PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, + &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value), + od_table->GfxclkFreq2), + "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0); + od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value + * VOLTAGE_SCALE; + + PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, + &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value), + od_table->GfxclkFreq3), + "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0); + od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value + * VOLTAGE_SCALE; + } else { + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = + 0; + od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = + 0; + } + + if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX) + od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = + od_table->UclkFmax; + else + od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT) + od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = + od_table->OverDrivePct; + else + od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) + od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = + od_table->FanMaximumRpm; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) + od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = + od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) + od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = + od_table->FanTargetTemperature; + else + od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = + 0; + + if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) + od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = + od_table->MaxOpTemp; + else + od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = + 0; + + for (i = 0; i < OD8_SETTING_COUNT; i++) { + if (od8_settings->od8_settings_array[i].feature_id) { + od8_settings->od8_settings_array[i].min_value = + pptable_information->od_settings_min[i]; + od8_settings->od8_settings_array[i].max_value = + pptable_information->od_settings_max[i]; + od8_settings->od8_settings_array[i].current_value = + od8_settings->od8_settings_array[i].default_value; + } else { + od8_settings->od8_settings_array[i].min_value = + 0; + od8_settings->od8_settings_array[i].max_value = + 0; + od8_settings->od8_settings_array[i].current_value = + 0; + } + } + + ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false); + PP_ASSERT_WITH_CODE(!ret, + "Failed to import over drive table!", + return ret); + + return 0; +} + +static int vega20_od8_set_settings( + struct pp_hwmgr *hwmgr, + uint32_t index, + uint32_t value) +{ + OverDriveTable_t od_table; + int ret = 0; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_single_setting *od8_settings = + data->od8_settings.od8_settings_array; + + ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true); + PP_ASSERT_WITH_CODE(!ret, + "Failed to export over drive table!", + return ret); + + switch(index) { + case OD8_SETTING_GFXCLK_FMIN: + od_table.GfxclkFmin = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_FMAX: + if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value || + value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) + return -EINVAL; + + od_table.GfxclkFmax = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_FREQ1: + od_table.GfxclkFreq1 = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_VOLTAGE1: + od_table.GfxclkVolt1 = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_FREQ2: + od_table.GfxclkFreq2 = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_VOLTAGE2: + od_table.GfxclkVolt2 = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_FREQ3: + od_table.GfxclkFreq3 = (uint16_t)value; + break; + case OD8_SETTING_GFXCLK_VOLTAGE3: + od_table.GfxclkVolt3 = (uint16_t)value; + break; + case OD8_SETTING_UCLK_FMAX: + if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || + value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) + return -EINVAL; + od_table.UclkFmax = (uint16_t)value; + break; + case OD8_SETTING_POWER_PERCENTAGE: + od_table.OverDrivePct = (int16_t)value; + break; + case OD8_SETTING_FAN_ACOUSTIC_LIMIT: + od_table.FanMaximumRpm = (uint16_t)value; + break; + case OD8_SETTING_FAN_MIN_SPEED: + od_table.FanMinimumPwm = (uint16_t)value; + break; + case OD8_SETTING_FAN_TARGET_TEMP: + od_table.FanTargetTemperature = (uint16_t)value; + break; + case OD8_SETTING_OPERATING_TEMP_MAX: + od_table.MaxOpTemp = (uint16_t)value; + break; + } + + ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false); + PP_ASSERT_WITH_CODE(!ret, + "Failed to import over drive table!", + return ret); + + return 0; +} + +static int vega20_get_sclk_od( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + struct vega20_single_dpm_table *sclk_table = + &(data->dpm_table.gfx_table); + struct vega20_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.gfx_table); + int value = sclk_table->dpm_levels[sclk_table->count - 1].value; + int golden_value = golden_sclk_table->dpm_levels + [golden_sclk_table->count - 1].value; + + /* od percentage */ + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega20_set_sclk_od( + struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct vega20_hwmgr *data = hwmgr->backend; + struct vega20_single_dpm_table *golden_sclk_table = + &(data->golden_dpm_table.gfx_table); + uint32_t od_sclk; + int ret = 0; + + od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value; + od_sclk /= 100; + od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; + + ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk); + PP_ASSERT_WITH_CODE(!ret, + "[SetSclkOD] failed to set od gfxclk!", + return ret); + + /* retrieve updated gfxclk table */ + ret = vega20_setup_gfxclk_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "[SetSclkOD] failed to refresh gfxclk table!", + return ret); + + return 0; +} + +static int vega20_get_mclk_od( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + struct vega20_single_dpm_table *mclk_table = + &(data->dpm_table.mem_table); + struct vega20_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mem_table); + int value = mclk_table->dpm_levels[mclk_table->count - 1].value; + int golden_value = golden_mclk_table->dpm_levels + [golden_mclk_table->count - 1].value; + + /* od percentage */ + value -= golden_value; + value = DIV_ROUND_UP(value * 100, golden_value); + + return value; +} + +static int vega20_set_mclk_od( + struct pp_hwmgr *hwmgr, uint32_t value) +{ + struct vega20_hwmgr *data = hwmgr->backend; + struct vega20_single_dpm_table *golden_mclk_table = + &(data->golden_dpm_table.mem_table); + uint32_t od_mclk; + int ret = 0; + + od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value; + od_mclk /= 100; + od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; + + ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk); + PP_ASSERT_WITH_CODE(!ret, + "[SetMclkOD] failed to set od memclk!", + return ret); + + /* retrieve updated memclk table */ + ret = vega20_setup_memclk_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "[SetMclkOD] failed to refresh memclk table!", + return ret); + + return 0; +} + +static int vega20_populate_umdpstate_clocks( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table); + struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table); + + hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value; + hwmgr->pstate_mclk = mem_table->dpm_levels[0].value; + + if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && + mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { + hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; + hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; + } + + hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100; + hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100; + + return 0; +} + +static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr, + PP_Clock *clock, PPCLK_e clock_select) +{ + int ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDcModeMaxDpmFreq, + (clock_select << 16), + clock)) == 0, + "[GetMaxSustainableClock] Failed to get max DC clock from SMC!", + return ret); + + /* if DC limit is zero, return AC limit */ + if (*clock == 0) { + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetMaxDpmFreq, + (clock_select << 16), + clock)) == 0, + "[GetMaxSustainableClock] failed to get max AC clock from SMC!", + return ret); + } + + return 0; +} + +static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_max_sustainable_clocks *max_sustainable_clocks = + &(data->max_sustainable_clocks); + int ret = 0; + + max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100; + max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100; + max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100; + max_sustainable_clocks->display_clock = 0xFFFFFFFF; + max_sustainable_clocks->phy_clock = 0xFFFFFFFF; + max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; + + if (data->smu_features[GNLD_DPM_UCLK].enabled) + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->uclock), + PPCLK_UCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max UCLK from SMC!", + return ret); + + if (data->smu_features[GNLD_DPM_SOCCLK].enabled) + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->soc_clock), + PPCLK_SOCCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!", + return ret); + + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->dcef_clock), + PPCLK_DCEFCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!", + return ret); + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->display_clock), + PPCLK_DISPCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!", + return ret); + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->phy_clock), + PPCLK_PHYCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!", + return ret); + PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, + &(max_sustainable_clocks->pixel_clock), + PPCLK_PIXCLK)) == 0, + "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!", + return ret); + } + + if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) + max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; + + return 0; +} + +static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) +{ + int result; + + result = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_SetMGpuFanBoostLimitRpm, + NULL); + PP_ASSERT_WITH_CODE(!result, + "[EnableMgpuFan] Failed to enable mgpu fan boost!", + return result); + + return 0; +} + +static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = true; + data->vce_power_gated = true; +} + +static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, 0, NULL); + + result = vega20_set_allowed_featuresmask(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to set allowed featuresmask!\n", + return result); + + result = vega20_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to initialize SMC table!", + return result); + + result = vega20_run_btc(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to run btc!", + return result); + + result = vega20_run_btc_afll(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to run btc afll!", + return result); + + result = vega20_enable_all_smu_features(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to enable all smu features!", + return result); + + result = vega20_override_pcie_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to override pcie parameters!", + return result); + + result = vega20_notify_smc_display_change(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to notify smc display change!", + return result); + + result = vega20_send_clock_ratio(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to send clock ratio!", + return result); + + /* Initialize UVD/VCE powergating state */ + vega20_init_powergate_state(hwmgr); + + result = vega20_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to setup default DPM tables!", + return result); + + result = vega20_init_max_sustainable_clocks(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to get maximum sustainable clocks!", + return result); + + result = vega20_power_control_set_level(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to power control set level!", + return result); + + result = vega20_od8_initialize_default_settings(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to initialize odn settings!", + return result); + + result = vega20_populate_umdpstate_clocks(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "[EnableDPMTasks] Failed to populate umdpstate clocks!", + return result); + + result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit, + POWER_SOURCE_AC << 16, &hwmgr->default_power_limit); + PP_ASSERT_WITH_CODE(!result, + "[GetPptLimit] get default PPT limit failed!", + return result); + hwmgr->power_limit = + hwmgr->default_power_limit; + + return 0; +} + +static uint32_t vega20_find_lowest_dpm_level( + struct vega20_single_dpm_table *table) +{ + uint32_t i; + + for (i = 0; i < table->count; i++) { + if (table->dpm_levels[i].enabled) + break; + } + if (i >= table->count) { + i = 0; + table->dpm_levels[i].enabled = true; + } + + return i; +} + +static uint32_t vega20_find_highest_dpm_level( + struct vega20_single_dpm_table *table) +{ + int i = 0; + + PP_ASSERT_WITH_CODE(table != NULL, + "[FindHighestDPMLevel] DPM Table does not exist!", + return 0); + PP_ASSERT_WITH_CODE(table->count > 0, + "[FindHighestDPMLevel] DPM Table has no entry!", + return 0); + PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, + "[FindHighestDPMLevel] DPM Table has too many entries!", + return MAX_REGULAR_DPM_NUMBER - 1); + + for (i = table->count - 1; i >= 0; i--) { + if (table->dpm_levels[i].enabled) + break; + } + if (i < 0) { + i = 0; + table->dpm_levels[i].enabled = true; + } + + return i; +} + +static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t min_freq; + int ret = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled && + (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { + min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min gfxclk !", + return ret); + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled && + (feature_mask & FEATURE_DPM_UCLK_MASK)) { + min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_UCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min memclk !", + return ret); + } + + if (data->smu_features[GNLD_DPM_UVD].enabled && + (feature_mask & FEATURE_DPM_UVD_MASK)) { + min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_VCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min vclk!", + return ret); + + min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_DCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min dclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_VCE].enabled && + (feature_mask & FEATURE_DPM_VCE_MASK)) { + min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_ECLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min eclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_SOCCLK].enabled && + (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { + min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min socclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_FCLK].enabled && + (feature_mask & FEATURE_DPM_FCLK_MASK)) { + min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_FCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set soft min fclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled && + (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { + min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetHardMinByFreq, + (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), + NULL)), + "Failed to set hard min dcefclk!", + return ret); + } + + return ret; +} + +static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t max_freq; + int ret = 0; + + if (data->smu_features[GNLD_DPM_GFXCLK].enabled && + (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { + max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max gfxclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled && + (feature_mask & FEATURE_DPM_UCLK_MASK)) { + max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_UCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max memclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_UVD].enabled && + (feature_mask & FEATURE_DPM_UVD_MASK)) { + max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_VCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max vclk!", + return ret); + + max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_DCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max dclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_VCE].enabled && + (feature_mask & FEATURE_DPM_VCE_MASK)) { + max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_ECLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max eclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_SOCCLK].enabled && + (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { + max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max socclk!", + return ret); + } + + if (data->smu_features[GNLD_DPM_FCLK].enabled && + (feature_mask & FEATURE_DPM_FCLK_MASK)) { + max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level; + + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetSoftMaxByFreq, + (PPCLK_FCLK << 16) | (max_freq & 0xffff), + NULL)), + "Failed to set soft max fclk!", + return ret); + } + + return ret; +} + +static int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->smu_features[GNLD_DPM_VCE].supported) { + if (data->smu_features[GNLD_DPM_VCE].enabled == enable) { + if (enable) + PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n"); + else + PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n"); + } + + ret = vega20_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to Enable/Disable DPM VCE Failed!", + return ret); + data->smu_features[GNLD_DPM_VCE].enabled = enable; + } + + return 0; +} + +static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr, + uint32_t *clock, + PPCLK_e clock_select, + bool max) +{ + int ret; + *clock = 0; + + if (max) { + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16), + clock)) == 0, + "[GetClockRanges] Failed to get max clock from SMC!", + return ret); + } else { + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetMinDpmFreq, + (clock_select << 16), + clock)) == 0, + "[GetClockRanges] Failed to get min clock from SMC!", + return ret); + } + + return 0; +} + +static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t gfx_clk; + int ret = 0; + + PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled, + "[GetSclks]: gfxclk dpm not enabled!\n", + return -EPERM); + + if (low) { + ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false); + PP_ASSERT_WITH_CODE(!ret, + "[GetSclks]: fail to get min PPCLK_GFXCLK\n", + return ret); + } else { + ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true); + PP_ASSERT_WITH_CODE(!ret, + "[GetSclks]: fail to get max PPCLK_GFXCLK\n", + return ret); + } + + return (gfx_clk * 100); +} + +static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t mem_clk; + int ret = 0; + + PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled, + "[MemMclks]: memclk dpm not enabled!\n", + return -EPERM); + + if (low) { + ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false); + PP_ASSERT_WITH_CODE(!ret, + "[GetMclks]: fail to get min PPCLK_UCLK\n", + return ret); + } else { + ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true); + PP_ASSERT_WITH_CODE(!ret, + "[GetMclks]: fail to get max PPCLK_UCLK\n", + return ret); + } + + return (mem_clk * 100); +} + +static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, + SmuMetrics_t *metrics_table, + bool bypass_cache) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (bypass_cache || + !data->metrics_time || + time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)(&data->metrics_table), + TABLE_SMU_METRICS, + true); + if (ret) { + pr_info("Failed to export SMU metrics table!\n"); + return ret; + } + data->metrics_time = jiffies; + } + + if (metrics_table) + memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); + + return ret; +} + +static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, + uint32_t *query) +{ + int ret = 0; + SmuMetrics_t metrics_table; + + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + /* For the 40.46 release, they changed the value name */ + if (hwmgr->smu_version == 0x282e00) + *query = metrics_table.AverageSocketPower << 8; + else + *query = metrics_table.CurrSocketPower << 8; + + return ret; +} + +static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, + PPCLK_e clk_id, uint32_t *clk_freq) +{ + int ret = 0; + + *clk_freq = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetDpmClockFreq, (clk_id << 16), + clk_freq)) == 0, + "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", + return ret); + + *clk_freq = *clk_freq * 100; + + return 0; +} + +static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, + int idx, + uint32_t *activity_percent) +{ + int ret = 0; + SmuMetrics_t metrics_table; + + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + switch (idx) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + *activity_percent = metrics_table.AverageGfxActivity; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + *activity_percent = metrics_table.AverageUclkActivity; + break; + default: + pr_err("Invalid index for retrieving clock activity\n"); + return -EINVAL; + } + + return ret; +} + +static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, + void *value, int *size) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct amdgpu_device *adev = hwmgr->adev; + SmuMetrics_t metrics_table; + uint32_t val_vid; + int ret = 0; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = vega20_get_current_clk_freq(hwmgr, + PPCLK_UCLK, + (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_LOAD: + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); + if (!ret) + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr); + *size = 4; + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *((uint32_t *)value) = metrics_table.TemperatureEdge * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); + if (ret) + return ret; + + *((uint32_t *)value) = metrics_table.TemperatureHBM * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + *size = 4; + break; + case AMDGPU_PP_SENSOR_UVD_POWER: + *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VCE_POWER: + *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + *size = 16; + ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value); + break; + case AMDGPU_PP_SENSOR_VDDGFX: + val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & + SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> + SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; + *((uint32_t *)value) = + (uint32_t)convert_to_vddc((uint8_t)val_vid); + break; + case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: + ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value); + if (!ret) + *size = 8; + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +static int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, + struct pp_display_clock_request *clock_req) +{ + int result = 0; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + enum amd_pp_clock_type clk_type = clock_req->clock_type; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + PPCLK_e clk_select = 0; + uint32_t clk_request = 0; + + if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { + switch (clk_type) { + case amd_pp_dcef_clock: + clk_select = PPCLK_DCEFCLK; + break; + case amd_pp_disp_clock: + clk_select = PPCLK_DISPCLK; + break; + case amd_pp_pixel_clock: + clk_select = PPCLK_PIXCLK; + break; + case amd_pp_phy_clock: + clk_select = PPCLK_PHYCLK; + break; + default: + pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); + result = -EINVAL; + break; + } + + if (!result) { + clk_request = (clk_select << 16) | clk_freq; + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinByFreq, + clk_request, + NULL); + } + } + + return result; +} + +static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, + PHM_PerformanceLevelDesignation designation, uint32_t index, + PHM_PerformanceLevel *level) +{ + return 0; +} + +static int vega20_notify_smc_display_config_after_ps_adjustment( + struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = + &data->dpm_table.mem_table; + struct PP_Clocks min_clocks = {0}; + struct pp_display_clock_request clock_req; + int ret = 0; + + min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; + min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; + min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; + + if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { + clock_req.clock_type = amd_pp_dcef_clock; + clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; + if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { + if (data->smu_features[GNLD_DS_DCEFCLK].supported) + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( + hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, + min_clocks.dcefClockInSR / 100, + NULL)) == 0, + "Attempt to set divider for DCEFCLK Failed!", + return ret); + } else { + pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); + } + } + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinByFreq, + (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, + NULL)), + "[SetHardMinFreq] Set hard min uclk failed!", + return ret); + } + + return 0; +} + +static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t soft_level; + int ret = 0; + + soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_level].value; + + soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_level].value; + + soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); + + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->dpm_table.soc_table.dpm_levels[soft_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to highest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + return 0; +} + +static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t soft_level; + int ret = 0; + + soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_level].value; + + soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_level].value; + + soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); + + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->dpm_table.soc_table.dpm_levels[soft_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to highest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + return 0; + +} + +static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t soft_min_level, soft_max_level; + int ret = 0; + + /* gfxclk soft min/max settings */ + soft_min_level = + vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); + soft_max_level = + vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; + + /* uclk soft min/max settings */ + soft_min_level = + vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); + soft_max_level = + vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_levels[soft_min_level].value; + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_max_level].value; + + /* socclk soft min/max settings */ + soft_min_level = + vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); + soft_max_level = + vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); + + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->dpm_table.soc_table.dpm_levels[soft_min_level].value; + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->dpm_table.soc_table.dpm_levels[soft_max_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload DPM Bootup Levels!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | + FEATURE_DPM_UCLK_MASK | + FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload DPM Max Levels!", + return ret); + + return 0; +} + +static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, + uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); + struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); + struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); + + *sclk_mask = 0; + *mclk_mask = 0; + *soc_mask = 0; + + if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && + mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL && + soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { + *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; + *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; + *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; + } + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + *sclk_mask = gfx_dpm_table->count - 1; + *mclk_mask = mem_dpm_table->count - 1; + *soc_mask = soc_dpm_table->count - 1; + } + + return 0; +} + +static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, uint32_t mask) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + uint32_t soft_min_level, soft_max_level, hard_min_level; + int ret = 0; + + switch (type) { + case PP_SCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if (soft_max_level >= data->dpm_table.gfx_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.gfx_table.count - 1); + return -EINVAL; + } + + data->dpm_table.gfx_table.dpm_state.soft_min_level = + data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; + data->dpm_table.gfx_table.dpm_state.soft_max_level = + data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + break; + + case PP_MCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if (soft_max_level >= data->dpm_table.mem_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.mem_table.count - 1); + return -EINVAL; + } + + data->dpm_table.mem_table.dpm_state.soft_min_level = + data->dpm_table.mem_table.dpm_levels[soft_min_level].value; + data->dpm_table.mem_table.dpm_state.soft_max_level = + data->dpm_table.mem_table.dpm_levels[soft_max_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + break; + + case PP_SOCCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if (soft_max_level >= data->dpm_table.soc_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.soc_table.count - 1); + return -EINVAL; + } + + data->dpm_table.soc_table.dpm_state.soft_min_level = + data->dpm_table.soc_table.dpm_levels[soft_min_level].value; + data->dpm_table.soc_table.dpm_state.soft_max_level = + data->dpm_table.soc_table.dpm_levels[soft_max_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + break; + + case PP_FCLK: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if (soft_max_level >= data->dpm_table.fclk_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + soft_max_level, + data->dpm_table.fclk_table.count - 1); + return -EINVAL; + } + + data->dpm_table.fclk_table.dpm_state.soft_min_level = + data->dpm_table.fclk_table.dpm_levels[soft_min_level].value; + data->dpm_table.fclk_table.dpm_state.soft_max_level = + data->dpm_table.fclk_table.dpm_levels[soft_max_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload dpm max level to highest!", + return ret); + + break; + + case PP_DCEFCLK: + hard_min_level = mask ? (ffs(mask) - 1) : 0; + + if (hard_min_level >= data->dpm_table.dcef_table.count) { + pr_err("Clock level specified %d is over max allowed %d\n", + hard_min_level, + data->dpm_table.dcef_table.count - 1); + return -EINVAL; + } + + data->dpm_table.dcef_table.dpm_state.hard_min_level = + data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; + + ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK); + PP_ASSERT_WITH_CODE(!ret, + "Failed to upload boot level to lowest!", + return ret); + + //TODO: Setting DCEFCLK max dpm level is not supported + + break; + + case PP_PCIE: + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + if (soft_min_level >= NUM_LINK_LEVELS || + soft_max_level >= NUM_LINK_LEVELS) + return -EINVAL; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level, + NULL); + PP_ASSERT_WITH_CODE(!ret, + "Failed to set min link dpm level!", + return ret); + + break; + + default: + break; + } + + return 0; +} + +static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask, mclk_mask, soc_mask; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = vega20_force_dpm_highest(hwmgr); + break; + + case AMD_DPM_FORCED_LEVEL_LOW: + ret = vega20_force_dpm_lowest(hwmgr); + break; + + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = vega20_unforce_dpm_levels(hwmgr); + break; + + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); + if (ret) + return ret; + vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); + vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); + vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask); + break; + + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + + return ret; +} + +static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) + return AMD_FAN_CTRL_MANUAL; + else + return AMD_FAN_CTRL_AUTO; +} + +static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + switch (mode) { + case AMD_FAN_CTRL_NONE: + vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100); + break; + case AMD_FAN_CTRL_MANUAL: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega20_fan_ctrl_stop_smc_fan_control(hwmgr); + break; + case AMD_FAN_CTRL_AUTO: + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega20_fan_ctrl_start_smc_fan_control(hwmgr); + break; + default: + break; + } +} + +static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_simple_clock_info *info) +{ +#if 0 + struct phm_ppt_v2_information *table_info = + (struct phm_ppt_v2_information *)hwmgr->pptable; + struct phm_clock_and_voltage_limits *max_limits = + &table_info->max_clock_voltage_on_ac; + + info->engine_max_clock = max_limits->sclk; + info->memory_max_clock = max_limits->mclk; +#endif + return 0; +} + + +static int vega20_get_sclks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); + int i, count; + + if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) + return -1; + + count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; + clocks->num_levels = count; + + for (i = 0; i < count; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + clocks->data[i].latency_in_us = 0; + } + + return 0; +} + +static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr, + uint32_t clock) +{ + return 25; +} + +static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table); + int i, count; + + if (!data->smu_features[GNLD_DPM_UCLK].enabled) + return -1; + + count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; + clocks->num_levels = data->mclk_latency_table.count = count; + + for (i = 0; i < count; i++) { + clocks->data[i].clocks_in_khz = + data->mclk_latency_table.entries[i].frequency = + dpm_table->dpm_levels[i].value * 1000; + clocks->data[i].latency_in_us = + data->mclk_latency_table.entries[i].latency = + vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); + } + + return 0; +} + +static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table); + int i, count; + + if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) + return -1; + + count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; + clocks->num_levels = count; + + for (i = 0; i < count; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + clocks->data[i].latency_in_us = 0; + } + + return 0; +} + +static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, + struct pp_clock_levels_with_latency *clocks) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table); + int i, count; + + if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) + return -1; + + count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; + clocks->num_levels = count; + + for (i = 0; i < count; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + clocks->data[i].latency_in_us = 0; + } + + return 0; + +} + +static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks) +{ + int ret; + + switch (type) { + case amd_pp_sys_clock: + ret = vega20_get_sclks(hwmgr, clocks); + break; + case amd_pp_mem_clock: + ret = vega20_get_memclocks(hwmgr, clocks); + break; + case amd_pp_dcef_clock: + ret = vega20_get_dcefclocks(hwmgr, clocks); + break; + case amd_pp_soc_clock: + ret = vega20_get_socclocks(hwmgr, clocks); + break; + default: + return -EINVAL; + } + + return ret; +} + +static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + clocks->num_levels = 0; + + return 0; +} + +static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, + void *clock_ranges) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + Watermarks_t *table = &(data->smc_state_table.water_marks_table); + struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; + + if (!data->registry_data.disable_water_mark && + data->smu_features[GNLD_DPM_DCEFCLK].supported && + data->smu_features[GNLD_DPM_SOCCLK].supported) { + smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); + data->water_marks_bitmap |= WaterMarksExist; + data->water_marks_bitmap &= ~WaterMarksLoaded; + } + + return 0; +} + +static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_single_setting *od8_settings = + data->od8_settings.od8_settings_array; + OverDriveTable_t *od_table = + &(data->smc_state_table.overdrive_table); + int32_t input_index, input_clk, input_vol, i; + int od8_id; + int ret; + + PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", + return -EINVAL); + + switch (type) { + case PP_OD_EDIT_SCLK_VDDC_TABLE: + if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) { + pr_info("Sclk min/max frequency overdrive not supported\n"); + return -EOPNOTSUPP; + } + + for (i = 0; i < size; i += 2) { + if (i + 2 > size) { + pr_info("invalid number of input parameters %d\n", + size); + return -EINVAL; + } + + input_index = input[i]; + input_clk = input[i + 1]; + + if (input_index != 0 && input_index != 1) { + pr_info("Invalid index %d\n", input_index); + pr_info("Support min/max sclk frequency setting only which index by 0/1\n"); + return -EINVAL; + } + + if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value || + input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) { + pr_info("clock freq %d is not within allowed range [%d - %d]\n", + input_clk, + od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, + od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); + return -EINVAL; + } + + if ((input_index == 0 && od_table->GfxclkFmin != input_clk) || + (input_index == 1 && od_table->GfxclkFmax != input_clk)) + data->gfxclk_overdrive = true; + + if (input_index == 0) + od_table->GfxclkFmin = input_clk; + else + od_table->GfxclkFmax = input_clk; + } + + break; + + case PP_OD_EDIT_MCLK_VDDC_TABLE: + if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { + pr_info("Mclk max frequency overdrive not supported\n"); + return -EOPNOTSUPP; + } + + for (i = 0; i < size; i += 2) { + if (i + 2 > size) { + pr_info("invalid number of input parameters %d\n", + size); + return -EINVAL; + } + + input_index = input[i]; + input_clk = input[i + 1]; + + if (input_index != 1) { + pr_info("Invalid index %d\n", input_index); + pr_info("Support max Mclk frequency setting only which index by 1\n"); + return -EINVAL; + } + + if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || + input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { + pr_info("clock freq %d is not within allowed range [%d - %d]\n", + input_clk, + od8_settings[OD8_SETTING_UCLK_FMAX].min_value, + od8_settings[OD8_SETTING_UCLK_FMAX].max_value); + return -EINVAL; + } + + if (input_index == 1 && od_table->UclkFmax != input_clk) + data->memclk_overdrive = true; + + od_table->UclkFmax = input_clk; + } + + break; + + case PP_OD_EDIT_VDDC_CURVE: + if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { + pr_info("Voltage curve calibrate not supported\n"); + return -EOPNOTSUPP; + } + + for (i = 0; i < size; i += 3) { + if (i + 3 > size) { + pr_info("invalid number of input parameters %d\n", + size); + return -EINVAL; + } + + input_index = input[i]; + input_clk = input[i + 1]; + input_vol = input[i + 2]; + + if (input_index > 2) { + pr_info("Setting for point %d is not supported\n", + input_index + 1); + pr_info("Three supported points index by 0, 1, 2\n"); + return -EINVAL; + } + + od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; + if (input_clk < od8_settings[od8_id].min_value || + input_clk > od8_settings[od8_id].max_value) { + pr_info("clock freq %d is not within allowed range [%d - %d]\n", + input_clk, + od8_settings[od8_id].min_value, + od8_settings[od8_id].max_value); + return -EINVAL; + } + + od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; + if (input_vol < od8_settings[od8_id].min_value || + input_vol > od8_settings[od8_id].max_value) { + pr_info("clock voltage %d is not within allowed range [%d - %d]\n", + input_vol, + od8_settings[od8_id].min_value, + od8_settings[od8_id].max_value); + return -EINVAL; + } + + switch (input_index) { + case 0: + od_table->GfxclkFreq1 = input_clk; + od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; + break; + case 1: + od_table->GfxclkFreq2 = input_clk; + od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; + break; + case 2: + od_table->GfxclkFreq3 = input_clk; + od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; + break; + } + } + break; + + case PP_OD_RESTORE_DEFAULT_TABLE: + data->gfxclk_overdrive = false; + data->memclk_overdrive = false; + + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)od_table, + TABLE_OVERDRIVE, true); + PP_ASSERT_WITH_CODE(!ret, + "Failed to export overdrive table!", + return ret); + break; + + case PP_OD_COMMIT_DPM_TABLE: + ret = smum_smc_table_manager(hwmgr, + (uint8_t *)od_table, + TABLE_OVERDRIVE, false); + PP_ASSERT_WITH_CODE(!ret, + "Failed to import overdrive table!", + return ret); + + /* retrieve updated gfxclk table */ + if (data->gfxclk_overdrive) { + data->gfxclk_overdrive = false; + + ret = vega20_setup_gfxclk_dpm_table(hwmgr); + if (ret) + return ret; + } + + /* retrieve updated memclk table */ + if (data->memclk_overdrive) { + data->memclk_overdrive = false; + + ret = vega20_setup_memclk_dpm_table(hwmgr); + if (ret) + return ret; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr, + enum pp_mp1_state mp1_state) +{ + uint16_t msg; + int ret; + + switch (mp1_state) { + case PP_MP1_STATE_SHUTDOWN: + msg = PPSMC_MSG_PrepareMp1ForShutdown; + break; + case PP_MP1_STATE_UNLOAD: + msg = PPSMC_MSG_PrepareMp1ForUnload; + break; + case PP_MP1_STATE_RESET: + msg = PPSMC_MSG_PrepareMp1ForReset; + break; + case PP_MP1_STATE_NONE: + default: + return 0; + } + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, + "[PrepareMp1] Failed!", + return ret); + + return 0; +} + +static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) +{ + static const char *ppfeature_name[] = { + "DPM_PREFETCHER", + "GFXCLK_DPM", + "UCLK_DPM", + "SOCCLK_DPM", + "UVD_DPM", + "VCE_DPM", + "ULV", + "MP0CLK_DPM", + "LINK_DPM", + "DCEFCLK_DPM", + "GFXCLK_DS", + "SOCCLK_DS", + "LCLK_DS", + "PPT", + "TDC", + "THERMAL", + "GFX_PER_CU_CG", + "RM", + "DCEFCLK_DS", + "ACDC", + "VR0HOT", + "VR1HOT", + "FW_CTF", + "LED_DISPLAY", + "FAN_CONTROL", + "GFX_EDC", + "GFXOFF", + "CG", + "FCLK_DPM", + "FCLK_DS", + "MP1CLK_DS", + "MP0CLK_DS", + "XGMI", + "ECC"}; + static const char *output_title[] = { + "FEATURES", + "BITMASK", + "ENABLEMENT"}; + uint64_t features_enabled; + int i; + int ret = 0; + int size = 0; + + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + PP_ASSERT_WITH_CODE(!ret, + "[EnableAllSmuFeatures] Failed to get enabled smc features!", + return ret); + + size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); + size += sprintf(buf + size, "%-19s %-22s %s\n", + output_title[0], + output_title[1], + output_title[2]); + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", + ppfeature_name[i], + 1ULL << i, + (features_enabled & (1ULL << i)) ? "Y" : "N"); + } + + return size; +} + +static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + uint64_t features_enabled, features_to_enable, features_to_disable; + int i, ret = 0; + bool enabled; + + if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) + return -EINVAL; + + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + features_to_disable = + features_enabled & ~new_ppfeature_masks; + features_to_enable = + ~features_enabled & new_ppfeature_masks; + + pr_debug("features_to_disable 0x%llx\n", features_to_disable); + pr_debug("features_to_enable 0x%llx\n", features_to_enable); + + if (features_to_disable) { + ret = vega20_enable_smc_features(hwmgr, false, features_to_disable); + if (ret) + return ret; + } + + if (features_to_enable) { + ret = vega20_enable_smc_features(hwmgr, true, features_to_enable); + if (ret) + return ret; + } + + /* Update the cached feature enablement state */ + ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); + if (ret) + return ret; + + for (i = 0; i < GNLD_FEATURES_MAX; i++) { + enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? + true : false; + data->smu_features[i].enabled = enabled; + } + + return 0; +} + +static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) +{ + uint32_t width_level; + + width_level = vega20_get_current_pcie_link_width_level(hwmgr); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speed_level; + + speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + +static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_od8_single_setting *od8_settings = + data->od8_settings.od8_settings_array; + OverDriveTable_t *od_table = + &(data->smc_state_table.overdrive_table); + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable; + struct pp_clock_levels_with_latency clocks; + struct vega20_single_dpm_table *fclk_dpm_table = + &(data->dpm_table.fclk_table); + int i, now, size = 0; + int ret = 0; + uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width; + + switch (type) { + case PP_SCLK: + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to get current gfx clk Failed!", + return ret); + + if (vega20_get_sclks(hwmgr, &clocks)) { + size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; + + case PP_MCLK: + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to get current mclk freq Failed!", + return ret); + + if (vega20_get_memclocks(hwmgr, &clocks)) { + size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; + + case PP_SOCCLK: + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to get current socclk freq Failed!", + return ret); + + if (vega20_get_socclocks(hwmgr, &clocks)) { + size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; + + case PP_FCLK: + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to get current fclk freq Failed!", + return ret); + + for (i = 0; i < fclk_dpm_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, fclk_dpm_table->dpm_levels[i].value, + fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); + break; + + case PP_DCEFCLK: + ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now); + PP_ASSERT_WITH_CODE(!ret, + "Attempt to get current dcefclk freq Failed!", + return ret); + + if (vega20_get_dcefclocks(hwmgr, &clocks)) { + size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", + now / 100); + break; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); + break; + + case PP_PCIE: + current_gen_speed = + vega20_get_current_pcie_link_speed_level(hwmgr); + current_lane_width = + vega20_get_current_pcie_link_width_level(hwmgr); + for (i = 0; i < NUM_LINK_LEVELS; i++) { + if (i == 1 && data->pcie_parameters_override) { + gen_speed = data->pcie_gen_level1; + lane_width = data->pcie_width_level1; + } else { + gen_speed = pptable->PcieGenSpeed[i]; + lane_width = pptable->PcieLaneCount[i]; + } + size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, + (gen_speed == 0) ? "2.5GT/s," : + (gen_speed == 1) ? "5.0GT/s," : + (gen_speed == 2) ? "8.0GT/s," : + (gen_speed == 3) ? "16.0GT/s," : "", + (lane_width == 1) ? "x1" : + (lane_width == 2) ? "x2" : + (lane_width == 3) ? "x4" : + (lane_width == 4) ? "x8" : + (lane_width == 5) ? "x12" : + (lane_width == 6) ? "x16" : "", + pptable->LclkFreq[i], + (current_gen_speed == gen_speed) && + (current_lane_width == lane_width) ? + "*" : ""); + } + break; + + case OD_SCLK: + if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { + size = sprintf(buf, "%s:\n", "OD_SCLK"); + size += sprintf(buf + size, "0: %10uMhz\n", + od_table->GfxclkFmin); + size += sprintf(buf + size, "1: %10uMhz\n", + od_table->GfxclkFmax); + } + break; + + case OD_MCLK: + if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { + size = sprintf(buf, "%s:\n", "OD_MCLK"); + size += sprintf(buf + size, "1: %10uMhz\n", + od_table->UclkFmax); + } + + break; + + case OD_VDDC_CURVE: + if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { + size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); + size += sprintf(buf + size, "0: %10uMhz %10dmV\n", + od_table->GfxclkFreq1, + od_table->GfxclkVolt1 / VOLTAGE_SCALE); + size += sprintf(buf + size, "1: %10uMhz %10dmV\n", + od_table->GfxclkFreq2, + od_table->GfxclkVolt2 / VOLTAGE_SCALE); + size += sprintf(buf + size, "2: %10uMhz %10dmV\n", + od_table->GfxclkFreq3, + od_table->GfxclkVolt3 / VOLTAGE_SCALE); + } + + break; + + case OD_RANGE: + size = sprintf(buf, "%s:\n", "OD_RANGE"); + + if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { + size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, + od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); + } + + if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { + size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_UCLK_FMAX].min_value, + od8_settings[OD8_SETTING_UCLK_FMAX].max_value); + } + + if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { + size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); + size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); + size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", + od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, + od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, + od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); + } + + break; + default: + break; + } + return size; +} + +static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, + struct vega20_single_dpm_table *dpm_table) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->smu_features[GNLD_DPM_UCLK].enabled) { + PP_ASSERT_WITH_CODE(dpm_table->count > 0, + "[SetUclkToHightestDpmLevel] Dpm table has no entry!", + return -EINVAL); + PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, + "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", + return -EINVAL); + + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetHardMinByFreq, + (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, + NULL)), + "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", + return ret); + } + + return ret; +} + +static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table); + int ret = 0; + + if (data->smu_features[GNLD_DPM_FCLK].enabled) { + PP_ASSERT_WITH_CODE(dpm_table->count > 0, + "[SetFclkToHightestDpmLevel] Dpm table has no entry!", + return -EINVAL); + PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS, + "[SetFclkToHightestDpmLevel] Dpm table has too many entries!", + return -EINVAL); + + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSoftMinByFreq, + (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level, + NULL)), + "[SetFclkToHightestDpmLevel] Set soft min fclk failed!", + return ret); + } + + return ret; +} + +static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + int ret = 0; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, 0, NULL); + + ret = vega20_set_uclk_to_highest_dpm_level(hwmgr, + &data->dpm_table.mem_table); + if (ret) + return ret; + + return vega20_set_fclk_to_highest_dpm_level(hwmgr); +} + +static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + int result = 0; + Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); + + if ((data->water_marks_bitmap & WaterMarksExist) && + !(data->water_marks_bitmap & WaterMarksLoaded)) { + result = smum_smc_table_manager(hwmgr, + (uint8_t *)wm_table, TABLE_WATERMARKS, false); + PP_ASSERT_WITH_CODE(!result, + "Failed to update WMTABLE!", + return result); + data->water_marks_bitmap |= WaterMarksLoaded; + } + + if ((data->water_marks_bitmap & WaterMarksExist) && + data->smu_features[GNLD_DPM_DCEFCLK].supported && + data->smu_features[GNLD_DPM_SOCCLK].supported) { + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_NumOfDisplays, + hwmgr->display_config->num_display, + NULL); + } + + return result; +} + +static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + int ret = 0; + + if (data->smu_features[GNLD_DPM_UVD].supported) { + if (data->smu_features[GNLD_DPM_UVD].enabled == enable) { + if (enable) + PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n"); + else + PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n"); + } + + ret = vega20_enable_smc_features(hwmgr, + enable, + data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap); + PP_ASSERT_WITH_CODE(!ret, + "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!", + return ret); + data->smu_features[GNLD_DPM_UVD].enabled = enable; + } + + return 0; +} + +static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + + if (data->vce_power_gated == bgate) + return ; + + data->vce_power_gated = bgate; + if (bgate) { + vega20_enable_disable_vce_dpm(hwmgr, !bgate); + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + } else { + amdgpu_device_ip_set_powergating_state(hwmgr->adev, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + vega20_enable_disable_vce_dpm(hwmgr, !bgate); + } + +} + +static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + + if (data->uvd_power_gated == bgate) + return ; + + data->uvd_power_gated = bgate; + vega20_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + struct vega20_single_dpm_table *dpm_table; + bool vblank_too_short = false; + bool disable_mclk_switching; + bool disable_fclk_switching; + uint32_t i, latency; + + disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && + !hwmgr->display_config->multi_monitor_in_sync) || + vblank_too_short; + latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; + + /* gfxclk */ + dpm_table = &(data->dpm_table.gfx_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* memclk */ + dpm_table = &(data->dpm_table.mem_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* honour DAL's UCLK Hardmin */ + if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) + dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; + + /* Hardmin is dependent on displayconfig */ + if (disable_mclk_switching) { + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + for (i = 0; i < data->mclk_latency_table.count - 1; i++) { + if (data->mclk_latency_table.entries[i].latency <= latency) { + if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; + break; + } + } + } + } + + if (hwmgr->display_config->nb_pstate_switch_disable) + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + if ((disable_mclk_switching && + (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) || + hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value) + disable_fclk_switching = true; + else + disable_fclk_switching = false; + + /* fclk */ + dpm_table = &(data->dpm_table.fclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching) + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + + /* vclk */ + dpm_table = &(data->dpm_table.vclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* dclk */ + dpm_table = &(data->dpm_table.dclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* socclk */ + dpm_table = &(data->dpm_table.soc_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + /* eclk */ + dpm_table = &(data->dpm_table.eclk_table); + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; + dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; + dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; + + if (PP_CAP(PHM_PlatformCaps_UMDPState)) { + if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; + } + + if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; + } + } + + return 0; +} + +static bool +vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + bool is_update_required = false; + + if (data->display_timing.num_existing_displays != + hwmgr->display_config->num_display) + is_update_required = true; + + if (data->registry_data.gfx_clk_deep_sleep_support && + (data->display_timing.min_clock_in_sr != + hwmgr->display_config->min_core_set_clock_in_sr)) + is_update_required = true; + + return is_update_required; +} + +static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + + ret = vega20_disable_all_smu_features(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "[DisableDpmTasks] Failed to disable all smu features!", + return ret); + + return 0; +} + +static int vega20_power_off_asic(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + int result; + + result = vega20_disable_dpm_tasks(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "[PowerOffAsic] Failed to disable DPM!", + ); + data->water_marks_bitmap &= ~(WaterMarksLoaded); + + return result; +} + +static int conv_power_profile_to_pplib_workload(int power_profile) +{ + int pplib_workload = 0; + + switch (power_profile) { + case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: + pplib_workload = WORKLOAD_DEFAULT_BIT; + break; + case PP_SMC_POWER_PROFILE_FULLSCREEN3D: + pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; + break; + case PP_SMC_POWER_PROFILE_POWERSAVING: + pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; + break; + case PP_SMC_POWER_PROFILE_VIDEO: + pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; + break; + case PP_SMC_POWER_PROFILE_VR: + pplib_workload = WORKLOAD_PPLIB_VR_BIT; + break; + case PP_SMC_POWER_PROFILE_COMPUTE: + pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; + break; + case PP_SMC_POWER_PROFILE_CUSTOM: + pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT; + break; + } + + return pplib_workload; +} + +static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + uint32_t i, size = 0; + uint16_t workload_type = 0; + static const char *profile_name[] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + static const char *title[] = { + "PROFILE_INDEX(NAME)", + "CLOCK_TYPE(NAME)", + "FPS", + "UseRlcBusy", + "MinActiveFreqType", + "MinActiveFreq", + "BoosterFreqType", + "BoosterFreq", + "PD_Data_limit_c", + "PD_Data_error_coeff", + "PD_Data_error_rate_coeff"}; + int result = 0; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9], title[10]); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = conv_power_profile_to_pplib_workload(i); + result = vega20_get_activity_monitor_coeff(hwmgr, + (uint8_t *)(&activity_monitor), workload_type); + PP_ASSERT_WITH_CODE(!result, + "[GetPowerProfile] Failed to get activity monitor!", + return result); + + size += sprintf(buf + size, "%2d %14s%s:\n", + i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " "); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 0, + "GFXCLK", + activity_monitor.Gfx_FPS, + activity_monitor.Gfx_UseRlcBusy, + activity_monitor.Gfx_MinActiveFreqType, + activity_monitor.Gfx_MinActiveFreq, + activity_monitor.Gfx_BoosterFreqType, + activity_monitor.Gfx_BoosterFreq, + activity_monitor.Gfx_PD_Data_limit_c, + activity_monitor.Gfx_PD_Data_error_coeff, + activity_monitor.Gfx_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 1, + "SOCCLK", + activity_monitor.Soc_FPS, + activity_monitor.Soc_UseRlcBusy, + activity_monitor.Soc_MinActiveFreqType, + activity_monitor.Soc_MinActiveFreq, + activity_monitor.Soc_BoosterFreqType, + activity_monitor.Soc_BoosterFreq, + activity_monitor.Soc_PD_Data_limit_c, + activity_monitor.Soc_PD_Data_error_coeff, + activity_monitor.Soc_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 2, + "UCLK", + activity_monitor.Mem_FPS, + activity_monitor.Mem_UseRlcBusy, + activity_monitor.Mem_MinActiveFreqType, + activity_monitor.Mem_MinActiveFreq, + activity_monitor.Mem_BoosterFreqType, + activity_monitor.Mem_BoosterFreq, + activity_monitor.Mem_PD_Data_limit_c, + activity_monitor.Mem_PD_Data_error_coeff, + activity_monitor.Mem_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 3, + "FCLK", + activity_monitor.Fclk_FPS, + activity_monitor.Fclk_UseRlcBusy, + activity_monitor.Fclk_MinActiveFreqType, + activity_monitor.Fclk_MinActiveFreq, + activity_monitor.Fclk_BoosterFreqType, + activity_monitor.Fclk_BoosterFreq, + activity_monitor.Fclk_PD_Data_limit_c, + activity_monitor.Fclk_PD_Data_error_coeff, + activity_monitor.Fclk_PD_Data_error_rate_coeff); + } + + return size; +} + +static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + int workload_type, result = 0; + uint32_t power_profile_mode = input[size]; + + if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { + pr_err("Invalid power profile mode %d\n", power_profile_mode); + return -EINVAL; + } + + if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + if (size == 0 && !data->is_custom_profile_set) + return -EINVAL; + if (size < 10 && size != 0) + return -EINVAL; + + result = vega20_get_activity_monitor_coeff(hwmgr, + (uint8_t *)(&activity_monitor), + WORKLOAD_PPLIB_CUSTOM_BIT); + PP_ASSERT_WITH_CODE(!result, + "[SetPowerProfile] Failed to get activity monitor!", + return result); + + /* If size==0, then we want to apply the already-configured + * CUSTOM profile again. Just apply it, since we checked its + * validity above + */ + if (size == 0) + goto out; + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor.Gfx_FPS = input[1]; + activity_monitor.Gfx_UseRlcBusy = input[2]; + activity_monitor.Gfx_MinActiveFreqType = input[3]; + activity_monitor.Gfx_MinActiveFreq = input[4]; + activity_monitor.Gfx_BoosterFreqType = input[5]; + activity_monitor.Gfx_BoosterFreq = input[6]; + activity_monitor.Gfx_PD_Data_limit_c = input[7]; + activity_monitor.Gfx_PD_Data_error_coeff = input[8]; + activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; + break; + case 1: /* Socclk */ + activity_monitor.Soc_FPS = input[1]; + activity_monitor.Soc_UseRlcBusy = input[2]; + activity_monitor.Soc_MinActiveFreqType = input[3]; + activity_monitor.Soc_MinActiveFreq = input[4]; + activity_monitor.Soc_BoosterFreqType = input[5]; + activity_monitor.Soc_BoosterFreq = input[6]; + activity_monitor.Soc_PD_Data_limit_c = input[7]; + activity_monitor.Soc_PD_Data_error_coeff = input[8]; + activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; + break; + case 2: /* Uclk */ + activity_monitor.Mem_FPS = input[1]; + activity_monitor.Mem_UseRlcBusy = input[2]; + activity_monitor.Mem_MinActiveFreqType = input[3]; + activity_monitor.Mem_MinActiveFreq = input[4]; + activity_monitor.Mem_BoosterFreqType = input[5]; + activity_monitor.Mem_BoosterFreq = input[6]; + activity_monitor.Mem_PD_Data_limit_c = input[7]; + activity_monitor.Mem_PD_Data_error_coeff = input[8]; + activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; + break; + case 3: /* Fclk */ + activity_monitor.Fclk_FPS = input[1]; + activity_monitor.Fclk_UseRlcBusy = input[2]; + activity_monitor.Fclk_MinActiveFreqType = input[3]; + activity_monitor.Fclk_MinActiveFreq = input[4]; + activity_monitor.Fclk_BoosterFreqType = input[5]; + activity_monitor.Fclk_BoosterFreq = input[6]; + activity_monitor.Fclk_PD_Data_limit_c = input[7]; + activity_monitor.Fclk_PD_Data_error_coeff = input[8]; + activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; + break; + } + + result = vega20_set_activity_monitor_coeff(hwmgr, + (uint8_t *)(&activity_monitor), + WORKLOAD_PPLIB_CUSTOM_BIT); + data->is_custom_profile_set = true; + PP_ASSERT_WITH_CODE(!result, + "[SetPowerProfile] Failed to set activity monitor!", + return result); + } + +out: + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = + conv_power_profile_to_pplib_workload(power_profile_mode); + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, + 1 << workload_type, + NULL); + + hwmgr->power_profile_mode = power_profile_mode; + + return 0; +} + +static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrHigh, + virtual_addr_hi, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrLow, + virtual_addr_low, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrHigh, + mc_addr_hi, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrLow, + mc_addr_low, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramSize, + size, + NULL); + return 0; +} + +static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *thermal_data) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + + memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); + + thermal_data->max = pp_table->TedgeLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_crit_max = pp_table->ThbmLimit * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire) +{ + int res; + + /* I2C bus access can happen very early, when SMU not loaded yet */ + if (!vega20_is_smc_ram_running(hwmgr)) + return 0; + + res = smum_send_msg_to_smc_with_parameter(hwmgr, + (acquire ? + PPSMC_MSG_RequestI2CBus : + PPSMC_MSG_ReleaseI2CBus), + 0, + NULL); + + PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res); + return res; +} + +static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr, + enum pp_df_cstate state) +{ + int ret; + + /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */ + if (hwmgr->smu_version < 0x283200) { + pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n"); + return -EINVAL; + } + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state, + NULL); + if (ret) + pr_err("SetDfCstate failed!\n"); + + return ret; +} + +static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, + uint32_t pstate) +{ + int ret; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetXgmiMode, + pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, + NULL); + if (ret) + pr_err("SetXgmiPstate failed!\n"); + + return ret; +} + +static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} + +static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, + void **table) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + struct gpu_metrics_v1_0 *gpu_metrics = + &data->gpu_metrics_table; + SmuMetrics_t metrics; + uint32_t fan_speed_rpm; + int ret; + + ret = vega20_get_metrics_table(hwmgr, &metrics, true); + if (ret) + return ret; + + vega20_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); + gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; + + gpu_metrics->pcie_link_width = + vega20_get_current_pcie_link_width(hwmgr); + gpu_metrics->pcie_link_speed = + vega20_get_current_pcie_link_speed(hwmgr); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + +static const struct pp_hwmgr_func vega20_hwmgr_funcs = { + /* init/fini related */ + .backend_init = vega20_hwmgr_backend_init, + .backend_fini = vega20_hwmgr_backend_fini, + .asic_setup = vega20_setup_asic_task, + .power_off_asic = vega20_power_off_asic, + .dynamic_state_management_enable = vega20_enable_dpm_tasks, + .dynamic_state_management_disable = vega20_disable_dpm_tasks, + /* power state related */ + .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, + .pre_display_config_changed = vega20_pre_display_configuration_changed_task, + .display_config_changed = vega20_display_configuration_changed_task, + .check_smc_update_required_for_display_configuration = + vega20_check_smc_update_required_for_display_configuration, + .notify_smc_display_config_after_ps_adjustment = + vega20_notify_smc_display_config_after_ps_adjustment, + /* export to DAL */ + .get_sclk = vega20_dpm_get_sclk, + .get_mclk = vega20_dpm_get_mclk, + .get_dal_power_level = vega20_get_dal_power_level, + .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, + .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage, + .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges, + .display_clock_voltage_request = vega20_display_clock_voltage_request, + .get_performance_level = vega20_get_performance_level, + /* UMD pstate, profile related */ + .force_dpm_level = vega20_dpm_force_dpm_level, + .get_power_profile_mode = vega20_get_power_profile_mode, + .set_power_profile_mode = vega20_set_power_profile_mode, + /* od related */ + .set_power_limit = vega20_set_power_limit, + .get_sclk_od = vega20_get_sclk_od, + .set_sclk_od = vega20_set_sclk_od, + .get_mclk_od = vega20_get_mclk_od, + .set_mclk_od = vega20_set_mclk_od, + .odn_edit_dpm_table = vega20_odn_edit_dpm_table, + /* for sysfs to retrive/set gfxclk/memclk */ + .force_clock_level = vega20_force_clock_level, + .print_clock_levels = vega20_print_clock_levels, + .read_sensor = vega20_read_sensor, + .get_ppfeature_status = vega20_get_ppfeature_status, + .set_ppfeature_status = vega20_set_ppfeature_status, + /* powergate related */ + .powergate_uvd = vega20_power_gate_uvd, + .powergate_vce = vega20_power_gate_vce, + /* thermal related */ + .start_thermal_controller = vega20_start_thermal_controller, + .stop_thermal_controller = vega20_thermal_stop_thermal_controller, + .get_thermal_temperature_range = vega20_get_thermal_temperature_range, + .register_irq_handlers = smu9_register_irq_handlers, + .disable_smc_firmware_ctf = vega20_thermal_disable_alert, + /* fan control related */ + .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent, + .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info, + .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm, + .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm, + .get_fan_control_mode = vega20_get_fan_control_mode, + .set_fan_control_mode = vega20_set_fan_control_mode, + /* smu memory related */ + .notify_cac_buffer_info = vega20_notify_cac_buffer_info, + .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost, + /* BACO related */ + .get_asic_baco_capability = vega20_baco_get_capability, + .get_asic_baco_state = vega20_baco_get_state, + .set_asic_baco_state = vega20_baco_set_state, + .set_mp1_state = vega20_set_mp1_state, + .smu_i2c_bus_access = vega20_smu_i2c_bus_access, + .set_df_cstate = vega20_set_df_cstate, + .set_xgmi_pstate = vega20_set_xgmi_pstate, + .get_gpu_metrics = vega20_get_gpu_metrics, +}; + +int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + hwmgr->hwmgr_func = &vega20_hwmgr_funcs; + hwmgr->pptable_func = &vega20_pptable_funcs; + + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h new file mode 100644 index 000000000000..075c0094da9c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.h @@ -0,0 +1,590 @@ +/* + * Copyright 2018 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 _VEGA20_HWMGR_H_ +#define _VEGA20_HWMGR_H_ + +#include "hwmgr.h" +#include "smu11_driver_if.h" +#include "ppatomfwctrl.h" + +#define VEGA20_MAX_HARDWARE_POWERLEVELS 2 + +#define WaterMarksExist 1 +#define WaterMarksLoaded 2 + +#define VG20_PSUEDO_NUM_GFXCLK_DPM_LEVELS 8 +#define VG20_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8 +#define VG20_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8 +#define VG20_PSUEDO_NUM_UCLK_DPM_LEVELS 4 + +//OverDriver8 macro defs +#define AVFS_CURVE 0 +#define OD8_HOTCURVE_TEMPERATURE 85 + +#define VG20_CLOCK_MAX_DEFAULT 0xFFFF + +typedef uint32_t PP_Clock; + +enum { + GNLD_DPM_PREFETCHER = 0, + GNLD_DPM_GFXCLK, + GNLD_DPM_UCLK, + GNLD_DPM_SOCCLK, + GNLD_DPM_UVD, + GNLD_DPM_VCE, + GNLD_ULV, + GNLD_DPM_MP0CLK, + GNLD_DPM_LINK, + GNLD_DPM_DCEFCLK, + GNLD_DS_GFXCLK, + GNLD_DS_SOCCLK, + GNLD_DS_LCLK, + GNLD_PPT, + GNLD_TDC, + GNLD_THERMAL, + GNLD_GFX_PER_CU_CG, + GNLD_RM, + GNLD_DS_DCEFCLK, + GNLD_ACDC, + GNLD_VR0HOT, + GNLD_VR1HOT, + GNLD_FW_CTF, + GNLD_LED_DISPLAY, + GNLD_FAN_CONTROL, + GNLD_DIDT, + GNLD_GFXOFF, + GNLD_CG, + GNLD_DPM_FCLK, + GNLD_DS_FCLK, + GNLD_DS_MP1CLK, + GNLD_DS_MP0CLK, + GNLD_XGMI, + GNLD_ECC, + + GNLD_FEATURES_MAX +}; + + +#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) + +#define SMC_DPM_FEATURES 0x30F + +struct smu_features { + bool supported; + bool enabled; + bool allowed; + uint32_t smu_feature_id; + uint64_t smu_feature_bitmap; +}; + +struct vega20_performance_level { + uint32_t soc_clock; + uint32_t gfx_clock; + uint32_t mem_clock; +}; + +struct vega20_bacos { + uint32_t baco_flags; + /* struct vega20_performance_level performance_level; */ +}; + +struct vega20_uvd_clocks { + uint32_t vclk; + uint32_t dclk; +}; + +struct vega20_vce_clocks { + uint32_t evclk; + uint32_t ecclk; +}; + +struct vega20_power_state { + uint32_t magic; + struct vega20_uvd_clocks uvd_clks; + struct vega20_vce_clocks vce_clks; + uint16_t performance_level_count; + bool dc_compatible; + uint32_t sclk_threshold; + struct vega20_performance_level performance_levels[VEGA20_MAX_HARDWARE_POWERLEVELS]; +}; + +struct vega20_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +#define VEGA20_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 16 +#define MAX_PCIE_CONF 2 +#define VEGA20_MINIMUM_ENGINE_CLOCK 2500 + +struct vega20_max_sustainable_clocks { + PP_Clock display_clock; + PP_Clock phy_clock; + PP_Clock pixel_clock; + PP_Clock uclock; + PP_Clock dcef_clock; + PP_Clock soc_clock; +}; + +struct vega20_dpm_state { + uint32_t soft_min_level; + uint32_t soft_max_level; + uint32_t hard_min_level; + uint32_t hard_max_level; +}; + +struct vega20_single_dpm_table { + uint32_t count; + struct vega20_dpm_state dpm_state; + struct vega20_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega20_odn_dpm_control { + uint32_t count; + uint32_t entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega20_pcie_table { + uint16_t count; + uint8_t pcie_gen[MAX_PCIE_CONF]; + uint8_t pcie_lane[MAX_PCIE_CONF]; + uint32_t lclk[MAX_PCIE_CONF]; +}; + +struct vega20_dpm_table { + struct vega20_single_dpm_table soc_table; + struct vega20_single_dpm_table gfx_table; + struct vega20_single_dpm_table mem_table; + struct vega20_single_dpm_table eclk_table; + struct vega20_single_dpm_table vclk_table; + struct vega20_single_dpm_table dclk_table; + struct vega20_single_dpm_table dcef_table; + struct vega20_single_dpm_table pixel_table; + struct vega20_single_dpm_table display_table; + struct vega20_single_dpm_table phy_table; + struct vega20_single_dpm_table fclk_table; + struct vega20_pcie_table pcie_table; +}; + +#define VEGA20_MAX_LEAKAGE_COUNT 8 +struct vega20_leakage_voltage { + uint16_t count; + uint16_t leakage_id[VEGA20_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[VEGA20_MAX_LEAKAGE_COUNT]; +}; + +struct vega20_display_timing { + uint32_t min_clock_in_sr; + uint32_t num_existing_displays; +}; + +struct vega20_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; +}; + +struct vega20_vbios_boot_state { + uint8_t uc_cooling_id; + uint16_t vddc; + uint16_t vddci; + uint16_t mvddc; + uint16_t vdd_gfx; + uint32_t gfx_clock; + uint32_t mem_clock; + uint32_t soc_clock; + uint32_t dcef_clock; + uint32_t eclock; + uint32_t dclock; + uint32_t vclock; + uint32_t fclock; +}; + +#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 +#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 +#define DPMTABLE_UPDATE_SCLK 0x00000004 +#define DPMTABLE_UPDATE_MCLK 0x00000008 +#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 +#define DPMTABLE_OD_UPDATE_SCLK_MASK 0x00000020 +#define DPMTABLE_OD_UPDATE_MCLK_MASK 0x00000040 + +// To determine if sclk and mclk are in overdrive state +#define SCLK_MASK_OVERDRIVE_ENABLED 0x00000008 +#define MCLK_MASK_OVERDRIVE_ENABLED 0x00000010 +#define SOCCLK_OVERDRIVE_ENABLED 0x00000020 + +struct vega20_smc_state_table { + uint32_t soc_boot_level; + uint32_t gfx_boot_level; + uint32_t dcef_boot_level; + uint32_t mem_boot_level; + uint32_t uvd_boot_level; + uint32_t vce_boot_level; + uint32_t gfx_max_level; + uint32_t mem_max_level; + uint8_t vr_hot_gpio; + uint8_t ac_dc_gpio; + uint8_t therm_out_gpio; + uint8_t therm_out_polarity; + uint8_t therm_out_mode; + PPTable_t pp_table; + Watermarks_t water_marks_table; + AvfsDebugTable_t avfs_debug_table; + AvfsFuseOverride_t avfs_fuse_override_table; + SmuMetrics_t smu_metrics; + DriverSmuConfig_t driver_smu_config; + DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint; + OverDriveTable_t overdrive_table; +}; + +struct vega20_mclk_latency_entries { + uint32_t frequency; + uint32_t latency; +}; + +struct vega20_mclk_latency_table { + uint32_t count; + struct vega20_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega20_registry_data { + uint64_t disallowed_features; + uint8_t ac_dc_switch_gpio_support; + uint8_t acg_loop_support; + uint8_t clock_stretcher_support; + uint8_t db_ramping_support; + uint8_t didt_mode; + uint8_t didt_support; + uint8_t edc_didt_support; + uint8_t force_dpm_high; + uint8_t fuzzy_fan_control_support; + uint8_t mclk_dpm_key_disabled; + uint8_t od_state_in_dc_support; + uint8_t pcie_lane_override; + uint8_t pcie_speed_override; + uint32_t pcie_clock_override; + uint8_t pcie_dpm_key_disabled; + uint8_t dcefclk_dpm_key_disabled; + uint8_t prefetcher_dpm_key_disabled; + uint8_t quick_transition_support; + uint8_t regulator_hot_gpio_support; + uint8_t master_deep_sleep_support; + uint8_t gfx_clk_deep_sleep_support; + uint8_t sclk_deep_sleep_support; + uint8_t lclk_deep_sleep_support; + uint8_t dce_fclk_deep_sleep_support; + uint8_t sclk_dpm_key_disabled; + uint8_t sclk_throttle_low_notification; + uint8_t skip_baco_hardware; + uint8_t socclk_dpm_key_disabled; + uint8_t sq_ramping_support; + uint8_t tcp_ramping_support; + uint8_t td_ramping_support; + uint8_t dbr_ramping_support; + uint8_t gc_didt_support; + uint8_t psm_didt_support; + uint8_t thermal_support; + uint8_t fw_ctf_enabled; + uint8_t led_dpm_enabled; + uint8_t fan_control_support; + uint8_t ulv_support; + uint8_t od8_feature_enable; + uint8_t disable_water_mark; + uint8_t disable_workload_policy; + uint32_t force_workload_policy_mask; + uint8_t disable_3d_fs_detection; + uint8_t disable_pp_tuning; + uint8_t disable_xlpp_tuning; + uint32_t perf_ui_tuning_profile_turbo; + uint32_t perf_ui_tuning_profile_powerSave; + uint32_t perf_ui_tuning_profile_xl; + uint16_t zrpm_stop_temp; + uint16_t zrpm_start_temp; + uint32_t stable_pstate_sclk_dpm_percentage; + uint8_t fps_support; + uint8_t vr0hot; + uint8_t vr1hot; + uint8_t disable_auto_wattman; + uint32_t auto_wattman_debug; + uint32_t auto_wattman_sample_period; + uint32_t fclk_gfxclk_ratio; + uint8_t auto_wattman_threshold; + uint8_t log_avfs_param; + uint8_t enable_enginess; + uint8_t custom_fan_support; + uint8_t disable_pcc_limit_control; + uint8_t gfxoff_controlled_by_driver; +}; + +struct vega20_odn_clock_voltage_dependency_table { + uint32_t count; + struct phm_ppt_v1_clock_voltage_dependency_record + entries[MAX_REGULAR_DPM_NUMBER]; +}; + +struct vega20_odn_dpm_table { + struct vega20_odn_dpm_control control_gfxclk_state; + struct vega20_odn_dpm_control control_memclk_state; + struct phm_odn_clock_levels odn_core_clock_dpm_levels; + struct phm_odn_clock_levels odn_memory_clock_dpm_levels; + struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; + struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; + struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_socclk; + uint32_t odn_mclk_min_limit; +}; + +struct vega20_odn_fan_table { + uint32_t target_fan_speed; + uint32_t target_temperature; + uint32_t min_performance_clock; + uint32_t min_fan_limit; + bool force_fan_pwm; +}; + +struct vega20_odn_temp_table { + uint16_t target_operating_temp; + uint16_t default_target_operating_temp; + uint16_t operating_temp_min_limit; + uint16_t operating_temp_max_limit; + uint16_t operating_temp_step; +}; + +struct vega20_odn_data { + uint32_t apply_overdrive_next_settings_mask; + uint32_t overdrive_next_state; + uint32_t overdrive_next_capabilities; + uint32_t odn_sclk_dpm_enable_mask; + uint32_t odn_mclk_dpm_enable_mask; + struct vega20_odn_dpm_table odn_dpm_table; + struct vega20_odn_fan_table odn_fan_table; + struct vega20_odn_temp_table odn_temp_table; +}; + +enum OD8_FEATURE_ID +{ + OD8_GFXCLK_LIMITS = 1 << 0, + OD8_GFXCLK_CURVE = 1 << 1, + OD8_UCLK_MAX = 1 << 2, + OD8_POWER_LIMIT = 1 << 3, + OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm + OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm + OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature + OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp + OD8_MEMORY_TIMING_TUNE = 1 << 8, + OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 +}; + +enum OD8_SETTING_ID +{ + OD8_SETTING_GFXCLK_FMIN = 0, + OD8_SETTING_GFXCLK_FMAX, + OD8_SETTING_GFXCLK_FREQ1, + OD8_SETTING_GFXCLK_VOLTAGE1, + OD8_SETTING_GFXCLK_FREQ2, + OD8_SETTING_GFXCLK_VOLTAGE2, + OD8_SETTING_GFXCLK_FREQ3, + OD8_SETTING_GFXCLK_VOLTAGE3, + OD8_SETTING_UCLK_FMAX, + OD8_SETTING_POWER_PERCENTAGE, + OD8_SETTING_FAN_ACOUSTIC_LIMIT, + OD8_SETTING_FAN_MIN_SPEED, + OD8_SETTING_FAN_TARGET_TEMP, + OD8_SETTING_OPERATING_TEMP_MAX, + OD8_SETTING_AC_TIMING, + OD8_SETTING_FAN_ZERO_RPM_CONTROL, + OD8_SETTING_COUNT +}; + +struct vega20_od8_single_setting { + uint32_t feature_id; + int32_t min_value; + int32_t max_value; + int32_t current_value; + int32_t default_value; +}; + +struct vega20_od8_settings { + uint32_t overdrive8_capabilities; + struct vega20_od8_single_setting od8_settings_array[OD8_SETTING_COUNT]; +}; + +struct vega20_hwmgr { + struct vega20_dpm_table dpm_table; + struct vega20_dpm_table golden_dpm_table; + struct vega20_registry_data registry_data; + struct vega20_vbios_boot_state vbios_boot_state; + struct vega20_mclk_latency_table mclk_latency_table; + + struct vega20_max_sustainable_clocks max_sustainable_clocks; + + struct vega20_leakage_voltage vddc_leakage; + + uint32_t vddc_control; + struct pp_atomfwctrl_voltage_table vddc_voltage_table; + uint32_t mvdd_control; + struct pp_atomfwctrl_voltage_table mvdd_voltage_table; + uint32_t vddci_control; + struct pp_atomfwctrl_voltage_table vddci_voltage_table; + + uint32_t active_auto_throttle_sources; + struct vega20_bacos bacos; + + /* ---- General data ---- */ + uint8_t need_update_dpm_table; + + bool cac_enabled; + bool battery_state; + bool is_tlu_enabled; + bool avfs_exist; + + uint32_t low_sclk_interrupt_threshold; + + uint32_t total_active_cus; + + uint32_t water_marks_bitmap; + + struct vega20_display_timing display_timing; + + /* ---- Vega20 Dyn Register Settings ---- */ + + uint32_t debug_settings; + uint32_t lowest_uclk_reserved_for_ulv; + uint32_t gfxclk_average_alpha; + uint32_t socclk_average_alpha; + uint32_t uclk_average_alpha; + uint32_t gfx_activity_average_alpha; + uint32_t display_voltage_mode; + uint32_t dcef_clk_quad_eqn_a; + uint32_t dcef_clk_quad_eqn_b; + uint32_t dcef_clk_quad_eqn_c; + uint32_t disp_clk_quad_eqn_a; + uint32_t disp_clk_quad_eqn_b; + uint32_t disp_clk_quad_eqn_c; + uint32_t pixel_clk_quad_eqn_a; + uint32_t pixel_clk_quad_eqn_b; + uint32_t pixel_clk_quad_eqn_c; + uint32_t phy_clk_quad_eqn_a; + uint32_t phy_clk_quad_eqn_b; + uint32_t phy_clk_quad_eqn_c; + + /* ---- Thermal Temperature Setting ---- */ + struct vega20_dpmlevel_enable_mask dpm_level_enable_mask; + + /* ---- Power Gating States ---- */ + bool uvd_power_gated; + bool vce_power_gated; + bool samu_power_gated; + bool need_long_memory_training; + + /* Internal settings to apply the application power optimization parameters */ + bool apply_optimized_settings; + uint32_t disable_dpm_mask; + + /* ---- Overdrive next setting ---- */ + struct vega20_odn_data odn_data; + bool gfxclk_overdrive; + bool memclk_overdrive; + + /* ---- Overdrive8 Setting ---- */ + struct vega20_od8_settings od8_settings; + + /* ---- Workload Mask ---- */ + uint32_t workload_mask; + + /* ---- SMU9 ---- */ + uint32_t smu_version; + struct smu_features smu_features[GNLD_FEATURES_MAX]; + struct vega20_smc_state_table smc_state_table; + + /* ---- Gfxoff ---- */ + bool gfxoff_allowed; + uint32_t counter_gfxoff; + + unsigned long metrics_time; + SmuMetrics_t metrics_table; + struct gpu_metrics_v1_0 gpu_metrics_table; + + bool pcie_parameters_override; + uint32_t pcie_gen_level1; + uint32_t pcie_width_level1; + + bool is_custom_profile_set; +}; + +#define VEGA20_DPM2_NEAR_TDP_DEC 10 +#define VEGA20_DPM2_ABOVE_SAFE_INC 5 +#define VEGA20_DPM2_BELOW_SAFE_INC 20 + +#define VEGA20_DPM2_LTA_WINDOW_SIZE 7 + +#define VEGA20_DPM2_LTS_TRUNCATE 0 + +#define VEGA20_DPM2_TDP_SAFE_LIMIT_PERCENT 80 + +#define VEGA20_DPM2_MAXPS_PERCENT_M 90 +#define VEGA20_DPM2_MAXPS_PERCENT_H 90 + +#define VEGA20_DPM2_PWREFFICIENCYRATIO_MARGIN 50 + +#define VEGA20_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define VEGA20_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define VEGA20_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define VEGA20_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E +#define VEGA20_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF + +#define VEGA20_VOLTAGE_CONTROL_NONE 0x0 +#define VEGA20_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define VEGA20_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define VEGA20_VOLTAGE_CONTROL_MERGED 0x3 +/* To convert to Q8.8 format for firmware */ +#define VEGA20_Q88_FORMAT_CONVERSION_UNIT 256 + +#define VEGA20_UNUSED_GPIO_PIN 0x7F + +#define VEGA20_THERM_OUT_MODE_DISABLE 0x0 +#define VEGA20_THERM_OUT_MODE_THERM_ONLY 0x1 +#define VEGA20_THERM_OUT_MODE_THERM_VRHOT 0x2 + +#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff +#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff + +#define PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ +#define PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff +#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff +#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff + +#define VEGA20_UMD_PSTATE_GFXCLK_LEVEL 0x3 +#define VEGA20_UMD_PSTATE_SOCCLK_LEVEL 0x3 +#define VEGA20_UMD_PSTATE_MCLK_LEVEL 0x2 +#define VEGA20_UMD_PSTATE_UVDCLK_LEVEL 0x3 +#define VEGA20_UMD_PSTATE_VCEMCLK_LEVEL 0x3 + +#endif /* _VEGA20_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h new file mode 100644 index 000000000000..613cb1989b3d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_inc.h @@ -0,0 +1,36 @@ +/* + * Copyright 2018 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 VEGA20_INC_H +#define VEGA20_INC_H + +#include "asic_reg/thm/thm_11_0_2_offset.h" +#include "asic_reg/thm/thm_11_0_2_sh_mask.h" + +#include "asic_reg/mp/mp_9_0_offset.h" +#include "asic_reg/mp/mp_9_0_sh_mask.h" + +#include "asic_reg/nbio/nbio_7_4_offset.h" +#include "asic_reg/nbio/nbio_7_4_sh_mask.h" + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c new file mode 100644 index 000000000000..d7cc3d2d9e17 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.c @@ -0,0 +1,72 @@ +/* + * Copyright 2018 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 "hwmgr.h" +#include "vega20_hwmgr.h" +#include "vega20_powertune.h" +#include "vega20_smumgr.h" +#include "vega20_ppsmc.h" +#include "vega20_inc.h" +#include "pp_debug.h" + +int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) +{ + struct vega20_hwmgr *data = + (struct vega20_hwmgr *)(hwmgr->backend); + + if (data->smu_features[GNLD_PPT].enabled) + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetPptLimit, n, + NULL); + + return 0; +} + +int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr, + uint32_t tdp_percentage_adjustment, uint32_t tdp_absolute_value_adjustment) +{ + return (tdp_percentage_adjustment > hwmgr->platform_descriptor.TDPLimit) ? -1 : 0; +} + +static int vega20_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, + uint32_t adjust_percent) +{ + return smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_OverDriveSetPercentage, adjust_percent, + NULL); +} + +int vega20_power_control_set_level(struct pp_hwmgr *hwmgr) +{ + int adjust_percent, result = 0; + + if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { + adjust_percent = + hwmgr->platform_descriptor.TDPAdjustmentPolarity ? + hwmgr->platform_descriptor.TDPAdjustment : + (-1 * hwmgr->platform_descriptor.TDPAdjustment); + result = vega20_set_overdrive_target_percentage(hwmgr, + (uint32_t)adjust_percent); + } + return result; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h new file mode 100644 index 000000000000..d68c734c0f4e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_powertune.h @@ -0,0 +1,32 @@ +/* + * Copyright 2018 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 _VEGA20_POWERTUNE_H_ +#define _VEGA20_POWERTUNE_H_ + +int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); +int vega20_power_control_set_level(struct pp_hwmgr *hwmgr); +int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr, + uint32_t tdp_percentage_adjustment, + uint32_t tdp_absolute_value_adjustment); +#endif /* _VEGA20_POWERTUNE_H_ */ + diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h new file mode 100644 index 000000000000..2222e29405c6 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_pptable.h @@ -0,0 +1,142 @@ +/* + * Copyright 2018 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 _VEGA20_PPTABLE_H_ +#define _VEGA20_PPTABLE_H_ + +#pragma pack(push, 1) + +#define ATOM_VEGA20_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_VEGA20_PP_THERMALCONTROLLER_VEGA20 26 + +#define ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY 0x1 +#define ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 +#define ATOM_VEGA20_PP_PLATFORM_CAP_HARDWAREDC 0x4 +#define ATOM_VEGA20_PP_PLATFORM_CAP_BACO 0x8 +#define ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO 0x10 +#define ATOM_VEGA20_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20 + +#define ATOM_VEGA20_TABLE_REVISION_VEGA20 11 +#define ATOM_VEGA20_ODFEATURE_MAX_COUNT 32 +#define ATOM_VEGA20_ODSETTING_MAX_COUNT 32 +#define ATOM_VEGA20_PPCLOCK_MAX_COUNT 16 + +enum ATOM_VEGA20_ODFEATURE_ID { + ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS = 0, + ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE, + ATOM_VEGA20_ODFEATURE_UCLK_MAX, + ATOM_VEGA20_ODFEATURE_POWER_LIMIT, + ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT, //FanMaximumRpm + ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN, //FanMinimumPwm + ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN, //FanTargetTemperature + ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM, //MaxOpTemp + ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE, + ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL, + ATOM_VEGA20_ODFEATURE_COUNT, +}; + +enum ATOM_VEGA20_ODSETTING_ID { + ATOM_VEGA20_ODSETTING_GFXCLKFMAX = 0, + ATOM_VEGA20_ODSETTING_GFXCLKFMIN, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P1, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P2, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P3, + ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3, + ATOM_VEGA20_ODSETTING_UCLKFMAX, + ATOM_VEGA20_ODSETTING_POWERPERCENTAGE, + ATOM_VEGA20_ODSETTING_FANRPMMIN, + ATOM_VEGA20_ODSETTING_FANRPMACOUSTICLIMIT, + ATOM_VEGA20_ODSETTING_FANTARGETTEMPERATURE, + ATOM_VEGA20_ODSETTING_OPERATINGTEMPMAX, + ATOM_VEGA20_ODSETTING_COUNT, +}; +typedef enum ATOM_VEGA20_ODSETTING_ID ATOM_VEGA20_ODSETTING_ID; + +typedef struct _ATOM_VEGA20_OVERDRIVE8_RECORD +{ + UCHAR ucODTableRevision; + ULONG ODFeatureCount; + UCHAR ODFeatureCapabilities [ATOM_VEGA20_ODFEATURE_MAX_COUNT]; //OD feature support flags + ULONG ODSettingCount; + ULONG ODSettingsMax [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Upper Limit for each OD Setting + ULONG ODSettingsMin [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Lower Limit for each OD Setting +} ATOM_VEGA20_OVERDRIVE8_RECORD; + +enum ATOM_VEGA20_PPCLOCK_ID { + ATOM_VEGA20_PPCLOCK_GFXCLK = 0, + ATOM_VEGA20_PPCLOCK_VCLK, + ATOM_VEGA20_PPCLOCK_DCLK, + ATOM_VEGA20_PPCLOCK_ECLK, + ATOM_VEGA20_PPCLOCK_SOCCLK, + ATOM_VEGA20_PPCLOCK_UCLK, + ATOM_VEGA20_PPCLOCK_FCLK, + ATOM_VEGA20_PPCLOCK_DCEFCLK, + ATOM_VEGA20_PPCLOCK_DISPCLK, + ATOM_VEGA20_PPCLOCK_PIXCLK, + ATOM_VEGA20_PPCLOCK_PHYCLK, + ATOM_VEGA20_PPCLOCK_COUNT, +}; +typedef enum ATOM_VEGA20_PPCLOCK_ID ATOM_VEGA20_PPCLOCK_ID; + +typedef struct _ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD +{ + UCHAR ucTableRevision; + ULONG PowerSavingClockCount; // Count of PowerSavingClock Mode + ULONG PowerSavingClockMax [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Maximum array In MHz + ULONG PowerSavingClockMin [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Minimum array In MHz +} ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD; + +typedef struct _ATOM_VEGA20_POWERPLAYTABLE +{ + struct atom_common_table_header sHeader; + UCHAR ucTableRevision; + USHORT usTableSize; + ULONG ulGoldenPPID; + ULONG ulGoldenRevision; + USHORT usFormatID; + + ULONG ulPlatformCaps; + + UCHAR ucThermalControllerType; + + USHORT usSmallPowerLimit1; + USHORT usSmallPowerLimit2; + USHORT usBoostPowerLimit; + USHORT usODTurboPowerLimit; + USHORT usODPowerSavePowerLimit; + USHORT usSoftwareShutdownTemp; + + ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD PowerSavingClockTable; //PowerSavingClock Mode Clock Min/Max array + + ATOM_VEGA20_OVERDRIVE8_RECORD OverDrive8Table; //OverDrive8 Feature capabilities and Settings Range (Max and Min) + + USHORT usReserve[5]; + + PPTable_t smcPPTable; + +} ATOM_Vega20_POWERPLAYTABLE; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c new file mode 100644 index 000000000000..f56a3cbdfa3b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c @@ -0,0 +1,972 @@ +/* + * Copyright 2018 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 +#include +#include + +#include "smu11_driver_if.h" +#include "vega20_processpptables.h" +#include "ppatomfwctrl.h" +#include "atomfirmware.h" +#include "pp_debug.h" +#include "cgs_common.h" +#include "vega20_pptable.h" + +#define VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE 105 + +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, + enum phm_platform_caps cap) +{ + if (enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + +static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterDataTable(powerplayinfo); + + u16 size; + u8 frev, crev; + const void *table_address = hwmgr->soft_pp_table; + + if (!table_address) { + table_address = (ATOM_Vega20_POWERPLAYTABLE *) + smu_atom_get_data_table(hwmgr->adev, index, + &size, &frev, &crev); + + hwmgr->soft_pp_table = table_address; + hwmgr->soft_pp_table_size = size; + } + + return table_address; +} + +#if 0 +static void dump_pptable(PPTable_t *pptable) +{ + int i; + + pr_info("Version = 0x%08x\n", pptable->Version); + + pr_info("FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); + pr_info("FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); + + pr_info("SocketPowerLimitAc0 = %d\n", pptable->SocketPowerLimitAc0); + pr_info("SocketPowerLimitAc0Tau = %d\n", pptable->SocketPowerLimitAc0Tau); + pr_info("SocketPowerLimitAc1 = %d\n", pptable->SocketPowerLimitAc1); + pr_info("SocketPowerLimitAc1Tau = %d\n", pptable->SocketPowerLimitAc1Tau); + pr_info("SocketPowerLimitAc2 = %d\n", pptable->SocketPowerLimitAc2); + pr_info("SocketPowerLimitAc2Tau = %d\n", pptable->SocketPowerLimitAc2Tau); + pr_info("SocketPowerLimitAc3 = %d\n", pptable->SocketPowerLimitAc3); + pr_info("SocketPowerLimitAc3Tau = %d\n", pptable->SocketPowerLimitAc3Tau); + pr_info("SocketPowerLimitDc = %d\n", pptable->SocketPowerLimitDc); + pr_info("SocketPowerLimitDcTau = %d\n", pptable->SocketPowerLimitDcTau); + pr_info("TdcLimitSoc = %d\n", pptable->TdcLimitSoc); + pr_info("TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau); + pr_info("TdcLimitGfx = %d\n", pptable->TdcLimitGfx); + pr_info("TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau); + + pr_info("TedgeLimit = %d\n", pptable->TedgeLimit); + pr_info("ThotspotLimit = %d\n", pptable->ThotspotLimit); + pr_info("ThbmLimit = %d\n", pptable->ThbmLimit); + pr_info("Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit); + pr_info("Tvr_memLimit = %d\n", pptable->Tvr_memLimit); + pr_info("Tliquid1Limit = %d\n", pptable->Tliquid1Limit); + pr_info("Tliquid2Limit = %d\n", pptable->Tliquid2Limit); + pr_info("TplxLimit = %d\n", pptable->TplxLimit); + pr_info("FitLimit = %d\n", pptable->FitLimit); + + pr_info("PpmPowerLimit = %d\n", pptable->PpmPowerLimit); + pr_info("PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold); + + pr_info("MemoryOnPackage = 0x%02x\n", pptable->MemoryOnPackage); + pr_info("padding8_limits = 0x%02x\n", pptable->padding8_limits); + pr_info("Tvr_SocLimit = %d\n", pptable->Tvr_SocLimit); + + pr_info("UlvVoltageOffsetSoc = %d\n", pptable->UlvVoltageOffsetSoc); + pr_info("UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx); + + pr_info("UlvSmnclkDid = %d\n", pptable->UlvSmnclkDid); + pr_info("UlvMp1clkDid = %d\n", pptable->UlvMp1clkDid); + pr_info("UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass); + pr_info("Padding234 = 0x%02x\n", pptable->Padding234); + + pr_info("MinVoltageGfx = %d\n", pptable->MinVoltageGfx); + pr_info("MinVoltageSoc = %d\n", pptable->MinVoltageSoc); + pr_info("MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx); + pr_info("MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc); + + pr_info("LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx); + pr_info("LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc); + + pr_info("[PPCLK_GFXCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_GFXCLK].padding, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c); + + pr_info("[PPCLK_VCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_VCLK].padding, + pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c); + + pr_info("[PPCLK_DCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DCLK].padding, + pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c); + + pr_info("[PPCLK_ECLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_ECLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_ECLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_ECLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_ECLK].padding, + pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.c); + + pr_info("[PPCLK_SOCCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_SOCCLK].padding, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c); + + pr_info("[PPCLK_UCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_UCLK].padding, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c); + + pr_info("[PPCLK_DCEFCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_DCEFCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DCEFCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DCEFCLK].padding, + pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.c); + + pr_info("[PPCLK_DISPCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_DISPCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DISPCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DISPCLK].padding, + pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.c); + + pr_info("[PPCLK_PIXCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_PIXCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_PIXCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_PIXCLK].padding, + pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.c); + + pr_info("[PPCLK_PHYCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_PHYCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_PHYCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_PHYCLK].padding, + pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.c); + + pr_info("[PPCLK_FCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", + pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_FCLK].padding, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c); + + + pr_info("FreqTableGfx\n"); + for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableGfx[i]); + + pr_info("FreqTableVclk\n"); + for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableVclk[i]); + + pr_info("FreqTableDclk\n"); + for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDclk[i]); + + pr_info("FreqTableEclk\n"); + for (i = 0; i < NUM_ECLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableEclk[i]); + + pr_info("FreqTableSocclk\n"); + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]); + + pr_info("FreqTableUclk\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableUclk[i]); + + pr_info("FreqTableFclk\n"); + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableFclk[i]); + + pr_info("FreqTableDcefclk\n"); + for (i = 0; i < NUM_DCEFCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDcefclk[i]); + + pr_info("FreqTableDispclk\n"); + for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDispclk[i]); + + pr_info("FreqTablePixclk\n"); + for (i = 0; i < NUM_PIXCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePixclk[i]); + + pr_info("FreqTablePhyclk\n"); + for (i = 0; i < NUM_PHYCLK_DPM_LEVELS; i++) + pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePhyclk[i]); + + pr_info("DcModeMaxFreq[PPCLK_GFXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]); + pr_info("DcModeMaxFreq[PPCLK_VCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_VCLK]); + pr_info("DcModeMaxFreq[PPCLK_DCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCLK]); + pr_info("DcModeMaxFreq[PPCLK_ECLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_ECLK]); + pr_info("DcModeMaxFreq[PPCLK_SOCCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]); + pr_info("DcModeMaxFreq[PPCLK_UCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_UCLK]); + pr_info("DcModeMaxFreq[PPCLK_DCEFCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCEFCLK]); + pr_info("DcModeMaxFreq[PPCLK_DISPCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DISPCLK]); + pr_info("DcModeMaxFreq[PPCLK_PIXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PIXCLK]); + pr_info("DcModeMaxFreq[PPCLK_PHYCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PHYCLK]); + pr_info("DcModeMaxFreq[PPCLK_FCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_FCLK]); + pr_info("Padding8_Clks = %d\n", pptable->Padding8_Clks); + + pr_info("Mp0clkFreq\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->Mp0clkFreq[i]); + + pr_info("Mp0DpmVoltage\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]); + + pr_info("GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); + pr_info("GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate); + pr_info("CksEnableFreq = 0x%x\n", pptable->CksEnableFreq); + pr_info("Padding789 = 0x%x\n", pptable->Padding789); + pr_info("CksVoltageOffset[a = 0x%08x b = 0x%08x c = 0x%08x]\n", + pptable->CksVoltageOffset.a, + pptable->CksVoltageOffset.b, + pptable->CksVoltageOffset.c); + pr_info("Padding567[0] = 0x%x\n", pptable->Padding567[0]); + pr_info("Padding567[1] = 0x%x\n", pptable->Padding567[1]); + pr_info("Padding567[2] = 0x%x\n", pptable->Padding567[2]); + pr_info("Padding567[3] = 0x%x\n", pptable->Padding567[3]); + pr_info("GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq); + pr_info("GfxclkSource = 0x%x\n", pptable->GfxclkSource); + pr_info("Padding456 = 0x%x\n", pptable->Padding456); + + pr_info("LowestUclkReservedForUlv = %d\n", pptable->LowestUclkReservedForUlv); + pr_info("Padding8_Uclk[0] = 0x%x\n", pptable->Padding8_Uclk[0]); + pr_info("Padding8_Uclk[1] = 0x%x\n", pptable->Padding8_Uclk[1]); + pr_info("Padding8_Uclk[2] = 0x%x\n", pptable->Padding8_Uclk[2]); + + pr_info("PcieGenSpeed\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->PcieGenSpeed[i]); + + pr_info("PcieLaneCount\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->PcieLaneCount[i]); + + pr_info("LclkFreq\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->LclkFreq[i]); + + pr_info("EnableTdpm = %d\n", pptable->EnableTdpm); + pr_info("TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature); + pr_info("TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature); + pr_info("GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit); + + pr_info("FanStopTemp = %d\n", pptable->FanStopTemp); + pr_info("FanStartTemp = %d\n", pptable->FanStartTemp); + + pr_info("FanGainEdge = %d\n", pptable->FanGainEdge); + pr_info("FanGainHotspot = %d\n", pptable->FanGainHotspot); + pr_info("FanGainLiquid = %d\n", pptable->FanGainLiquid); + pr_info("FanGainVrGfx = %d\n", pptable->FanGainVrGfx); + pr_info("FanGainVrSoc = %d\n", pptable->FanGainVrSoc); + pr_info("FanGainPlx = %d\n", pptable->FanGainPlx); + pr_info("FanGainHbm = %d\n", pptable->FanGainHbm); + pr_info("FanPwmMin = %d\n", pptable->FanPwmMin); + pr_info("FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm); + pr_info("FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm); + pr_info("FanMaximumRpm = %d\n", pptable->FanMaximumRpm); + pr_info("FanTargetTemperature = %d\n", pptable->FanTargetTemperature); + pr_info("FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk); + pr_info("FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable); + pr_info("FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev); + + pr_info("FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta); + pr_info("FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta); + pr_info("FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta); + pr_info("FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved); + + pr_info("OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); + pr_info("OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); + pr_info("Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]); + pr_info("Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]); + + pr_info("qAvfsGb[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].a, + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].b, + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].c); + pr_info("qAvfsGb[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].a, + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].b, + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].c); + pr_info("dBtcGbGfxCksOn{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxCksOn.a, + pptable->dBtcGbGfxCksOn.b, + pptable->dBtcGbGfxCksOn.c); + pr_info("dBtcGbGfxCksOff{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxCksOff.a, + pptable->dBtcGbGfxCksOff.b, + pptable->dBtcGbGfxCksOff.c); + pr_info("dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxAfll.a, + pptable->dBtcGbGfxAfll.b, + pptable->dBtcGbGfxAfll.c); + pr_info("dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbSoc.a, + pptable->dBtcGbSoc.b, + pptable->dBtcGbSoc.c); + pr_info("qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, + pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); + pr_info("qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, + pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); + + pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); + pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); + + pr_info("DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); + pr_info("DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); + + pr_info("DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); + pr_info("DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); + pr_info("Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); + pr_info("Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); + + pr_info("DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); + pr_info("DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); + pr_info("DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); + pr_info("DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); + + pr_info("XgmiLinkSpeed\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]); + pr_info("XgmiLinkWidth\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]); + pr_info("XgmiFclkFreq\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]); + pr_info("XgmiUclkFreq\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiUclkFreq[i]); + pr_info("XgmiSocclkFreq\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiSocclkFreq[i]); + pr_info("XgmiSocVoltage\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + pr_info(" .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]); + + pr_info("DebugOverrides = 0x%x\n", pptable->DebugOverrides); + pr_info("ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation0.a, + pptable->ReservedEquation0.b, + pptable->ReservedEquation0.c); + pr_info("ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation1.a, + pptable->ReservedEquation1.b, + pptable->ReservedEquation1.c); + pr_info("ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation2.a, + pptable->ReservedEquation2.b, + pptable->ReservedEquation2.c); + pr_info("ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation3.a, + pptable->ReservedEquation3.b, + pptable->ReservedEquation3.c); + + pr_info("MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx); + pr_info("MinVoltageUlvSoc = %d\n", pptable->MinVoltageUlvSoc); + + pr_info("MGpuFanBoostLimitRpm = %d\n", pptable->MGpuFanBoostLimitRpm); + pr_info("padding16_Fan = %d\n", pptable->padding16_Fan); + + pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0); + pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0); + + pr_info("DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); + pr_info("DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); + + for (i = 0; i < 11; i++) + pr_info("Reserved[%d] = 0x%x\n", i, pptable->Reserved[i]); + + for (i = 0; i < 3; i++) + pr_info("Padding32[%d] = 0x%x\n", i, pptable->Padding32[i]); + + pr_info("MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx); + pr_info("MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc); + + pr_info("VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); + pr_info("VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); + pr_info("VddMem0VrMapping = 0x%x\n", pptable->VddMem0VrMapping); + pr_info("VddMem1VrMapping = 0x%x\n", pptable->VddMem1VrMapping); + + pr_info("GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); + pr_info("SocUlvPhaseSheddingMask = 0x%x\n", pptable->SocUlvPhaseSheddingMask); + pr_info("ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent); + pr_info("Padding8_V = 0x%x\n", pptable->Padding8_V); + + pr_info("GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); + pr_info("GfxOffset = 0x%x\n", pptable->GfxOffset); + pr_info("Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); + + pr_info("SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); + pr_info("SocOffset = 0x%x\n", pptable->SocOffset); + pr_info("Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); + + pr_info("Mem0MaxCurrent = 0x%x\n", pptable->Mem0MaxCurrent); + pr_info("Mem0Offset = 0x%x\n", pptable->Mem0Offset); + pr_info("Padding_TelemetryMem0 = 0x%x\n", pptable->Padding_TelemetryMem0); + + pr_info("Mem1MaxCurrent = 0x%x\n", pptable->Mem1MaxCurrent); + pr_info("Mem1Offset = 0x%x\n", pptable->Mem1Offset); + pr_info("Padding_TelemetryMem1 = 0x%x\n", pptable->Padding_TelemetryMem1); + + pr_info("AcDcGpio = %d\n", pptable->AcDcGpio); + pr_info("AcDcPolarity = %d\n", pptable->AcDcPolarity); + pr_info("VR0HotGpio = %d\n", pptable->VR0HotGpio); + pr_info("VR0HotPolarity = %d\n", pptable->VR0HotPolarity); + + pr_info("VR1HotGpio = %d\n", pptable->VR1HotGpio); + pr_info("VR1HotPolarity = %d\n", pptable->VR1HotPolarity); + pr_info("Padding1 = 0x%x\n", pptable->Padding1); + pr_info("Padding2 = 0x%x\n", pptable->Padding2); + + pr_info("LedPin0 = %d\n", pptable->LedPin0); + pr_info("LedPin1 = %d\n", pptable->LedPin1); + pr_info("LedPin2 = %d\n", pptable->LedPin2); + pr_info("padding8_4 = 0x%x\n", pptable->padding8_4); + + pr_info("PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled); + pr_info("PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent); + pr_info("PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq); + + pr_info("UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled); + pr_info("UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent); + pr_info("UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq); + + pr_info("FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled); + pr_info("FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent); + pr_info("FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq); + + pr_info("FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled); + pr_info("FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent); + pr_info("FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq); + + for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { + pr_info("I2cControllers[%d]:\n", i); + pr_info(" .Enabled = %d\n", + pptable->I2cControllers[i].Enabled); + pr_info(" .SlaveAddress = 0x%x\n", + pptable->I2cControllers[i].SlaveAddress); + pr_info(" .ControllerPort = %d\n", + pptable->I2cControllers[i].ControllerPort); + pr_info(" .ControllerName = %d\n", + pptable->I2cControllers[i].ControllerName); + pr_info(" .ThermalThrottler = %d\n", + pptable->I2cControllers[i].ThermalThrottler); + pr_info(" .I2cProtocol = %d\n", + pptable->I2cControllers[i].I2cProtocol); + pr_info(" .I2cSpeed = %d\n", + pptable->I2cControllers[i].I2cSpeed); + } + + for (i = 0; i < 10; i++) + pr_info("BoardReserved[%d] = 0x%x\n", i, pptable->BoardReserved[i]); + + for (i = 0; i < 8; i++) + pr_info("MmHubPadding[%d] = 0x%x\n", i, pptable->MmHubPadding[i]); +} +#endif + +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Vega20_POWERPLAYTABLE *powerplay_table) +{ + PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= + ATOM_VEGA20_TABLE_REVISION_VEGA20), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, + "Invalid PowerPlay Table!", return -1); + + if (powerplay_table->smcPPTable.Version != PPTABLE_V20_SMU_VERSION) { + pr_info("Unmatch PPTable version: " + "pptable from VBIOS is V%d while driver supported is V%d!", + powerplay_table->smcPPTable.Version, + PPTABLE_V20_SMU_VERSION); + return -EINVAL; + } + + //dump_pptable(&powerplay_table->smcPPTable); + + return 0; +} + +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO), + PHM_PlatformCaps_BAMACO); + + return 0; +} + +static int copy_overdrive_feature_capabilities_array( + struct pp_hwmgr *hwmgr, + uint8_t **pptable_info_array, + const uint8_t *pptable_array, + uint8_t od_feature_count) +{ + uint32_t array_size, i; + uint8_t *table; + bool od_supported = false; + + array_size = sizeof(uint8_t) * od_feature_count; + table = kzalloc(array_size, GFP_KERNEL); + if (NULL == table) + return -ENOMEM; + + for (i = 0; i < od_feature_count; i++) { + table[i] = le32_to_cpu(pptable_array[i]); + if (table[i]) + od_supported = true; + } + + *pptable_info_array = table; + + if (od_supported) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ACOverdriveSupport); + + return 0; +} + +static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable) +{ + struct atom_smc_dpm_info_v4_4 *smc_dpm_table; + int index = GetIndexIntoMasterDataTable(smc_dpm_info); + int i; + + PP_ASSERT_WITH_CODE( + smc_dpm_table = smu_atom_get_data_table(hwmgr->adev, index, NULL, NULL, NULL), + "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", + return -1); + + ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; + ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; + + ppsmc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping; + ppsmc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping; + ppsmc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping; + ppsmc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping; + + ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask; + ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask; + ppsmc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent; + + ppsmc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent; + ppsmc_pptable->GfxOffset = smc_dpm_table->gfxoffset; + ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx; + + ppsmc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent; + ppsmc_pptable->SocOffset = smc_dpm_table->socoffset; + ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc; + + ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent; + ppsmc_pptable->Mem0Offset = smc_dpm_table->mem0offset; + ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0; + + ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent; + ppsmc_pptable->Mem1Offset = smc_dpm_table->mem1offset; + ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1; + + ppsmc_pptable->AcDcGpio = smc_dpm_table->acdcgpio; + ppsmc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity; + ppsmc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio; + ppsmc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity; + + ppsmc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio; + ppsmc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity; + ppsmc_pptable->Padding1 = smc_dpm_table->padding1; + ppsmc_pptable->Padding2 = smc_dpm_table->padding2; + + ppsmc_pptable->LedPin0 = smc_dpm_table->ledpin0; + ppsmc_pptable->LedPin1 = smc_dpm_table->ledpin1; + ppsmc_pptable->LedPin2 = smc_dpm_table->ledpin2; + + ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled; + ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent; + ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq; + + ppsmc_pptable->UclkSpreadEnabled = 0; + ppsmc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent; + ppsmc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq; + + ppsmc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled; + ppsmc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent; + ppsmc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq; + + ppsmc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled; + ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; + ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; + + for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { + ppsmc_pptable->I2cControllers[i].Enabled = + smc_dpm_table->i2ccontrollers[i].enabled; + ppsmc_pptable->I2cControllers[i].SlaveAddress = + smc_dpm_table->i2ccontrollers[i].slaveaddress; + ppsmc_pptable->I2cControllers[i].ControllerPort = + smc_dpm_table->i2ccontrollers[i].controllerport; + ppsmc_pptable->I2cControllers[i].ThermalThrottler = + smc_dpm_table->i2ccontrollers[i].thermalthrottler; + ppsmc_pptable->I2cControllers[i].I2cProtocol = + smc_dpm_table->i2ccontrollers[i].i2cprotocol; + ppsmc_pptable->I2cControllers[i].I2cSpeed = + smc_dpm_table->i2ccontrollers[i].i2cspeed; + } + + return 0; +} + +static int override_powerplay_table_fantargettemperature(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + PPTable_t *ppsmc_pptable = (PPTable_t *)(pptable_information->smc_pptable); + + ppsmc_pptable->FanTargetTemperature = VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE; + + return 0; +} + +#define VEGA20_ENGINECLOCK_HARDMAX 198000 +static int init_powerplay_table_information( + struct pp_hwmgr *hwmgr, + const ATOM_Vega20_POWERPLAYTABLE *powerplay_table) +{ + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; + uint32_t disable_power_control = 0; + uint32_t od_feature_count, od_setting_count, power_saving_clock_count; + int result; + + hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType; + pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType; + hwmgr->thermal_controller.fanInfo.ulMinRPM = 0; + hwmgr->thermal_controller.fanInfo.ulMaxRPM = powerplay_table->smcPPTable.FanMaximumRpm; + + set_hw_cap(hwmgr, + ATOM_VEGA20_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + + if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { + od_feature_count = + (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) > + ATOM_VEGA20_ODFEATURE_COUNT) ? + ATOM_VEGA20_ODFEATURE_COUNT : + le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount); + od_setting_count = + (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) > + ATOM_VEGA20_ODSETTING_COUNT) ? + ATOM_VEGA20_ODSETTING_COUNT : + le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount); + + copy_overdrive_feature_capabilities_array(hwmgr, + &pptable_information->od_feature_capabilities, + powerplay_table->OverDrive8Table.ODFeatureCapabilities, + od_feature_count); + phm_copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_max, + powerplay_table->OverDrive8Table.ODSettingsMax, + od_setting_count); + phm_copy_overdrive_settings_limits_array(hwmgr, + &pptable_information->od_settings_min, + powerplay_table->OverDrive8Table.ODSettingsMin, + od_setting_count); + } + + pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1); + pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2); + pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit); + pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit); + pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit); + + pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp); + + hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]); + + disable_power_control = 0; + if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit) + /* enable TDP overdrive (PowerControl) feature as well if supported */ + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerControl); + + if (powerplay_table->PowerSavingClockTable.ucTableRevision == 1) { + power_saving_clock_count = + (le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount) >= + ATOM_VEGA20_PPCLOCK_COUNT) ? + ATOM_VEGA20_PPCLOCK_COUNT : + le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount); + phm_copy_clock_limits_array(hwmgr, + &pptable_information->power_saving_clock_max, + powerplay_table->PowerSavingClockTable.PowerSavingClockMax, + power_saving_clock_count); + phm_copy_clock_limits_array(hwmgr, + &pptable_information->power_saving_clock_min, + powerplay_table->PowerSavingClockTable.PowerSavingClockMin, + power_saving_clock_count); + } + + pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); + if (pptable_information->smc_pptable == NULL) + return -ENOMEM; + + memcpy(pptable_information->smc_pptable, + &(powerplay_table->smcPPTable), + sizeof(PPTable_t)); + + + result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); + if (result) + return result; + + result = override_powerplay_table_fantargettemperature(hwmgr); + + return result; +} + +static int vega20_pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Vega20_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL); + PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), + "Failed to allocate hwmgr->pptable!", return -ENOMEM); + + powerplay_table = get_powerplay_table(hwmgr); + PP_ASSERT_WITH_CODE((powerplay_table != NULL), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_powerplay_table_information(hwmgr, powerplay_table); + PP_ASSERT_WITH_CODE((result == 0), + "init_powerplay_table_information failed", return result); + + return result; +} + +static int vega20_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v3_information *pp_table_info = + (struct phm_ppt_v3_information *)(hwmgr->pptable); + + kfree(pp_table_info->power_saving_clock_max); + pp_table_info->power_saving_clock_max = NULL; + + kfree(pp_table_info->power_saving_clock_min); + pp_table_info->power_saving_clock_min = NULL; + + kfree(pp_table_info->od_feature_capabilities); + pp_table_info->od_feature_capabilities = NULL; + + kfree(pp_table_info->od_settings_max); + pp_table_info->od_settings_max = NULL; + + kfree(pp_table_info->od_settings_min); + pp_table_info->od_settings_min = NULL; + + kfree(pp_table_info->smc_pptable); + pp_table_info->smc_pptable = NULL; + + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + + return 0; +} + +const struct pp_table_func vega20_pptable_funcs = { + .pptable_init = vega20_pp_tables_initialize, + .pptable_fini = vega20_pp_tables_uninitialize, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h new file mode 100644 index 000000000000..846c2cb40b35 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 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 VEGA20_PROCESSPPTABLES_H +#define VEGA20_PROCESSPPTABLES_H + +#include "hwmgr.h" + +extern const struct pp_table_func vega20_pptable_funcs; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c new file mode 100644 index 000000000000..7add2f60f49c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -0,0 +1,357 @@ +/* + * Copyright 2018 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 "vega20_thermal.h" +#include "vega20_hwmgr.h" +#include "vega20_smumgr.h" +#include "vega20_ppsmc.h" +#include "vega20_inc.h" +#include "soc15_common.h" +#include "pp_debug.h" + +static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + int ret = 0; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + ret = vega20_enable_smc_features( + hwmgr, false, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap); + PP_ASSERT_WITH_CODE(!ret, + "Disable FAN CONTROL feature Failed!", + return ret); + data->smu_features[GNLD_FAN_CONTROL].enabled = false; + } + + return ret; +} + +int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) + return vega20_disable_fan_control_feature(hwmgr); + + return 0; +} + +static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + int ret = 0; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) { + ret = vega20_enable_smc_features( + hwmgr, true, + data->smu_features[GNLD_FAN_CONTROL]. + smu_feature_bitmap); + PP_ASSERT_WITH_CODE(!ret, + "Enable FAN CONTROL feature Failed!", + return ret); + data->smu_features[GNLD_FAN_CONTROL].enabled = true; + } + + return ret; +} + +int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + struct vega20_hwmgr *data = hwmgr->backend; + + if (data->smu_features[GNLD_FAN_CONTROL].supported) + return vega20_enable_fan_control_feature(hwmgr); + + return 0; +} + +static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + struct amdgpu_device *adev = hwmgr->adev; + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TMIN, 0)); + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, FDO_PWM_MODE, mode)); + + return 0; +} + +static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) +{ + int ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetCurrentRpm, + current_rpm)) == 0, + "Attempt to get current RPM from SMC Failed!", + return ret); + + return 0; +} + +int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed) +{ + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + PPTable_t *pp_table = &(data->smc_state_table.pp_table); + uint32_t current_rpm, percent = 0; + int ret = 0; + + ret = vega20_get_current_rpm(hwmgr, ¤t_rpm); + if (ret) + return ret; + + percent = current_rpm * 100 / pp_table->FanMaximumRpm; + + *speed = percent > 100 ? 100 : percent; + + return 0; +} + +int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (speed > 100) + speed = 100; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) + vega20_fan_ctrl_stop_smc_fan_control(hwmgr); + + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (uint64_t)speed * duty100; + do_div(tmp64, 100); + duty = (uint32_t)tmp64; + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); + + return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info) +{ + memset(fan_speed_info, 0, sizeof(*fan_speed_info)); + fan_speed_info->supports_percent_read = true; + fan_speed_info->supports_percent_write = true; + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + + return 0; +} + +int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + *speed = 0; + + return vega20_get_current_rpm(hwmgr, speed); +} + +int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t tach_period, crystal_clock_freq; + int result = 0; + + if (!speed) + return -EINVAL; + + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { + result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr); + if (result) + return result; + } + + crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); + WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, TARGET_PERIOD, + tach_period)); + + return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + int temp = 0; + + temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); + + temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> + CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; + + temp = temp & 0x1ff; + + temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for +* high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + struct amdgpu_device *adev = hwmgr->adev; + int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + uint32_t val; + + if (low < range->min) + low = range->min; + if (high > range->max) + high = range->max; + + if (low > high) + return -EINVAL; + + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t val = 0; + + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); + + return 0; +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); + + return 0; +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = vega20_thermal_disable_alert(hwmgr); + + return result; +} + +/** +* Set up the fan table to control the fan using the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + int ret; + struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + PPTable_t *table = &(data->smc_state_table.pp_table); + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanTemperatureTarget, + (uint32_t)table->FanTargetTemperature, + NULL); + + return ret; +} + +int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range) +{ + int ret = 0; + + if (range == NULL) + return -EINVAL; + + ret = vega20_thermal_set_temperature_range(hwmgr, range); + if (ret) + return ret; + + ret = vega20_thermal_enable_alert(hwmgr); + if (ret) + return ret; + + ret = vega20_thermal_setup_fan_table(hwmgr); + + return ret; +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h new file mode 100644 index 000000000000..2d1769bbd24e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.h @@ -0,0 +1,71 @@ +/* + * Copyright 2018 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 VEGA20_THERMAL_H +#define VEGA20_THERMAL_H + +#include "hwmgr.h" + +struct vega20_temperature { + uint16_t edge_temp; + uint16_t hot_spot_temp; + uint16_t hbm_temp; + uint16_t vr_soc_temp; + uint16_t vr_mem_temp; + uint16_t liquid1_temp; + uint16_t liquid2_temp; + uint16_t plx_temp; +}; + +#define VEGA20_THERMAL_HIGH_ALERT_MASK 0x1 +#define VEGA20_THERMAL_LOW_ALERT_MASK 0x2 + +#define VEGA20_THERMAL_MINIMUM_TEMP_READING -256 +#define VEGA20_THERMAL_MAXIMUM_TEMP_READING 255 + +#define VEGA20_THERMAL_MINIMUM_ALERT_TEMP 0 +#define VEGA20_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +extern int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info); +extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, + uint32_t *speed); +extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, + uint32_t speed); +extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed); +extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed); +extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); +extern int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr); +extern int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range); +extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c new file mode 100644 index 000000000000..4b3faaccecb9 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.c @@ -0,0 +1,3382 @@ +/* + * Copyright 2013 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 "amdgpu.h" +#include "amdgpu_pm.h" +#include "cikd.h" +#include "atom.h" +#include "amdgpu_atombios.h" +#include "amdgpu_dpm.h" +#include "kv_dpm.h" +#include "gfx_v7_0.h" +#include + +#include "smu/smu_7_0_0_d.h" +#include "smu/smu_7_0_0_sh_mask.h" + +#include "gca/gfx_7_2_d.h" +#include "gca/gfx_7_2_sh_mask.h" + +#define KV_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define KV_MINIMUM_ENGINE_CLOCK 800 +#define SMC_RAM_END 0x40000 + +static const struct amd_pm_funcs kv_dpm_funcs; + +static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev); +static int kv_enable_nb_dpm(struct amdgpu_device *adev, + bool enable); +static void kv_init_graphics_levels(struct amdgpu_device *adev); +static int kv_calculate_ds_divider(struct amdgpu_device *adev); +static int kv_calculate_nbps_level_settings(struct amdgpu_device *adev); +static int kv_calculate_dpm_settings(struct amdgpu_device *adev); +static void kv_enable_new_levels(struct amdgpu_device *adev); +static void kv_program_nbps_index_settings(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps); +static int kv_set_enabled_level(struct amdgpu_device *adev, u32 level); +static int kv_set_enabled_levels(struct amdgpu_device *adev); +static int kv_force_dpm_highest(struct amdgpu_device *adev); +static int kv_force_dpm_lowest(struct amdgpu_device *adev); +static void kv_apply_state_adjust_rules(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps, + struct amdgpu_ps *old_rps); +static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, + int min_temp, int max_temp); +static int kv_init_fps_limits(struct amdgpu_device *adev); + +static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate); +static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate); + + +static u32 kv_convert_vid2_to_vid7(struct amdgpu_device *adev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_2bit) +{ + struct amdgpu_clock_voltage_dependency_table *vddc_sclk_table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + if (vid_2bit < vddc_sclk_table->count) + return vddc_sclk_table->entries[vid_2bit].v; + else + return vddc_sclk_table->entries[vddc_sclk_table->count - 1].v; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_2bit == vid_2bit) + return vid_mapping_table->entries[i].vid_7bit; + } + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_7bit; + } +} + +static u32 kv_convert_vid7_to_vid2(struct amdgpu_device *adev, + struct sumo_vid_mapping_table *vid_mapping_table, + u32 vid_7bit) +{ + struct amdgpu_clock_voltage_dependency_table *vddc_sclk_table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 i; + + if (vddc_sclk_table && vddc_sclk_table->count) { + for (i = 0; i < vddc_sclk_table->count; i++) { + if (vddc_sclk_table->entries[i].v == vid_7bit) + return i; + } + return vddc_sclk_table->count - 1; + } else { + for (i = 0; i < vid_mapping_table->num_entries; i++) { + if (vid_mapping_table->entries[i].vid_7bit == vid_7bit) + return vid_mapping_table->entries[i].vid_2bit; + } + + return vid_mapping_table->entries[vid_mapping_table->num_entries - 1].vid_2bit; + } +} + +static void sumo_take_smu_control(struct amdgpu_device *adev, bool enable) +{ +/* This bit selects who handles display phy powergating. + * Clear the bit to let atom handle it. + * Set it to let the driver handle it. + * For now we just let atom handle it. + */ +#if 0 + u32 v = RREG32(mmDOUT_SCRATCH3); + + if (enable) + v |= 0x4; + else + v &= 0xFFFFFFFB; + + WREG32(mmDOUT_SCRATCH3, v); +#endif +} + +static void sumo_construct_sclk_voltage_mapping_table(struct amdgpu_device *adev, + struct sumo_sclk_voltage_mapping_table *sclk_voltage_mapping_table, + ATOM_AVAILABLE_SCLK_LIST *table) +{ + u32 i; + u32 n = 0; + u32 prev_sclk = 0; + + for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { + if (table[i].ulSupportedSCLK > prev_sclk) { + sclk_voltage_mapping_table->entries[n].sclk_frequency = + table[i].ulSupportedSCLK; + sclk_voltage_mapping_table->entries[n].vid_2bit = + table[i].usVoltageIndex; + prev_sclk = table[i].ulSupportedSCLK; + n++; + } + } + + sclk_voltage_mapping_table->num_max_dpm_entries = n; +} + +static void sumo_construct_vid_mapping_table(struct amdgpu_device *adev, + struct sumo_vid_mapping_table *vid_mapping_table, + ATOM_AVAILABLE_SCLK_LIST *table) +{ + u32 i, j; + + for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) { + if (table[i].ulSupportedSCLK != 0) { + vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit = + table[i].usVoltageID; + vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit = + table[i].usVoltageIndex; + } + } + + for (i = 0; i < SUMO_MAX_NUMBER_VOLTAGES; i++) { + if (vid_mapping_table->entries[i].vid_7bit == 0) { + for (j = i + 1; j < SUMO_MAX_NUMBER_VOLTAGES; j++) { + if (vid_mapping_table->entries[j].vid_7bit != 0) { + vid_mapping_table->entries[i] = + vid_mapping_table->entries[j]; + vid_mapping_table->entries[j].vid_7bit = 0; + break; + } + } + + if (j == SUMO_MAX_NUMBER_VOLTAGES) + break; + } + } + + vid_mapping_table->num_entries = i; +} + +#if 0 +static const struct kv_lcac_config_values sx_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 1, 4, 1 }, + { 2, 5, 1 }, + { 3, 4, 2 }, + { 4, 1, 1 }, + { 5, 5, 2 }, + { 6, 6, 1 }, + { 7, 9, 2 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_values mc0_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_values mc1_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_values mc2_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_values mc3_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_values cpl_local_cac_cfg_kv[] = +{ + { 0, 4, 1 }, + { 1, 4, 1 }, + { 2, 5, 1 }, + { 3, 4, 1 }, + { 4, 1, 1 }, + { 5, 5, 1 }, + { 6, 6, 1 }, + { 7, 9, 1 }, + { 8, 4, 1 }, + { 9, 2, 1 }, + { 10, 3, 1 }, + { 11, 6, 1 }, + { 12, 8, 2 }, + { 13, 1, 1 }, + { 14, 2, 1 }, + { 15, 3, 1 }, + { 16, 1, 1 }, + { 17, 4, 1 }, + { 18, 3, 1 }, + { 19, 1, 1 }, + { 20, 8, 1 }, + { 21, 5, 1 }, + { 22, 1, 1 }, + { 23, 1, 1 }, + { 24, 4, 1 }, + { 27, 6, 1 }, + { 28, 1, 1 }, + { 0xffffffff } +}; + +static const struct kv_lcac_config_reg sx0_cac_config_reg[] = +{ + { 0xc0400d00, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; + +static const struct kv_lcac_config_reg mc0_cac_config_reg[] = +{ + { 0xc0400d30, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; + +static const struct kv_lcac_config_reg mc1_cac_config_reg[] = +{ + { 0xc0400d3c, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; + +static const struct kv_lcac_config_reg mc2_cac_config_reg[] = +{ + { 0xc0400d48, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; + +static const struct kv_lcac_config_reg mc3_cac_config_reg[] = +{ + { 0xc0400d54, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; + +static const struct kv_lcac_config_reg cpl_cac_config_reg[] = +{ + { 0xc0400d80, 0x003e0000, 17, 0x3fc00000, 22, 0x0001fffe, 1, 0x00000001, 0 } +}; +#endif + +static const struct kv_pt_config_reg didt_config_kv[] = +{ + { 0x10, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x10, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x10, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x10, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x11, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x11, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x11, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x11, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x12, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x12, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x12, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x12, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x2, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, + { 0x2, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, + { 0x2, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, + { 0x1, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x1, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x0, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x30, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x30, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x30, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x30, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x31, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x31, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x31, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x31, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x32, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x32, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x32, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x32, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x22, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, + { 0x22, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, + { 0x22, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, + { 0x21, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x21, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x20, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x50, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x50, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x50, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x50, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x51, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x51, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x51, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x51, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x52, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x52, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x52, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x52, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x42, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, + { 0x42, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, + { 0x42, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, + { 0x41, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x41, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x40, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x70, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x70, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x70, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x70, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x71, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x71, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x71, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x71, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x72, 0x000000ff, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x72, 0x0000ff00, 8, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x72, 0x00ff0000, 16, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x72, 0xff000000, 24, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0x62, 0x00003fff, 0, 0x4, KV_CONFIGREG_DIDT_IND }, + { 0x62, 0x03ff0000, 16, 0x80, KV_CONFIGREG_DIDT_IND }, + { 0x62, 0x78000000, 27, 0x3, KV_CONFIGREG_DIDT_IND }, + { 0x61, 0x0000ffff, 0, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x61, 0xffff0000, 16, 0x3FFF, KV_CONFIGREG_DIDT_IND }, + { 0x60, 0x00000001, 0, 0x0, KV_CONFIGREG_DIDT_IND }, + { 0xFFFFFFFF } +}; + +static struct kv_ps *kv_get_ps(struct amdgpu_ps *rps) +{ + struct kv_ps *ps = rps->ps_priv; + + return ps; +} + +static struct kv_power_info *kv_get_pi(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +#if 0 +static void kv_program_local_cac_table(struct amdgpu_device *adev, + const struct kv_lcac_config_values *local_cac_table, + const struct kv_lcac_config_reg *local_cac_reg) +{ + u32 i, count, data; + const struct kv_lcac_config_values *values = local_cac_table; + + while (values->block_id != 0xffffffff) { + count = values->signal_id; + for (i = 0; i < count; i++) { + data = ((values->block_id << local_cac_reg->block_shift) & + local_cac_reg->block_mask); + data |= ((i << local_cac_reg->signal_shift) & + local_cac_reg->signal_mask); + data |= ((values->t << local_cac_reg->t_shift) & + local_cac_reg->t_mask); + data |= ((1 << local_cac_reg->enable_shift) & + local_cac_reg->enable_mask); + WREG32_SMC(local_cac_reg->cntl, data); + } + values++; + } +} +#endif + +static int kv_program_pt_config_registers(struct amdgpu_device *adev, + const struct kv_pt_config_reg *cac_config_regs) +{ + const struct kv_pt_config_reg *config_regs = cac_config_regs; + u32 data; + u32 cache = 0; + + if (config_regs == NULL) + return -EINVAL; + + while (config_regs->offset != 0xFFFFFFFF) { + if (config_regs->type == KV_CONFIGREG_CACHE) { + cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); + } else { + switch (config_regs->type) { + case KV_CONFIGREG_SMC_IND: + data = RREG32_SMC(config_regs->offset); + break; + case KV_CONFIGREG_DIDT_IND: + data = RREG32_DIDT(config_regs->offset); + break; + default: + data = RREG32(config_regs->offset); + break; + } + + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + data |= cache; + cache = 0; + + switch (config_regs->type) { + case KV_CONFIGREG_SMC_IND: + WREG32_SMC(config_regs->offset, data); + break; + case KV_CONFIGREG_DIDT_IND: + WREG32_DIDT(config_regs->offset, data); + break; + default: + WREG32(config_regs->offset, data); + break; + } + } + config_regs++; + } + + return 0; +} + +static void kv_do_enable_didt(struct amdgpu_device *adev, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 data; + + if (pi->caps_sq_ramping) { + data = RREG32_DIDT(ixDIDT_SQ_CTRL0); + if (enable) + data |= DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; + else + data &= ~DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK; + WREG32_DIDT(ixDIDT_SQ_CTRL0, data); + } + + if (pi->caps_db_ramping) { + data = RREG32_DIDT(ixDIDT_DB_CTRL0); + if (enable) + data |= DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; + else + data &= ~DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK; + WREG32_DIDT(ixDIDT_DB_CTRL0, data); + } + + if (pi->caps_td_ramping) { + data = RREG32_DIDT(ixDIDT_TD_CTRL0); + if (enable) + data |= DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; + else + data &= ~DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK; + WREG32_DIDT(ixDIDT_TD_CTRL0, data); + } + + if (pi->caps_tcp_ramping) { + data = RREG32_DIDT(ixDIDT_TCP_CTRL0); + if (enable) + data |= DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; + else + data &= ~DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK; + WREG32_DIDT(ixDIDT_TCP_CTRL0, data); + } +} + +static int kv_enable_didt(struct amdgpu_device *adev, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + if (pi->caps_sq_ramping || + pi->caps_db_ramping || + pi->caps_td_ramping || + pi->caps_tcp_ramping) { + amdgpu_gfx_rlc_enter_safe_mode(adev); + + if (enable) { + ret = kv_program_pt_config_registers(adev, didt_config_kv); + if (ret) { + amdgpu_gfx_rlc_exit_safe_mode(adev); + return ret; + } + } + + kv_do_enable_didt(adev, enable); + + amdgpu_gfx_rlc_exit_safe_mode(adev); + } + + return 0; +} + +#if 0 +static void kv_initialize_hardware_cac_manager(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + if (pi->caps_cac) { + WREG32_SMC(ixLCAC_SX0_OVR_SEL, 0); + WREG32_SMC(ixLCAC_SX0_OVR_VAL, 0); + kv_program_local_cac_table(adev, sx_local_cac_cfg_kv, sx0_cac_config_reg); + + WREG32_SMC(ixLCAC_MC0_OVR_SEL, 0); + WREG32_SMC(ixLCAC_MC0_OVR_VAL, 0); + kv_program_local_cac_table(adev, mc0_local_cac_cfg_kv, mc0_cac_config_reg); + + WREG32_SMC(ixLCAC_MC1_OVR_SEL, 0); + WREG32_SMC(ixLCAC_MC1_OVR_VAL, 0); + kv_program_local_cac_table(adev, mc1_local_cac_cfg_kv, mc1_cac_config_reg); + + WREG32_SMC(ixLCAC_MC2_OVR_SEL, 0); + WREG32_SMC(ixLCAC_MC2_OVR_VAL, 0); + kv_program_local_cac_table(adev, mc2_local_cac_cfg_kv, mc2_cac_config_reg); + + WREG32_SMC(ixLCAC_MC3_OVR_SEL, 0); + WREG32_SMC(ixLCAC_MC3_OVR_VAL, 0); + kv_program_local_cac_table(adev, mc3_local_cac_cfg_kv, mc3_cac_config_reg); + + WREG32_SMC(ixLCAC_CPL_OVR_SEL, 0); + WREG32_SMC(ixLCAC_CPL_OVR_VAL, 0); + kv_program_local_cac_table(adev, cpl_local_cac_cfg_kv, cpl_cac_config_reg); + } +} +#endif + +static int kv_enable_smc_cac(struct amdgpu_device *adev, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret = 0; + + if (pi->caps_cac) { + if (enable) { + ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableCac); + if (ret) + pi->cac_enabled = false; + else + pi->cac_enabled = true; + } else if (pi->cac_enabled) { + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableCac); + pi->cac_enabled = false; + } + } + + return ret; +} + +static int kv_process_firmware_header(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 tmp; + int ret; + + ret = amdgpu_kv_read_smc_sram_dword(adev, SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, DpmTable), + &tmp, pi->sram_end); + + if (ret == 0) + pi->dpm_table_start = tmp; + + ret = amdgpu_kv_read_smc_sram_dword(adev, SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, SoftRegisters), + &tmp, pi->sram_end); + + if (ret == 0) + pi->soft_regs_start = tmp; + + return ret; +} + +static int kv_enable_dpm_voltage_scaling(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + pi->graphics_voltage_change_enable = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsVoltageChangeEnable), + &pi->graphics_voltage_change_enable, + sizeof(u8), pi->sram_end); + + return ret; +} + +static int kv_set_dpm_interval(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + pi->graphics_interval = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsInterval), + &pi->graphics_interval, + sizeof(u8), pi->sram_end); + + return ret; +} + +static int kv_set_dpm_boot_state(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsBootLevel), + &pi->graphics_boot_level, + sizeof(u8), pi->sram_end); + + return ret; +} + +static void kv_program_vc(struct amdgpu_device *adev) +{ + WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0x3FFFC100); +} + +static void kv_clear_vc(struct amdgpu_device *adev) +{ + WREG32_SMC(ixCG_FREQ_TRAN_VOTING_0, 0); +} + +static int kv_set_divider_value(struct amdgpu_device *adev, + u32 index, u32 sclk) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct atom_clock_dividers dividers; + int ret; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + sclk, false, ÷rs); + if (ret) + return ret; + + pi->graphics_level[index].SclkDid = (u8)dividers.post_div; + pi->graphics_level[index].SclkFrequency = cpu_to_be32(sclk); + + return 0; +} + +static u16 kv_convert_8bit_index_to_voltage(struct amdgpu_device *adev, + u16 voltage) +{ + return 6200 - (voltage * 25); +} + +static u16 kv_convert_2bit_index_to_voltage(struct amdgpu_device *adev, + u32 vid_2bit) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 vid_8bit = kv_convert_vid2_to_vid7(adev, + &pi->sys_info.vid_mapping_table, + vid_2bit); + + return kv_convert_8bit_index_to_voltage(adev, (u16)vid_8bit); +} + + +static int kv_set_vid(struct amdgpu_device *adev, u32 index, u32 vid) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->graphics_level[index].VoltageDownH = (u8)pi->voltage_drop_t; + pi->graphics_level[index].MinVddNb = + cpu_to_be32(kv_convert_2bit_index_to_voltage(adev, vid)); + + return 0; +} + +static int kv_set_at(struct amdgpu_device *adev, u32 index, u32 at) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->graphics_level[index].AT = cpu_to_be16((u16)at); + + return 0; +} + +static void kv_dpm_power_level_enable(struct amdgpu_device *adev, + u32 index, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->graphics_level[index].EnabledForActivity = enable ? 1 : 0; +} + +static void kv_start_dpm(struct amdgpu_device *adev) +{ + u32 tmp = RREG32_SMC(ixGENERAL_PWRMGT); + + tmp |= GENERAL_PWRMGT__GLOBAL_PWRMGT_EN_MASK; + WREG32_SMC(ixGENERAL_PWRMGT, tmp); + + amdgpu_kv_smc_dpm_enable(adev, true); +} + +static void kv_stop_dpm(struct amdgpu_device *adev) +{ + amdgpu_kv_smc_dpm_enable(adev, false); +} + +static void kv_start_am(struct amdgpu_device *adev) +{ + u32 sclk_pwrmgt_cntl = RREG32_SMC(ixSCLK_PWRMGT_CNTL); + + sclk_pwrmgt_cntl &= ~(SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | + SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK); + sclk_pwrmgt_cntl |= SCLK_PWRMGT_CNTL__DYNAMIC_PM_EN_MASK; + + WREG32_SMC(ixSCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); +} + +static void kv_reset_am(struct amdgpu_device *adev) +{ + u32 sclk_pwrmgt_cntl = RREG32_SMC(ixSCLK_PWRMGT_CNTL); + + sclk_pwrmgt_cntl |= (SCLK_PWRMGT_CNTL__RESET_SCLK_CNT_MASK | + SCLK_PWRMGT_CNTL__RESET_BUSY_CNT_MASK); + + WREG32_SMC(ixSCLK_PWRMGT_CNTL, sclk_pwrmgt_cntl); +} + +static int kv_freeze_sclk_dpm(struct amdgpu_device *adev, bool freeze) +{ + return amdgpu_kv_notify_message_to_smu(adev, freeze ? + PPSMC_MSG_SCLKDPM_FreezeLevel : PPSMC_MSG_SCLKDPM_UnfreezeLevel); +} + +static int kv_force_lowest_valid(struct amdgpu_device *adev) +{ + return kv_force_dpm_lowest(adev); +} + +static int kv_unforce_levels(struct amdgpu_device *adev) +{ + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) + return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NoForcedLevel); + else + return kv_set_enabled_levels(adev); +} + +static int kv_update_sclk_t(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 low_sclk_interrupt_t = 0; + int ret = 0; + + if (pi->caps_sclk_throttle_low_notification) { + low_sclk_interrupt_t = cpu_to_be32(pi->low_sclk_interrupt_t); + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, LowSclkInterruptT), + (u8 *)&low_sclk_interrupt_t, + sizeof(u32), pi->sram_end); + } + return ret; +} + +static int kv_program_bootup_state(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + + if (table && table->count) { + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].clk == pi->boot_pl.sclk) + break; + } + + pi->graphics_boot_level = (u8)i; + kv_dpm_power_level_enable(adev, i, true); + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + + if (table->num_max_dpm_entries == 0) + return -EINVAL; + + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].sclk_frequency == pi->boot_pl.sclk) + break; + } + + pi->graphics_boot_level = (u8)i; + kv_dpm_power_level_enable(adev, i, true); + } + return 0; +} + +static int kv_enable_auto_thermal_throttling(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + pi->graphics_therm_throttle_enable = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsThermThrottleEnable), + &pi->graphics_therm_throttle_enable, + sizeof(u8), pi->sram_end); + + return ret; +} + +static int kv_upload_dpm_settings(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsLevel), + (u8 *)&pi->graphics_level, + sizeof(SMU7_Fusion_GraphicsLevel) * SMU7_MAX_LEVELS_GRAPHICS, + pi->sram_end); + + if (ret) + return ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsDpmLevelCount), + &pi->graphics_dpm_level_count, + sizeof(u8), pi->sram_end); + + return ret; +} + +static u32 kv_get_clock_difference(u32 a, u32 b) +{ + return (a >= b) ? a - b : b - a; +} + +static u32 kv_get_clk_bypass(struct amdgpu_device *adev, u32 clk) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 value; + + if (pi->caps_enable_dfs_bypass) { + if (kv_get_clock_difference(clk, 40000) < 200) + value = 3; + else if (kv_get_clock_difference(clk, 30000) < 200) + value = 2; + else if (kv_get_clock_difference(clk, 20000) < 200) + value = 7; + else if (kv_get_clock_difference(clk, 15000) < 200) + value = 6; + else if (kv_get_clock_difference(clk, 10000) < 200) + value = 8; + else + value = 0; + } else { + value = 0; + } + + return value; +} + +static int kv_populate_uvd_table(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_uvd_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct atom_clock_dividers dividers; + int ret; + u32 i; + + if (table == NULL || table->count == 0) + return 0; + + pi->uvd_level_count = 0; + for (i = 0; i < table->count; i++) { + if (pi->high_voltage_t && + (pi->high_voltage_t < table->entries[i].v)) + break; + + pi->uvd_level[i].VclkFrequency = cpu_to_be32(table->entries[i].vclk); + pi->uvd_level[i].DclkFrequency = cpu_to_be32(table->entries[i].dclk); + pi->uvd_level[i].MinVddNb = cpu_to_be16(table->entries[i].v); + + pi->uvd_level[i].VClkBypassCntl = + (u8)kv_get_clk_bypass(adev, table->entries[i].vclk); + pi->uvd_level[i].DClkBypassCntl = + (u8)kv_get_clk_bypass(adev, table->entries[i].dclk); + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + table->entries[i].vclk, false, ÷rs); + if (ret) + return ret; + pi->uvd_level[i].VclkDivider = (u8)dividers.post_div; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + table->entries[i].dclk, false, ÷rs); + if (ret) + return ret; + pi->uvd_level[i].DclkDivider = (u8)dividers.post_div; + + pi->uvd_level_count++; + } + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, UvdLevelCount), + (u8 *)&pi->uvd_level_count, + sizeof(u8), pi->sram_end); + if (ret) + return ret; + + pi->uvd_interval = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, UVDInterval), + &pi->uvd_interval, + sizeof(u8), pi->sram_end); + if (ret) + return ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, UvdLevel), + (u8 *)&pi->uvd_level, + sizeof(SMU7_Fusion_UvdLevel) * SMU7_MAX_LEVELS_UVD, + pi->sram_end); + + return ret; + +} + +static int kv_populate_vce_table(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + u32 i; + struct amdgpu_vce_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + struct atom_clock_dividers dividers; + + if (table == NULL || table->count == 0) + return 0; + + pi->vce_level_count = 0; + for (i = 0; i < table->count; i++) { + if (pi->high_voltage_t && + pi->high_voltage_t < table->entries[i].v) + break; + + pi->vce_level[i].Frequency = cpu_to_be32(table->entries[i].evclk); + pi->vce_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); + + pi->vce_level[i].ClkBypassCntl = + (u8)kv_get_clk_bypass(adev, table->entries[i].evclk); + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + table->entries[i].evclk, false, ÷rs); + if (ret) + return ret; + pi->vce_level[i].Divider = (u8)dividers.post_div; + + pi->vce_level_count++; + } + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, VceLevelCount), + (u8 *)&pi->vce_level_count, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + pi->vce_interval = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, VCEInterval), + (u8 *)&pi->vce_interval, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, VceLevel), + (u8 *)&pi->vce_level, + sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_VCE, + pi->sram_end); + + return ret; +} + +static int kv_populate_samu_table(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; + struct atom_clock_dividers dividers; + int ret; + u32 i; + + if (table == NULL || table->count == 0) + return 0; + + pi->samu_level_count = 0; + for (i = 0; i < table->count; i++) { + if (pi->high_voltage_t && + pi->high_voltage_t < table->entries[i].v) + break; + + pi->samu_level[i].Frequency = cpu_to_be32(table->entries[i].clk); + pi->samu_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); + + pi->samu_level[i].ClkBypassCntl = + (u8)kv_get_clk_bypass(adev, table->entries[i].clk); + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + table->entries[i].clk, false, ÷rs); + if (ret) + return ret; + pi->samu_level[i].Divider = (u8)dividers.post_div; + + pi->samu_level_count++; + } + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, SamuLevelCount), + (u8 *)&pi->samu_level_count, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + pi->samu_interval = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, SAMUInterval), + (u8 *)&pi->samu_interval, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, SamuLevel), + (u8 *)&pi->samu_level, + sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_SAMU, + pi->sram_end); + if (ret) + return ret; + + return ret; +} + + +static int kv_populate_acp_table(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + struct atom_clock_dividers dividers; + int ret; + u32 i; + + if (table == NULL || table->count == 0) + return 0; + + pi->acp_level_count = 0; + for (i = 0; i < table->count; i++) { + pi->acp_level[i].Frequency = cpu_to_be32(table->entries[i].clk); + pi->acp_level[i].MinVoltage = cpu_to_be16(table->entries[i].v); + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + table->entries[i].clk, false, ÷rs); + if (ret) + return ret; + pi->acp_level[i].Divider = (u8)dividers.post_div; + + pi->acp_level_count++; + } + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, AcpLevelCount), + (u8 *)&pi->acp_level_count, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + pi->acp_interval = 1; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, ACPInterval), + (u8 *)&pi->acp_interval, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, AcpLevel), + (u8 *)&pi->acp_level, + sizeof(SMU7_Fusion_ExtClkLevel) * SMU7_MAX_LEVELS_ACP, + pi->sram_end); + if (ret) + return ret; + + return ret; +} + +static void kv_calculate_dfs_bypass_settings(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + + if (table && table->count) { + for (i = 0; i < pi->graphics_dpm_level_count; i++) { + if (pi->caps_enable_dfs_bypass) { + if (kv_get_clock_difference(table->entries[i].clk, 40000) < 200) + pi->graphics_level[i].ClkBypassCntl = 3; + else if (kv_get_clock_difference(table->entries[i].clk, 30000) < 200) + pi->graphics_level[i].ClkBypassCntl = 2; + else if (kv_get_clock_difference(table->entries[i].clk, 26600) < 200) + pi->graphics_level[i].ClkBypassCntl = 7; + else if (kv_get_clock_difference(table->entries[i].clk , 20000) < 200) + pi->graphics_level[i].ClkBypassCntl = 6; + else if (kv_get_clock_difference(table->entries[i].clk , 10000) < 200) + pi->graphics_level[i].ClkBypassCntl = 8; + else + pi->graphics_level[i].ClkBypassCntl = 0; + } else { + pi->graphics_level[i].ClkBypassCntl = 0; + } + } + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + for (i = 0; i < pi->graphics_dpm_level_count; i++) { + if (pi->caps_enable_dfs_bypass) { + if (kv_get_clock_difference(table->entries[i].sclk_frequency, 40000) < 200) + pi->graphics_level[i].ClkBypassCntl = 3; + else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 30000) < 200) + pi->graphics_level[i].ClkBypassCntl = 2; + else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 26600) < 200) + pi->graphics_level[i].ClkBypassCntl = 7; + else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 20000) < 200) + pi->graphics_level[i].ClkBypassCntl = 6; + else if (kv_get_clock_difference(table->entries[i].sclk_frequency, 10000) < 200) + pi->graphics_level[i].ClkBypassCntl = 8; + else + pi->graphics_level[i].ClkBypassCntl = 0; + } else { + pi->graphics_level[i].ClkBypassCntl = 0; + } + } + } +} + +static int kv_enable_ulv(struct amdgpu_device *adev, bool enable) +{ + return amdgpu_kv_notify_message_to_smu(adev, enable ? + PPSMC_MSG_EnableULV : PPSMC_MSG_DisableULV); +} + +static void kv_reset_acp_boot_level(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->acp_boot_level = 0xff; +} + +static void kv_update_current_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct kv_ps *new_ps = kv_get_ps(rps); + struct kv_power_info *pi = kv_get_pi(adev); + + pi->current_rps = *rps; + pi->current_ps = *new_ps; + pi->current_rps.ps_priv = &pi->current_ps; + adev->pm.dpm.current_ps = &pi->current_rps; +} + +static void kv_update_requested_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct kv_ps *new_ps = kv_get_ps(rps); + struct kv_power_info *pi = kv_get_pi(adev); + + pi->requested_rps = *rps; + pi->requested_ps = *new_ps; + pi->requested_rps.ps_priv = &pi->requested_ps; + adev->pm.dpm.requested_ps = &pi->requested_rps; +} + +static void kv_dpm_enable_bapm(void *handle, bool enable) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + if (pi->bapm_enable) { + ret = amdgpu_kv_smc_bapm_enable(adev, enable); + if (ret) + DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); + } +} + +static int kv_dpm_enable(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + ret = kv_process_firmware_header(adev); + if (ret) { + DRM_ERROR("kv_process_firmware_header failed\n"); + return ret; + } + kv_init_fps_limits(adev); + kv_init_graphics_levels(adev); + ret = kv_program_bootup_state(adev); + if (ret) { + DRM_ERROR("kv_program_bootup_state failed\n"); + return ret; + } + kv_calculate_dfs_bypass_settings(adev); + ret = kv_upload_dpm_settings(adev); + if (ret) { + DRM_ERROR("kv_upload_dpm_settings failed\n"); + return ret; + } + ret = kv_populate_uvd_table(adev); + if (ret) { + DRM_ERROR("kv_populate_uvd_table failed\n"); + return ret; + } + ret = kv_populate_vce_table(adev); + if (ret) { + DRM_ERROR("kv_populate_vce_table failed\n"); + return ret; + } + ret = kv_populate_samu_table(adev); + if (ret) { + DRM_ERROR("kv_populate_samu_table failed\n"); + return ret; + } + ret = kv_populate_acp_table(adev); + if (ret) { + DRM_ERROR("kv_populate_acp_table failed\n"); + return ret; + } + kv_program_vc(adev); +#if 0 + kv_initialize_hardware_cac_manager(adev); +#endif + kv_start_am(adev); + if (pi->enable_auto_thermal_throttling) { + ret = kv_enable_auto_thermal_throttling(adev); + if (ret) { + DRM_ERROR("kv_enable_auto_thermal_throttling failed\n"); + return ret; + } + } + ret = kv_enable_dpm_voltage_scaling(adev); + if (ret) { + DRM_ERROR("kv_enable_dpm_voltage_scaling failed\n"); + return ret; + } + ret = kv_set_dpm_interval(adev); + if (ret) { + DRM_ERROR("kv_set_dpm_interval failed\n"); + return ret; + } + ret = kv_set_dpm_boot_state(adev); + if (ret) { + DRM_ERROR("kv_set_dpm_boot_state failed\n"); + return ret; + } + ret = kv_enable_ulv(adev, true); + if (ret) { + DRM_ERROR("kv_enable_ulv failed\n"); + return ret; + } + kv_start_dpm(adev); + ret = kv_enable_didt(adev, true); + if (ret) { + DRM_ERROR("kv_enable_didt failed\n"); + return ret; + } + ret = kv_enable_smc_cac(adev, true); + if (ret) { + DRM_ERROR("kv_enable_smc_cac failed\n"); + return ret; + } + + kv_reset_acp_boot_level(adev); + + ret = amdgpu_kv_smc_bapm_enable(adev, false); + if (ret) { + DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); + return ret; + } + + if (adev->irq.installed && + amdgpu_is_internal_thermal_sensor(adev->pm.int_thermal_type)) { + ret = kv_set_thermal_temperature_range(adev, KV_TEMP_RANGE_MIN, KV_TEMP_RANGE_MAX); + if (ret) { + DRM_ERROR("kv_set_thermal_temperature_range failed\n"); + return ret; + } + amdgpu_irq_get(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); + amdgpu_irq_get(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); + } + + return ret; +} + +static void kv_dpm_disable(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_LOW_TO_HIGH); + amdgpu_irq_put(adev, &adev->pm.dpm.thermal.irq, + AMDGPU_THERMAL_IRQ_HIGH_TO_LOW); + + amdgpu_kv_smc_bapm_enable(adev, false); + + if (adev->asic_type == CHIP_MULLINS) + kv_enable_nb_dpm(adev, false); + + /* powerup blocks */ + kv_dpm_powergate_acp(adev, false); + kv_dpm_powergate_samu(adev, false); + if (pi->caps_vce_pg) /* power on the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); + if (pi->caps_uvd_pg) /* power on the UVD block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); + + kv_enable_smc_cac(adev, false); + kv_enable_didt(adev, false); + kv_clear_vc(adev); + kv_stop_dpm(adev); + kv_enable_ulv(adev, false); + kv_reset_am(adev); + + kv_update_current_ps(adev, adev->pm.dpm.boot_ps); +} + +#if 0 +static int kv_write_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 value) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + return amdgpu_kv_copy_bytes_to_smc(adev, pi->soft_regs_start + reg_offset, + (u8 *)&value, sizeof(u16), pi->sram_end); +} + +static int kv_read_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 *value) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + return amdgpu_kv_read_smc_sram_dword(adev, pi->soft_regs_start + reg_offset, + value, pi->sram_end); +} +#endif + +static void kv_init_sclk_t(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->low_sclk_interrupt_t = 0; +} + +static int kv_init_fps_limits(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret = 0; + + if (pi->caps_fps) { + u16 tmp; + + tmp = 45; + pi->fps_high_t = cpu_to_be16(tmp); + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, FpsHighT), + (u8 *)&pi->fps_high_t, + sizeof(u16), pi->sram_end); + + tmp = 30; + pi->fps_low_t = cpu_to_be16(tmp); + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, FpsLowT), + (u8 *)&pi->fps_low_t, + sizeof(u16), pi->sram_end); + + } + return ret; +} + +static void kv_init_powergate_state(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->uvd_power_gated = false; + pi->vce_power_gated = false; + pi->samu_power_gated = false; + pi->acp_power_gated = false; + +} + +static int kv_enable_uvd_dpm(struct amdgpu_device *adev, bool enable) +{ + return amdgpu_kv_notify_message_to_smu(adev, enable ? + PPSMC_MSG_UVDDPM_Enable : PPSMC_MSG_UVDDPM_Disable); +} + +static int kv_enable_vce_dpm(struct amdgpu_device *adev, bool enable) +{ + return amdgpu_kv_notify_message_to_smu(adev, enable ? + PPSMC_MSG_VCEDPM_Enable : PPSMC_MSG_VCEDPM_Disable); +} + +static int kv_enable_samu_dpm(struct amdgpu_device *adev, bool enable) +{ + return amdgpu_kv_notify_message_to_smu(adev, enable ? + PPSMC_MSG_SAMUDPM_Enable : PPSMC_MSG_SAMUDPM_Disable); +} + +static int kv_enable_acp_dpm(struct amdgpu_device *adev, bool enable) +{ + return amdgpu_kv_notify_message_to_smu(adev, enable ? + PPSMC_MSG_ACPDPM_Enable : PPSMC_MSG_ACPDPM_Disable); +} + +static int kv_update_uvd_dpm(struct amdgpu_device *adev, bool gate) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_uvd_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + int ret; + u32 mask; + + if (!gate) { + if (table->count) + pi->uvd_boot_level = table->count - 1; + else + pi->uvd_boot_level = 0; + + if (!pi->caps_uvd_dpm || pi->caps_stable_p_state) { + mask = 1 << pi->uvd_boot_level; + } else { + mask = 0x1f; + } + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, UvdBootLevel), + (uint8_t *)&pi->uvd_boot_level, + sizeof(u8), pi->sram_end); + if (ret) + return ret; + + amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_UVDDPM_SetEnabledMask, + mask); + } + + return kv_enable_uvd_dpm(adev, !gate); +} + +static u8 kv_get_vce_boot_level(struct amdgpu_device *adev, u32 evclk) +{ + u8 i; + struct amdgpu_vce_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + + for (i = 0; i < table->count; i++) { + if (table->entries[i].evclk >= evclk) + break; + } + + return i; +} + +static int kv_update_vce_dpm(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_vce_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + int ret; + + if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) { + if (pi->caps_stable_p_state) + pi->vce_boot_level = table->count - 1; + else + pi->vce_boot_level = kv_get_vce_boot_level(adev, amdgpu_new_state->evclk); + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, VceBootLevel), + (u8 *)&pi->vce_boot_level, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + if (pi->caps_stable_p_state) + amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (1 << pi->vce_boot_level)); + kv_enable_vce_dpm(adev, true); + } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) { + kv_enable_vce_dpm(adev, false); + } + + return 0; +} + +static int kv_update_samu_dpm(struct amdgpu_device *adev, bool gate) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; + int ret; + + if (!gate) { + if (pi->caps_stable_p_state) + pi->samu_boot_level = table->count - 1; + else + pi->samu_boot_level = 0; + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, SamuBootLevel), + (u8 *)&pi->samu_boot_level, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + if (pi->caps_stable_p_state) + amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_SAMUDPM_SetEnabledMask, + (1 << pi->samu_boot_level)); + } + + return kv_enable_samu_dpm(adev, !gate); +} + +static u8 kv_get_acp_boot_level(struct amdgpu_device *adev) +{ + u8 i; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + + for (i = 0; i < table->count; i++) { + if (table->entries[i].clk >= 0) /* XXX */ + break; + } + + if (i >= table->count) + i = table->count - 1; + + return i; +} + +static void kv_update_acp_boot_level(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u8 acp_boot_level; + + if (!pi->caps_stable_p_state) { + acp_boot_level = kv_get_acp_boot_level(adev); + if (acp_boot_level != pi->acp_boot_level) { + pi->acp_boot_level = acp_boot_level; + amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_ACPDPM_SetEnabledMask, + (1 << pi->acp_boot_level)); + } + } +} + +static int kv_update_acp_dpm(struct amdgpu_device *adev, bool gate) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + int ret; + + if (!gate) { + if (pi->caps_stable_p_state) + pi->acp_boot_level = table->count - 1; + else + pi->acp_boot_level = kv_get_acp_boot_level(adev); + + ret = amdgpu_kv_copy_bytes_to_smc(adev, + pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, AcpBootLevel), + (u8 *)&pi->acp_boot_level, + sizeof(u8), + pi->sram_end); + if (ret) + return ret; + + if (pi->caps_stable_p_state) + amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_ACPDPM_SetEnabledMask, + (1 << pi->acp_boot_level)); + } + + return kv_enable_acp_dpm(adev, !gate); +} + +static void kv_dpm_powergate_uvd(void *handle, bool gate) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + pi->uvd_power_gated = gate; + + if (gate) { + /* stop the UVD block */ + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + kv_update_uvd_dpm(adev, gate); + if (pi->caps_uvd_pg) + /* power off the UVD block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerOFF); + } else { + if (pi->caps_uvd_pg) + /* power on the UVD block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); + /* re-init the UVD block */ + kv_update_uvd_dpm(adev, gate); + + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); + } +} + +static void kv_dpm_powergate_vce(void *handle, bool gate) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + int ret; + + pi->vce_power_gated = gate; + + if (gate) { + /* stop the VCE block */ + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + kv_enable_vce_dpm(adev, false); + if (pi->caps_vce_pg) /* power off the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF); + } else { + if (pi->caps_vce_pg) /* power on the VCE block */ + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON); + kv_enable_vce_dpm(adev, true); + /* re-init the VCE block */ + ret = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + } +} + + +static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + if (pi->samu_power_gated == gate) + return; + + pi->samu_power_gated = gate; + + if (gate) { + kv_update_samu_dpm(adev, true); + if (pi->caps_samu_pg) + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SAMPowerOFF); + } else { + if (pi->caps_samu_pg) + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SAMPowerON); + kv_update_samu_dpm(adev, false); + } +} + +static void kv_dpm_powergate_acp(struct amdgpu_device *adev, bool gate) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + if (pi->acp_power_gated == gate) + return; + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) + return; + + pi->acp_power_gated = gate; + + if (gate) { + kv_update_acp_dpm(adev, true); + if (pi->caps_acp_pg) + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_ACPPowerOFF); + } else { + if (pi->caps_acp_pg) + amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_ACPPowerON); + kv_update_acp_dpm(adev, false); + } +} + +static void kv_set_valid_clock_range(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps) +{ + struct kv_ps *new_ps = kv_get_ps(new_rps); + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + + if (table && table->count) { + for (i = 0; i < pi->graphics_dpm_level_count; i++) { + if ((table->entries[i].clk >= new_ps->levels[0].sclk) || + (i == (pi->graphics_dpm_level_count - 1))) { + pi->lowest_valid = i; + break; + } + } + + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].clk <= new_ps->levels[new_ps->num_levels - 1].sclk) + break; + } + pi->highest_valid = i; + + if (pi->lowest_valid > pi->highest_valid) { + if ((new_ps->levels[0].sclk - table->entries[pi->highest_valid].clk) > + (table->entries[pi->lowest_valid].clk - new_ps->levels[new_ps->num_levels - 1].sclk)) + pi->highest_valid = pi->lowest_valid; + else + pi->lowest_valid = pi->highest_valid; + } + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + + for (i = 0; i < (int)pi->graphics_dpm_level_count; i++) { + if (table->entries[i].sclk_frequency >= new_ps->levels[0].sclk || + i == (int)(pi->graphics_dpm_level_count - 1)) { + pi->lowest_valid = i; + break; + } + } + + for (i = pi->graphics_dpm_level_count - 1; i > 0; i--) { + if (table->entries[i].sclk_frequency <= + new_ps->levels[new_ps->num_levels - 1].sclk) + break; + } + pi->highest_valid = i; + + if (pi->lowest_valid > pi->highest_valid) { + if ((new_ps->levels[0].sclk - + table->entries[pi->highest_valid].sclk_frequency) > + (table->entries[pi->lowest_valid].sclk_frequency - + new_ps->levels[new_ps->num_levels -1].sclk)) + pi->highest_valid = pi->lowest_valid; + else + pi->lowest_valid = pi->highest_valid; + } + } +} + +static int kv_update_dfs_bypass_settings(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps) +{ + struct kv_ps *new_ps = kv_get_ps(new_rps); + struct kv_power_info *pi = kv_get_pi(adev); + int ret = 0; + u8 clk_bypass_cntl; + + if (pi->caps_enable_dfs_bypass) { + clk_bypass_cntl = new_ps->need_dfs_bypass ? + pi->graphics_level[pi->graphics_boot_level].ClkBypassCntl : 0; + ret = amdgpu_kv_copy_bytes_to_smc(adev, + (pi->dpm_table_start + + offsetof(SMU7_Fusion_DpmTable, GraphicsLevel) + + (pi->graphics_boot_level * sizeof(SMU7_Fusion_GraphicsLevel)) + + offsetof(SMU7_Fusion_GraphicsLevel, ClkBypassCntl)), + &clk_bypass_cntl, + sizeof(u8), pi->sram_end); + } + + return ret; +} + +static int kv_enable_nb_dpm(struct amdgpu_device *adev, + bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + int ret = 0; + + if (enable) { + if (pi->enable_nb_dpm && !pi->nb_dpm_enabled) { + ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NBDPM_Enable); + if (ret == 0) + pi->nb_dpm_enabled = true; + } + } else { + if (pi->enable_nb_dpm && pi->nb_dpm_enabled) { + ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_NBDPM_Disable); + if (ret == 0) + pi->nb_dpm_enabled = false; + } + } + + return ret; +} + +static int kv_dpm_force_performance_level(void *handle, + enum amd_dpm_forced_level level) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (level == AMD_DPM_FORCED_LEVEL_HIGH) { + ret = kv_force_dpm_highest(adev); + if (ret) + return ret; + } else if (level == AMD_DPM_FORCED_LEVEL_LOW) { + ret = kv_force_dpm_lowest(adev); + if (ret) + return ret; + } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) { + ret = kv_unforce_levels(adev); + if (ret) + return ret; + } + + adev->pm.dpm.forced_level = level; + + return 0; +} + +static int kv_dpm_pre_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; + struct amdgpu_ps *new_ps = &requested_ps; + + kv_update_requested_ps(adev, new_ps); + + kv_apply_state_adjust_rules(adev, + &pi->requested_rps, + &pi->current_rps); + + return 0; +} + +static int kv_dpm_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_ps *new_ps = &pi->requested_rps; + struct amdgpu_ps *old_ps = &pi->current_rps; + int ret; + + if (pi->bapm_enable) { + ret = amdgpu_kv_smc_bapm_enable(adev, adev->pm.ac_power); + if (ret) { + DRM_ERROR("amdgpu_kv_smc_bapm_enable failed\n"); + return ret; + } + } + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { + if (pi->enable_dpm) { + kv_set_valid_clock_range(adev, new_ps); + kv_update_dfs_bypass_settings(adev, new_ps); + ret = kv_calculate_ds_divider(adev); + if (ret) { + DRM_ERROR("kv_calculate_ds_divider failed\n"); + return ret; + } + kv_calculate_nbps_level_settings(adev); + kv_calculate_dpm_settings(adev); + kv_force_lowest_valid(adev); + kv_enable_new_levels(adev); + kv_upload_dpm_settings(adev); + kv_program_nbps_index_settings(adev, new_ps); + kv_unforce_levels(adev); + kv_set_enabled_levels(adev); + kv_force_lowest_valid(adev); + kv_unforce_levels(adev); + + ret = kv_update_vce_dpm(adev, new_ps, old_ps); + if (ret) { + DRM_ERROR("kv_update_vce_dpm failed\n"); + return ret; + } + kv_update_sclk_t(adev); + if (adev->asic_type == CHIP_MULLINS) + kv_enable_nb_dpm(adev, true); + } + } else { + if (pi->enable_dpm) { + kv_set_valid_clock_range(adev, new_ps); + kv_update_dfs_bypass_settings(adev, new_ps); + ret = kv_calculate_ds_divider(adev); + if (ret) { + DRM_ERROR("kv_calculate_ds_divider failed\n"); + return ret; + } + kv_calculate_nbps_level_settings(adev); + kv_calculate_dpm_settings(adev); + kv_freeze_sclk_dpm(adev, true); + kv_upload_dpm_settings(adev); + kv_program_nbps_index_settings(adev, new_ps); + kv_freeze_sclk_dpm(adev, false); + kv_set_enabled_levels(adev); + ret = kv_update_vce_dpm(adev, new_ps, old_ps); + if (ret) { + DRM_ERROR("kv_update_vce_dpm failed\n"); + return ret; + } + kv_update_acp_boot_level(adev); + kv_update_sclk_t(adev); + kv_enable_nb_dpm(adev, true); + } + } + + return 0; +} + +static void kv_dpm_post_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_ps *new_ps = &pi->requested_rps; + + kv_update_current_ps(adev, new_ps); +} + +static void kv_dpm_setup_asic(struct amdgpu_device *adev) +{ + sumo_take_smu_control(adev, true); + kv_init_powergate_state(adev); + kv_init_sclk_t(adev); +} + +#if 0 +static void kv_dpm_reset_asic(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { + kv_force_lowest_valid(adev); + kv_init_graphics_levels(adev); + kv_program_bootup_state(adev); + kv_upload_dpm_settings(adev); + kv_force_lowest_valid(adev); + kv_unforce_levels(adev); + } else { + kv_init_graphics_levels(adev); + kv_program_bootup_state(adev); + kv_freeze_sclk_dpm(adev, true); + kv_upload_dpm_settings(adev); + kv_freeze_sclk_dpm(adev, false); + kv_set_enabled_level(adev, pi->graphics_boot_level); + } +} +#endif + +static void kv_construct_max_power_limits_table(struct amdgpu_device *adev, + struct amdgpu_clock_and_voltage_limits *table) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + if (pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries > 0) { + int idx = pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries - 1; + table->sclk = + pi->sys_info.sclk_voltage_mapping_table.entries[idx].sclk_frequency; + table->vddc = + kv_convert_2bit_index_to_voltage(adev, + pi->sys_info.sclk_voltage_mapping_table.entries[idx].vid_2bit); + } + + table->mclk = pi->sys_info.nbp_memory_clock[0]; +} + +static void kv_patch_voltage_values(struct amdgpu_device *adev) +{ + int i; + struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table = + &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table; + struct amdgpu_vce_clock_voltage_dependency_table *vce_table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table *samu_table = + &adev->pm.dpm.dyn_state.samu_clock_voltage_dependency_table; + struct amdgpu_clock_voltage_dependency_table *acp_table = + &adev->pm.dpm.dyn_state.acp_clock_voltage_dependency_table; + + if (uvd_table->count) { + for (i = 0; i < uvd_table->count; i++) + uvd_table->entries[i].v = + kv_convert_8bit_index_to_voltage(adev, + uvd_table->entries[i].v); + } + + if (vce_table->count) { + for (i = 0; i < vce_table->count; i++) + vce_table->entries[i].v = + kv_convert_8bit_index_to_voltage(adev, + vce_table->entries[i].v); + } + + if (samu_table->count) { + for (i = 0; i < samu_table->count; i++) + samu_table->entries[i].v = + kv_convert_8bit_index_to_voltage(adev, + samu_table->entries[i].v); + } + + if (acp_table->count) { + for (i = 0; i < acp_table->count; i++) + acp_table->entries[i].v = + kv_convert_8bit_index_to_voltage(adev, + acp_table->entries[i].v); + } + +} + +static void kv_construct_boot_state(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->boot_pl.sclk = pi->sys_info.bootup_sclk; + pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; + pi->boot_pl.ds_divider_index = 0; + pi->boot_pl.ss_divider_index = 0; + pi->boot_pl.allow_gnb_slow = 1; + pi->boot_pl.force_nbp_state = 0; + pi->boot_pl.display_wm = 0; + pi->boot_pl.vce_wm = 0; +} + +static int kv_force_dpm_highest(struct amdgpu_device *adev) +{ + int ret; + u32 enable_mask, i; + + ret = amdgpu_kv_dpm_get_enable_mask(adev, &enable_mask); + if (ret) + return ret; + + for (i = SMU7_MAX_LEVELS_GRAPHICS - 1; i > 0; i--) { + if (enable_mask & (1 << i)) + break; + } + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) + return amdgpu_kv_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DPM_ForceState, i); + else + return kv_set_enabled_level(adev, i); +} + +static int kv_force_dpm_lowest(struct amdgpu_device *adev) +{ + int ret; + u32 enable_mask, i; + + ret = amdgpu_kv_dpm_get_enable_mask(adev, &enable_mask); + if (ret) + return ret; + + for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { + if (enable_mask & (1 << i)) + break; + } + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) + return amdgpu_kv_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_DPM_ForceState, i); + else + return kv_set_enabled_level(adev, i); +} + +static u8 kv_get_sleep_divider_id_from_clock(struct amdgpu_device *adev, + u32 sclk, u32 min_sclk_in_sr) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + u32 temp; + u32 min = max(min_sclk_in_sr, (u32)KV_MINIMUM_ENGINE_CLOCK); + + if (sclk < min) + return 0; + + if (!pi->caps_sclk_ds) + return 0; + + for (i = KV_MAX_DEEPSLEEP_DIVIDER_ID; i > 0; i--) { + temp = sclk >> i; + if (temp >= min) + break; + } + + return (u8)i; +} + +static int kv_get_high_voltage_limit(struct amdgpu_device *adev, int *limit) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + int i; + + if (table && table->count) { + for (i = table->count - 1; i >= 0; i--) { + if (pi->high_voltage_t && + (kv_convert_8bit_index_to_voltage(adev, table->entries[i].v) <= + pi->high_voltage_t)) { + *limit = i; + return 0; + } + } + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + + for (i = table->num_max_dpm_entries - 1; i >= 0; i--) { + if (pi->high_voltage_t && + (kv_convert_2bit_index_to_voltage(adev, table->entries[i].vid_2bit) <= + pi->high_voltage_t)) { + *limit = i; + return 0; + } + } + } + + *limit = 0; + return 0; +} + +static void kv_apply_state_adjust_rules(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps, + struct amdgpu_ps *old_rps) +{ + struct kv_ps *ps = kv_get_ps(new_rps); + struct kv_power_info *pi = kv_get_pi(adev); + u32 min_sclk = 10000; /* ??? */ + u32 sclk, mclk = 0; + int i, limit; + bool force_high; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + u32 stable_p_state_sclk = 0; + struct amdgpu_clock_and_voltage_limits *max_limits = + &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + + if (new_rps->vce_active) { + new_rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; + new_rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; + } else { + new_rps->evclk = 0; + new_rps->ecclk = 0; + } + + mclk = max_limits->mclk; + sclk = min_sclk; + + if (pi->caps_stable_p_state) { + stable_p_state_sclk = (max_limits->sclk * 75) / 100; + + for (i = table->count - 1; i >= 0; i--) { + if (stable_p_state_sclk >= table->entries[i].clk) { + stable_p_state_sclk = table->entries[i].clk; + break; + } + } + + if (i > 0) + stable_p_state_sclk = table->entries[0].clk; + + sclk = stable_p_state_sclk; + } + + if (new_rps->vce_active) { + if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) + sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; + } + + ps->need_dfs_bypass = true; + + for (i = 0; i < ps->num_levels; i++) { + if (ps->levels[i].sclk < sclk) + ps->levels[i].sclk = sclk; + } + + if (table && table->count) { + for (i = 0; i < ps->num_levels; i++) { + if (pi->high_voltage_t && + (pi->high_voltage_t < + kv_convert_8bit_index_to_voltage(adev, ps->levels[i].vddc_index))) { + kv_get_high_voltage_limit(adev, &limit); + ps->levels[i].sclk = table->entries[limit].clk; + } + } + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + + for (i = 0; i < ps->num_levels; i++) { + if (pi->high_voltage_t && + (pi->high_voltage_t < + kv_convert_8bit_index_to_voltage(adev, ps->levels[i].vddc_index))) { + kv_get_high_voltage_limit(adev, &limit); + ps->levels[i].sclk = table->entries[limit].sclk_frequency; + } + } + } + + if (pi->caps_stable_p_state) { + for (i = 0; i < ps->num_levels; i++) { + ps->levels[i].sclk = stable_p_state_sclk; + } + } + + pi->video_start = new_rps->dclk || new_rps->vclk || + new_rps->evclk || new_rps->ecclk; + + if ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == + ATOM_PPLIB_CLASSIFICATION_UI_BATTERY) + pi->battery_state = true; + else + pi->battery_state = false; + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { + ps->dpm0_pg_nb_ps_lo = 0x1; + ps->dpm0_pg_nb_ps_hi = 0x0; + ps->dpmx_nb_ps_lo = 0x1; + ps->dpmx_nb_ps_hi = 0x0; + } else { + ps->dpm0_pg_nb_ps_lo = 0x3; + ps->dpm0_pg_nb_ps_hi = 0x0; + ps->dpmx_nb_ps_lo = 0x3; + ps->dpmx_nb_ps_hi = 0x0; + + if (pi->sys_info.nb_dpm_enable) { + force_high = (mclk >= pi->sys_info.nbp_memory_clock[3]) || + pi->video_start || (adev->pm.dpm.new_active_crtc_count >= 3) || + pi->disable_nb_ps3_in_battery; + ps->dpm0_pg_nb_ps_lo = force_high ? 0x2 : 0x3; + ps->dpm0_pg_nb_ps_hi = 0x2; + ps->dpmx_nb_ps_lo = force_high ? 0x2 : 0x3; + ps->dpmx_nb_ps_hi = 0x2; + } + } +} + +static void kv_dpm_power_level_enabled_for_throttle(struct amdgpu_device *adev, + u32 index, bool enable) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + pi->graphics_level[index].EnabledForThrottle = enable ? 1 : 0; +} + +static int kv_calculate_ds_divider(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 sclk_in_sr = 10000; /* ??? */ + u32 i; + + if (pi->lowest_valid > pi->highest_valid) + return -EINVAL; + + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { + pi->graphics_level[i].DeepSleepDivId = + kv_get_sleep_divider_id_from_clock(adev, + be32_to_cpu(pi->graphics_level[i].SclkFrequency), + sclk_in_sr); + } + return 0; +} + +static int kv_calculate_nbps_level_settings(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + bool force_high; + struct amdgpu_clock_and_voltage_limits *max_limits = + &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + u32 mclk = max_limits->mclk; + + if (pi->lowest_valid > pi->highest_valid) + return -EINVAL; + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) { + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { + pi->graphics_level[i].GnbSlow = 1; + pi->graphics_level[i].ForceNbPs1 = 0; + pi->graphics_level[i].UpH = 0; + } + + if (!pi->sys_info.nb_dpm_enable) + return 0; + + force_high = ((mclk >= pi->sys_info.nbp_memory_clock[3]) || + (adev->pm.dpm.new_active_crtc_count >= 3) || pi->video_start); + + if (force_high) { + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) + pi->graphics_level[i].GnbSlow = 0; + } else { + if (pi->battery_state) + pi->graphics_level[0].ForceNbPs1 = 1; + + pi->graphics_level[1].GnbSlow = 0; + pi->graphics_level[2].GnbSlow = 0; + pi->graphics_level[3].GnbSlow = 0; + pi->graphics_level[4].GnbSlow = 0; + } + } else { + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) { + pi->graphics_level[i].GnbSlow = 1; + pi->graphics_level[i].ForceNbPs1 = 0; + pi->graphics_level[i].UpH = 0; + } + + if (pi->sys_info.nb_dpm_enable && pi->battery_state) { + pi->graphics_level[pi->lowest_valid].UpH = 0x28; + pi->graphics_level[pi->lowest_valid].GnbSlow = 0; + if (pi->lowest_valid != pi->highest_valid) + pi->graphics_level[pi->lowest_valid].ForceNbPs1 = 1; + } + } + return 0; +} + +static int kv_calculate_dpm_settings(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + + if (pi->lowest_valid > pi->highest_valid) + return -EINVAL; + + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) + pi->graphics_level[i].DisplayWatermark = (i == pi->highest_valid) ? 1 : 0; + + return 0; +} + +static void kv_init_graphics_levels(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + struct amdgpu_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk; + + if (table && table->count) { + u32 vid_2bit; + + pi->graphics_dpm_level_count = 0; + for (i = 0; i < table->count; i++) { + if (pi->high_voltage_t && + (pi->high_voltage_t < + kv_convert_8bit_index_to_voltage(adev, table->entries[i].v))) + break; + + kv_set_divider_value(adev, i, table->entries[i].clk); + vid_2bit = kv_convert_vid7_to_vid2(adev, + &pi->sys_info.vid_mapping_table, + table->entries[i].v); + kv_set_vid(adev, i, vid_2bit); + kv_set_at(adev, i, pi->at[i]); + kv_dpm_power_level_enabled_for_throttle(adev, i, true); + pi->graphics_dpm_level_count++; + } + } else { + struct sumo_sclk_voltage_mapping_table *table = + &pi->sys_info.sclk_voltage_mapping_table; + + pi->graphics_dpm_level_count = 0; + for (i = 0; i < table->num_max_dpm_entries; i++) { + if (pi->high_voltage_t && + pi->high_voltage_t < + kv_convert_2bit_index_to_voltage(adev, table->entries[i].vid_2bit)) + break; + + kv_set_divider_value(adev, i, table->entries[i].sclk_frequency); + kv_set_vid(adev, i, table->entries[i].vid_2bit); + kv_set_at(adev, i, pi->at[i]); + kv_dpm_power_level_enabled_for_throttle(adev, i, true); + pi->graphics_dpm_level_count++; + } + } + + for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) + kv_dpm_power_level_enable(adev, i, false); +} + +static void kv_enable_new_levels(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i; + + for (i = 0; i < SMU7_MAX_LEVELS_GRAPHICS; i++) { + if (i >= pi->lowest_valid && i <= pi->highest_valid) + kv_dpm_power_level_enable(adev, i, true); + } +} + +static int kv_set_enabled_level(struct amdgpu_device *adev, u32 level) +{ + u32 new_mask = (1 << level); + + return amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + new_mask); +} + +static int kv_set_enabled_levels(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + u32 i, new_mask = 0; + + for (i = pi->lowest_valid; i <= pi->highest_valid; i++) + new_mask |= (1 << i); + + return amdgpu_kv_send_msg_to_smc_with_parameter(adev, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + new_mask); +} + +static void kv_program_nbps_index_settings(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps) +{ + struct kv_ps *new_ps = kv_get_ps(new_rps); + struct kv_power_info *pi = kv_get_pi(adev); + u32 nbdpmconfig1; + + if (adev->asic_type == CHIP_KABINI || adev->asic_type == CHIP_MULLINS) + return; + + if (pi->sys_info.nb_dpm_enable) { + nbdpmconfig1 = RREG32_SMC(ixNB_DPM_CONFIG_1); + nbdpmconfig1 &= ~(NB_DPM_CONFIG_1__Dpm0PgNbPsLo_MASK | + NB_DPM_CONFIG_1__Dpm0PgNbPsHi_MASK | + NB_DPM_CONFIG_1__DpmXNbPsLo_MASK | + NB_DPM_CONFIG_1__DpmXNbPsHi_MASK); + nbdpmconfig1 |= (new_ps->dpm0_pg_nb_ps_lo << NB_DPM_CONFIG_1__Dpm0PgNbPsLo__SHIFT) | + (new_ps->dpm0_pg_nb_ps_hi << NB_DPM_CONFIG_1__Dpm0PgNbPsHi__SHIFT) | + (new_ps->dpmx_nb_ps_lo << NB_DPM_CONFIG_1__DpmXNbPsLo__SHIFT) | + (new_ps->dpmx_nb_ps_hi << NB_DPM_CONFIG_1__DpmXNbPsHi__SHIFT); + WREG32_SMC(ixNB_DPM_CONFIG_1, nbdpmconfig1); + } +} + +static int kv_set_thermal_temperature_range(struct amdgpu_device *adev, + int min_temp, int max_temp) +{ + int low_temp = 0 * 1000; + int high_temp = 255 * 1000; + u32 tmp; + + if (low_temp < min_temp) + low_temp = min_temp; + if (high_temp > max_temp) + high_temp = max_temp; + if (high_temp < low_temp) { + DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); + return -EINVAL; + } + + tmp = RREG32_SMC(ixCG_THERMAL_INT_CTRL); + tmp &= ~(CG_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK | + CG_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK); + tmp |= ((49 + (high_temp / 1000)) << CG_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT) | + ((49 + (low_temp / 1000)) << CG_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT); + WREG32_SMC(ixCG_THERMAL_INT_CTRL, tmp); + + adev->pm.dpm.thermal.min_temp = low_temp; + adev->pm.dpm.thermal.max_temp = high_temp; + + return 0; +} + +union igp_info { + struct _ATOM_INTEGRATED_SYSTEM_INFO info; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; + struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_8 info_8; +}; + +static int kv_parse_sys_info_table(struct amdgpu_device *adev) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct amdgpu_mode_info *mode_info = &adev->mode_info; + int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); + union igp_info *igp_info; + u8 frev, crev; + u16 data_offset; + int i; + + if (amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) { + igp_info = (union igp_info *)(mode_info->atom_context->bios + + data_offset); + + if (crev != 8) { + DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); + return -EINVAL; + } + pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_8.ulBootUpEngineClock); + pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_8.ulBootUpUMAClock); + pi->sys_info.bootup_nb_voltage_index = + le16_to_cpu(igp_info->info_8.usBootUpNBVoltage); + if (igp_info->info_8.ucHtcTmpLmt == 0) + pi->sys_info.htc_tmp_lmt = 203; + else + pi->sys_info.htc_tmp_lmt = igp_info->info_8.ucHtcTmpLmt; + if (igp_info->info_8.ucHtcHystLmt == 0) + pi->sys_info.htc_hyst_lmt = 5; + else + pi->sys_info.htc_hyst_lmt = igp_info->info_8.ucHtcHystLmt; + if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { + DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); + } + + if (le32_to_cpu(igp_info->info_8.ulSystemConfig) & (1 << 3)) + pi->sys_info.nb_dpm_enable = true; + else + pi->sys_info.nb_dpm_enable = false; + + for (i = 0; i < KV_NUM_NBPSTATES; i++) { + pi->sys_info.nbp_memory_clock[i] = + le32_to_cpu(igp_info->info_8.ulNbpStateMemclkFreq[i]); + pi->sys_info.nbp_n_clock[i] = + le32_to_cpu(igp_info->info_8.ulNbpStateNClkFreq[i]); + } + if (le32_to_cpu(igp_info->info_8.ulGPUCapInfo) & + SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) + pi->caps_enable_dfs_bypass = true; + + sumo_construct_sclk_voltage_mapping_table(adev, + &pi->sys_info.sclk_voltage_mapping_table, + igp_info->info_8.sAvail_SCLK); + + sumo_construct_vid_mapping_table(adev, + &pi->sys_info.vid_mapping_table, + igp_info->info_8.sAvail_SCLK); + + kv_construct_max_power_limits_table(adev, + &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac); + } + return 0; +} + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; +}; + +union pplib_clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; +}; + +union pplib_power_state { + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; +}; + +static void kv_patch_boot_state(struct amdgpu_device *adev, + struct kv_ps *ps) +{ + struct kv_power_info *pi = kv_get_pi(adev); + + ps->num_levels = 1; + ps->levels[0] = pi->boot_pl; +} + +static void kv_parse_pplib_non_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, + u8 table_rev) +{ + struct kv_ps *ps = kv_get_ps(rps); + + rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); + rps->class = le16_to_cpu(non_clock_info->usClassification); + rps->class2 = le16_to_cpu(non_clock_info->usClassification2); + + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { + rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); + rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); + } else { + rps->vclk = 0; + rps->dclk = 0; + } + + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { + adev->pm.dpm.boot_ps = rps; + kv_patch_boot_state(adev, ps); + } + if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + adev->pm.dpm.uvd_ps = rps; +} + +static void kv_parse_pplib_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, int index, + union pplib_clock_info *clock_info) +{ + struct kv_power_info *pi = kv_get_pi(adev); + struct kv_ps *ps = kv_get_ps(rps); + struct kv_pl *pl = &ps->levels[index]; + u32 sclk; + + sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); + sclk |= clock_info->sumo.ucEngineClockHigh << 16; + pl->sclk = sclk; + pl->vddc_index = clock_info->sumo.vddcIndex; + + ps->num_levels = index + 1; + + if (pi->caps_sclk_ds) { + pl->ds_divider_index = 5; + pl->ss_divider_index = 5; + } +} + +static int kv_parse_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j, k, non_clock_array_index, clock_array_index; + union pplib_clock_info *clock_info; + struct _StateArray *state_array; + struct _ClockInfoArray *clock_info_array; + struct _NonClockInfoArray *non_clock_info_array; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + u8 *power_state_offset; + struct kv_ps *ps; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + amdgpu_add_thermal_controller(adev); + + state_array = (struct _StateArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset)); + clock_info_array = (struct _ClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); + non_clock_info_array = (struct _NonClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + + adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct amdgpu_ps), + GFP_KERNEL); + if (!adev->pm.dpm.ps) + return -ENOMEM; + power_state_offset = (u8 *)state_array->states; + for (i = 0; i < state_array->ucNumEntries; i++) { + u8 *idx; + power_state = (union pplib_power_state *)power_state_offset; + non_clock_array_index = power_state->v2.nonClockInfoIndex; + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + &non_clock_info_array->nonClockInfo[non_clock_array_index]; + ps = kzalloc(sizeof(struct kv_ps), GFP_KERNEL); + if (ps == NULL) { + kfree(adev->pm.dpm.ps); + return -ENOMEM; + } + adev->pm.dpm.ps[i].ps_priv = ps; + k = 0; + idx = (u8 *)&power_state->v2.clockInfoIndex[0]; + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = idx[j]; + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) + break; + clock_info = (union pplib_clock_info *) + ((u8 *)&clock_info_array->clockInfo[0] + + (clock_array_index * clock_info_array->ucEntrySize)); + kv_parse_pplib_clock_info(adev, + &adev->pm.dpm.ps[i], k, + clock_info); + k++; + } + kv_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], + non_clock_info, + non_clock_info_array->ucEntrySize); + power_state_offset += 2 + power_state->v2.ucNumDPMLevels; + } + adev->pm.dpm.num_ps = state_array->ucNumEntries; + + /* fill in the vce power states */ + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { + u32 sclk; + clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; + sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); + sclk |= clock_info->sumo.ucEngineClockHigh << 16; + adev->pm.dpm.vce_states[i].sclk = sclk; + adev->pm.dpm.vce_states[i].mclk = 0; + } + + return 0; +} + +static int kv_dpm_init(struct amdgpu_device *adev) +{ + struct kv_power_info *pi; + int ret, i; + + pi = kzalloc(sizeof(struct kv_power_info), GFP_KERNEL); + if (pi == NULL) + return -ENOMEM; + adev->pm.dpm.priv = pi; + + ret = amdgpu_get_platform_caps(adev); + if (ret) + return ret; + + ret = amdgpu_parse_extended_power_table(adev); + if (ret) + return ret; + + for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) + pi->at[i] = TRINITY_AT_DFLT; + + pi->sram_end = SMC_RAM_END; + + pi->enable_nb_dpm = true; + + pi->caps_power_containment = true; + pi->caps_cac = true; + pi->enable_didt = false; + if (pi->enable_didt) { + pi->caps_sq_ramping = true; + pi->caps_db_ramping = true; + pi->caps_td_ramping = true; + pi->caps_tcp_ramping = true; + } + + if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) + pi->caps_sclk_ds = true; + else + pi->caps_sclk_ds = false; + + pi->enable_auto_thermal_throttling = true; + pi->disable_nb_ps3_in_battery = false; + if (amdgpu_bapm == 0) + pi->bapm_enable = false; + else + pi->bapm_enable = true; + pi->voltage_drop_t = 0; + pi->caps_sclk_throttle_low_notification = false; + pi->caps_fps = false; /* true? */ + pi->caps_uvd_pg = (adev->pg_flags & AMD_PG_SUPPORT_UVD) ? true : false; + pi->caps_uvd_dpm = true; + pi->caps_vce_pg = (adev->pg_flags & AMD_PG_SUPPORT_VCE) ? true : false; + pi->caps_samu_pg = (adev->pg_flags & AMD_PG_SUPPORT_SAMU) ? true : false; + pi->caps_acp_pg = (adev->pg_flags & AMD_PG_SUPPORT_ACP) ? true : false; + pi->caps_stable_p_state = false; + + ret = kv_parse_sys_info_table(adev); + if (ret) + return ret; + + kv_patch_voltage_values(adev); + kv_construct_boot_state(adev); + + ret = kv_parse_power_table(adev); + if (ret) + return ret; + + pi->enable_dpm = true; + + return 0; +} + +static void +kv_dpm_debugfs_print_current_performance_level(void *handle, + struct seq_file *m) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + u32 current_index = + (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; + u32 sclk, tmp; + u16 vddc; + + if (current_index >= SMU__NUM_SCLK_DPM_STATE) { + seq_printf(m, "invalid dpm profile %d\n", current_index); + } else { + sclk = be32_to_cpu(pi->graphics_level[current_index].SclkFrequency); + tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) & + SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >> + SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT; + vddc = kv_convert_8bit_index_to_voltage(adev, (u16)tmp); + seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en"); + seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en"); + seq_printf(m, "power level %d sclk: %u vddc: %u\n", + current_index, sclk, vddc); + } +} + +static void +kv_dpm_print_power_state(void *handle, void *request_ps) +{ + int i; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct kv_ps *ps = kv_get_ps(rps); + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + amdgpu_dpm_print_class_info(rps->class, rps->class2); + amdgpu_dpm_print_cap_info(rps->caps); + printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + for (i = 0; i < ps->num_levels; i++) { + struct kv_pl *pl = &ps->levels[i]; + printk("\t\tpower level %d sclk: %u vddc: %u\n", + i, pl->sclk, + kv_convert_8bit_index_to_voltage(adev, pl->vddc_index)); + } + amdgpu_dpm_print_ps_status(adev, rps); +} + +static void kv_dpm_fini(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) { + kfree(adev->pm.dpm.ps[i].ps_priv); + } + kfree(adev->pm.dpm.ps); + kfree(adev->pm.dpm.priv); + amdgpu_free_extended_power_table(adev); +} + +static void kv_dpm_display_configuration_changed(void *handle) +{ + +} + +static u32 kv_dpm_get_sclk(void *handle, bool low) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + struct kv_ps *requested_state = kv_get_ps(&pi->requested_rps); + + if (low) + return requested_state->levels[0].sclk; + else + return requested_state->levels[requested_state->num_levels - 1].sclk; +} + +static u32 kv_dpm_get_mclk(void *handle, bool low) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + + return pi->sys_info.bootup_uma_clk; +} + +/* get temperature in millidegrees */ +static int kv_dpm_get_temp(void *handle) +{ + u32 temp; + int actual_temp = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + temp = RREG32_SMC(0xC0300E0C); + + if (temp) + actual_temp = (temp / 8) - 49; + else + actual_temp = 0; + + actual_temp = actual_temp * 1000; + + return actual_temp; +} + +static int kv_dpm_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->powerplay.pp_funcs = &kv_dpm_funcs; + adev->powerplay.pp_handle = adev; + kv_dpm_set_irq_funcs(adev); + + return 0; +} + +static int kv_dpm_late_init(void *handle) +{ + /* powerdown unused blocks for now */ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!adev->pm.dpm_enabled) + return 0; + + kv_dpm_powergate_acp(adev, true); + kv_dpm_powergate_samu(adev, true); + + return 0; +} + +static int kv_dpm_sw_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, + &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, + &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + /* default to balanced state */ + adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO; + adev->pm.default_sclk = adev->clock.default_sclk; + adev->pm.default_mclk = adev->clock.default_mclk; + adev->pm.current_sclk = adev->clock.default_sclk; + adev->pm.current_mclk = adev->clock.default_mclk; + adev->pm.int_thermal_type = THERMAL_TYPE_NONE; + + if (amdgpu_dpm == 0) + return 0; + + INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); + mutex_lock(&adev->pm.mutex); + ret = kv_dpm_init(adev); + if (ret) + goto dpm_failed; + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + if (amdgpu_dpm == 1) + amdgpu_pm_print_power_states(adev); + mutex_unlock(&adev->pm.mutex); + DRM_INFO("amdgpu: dpm initialized\n"); + + return 0; + +dpm_failed: + kv_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + DRM_ERROR("amdgpu: dpm initialization failed\n"); + return ret; +} + +static int kv_dpm_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + flush_work(&adev->pm.dpm.thermal.work); + + mutex_lock(&adev->pm.mutex); + kv_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + + return 0; +} + +static int kv_dpm_hw_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!amdgpu_dpm) + return 0; + + mutex_lock(&adev->pm.mutex); + kv_dpm_setup_asic(adev); + ret = kv_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + amdgpu_pm_compute_clocks(adev); + return ret; +} + +static int kv_dpm_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + kv_dpm_disable(adev); + mutex_unlock(&adev->pm.mutex); + } + + return 0; +} + +static int kv_dpm_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + /* disable dpm */ + kv_dpm_disable(adev); + /* reset the power state */ + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + mutex_unlock(&adev->pm.mutex); + } + return 0; +} + +static int kv_dpm_resume(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + /* asic init will reset to the boot state */ + mutex_lock(&adev->pm.mutex); + kv_dpm_setup_asic(adev); + ret = kv_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + if (adev->pm.dpm_enabled) + amdgpu_pm_compute_clocks(adev); + } + return 0; +} + +static bool kv_dpm_is_idle(void *handle) +{ + return true; +} + +static int kv_dpm_wait_for_idle(void *handle) +{ + return 0; +} + + +static int kv_dpm_soft_reset(void *handle) +{ + return 0; +} + +static int kv_dpm_set_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *src, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 cg_thermal_int; + + switch (type) { + case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); + break; + default: + break; + } + break; + + case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(ixCG_THERMAL_INT_CTRL); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + WREG32_SMC(ixCG_THERMAL_INT_CTRL, cg_thermal_int); + break; + default: + break; + } + break; + + default: + break; + } + return 0; +} + +static int kv_dpm_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + bool queue_thermal = false; + + if (entry == NULL) + return -EINVAL; + + switch (entry->src_id) { + case 230: /* thermal low to high */ + DRM_DEBUG("IH: thermal low to high\n"); + adev->pm.dpm.thermal.high_to_low = false; + queue_thermal = true; + break; + case 231: /* thermal high to low */ + DRM_DEBUG("IH: thermal high to low\n"); + adev->pm.dpm.thermal.high_to_low = true; + queue_thermal = true; + break; + default: + break; + } + + if (queue_thermal) + schedule_work(&adev->pm.dpm.thermal.work); + + return 0; +} + +static int kv_dpm_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int kv_dpm_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static inline bool kv_are_power_levels_equal(const struct kv_pl *kv_cpl1, + const struct kv_pl *kv_cpl2) +{ + return ((kv_cpl1->sclk == kv_cpl2->sclk) && + (kv_cpl1->vddc_index == kv_cpl2->vddc_index) && + (kv_cpl1->ds_divider_index == kv_cpl2->ds_divider_index) && + (kv_cpl1->force_nbp_state == kv_cpl2->force_nbp_state)); +} + +static int kv_check_state_equal(void *handle, + void *current_ps, + void *request_ps, + bool *equal) +{ + struct kv_ps *kv_cps; + struct kv_ps *kv_rps; + int i; + struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) + return -EINVAL; + + kv_cps = kv_get_ps(cps); + kv_rps = kv_get_ps(rps); + + if (kv_cps == NULL) { + *equal = false; + return 0; + } + + if (kv_cps->num_levels != kv_rps->num_levels) { + *equal = false; + return 0; + } + + for (i = 0; i < kv_cps->num_levels; i++) { + if (!kv_are_power_levels_equal(&(kv_cps->levels[i]), + &(kv_rps->levels[i]))) { + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); + *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); + + return 0; +} + +static int kv_dpm_read_sensor(void *handle, int idx, + void *value, int *size) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct kv_power_info *pi = kv_get_pi(adev); + uint32_t sclk; + u32 pl_index = + (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) & + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >> + TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT; + + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + if (pl_index < SMU__NUM_SCLK_DPM_STATE) { + sclk = be32_to_cpu( + pi->graphics_level[pl_index].SclkFrequency); + *((uint32_t *)value) = sclk; + *size = 4; + return 0; + } + return -EINVAL; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = kv_dpm_get_temp(adev); + *size = 4; + return 0; + default: + return -EINVAL; + } +} + +static int kv_set_powergating_by_smu(void *handle, + uint32_t block_type, bool gate) +{ + switch (block_type) { + case AMD_IP_BLOCK_TYPE_UVD: + kv_dpm_powergate_uvd(handle, gate); + break; + case AMD_IP_BLOCK_TYPE_VCE: + kv_dpm_powergate_vce(handle, gate); + break; + default: + break; + } + return 0; +} + +static const struct amd_ip_funcs kv_dpm_ip_funcs = { + .name = "kv_dpm", + .early_init = kv_dpm_early_init, + .late_init = kv_dpm_late_init, + .sw_init = kv_dpm_sw_init, + .sw_fini = kv_dpm_sw_fini, + .hw_init = kv_dpm_hw_init, + .hw_fini = kv_dpm_hw_fini, + .suspend = kv_dpm_suspend, + .resume = kv_dpm_resume, + .is_idle = kv_dpm_is_idle, + .wait_for_idle = kv_dpm_wait_for_idle, + .soft_reset = kv_dpm_soft_reset, + .set_clockgating_state = kv_dpm_set_clockgating_state, + .set_powergating_state = kv_dpm_set_powergating_state, +}; + +const struct amdgpu_ip_block_version kv_smu_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 1, + .minor = 0, + .rev = 0, + .funcs = &kv_dpm_ip_funcs, +}; + +static const struct amd_pm_funcs kv_dpm_funcs = { + .pre_set_power_state = &kv_dpm_pre_set_power_state, + .set_power_state = &kv_dpm_set_power_state, + .post_set_power_state = &kv_dpm_post_set_power_state, + .display_configuration_changed = &kv_dpm_display_configuration_changed, + .get_sclk = &kv_dpm_get_sclk, + .get_mclk = &kv_dpm_get_mclk, + .print_power_state = &kv_dpm_print_power_state, + .debugfs_print_current_performance_level = &kv_dpm_debugfs_print_current_performance_level, + .force_performance_level = &kv_dpm_force_performance_level, + .set_powergating_by_smu = kv_set_powergating_by_smu, + .enable_bapm = &kv_dpm_enable_bapm, + .get_vce_clock_state = amdgpu_get_vce_clock_state, + .check_state_equal = kv_check_state_equal, + .read_sensor = &kv_dpm_read_sensor, +}; + +static const struct amdgpu_irq_src_funcs kv_dpm_irq_funcs = { + .set = kv_dpm_set_interrupt_state, + .process = kv_dpm_process_interrupt, +}; + +static void kv_dpm_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; + adev->pm.dpm.thermal.irq.funcs = &kv_dpm_irq_funcs; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h new file mode 100644 index 000000000000..6df0ed41317c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_dpm.h @@ -0,0 +1,229 @@ +/* + * Copyright 2013 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 __KV_DPM_H__ +#define __KV_DPM_H__ + +#define SMU__NUM_SCLK_DPM_STATE 8 +#define SMU__NUM_MCLK_DPM_LEVELS 4 +#define SMU__NUM_LCLK_DPM_LEVELS 8 +#define SMU__NUM_PCIE_DPM_LEVELS 0 /* ??? */ +#include "smu7_fusion.h" +#include "ppsmc.h" + +#define SUMO_MAX_HARDWARE_POWERLEVELS 5 + +#define SUMO_MAX_NUMBER_VOLTAGES 4 + +struct sumo_vid_mapping_entry { + u16 vid_2bit; + u16 vid_7bit; +}; + +struct sumo_vid_mapping_table { + u32 num_entries; + struct sumo_vid_mapping_entry entries[SUMO_MAX_NUMBER_VOLTAGES]; +}; + +struct sumo_sclk_voltage_mapping_entry { + u32 sclk_frequency; + u16 vid_2bit; + u16 rsv; +}; + +struct sumo_sclk_voltage_mapping_table { + u32 num_max_dpm_entries; + struct sumo_sclk_voltage_mapping_entry entries[SUMO_MAX_HARDWARE_POWERLEVELS]; +}; + +#define TRINITY_AT_DFLT 30 + +#define KV_NUM_NBPSTATES 4 + +enum kv_pt_config_reg_type { + KV_CONFIGREG_MMR = 0, + KV_CONFIGREG_SMC_IND, + KV_CONFIGREG_DIDT_IND, + KV_CONFIGREG_CACHE, + KV_CONFIGREG_MAX +}; + +struct kv_pt_config_reg { + u32 offset; + u32 mask; + u32 shift; + u32 value; + enum kv_pt_config_reg_type type; +}; + +struct kv_lcac_config_values { + u32 block_id; + u32 signal_id; + u32 t; +}; + +struct kv_lcac_config_reg { + u32 cntl; + u32 block_mask; + u32 block_shift; + u32 signal_mask; + u32 signal_shift; + u32 t_mask; + u32 t_shift; + u32 enable_mask; + u32 enable_shift; +}; + +struct kv_pl { + u32 sclk; + u8 vddc_index; + u8 ds_divider_index; + u8 ss_divider_index; + u8 allow_gnb_slow; + u8 force_nbp_state; + u8 display_wm; + u8 vce_wm; +}; + +struct kv_ps { + struct kv_pl levels[SUMO_MAX_HARDWARE_POWERLEVELS]; + u32 num_levels; + bool need_dfs_bypass; + u8 dpm0_pg_nb_ps_lo; + u8 dpm0_pg_nb_ps_hi; + u8 dpmx_nb_ps_lo; + u8 dpmx_nb_ps_hi; +}; + +struct kv_sys_info { + u32 bootup_uma_clk; + u32 bootup_sclk; + u32 dentist_vco_freq; + u32 nb_dpm_enable; + u32 nbp_memory_clock[KV_NUM_NBPSTATES]; + u32 nbp_n_clock[KV_NUM_NBPSTATES]; + u16 bootup_nb_voltage_index; + u8 htc_tmp_lmt; + u8 htc_hyst_lmt; + struct sumo_sclk_voltage_mapping_table sclk_voltage_mapping_table; + struct sumo_vid_mapping_table vid_mapping_table; + u32 uma_channel_number; +}; + +struct kv_power_info { + u32 at[SUMO_MAX_HARDWARE_POWERLEVELS]; + u32 voltage_drop_t; + struct kv_sys_info sys_info; + struct kv_pl boot_pl; + bool enable_nb_ps_policy; + bool disable_nb_ps3_in_battery; + bool video_start; + bool battery_state; + u32 lowest_valid; + u32 highest_valid; + u16 high_voltage_t; + bool cac_enabled; + bool bapm_enable; + /* smc offsets */ + u32 sram_end; + u32 dpm_table_start; + u32 soft_regs_start; + /* dpm SMU tables */ + u8 graphics_dpm_level_count; + u8 uvd_level_count; + u8 vce_level_count; + u8 acp_level_count; + u8 samu_level_count; + u16 fps_high_t; + SMU7_Fusion_GraphicsLevel graphics_level[SMU__NUM_SCLK_DPM_STATE]; + SMU7_Fusion_ACPILevel acpi_level; + SMU7_Fusion_UvdLevel uvd_level[SMU7_MAX_LEVELS_UVD]; + SMU7_Fusion_ExtClkLevel vce_level[SMU7_MAX_LEVELS_VCE]; + SMU7_Fusion_ExtClkLevel acp_level[SMU7_MAX_LEVELS_ACP]; + SMU7_Fusion_ExtClkLevel samu_level[SMU7_MAX_LEVELS_SAMU]; + u8 uvd_boot_level; + u8 vce_boot_level; + u8 acp_boot_level; + u8 samu_boot_level; + u8 uvd_interval; + u8 vce_interval; + u8 acp_interval; + u8 samu_interval; + u8 graphics_boot_level; + u8 graphics_interval; + u8 graphics_therm_throttle_enable; + u8 graphics_voltage_change_enable; + u8 graphics_clk_slow_enable; + u8 graphics_clk_slow_divider; + u8 fps_low_t; + u32 low_sclk_interrupt_t; + bool uvd_power_gated; + bool vce_power_gated; + bool acp_power_gated; + bool samu_power_gated; + bool nb_dpm_enabled; + /* flags */ + bool enable_didt; + bool enable_dpm; + bool enable_auto_thermal_throttling; + bool enable_nb_dpm; + /* caps */ + bool caps_cac; + bool caps_power_containment; + bool caps_sq_ramping; + bool caps_db_ramping; + bool caps_td_ramping; + bool caps_tcp_ramping; + bool caps_sclk_throttle_low_notification; + bool caps_fps; + bool caps_uvd_dpm; + bool caps_uvd_pg; + bool caps_vce_pg; + bool caps_samu_pg; + bool caps_acp_pg; + bool caps_stable_p_state; + bool caps_enable_dfs_bypass; + bool caps_sclk_ds; + struct amdgpu_ps current_rps; + struct kv_ps current_ps; + struct amdgpu_ps requested_rps; + struct kv_ps requested_ps; +}; + +/* XXX are these ok? */ +#define KV_TEMP_RANGE_MIN (90 * 1000) +#define KV_TEMP_RANGE_MAX (120 * 1000) + +/* kv_smc.c */ +int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id); +int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask); +int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, + PPSMC_Msg msg, u32 parameter); +int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit); +int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable); +int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable); +int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/kv_smc.c b/drivers/gpu/drm/amd/pm/powerplay/kv_smc.c new file mode 100644 index 000000000000..2d9ab6b8be66 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/kv_smc.c @@ -0,0 +1,218 @@ +/* + * Copyright 2013 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include "amdgpu.h" +#include "cikd.h" +#include "kv_dpm.h" + +#include "smu/smu_7_0_0_d.h" +#include "smu/smu_7_0_0_sh_mask.h" + +int amdgpu_kv_notify_message_to_smu(struct amdgpu_device *adev, u32 id) +{ + u32 i; + u32 tmp = 0; + + WREG32(mmSMC_MESSAGE_0, id & SMC_MESSAGE_0__SMC_MSG_MASK); + + for (i = 0; i < adev->usec_timeout; i++) { + if ((RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK) != 0) + break; + udelay(1); + } + tmp = RREG32(mmSMC_RESP_0) & SMC_RESP_0__SMC_RESP_MASK; + + if (tmp != 1) { + if (tmp == 0xFF) + return -EINVAL; + else if (tmp == 0xFE) + return -EINVAL; + } + + return 0; +} + +int amdgpu_kv_dpm_get_enable_mask(struct amdgpu_device *adev, u32 *enable_mask) +{ + int ret; + + ret = amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_SCLKDPM_GetEnabledMask); + + if (ret == 0) + *enable_mask = RREG32_SMC(ixSMC_SYSCON_MSG_ARG_0); + + return ret; +} + +int amdgpu_kv_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, + PPSMC_Msg msg, u32 parameter) +{ + + WREG32(mmSMC_MSG_ARG_0, parameter); + + return amdgpu_kv_notify_message_to_smu(adev, msg); +} + +static int kv_set_smc_sram_address(struct amdgpu_device *adev, + u32 smc_address, u32 limit) +{ + if (smc_address & 3) + return -EINVAL; + if ((smc_address + 3) > limit) + return -EINVAL; + + WREG32(mmSMC_IND_INDEX_0, smc_address); + WREG32_P(mmSMC_IND_ACCESS_CNTL, 0, + ~SMC_IND_ACCESS_CNTL__AUTO_INCREMENT_IND_0_MASK); + + return 0; +} + +int amdgpu_kv_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit) +{ + int ret; + + ret = kv_set_smc_sram_address(adev, smc_address, limit); + if (ret) + return ret; + + *value = RREG32(mmSMC_IND_DATA_0); + return 0; +} + +int amdgpu_kv_smc_dpm_enable(struct amdgpu_device *adev, bool enable) +{ + if (enable) + return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Enable); + else + return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DPM_Disable); +} + +int amdgpu_kv_smc_bapm_enable(struct amdgpu_device *adev, bool enable) +{ + if (enable) + return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_EnableBAPM); + else + return amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_DisableBAPM); +} + +int amdgpu_kv_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit) +{ + int ret; + u32 data, original_data, addr, extra_shift, t_byte, count, mask; + + if ((smc_start_address + byte_count) > limit) + return -EINVAL; + + addr = smc_start_address; + t_byte = addr & 3; + + /* RMW for the initial bytes */ + if (t_byte != 0) { + addr -= t_byte; + + ret = kv_set_smc_sram_address(adev, addr, limit); + if (ret) + return ret; + + original_data = RREG32(mmSMC_IND_DATA_0); + + data = 0; + mask = 0; + count = 4; + while (count > 0) { + if (t_byte > 0) { + mask = (mask << 8) | 0xff; + t_byte--; + } else if (byte_count > 0) { + data = (data << 8) + *src++; + byte_count--; + mask <<= 8; + } else { + data <<= 8; + mask = (mask << 8) | 0xff; + } + count--; + } + + data |= original_data & mask; + + ret = kv_set_smc_sram_address(adev, addr, limit); + if (ret) + return ret; + + WREG32(mmSMC_IND_DATA_0, data); + + addr += 4; + } + + while (byte_count >= 4) { + /* SMC address space is BE */ + data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; + + ret = kv_set_smc_sram_address(adev, addr, limit); + if (ret) + return ret; + + WREG32(mmSMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + /* RMW for the final bytes */ + if (byte_count > 0) { + data = 0; + + ret = kv_set_smc_sram_address(adev, addr, limit); + if (ret) + return ret; + + original_data = RREG32(mmSMC_IND_DATA_0); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* SMC address space is BE */ + data = (data << 8) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + ret = kv_set_smc_sram_address(adev, addr, limit); + if (ret) + return ret; + + WREG32(mmSMC_IND_DATA_0, data); + } + return 0; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/ppsmc.h b/drivers/gpu/drm/amd/pm/powerplay/ppsmc.h new file mode 100644 index 000000000000..8463245f424f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/ppsmc.h @@ -0,0 +1,200 @@ +/* + * Copyright 2011 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 PP_SMC_H +#define PP_SMC_H + +#pragma pack(push, 1) + +#define PPSMC_SWSTATE_FLAG_DC 0x01 +#define PPSMC_SWSTATE_FLAG_UVD 0x02 +#define PPSMC_SWSTATE_FLAG_VCE 0x04 +#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 + +#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 +#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 +#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff + +#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 +#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 +#define PPSMC_SYSTEMFLAG_GDDR5 0x04 +#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO 0x40 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 +#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 +#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x02 + +#define PPSMC_DISPLAY_WATERMARK_LOW 0 +#define PPSMC_DISPLAY_WATERMARK_HIGH 1 + +#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 +#define PPSMC_STATEFLAG_POWERBOOST 0x02 +#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 +#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 + +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +#define PPSMC_Result_OK ((uint8_t)0x01) +#define PPSMC_Result_Failed ((uint8_t)0xFF) + +typedef uint8_t PPSMC_Result; + +#define PPSMC_MSG_Halt ((uint8_t)0x10) +#define PPSMC_MSG_Resume ((uint8_t)0x11) +#define PPSMC_MSG_ZeroLevelsDisabled ((uint8_t)0x13) +#define PPSMC_MSG_OneLevelsDisabled ((uint8_t)0x14) +#define PPSMC_MSG_TwoLevelsDisabled ((uint8_t)0x15) +#define PPSMC_MSG_EnableThermalInterrupt ((uint8_t)0x16) +#define PPSMC_MSG_RunningOnAC ((uint8_t)0x17) +#define PPSMC_MSG_SwitchToSwState ((uint8_t)0x20) +#define PPSMC_MSG_SwitchToInitialState ((uint8_t)0x40) +#define PPSMC_MSG_NoForcedLevel ((uint8_t)0x41) +#define PPSMC_MSG_ForceHigh ((uint8_t)0x42) +#define PPSMC_MSG_ForceMediumOrHigh ((uint8_t)0x43) +#define PPSMC_MSG_SwitchToMinimumPower ((uint8_t)0x51) +#define PPSMC_MSG_ResumeFromMinimumPower ((uint8_t)0x52) +#define PPSMC_MSG_EnableCac ((uint8_t)0x53) +#define PPSMC_MSG_DisableCac ((uint8_t)0x54) +#define PPSMC_TDPClampingActive ((uint8_t)0x59) +#define PPSMC_TDPClampingInactive ((uint8_t)0x5A) +#define PPSMC_StartFanControl ((uint8_t)0x5B) +#define PPSMC_StopFanControl ((uint8_t)0x5C) +#define PPSMC_MSG_NoDisplay ((uint8_t)0x5D) +#define PPSMC_NoDisplay ((uint8_t)0x5D) +#define PPSMC_MSG_HasDisplay ((uint8_t)0x5E) +#define PPSMC_HasDisplay ((uint8_t)0x5E) +#define PPSMC_MSG_UVDPowerOFF ((uint8_t)0x60) +#define PPSMC_MSG_UVDPowerON ((uint8_t)0x61) +#define PPSMC_MSG_EnableULV ((uint8_t)0x62) +#define PPSMC_MSG_DisableULV ((uint8_t)0x63) +#define PPSMC_MSG_EnterULV ((uint8_t)0x64) +#define PPSMC_MSG_ExitULV ((uint8_t)0x65) +#define PPSMC_CACLongTermAvgEnable ((uint8_t)0x6E) +#define PPSMC_CACLongTermAvgDisable ((uint8_t)0x6F) +#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint8_t)0x7A) +#define PPSMC_FlushDataCache ((uint8_t)0x80) +#define PPSMC_MSG_SetEnabledLevels ((uint8_t)0x82) +#define PPSMC_MSG_SetForcedLevels ((uint8_t)0x83) +#define PPSMC_MSG_ResetToDefaults ((uint8_t)0x84) +#define PPSMC_MSG_EnableDTE ((uint8_t)0x87) +#define PPSMC_MSG_DisableDTE ((uint8_t)0x88) +#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint8_t)0x96) +#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint8_t)0x97) +#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) + +/* CI/KV/KB */ +#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) +#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) +#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) +#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) +#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) +#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) +#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) +#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) +#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) +#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) +#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) +#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) +#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) +#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) +#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) +#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) +#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150) +#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151) +#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154) +#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155) +#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156) +#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157) +#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158) +#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159) +#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a) +#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b) +#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) +#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) +#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) +#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) +#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) +#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) +#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) +#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) +#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) +#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) +#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) +#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) +#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) +#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) +#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) +#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) +#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) +#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) + +#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) +#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) + +#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) +#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) + +/* TN */ +#define PPSMC_MSG_DPM_Config ((uint32_t) 0x102) +#define PPSMC_MSG_DPM_ForceState ((uint32_t) 0x104) +#define PPSMC_MSG_PG_SIMD_Config ((uint32_t) 0x108) +#define PPSMC_MSG_Voltage_Cntl_Enable ((uint32_t) 0x109) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint32_t) 0x10a) +#define PPSMC_MSG_VCEPowerOFF ((uint32_t) 0x10e) +#define PPSMC_MSG_VCEPowerON ((uint32_t) 0x10f) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint32_t) 0x112) +#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint32_t) 0x11d) +#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint32_t) 0x11e) +#define PPSMC_MSG_EnableBAPM ((uint32_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint32_t) 0x121) +#define PPSMC_MSG_UVD_DPM_Config ((uint32_t) 0x124) + +#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) +#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) +#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) +#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) + +typedef uint16_t PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h new file mode 100644 index 000000000000..055321f61ca7 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/r600_dpm.h @@ -0,0 +1,127 @@ +/* + * Copyright 2011 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 __R600_DPM_H__ +#define __R600_DPM_H__ + +#define R600_ASI_DFLT 10000 +#define R600_BSP_DFLT 0x41EB +#define R600_BSU_DFLT 0x2 +#define R600_AH_DFLT 5 +#define R600_RLP_DFLT 25 +#define R600_RMP_DFLT 65 +#define R600_LHP_DFLT 40 +#define R600_LMP_DFLT 15 +#define R600_TD_DFLT 0 +#define R600_UTC_DFLT_00 0x24 +#define R600_UTC_DFLT_01 0x22 +#define R600_UTC_DFLT_02 0x22 +#define R600_UTC_DFLT_03 0x22 +#define R600_UTC_DFLT_04 0x22 +#define R600_UTC_DFLT_05 0x22 +#define R600_UTC_DFLT_06 0x22 +#define R600_UTC_DFLT_07 0x22 +#define R600_UTC_DFLT_08 0x22 +#define R600_UTC_DFLT_09 0x22 +#define R600_UTC_DFLT_10 0x22 +#define R600_UTC_DFLT_11 0x22 +#define R600_UTC_DFLT_12 0x22 +#define R600_UTC_DFLT_13 0x22 +#define R600_UTC_DFLT_14 0x22 +#define R600_DTC_DFLT_00 0x24 +#define R600_DTC_DFLT_01 0x22 +#define R600_DTC_DFLT_02 0x22 +#define R600_DTC_DFLT_03 0x22 +#define R600_DTC_DFLT_04 0x22 +#define R600_DTC_DFLT_05 0x22 +#define R600_DTC_DFLT_06 0x22 +#define R600_DTC_DFLT_07 0x22 +#define R600_DTC_DFLT_08 0x22 +#define R600_DTC_DFLT_09 0x22 +#define R600_DTC_DFLT_10 0x22 +#define R600_DTC_DFLT_11 0x22 +#define R600_DTC_DFLT_12 0x22 +#define R600_DTC_DFLT_13 0x22 +#define R600_DTC_DFLT_14 0x22 +#define R600_VRC_DFLT 0x0000C003 +#define R600_VOLTAGERESPONSETIME_DFLT 1000 +#define R600_BACKBIASRESPONSETIME_DFLT 1000 +#define R600_VRU_DFLT 0x3 +#define R600_SPLLSTEPTIME_DFLT 0x1000 +#define R600_SPLLSTEPUNIT_DFLT 0x3 +#define R600_TPU_DFLT 0 +#define R600_TPC_DFLT 0x200 +#define R600_SSTU_DFLT 0 +#define R600_SST_DFLT 0x00C8 +#define R600_GICST_DFLT 0x200 +#define R600_FCT_DFLT 0x0400 +#define R600_FCTU_DFLT 0 +#define R600_CTXCGTT3DRPHC_DFLT 0x20 +#define R600_CTXCGTT3DRSDC_DFLT 0x40 +#define R600_VDDC3DOORPHC_DFLT 0x100 +#define R600_VDDC3DOORSDC_DFLT 0x7 +#define R600_VDDC3DOORSU_DFLT 0 +#define R600_MPLLLOCKTIME_DFLT 100 +#define R600_MPLLRESETTIME_DFLT 150 +#define R600_VCOSTEPPCT_DFLT 20 +#define R600_ENDINGVCOSTEPPCT_DFLT 5 +#define R600_REFERENCEDIVIDER_DFLT 4 + +#define R600_PM_NUMBER_OF_TC 15 +#define R600_PM_NUMBER_OF_SCLKS 20 +#define R600_PM_NUMBER_OF_MCLKS 4 +#define R600_PM_NUMBER_OF_VOLTAGE_LEVELS 4 +#define R600_PM_NUMBER_OF_ACTIVITY_LEVELS 3 + +/* XXX are these ok? */ +#define R600_TEMP_RANGE_MIN (90 * 1000) +#define R600_TEMP_RANGE_MAX (120 * 1000) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +enum r600_power_level { + R600_POWER_LEVEL_LOW = 0, + R600_POWER_LEVEL_MEDIUM = 1, + R600_POWER_LEVEL_HIGH = 2, + R600_POWER_LEVEL_CTXSW = 3, +}; + +enum r600_td { + R600_TD_AUTO, + R600_TD_UP, + R600_TD_DOWN, +}; + +enum r600_display_watermark { + R600_DISPLAY_WATERMARK_LOW = 0, + R600_DISPLAY_WATERMARK_HIGH = 1, +}; + +enum r600_display_gap +{ + R600_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, + R600_PM_DISPLAY_GAP_VBLANK = 1, + R600_PM_DISPLAY_GAP_WATERMARK = 2, + R600_PM_DISPLAY_GAP_IGNORE = 3, +}; +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c new file mode 100644 index 000000000000..ea914b256ebd --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.c @@ -0,0 +1,8079 @@ +/* + * Copyright 2013 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 +#include + +#include "amdgpu.h" +#include "amdgpu_pm.h" +#include "amdgpu_dpm.h" +#include "amdgpu_atombios.h" +#include "amd_pcie.h" +#include "sid.h" +#include "r600_dpm.h" +#include "si_dpm.h" +#include "atom.h" +#include "../include/pptable.h" +#include +#include +#include + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define SMC_RAM_END 0x20000 + +#define SCLK_MIN_DEEPSLEEP_FREQ 1350 + + +/* sizeof(ATOM_PPLIB_EXTENDEDHEADER) */ +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 + +#define BIOS_SCRATCH_4 0x5cd + +MODULE_FIRMWARE("amdgpu/tahiti_smc.bin"); +MODULE_FIRMWARE("amdgpu/pitcairn_smc.bin"); +MODULE_FIRMWARE("amdgpu/pitcairn_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/verde_smc.bin"); +MODULE_FIRMWARE("amdgpu/verde_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/oland_smc.bin"); +MODULE_FIRMWARE("amdgpu/oland_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/hainan_smc.bin"); +MODULE_FIRMWARE("amdgpu/hainan_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/banks_k_2_smc.bin"); + +static const struct amd_pm_funcs si_dpm_funcs; + +union power_info { + struct _ATOM_POWERPLAY_INFO info; + struct _ATOM_POWERPLAY_INFO_V2 info_2; + struct _ATOM_POWERPLAY_INFO_V3 info_3; + struct _ATOM_PPLIB_POWERPLAYTABLE pplib; + struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; + struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; + struct _ATOM_PPLIB_POWERPLAYTABLE4 pplib4; + struct _ATOM_PPLIB_POWERPLAYTABLE5 pplib5; +}; + +union fan_info { + struct _ATOM_PPLIB_FANTABLE fan; + struct _ATOM_PPLIB_FANTABLE2 fan2; + struct _ATOM_PPLIB_FANTABLE3 fan3; +}; + +union pplib_clock_info { + struct _ATOM_PPLIB_R600_CLOCK_INFO r600; + struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; + struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; + struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; + struct _ATOM_PPLIB_SI_CLOCK_INFO si; +}; + +static const u32 r600_utc[R600_PM_NUMBER_OF_TC] = +{ + R600_UTC_DFLT_00, + R600_UTC_DFLT_01, + R600_UTC_DFLT_02, + R600_UTC_DFLT_03, + R600_UTC_DFLT_04, + R600_UTC_DFLT_05, + R600_UTC_DFLT_06, + R600_UTC_DFLT_07, + R600_UTC_DFLT_08, + R600_UTC_DFLT_09, + R600_UTC_DFLT_10, + R600_UTC_DFLT_11, + R600_UTC_DFLT_12, + R600_UTC_DFLT_13, + R600_UTC_DFLT_14, +}; + +static const u32 r600_dtc[R600_PM_NUMBER_OF_TC] = +{ + R600_DTC_DFLT_00, + R600_DTC_DFLT_01, + R600_DTC_DFLT_02, + R600_DTC_DFLT_03, + R600_DTC_DFLT_04, + R600_DTC_DFLT_05, + R600_DTC_DFLT_06, + R600_DTC_DFLT_07, + R600_DTC_DFLT_08, + R600_DTC_DFLT_09, + R600_DTC_DFLT_10, + R600_DTC_DFLT_11, + R600_DTC_DFLT_12, + R600_DTC_DFLT_13, + R600_DTC_DFLT_14, +}; + +static const struct si_cac_config_reg cac_weights_tahiti[] = +{ + { 0x0, 0x0000ffff, 0, 0xc, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x101, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0xc, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x8fc, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x95, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x34e, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x1a1, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0xda, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x46, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x208, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0xe7, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x948, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x167, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x31, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x18e, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_tahiti[] = +{ + { 0x143, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x0001fffe, 1, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x0001fffe, 1, 0x8, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } + +}; + +static const struct si_cac_config_reg cac_override_tahiti[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_tahiti = +{ + ((1 << 16) | 27027), + 6, + 0, + 4, + 95, + { + 0UL, + 0UL, + 4521550UL, + 309631529UL, + -1270850L, + 4513710L, + 40 + }, + 595000000UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_tahiti = +{ + { 1159409, 0, 0, 0, 0 }, + { 777, 0, 0, 0, 0 }, + 2, + 54000, + 127000, + 25, + 2, + 10, + 13, + { 27, 31, 35, 39, 43, 47, 54, 61, 67, 74, 81, 88, 95, 0, 0, 0 }, + { 240888759, 221057860, 235370597, 162287531, 158510299, 131423027, 116673180, 103067515, 87941937, 76209048, 68209175, 64090048, 58301890, 0, 0, 0 }, + { 12024, 11189, 11451, 8411, 7939, 6666, 5681, 4905, 4241, 3720, 3354, 3122, 2890, 0, 0, 0 }, + 85, + false +}; + +static const struct si_dte_data dte_data_tahiti_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x7D0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_new_zealand = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0 }, + { 0x29B, 0x3E9, 0x537, 0x7D2, 0 }, + 0x5, + 0xAFC8, + 0x69, + 0x32, + 1, + 0, + 0x10, + { 0x82, 0xA0, 0xB4, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xDAC, 0x1388, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685, 0x685 }, + 85, + true +}; + +static const struct si_dte_data dte_data_aruba_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_malta = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_cac_config_reg cac_weights_pitcairn[] = +{ + { 0x0, 0x0000ffff, 0, 0x8a, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x24d, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x19, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0xc11, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x7f3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x403, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x367, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x4c9, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x45d, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x36d, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x534, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x5da, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x880, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0x201, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x1f, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5de, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x7b, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x13, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0xf9, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x66, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x13, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x186, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_pitcairn[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x116, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x155, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x92, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x149, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x101, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x119, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x158, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x95, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x14c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x122, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x125, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x128, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x12b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_pitcairn[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_pitcairn = +{ + ((1 << 16) | 27027), + 5, + 0, + 6, + 100, + { + 51600000UL, + 1800000UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_pitcairn = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_curacao_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_curacao_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x1D17, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_neptune_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 45000, + 100, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0x3A2F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_cac_config_reg cac_weights_chelsea_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x2BD, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_chelsea_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x30A, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_heathrow[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x362, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_cape_verde_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x315, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_cape_verde[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_cape_verde[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x9b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x107, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x113, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x0001fffe, 1, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x152, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x146, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_cape_verde[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_cape_verde = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_cape_verde = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_venus_xtx = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x71C, 0xAAB, 0xE39, 0x11C7, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0xD6D8, 0x88B8, 0x1555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_venus_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0xBDA, 0x11C7, 0x17B4, 0x1DA1, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0xAFC8, 0x88B8, 0x238E, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_venus_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x11C7, 0x1AAB, 0x238E, 0x2C72, 0x0 }, + 5, + 55000, + 0x69, + 0xA, + 1, + 0, + 0x3, + { 0x96, 0xB4, 0xFF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x895440, 0x3D0900, 0x989680, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + { 0x88B8, 0x88B8, 0x3555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_cac_config_reg cac_weights_oland[] = +{ + { 0x0, 0x0000ffff, 0, 0x82, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x153, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x52, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x4F, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x135, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0xAC, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x118, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0xBE, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x110, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x4CD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x37, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x27, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0xC3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x35, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0x28, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x26C, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3B2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x99D, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA3F, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0xA, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x34, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x3BA, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x30, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7A, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x100, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_mars_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_mars_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x60, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_oland_pro[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x90, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_weights_oland_xt[] = +{ + { 0x0, 0x0000ffff, 0, 0x43, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0xAF, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x2A, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x29, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0xA0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x59, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x1A5, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1D6, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0x2A3, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x8FD, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x76, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x8A, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0xA3, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x71, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xA6, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x81, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0x3D2, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0x27C, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xA96, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x5, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0xB, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x15, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x36, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x10, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x120, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x32, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x7E, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0x280, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0x7, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0x3C, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0x203, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0xB4, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_oland[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x4, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg lcac_mars_pro[] = +{ + { 0x98, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x98, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x104, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x110, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x14f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x0001fffe, 1, 0x6, SISLANDS_CACCONFIG_CGIND }, + { 0x8c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x143, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x11f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x164, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x167, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16a, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15e, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x161, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x15b, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x0001fffe, 1, 0x2, SISLANDS_CACCONFIG_CGIND }, + { 0x16d, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x170, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x173, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x176, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x179, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17c, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x0001fffe, 1, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0x17f, 0x00000001, 0, 0x1, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_cac_config_reg cac_override_oland[] = +{ + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_oland = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_powertune_data powertune_data_mars_pro = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 7, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static const struct si_dte_data dte_data_oland = +{ + { 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0 }, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + 0, + false +}; + +static const struct si_dte_data dte_data_mars_pro = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 55000, + 105, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xF627, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + +static const struct si_dte_data dte_data_sun_xt = +{ + { 0x1E8480, 0x3D0900, 0x989680, 0x2625A00, 0x0 }, + { 0x0, 0x0, 0x0, 0x0, 0x0 }, + 5, + 55000, + 105, + 0xA, + 1, + 0, + 0x10, + { 0x96, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, + { 0x895440, 0x3D0900, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680, 0x989680 }, + { 0xD555, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, + 90, + true +}; + + +static const struct si_cac_config_reg cac_weights_hainan[] = +{ + { 0x0, 0x0000ffff, 0, 0x2d9, SISLANDS_CACCONFIG_CGIND }, + { 0x0, 0xffff0000, 16, 0x22b, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0x0000ffff, 0, 0x21c, SISLANDS_CACCONFIG_CGIND }, + { 0x1, 0xffff0000, 16, 0x1dc, SISLANDS_CACCONFIG_CGIND }, + { 0x2, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0x0000ffff, 0, 0x24e, SISLANDS_CACCONFIG_CGIND }, + { 0x3, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0x0000ffff, 0, 0x35e, SISLANDS_CACCONFIG_CGIND }, + { 0x5, 0xffff0000, 16, 0x1143, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0x0000ffff, 0, 0xe17, SISLANDS_CACCONFIG_CGIND }, + { 0x6, 0xffff0000, 16, 0x441, SISLANDS_CACCONFIG_CGIND }, + { 0x18f, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0x0000ffff, 0, 0x28b, SISLANDS_CACCONFIG_CGIND }, + { 0x7, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x8, 0xffff0000, 16, 0xabe, SISLANDS_CACCONFIG_CGIND }, + { 0x9, 0x0000ffff, 0, 0xf11, SISLANDS_CACCONFIG_CGIND }, + { 0xa, 0x0000ffff, 0, 0x907, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0x0000ffff, 0, 0xb45, SISLANDS_CACCONFIG_CGIND }, + { 0xb, 0xffff0000, 16, 0xd1e, SISLANDS_CACCONFIG_CGIND }, + { 0xc, 0x0000ffff, 0, 0xa2c, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0x0000ffff, 0, 0x62, SISLANDS_CACCONFIG_CGIND }, + { 0xd, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0xe, 0x0000ffff, 0, 0x1f3, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0x0000ffff, 0, 0x42, SISLANDS_CACCONFIG_CGIND }, + { 0xf, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x10, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0x0000ffff, 0, 0x709, SISLANDS_CACCONFIG_CGIND }, + { 0x11, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x12, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x13, 0xffff0000, 16, 0x3a, SISLANDS_CACCONFIG_CGIND }, + { 0x14, 0x0000ffff, 0, 0x357, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0x0000ffff, 0, 0x9f, SISLANDS_CACCONFIG_CGIND }, + { 0x15, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x4e, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0x0000ffff, 0, 0x314, SISLANDS_CACCONFIG_CGIND }, + { 0x16, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x17, 0x0000ffff, 0, 0x6d, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x18, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0x0000ffff, 0, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x19, 0xffff0000, 16, 0x0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1a, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1b, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1c, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1d, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1e, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x1f, 0xffff0000, 16, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x20, 0x0000ffff, 0, 0, SISLANDS_CACCONFIG_CGIND }, + { 0x6d, 0x0000ffff, 0, 0x1b9, SISLANDS_CACCONFIG_CGIND }, + { 0xFFFFFFFF } +}; + +static const struct si_powertune_data powertune_data_hainan = +{ + ((1 << 16) | 0x6993), + 5, + 0, + 9, + 105, + { + 0UL, + 0UL, + 7194395UL, + 309631529UL, + -1270850L, + 4513710L, + 100 + }, + 117830498UL, + 12, + { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }, + true +}; + +static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev); +static struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev); +static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev); +static struct si_ps *si_get_ps(struct amdgpu_ps *rps); + +static int si_populate_voltage_value(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage); +static int si_get_std_voltage_value(struct amdgpu_device *adev, + SISLANDS_SMC_VOLTAGE_VALUE *voltage, + u16 *std_voltage); +static int si_write_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 value); +static int si_convert_power_level_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level); +static int si_calculate_sclk_params(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk); + +static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev); +static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev); +static void si_dpm_set_irq_funcs(struct amdgpu_device *adev); + +static struct si_power_info *si_get_pi(struct amdgpu_device *adev) +{ + struct si_power_info *pi = adev->pm.dpm.priv; + return pi; +} + +static void si_calculate_leakage_for_v_and_t_formula(const struct ni_leakage_coeffients *coeff, + u16 v, s32 t, u32 ileakage, u32 *leakage) +{ + s64 kt, kv, leakage_w, i_leakage, vddc; + s64 temperature, t_slope, t_intercept, av, bv, t_ref; + s64 tmp; + + i_leakage = div64_s64(drm_int2fixp(ileakage), 100); + vddc = div64_s64(drm_int2fixp(v), 1000); + temperature = div64_s64(drm_int2fixp(t), 1000); + + t_slope = div64_s64(drm_int2fixp(coeff->t_slope), 100000000); + t_intercept = div64_s64(drm_int2fixp(coeff->t_intercept), 100000000); + av = div64_s64(drm_int2fixp(coeff->av), 100000000); + bv = div64_s64(drm_int2fixp(coeff->bv), 100000000); + t_ref = drm_int2fixp(coeff->t_ref); + + tmp = drm_fixp_mul(t_slope, vddc) + t_intercept; + kt = drm_fixp_exp(drm_fixp_mul(tmp, temperature)); + kt = drm_fixp_div(kt, drm_fixp_exp(drm_fixp_mul(tmp, t_ref))); + kv = drm_fixp_mul(av, drm_fixp_exp(drm_fixp_mul(bv, vddc))); + + leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); + + *leakage = drm_fixp2int(leakage_w * 1000); +} + +static void si_calculate_leakage_for_v_and_t(struct amdgpu_device *adev, + const struct ni_leakage_coeffients *coeff, + u16 v, + s32 t, + u32 i_leakage, + u32 *leakage) +{ + si_calculate_leakage_for_v_and_t_formula(coeff, v, t, i_leakage, leakage); +} + +static void si_calculate_leakage_for_v_formula(const struct ni_leakage_coeffients *coeff, + const u32 fixed_kt, u16 v, + u32 ileakage, u32 *leakage) +{ + s64 kt, kv, leakage_w, i_leakage, vddc; + + i_leakage = div64_s64(drm_int2fixp(ileakage), 100); + vddc = div64_s64(drm_int2fixp(v), 1000); + + kt = div64_s64(drm_int2fixp(fixed_kt), 100000000); + kv = drm_fixp_mul(div64_s64(drm_int2fixp(coeff->av), 100000000), + drm_fixp_exp(drm_fixp_mul(div64_s64(drm_int2fixp(coeff->bv), 100000000), vddc))); + + leakage_w = drm_fixp_mul(drm_fixp_mul(drm_fixp_mul(i_leakage, kt), kv), vddc); + + *leakage = drm_fixp2int(leakage_w * 1000); +} + +static void si_calculate_leakage_for_v(struct amdgpu_device *adev, + const struct ni_leakage_coeffients *coeff, + const u32 fixed_kt, + u16 v, + u32 i_leakage, + u32 *leakage) +{ + si_calculate_leakage_for_v_formula(coeff, fixed_kt, v, i_leakage, leakage); +} + + +static void si_update_dte_from_pl2(struct amdgpu_device *adev, + struct si_dte_data *dte_data) +{ + u32 p_limit1 = adev->pm.dpm.tdp_limit; + u32 p_limit2 = adev->pm.dpm.near_tdp_limit; + u32 k = dte_data->k; + u32 t_max = dte_data->max_t; + u32 t_split[5] = { 10, 15, 20, 25, 30 }; + u32 t_0 = dte_data->t0; + u32 i; + + if (p_limit2 != 0 && p_limit2 <= p_limit1) { + dte_data->tdep_count = 3; + + for (i = 0; i < k; i++) { + dte_data->r[i] = + (t_split[i] * (t_max - t_0/(u32)1000) * (1 << 14)) / + (p_limit2 * (u32)100); + } + + dte_data->tdep_r[1] = dte_data->r[4] * 2; + + for (i = 2; i < SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; i++) { + dte_data->tdep_r[i] = dte_data->r[4]; + } + } else { + DRM_ERROR("Invalid PL2! DTE will not be updated.\n"); + } +} + +static struct rv7xx_power_info *rv770_get_pi(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +static struct ni_power_info *ni_get_pi(struct amdgpu_device *adev) +{ + struct ni_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +static struct si_ps *si_get_ps(struct amdgpu_ps *aps) +{ + struct si_ps *ps = aps->ps_priv; + + return ps; +} + +static void si_initialize_powertune_defaults(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + bool update_dte_from_pl2 = false; + + if (adev->asic_type == CHIP_TAHITI) { + si_pi->cac_weights = cac_weights_tahiti; + si_pi->lcac_config = lcac_tahiti; + si_pi->cac_override = cac_override_tahiti; + si_pi->powertune_data = &powertune_data_tahiti; + si_pi->dte_data = dte_data_tahiti; + + switch (adev->pdev->device) { + case 0x6798: + si_pi->dte_data.enable_dte_by_default = true; + break; + case 0x6799: + si_pi->dte_data = dte_data_new_zealand; + break; + case 0x6790: + case 0x6791: + case 0x6792: + case 0x679E: + si_pi->dte_data = dte_data_aruba_pro; + update_dte_from_pl2 = true; + break; + case 0x679B: + si_pi->dte_data = dte_data_malta; + update_dte_from_pl2 = true; + break; + case 0x679A: + si_pi->dte_data = dte_data_tahiti_pro; + update_dte_from_pl2 = true; + break; + default: + if (si_pi->dte_data.enable_dte_by_default == true) + DRM_ERROR("DTE is not enabled!\n"); + break; + } + } else if (adev->asic_type == CHIP_PITCAIRN) { + si_pi->cac_weights = cac_weights_pitcairn; + si_pi->lcac_config = lcac_pitcairn; + si_pi->cac_override = cac_override_pitcairn; + si_pi->powertune_data = &powertune_data_pitcairn; + + switch (adev->pdev->device) { + case 0x6810: + case 0x6818: + si_pi->dte_data = dte_data_curacao_xt; + update_dte_from_pl2 = true; + break; + case 0x6819: + case 0x6811: + si_pi->dte_data = dte_data_curacao_pro; + update_dte_from_pl2 = true; + break; + case 0x6800: + case 0x6806: + si_pi->dte_data = dte_data_neptune_xt; + update_dte_from_pl2 = true; + break; + default: + si_pi->dte_data = dte_data_pitcairn; + break; + } + } else if (adev->asic_type == CHIP_VERDE) { + si_pi->lcac_config = lcac_cape_verde; + si_pi->cac_override = cac_override_cape_verde; + si_pi->powertune_data = &powertune_data_cape_verde; + + switch (adev->pdev->device) { + case 0x683B: + case 0x683F: + case 0x6829: + case 0x6835: + si_pi->cac_weights = cac_weights_cape_verde_pro; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x682C: + si_pi->cac_weights = cac_weights_cape_verde_pro; + si_pi->dte_data = dte_data_sun_xt; + update_dte_from_pl2 = true; + break; + case 0x6825: + case 0x6827: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x6824: + case 0x682D: + si_pi->cac_weights = cac_weights_chelsea_xt; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x682F: + si_pi->cac_weights = cac_weights_chelsea_pro; + si_pi->dte_data = dte_data_cape_verde; + break; + case 0x6820: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_venus_xtx; + break; + case 0x6821: + si_pi->cac_weights = cac_weights_heathrow; + si_pi->dte_data = dte_data_venus_xt; + break; + case 0x6823: + case 0x682B: + case 0x6822: + case 0x682A: + si_pi->cac_weights = cac_weights_chelsea_pro; + si_pi->dte_data = dte_data_venus_pro; + break; + default: + si_pi->cac_weights = cac_weights_cape_verde; + si_pi->dte_data = dte_data_cape_verde; + break; + } + } else if (adev->asic_type == CHIP_OLAND) { + si_pi->lcac_config = lcac_mars_pro; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_mars_pro; + si_pi->dte_data = dte_data_mars_pro; + + switch (adev->pdev->device) { + case 0x6601: + case 0x6621: + case 0x6603: + case 0x6605: + si_pi->cac_weights = cac_weights_mars_pro; + update_dte_from_pl2 = true; + break; + case 0x6600: + case 0x6606: + case 0x6620: + case 0x6604: + si_pi->cac_weights = cac_weights_mars_xt; + update_dte_from_pl2 = true; + break; + case 0x6611: + case 0x6613: + case 0x6608: + si_pi->cac_weights = cac_weights_oland_pro; + update_dte_from_pl2 = true; + break; + case 0x6610: + si_pi->cac_weights = cac_weights_oland_xt; + update_dte_from_pl2 = true; + break; + default: + si_pi->cac_weights = cac_weights_oland; + si_pi->lcac_config = lcac_oland; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_oland; + si_pi->dte_data = dte_data_oland; + break; + } + } else if (adev->asic_type == CHIP_HAINAN) { + si_pi->cac_weights = cac_weights_hainan; + si_pi->lcac_config = lcac_oland; + si_pi->cac_override = cac_override_oland; + si_pi->powertune_data = &powertune_data_hainan; + si_pi->dte_data = dte_data_sun_xt; + update_dte_from_pl2 = true; + } else { + DRM_ERROR("Unknown SI asic revision, failed to initialize PowerTune!\n"); + return; + } + + ni_pi->enable_power_containment = false; + ni_pi->enable_cac = false; + ni_pi->enable_sq_ramping = false; + si_pi->enable_dte = false; + + if (si_pi->powertune_data->enable_powertune_by_default) { + ni_pi->enable_power_containment = true; + ni_pi->enable_cac = true; + if (si_pi->dte_data.enable_dte_by_default) { + si_pi->enable_dte = true; + if (update_dte_from_pl2) + si_update_dte_from_pl2(adev, &si_pi->dte_data); + + } + ni_pi->enable_sq_ramping = true; + } + + ni_pi->driver_calculate_cac_leakage = true; + ni_pi->cac_configuration_required = true; + + if (ni_pi->cac_configuration_required) { + ni_pi->support_cac_long_term_average = true; + si_pi->dyn_powertune_data.l2_lta_window_size = + si_pi->powertune_data->l2_lta_window_size_default; + si_pi->dyn_powertune_data.lts_truncate = + si_pi->powertune_data->lts_truncate_default; + } else { + ni_pi->support_cac_long_term_average = false; + si_pi->dyn_powertune_data.l2_lta_window_size = 0; + si_pi->dyn_powertune_data.lts_truncate = 0; + } + + si_pi->dyn_powertune_data.disable_uvd_powertune = false; +} + +static u32 si_get_smc_power_scaling_factor(struct amdgpu_device *adev) +{ + return 1; +} + +static u32 si_calculate_cac_wintime(struct amdgpu_device *adev) +{ + u32 xclk; + u32 wintime; + u32 cac_window; + u32 cac_window_size; + + xclk = amdgpu_asic_get_xclk(adev); + + if (xclk == 0) + return 0; + + cac_window = RREG32(CG_CAC_CTRL) & CAC_WINDOW_MASK; + cac_window_size = ((cac_window & 0xFFFF0000) >> 16) * (cac_window & 0x0000FFFF); + + wintime = (cac_window_size * 100) / xclk; + + return wintime; +} + +static u32 si_scale_power_for_smc(u32 power_in_watts, u32 scaling_factor) +{ + return power_in_watts; +} + +static int si_calculate_adjusted_tdp_limits(struct amdgpu_device *adev, + bool adjust_polarity, + u32 tdp_adjustment, + u32 *tdp_limit, + u32 *near_tdp_limit) +{ + u32 adjustment_delta, max_tdp_limit; + + if (tdp_adjustment > (u32)adev->pm.dpm.tdp_od_limit) + return -EINVAL; + + max_tdp_limit = ((100 + 100) * adev->pm.dpm.tdp_limit) / 100; + + if (adjust_polarity) { + *tdp_limit = ((100 + tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; + *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted + (*tdp_limit - adev->pm.dpm.tdp_limit); + } else { + *tdp_limit = ((100 - tdp_adjustment) * adev->pm.dpm.tdp_limit) / 100; + adjustment_delta = adev->pm.dpm.tdp_limit - *tdp_limit; + if (adjustment_delta < adev->pm.dpm.near_tdp_limit_adjusted) + *near_tdp_limit = adev->pm.dpm.near_tdp_limit_adjusted - adjustment_delta; + else + *near_tdp_limit = 0; + } + + if ((*tdp_limit <= 0) || (*tdp_limit > max_tdp_limit)) + return -EINVAL; + if ((*near_tdp_limit <= 0) || (*near_tdp_limit > *tdp_limit)) + return -EINVAL; + + return 0; +} + +static int si_populate_smc_tdp_limits(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (ni_pi->enable_power_containment) { + SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; + PP_SIslands_PAPMParameters *papm_parm; + struct amdgpu_ppm_table *ppm = adev->pm.dpm.dyn_state.ppm_table; + u32 scaling_factor = si_get_smc_power_scaling_factor(adev); + u32 tdp_limit; + u32 near_tdp_limit; + int ret; + + if (scaling_factor == 0) + return -EINVAL; + + memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); + + ret = si_calculate_adjusted_tdp_limits(adev, + false, /* ??? */ + adev->pm.dpm.tdp_adjustment, + &tdp_limit, + &near_tdp_limit); + if (ret) + return ret; + + smc_table->dpm2Params.TDPLimit = + cpu_to_be32(si_scale_power_for_smc(tdp_limit, scaling_factor) * 1000); + smc_table->dpm2Params.NearTDPLimit = + cpu_to_be32(si_scale_power_for_smc(near_tdp_limit, scaling_factor) * 1000); + smc_table->dpm2Params.SafePowerLimit = + cpu_to_be32(si_scale_power_for_smc((near_tdp_limit * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); + + ret = amdgpu_si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, TDPLimit)), + (u8 *)(&(smc_table->dpm2Params.TDPLimit)), + sizeof(u32) * 3, + si_pi->sram_end); + if (ret) + return ret; + + if (si_pi->enable_ppm) { + papm_parm = &si_pi->papm_parm; + memset(papm_parm, 0, sizeof(PP_SIslands_PAPMParameters)); + papm_parm->NearTDPLimitTherm = cpu_to_be32(ppm->dgpu_tdp); + papm_parm->dGPU_T_Limit = cpu_to_be32(ppm->tj_max); + papm_parm->dGPU_T_Warning = cpu_to_be32(95); + papm_parm->dGPU_T_Hysteresis = cpu_to_be32(5); + papm_parm->PlatformPowerLimit = 0xffffffff; + papm_parm->NearTDPLimitPAPM = 0xffffffff; + + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->papm_cfg_table_start, + (u8 *)papm_parm, + sizeof(PP_SIslands_PAPMParameters), + si_pi->sram_end); + if (ret) + return ret; + } + } + return 0; +} + +static int si_populate_smc_tdp_limits_2(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (ni_pi->enable_power_containment) { + SISLANDS_SMC_STATETABLE *smc_table = &si_pi->smc_statetable; + u32 scaling_factor = si_get_smc_power_scaling_factor(adev); + int ret; + + memset(smc_table, 0, sizeof(SISLANDS_SMC_STATETABLE)); + + smc_table->dpm2Params.NearTDPLimit = + cpu_to_be32(si_scale_power_for_smc(adev->pm.dpm.near_tdp_limit_adjusted, scaling_factor) * 1000); + smc_table->dpm2Params.SafePowerLimit = + cpu_to_be32(si_scale_power_for_smc((adev->pm.dpm.near_tdp_limit_adjusted * SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT) / 100, scaling_factor) * 1000); + + ret = amdgpu_si_copy_bytes_to_smc(adev, + (si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, dpm2Params) + + offsetof(PP_SIslands_DPM2Parameters, NearTDPLimit)), + (u8 *)(&(smc_table->dpm2Params.NearTDPLimit)), + sizeof(u32) * 2, + si_pi->sram_end); + if (ret) + return ret; + } + + return 0; +} + +static u16 si_calculate_power_efficiency_ratio(struct amdgpu_device *adev, + const u16 prev_std_vddc, + const u16 curr_std_vddc) +{ + u64 margin = (u64)SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN; + u64 prev_vddc = (u64)prev_std_vddc; + u64 curr_vddc = (u64)curr_std_vddc; + u64 pwr_efficiency_ratio, n, d; + + if ((prev_vddc == 0) || (curr_vddc == 0)) + return 0; + + n = div64_u64((u64)1024 * curr_vddc * curr_vddc * ((u64)1000 + margin), (u64)1000); + d = prev_vddc * prev_vddc; + pwr_efficiency_ratio = div64_u64(n, d); + + if (pwr_efficiency_ratio > (u64)0xFFFF) + return 0; + + return (u16)pwr_efficiency_ratio; +} + +static bool si_should_disable_uvd_powertune(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + if (si_pi->dyn_powertune_data.disable_uvd_powertune && + amdgpu_state->vclk && amdgpu_state->dclk) + return true; + + return false; +} + +struct evergreen_power_info *evergreen_get_pi(struct amdgpu_device *adev) +{ + struct evergreen_power_info *pi = adev->pm.dpm.priv; + + return pi; +} + +static int si_populate_power_containment_values(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + SISLANDS_SMC_VOLTAGE_VALUE vddc; + u32 prev_sclk; + u32 max_sclk; + u32 min_sclk; + u16 prev_std_vddc; + u16 curr_std_vddc; + int i; + u16 pwr_efficiency_ratio; + u8 max_ps_percent; + bool disable_uvd_power_tune; + int ret; + + if (ni_pi->enable_power_containment == false) + return 0; + + if (state->performance_level_count == 0) + return -EINVAL; + + if (smc_state->levelCount != state->performance_level_count) + return -EINVAL; + + disable_uvd_power_tune = si_should_disable_uvd_powertune(adev, amdgpu_state); + + smc_state->levels[0].dpm2.MaxPS = 0; + smc_state->levels[0].dpm2.NearTDPDec = 0; + smc_state->levels[0].dpm2.AboveSafeInc = 0; + smc_state->levels[0].dpm2.BelowSafeInc = 0; + smc_state->levels[0].dpm2.PwrEfficiencyRatio = 0; + + for (i = 1; i < state->performance_level_count; i++) { + prev_sclk = state->performance_levels[i-1].sclk; + max_sclk = state->performance_levels[i].sclk; + if (i == 1) + max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_M; + else + max_ps_percent = SISLANDS_DPM2_MAXPS_PERCENT_H; + + if (prev_sclk > max_sclk) + return -EINVAL; + + if ((max_ps_percent == 0) || + (prev_sclk == max_sclk) || + disable_uvd_power_tune) + min_sclk = max_sclk; + else if (i == 1) + min_sclk = prev_sclk; + else + min_sclk = (prev_sclk * (u32)max_ps_percent) / 100; + + if (min_sclk < state->performance_levels[0].sclk) + min_sclk = state->performance_levels[0].sclk; + + if (min_sclk == 0) + return -EINVAL; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + state->performance_levels[i-1].vddc, &vddc); + if (ret) + return ret; + + ret = si_get_std_voltage_value(adev, &vddc, &prev_std_vddc); + if (ret) + return ret; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + state->performance_levels[i].vddc, &vddc); + if (ret) + return ret; + + ret = si_get_std_voltage_value(adev, &vddc, &curr_std_vddc); + if (ret) + return ret; + + pwr_efficiency_ratio = si_calculate_power_efficiency_ratio(adev, + prev_std_vddc, curr_std_vddc); + + smc_state->levels[i].dpm2.MaxPS = (u8)((SISLANDS_DPM2_MAX_PULSE_SKIP * (max_sclk - min_sclk)) / max_sclk); + smc_state->levels[i].dpm2.NearTDPDec = SISLANDS_DPM2_NEAR_TDP_DEC; + smc_state->levels[i].dpm2.AboveSafeInc = SISLANDS_DPM2_ABOVE_SAFE_INC; + smc_state->levels[i].dpm2.BelowSafeInc = SISLANDS_DPM2_BELOW_SAFE_INC; + smc_state->levels[i].dpm2.PwrEfficiencyRatio = cpu_to_be16(pwr_efficiency_ratio); + } + + return 0; +} + +static int si_populate_sq_ramping_values(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + u32 sq_power_throttle, sq_power_throttle2; + bool enable_sq_ramping = ni_pi->enable_sq_ramping; + int i; + + if (state->performance_level_count == 0) + return -EINVAL; + + if (smc_state->levelCount != state->performance_level_count) + return -EINVAL; + + if (adev->pm.dpm.sq_ramping_threshold == 0) + return -EINVAL; + + if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER > (MAX_POWER_MASK >> MAX_POWER_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_MIN_POWER > (MIN_POWER_MASK >> MIN_POWER_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA > (MAX_POWER_DELTA_MASK >> MAX_POWER_DELTA_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_STI_SIZE > (STI_SIZE_MASK >> STI_SIZE_SHIFT)) + enable_sq_ramping = false; + + if (SISLANDS_DPM2_SQ_RAMP_LTI_RATIO > (LTI_RATIO_MASK >> LTI_RATIO_SHIFT)) + enable_sq_ramping = false; + + for (i = 0; i < state->performance_level_count; i++) { + sq_power_throttle = 0; + sq_power_throttle2 = 0; + + if ((state->performance_levels[i].sclk >= adev->pm.dpm.sq_ramping_threshold) && + enable_sq_ramping) { + sq_power_throttle |= MAX_POWER(SISLANDS_DPM2_SQ_RAMP_MAX_POWER); + sq_power_throttle |= MIN_POWER(SISLANDS_DPM2_SQ_RAMP_MIN_POWER); + sq_power_throttle2 |= MAX_POWER_DELTA(SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA); + sq_power_throttle2 |= STI_SIZE(SISLANDS_DPM2_SQ_RAMP_STI_SIZE); + sq_power_throttle2 |= LTI_RATIO(SISLANDS_DPM2_SQ_RAMP_LTI_RATIO); + } else { + sq_power_throttle |= MAX_POWER_MASK | MIN_POWER_MASK; + sq_power_throttle2 |= MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + } + + smc_state->levels[i].SQPowerThrottle = cpu_to_be32(sq_power_throttle); + smc_state->levels[i].SQPowerThrottle_2 = cpu_to_be32(sq_power_throttle2); + } + + return 0; +} + +static int si_enable_power_containment(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + bool enable) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + PPSMC_Result smc_result; + int ret = 0; + + if (ni_pi->enable_power_containment) { + if (enable) { + if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingActive); + if (smc_result != PPSMC_Result_OK) { + ret = -EINVAL; + ni_pi->pc_enabled = false; + } else { + ni_pi->pc_enabled = true; + } + } + } else { + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_TDPClampingInactive); + if (smc_result != PPSMC_Result_OK) + ret = -EINVAL; + ni_pi->pc_enabled = false; + } + } + + return ret; +} + +static int si_initialize_smc_dte_tables(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + int ret = 0; + struct si_dte_data *dte_data = &si_pi->dte_data; + Smc_SIslands_DTE_Configuration *dte_tables = NULL; + u32 table_size; + u8 tdep_count; + u32 i; + + if (dte_data == NULL) + si_pi->enable_dte = false; + + if (si_pi->enable_dte == false) + return 0; + + if (dte_data->k <= 0) + return -EINVAL; + + dte_tables = kzalloc(sizeof(Smc_SIslands_DTE_Configuration), GFP_KERNEL); + if (dte_tables == NULL) { + si_pi->enable_dte = false; + return -ENOMEM; + } + + table_size = dte_data->k; + + if (table_size > SMC_SISLANDS_DTE_MAX_FILTER_STAGES) + table_size = SMC_SISLANDS_DTE_MAX_FILTER_STAGES; + + tdep_count = dte_data->tdep_count; + if (tdep_count > SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE) + tdep_count = SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE; + + dte_tables->K = cpu_to_be32(table_size); + dte_tables->T0 = cpu_to_be32(dte_data->t0); + dte_tables->MaxT = cpu_to_be32(dte_data->max_t); + dte_tables->WindowSize = dte_data->window_size; + dte_tables->temp_select = dte_data->temp_select; + dte_tables->DTE_mode = dte_data->dte_mode; + dte_tables->Tthreshold = cpu_to_be32(dte_data->t_threshold); + + if (tdep_count > 0) + table_size--; + + for (i = 0; i < table_size; i++) { + dte_tables->tau[i] = cpu_to_be32(dte_data->tau[i]); + dte_tables->R[i] = cpu_to_be32(dte_data->r[i]); + } + + dte_tables->Tdep_count = tdep_count; + + for (i = 0; i < (u32)tdep_count; i++) { + dte_tables->T_limits[i] = dte_data->t_limits[i]; + dte_tables->Tdep_tau[i] = cpu_to_be32(dte_data->tdep_tau[i]); + dte_tables->Tdep_R[i] = cpu_to_be32(dte_data->tdep_r[i]); + } + + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->dte_table_start, + (u8 *)dte_tables, + sizeof(Smc_SIslands_DTE_Configuration), + si_pi->sram_end); + kfree(dte_tables); + + return ret; +} + +static int si_get_cac_std_voltage_max_min(struct amdgpu_device *adev, + u16 *max, u16 *min) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_cac_leakage_table *table = + &adev->pm.dpm.dyn_state.cac_leakage_table; + u32 i; + u32 v0_loadline; + + if (table == NULL) + return -EINVAL; + + *max = 0; + *min = 0xFFFF; + + for (i = 0; i < table->count; i++) { + if (table->entries[i].vddc > *max) + *max = table->entries[i].vddc; + if (table->entries[i].vddc < *min) + *min = table->entries[i].vddc; + } + + if (si_pi->powertune_data->lkge_lut_v0_percent > 100) + return -EINVAL; + + v0_loadline = (*min) * (100 - si_pi->powertune_data->lkge_lut_v0_percent) / 100; + + if (v0_loadline > 0xFFFFUL) + return -EINVAL; + + *min = (u16)v0_loadline; + + if ((*min > *max) || (*max == 0) || (*min == 0)) + return -EINVAL; + + return 0; +} + +static u16 si_get_cac_std_voltage_step(u16 max, u16 min) +{ + return ((max - min) + (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)) / + SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; +} + +static int si_init_dte_leakage_table(struct amdgpu_device *adev, + PP_SIslands_CacConfig *cac_tables, + u16 vddc_max, u16 vddc_min, u16 vddc_step, + u16 t0, u16 t_step) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 leakage; + unsigned int i, j; + s32 t; + u32 smc_leakage; + u32 scaling_factor; + u16 voltage; + + scaling_factor = si_get_smc_power_scaling_factor(adev); + + for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) { + t = (1000 * (i * t_step + t0)); + + for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { + voltage = vddc_max - (vddc_step * j); + + si_calculate_leakage_for_v_and_t(adev, + &si_pi->powertune_data->leakage_coefficients, + voltage, + t, + si_pi->dyn_powertune_data.cac_leakage, + &leakage); + + smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; + + if (smc_leakage > 0xFFFF) + smc_leakage = 0xFFFF; + + cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = + cpu_to_be16((u16)smc_leakage); + } + } + return 0; +} + +static int si_init_simplified_leakage_table(struct amdgpu_device *adev, + PP_SIslands_CacConfig *cac_tables, + u16 vddc_max, u16 vddc_min, u16 vddc_step) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 leakage; + unsigned int i, j; + u32 smc_leakage; + u32 scaling_factor; + u16 voltage; + + scaling_factor = si_get_smc_power_scaling_factor(adev); + + for (j = 0; j < SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES; j++) { + voltage = vddc_max - (vddc_step * j); + + si_calculate_leakage_for_v(adev, + &si_pi->powertune_data->leakage_coefficients, + si_pi->powertune_data->fixed_kt, + voltage, + si_pi->dyn_powertune_data.cac_leakage, + &leakage); + + smc_leakage = si_scale_power_for_smc(leakage, scaling_factor) / 4; + + if (smc_leakage > 0xFFFF) + smc_leakage = 0xFFFF; + + for (i = 0; i < SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES ; i++) + cac_tables->cac_lkge_lut[i][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES-1-j] = + cpu_to_be16((u16)smc_leakage); + } + return 0; +} + +static int si_initialize_smc_cac_tables(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + PP_SIslands_CacConfig *cac_tables = NULL; + u16 vddc_max, vddc_min, vddc_step; + u16 t0, t_step; + u32 load_line_slope, reg; + int ret = 0; + u32 ticks_per_us = amdgpu_asic_get_xclk(adev) / 100; + + if (ni_pi->enable_cac == false) + return 0; + + cac_tables = kzalloc(sizeof(PP_SIslands_CacConfig), GFP_KERNEL); + if (!cac_tables) + return -ENOMEM; + + reg = RREG32(CG_CAC_CTRL) & ~CAC_WINDOW_MASK; + reg |= CAC_WINDOW(si_pi->powertune_data->cac_window); + WREG32(CG_CAC_CTRL, reg); + + si_pi->dyn_powertune_data.cac_leakage = adev->pm.dpm.cac_leakage; + si_pi->dyn_powertune_data.dc_pwr_value = + si_pi->powertune_data->dc_cac[NISLANDS_DCCAC_LEVEL_0]; + si_pi->dyn_powertune_data.wintime = si_calculate_cac_wintime(adev); + si_pi->dyn_powertune_data.shift_n = si_pi->powertune_data->shift_n_default; + + si_pi->dyn_powertune_data.leakage_minimum_temperature = 80 * 1000; + + ret = si_get_cac_std_voltage_max_min(adev, &vddc_max, &vddc_min); + if (ret) + goto done_free; + + vddc_step = si_get_cac_std_voltage_step(vddc_max, vddc_min); + vddc_min = vddc_max - (vddc_step * (SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES - 1)); + t_step = 4; + t0 = 60; + + if (si_pi->enable_dte || ni_pi->driver_calculate_cac_leakage) + ret = si_init_dte_leakage_table(adev, cac_tables, + vddc_max, vddc_min, vddc_step, + t0, t_step); + else + ret = si_init_simplified_leakage_table(adev, cac_tables, + vddc_max, vddc_min, vddc_step); + if (ret) + goto done_free; + + load_line_slope = ((u32)adev->pm.dpm.load_line_slope << SMC_SISLANDS_SCALE_R) / 100; + + cac_tables->l2numWin_TDP = cpu_to_be32(si_pi->dyn_powertune_data.l2_lta_window_size); + cac_tables->lts_truncate_n = si_pi->dyn_powertune_data.lts_truncate; + cac_tables->SHIFT_N = si_pi->dyn_powertune_data.shift_n; + cac_tables->lkge_lut_V0 = cpu_to_be32((u32)vddc_min); + cac_tables->lkge_lut_Vstep = cpu_to_be32((u32)vddc_step); + cac_tables->R_LL = cpu_to_be32(load_line_slope); + cac_tables->WinTime = cpu_to_be32(si_pi->dyn_powertune_data.wintime); + cac_tables->calculation_repeats = cpu_to_be32(2); + cac_tables->dc_cac = cpu_to_be32(0); + cac_tables->log2_PG_LKG_SCALE = 12; + cac_tables->cac_temp = si_pi->powertune_data->operating_temp; + cac_tables->lkge_lut_T0 = cpu_to_be32((u32)t0); + cac_tables->lkge_lut_Tstep = cpu_to_be32((u32)t_step); + + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->cac_table_start, + (u8 *)cac_tables, + sizeof(PP_SIslands_CacConfig), + si_pi->sram_end); + + if (ret) + goto done_free; + + ret = si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ticks_per_us, ticks_per_us); + +done_free: + if (ret) { + ni_pi->enable_cac = false; + ni_pi->enable_power_containment = false; + } + + kfree(cac_tables); + + return ret; +} + +static int si_program_cac_config_registers(struct amdgpu_device *adev, + const struct si_cac_config_reg *cac_config_regs) +{ + const struct si_cac_config_reg *config_regs = cac_config_regs; + u32 data = 0, offset; + + if (!config_regs) + return -EINVAL; + + while (config_regs->offset != 0xFFFFFFFF) { + switch (config_regs->type) { + case SISLANDS_CACCONFIG_CGIND: + offset = SMC_CG_IND_START + config_regs->offset; + if (offset < SMC_CG_IND_END) + data = RREG32_SMC(offset); + break; + default: + data = RREG32(config_regs->offset); + break; + } + + data &= ~config_regs->mask; + data |= ((config_regs->value << config_regs->shift) & config_regs->mask); + + switch (config_regs->type) { + case SISLANDS_CACCONFIG_CGIND: + offset = SMC_CG_IND_START + config_regs->offset; + if (offset < SMC_CG_IND_END) + WREG32_SMC(offset, data); + break; + default: + WREG32(config_regs->offset, data); + break; + } + config_regs++; + } + return 0; +} + +static int si_initialize_hardware_cac_manager(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + + if ((ni_pi->enable_cac == false) || + (ni_pi->cac_configuration_required == false)) + return 0; + + ret = si_program_cac_config_registers(adev, si_pi->lcac_config); + if (ret) + return ret; + ret = si_program_cac_config_registers(adev, si_pi->cac_override); + if (ret) + return ret; + ret = si_program_cac_config_registers(adev, si_pi->cac_weights); + if (ret) + return ret; + + return 0; +} + +static int si_enable_smc_cac(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + bool enable) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result smc_result; + int ret = 0; + + if (ni_pi->enable_cac) { + if (enable) { + if (!si_should_disable_uvd_powertune(adev, amdgpu_new_state)) { + if (ni_pi->support_cac_long_term_average) { + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgEnable); + if (smc_result != PPSMC_Result_OK) + ni_pi->support_cac_long_term_average = false; + } + + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableCac); + if (smc_result != PPSMC_Result_OK) { + ret = -EINVAL; + ni_pi->cac_enabled = false; + } else { + ni_pi->cac_enabled = true; + } + + if (si_pi->enable_dte) { + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableDTE); + if (smc_result != PPSMC_Result_OK) + ret = -EINVAL; + } + } + } else if (ni_pi->cac_enabled) { + if (si_pi->enable_dte) + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableDTE); + + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableCac); + + ni_pi->cac_enabled = false; + + if (ni_pi->support_cac_long_term_average) + smc_result = amdgpu_si_send_msg_to_smc(adev, PPSMC_CACLongTermAvgDisable); + } + } + return ret; +} + +static int si_init_smc_spll_table(struct amdgpu_device *adev) +{ + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + SMC_SISLANDS_SPLL_DIV_TABLE *spll_table; + SISLANDS_SMC_SCLK_VALUE sclk_params; + u32 fb_div, p_div; + u32 clk_s, clk_v; + u32 sclk = 0; + int ret = 0; + u32 tmp; + int i; + + if (si_pi->spll_table_start == 0) + return -EINVAL; + + spll_table = kzalloc(sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), GFP_KERNEL); + if (spll_table == NULL) + return -ENOMEM; + + for (i = 0; i < 256; i++) { + ret = si_calculate_sclk_params(adev, sclk, &sclk_params); + if (ret) + break; + p_div = (sclk_params.vCG_SPLL_FUNC_CNTL & SPLL_PDIV_A_MASK) >> SPLL_PDIV_A_SHIFT; + fb_div = (sclk_params.vCG_SPLL_FUNC_CNTL_3 & SPLL_FB_DIV_MASK) >> SPLL_FB_DIV_SHIFT; + clk_s = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM & CLK_S_MASK) >> CLK_S_SHIFT; + clk_v = (sclk_params.vCG_SPLL_SPREAD_SPECTRUM_2 & CLK_V_MASK) >> CLK_V_SHIFT; + + fb_div &= ~0x00001FFF; + fb_div >>= 1; + clk_v >>= 6; + + if (p_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT)) + ret = -EINVAL; + if (fb_div & ~(SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT)) + ret = -EINVAL; + if (clk_s & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT)) + ret = -EINVAL; + if (clk_v & ~(SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK >> SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT)) + ret = -EINVAL; + + if (ret) + break; + + tmp = ((fb_div << SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK) | + ((p_div << SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK); + spll_table->freq[i] = cpu_to_be32(tmp); + + tmp = ((clk_v << SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK) | + ((clk_s << SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT) & SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK); + spll_table->ss[i] = cpu_to_be32(tmp); + + sclk += 512; + } + + + if (!ret) + ret = amdgpu_si_copy_bytes_to_smc(adev, si_pi->spll_table_start, + (u8 *)spll_table, + sizeof(SMC_SISLANDS_SPLL_DIV_TABLE), + si_pi->sram_end); + + if (ret) + ni_pi->enable_power_containment = false; + + kfree(spll_table); + + return ret; +} + +static u16 si_get_lower_of_leakage_and_vce_voltage(struct amdgpu_device *adev, + u16 vce_voltage) +{ + u16 highest_leakage = 0; + struct si_power_info *si_pi = si_get_pi(adev); + int i; + + for (i = 0; i < si_pi->leakage_voltage.count; i++){ + if (highest_leakage < si_pi->leakage_voltage.entries[i].voltage) + highest_leakage = si_pi->leakage_voltage.entries[i].voltage; + } + + if (si_pi->leakage_voltage.count && (highest_leakage < vce_voltage)) + return highest_leakage; + + return vce_voltage; +} + +static int si_get_vce_clock_voltage(struct amdgpu_device *adev, + u32 evclk, u32 ecclk, u16 *voltage) +{ + u32 i; + int ret = -EINVAL; + struct amdgpu_vce_clock_voltage_dependency_table *table = + &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; + + if (((evclk == 0) && (ecclk == 0)) || + (table && (table->count == 0))) { + *voltage = 0; + return 0; + } + + for (i = 0; i < table->count; i++) { + if ((evclk <= table->entries[i].evclk) && + (ecclk <= table->entries[i].ecclk)) { + *voltage = table->entries[i].v; + ret = 0; + break; + } + } + + /* if no match return the highest voltage */ + if (ret) + *voltage = table->entries[table->count - 1].v; + + *voltage = si_get_lower_of_leakage_and_vce_voltage(adev, *voltage); + + return ret; +} + +static bool si_dpm_vblank_too_short(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + u32 vblank_time = amdgpu_dpm_get_vblank_time(adev); + /* we never hit the non-gddr5 limit so disable it */ + u32 switch_limit = adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5 ? 450 : 0; + + if (vblank_time < switch_limit) + return true; + else + return false; + +} + +static int ni_copy_and_switch_arb_sets(struct amdgpu_device *adev, + u32 arb_freq_src, u32 arb_freq_dest) +{ + u32 mc_arb_dram_timing; + u32 mc_arb_dram_timing2; + u32 burst_time; + u32 mc_cg_config; + + switch (arb_freq_src) { + case MC_CG_ARB_FREQ_F0: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE0_MASK) >> STATE0_SHIFT; + break; + case MC_CG_ARB_FREQ_F1: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_1); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_1); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE1_MASK) >> STATE1_SHIFT; + break; + case MC_CG_ARB_FREQ_F2: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_2); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_2); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE2_MASK) >> STATE2_SHIFT; + break; + case MC_CG_ARB_FREQ_F3: + mc_arb_dram_timing = RREG32(MC_ARB_DRAM_TIMING_3); + mc_arb_dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2_3); + burst_time = (RREG32(MC_ARB_BURST_TIME) & STATE3_MASK) >> STATE3_SHIFT; + break; + default: + return -EINVAL; + } + + switch (arb_freq_dest) { + case MC_CG_ARB_FREQ_F0: + WREG32(MC_ARB_DRAM_TIMING, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE0(burst_time), ~STATE0_MASK); + break; + case MC_CG_ARB_FREQ_F1: + WREG32(MC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE1(burst_time), ~STATE1_MASK); + break; + case MC_CG_ARB_FREQ_F2: + WREG32(MC_ARB_DRAM_TIMING_2, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_2, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE2(burst_time), ~STATE2_MASK); + break; + case MC_CG_ARB_FREQ_F3: + WREG32(MC_ARB_DRAM_TIMING_3, mc_arb_dram_timing); + WREG32(MC_ARB_DRAM_TIMING2_3, mc_arb_dram_timing2); + WREG32_P(MC_ARB_BURST_TIME, STATE3(burst_time), ~STATE3_MASK); + break; + default: + return -EINVAL; + } + + mc_cg_config = RREG32(MC_CG_CONFIG) | 0x0000000F; + WREG32(MC_CG_CONFIG, mc_cg_config); + WREG32_P(MC_ARB_CG, CG_ARB_REQ(arb_freq_dest), ~CG_ARB_REQ_MASK); + + return 0; +} + +static void ni_update_current_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *new_ps = si_get_ps(rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + + eg_pi->current_rps = *rps; + ni_pi->current_ps = *new_ps; + eg_pi->current_rps.ps_priv = &ni_pi->current_ps; + adev->pm.dpm.current_ps = &eg_pi->current_rps; +} + +static void ni_update_requested_ps(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *new_ps = si_get_ps(rps); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + + eg_pi->requested_rps = *rps; + ni_pi->requested_ps = *new_ps; + eg_pi->requested_rps.ps_priv = &ni_pi->requested_ps; + adev->pm.dpm.requested_ps = &eg_pi->requested_rps; +} + +static void ni_set_uvd_clock_before_set_eng_clock(struct amdgpu_device *adev, + struct amdgpu_ps *new_ps, + struct amdgpu_ps *old_ps) +{ + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); + + if ((new_ps->vclk == old_ps->vclk) && + (new_ps->dclk == old_ps->dclk)) + return; + + if (new_state->performance_levels[new_state->performance_level_count - 1].sclk >= + current_state->performance_levels[current_state->performance_level_count - 1].sclk) + return; + + amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); +} + +static void ni_set_uvd_clock_after_set_eng_clock(struct amdgpu_device *adev, + struct amdgpu_ps *new_ps, + struct amdgpu_ps *old_ps) +{ + struct si_ps *new_state = si_get_ps(new_ps); + struct si_ps *current_state = si_get_ps(old_ps); + + if ((new_ps->vclk == old_ps->vclk) && + (new_ps->dclk == old_ps->dclk)) + return; + + if (new_state->performance_levels[new_state->performance_level_count - 1].sclk < + current_state->performance_levels[current_state->performance_level_count - 1].sclk) + return; + + amdgpu_asic_set_uvd_clocks(adev, new_ps->vclk, new_ps->dclk); +} + +static u16 btc_find_voltage(struct atom_voltage_table *table, u16 voltage) +{ + unsigned int i; + + for (i = 0; i < table->count; i++) + if (voltage <= table->entries[i].value) + return table->entries[i].value; + + return table->entries[table->count - 1].value; +} + +static u32 btc_find_valid_clock(struct amdgpu_clock_array *clocks, + u32 max_clock, u32 requested_clock) +{ + unsigned int i; + + if ((clocks == NULL) || (clocks->count == 0)) + return (requested_clock < max_clock) ? requested_clock : max_clock; + + for (i = 0; i < clocks->count; i++) { + if (clocks->values[i] >= requested_clock) + return (clocks->values[i] < max_clock) ? clocks->values[i] : max_clock; + } + + return (clocks->values[clocks->count - 1] < max_clock) ? + clocks->values[clocks->count - 1] : max_clock; +} + +static u32 btc_get_valid_mclk(struct amdgpu_device *adev, + u32 max_mclk, u32 requested_mclk) +{ + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_mclk_values, + max_mclk, requested_mclk); +} + +static u32 btc_get_valid_sclk(struct amdgpu_device *adev, + u32 max_sclk, u32 requested_sclk) +{ + return btc_find_valid_clock(&adev->pm.dpm.dyn_state.valid_sclk_values, + max_sclk, requested_sclk); +} + +static void btc_get_max_clock_from_voltage_dependency_table(struct amdgpu_clock_voltage_dependency_table *table, + u32 *max_clock) +{ + u32 i, clock = 0; + + if ((table == NULL) || (table->count == 0)) { + *max_clock = clock; + return; + } + + for (i = 0; i < table->count; i++) { + if (clock < table->entries[i].clk) + clock = table->entries[i].clk; + } + *max_clock = clock; +} + +static void btc_apply_voltage_dependency_rules(struct amdgpu_clock_voltage_dependency_table *table, + u32 clock, u16 max_voltage, u16 *voltage) +{ + u32 i; + + if ((table == NULL) || (table->count == 0)) + return; + + for (i= 0; i < table->count; i++) { + if (clock <= table->entries[i].clk) { + if (*voltage < table->entries[i].v) + *voltage = (u16)((table->entries[i].v < max_voltage) ? + table->entries[i].v : max_voltage); + return; + } + } + + *voltage = (*voltage > max_voltage) ? *voltage : max_voltage; +} + +static void btc_adjust_clock_combinations(struct amdgpu_device *adev, + const struct amdgpu_clock_and_voltage_limits *max_limits, + struct rv7xx_pl *pl) +{ + + if ((pl->mclk == 0) || (pl->sclk == 0)) + return; + + if (pl->mclk == pl->sclk) + return; + + if (pl->mclk > pl->sclk) { + if (((pl->mclk + (pl->sclk - 1)) / pl->sclk) > adev->pm.dpm.dyn_state.mclk_sclk_ratio) + pl->sclk = btc_get_valid_sclk(adev, + max_limits->sclk, + (pl->mclk + + (adev->pm.dpm.dyn_state.mclk_sclk_ratio - 1)) / + adev->pm.dpm.dyn_state.mclk_sclk_ratio); + } else { + if ((pl->sclk - pl->mclk) > adev->pm.dpm.dyn_state.sclk_mclk_delta) + pl->mclk = btc_get_valid_mclk(adev, + max_limits->mclk, + pl->sclk - + adev->pm.dpm.dyn_state.sclk_mclk_delta); + } +} + +static void btc_apply_voltage_delta_rules(struct amdgpu_device *adev, + u16 max_vddc, u16 max_vddci, + u16 *vddc, u16 *vddci) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + u16 new_voltage; + + if ((0 == *vddc) || (0 == *vddci)) + return; + + if (*vddc > *vddci) { + if ((*vddc - *vddci) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddci_voltage_table, + (*vddc - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddci = (new_voltage < max_vddci) ? new_voltage : max_vddci; + } + } else { + if ((*vddci - *vddc) > adev->pm.dpm.dyn_state.vddc_vddci_delta) { + new_voltage = btc_find_voltage(&eg_pi->vddc_voltage_table, + (*vddci - adev->pm.dpm.dyn_state.vddc_vddci_delta)); + *vddc = (new_voltage < max_vddc) ? new_voltage : max_vddc; + } + } +} + +static void r600_calculate_u_and_p(u32 i, u32 r_c, u32 p_b, + u32 *p, u32 *u) +{ + u32 b_c = 0; + u32 i_c; + u32 tmp; + + i_c = (i * r_c) / 100; + tmp = i_c >> p_b; + + while (tmp) { + b_c++; + tmp >>= 1; + } + + *u = (b_c + 1) / 2; + *p = i_c / (1 << (2 * (*u))); +} + +static int r600_calculate_at(u32 t, u32 h, u32 fh, u32 fl, u32 *tl, u32 *th) +{ + u32 k, a, ah, al; + u32 t1; + + if ((fl == 0) || (fh == 0) || (fl > fh)) + return -EINVAL; + + k = (100 * fh) / fl; + t1 = (t * (k - 100)); + a = (1000 * (100 * h + t1)) / (10000 + (t1 / 100)); + a = (a + 5) / 10; + ah = ((a * t) + 5000) / 10000; + al = a - ah; + + *th = t - ah; + *tl = t + al; + + return 0; +} + +static bool r600_is_uvd_state(u32 class, u32 class2) +{ + if (class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + return true; + if (class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + return true; + if (class2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + return true; + return false; +} + +static u8 rv770_get_memory_module_index(struct amdgpu_device *adev) +{ + return (u8) ((RREG32(BIOS_SCRATCH_4) >> 16) & 0xff); +} + +static void rv770_get_max_vddc(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + u16 vddc; + + if (amdgpu_atombios_get_max_vddc(adev, 0, 0, &vddc)) + pi->max_vddc = 0; + else + pi->max_vddc = vddc; +} + +static void rv770_get_engine_memory_ss(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct amdgpu_atom_ss ss; + + pi->sclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_ENGINE_SS, 0); + pi->mclk_ss = amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_MEMORY_SS, 0); + + if (pi->sclk_ss || pi->mclk_ss) + pi->dynamic_ss = true; + else + pi->dynamic_ss = false; +} + + +static void si_apply_state_adjust_rules(struct amdgpu_device *adev, + struct amdgpu_ps *rps) +{ + struct si_ps *ps = si_get_ps(rps); + struct amdgpu_clock_and_voltage_limits *max_limits; + bool disable_mclk_switching = false; + bool disable_sclk_switching = false; + u32 mclk, sclk; + u16 vddc, vddci, min_vce_voltage = 0; + u32 max_sclk_vddc, max_mclk_vddci, max_mclk_vddc; + u32 max_sclk = 0, max_mclk = 0; + int i; + + if (adev->asic_type == CHIP_HAINAN) { + if ((adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0xC3) || + (adev->pdev->device == 0x6664) || + (adev->pdev->device == 0x6665) || + (adev->pdev->device == 0x6667)) { + max_sclk = 75000; + } + if ((adev->pdev->revision == 0xC3) || + (adev->pdev->device == 0x6665)) { + max_sclk = 60000; + max_mclk = 80000; + } + } else if (adev->asic_type == CHIP_OLAND) { + if ((adev->pdev->revision == 0xC7) || + (adev->pdev->revision == 0x80) || + (adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83) || + (adev->pdev->revision == 0x87) || + (adev->pdev->device == 0x6604) || + (adev->pdev->device == 0x6605)) { + max_sclk = 75000; + } + } + + if (rps->vce_active) { + rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; + rps->ecclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].ecclk; + si_get_vce_clock_voltage(adev, rps->evclk, rps->ecclk, + &min_vce_voltage); + } else { + rps->evclk = 0; + rps->ecclk = 0; + } + + if ((adev->pm.dpm.new_active_crtc_count > 1) || + si_dpm_vblank_too_short(adev)) + disable_mclk_switching = true; + + if (rps->vclk || rps->dclk) { + disable_mclk_switching = true; + disable_sclk_switching = true; + } + + if (adev->pm.ac_power) + max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + else + max_limits = &adev->pm.dpm.dyn_state.max_clock_voltage_on_dc; + + for (i = ps->performance_level_count - 2; i >= 0; i--) { + if (ps->performance_levels[i].vddc > ps->performance_levels[i+1].vddc) + ps->performance_levels[i].vddc = ps->performance_levels[i+1].vddc; + } + if (adev->pm.ac_power == false) { + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].mclk > max_limits->mclk) + ps->performance_levels[i].mclk = max_limits->mclk; + if (ps->performance_levels[i].sclk > max_limits->sclk) + ps->performance_levels[i].sclk = max_limits->sclk; + if (ps->performance_levels[i].vddc > max_limits->vddc) + ps->performance_levels[i].vddc = max_limits->vddc; + if (ps->performance_levels[i].vddci > max_limits->vddci) + ps->performance_levels[i].vddci = max_limits->vddci; + } + } + + /* limit clocks to max supported clocks based on voltage dependency tables */ + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + &max_sclk_vddc); + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + &max_mclk_vddci); + btc_get_max_clock_from_voltage_dependency_table(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + &max_mclk_vddc); + + for (i = 0; i < ps->performance_level_count; i++) { + if (max_sclk_vddc) { + if (ps->performance_levels[i].sclk > max_sclk_vddc) + ps->performance_levels[i].sclk = max_sclk_vddc; + } + if (max_mclk_vddci) { + if (ps->performance_levels[i].mclk > max_mclk_vddci) + ps->performance_levels[i].mclk = max_mclk_vddci; + } + if (max_mclk_vddc) { + if (ps->performance_levels[i].mclk > max_mclk_vddc) + ps->performance_levels[i].mclk = max_mclk_vddc; + } + if (max_mclk) { + if (ps->performance_levels[i].mclk > max_mclk) + ps->performance_levels[i].mclk = max_mclk; + } + if (max_sclk) { + if (ps->performance_levels[i].sclk > max_sclk) + ps->performance_levels[i].sclk = max_sclk; + } + } + + /* XXX validate the min clocks required for display */ + + if (disable_mclk_switching) { + mclk = ps->performance_levels[ps->performance_level_count - 1].mclk; + vddci = ps->performance_levels[ps->performance_level_count - 1].vddci; + } else { + mclk = ps->performance_levels[0].mclk; + vddci = ps->performance_levels[0].vddci; + } + + if (disable_sclk_switching) { + sclk = ps->performance_levels[ps->performance_level_count - 1].sclk; + vddc = ps->performance_levels[ps->performance_level_count - 1].vddc; + } else { + sclk = ps->performance_levels[0].sclk; + vddc = ps->performance_levels[0].vddc; + } + + if (rps->vce_active) { + if (sclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk) + sclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].sclk; + if (mclk < adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk) + mclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].mclk; + } + + /* adjusted low state */ + ps->performance_levels[0].sclk = sclk; + ps->performance_levels[0].mclk = mclk; + ps->performance_levels[0].vddc = vddc; + ps->performance_levels[0].vddci = vddci; + + if (disable_sclk_switching) { + sclk = ps->performance_levels[0].sclk; + for (i = 1; i < ps->performance_level_count; i++) { + if (sclk < ps->performance_levels[i].sclk) + sclk = ps->performance_levels[i].sclk; + } + for (i = 0; i < ps->performance_level_count; i++) { + ps->performance_levels[i].sclk = sclk; + ps->performance_levels[i].vddc = vddc; + } + } else { + for (i = 1; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].sclk < ps->performance_levels[i - 1].sclk) + ps->performance_levels[i].sclk = ps->performance_levels[i - 1].sclk; + if (ps->performance_levels[i].vddc < ps->performance_levels[i - 1].vddc) + ps->performance_levels[i].vddc = ps->performance_levels[i - 1].vddc; + } + } + + if (disable_mclk_switching) { + mclk = ps->performance_levels[0].mclk; + for (i = 1; i < ps->performance_level_count; i++) { + if (mclk < ps->performance_levels[i].mclk) + mclk = ps->performance_levels[i].mclk; + } + for (i = 0; i < ps->performance_level_count; i++) { + ps->performance_levels[i].mclk = mclk; + ps->performance_levels[i].vddci = vddci; + } + } else { + for (i = 1; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].mclk < ps->performance_levels[i - 1].mclk) + ps->performance_levels[i].mclk = ps->performance_levels[i - 1].mclk; + if (ps->performance_levels[i].vddci < ps->performance_levels[i - 1].vddci) + ps->performance_levels[i].vddci = ps->performance_levels[i - 1].vddci; + } + } + + for (i = 0; i < ps->performance_level_count; i++) + btc_adjust_clock_combinations(adev, max_limits, + &ps->performance_levels[i]); + + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].vddc < min_vce_voltage) + ps->performance_levels[i].vddc = min_vce_voltage; + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk, + ps->performance_levels[i].sclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + ps->performance_levels[i].mclk, + max_limits->vddci, &ps->performance_levels[i].vddci); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + ps->performance_levels[i].mclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + btc_apply_voltage_dependency_rules(&adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk, + adev->clock.current_dispclk, + max_limits->vddc, &ps->performance_levels[i].vddc); + } + + for (i = 0; i < ps->performance_level_count; i++) { + btc_apply_voltage_delta_rules(adev, + max_limits->vddc, max_limits->vddci, + &ps->performance_levels[i].vddc, + &ps->performance_levels[i].vddci); + } + + ps->dc_compatible = true; + for (i = 0; i < ps->performance_level_count; i++) { + if (ps->performance_levels[i].vddc > adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.vddc) + ps->dc_compatible = false; + } +} + +#if 0 +static int si_read_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 *value) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + return amdgpu_si_read_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, value, + si_pi->sram_end); +} +#endif + +static int si_write_smc_soft_register(struct amdgpu_device *adev, + u16 reg_offset, u32 value) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + return amdgpu_si_write_smc_sram_dword(adev, + si_pi->soft_regs_start + reg_offset, + value, si_pi->sram_end); +} + +static bool si_is_special_1gb_platform(struct amdgpu_device *adev) +{ + bool ret = false; + u32 tmp, width, row, column, bank, density; + bool is_memory_gddr5, is_special; + + tmp = RREG32(MC_SEQ_MISC0); + is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == ((tmp & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT)); + is_special = (MC_SEQ_MISC0_REV_ID_VALUE == ((tmp & MC_SEQ_MISC0_REV_ID_MASK) >> MC_SEQ_MISC0_REV_ID_SHIFT)) + & (MC_SEQ_MISC0_VEN_ID_VALUE == ((tmp & MC_SEQ_MISC0_VEN_ID_MASK) >> MC_SEQ_MISC0_VEN_ID_SHIFT)); + + WREG32(MC_SEQ_IO_DEBUG_INDEX, 0xb); + width = ((RREG32(MC_SEQ_IO_DEBUG_DATA) >> 1) & 1) ? 16 : 32; + + tmp = RREG32(MC_ARB_RAMCFG); + row = ((tmp & NOOFROWS_MASK) >> NOOFROWS_SHIFT) + 10; + column = ((tmp & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT) + 8; + bank = ((tmp & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + 2; + + density = (1 << (row + column - 20 + bank)) * width; + + if ((adev->pdev->device == 0x6819) && + is_memory_gddr5 && is_special && (density == 0x400)) + ret = true; + + return ret; +} + +static void si_get_leakage_vddc(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u16 vddc, count = 0; + int i, ret; + + for (i = 0; i < SISLANDS_MAX_LEAKAGE_COUNT; i++) { + ret = amdgpu_atombios_get_leakage_vddc_based_on_leakage_idx(adev, &vddc, SISLANDS_LEAKAGE_INDEX0 + i); + + if (!ret && (vddc > 0) && (vddc != (SISLANDS_LEAKAGE_INDEX0 + i))) { + si_pi->leakage_voltage.entries[count].voltage = vddc; + si_pi->leakage_voltage.entries[count].leakage_index = + SISLANDS_LEAKAGE_INDEX0 + i; + count++; + } + } + si_pi->leakage_voltage.count = count; +} + +static int si_get_leakage_voltage_from_leakage_index(struct amdgpu_device *adev, + u32 index, u16 *leakage_voltage) +{ + struct si_power_info *si_pi = si_get_pi(adev); + int i; + + if (leakage_voltage == NULL) + return -EINVAL; + + if ((index & 0xff00) != 0xff00) + return -EINVAL; + + if ((index & 0xff) > SISLANDS_MAX_LEAKAGE_COUNT + 1) + return -EINVAL; + + if (index < SISLANDS_LEAKAGE_INDEX0) + return -EINVAL; + + for (i = 0; i < si_pi->leakage_voltage.count; i++) { + if (si_pi->leakage_voltage.entries[i].leakage_index == index) { + *leakage_voltage = si_pi->leakage_voltage.entries[i].voltage; + return 0; + } + } + return -EAGAIN; +} + +static void si_set_dpm_event_sources(struct amdgpu_device *adev, u32 sources) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + bool want_thermal_protection; + enum amdgpu_dpm_event_src dpm_event_src; + + switch (sources) { + case 0: + default: + want_thermal_protection = false; + break; + case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGITAL; + break; + case (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_EXTERNAL; + break; + case ((1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_EXTERNAL) | + (1 << AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL)): + want_thermal_protection = true; + dpm_event_src = AMDGPU_DPM_EVENT_SRC_DIGIAL_OR_EXTERNAL; + break; + } + + if (want_thermal_protection) { + WREG32_P(CG_THERMAL_CTRL, DPM_EVENT_SRC(dpm_event_src), ~DPM_EVENT_SRC_MASK); + if (pi->thermal_protection) + WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); + } else { + WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); + } +} + +static void si_enable_auto_throttle_source(struct amdgpu_device *adev, + enum amdgpu_dpm_auto_throttle_src source, + bool enable) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + if (enable) { + if (!(pi->active_auto_throttle_sources & (1 << source))) { + pi->active_auto_throttle_sources |= 1 << source; + si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); + } + } else { + if (pi->active_auto_throttle_sources & (1 << source)) { + pi->active_auto_throttle_sources &= ~(1 << source); + si_set_dpm_event_sources(adev, pi->active_auto_throttle_sources); + } + } +} + +static void si_start_dpm(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); +} + +static void si_stop_dpm(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, 0, ~GLOBAL_PWRMGT_EN); +} + +static void si_enable_sclk_control(struct amdgpu_device *adev, bool enable) +{ + if (enable) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~SCLK_PWRMGT_OFF); + else + WREG32_P(SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, ~SCLK_PWRMGT_OFF); + +} + +#if 0 +static int si_notify_hardware_of_thermal_state(struct amdgpu_device *adev, + u32 thermal_level) +{ + PPSMC_Result ret; + + if (thermal_level == 0) { + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + if (ret == PPSMC_Result_OK) + return 0; + else + return -EINVAL; + } + return 0; +} + +static void si_notify_hardware_vpu_recovery_event(struct amdgpu_device *adev) +{ + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen, true); +} +#endif + +#if 0 +static int si_notify_hw_of_powersource(struct amdgpu_device *adev, bool ac_power) +{ + if (ac_power) + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_RunningOnAC) == PPSMC_Result_OK) ? + 0 : -EINVAL; + + return 0; +} +#endif + +static PPSMC_Result si_send_msg_to_smc_with_parameter(struct amdgpu_device *adev, + PPSMC_Msg msg, u32 parameter) +{ + WREG32(SMC_SCRATCH0, parameter); + return amdgpu_si_send_msg_to_smc(adev, msg); +} + +static int si_restrict_performance_levels_before_switch(struct amdgpu_device *adev) +{ + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_NoForcedLevel) != PPSMC_Result_OK) + return -EINVAL; + + return (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_dpm_force_performance_level(void *handle, + enum amd_dpm_forced_level level) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_ps *rps = adev->pm.dpm.current_ps; + struct si_ps *ps = si_get_ps(rps); + u32 levels = ps->performance_level_count; + + if (level == AMD_DPM_FORCED_LEVEL_HIGH) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 1) != PPSMC_Result_OK) + return -EINVAL; + } else if (level == AMD_DPM_FORCED_LEVEL_LOW) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, 1) != PPSMC_Result_OK) + return -EINVAL; + } else if (level == AMD_DPM_FORCED_LEVEL_AUTO) { + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetForcedLevels, 0) != PPSMC_Result_OK) + return -EINVAL; + + if (si_send_msg_to_smc_with_parameter(adev, PPSMC_MSG_SetEnabledLevels, levels) != PPSMC_Result_OK) + return -EINVAL; + } + + adev->pm.dpm.forced_level = level; + + return 0; +} + +#if 0 +static int si_set_boot_state(struct amdgpu_device *adev) +{ + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToInitialState) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} +#endif + +static int si_set_sw_state(struct amdgpu_device *adev) +{ + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_SwitchToSwState) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_halt_smc(struct amdgpu_device *adev) +{ + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Halt) != PPSMC_Result_OK) + return -EINVAL; + + return (amdgpu_si_wait_for_smc_inactive(adev) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_resume_smc(struct amdgpu_device *adev) +{ + if (amdgpu_si_send_msg_to_smc(adev, PPSMC_FlushDataCache) != PPSMC_Result_OK) + return -EINVAL; + + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_Resume) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static void si_dpm_start_smc(struct amdgpu_device *adev) +{ + amdgpu_si_program_jump_on_start(adev); + amdgpu_si_start_smc(adev); + amdgpu_si_smc_clock(adev, true); +} + +static void si_dpm_stop_smc(struct amdgpu_device *adev) +{ + amdgpu_si_reset_smc(adev); + amdgpu_si_smc_clock(adev, false); +} + +static int si_process_firmware_header(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_stateTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->state_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_softRegisters, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->soft_regs_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->mc_reg_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_fanTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->fan_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->arb_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->cac_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->dte_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_spllTable, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->spll_table_start = tmp; + + ret = amdgpu_si_read_smc_sram_dword(adev, + SISLANDS_SMC_FIRMWARE_HEADER_LOCATION + + SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + si_pi->papm_cfg_table_start = tmp; + + return ret; +} + +static void si_read_clock_registers(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + si_pi->clock_registers.cg_spll_func_cntl = RREG32(CG_SPLL_FUNC_CNTL); + si_pi->clock_registers.cg_spll_func_cntl_2 = RREG32(CG_SPLL_FUNC_CNTL_2); + si_pi->clock_registers.cg_spll_func_cntl_3 = RREG32(CG_SPLL_FUNC_CNTL_3); + si_pi->clock_registers.cg_spll_func_cntl_4 = RREG32(CG_SPLL_FUNC_CNTL_4); + si_pi->clock_registers.cg_spll_spread_spectrum = RREG32(CG_SPLL_SPREAD_SPECTRUM); + si_pi->clock_registers.cg_spll_spread_spectrum_2 = RREG32(CG_SPLL_SPREAD_SPECTRUM_2); + si_pi->clock_registers.dll_cntl = RREG32(DLL_CNTL); + si_pi->clock_registers.mclk_pwrmgt_cntl = RREG32(MCLK_PWRMGT_CNTL); + si_pi->clock_registers.mpll_ad_func_cntl = RREG32(MPLL_AD_FUNC_CNTL); + si_pi->clock_registers.mpll_dq_func_cntl = RREG32(MPLL_DQ_FUNC_CNTL); + si_pi->clock_registers.mpll_func_cntl = RREG32(MPLL_FUNC_CNTL); + si_pi->clock_registers.mpll_func_cntl_1 = RREG32(MPLL_FUNC_CNTL_1); + si_pi->clock_registers.mpll_func_cntl_2 = RREG32(MPLL_FUNC_CNTL_2); + si_pi->clock_registers.mpll_ss1 = RREG32(MPLL_SS1); + si_pi->clock_registers.mpll_ss2 = RREG32(MPLL_SS2); +} + +static void si_enable_thermal_protection(struct amdgpu_device *adev, + bool enable) +{ + if (enable) + WREG32_P(GENERAL_PWRMGT, 0, ~THERMAL_PROTECTION_DIS); + else + WREG32_P(GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, ~THERMAL_PROTECTION_DIS); +} + +static void si_enable_acpi_power_management(struct amdgpu_device *adev) +{ + WREG32_P(GENERAL_PWRMGT, STATIC_PM_EN, ~STATIC_PM_EN); +} + +#if 0 +static int si_enter_ulp_state(struct amdgpu_device *adev) +{ + WREG32(SMC_MESSAGE_0, PPSMC_MSG_SwitchToMinimumPower); + + udelay(25000); + + return 0; +} + +static int si_exit_ulp_state(struct amdgpu_device *adev) +{ + int i; + + WREG32(SMC_MESSAGE_0, PPSMC_MSG_ResumeFromMinimumPower); + + udelay(7000); + + for (i = 0; i < adev->usec_timeout; i++) { + if (RREG32(SMC_RESP_0) == 1) + break; + udelay(1000); + } + + return 0; +} +#endif + +static int si_notify_smc_display_change(struct amdgpu_device *adev, + bool has_display) +{ + PPSMC_Msg msg = has_display ? + PPSMC_MSG_HasDisplay : PPSMC_MSG_NoDisplay; + + return (amdgpu_si_send_msg_to_smc(adev, msg) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static void si_program_response_times(struct amdgpu_device *adev) +{ + u32 voltage_response_time, acpi_delay_time, vbi_time_out; + u32 vddc_dly, acpi_dly, vbi_dly; + u32 reference_clock; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mvdd_chg_time, 1); + + voltage_response_time = (u32)adev->pm.dpm.voltage_response_time; + + if (voltage_response_time == 0) + voltage_response_time = 1000; + + acpi_delay_time = 15000; + vbi_time_out = 100000; + + reference_clock = amdgpu_asic_get_xclk(adev); + + vddc_dly = (voltage_response_time * reference_clock) / 100; + acpi_dly = (acpi_delay_time * reference_clock) / 100; + vbi_dly = (vbi_time_out * reference_clock) / 100; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_vreg, vddc_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_delay_acpi, acpi_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mclk_chg_timeout, vbi_dly); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_mc_block_delay, 0xAA); +} + +static void si_program_ds_registers(struct amdgpu_device *adev) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + u32 tmp; + + /* DEEP_SLEEP_CLK_SEL field should be 0x10 on tahiti A0 */ + if (adev->asic_type == CHIP_TAHITI && adev->rev_id == 0x0) + tmp = 0x10; + else + tmp = 0x1; + + if (eg_pi->sclk_deep_sleep) { + WREG32_P(MISC_CLK_CNTL, DEEP_SLEEP_CLK_SEL(tmp), ~DEEP_SLEEP_CLK_SEL_MASK); + WREG32_P(CG_SPLL_AUTOSCALE_CNTL, AUTOSCALE_ON_SS_CLEAR, + ~AUTOSCALE_ON_SS_CLEAR); + } +} + +static void si_program_display_gap(struct amdgpu_device *adev) +{ + u32 tmp, pipe; + int i; + + tmp = RREG32(CG_DISPLAY_GAP_CNTL) & ~(DISP1_GAP_MASK | DISP2_GAP_MASK); + if (adev->pm.dpm.new_active_crtc_count > 0) + tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); + else + tmp |= DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE); + + if (adev->pm.dpm.new_active_crtc_count > 1) + tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_VBLANK_OR_WM); + else + tmp |= DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE); + + WREG32(CG_DISPLAY_GAP_CNTL, tmp); + + tmp = RREG32(DCCG_DISP_SLOW_SELECT_REG); + pipe = (tmp & DCCG_DISP1_SLOW_SELECT_MASK) >> DCCG_DISP1_SLOW_SELECT_SHIFT; + + if ((adev->pm.dpm.new_active_crtc_count > 0) && + (!(adev->pm.dpm.new_active_crtcs & (1 << pipe)))) { + /* find the first active crtc */ + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->pm.dpm.new_active_crtcs & (1 << i)) + break; + } + if (i == adev->mode_info.num_crtc) + pipe = 0; + else + pipe = i; + + tmp &= ~DCCG_DISP1_SLOW_SELECT_MASK; + tmp |= DCCG_DISP1_SLOW_SELECT(pipe); + WREG32(DCCG_DISP_SLOW_SELECT_REG, tmp); + } + + /* Setting this to false forces the performance state to low if the crtcs are disabled. + * This can be a problem on PowerXpress systems or if you want to use the card + * for offscreen rendering or compute if there are no crtcs enabled. + */ + si_notify_smc_display_change(adev, adev->pm.dpm.new_active_crtc_count > 0); +} + +static void si_enable_spread_spectrum(struct amdgpu_device *adev, bool enable) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + if (enable) { + if (pi->sclk_ss) + WREG32_P(GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, ~DYN_SPREAD_SPECTRUM_EN); + } else { + WREG32_P(CG_SPLL_SPREAD_SPECTRUM, 0, ~SSEN); + WREG32_P(GENERAL_PWRMGT, 0, ~DYN_SPREAD_SPECTRUM_EN); + } +} + +static void si_setup_bsp(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + u32 xclk = amdgpu_asic_get_xclk(adev); + + r600_calculate_u_and_p(pi->asi, + xclk, + 16, + &pi->bsp, + &pi->bsu); + + r600_calculate_u_and_p(pi->pasi, + xclk, + 16, + &pi->pbsp, + &pi->pbsu); + + + pi->dsp = BSP(pi->bsp) | BSU(pi->bsu); + pi->psp = BSP(pi->pbsp) | BSU(pi->pbsu); + + WREG32(CG_BSP, pi->dsp); +} + +static void si_program_git(struct amdgpu_device *adev) +{ + WREG32_P(CG_GIT, CG_GICST(R600_GICST_DFLT), ~CG_GICST_MASK); +} + +static void si_program_tp(struct amdgpu_device *adev) +{ + int i; + enum r600_td td = R600_TD_DFLT; + + for (i = 0; i < R600_PM_NUMBER_OF_TC; i++) + WREG32(CG_FFCT_0 + i, (UTC_0(r600_utc[i]) | DTC_0(r600_dtc[i]))); + + if (td == R600_TD_AUTO) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_FORCE_TREND_SEL); + else + WREG32_P(SCLK_PWRMGT_CNTL, FIR_FORCE_TREND_SEL, ~FIR_FORCE_TREND_SEL); + + if (td == R600_TD_UP) + WREG32_P(SCLK_PWRMGT_CNTL, 0, ~FIR_TREND_MODE); + + if (td == R600_TD_DOWN) + WREG32_P(SCLK_PWRMGT_CNTL, FIR_TREND_MODE, ~FIR_TREND_MODE); +} + +static void si_program_tpp(struct amdgpu_device *adev) +{ + WREG32(CG_TPC, R600_TPC_DFLT); +} + +static void si_program_sstp(struct amdgpu_device *adev) +{ + WREG32(CG_SSP, (SSTU(R600_SSTU_DFLT) | SST(R600_SST_DFLT))); +} + +static void si_enable_display_gap(struct amdgpu_device *adev) +{ + u32 tmp = RREG32(CG_DISPLAY_GAP_CNTL); + + tmp &= ~(DISP1_GAP_MASK | DISP2_GAP_MASK); + tmp |= (DISP1_GAP(R600_PM_DISPLAY_GAP_IGNORE) | + DISP2_GAP(R600_PM_DISPLAY_GAP_IGNORE)); + + tmp &= ~(DISP1_GAP_MCHG_MASK | DISP2_GAP_MCHG_MASK); + tmp |= (DISP1_GAP_MCHG(R600_PM_DISPLAY_GAP_VBLANK) | + DISP2_GAP_MCHG(R600_PM_DISPLAY_GAP_IGNORE)); + WREG32(CG_DISPLAY_GAP_CNTL, tmp); +} + +static void si_program_vc(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + WREG32(CG_FTV, pi->vrc); +} + +static void si_clear_vc(struct amdgpu_device *adev) +{ + WREG32(CG_FTV, 0); +} + +static u8 si_get_ddr3_mclk_frequency_ratio(u32 memory_clock) +{ + u8 mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 10000) / 5000 + 1); + return mc_para_index; +} + +static u8 si_get_mclk_frequency_ratio(u32 memory_clock, bool strobe_mode) +{ + u8 mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (u8)((memory_clock - 60000) / 5000); + } + return mc_para_index; +} + +static u8 si_get_strobe_mode_settings(struct amdgpu_device *adev, u32 mclk) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + bool strobe_mode = false; + u8 result = 0; + + if (mclk <= pi->mclk_strobe_mode_threshold) + strobe_mode = true; + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + result = si_get_mclk_frequency_ratio(mclk, strobe_mode); + else + result = si_get_ddr3_mclk_frequency_ratio(mclk); + + if (strobe_mode) + result |= SISLANDS_SMC_STROBE_ENABLE; + + return result; +} + +static int si_upload_firmware(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + amdgpu_si_reset_smc(adev); + amdgpu_si_smc_clock(adev, false); + + return amdgpu_si_load_smc_ucode(adev, si_pi->sram_end); +} + +static bool si_validate_phase_shedding_tables(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + const struct amdgpu_phase_shedding_limits_table *limits) +{ + u32 data, num_bits, num_levels; + + if ((table == NULL) || (limits == NULL)) + return false; + + data = table->mask_low; + + num_bits = hweight32(data); + + if (num_bits == 0) + return false; + + num_levels = (1 << num_bits); + + if (table->count != num_levels) + return false; + + if (limits->count != (num_levels - 1)) + return false; + + return true; +} + +static void si_trim_voltage_table_to_fit_state_table(struct amdgpu_device *adev, + u32 max_voltage_steps, + struct atom_voltage_table *voltage_table) +{ + unsigned int i, diff; + + if (voltage_table->count <= max_voltage_steps) + return; + + diff = voltage_table->count - max_voltage_steps; + + for (i= 0; i < max_voltage_steps; i++) + voltage_table->entries[i] = voltage_table->entries[i + diff]; + + voltage_table->count = max_voltage_steps; +} + +static int si_get_svi2_voltage_table(struct amdgpu_device *adev, + struct amdgpu_clock_voltage_dependency_table *voltage_dependency_table, + struct atom_voltage_table *voltage_table) +{ + u32 i; + + if (voltage_dependency_table == NULL) + return -EINVAL; + + voltage_table->mask_low = 0; + voltage_table->phase_delay = 0; + + voltage_table->count = voltage_dependency_table->count; + for (i = 0; i < voltage_table->count; i++) { + voltage_table->entries[i].value = voltage_dependency_table->entries[i].v; + voltage_table->entries[i].smio_low = 0; + } + + return 0; +} + +static int si_construct_voltage_tables(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + + if (pi->voltage_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, + VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddc_voltage_table); + if (ret) + return ret; + + if (eg_pi->vddc_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddc_voltage_table); + } else if (si_pi->voltage_control_svi2) { + ret = si_get_svi2_voltage_table(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk, + &eg_pi->vddc_voltage_table); + if (ret) + return ret; + } else { + return -EINVAL; + } + + if (eg_pi->vddci_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDCI, + VOLTAGE_OBJ_GPIO_LUT, &eg_pi->vddci_voltage_table); + if (ret) + return ret; + + if (eg_pi->vddci_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &eg_pi->vddci_voltage_table); + } + if (si_pi->vddci_control_svi2) { + ret = si_get_svi2_voltage_table(adev, + &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk, + &eg_pi->vddci_voltage_table); + if (ret) + return ret; + } + + if (pi->mvdd_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_MVDDC, + VOLTAGE_OBJ_GPIO_LUT, &si_pi->mvdd_voltage_table); + + if (ret) { + pi->mvdd_control = false; + return ret; + } + + if (si_pi->mvdd_voltage_table.count == 0) { + pi->mvdd_control = false; + return -EINVAL; + } + + if (si_pi->mvdd_voltage_table.count > SISLANDS_MAX_NO_VREG_STEPS) + si_trim_voltage_table_to_fit_state_table(adev, + SISLANDS_MAX_NO_VREG_STEPS, + &si_pi->mvdd_voltage_table); + } + + if (si_pi->vddc_phase_shed_control) { + ret = amdgpu_atombios_get_voltage_table(adev, VOLTAGE_TYPE_VDDC, + VOLTAGE_OBJ_PHASE_LUT, &si_pi->vddc_phase_shed_table); + if (ret) + si_pi->vddc_phase_shed_control = false; + + if ((si_pi->vddc_phase_shed_table.count == 0) || + (si_pi->vddc_phase_shed_table.count > SISLANDS_MAX_NO_VREG_STEPS)) + si_pi->vddc_phase_shed_control = false; + } + + return 0; +} + +static void si_populate_smc_voltage_table(struct amdgpu_device *adev, + const struct atom_voltage_table *voltage_table, + SISLANDS_SMC_STATETABLE *table) +{ + unsigned int i; + + for (i = 0; i < voltage_table->count; i++) + table->lowSMIO[i] |= cpu_to_be32(voltage_table->entries[i].smio_low); +} + +static int si_populate_smc_voltage_tables(struct amdgpu_device *adev, + SISLANDS_SMC_STATETABLE *table) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u8 i; + + if (si_pi->voltage_control_svi2) { + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc, + si_pi->svc_gpio_id); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd, + si_pi->svd_gpio_id); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_svi_rework_plat_type, + 2); + } else { + if (eg_pi->vddc_voltage_table.count) { + si_populate_smc_voltage_table(adev, &eg_pi->vddc_voltage_table, table); + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC] = + cpu_to_be32(eg_pi->vddc_voltage_table.mask_low); + + for (i = 0; i < eg_pi->vddc_voltage_table.count; i++) { + if (pi->max_vddc_in_table <= eg_pi->vddc_voltage_table.entries[i].value) { + table->maxVDDCIndexInPPTable = i; + break; + } + } + } + + if (eg_pi->vddci_voltage_table.count) { + si_populate_smc_voltage_table(adev, &eg_pi->vddci_voltage_table, table); + + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDCI] = + cpu_to_be32(eg_pi->vddci_voltage_table.mask_low); + } + + + if (si_pi->mvdd_voltage_table.count) { + si_populate_smc_voltage_table(adev, &si_pi->mvdd_voltage_table, table); + + table->voltageMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_MVDD] = + cpu_to_be32(si_pi->mvdd_voltage_table.mask_low); + } + + if (si_pi->vddc_phase_shed_control) { + if (si_validate_phase_shedding_tables(adev, &si_pi->vddc_phase_shed_table, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table)) { + si_populate_smc_voltage_table(adev, &si_pi->vddc_phase_shed_table, table); + + table->phaseMaskTable.lowMask[SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING] = + cpu_to_be32(si_pi->vddc_phase_shed_table.mask_low); + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_phase_shedding_delay, + (u32)si_pi->vddc_phase_shed_table.phase_delay); + } else { + si_pi->vddc_phase_shed_control = false; + } + } + } + + return 0; +} + +static int si_populate_voltage_value(struct amdgpu_device *adev, + const struct atom_voltage_table *table, + u16 value, SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + unsigned int i; + + for (i = 0; i < table->count; i++) { + if (value <= table->entries[i].value) { + voltage->index = (u8)i; + voltage->value = cpu_to_be16(table->entries[i].value); + break; + } + } + + if (i >= table->count) + return -EINVAL; + + return 0; +} + +static int si_populate_mvdd_value(struct amdgpu_device *adev, u32 mclk, + SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (pi->mvdd_control) { + if (mclk <= pi->mvdd_split_frequency) + voltage->index = 0; + else + voltage->index = (u8)(si_pi->mvdd_voltage_table.count) - 1; + + voltage->value = cpu_to_be16(si_pi->mvdd_voltage_table.entries[voltage->index].value); + } + return 0; +} + +static int si_get_std_voltage_value(struct amdgpu_device *adev, + SISLANDS_SMC_VOLTAGE_VALUE *voltage, + u16 *std_voltage) +{ + u16 v_index; + bool voltage_found = false; + *std_voltage = be16_to_cpu(voltage->value); + + if (adev->pm.dpm.dyn_state.cac_leakage_table.entries) { + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE) { + if (adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries == NULL) + return -EINVAL; + + for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { + if (be16_to_cpu(voltage->value) == + (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { + voltage_found = true; + if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; + else + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; + break; + } + } + + if (!voltage_found) { + for (v_index = 0; (u32)v_index < adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.count; v_index++) { + if (be16_to_cpu(voltage->value) <= + (u16)adev->pm.dpm.dyn_state.vddc_dependency_on_sclk.entries[v_index].v) { + voltage_found = true; + if ((u32)v_index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[v_index].vddc; + else + *std_voltage = + adev->pm.dpm.dyn_state.cac_leakage_table.entries[adev->pm.dpm.dyn_state.cac_leakage_table.count-1].vddc; + break; + } + } + } + } else { + if ((u32)voltage->index < adev->pm.dpm.dyn_state.cac_leakage_table.count) + *std_voltage = adev->pm.dpm.dyn_state.cac_leakage_table.entries[voltage->index].vddc; + } + } + + return 0; +} + +static int si_populate_std_voltage_value(struct amdgpu_device *adev, + u16 value, u8 index, + SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + voltage->index = index; + voltage->value = cpu_to_be16(value); + + return 0; +} + +static int si_populate_phase_shedding_value(struct amdgpu_device *adev, + const struct amdgpu_phase_shedding_limits_table *limits, + u16 voltage, u32 sclk, u32 mclk, + SISLANDS_SMC_VOLTAGE_VALUE *smc_voltage) +{ + unsigned int i; + + for (i = 0; i < limits->count; i++) { + if ((voltage <= limits->entries[i].voltage) && + (sclk <= limits->entries[i].sclk) && + (mclk <= limits->entries[i].mclk)) + break; + } + + smc_voltage->phase_settings = (u8)i; + + return 0; +} + +static int si_init_arb_table_index(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + tmp &= 0x00FFFFFF; + tmp |= MC_CG_ARB_FREQ_F1 << 24; + + return amdgpu_si_write_smc_sram_dword(adev, si_pi->arb_table_start, + tmp, si_pi->sram_end); +} + +static int si_initial_switch_from_arb_f0_to_f1(struct amdgpu_device *adev) +{ + return ni_copy_and_switch_arb_sets(adev, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); +} + +static int si_reset_to_default(struct amdgpu_device *adev) +{ + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ResetToDefaults) == PPSMC_Result_OK) ? + 0 : -EINVAL; +} + +static int si_force_switch_to_arb_f0(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + int ret; + + ret = amdgpu_si_read_smc_sram_dword(adev, si_pi->arb_table_start, + &tmp, si_pi->sram_end); + if (ret) + return ret; + + tmp = (tmp >> 24) & 0xff; + + if (tmp == MC_CG_ARB_FREQ_F0) + return 0; + + return ni_copy_and_switch_arb_sets(adev, tmp, MC_CG_ARB_FREQ_F0); +} + +static u32 si_calculate_memory_refresh_rate(struct amdgpu_device *adev, + u32 engine_clock) +{ + u32 dram_rows; + u32 dram_refresh_rate; + u32 mc_arb_rfsh_rate; + u32 tmp = (RREG32(MC_ARB_RAMCFG) & NOOFROWS_MASK) >> NOOFROWS_SHIFT; + + if (tmp >= 4) + dram_rows = 16384; + else + dram_rows = 1 << (tmp + 10); + + dram_refresh_rate = 1 << ((RREG32(MC_SEQ_MISC0) & 0x3) + 3); + mc_arb_rfsh_rate = ((engine_clock * 10) * dram_refresh_rate / dram_rows - 32) / 64; + + return mc_arb_rfsh_rate; +} + +static int si_populate_memory_timing_parameters(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SMC_SIslands_MCArbDramTimingRegisterSet *arb_regs) +{ + u32 dram_timing; + u32 dram_timing2; + u32 burst_time; + + arb_regs->mc_arb_rfsh_rate = + (u8)si_calculate_memory_refresh_rate(adev, pl->sclk); + + amdgpu_atombios_set_engine_dram_timings(adev, + pl->sclk, + pl->mclk); + + dram_timing = RREG32(MC_ARB_DRAM_TIMING); + dram_timing2 = RREG32(MC_ARB_DRAM_TIMING2); + burst_time = RREG32(MC_ARB_BURST_TIME) & STATE0_MASK; + + arb_regs->mc_arb_dram_timing = cpu_to_be32(dram_timing); + arb_regs->mc_arb_dram_timing2 = cpu_to_be32(dram_timing2); + arb_regs->mc_arb_burst_time = (u8)burst_time; + + return 0; +} + +static int si_do_program_memory_timing_parameters(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + unsigned int first_arb_set) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; + int i, ret = 0; + + for (i = 0; i < state->performance_level_count; i++) { + ret = si_populate_memory_timing_parameters(adev, &state->performance_levels[i], &arb_regs); + if (ret) + break; + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * (first_arb_set + i), + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); + if (ret) + break; + } + + return ret; +} + +static int si_program_memory_timing_parameters(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + return si_do_program_memory_timing_parameters(adev, amdgpu_new_state, + SISLANDS_DRIVER_STATE_ARB_INDEX); +} + +static int si_populate_initial_mvdd_value(struct amdgpu_device *adev, + struct SISLANDS_SMC_VOLTAGE_VALUE *voltage) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + + if (pi->mvdd_control) + return si_populate_voltage_value(adev, &si_pi->mvdd_voltage_table, + si_pi->mvdd_bootup_value, voltage); + + return 0; +} + +static int si_populate_smc_initial_state(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_initial_state, + SISLANDS_SMC_STATETABLE *table) +{ + struct si_ps *initial_state = si_get_ps(amdgpu_initial_state); + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 reg; + int ret; + + table->initialState.levels[0].mclk.vDLL_CNTL = + cpu_to_be32(si_pi->clock_registers.dll_cntl); + table->initialState.levels[0].mclk.vMCLK_PWRMGT_CNTL = + cpu_to_be32(si_pi->clock_registers.mclk_pwrmgt_cntl); + table->initialState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_ad_func_cntl); + table->initialState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_dq_func_cntl); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_1); + table->initialState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = + cpu_to_be32(si_pi->clock_registers.mpll_func_cntl_2); + table->initialState.levels[0].mclk.vMPLL_SS = + cpu_to_be32(si_pi->clock_registers.mpll_ss1); + table->initialState.levels[0].mclk.vMPLL_SS2 = + cpu_to_be32(si_pi->clock_registers.mpll_ss2); + + table->initialState.levels[0].mclk.mclk_value = + cpu_to_be32(initial_state->performance_levels[0].mclk); + + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_2); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_3); + table->initialState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = + cpu_to_be32(si_pi->clock_registers.cg_spll_func_cntl_4); + table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM = + cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum); + table->initialState.levels[0].sclk.vCG_SPLL_SPREAD_SPECTRUM_2 = + cpu_to_be32(si_pi->clock_registers.cg_spll_spread_spectrum_2); + + table->initialState.levels[0].sclk.sclk_value = + cpu_to_be32(initial_state->performance_levels[0].sclk); + + table->initialState.levels[0].arbRefreshState = + SISLANDS_INITIAL_STATE_ARB_INDEX; + + table->initialState.levels[0].ACIndex = 0; + + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + initial_state->performance_levels[0].vddc, + &table->initialState.levels[0].vddc); + + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->initialState.levels[0].vddc, + &std_vddc); + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->initialState.levels[0].vddc.index, + &table->initialState.levels[0].std_vddc); + } + + if (eg_pi->vddci_control) + si_populate_voltage_value(adev, + &eg_pi->vddci_voltage_table, + initial_state->performance_levels[0].vddci, + &table->initialState.levels[0].vddci); + + if (si_pi->vddc_phase_shed_control) + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + initial_state->performance_levels[0].vddc, + initial_state->performance_levels[0].sclk, + initial_state->performance_levels[0].mclk, + &table->initialState.levels[0].vddc); + + si_populate_initial_mvdd_value(adev, &table->initialState.levels[0].mvdd); + + reg = CG_R(0xffff) | CG_L(0); + table->initialState.levels[0].aT = cpu_to_be32(reg); + table->initialState.levels[0].bSP = cpu_to_be32(pi->dsp); + table->initialState.levels[0].gen2PCIE = (u8)si_pi->boot_pcie_gen; + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + table->initialState.levels[0].strobeMode = + si_get_strobe_mode_settings(adev, + initial_state->performance_levels[0].mclk); + + if (initial_state->performance_levels[0].mclk > pi->mclk_edc_enable_threshold) + table->initialState.levels[0].mcFlags = SISLANDS_SMC_MC_EDC_RD_FLAG | SISLANDS_SMC_MC_EDC_WR_FLAG; + else + table->initialState.levels[0].mcFlags = 0; + } + + table->initialState.levelCount = 1; + + table->initialState.flags |= PPSMC_SWSTATE_FLAG_DC; + + table->initialState.levels[0].dpm2.MaxPS = 0; + table->initialState.levels[0].dpm2.NearTDPDec = 0; + table->initialState.levels[0].dpm2.AboveSafeInc = 0; + table->initialState.levels[0].dpm2.BelowSafeInc = 0; + table->initialState.levels[0].dpm2.PwrEfficiencyRatio = 0; + + reg = MIN_POWER_MASK | MAX_POWER_MASK; + table->initialState.levels[0].SQPowerThrottle = cpu_to_be32(reg); + + reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + table->initialState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); + + return 0; +} + +static int si_populate_smc_acpi_state(struct amdgpu_device *adev, + SISLANDS_SMC_STATETABLE *table) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; + u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; + u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; + u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; + u32 dll_cntl = si_pi->clock_registers.dll_cntl; + u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; + u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; + u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; + u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; + u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; + u32 reg; + int ret; + + table->ACPIState = table->initialState; + + table->ACPIState.flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (pi->acpi_vddc) { + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + pi->acpi_vddc, &table->ACPIState.levels[0].vddc); + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->ACPIState.levels[0].vddc, &std_vddc); + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->ACPIState.levels[0].vddc.index, + &table->ACPIState.levels[0].std_vddc); + } + table->ACPIState.levels[0].gen2PCIE = si_pi->acpi_pcie_gen; + + if (si_pi->vddc_phase_shed_control) { + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pi->acpi_vddc, + 0, + 0, + &table->ACPIState.levels[0].vddc); + } + } else { + ret = si_populate_voltage_value(adev, &eg_pi->vddc_voltage_table, + pi->min_vddc_in_table, &table->ACPIState.levels[0].vddc); + if (!ret) { + u16 std_vddc; + + ret = si_get_std_voltage_value(adev, + &table->ACPIState.levels[0].vddc, &std_vddc); + + if (!ret) + si_populate_std_voltage_value(adev, std_vddc, + table->ACPIState.levels[0].vddc.index, + &table->ACPIState.levels[0].std_vddc); + } + table->ACPIState.levels[0].gen2PCIE = + (u8)amdgpu_get_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + AMDGPU_PCIE_GEN1); + + if (si_pi->vddc_phase_shed_control) + si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pi->min_vddc_in_table, + 0, + 0, + &table->ACPIState.levels[0].vddc); + } + + if (pi->acpi_vddc) { + if (eg_pi->acpi_vddci) + si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, + eg_pi->acpi_vddci, + &table->ACPIState.levels[0].vddci); + } + + mclk_pwrmgt_cntl |= MRDCK0_RESET | MRDCK1_RESET; + mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); + + dll_cntl &= ~(MRDCK0_BYPASS | MRDCK1_BYPASS); + + spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; + spll_func_cntl_2 |= SCLK_MUX_SEL(4); + + table->ACPIState.levels[0].mclk.vDLL_CNTL = + cpu_to_be32(dll_cntl); + table->ACPIState.levels[0].mclk.vMCLK_PWRMGT_CNTL = + cpu_to_be32(mclk_pwrmgt_cntl); + table->ACPIState.levels[0].mclk.vMPLL_AD_FUNC_CNTL = + cpu_to_be32(mpll_ad_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_DQ_FUNC_CNTL = + cpu_to_be32(mpll_dq_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL = + cpu_to_be32(mpll_func_cntl); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_1 = + cpu_to_be32(mpll_func_cntl_1); + table->ACPIState.levels[0].mclk.vMPLL_FUNC_CNTL_2 = + cpu_to_be32(mpll_func_cntl_2); + table->ACPIState.levels[0].mclk.vMPLL_SS = + cpu_to_be32(si_pi->clock_registers.mpll_ss1); + table->ACPIState.levels[0].mclk.vMPLL_SS2 = + cpu_to_be32(si_pi->clock_registers.mpll_ss2); + + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL = + cpu_to_be32(spll_func_cntl); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_2 = + cpu_to_be32(spll_func_cntl_2); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_3 = + cpu_to_be32(spll_func_cntl_3); + table->ACPIState.levels[0].sclk.vCG_SPLL_FUNC_CNTL_4 = + cpu_to_be32(spll_func_cntl_4); + + table->ACPIState.levels[0].mclk.mclk_value = 0; + table->ACPIState.levels[0].sclk.sclk_value = 0; + + si_populate_mvdd_value(adev, 0, &table->ACPIState.levels[0].mvdd); + + if (eg_pi->dynamic_ac_timing) + table->ACPIState.levels[0].ACIndex = 0; + + table->ACPIState.levels[0].dpm2.MaxPS = 0; + table->ACPIState.levels[0].dpm2.NearTDPDec = 0; + table->ACPIState.levels[0].dpm2.AboveSafeInc = 0; + table->ACPIState.levels[0].dpm2.BelowSafeInc = 0; + table->ACPIState.levels[0].dpm2.PwrEfficiencyRatio = 0; + + reg = MIN_POWER_MASK | MAX_POWER_MASK; + table->ACPIState.levels[0].SQPowerThrottle = cpu_to_be32(reg); + + reg = MAX_POWER_DELTA_MASK | STI_SIZE_MASK | LTI_RATIO_MASK; + table->ACPIState.levels[0].SQPowerThrottle_2 = cpu_to_be32(reg); + + return 0; +} + +static int si_populate_ulv_state(struct amdgpu_device *adev, + SISLANDS_SMC_SWSTATE *state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + u32 sclk_in_sr = 1350; /* ??? */ + int ret; + + ret = si_convert_power_level_to_smc(adev, &ulv->pl, + &state->levels[0]); + if (!ret) { + if (eg_pi->sclk_deep_sleep) { + if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) + state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; + else + state->levels[0].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; + } + if (ulv->one_pcie_lane_in_ulv) + state->flags |= PPSMC_SWSTATE_FLAG_PCIE_X1; + state->levels[0].arbRefreshState = (u8)(SISLANDS_ULV_STATE_ARB_INDEX); + state->levels[0].ACIndex = 1; + state->levels[0].std_vddc = state->levels[0].vddc; + state->levelCount = 1; + + state->flags |= PPSMC_SWSTATE_FLAG_DC; + } + + return ret; +} + +static int si_program_ulv_memory_timing_parameters(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + SMC_SIslands_MCArbDramTimingRegisterSet arb_regs = { 0 }; + int ret; + + ret = si_populate_memory_timing_parameters(adev, &ulv->pl, + &arb_regs); + if (ret) + return ret; + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_ulv_volt_change_delay, + ulv->volt_change_delay); + + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->arb_table_start + + offsetof(SMC_SIslands_MCArbDramTimingRegisters, data) + + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet) * SISLANDS_ULV_STATE_ARB_INDEX, + (u8 *)&arb_regs, + sizeof(SMC_SIslands_MCArbDramTimingRegisterSet), + si_pi->sram_end); + + return ret; +} + +static void si_get_mvdd_configuration(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + + pi->mvdd_split_frequency = 30000; +} + +static int si_init_smc_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_ps *amdgpu_boot_state = adev->pm.dpm.boot_ps; + const struct si_ulv_param *ulv = &si_pi->ulv; + SISLANDS_SMC_STATETABLE *table = &si_pi->smc_statetable; + int ret; + u32 lane_width; + u32 vr_hot_gpio; + + si_populate_smc_voltage_tables(adev, table); + + switch (adev->pm.int_thermal_type) { + case THERMAL_TYPE_SI: + case THERMAL_TYPE_EMC2103_WITH_INTERNAL: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_INTERNAL; + break; + case THERMAL_TYPE_NONE: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_NONE; + break; + default: + table->thermalProtectType = PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL; + break; + } + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC) + table->systemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT) { + if ((adev->pdev->device != 0x6818) && (adev->pdev->device != 0x6819)) + table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT; + } + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC) + table->systemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + table->systemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY) + table->extraFlags |= PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH; + + if (adev->pm.dpm.platform_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE) { + table->systemFlags |= PPSMC_SYSTEMFLAG_REGULATOR_HOT_PROG_GPIO; + vr_hot_gpio = adev->pm.dpm.backbias_response_time; + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_vr_hot_gpio, + vr_hot_gpio); + } + + ret = si_populate_smc_initial_state(adev, amdgpu_boot_state, table); + if (ret) + return ret; + + ret = si_populate_smc_acpi_state(adev, table); + if (ret) + return ret; + + table->driverState = table->initialState; + + ret = si_do_program_memory_timing_parameters(adev, amdgpu_boot_state, + SISLANDS_INITIAL_STATE_ARB_INDEX); + if (ret) + return ret; + + if (ulv->supported && ulv->pl.vddc) { + ret = si_populate_ulv_state(adev, &table->ULVState); + if (ret) + return ret; + + ret = si_program_ulv_memory_timing_parameters(adev); + if (ret) + return ret; + + WREG32(CG_ULV_CONTROL, ulv->cg_ulv_control); + WREG32(CG_ULV_PARAMETER, ulv->cg_ulv_parameter); + + lane_width = amdgpu_get_pcie_lanes(adev); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); + } else { + table->ULVState = table->initialState; + } + + return amdgpu_si_copy_bytes_to_smc(adev, si_pi->state_table_start, + (u8 *)table, sizeof(SISLANDS_SMC_STATETABLE), + si_pi->sram_end); +} + +static int si_calculate_sclk_params(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct atom_clock_dividers dividers; + u32 spll_func_cntl = si_pi->clock_registers.cg_spll_func_cntl; + u32 spll_func_cntl_2 = si_pi->clock_registers.cg_spll_func_cntl_2; + u32 spll_func_cntl_3 = si_pi->clock_registers.cg_spll_func_cntl_3; + u32 spll_func_cntl_4 = si_pi->clock_registers.cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum = si_pi->clock_registers.cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2 = si_pi->clock_registers.cg_spll_spread_spectrum_2; + u64 tmp; + u32 reference_clock = adev->clock.spll.reference_freq; + u32 reference_divider; + u32 fbdiv; + int ret; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + engine_clock, false, ÷rs); + if (ret) + return ret; + + reference_divider = 1 + dividers.ref_div; + + tmp = (u64) engine_clock * reference_divider * dividers.post_div * 16384; + do_div(tmp, reference_clock); + fbdiv = (u32) tmp; + + spll_func_cntl &= ~(SPLL_PDIV_A_MASK | SPLL_REF_DIV_MASK); + spll_func_cntl |= SPLL_REF_DIV(dividers.ref_div); + spll_func_cntl |= SPLL_PDIV_A(dividers.post_div); + + spll_func_cntl_2 &= ~SCLK_MUX_SEL_MASK; + spll_func_cntl_2 |= SCLK_MUX_SEL(2); + + spll_func_cntl_3 &= ~SPLL_FB_DIV_MASK; + spll_func_cntl_3 |= SPLL_FB_DIV(fbdiv); + spll_func_cntl_3 |= SPLL_DITHEN; + + if (pi->sclk_ss) { + struct amdgpu_atom_ss ss; + u32 vco_freq = engine_clock * dividers.post_div; + + if (amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_ENGINE_SS, vco_freq)) { + u32 clk_s = reference_clock * 5 / (reference_divider * ss.rate); + u32 clk_v = 4 * ss.percentage * fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum &= ~CLK_S_MASK; + cg_spll_spread_spectrum |= CLK_S(clk_s); + cg_spll_spread_spectrum |= SSEN; + + cg_spll_spread_spectrum_2 &= ~CLK_V_MASK; + cg_spll_spread_spectrum_2 |= CLK_V(clk_v); + } + } + + sclk->sclk_value = engine_clock; + sclk->vCG_SPLL_FUNC_CNTL = spll_func_cntl; + sclk->vCG_SPLL_FUNC_CNTL_2 = spll_func_cntl_2; + sclk->vCG_SPLL_FUNC_CNTL_3 = spll_func_cntl_3; + sclk->vCG_SPLL_FUNC_CNTL_4 = spll_func_cntl_4; + sclk->vCG_SPLL_SPREAD_SPECTRUM = cg_spll_spread_spectrum; + sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cg_spll_spread_spectrum_2; + + return 0; +} + +static int si_populate_sclk_value(struct amdgpu_device *adev, + u32 engine_clock, + SISLANDS_SMC_SCLK_VALUE *sclk) +{ + SISLANDS_SMC_SCLK_VALUE sclk_tmp; + int ret; + + ret = si_calculate_sclk_params(adev, engine_clock, &sclk_tmp); + if (!ret) { + sclk->sclk_value = cpu_to_be32(sclk_tmp.sclk_value); + sclk->vCG_SPLL_FUNC_CNTL = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL); + sclk->vCG_SPLL_FUNC_CNTL_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_2); + sclk->vCG_SPLL_FUNC_CNTL_3 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_3); + sclk->vCG_SPLL_FUNC_CNTL_4 = cpu_to_be32(sclk_tmp.vCG_SPLL_FUNC_CNTL_4); + sclk->vCG_SPLL_SPREAD_SPECTRUM = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM); + sclk->vCG_SPLL_SPREAD_SPECTRUM_2 = cpu_to_be32(sclk_tmp.vCG_SPLL_SPREAD_SPECTRUM_2); + } + + return ret; +} + +static int si_populate_mclk_value(struct amdgpu_device *adev, + u32 engine_clock, + u32 memory_clock, + SISLANDS_SMC_MCLK_VALUE *mclk, + bool strobe_mode, + bool dll_state_on) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + u32 dll_cntl = si_pi->clock_registers.dll_cntl; + u32 mclk_pwrmgt_cntl = si_pi->clock_registers.mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl = si_pi->clock_registers.mpll_ad_func_cntl; + u32 mpll_dq_func_cntl = si_pi->clock_registers.mpll_dq_func_cntl; + u32 mpll_func_cntl = si_pi->clock_registers.mpll_func_cntl; + u32 mpll_func_cntl_1 = si_pi->clock_registers.mpll_func_cntl_1; + u32 mpll_func_cntl_2 = si_pi->clock_registers.mpll_func_cntl_2; + u32 mpll_ss1 = si_pi->clock_registers.mpll_ss1; + u32 mpll_ss2 = si_pi->clock_registers.mpll_ss2; + struct atom_mpll_param mpll_param; + int ret; + + ret = amdgpu_atombios_get_memory_pll_dividers(adev, memory_clock, strobe_mode, &mpll_param); + if (ret) + return ret; + + mpll_func_cntl &= ~BWCTRL_MASK; + mpll_func_cntl |= BWCTRL(mpll_param.bwcntl); + + mpll_func_cntl_1 &= ~(CLKF_MASK | CLKFRAC_MASK | VCO_MODE_MASK); + mpll_func_cntl_1 |= CLKF(mpll_param.clkf) | + CLKFRAC(mpll_param.clkfrac) | VCO_MODE(mpll_param.vco_mode); + + mpll_ad_func_cntl &= ~YCLK_POST_DIV_MASK; + mpll_ad_func_cntl |= YCLK_POST_DIV(mpll_param.post_div); + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + mpll_dq_func_cntl &= ~(YCLK_SEL_MASK | YCLK_POST_DIV_MASK); + mpll_dq_func_cntl |= YCLK_SEL(mpll_param.yclk_sel) | + YCLK_POST_DIV(mpll_param.post_div); + } + + if (pi->mclk_ss) { + struct amdgpu_atom_ss ss; + u32 freq_nom; + u32 tmp; + u32 reference_clock = adev->clock.mpll.reference_freq; + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) + freq_nom = memory_clock * 4; + else + freq_nom = memory_clock * 2; + + tmp = freq_nom / reference_clock; + tmp = tmp * tmp; + if (amdgpu_atombios_get_asic_ss_info(adev, &ss, + ASIC_INTERNAL_MEMORY_SS, freq_nom)) { + u32 clks = reference_clock * 5 / ss.rate; + u32 clkv = (u32)((((131 * ss.percentage * ss.rate) / 100) * tmp) / freq_nom); + + mpll_ss1 &= ~CLKV_MASK; + mpll_ss1 |= CLKV(clkv); + + mpll_ss2 &= ~CLKS_MASK; + mpll_ss2 |= CLKS(clks); + } + } + + mclk_pwrmgt_cntl &= ~DLL_SPEED_MASK; + mclk_pwrmgt_cntl |= DLL_SPEED(mpll_param.dll_speed); + + if (dll_state_on) + mclk_pwrmgt_cntl |= MRDCK0_PDNB | MRDCK1_PDNB; + else + mclk_pwrmgt_cntl &= ~(MRDCK0_PDNB | MRDCK1_PDNB); + + mclk->mclk_value = cpu_to_be32(memory_clock); + mclk->vMPLL_FUNC_CNTL = cpu_to_be32(mpll_func_cntl); + mclk->vMPLL_FUNC_CNTL_1 = cpu_to_be32(mpll_func_cntl_1); + mclk->vMPLL_FUNC_CNTL_2 = cpu_to_be32(mpll_func_cntl_2); + mclk->vMPLL_AD_FUNC_CNTL = cpu_to_be32(mpll_ad_func_cntl); + mclk->vMPLL_DQ_FUNC_CNTL = cpu_to_be32(mpll_dq_func_cntl); + mclk->vMCLK_PWRMGT_CNTL = cpu_to_be32(mclk_pwrmgt_cntl); + mclk->vDLL_CNTL = cpu_to_be32(dll_cntl); + mclk->vMPLL_SS = cpu_to_be32(mpll_ss1); + mclk->vMPLL_SS2 = cpu_to_be32(mpll_ss2); + + return 0; +} + +static void si_populate_smc_sp(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct si_ps *ps = si_get_ps(amdgpu_state); + struct rv7xx_power_info *pi = rv770_get_pi(adev); + int i; + + for (i = 0; i < ps->performance_level_count - 1; i++) + smc_state->levels[i].bSP = cpu_to_be32(pi->dsp); + + smc_state->levels[ps->performance_level_count - 1].bSP = + cpu_to_be32(pi->psp); +} + +static int si_convert_power_level_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SISLANDS_SMC_HW_PERFORMANCE_LEVEL *level) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + int ret; + bool dll_state_on; + u16 std_vddc; + bool gmc_pg = false; + + if (eg_pi->pcie_performance_request && + (si_pi->force_pcie_gen != AMDGPU_PCIE_GEN_INVALID)) + level->gen2PCIE = (u8)si_pi->force_pcie_gen; + else + level->gen2PCIE = (u8)pl->pcie_gen; + + ret = si_populate_sclk_value(adev, pl->sclk, &level->sclk); + if (ret) + return ret; + + level->mcFlags = 0; + + if (pi->mclk_stutter_mode_threshold && + (pl->mclk <= pi->mclk_stutter_mode_threshold) && + !eg_pi->uvd_enabled && + (RREG32(DPG_PIPE_STUTTER_CONTROL) & STUTTER_ENABLE) && + (adev->pm.dpm.new_active_crtc_count <= 2)) { + level->mcFlags |= SISLANDS_SMC_MC_STUTTER_EN; + + if (gmc_pg) + level->mcFlags |= SISLANDS_SMC_MC_PG_EN; + } + + if (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5) { + if (pl->mclk > pi->mclk_edc_enable_threshold) + level->mcFlags |= SISLANDS_SMC_MC_EDC_RD_FLAG; + + if (pl->mclk > eg_pi->mclk_edc_wr_enable_threshold) + level->mcFlags |= SISLANDS_SMC_MC_EDC_WR_FLAG; + + level->strobeMode = si_get_strobe_mode_settings(adev, pl->mclk); + + if (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) { + if (si_get_mclk_frequency_ratio(pl->mclk, true) >= + ((RREG32(MC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; + else + dll_state_on = ((RREG32(MC_SEQ_MISC6) >> 1) & 0x1) ? true : false; + } else { + dll_state_on = false; + } + } else { + level->strobeMode = si_get_strobe_mode_settings(adev, + pl->mclk); + + dll_state_on = ((RREG32(MC_SEQ_MISC5) >> 1) & 0x1) ? true : false; + } + + ret = si_populate_mclk_value(adev, + pl->sclk, + pl->mclk, + &level->mclk, + (level->strobeMode & SISLANDS_SMC_STROBE_ENABLE) != 0, dll_state_on); + if (ret) + return ret; + + ret = si_populate_voltage_value(adev, + &eg_pi->vddc_voltage_table, + pl->vddc, &level->vddc); + if (ret) + return ret; + + + ret = si_get_std_voltage_value(adev, &level->vddc, &std_vddc); + if (ret) + return ret; + + ret = si_populate_std_voltage_value(adev, std_vddc, + level->vddc.index, &level->std_vddc); + if (ret) + return ret; + + if (eg_pi->vddci_control) { + ret = si_populate_voltage_value(adev, &eg_pi->vddci_voltage_table, + pl->vddci, &level->vddci); + if (ret) + return ret; + } + + if (si_pi->vddc_phase_shed_control) { + ret = si_populate_phase_shedding_value(adev, + &adev->pm.dpm.dyn_state.phase_shedding_limits_table, + pl->vddc, + pl->sclk, + pl->mclk, + &level->vddc); + if (ret) + return ret; + } + + level->MaxPoweredUpCU = si_pi->max_cu; + + ret = si_populate_mvdd_value(adev, pl->mclk, &level->mvdd); + + return ret; +} + +static int si_populate_smc_t(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + u32 a_t; + u32 t_l, t_h; + u32 high_bsp; + int i, ret; + + if (state->performance_level_count >= 9) + return -EINVAL; + + if (state->performance_level_count < 2) { + a_t = CG_R(0xffff) | CG_L(0); + smc_state->levels[0].aT = cpu_to_be32(a_t); + return 0; + } + + smc_state->levels[0].aT = cpu_to_be32(0); + + for (i = 0; i <= state->performance_level_count - 2; i++) { + ret = r600_calculate_at( + (50 / SISLANDS_MAX_HARDWARE_POWERLEVELS) * 100 * (i + 1), + 100 * R600_AH_DFLT, + state->performance_levels[i + 1].sclk, + state->performance_levels[i].sclk, + &t_l, + &t_h); + + if (ret) { + t_h = (i + 1) * 1000 - 50 * R600_AH_DFLT; + t_l = (i + 1) * 1000 + 50 * R600_AH_DFLT; + } + + a_t = be32_to_cpu(smc_state->levels[i].aT) & ~CG_R_MASK; + a_t |= CG_R(t_l * pi->bsp / 20000); + smc_state->levels[i].aT = cpu_to_be32(a_t); + + high_bsp = (i == state->performance_level_count - 2) ? + pi->pbsp : pi->bsp; + a_t = CG_R(0xffff) | CG_L(t_h * high_bsp / 20000); + smc_state->levels[i + 1].aT = cpu_to_be32(a_t); + } + + return 0; +} + +static int si_disable_ulv(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + + if (ulv->supported) + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_DisableULV) == PPSMC_Result_OK) ? + 0 : -EINVAL; + + return 0; +} + +static bool si_is_state_ulv_compatible(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + const struct si_power_info *si_pi = si_get_pi(adev); + const struct si_ulv_param *ulv = &si_pi->ulv; + const struct si_ps *state = si_get_ps(amdgpu_state); + int i; + + if (state->performance_levels[0].mclk != ulv->pl.mclk) + return false; + + /* XXX validate against display requirements! */ + + for (i = 0; i < adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count; i++) { + if (adev->clock.current_dispclk <= + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].clk) { + if (ulv->pl.vddc < + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[i].v) + return false; + } + } + + if ((amdgpu_state->vclk != 0) || (amdgpu_state->dclk != 0)) + return false; + + return true; +} + +static int si_set_power_state_conditionally_enable_ulv(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + const struct si_power_info *si_pi = si_get_pi(adev); + const struct si_ulv_param *ulv = &si_pi->ulv; + + if (ulv->supported) { + if (si_is_state_ulv_compatible(adev, amdgpu_new_state)) + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableULV) == PPSMC_Result_OK) ? + 0 : -EINVAL; + } + return 0; +} + +static int si_convert_power_state_to_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SISLANDS_SMC_SWSTATE *smc_state) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct ni_power_info *ni_pi = ni_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *state = si_get_ps(amdgpu_state); + int i, ret; + u32 threshold; + u32 sclk_in_sr = 1350; /* ??? */ + + if (state->performance_level_count > SISLANDS_MAX_HARDWARE_POWERLEVELS) + return -EINVAL; + + threshold = state->performance_levels[state->performance_level_count-1].sclk * 100 / 100; + + if (amdgpu_state->vclk && amdgpu_state->dclk) { + eg_pi->uvd_enabled = true; + if (eg_pi->smu_uvd_hs) + smc_state->flags |= PPSMC_SWSTATE_FLAG_UVD; + } else { + eg_pi->uvd_enabled = false; + } + + if (state->dc_compatible) + smc_state->flags |= PPSMC_SWSTATE_FLAG_DC; + + smc_state->levelCount = 0; + for (i = 0; i < state->performance_level_count; i++) { + if (eg_pi->sclk_deep_sleep) { + if ((i == 0) || si_pi->sclk_deep_sleep_above_low) { + if (sclk_in_sr <= SCLK_MIN_DEEPSLEEP_FREQ) + smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_BYPASS; + else + smc_state->levels[i].stateFlags |= PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE; + } + } + + ret = si_convert_power_level_to_smc(adev, &state->performance_levels[i], + &smc_state->levels[i]); + smc_state->levels[i].arbRefreshState = + (u8)(SISLANDS_DRIVER_STATE_ARB_INDEX + i); + + if (ret) + return ret; + + if (ni_pi->enable_power_containment) + smc_state->levels[i].displayWatermark = + (state->performance_levels[i].sclk < threshold) ? + PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; + else + smc_state->levels[i].displayWatermark = (i < 2) ? + PPSMC_DISPLAY_WATERMARK_LOW : PPSMC_DISPLAY_WATERMARK_HIGH; + + if (eg_pi->dynamic_ac_timing) + smc_state->levels[i].ACIndex = SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i; + else + smc_state->levels[i].ACIndex = 0; + + smc_state->levelCount++; + } + + si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_watermark_threshold, + threshold / 512); + + si_populate_smc_sp(adev, amdgpu_state, smc_state); + + ret = si_populate_power_containment_values(adev, amdgpu_state, smc_state); + if (ret) + ni_pi->enable_power_containment = false; + + ret = si_populate_sq_ramping_values(adev, amdgpu_state, smc_state); + if (ret) + ni_pi->enable_sq_ramping = false; + + return si_populate_smc_t(adev, amdgpu_state, smc_state); +} + +static int si_upload_sw_state(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *new_state = si_get_ps(amdgpu_new_state); + int ret; + u32 address = si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, driverState); + u32 state_size = sizeof(SISLANDS_SMC_SWSTATE) + + ((new_state->performance_level_count - 1) * + sizeof(SISLANDS_SMC_HW_PERFORMANCE_LEVEL)); + SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.driverState; + + memset(smc_state, 0, state_size); + + ret = si_convert_power_state_to_smc(adev, amdgpu_new_state, smc_state); + if (ret) + return ret; + + return amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); +} + +static int si_upload_ulv_state(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + int ret = 0; + + if (ulv->supported && ulv->pl.vddc) { + u32 address = si_pi->state_table_start + + offsetof(SISLANDS_SMC_STATETABLE, ULVState); + SISLANDS_SMC_SWSTATE *smc_state = &si_pi->smc_statetable.ULVState; + u32 state_size = sizeof(SISLANDS_SMC_SWSTATE); + + memset(smc_state, 0, state_size); + + ret = si_populate_ulv_state(adev, smc_state); + if (!ret) + ret = amdgpu_si_copy_bytes_to_smc(adev, address, (u8 *)smc_state, + state_size, si_pi->sram_end); + } + + return ret; +} + +static int si_upload_smc_data(struct amdgpu_device *adev) +{ + struct amdgpu_crtc *amdgpu_crtc = NULL; + int i; + + if (adev->pm.dpm.new_active_crtc_count == 0) + return 0; + + for (i = 0; i < adev->mode_info.num_crtc; i++) { + if (adev->pm.dpm.new_active_crtcs & (1 << i)) { + amdgpu_crtc = adev->mode_info.crtcs[i]; + break; + } + } + + if (amdgpu_crtc == NULL) + return 0; + + if (amdgpu_crtc->line_time <= 0) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_crtc_index, + amdgpu_crtc->crtc_id) != PPSMC_Result_OK) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min, + amdgpu_crtc->wm_high / amdgpu_crtc->line_time) != PPSMC_Result_OK) + return 0; + + if (si_write_smc_soft_register(adev, + SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max, + amdgpu_crtc->wm_low / amdgpu_crtc->line_time) != PPSMC_Result_OK) + return 0; + + return 0; +} + +static int si_set_mc_special_registers(struct amdgpu_device *adev, + struct si_mc_reg_table *table) +{ + u8 i, j, k; + u32 temp_reg; + + for (i = 0, j = table->last; i < table->last; i++) { + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + switch (table->mc_reg_address[i].s1) { + case MC_SEQ_MISC1: + temp_reg = RREG32(MC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = MC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + j++; + + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + temp_reg = RREG32(MC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + + if (adev->gmc.vram_type != AMDGPU_VRAM_TYPE_GDDR5) { + if (j >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + table->mc_reg_address[j].s1 = MC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = MC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + j++; + } + break; + case MC_SEQ_RESERVE_M: + temp_reg = RREG32(MC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = MC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = MC_SEQ_PMG_CMD_MRS1_LP; + for(k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + j++; + break; + default: + break; + } + } + + table->last = j; + + return 0; +} + +static bool si_check_s0_mc_reg_index(u16 in_reg, u16 *out_reg) +{ + bool result = true; + switch (in_reg) { + case MC_SEQ_RAS_TIMING: + *out_reg = MC_SEQ_RAS_TIMING_LP; + break; + case MC_SEQ_CAS_TIMING: + *out_reg = MC_SEQ_CAS_TIMING_LP; + break; + case MC_SEQ_MISC_TIMING: + *out_reg = MC_SEQ_MISC_TIMING_LP; + break; + case MC_SEQ_MISC_TIMING2: + *out_reg = MC_SEQ_MISC_TIMING2_LP; + break; + case MC_SEQ_RD_CTL_D0: + *out_reg = MC_SEQ_RD_CTL_D0_LP; + break; + case MC_SEQ_RD_CTL_D1: + *out_reg = MC_SEQ_RD_CTL_D1_LP; + break; + case MC_SEQ_WR_CTL_D0: + *out_reg = MC_SEQ_WR_CTL_D0_LP; + break; + case MC_SEQ_WR_CTL_D1: + *out_reg = MC_SEQ_WR_CTL_D1_LP; + break; + case MC_PMG_CMD_EMRS: + *out_reg = MC_SEQ_PMG_CMD_EMRS_LP; + break; + case MC_PMG_CMD_MRS: + *out_reg = MC_SEQ_PMG_CMD_MRS_LP; + break; + case MC_PMG_CMD_MRS1: + *out_reg = MC_SEQ_PMG_CMD_MRS1_LP; + break; + case MC_SEQ_PMG_TIMING: + *out_reg = MC_SEQ_PMG_TIMING_LP; + break; + case MC_PMG_CMD_MRS2: + *out_reg = MC_SEQ_PMG_CMD_MRS2_LP; + break; + case MC_SEQ_WR_CTL_2: + *out_reg = MC_SEQ_WR_CTL_2_LP; + break; + default: + result = false; + break; + } + + return result; +} + +static void si_set_valid_flag(struct si_mc_reg_table *table) +{ + u8 i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != table->mc_reg_table_entry[j].mc_data[i]) { + table->valid_flag |= 1 << i; + break; + } + } + } +} + +static void si_set_s0_mc_reg_index(struct si_mc_reg_table *table) +{ + u32 i; + u16 address; + + for (i = 0; i < table->last; i++) + table->mc_reg_address[i].s0 = si_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) ? + address : table->mc_reg_address[i].s1; + +} + +static int si_copy_vbios_mc_reg_table(struct atom_mc_reg_table *table, + struct si_mc_reg_table *si_table) +{ + u8 i, j; + + if (table->last > SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + return -EINVAL; + if (table->num_entries > MAX_AC_TIMING_ENTRIES) + return -EINVAL; + + for (i = 0; i < table->last; i++) + si_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + si_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + si_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + si_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + si_table->num_entries = table->num_entries; + + return 0; +} + +static int si_initialize_mc_reg_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + struct atom_mc_reg_table *table; + struct si_mc_reg_table *si_table = &si_pi->mc_reg_table; + u8 module_index = rv770_get_memory_module_index(adev); + int ret; + + table = kzalloc(sizeof(struct atom_mc_reg_table), GFP_KERNEL); + if (!table) + return -ENOMEM; + + WREG32(MC_SEQ_RAS_TIMING_LP, RREG32(MC_SEQ_RAS_TIMING)); + WREG32(MC_SEQ_CAS_TIMING_LP, RREG32(MC_SEQ_CAS_TIMING)); + WREG32(MC_SEQ_MISC_TIMING_LP, RREG32(MC_SEQ_MISC_TIMING)); + WREG32(MC_SEQ_MISC_TIMING2_LP, RREG32(MC_SEQ_MISC_TIMING2)); + WREG32(MC_SEQ_PMG_CMD_EMRS_LP, RREG32(MC_PMG_CMD_EMRS)); + WREG32(MC_SEQ_PMG_CMD_MRS_LP, RREG32(MC_PMG_CMD_MRS)); + WREG32(MC_SEQ_PMG_CMD_MRS1_LP, RREG32(MC_PMG_CMD_MRS1)); + WREG32(MC_SEQ_WR_CTL_D0_LP, RREG32(MC_SEQ_WR_CTL_D0)); + WREG32(MC_SEQ_WR_CTL_D1_LP, RREG32(MC_SEQ_WR_CTL_D1)); + WREG32(MC_SEQ_RD_CTL_D0_LP, RREG32(MC_SEQ_RD_CTL_D0)); + WREG32(MC_SEQ_RD_CTL_D1_LP, RREG32(MC_SEQ_RD_CTL_D1)); + WREG32(MC_SEQ_PMG_TIMING_LP, RREG32(MC_SEQ_PMG_TIMING)); + WREG32(MC_SEQ_PMG_CMD_MRS2_LP, RREG32(MC_PMG_CMD_MRS2)); + WREG32(MC_SEQ_WR_CTL_2_LP, RREG32(MC_SEQ_WR_CTL_2)); + + ret = amdgpu_atombios_init_mc_reg_table(adev, module_index, table); + if (ret) + goto init_mc_done; + + ret = si_copy_vbios_mc_reg_table(table, si_table); + if (ret) + goto init_mc_done; + + si_set_s0_mc_reg_index(si_table); + + ret = si_set_mc_special_registers(adev, si_table); + if (ret) + goto init_mc_done; + + si_set_valid_flag(si_table); + +init_mc_done: + kfree(table); + + return ret; + +} + +static void si_populate_mc_reg_addresses(struct amdgpu_device *adev, + SMC_SIslands_MCRegisters *mc_reg_table) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 i, j; + + for (i = 0, j = 0; j < si_pi->mc_reg_table.last; j++) { + if (si_pi->mc_reg_table.valid_flag & (1 << j)) { + if (i >= SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE) + break; + mc_reg_table->address[i].s0 = + cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + cpu_to_be16(si_pi->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + mc_reg_table->last = (u8)i; +} + +static void si_convert_mc_registers(const struct si_mc_reg_entry *entry, + SMC_SIslands_MCRegisterSet *data, + u32 num_entries, u32 valid_flag) +{ + u32 i, j; + + for(i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & (1 << j)) { + data->value[i] = cpu_to_be32(entry->mc_data[j]); + i++; + } + } +} + +static void si_convert_mc_reg_table_entry_to_smc(struct amdgpu_device *adev, + struct rv7xx_pl *pl, + SMC_SIslands_MCRegisterSet *mc_reg_table_data) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 i = 0; + + for (i = 0; i < si_pi->mc_reg_table.num_entries; i++) { + if (pl->mclk <= si_pi->mc_reg_table.mc_reg_table_entry[i].mclk_max) + break; + } + + if ((i == si_pi->mc_reg_table.num_entries) && (i > 0)) + --i; + + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); +} + +static void si_convert_mc_reg_table_to_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state, + SMC_SIslands_MCRegisters *mc_reg_table) +{ + struct si_ps *state = si_get_ps(amdgpu_state); + int i; + + for (i = 0; i < state->performance_level_count; i++) { + si_convert_mc_reg_table_entry_to_smc(adev, + &state->performance_levels[i], + &mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT + i]); + } +} + +static int si_populate_mc_reg_table(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_boot_state) +{ + struct si_ps *boot_state = si_get_ps(amdgpu_boot_state); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ulv_param *ulv = &si_pi->ulv; + SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; + + memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); + + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_seq_index, 1); + + si_populate_mc_reg_addresses(adev, smc_mc_reg_table); + + si_convert_mc_reg_table_entry_to_smc(adev, &boot_state->performance_levels[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_INITIAL_SLOT]); + + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ACPI_SLOT], + si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); + + if (ulv->supported && ulv->pl.vddc != 0) + si_convert_mc_reg_table_entry_to_smc(adev, &ulv->pl, + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT]); + else + si_convert_mc_registers(&si_pi->mc_reg_table.mc_reg_table_entry[0], + &smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_ULV_SLOT], + si_pi->mc_reg_table.last, + si_pi->mc_reg_table.valid_flag); + + si_convert_mc_reg_table_to_smc(adev, amdgpu_boot_state, smc_mc_reg_table); + + return amdgpu_si_copy_bytes_to_smc(adev, si_pi->mc_reg_table_start, + (u8 *)smc_mc_reg_table, + sizeof(SMC_SIslands_MCRegisters), si_pi->sram_end); +} + +static int si_upload_mc_reg_table(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state) +{ + struct si_ps *new_state = si_get_ps(amdgpu_new_state); + struct si_power_info *si_pi = si_get_pi(adev); + u32 address = si_pi->mc_reg_table_start + + offsetof(SMC_SIslands_MCRegisters, + data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT]); + SMC_SIslands_MCRegisters *smc_mc_reg_table = &si_pi->smc_mc_reg_table; + + memset(smc_mc_reg_table, 0, sizeof(SMC_SIslands_MCRegisters)); + + si_convert_mc_reg_table_to_smc(adev, amdgpu_new_state, smc_mc_reg_table); + + return amdgpu_si_copy_bytes_to_smc(adev, address, + (u8 *)&smc_mc_reg_table->data[SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT], + sizeof(SMC_SIslands_MCRegisterSet) * new_state->performance_level_count, + si_pi->sram_end); +} + +static void si_enable_voltage_control(struct amdgpu_device *adev, bool enable) +{ + if (enable) + WREG32_P(GENERAL_PWRMGT, VOLT_PWRMGT_EN, ~VOLT_PWRMGT_EN); + else + WREG32_P(GENERAL_PWRMGT, 0, ~VOLT_PWRMGT_EN); +} + +static enum amdgpu_pcie_gen si_get_maximum_link_speed(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_state) +{ + struct si_ps *state = si_get_ps(amdgpu_state); + int i; + u16 pcie_speed, max_speed = 0; + + for (i = 0; i < state->performance_level_count; i++) { + pcie_speed = state->performance_levels[i].pcie_gen; + if (max_speed < pcie_speed) + max_speed = pcie_speed; + } + return max_speed; +} + +static u16 si_get_current_pcie_speed(struct amdgpu_device *adev) +{ + u32 speed_cntl; + + speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL) & LC_CURRENT_DATA_RATE_MASK; + speed_cntl >>= LC_CURRENT_DATA_RATE_SHIFT; + + return (u16)speed_cntl; +} + +static void si_request_link_speed_change_before_state_change(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + enum amdgpu_pcie_gen current_link_speed; + + if (si_pi->force_pcie_gen == AMDGPU_PCIE_GEN_INVALID) + current_link_speed = si_get_maximum_link_speed(adev, amdgpu_current_state); + else + current_link_speed = si_pi->force_pcie_gen; + + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->pspp_notify_required = false; + if (target_link_speed > current_link_speed) { + switch (target_link_speed) { +#if defined(CONFIG_ACPI) + case AMDGPU_PCIE_GEN3: + if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN3, false) == 0) + break; + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN2; + if (current_link_speed == AMDGPU_PCIE_GEN2) + break; + /* fall through */ + case AMDGPU_PCIE_GEN2: + if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) + break; +#endif + /* fall through */ + default: + si_pi->force_pcie_gen = si_get_current_pcie_speed(adev); + break; + } + } else { + if (target_link_speed < current_link_speed) + si_pi->pspp_notify_required = true; + } +} + +static void si_notify_link_speed_change_after_state_change(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + struct si_power_info *si_pi = si_get_pi(adev); + enum amdgpu_pcie_gen target_link_speed = si_get_maximum_link_speed(adev, amdgpu_new_state); + u8 request; + + if (si_pi->pspp_notify_required) { + if (target_link_speed == AMDGPU_PCIE_GEN3) + request = PCIE_PERF_REQ_PECI_GEN3; + else if (target_link_speed == AMDGPU_PCIE_GEN2) + request = PCIE_PERF_REQ_PECI_GEN2; + else + request = PCIE_PERF_REQ_PECI_GEN1; + + if ((request == PCIE_PERF_REQ_PECI_GEN1) && + (si_get_current_pcie_speed(adev) > 0)) + return; + +#if defined(CONFIG_ACPI) + amdgpu_acpi_pcie_performance_request(adev, request, false); +#endif + } +} + +#if 0 +static int si_ds_request(struct amdgpu_device *adev, + bool ds_status_on, u32 count_write) +{ + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + + if (eg_pi->sclk_deep_sleep) { + if (ds_status_on) + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_CancelThrottleOVRDSCLKDS) == + PPSMC_Result_OK) ? + 0 : -EINVAL; + else + return (amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_ThrottleOVRDSCLKDS) == + PPSMC_Result_OK) ? 0 : -EINVAL; + } + return 0; +} +#endif + +static void si_set_max_cu_value(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + + if (adev->asic_type == CHIP_VERDE) { + switch (adev->pdev->device) { + case 0x6820: + case 0x6825: + case 0x6821: + case 0x6823: + case 0x6827: + si_pi->max_cu = 10; + break; + case 0x682D: + case 0x6824: + case 0x682F: + case 0x6826: + si_pi->max_cu = 8; + break; + case 0x6828: + case 0x6830: + case 0x6831: + case 0x6838: + case 0x6839: + case 0x683D: + si_pi->max_cu = 10; + break; + case 0x683B: + case 0x683F: + case 0x6829: + si_pi->max_cu = 8; + break; + default: + si_pi->max_cu = 0; + break; + } + } else { + si_pi->max_cu = 0; + } +} + +static int si_patch_single_dependency_table_based_on_leakage(struct amdgpu_device *adev, + struct amdgpu_clock_voltage_dependency_table *table) +{ + u32 i; + int j; + u16 leakage_voltage; + + if (table) { + for (i = 0; i < table->count; i++) { + switch (si_get_leakage_voltage_from_leakage_index(adev, + table->entries[i].v, + &leakage_voltage)) { + case 0: + table->entries[i].v = leakage_voltage; + break; + case -EAGAIN: + return -EINVAL; + case -EINVAL: + default: + break; + } + } + + for (j = (table->count - 2); j >= 0; j--) { + table->entries[j].v = (table->entries[j].v <= table->entries[j + 1].v) ? + table->entries[j].v : table->entries[j + 1].v; + } + } + return 0; +} + +static int si_patch_dependency_tables_based_on_leakage(struct amdgpu_device *adev) +{ + int ret = 0; + + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_sclk); + if (ret) + DRM_ERROR("Could not patch vddc_on_sclk leakage table\n"); + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddc_dependency_on_mclk); + if (ret) + DRM_ERROR("Could not patch vddc_on_mclk leakage table\n"); + ret = si_patch_single_dependency_table_based_on_leakage(adev, + &adev->pm.dpm.dyn_state.vddci_dependency_on_mclk); + if (ret) + DRM_ERROR("Could not patch vddci_on_mclk leakage table\n"); + return ret; +} + +static void si_set_pcie_lane_width_in_smc(struct amdgpu_device *adev, + struct amdgpu_ps *amdgpu_new_state, + struct amdgpu_ps *amdgpu_current_state) +{ + u32 lane_width; + u32 new_lane_width = + ((amdgpu_new_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + u32 current_lane_width = + ((amdgpu_current_state->caps & ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + + if (new_lane_width != current_lane_width) { + amdgpu_set_pcie_lanes(adev, new_lane_width); + lane_width = amdgpu_get_pcie_lanes(adev); + si_write_smc_soft_register(adev, SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width, lane_width); + } +} + +static void si_dpm_setup_asic(struct amdgpu_device *adev) +{ + si_read_clock_registers(adev); + si_enable_acpi_power_management(adev); +} + +static int si_thermal_enable_alert(struct amdgpu_device *adev, + bool enable) +{ + u32 thermal_int = RREG32(CG_THERMAL_INT); + + if (enable) { + PPSMC_Result result; + + thermal_int &= ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); + WREG32(CG_THERMAL_INT, thermal_int); + result = amdgpu_si_send_msg_to_smc(adev, PPSMC_MSG_EnableThermalInterrupt); + if (result != PPSMC_Result_OK) { + DRM_DEBUG_KMS("Could not enable thermal interrupts.\n"); + return -EINVAL; + } + } else { + thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; + WREG32(CG_THERMAL_INT, thermal_int); + } + + return 0; +} + +static int si_thermal_set_temperature_range(struct amdgpu_device *adev, + int min_temp, int max_temp) +{ + int low_temp = 0 * 1000; + int high_temp = 255 * 1000; + + if (low_temp < min_temp) + low_temp = min_temp; + if (high_temp > max_temp) + high_temp = max_temp; + if (high_temp < low_temp) { + DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); + return -EINVAL; + } + + WREG32_P(CG_THERMAL_INT, DIG_THERM_INTH(high_temp / 1000), ~DIG_THERM_INTH_MASK); + WREG32_P(CG_THERMAL_INT, DIG_THERM_INTL(low_temp / 1000), ~DIG_THERM_INTL_MASK); + WREG32_P(CG_THERMAL_CTRL, DIG_THERM_DPM(high_temp / 1000), ~DIG_THERM_DPM_MASK); + + adev->pm.dpm.thermal.min_temp = low_temp; + adev->pm.dpm.thermal.max_temp = high_temp; + + return 0; +} + +static void si_fan_ctrl_set_static_mode(struct amdgpu_device *adev, u32 mode) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (si_pi->fan_ctrl_is_in_default_mode) { + tmp = (RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK) >> FDO_PWM_MODE_SHIFT; + si_pi->fan_ctrl_default_mode = tmp; + tmp = (RREG32(CG_FDO_CTRL2) & TMIN_MASK) >> TMIN_SHIFT; + si_pi->t_min = tmp; + si_pi->fan_ctrl_is_in_default_mode = false; + } + + tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; + tmp |= TMIN(0); + WREG32(CG_FDO_CTRL2, tmp); + + tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; + tmp |= FDO_PWM_MODE(mode); + WREG32(CG_FDO_CTRL2, tmp); +} + +static int si_thermal_setup_fan_table(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PP_SIslands_FanTable fan_table = { FDO_MODE_HARDWARE }; + u32 duty100; + u32 t_diff1, t_diff2, pwm_diff1, pwm_diff2; + u16 fdo_min, slope1, slope2; + u32 reference_clock, tmp; + int ret; + u64 tmp64; + + if (!si_pi->fan_table_start) { + adev->pm.dpm.fan.ucode_fan_control = false; + return 0; + } + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + + if (duty100 == 0) { + adev->pm.dpm.fan.ucode_fan_control = false; + return 0; + } + + tmp64 = (u64)adev->pm.dpm.fan.pwm_min * duty100; + do_div(tmp64, 10000); + fdo_min = (u16)tmp64; + + t_diff1 = adev->pm.dpm.fan.t_med - adev->pm.dpm.fan.t_min; + t_diff2 = adev->pm.dpm.fan.t_high - adev->pm.dpm.fan.t_med; + + pwm_diff1 = adev->pm.dpm.fan.pwm_med - adev->pm.dpm.fan.pwm_min; + pwm_diff2 = adev->pm.dpm.fan.pwm_high - adev->pm.dpm.fan.pwm_med; + + slope1 = (u16)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (u16)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.temp_min = cpu_to_be16((50 + adev->pm.dpm.fan.t_min) / 100); + fan_table.temp_med = cpu_to_be16((50 + adev->pm.dpm.fan.t_med) / 100); + fan_table.temp_max = cpu_to_be16((50 + adev->pm.dpm.fan.t_max) / 100); + fan_table.slope1 = cpu_to_be16(slope1); + fan_table.slope2 = cpu_to_be16(slope2); + fan_table.fdo_min = cpu_to_be16(fdo_min); + fan_table.hys_down = cpu_to_be16(adev->pm.dpm.fan.t_hyst); + fan_table.hys_up = cpu_to_be16(1); + fan_table.hys_slope = cpu_to_be16(1); + fan_table.temp_resp_lim = cpu_to_be16(5); + reference_clock = amdgpu_asic_get_xclk(adev); + + fan_table.refresh_period = cpu_to_be32((adev->pm.dpm.fan.cycle_delay * + reference_clock) / 1600); + fan_table.fdo_max = cpu_to_be16((u16)duty100); + + tmp = (RREG32(CG_MULT_THERMAL_CTRL) & TEMP_SEL_MASK) >> TEMP_SEL_SHIFT; + fan_table.temp_src = (uint8_t)tmp; + + ret = amdgpu_si_copy_bytes_to_smc(adev, + si_pi->fan_table_start, + (u8 *)(&fan_table), + sizeof(fan_table), + si_pi->sram_end); + + if (ret) { + DRM_ERROR("Failed to load fan table to the SMC."); + adev->pm.dpm.fan.ucode_fan_control = false; + } + + return ret; +} + +static int si_fan_ctrl_start_smc_fan_control(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result ret; + + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StartFanControl); + if (ret == PPSMC_Result_OK) { + si_pi->fan_is_controlled_by_smc = true; + return 0; + } else { + return -EINVAL; + } +} + +static int si_fan_ctrl_stop_smc_fan_control(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + PPSMC_Result ret; + + ret = amdgpu_si_send_msg_to_smc(adev, PPSMC_StopFanControl); + + if (ret == PPSMC_Result_OK) { + si_pi->fan_is_controlled_by_smc = false; + return 0; + } else { + return -EINVAL; + } +} + +static int si_dpm_get_fan_speed_percent(void *handle, + u32 *speed) +{ + u32 duty, duty100; + u64 tmp64; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.no_fan) + return -ENOENT; + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + duty = (RREG32(CG_THERMAL_STATUS) & FDO_PWM_DUTY_MASK) >> FDO_PWM_DUTY_SHIFT; + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (u64)duty * 100; + do_div(tmp64, duty100); + *speed = (u32)tmp64; + + if (*speed > 100) + *speed = 100; + + return 0; +} + +static int si_dpm_set_fan_speed_percent(void *handle, + u32 speed) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + u32 duty, duty100; + u64 tmp64; + + if (adev->pm.no_fan) + return -ENOENT; + + if (si_pi->fan_is_controlled_by_smc) + return -EINVAL; + + if (speed > 100) + return -EINVAL; + + duty100 = (RREG32(CG_FDO_CTRL1) & FMAX_DUTY100_MASK) >> FMAX_DUTY100_SHIFT; + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (u64)speed * duty100; + do_div(tmp64, 100); + duty = (u32)tmp64; + + tmp = RREG32(CG_FDO_CTRL0) & ~FDO_STATIC_DUTY_MASK; + tmp |= FDO_STATIC_DUTY(duty); + WREG32(CG_FDO_CTRL0, tmp); + + return 0; +} + +static void si_dpm_set_fan_control_mode(void *handle, u32 mode) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (mode) { + /* stop auto-manage */ + if (adev->pm.dpm.fan.ucode_fan_control) + si_fan_ctrl_stop_smc_fan_control(adev); + si_fan_ctrl_set_static_mode(adev, mode); + } else { + /* restart auto-manage */ + if (adev->pm.dpm.fan.ucode_fan_control) + si_thermal_start_smc_fan_control(adev); + else + si_fan_ctrl_set_default_mode(adev); + } +} + +static u32 si_dpm_get_fan_control_mode(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (si_pi->fan_is_controlled_by_smc) + return 0; + + tmp = RREG32(CG_FDO_CTRL2) & FDO_PWM_MODE_MASK; + return (tmp >> FDO_PWM_MODE_SHIFT); +} + +#if 0 +static int si_fan_ctrl_get_fan_speed_rpm(struct amdgpu_device *adev, + u32 *speed) +{ + u32 tach_period; + u32 xclk = amdgpu_asic_get_xclk(adev); + + if (adev->pm.no_fan) + return -ENOENT; + + if (adev->pm.fan_pulses_per_revolution == 0) + return -ENOENT; + + tach_period = (RREG32(CG_TACH_STATUS) & TACH_PERIOD_MASK) >> TACH_PERIOD_SHIFT; + if (tach_period == 0) + return -ENOENT; + + *speed = 60 * xclk * 10000 / tach_period; + + return 0; +} + +static int si_fan_ctrl_set_fan_speed_rpm(struct amdgpu_device *adev, + u32 speed) +{ + u32 tach_period, tmp; + u32 xclk = amdgpu_asic_get_xclk(adev); + + if (adev->pm.no_fan) + return -ENOENT; + + if (adev->pm.fan_pulses_per_revolution == 0) + return -ENOENT; + + if ((speed < adev->pm.fan_min_rpm) || + (speed > adev->pm.fan_max_rpm)) + return -EINVAL; + + if (adev->pm.dpm.fan.ucode_fan_control) + si_fan_ctrl_stop_smc_fan_control(adev); + + tach_period = 60 * xclk * 10000 / (8 * speed); + tmp = RREG32(CG_TACH_CTRL) & ~TARGET_PERIOD_MASK; + tmp |= TARGET_PERIOD(tach_period); + WREG32(CG_TACH_CTRL, tmp); + + si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC_RPM); + + return 0; +} +#endif + +static void si_fan_ctrl_set_default_mode(struct amdgpu_device *adev) +{ + struct si_power_info *si_pi = si_get_pi(adev); + u32 tmp; + + if (!si_pi->fan_ctrl_is_in_default_mode) { + tmp = RREG32(CG_FDO_CTRL2) & ~FDO_PWM_MODE_MASK; + tmp |= FDO_PWM_MODE(si_pi->fan_ctrl_default_mode); + WREG32(CG_FDO_CTRL2, tmp); + + tmp = RREG32(CG_FDO_CTRL2) & ~TMIN_MASK; + tmp |= TMIN(si_pi->t_min); + WREG32(CG_FDO_CTRL2, tmp); + si_pi->fan_ctrl_is_in_default_mode = true; + } +} + +static void si_thermal_start_smc_fan_control(struct amdgpu_device *adev) +{ + if (adev->pm.dpm.fan.ucode_fan_control) { + si_fan_ctrl_start_smc_fan_control(adev); + si_fan_ctrl_set_static_mode(adev, FDO_PWM_MODE_STATIC); + } +} + +static void si_thermal_initialize(struct amdgpu_device *adev) +{ + u32 tmp; + + if (adev->pm.fan_pulses_per_revolution) { + tmp = RREG32(CG_TACH_CTRL) & ~EDGE_PER_REV_MASK; + tmp |= EDGE_PER_REV(adev->pm.fan_pulses_per_revolution -1); + WREG32(CG_TACH_CTRL, tmp); + } + + tmp = RREG32(CG_FDO_CTRL2) & ~TACH_PWM_RESP_RATE_MASK; + tmp |= TACH_PWM_RESP_RATE(0x28); + WREG32(CG_FDO_CTRL2, tmp); +} + +static int si_thermal_start_thermal_controller(struct amdgpu_device *adev) +{ + int ret; + + si_thermal_initialize(adev); + ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = si_thermal_enable_alert(adev, true); + if (ret) + return ret; + if (adev->pm.dpm.fan.ucode_fan_control) { + ret = si_halt_smc(adev); + if (ret) + return ret; + ret = si_thermal_setup_fan_table(adev); + if (ret) + return ret; + ret = si_resume_smc(adev); + if (ret) + return ret; + si_thermal_start_smc_fan_control(adev); + } + + return 0; +} + +static void si_thermal_stop_thermal_controller(struct amdgpu_device *adev) +{ + if (!adev->pm.no_fan) { + si_fan_ctrl_set_default_mode(adev); + si_fan_ctrl_stop_smc_fan_control(adev); + } +} + +static int si_dpm_enable(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; + int ret; + + if (amdgpu_si_is_smc_running(adev)) + return -EINVAL; + if (pi->voltage_control || si_pi->voltage_control_svi2) + si_enable_voltage_control(adev, true); + if (pi->mvdd_control) + si_get_mvdd_configuration(adev); + if (pi->voltage_control || si_pi->voltage_control_svi2) { + ret = si_construct_voltage_tables(adev); + if (ret) { + DRM_ERROR("si_construct_voltage_tables failed\n"); + return ret; + } + } + if (eg_pi->dynamic_ac_timing) { + ret = si_initialize_mc_reg_table(adev); + if (ret) + eg_pi->dynamic_ac_timing = false; + } + if (pi->dynamic_ss) + si_enable_spread_spectrum(adev, true); + if (pi->thermal_protection) + si_enable_thermal_protection(adev, true); + si_setup_bsp(adev); + si_program_git(adev); + si_program_tp(adev); + si_program_tpp(adev); + si_program_sstp(adev); + si_enable_display_gap(adev); + si_program_vc(adev); + ret = si_upload_firmware(adev); + if (ret) { + DRM_ERROR("si_upload_firmware failed\n"); + return ret; + } + ret = si_process_firmware_header(adev); + if (ret) { + DRM_ERROR("si_process_firmware_header failed\n"); + return ret; + } + ret = si_initial_switch_from_arb_f0_to_f1(adev); + if (ret) { + DRM_ERROR("si_initial_switch_from_arb_f0_to_f1 failed\n"); + return ret; + } + ret = si_init_smc_table(adev); + if (ret) { + DRM_ERROR("si_init_smc_table failed\n"); + return ret; + } + ret = si_init_smc_spll_table(adev); + if (ret) { + DRM_ERROR("si_init_smc_spll_table failed\n"); + return ret; + } + ret = si_init_arb_table_index(adev); + if (ret) { + DRM_ERROR("si_init_arb_table_index failed\n"); + return ret; + } + if (eg_pi->dynamic_ac_timing) { + ret = si_populate_mc_reg_table(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_mc_reg_table failed\n"); + return ret; + } + } + ret = si_initialize_smc_cac_tables(adev); + if (ret) { + DRM_ERROR("si_initialize_smc_cac_tables failed\n"); + return ret; + } + ret = si_initialize_hardware_cac_manager(adev); + if (ret) { + DRM_ERROR("si_initialize_hardware_cac_manager failed\n"); + return ret; + } + ret = si_initialize_smc_dte_tables(adev); + if (ret) { + DRM_ERROR("si_initialize_smc_dte_tables failed\n"); + return ret; + } + ret = si_populate_smc_tdp_limits(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_smc_tdp_limits failed\n"); + return ret; + } + ret = si_populate_smc_tdp_limits_2(adev, boot_ps); + if (ret) { + DRM_ERROR("si_populate_smc_tdp_limits_2 failed\n"); + return ret; + } + si_program_response_times(adev); + si_program_ds_registers(adev); + si_dpm_start_smc(adev); + ret = si_notify_smc_display_change(adev, false); + if (ret) { + DRM_ERROR("si_notify_smc_display_change failed\n"); + return ret; + } + si_enable_sclk_control(adev, true); + si_start_dpm(adev); + + si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, true); + si_thermal_start_thermal_controller(adev); + + return 0; +} + +static int si_set_temperature_range(struct amdgpu_device *adev) +{ + int ret; + + ret = si_thermal_enable_alert(adev, false); + if (ret) + return ret; + ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); + if (ret) + return ret; + ret = si_thermal_enable_alert(adev, true); + if (ret) + return ret; + + return ret; +} + +static void si_dpm_disable(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct amdgpu_ps *boot_ps = adev->pm.dpm.boot_ps; + + if (!amdgpu_si_is_smc_running(adev)) + return; + si_thermal_stop_thermal_controller(adev); + si_disable_ulv(adev); + si_clear_vc(adev); + if (pi->thermal_protection) + si_enable_thermal_protection(adev, false); + si_enable_power_containment(adev, boot_ps, false); + si_enable_smc_cac(adev, boot_ps, false); + si_enable_spread_spectrum(adev, false); + si_enable_auto_throttle_source(adev, AMDGPU_DPM_AUTO_THROTTLE_SRC_THERMAL, false); + si_stop_dpm(adev); + si_reset_to_default(adev); + si_dpm_stop_smc(adev); + si_force_switch_to_arb_f0(adev); + + ni_update_current_ps(adev, boot_ps); +} + +static int si_dpm_pre_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps requested_ps = *adev->pm.dpm.requested_ps; + struct amdgpu_ps *new_ps = &requested_ps; + + ni_update_requested_ps(adev, new_ps); + si_apply_state_adjust_rules(adev, &eg_pi->requested_rps); + + return 0; +} + +static int si_power_control_set_level(struct amdgpu_device *adev) +{ + struct amdgpu_ps *new_ps = adev->pm.dpm.requested_ps; + int ret; + + ret = si_restrict_performance_levels_before_switch(adev); + if (ret) + return ret; + ret = si_halt_smc(adev); + if (ret) + return ret; + ret = si_populate_smc_tdp_limits(adev, new_ps); + if (ret) + return ret; + ret = si_populate_smc_tdp_limits_2(adev, new_ps); + if (ret) + return ret; + ret = si_resume_smc(adev); + if (ret) + return ret; + ret = si_set_sw_state(adev); + if (ret) + return ret; + return 0; +} + +static void si_set_vce_clock(struct amdgpu_device *adev, + struct amdgpu_ps *new_rps, + struct amdgpu_ps *old_rps) +{ + if ((old_rps->evclk != new_rps->evclk) || + (old_rps->ecclk != new_rps->ecclk)) { + /* Turn the clocks on when encoding, off otherwise */ + if (new_rps->evclk || new_rps->ecclk) { + /* Place holder for future VCE1.0 porting to amdgpu + vce_v1_0_enable_mgcg(adev, false, false);*/ + } else { + /* Place holder for future VCE1.0 porting to amdgpu + vce_v1_0_enable_mgcg(adev, true, false); + amdgpu_asic_set_vce_clocks(adev, new_rps->evclk, new_rps->ecclk);*/ + } + } +} + +static int si_dpm_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *new_ps = &eg_pi->requested_rps; + struct amdgpu_ps *old_ps = &eg_pi->current_rps; + int ret; + + ret = si_disable_ulv(adev); + if (ret) { + DRM_ERROR("si_disable_ulv failed\n"); + return ret; + } + ret = si_restrict_performance_levels_before_switch(adev); + if (ret) { + DRM_ERROR("si_restrict_performance_levels_before_switch failed\n"); + return ret; + } + if (eg_pi->pcie_performance_request) + si_request_link_speed_change_before_state_change(adev, new_ps, old_ps); + ni_set_uvd_clock_before_set_eng_clock(adev, new_ps, old_ps); + ret = si_enable_power_containment(adev, new_ps, false); + if (ret) { + DRM_ERROR("si_enable_power_containment failed\n"); + return ret; + } + ret = si_enable_smc_cac(adev, new_ps, false); + if (ret) { + DRM_ERROR("si_enable_smc_cac failed\n"); + return ret; + } + ret = si_halt_smc(adev); + if (ret) { + DRM_ERROR("si_halt_smc failed\n"); + return ret; + } + ret = si_upload_sw_state(adev, new_ps); + if (ret) { + DRM_ERROR("si_upload_sw_state failed\n"); + return ret; + } + ret = si_upload_smc_data(adev); + if (ret) { + DRM_ERROR("si_upload_smc_data failed\n"); + return ret; + } + ret = si_upload_ulv_state(adev); + if (ret) { + DRM_ERROR("si_upload_ulv_state failed\n"); + return ret; + } + if (eg_pi->dynamic_ac_timing) { + ret = si_upload_mc_reg_table(adev, new_ps); + if (ret) { + DRM_ERROR("si_upload_mc_reg_table failed\n"); + return ret; + } + } + ret = si_program_memory_timing_parameters(adev, new_ps); + if (ret) { + DRM_ERROR("si_program_memory_timing_parameters failed\n"); + return ret; + } + si_set_pcie_lane_width_in_smc(adev, new_ps, old_ps); + + ret = si_resume_smc(adev); + if (ret) { + DRM_ERROR("si_resume_smc failed\n"); + return ret; + } + ret = si_set_sw_state(adev); + if (ret) { + DRM_ERROR("si_set_sw_state failed\n"); + return ret; + } + ni_set_uvd_clock_after_set_eng_clock(adev, new_ps, old_ps); + si_set_vce_clock(adev, new_ps, old_ps); + if (eg_pi->pcie_performance_request) + si_notify_link_speed_change_after_state_change(adev, new_ps, old_ps); + ret = si_set_power_state_conditionally_enable_ulv(adev, new_ps); + if (ret) { + DRM_ERROR("si_set_power_state_conditionally_enable_ulv failed\n"); + return ret; + } + ret = si_enable_smc_cac(adev, new_ps, true); + if (ret) { + DRM_ERROR("si_enable_smc_cac failed\n"); + return ret; + } + ret = si_enable_power_containment(adev, new_ps, true); + if (ret) { + DRM_ERROR("si_enable_power_containment failed\n"); + return ret; + } + + ret = si_power_control_set_level(adev); + if (ret) { + DRM_ERROR("si_power_control_set_level failed\n"); + return ret; + } + + return 0; +} + +static void si_dpm_post_set_power_state(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *new_ps = &eg_pi->requested_rps; + + ni_update_current_ps(adev, new_ps); +} + +#if 0 +void si_dpm_reset_asic(struct amdgpu_device *adev) +{ + si_restrict_performance_levels_before_switch(adev); + si_disable_ulv(adev); + si_set_boot_state(adev); +} +#endif + +static void si_dpm_display_configuration_changed(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + si_program_display_gap(adev); +} + + +static void si_parse_pplib_non_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, + u8 table_rev) +{ + rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); + rps->class = le16_to_cpu(non_clock_info->usClassification); + rps->class2 = le16_to_cpu(non_clock_info->usClassification2); + + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { + rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); + rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); + } else if (r600_is_uvd_state(rps->class, rps->class2)) { + rps->vclk = RV770_DEFAULT_VCLK_FREQ; + rps->dclk = RV770_DEFAULT_DCLK_FREQ; + } else { + rps->vclk = 0; + rps->dclk = 0; + } + + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) + adev->pm.dpm.boot_ps = rps; + if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + adev->pm.dpm.uvd_ps = rps; +} + +static void si_parse_pplib_clock_info(struct amdgpu_device *adev, + struct amdgpu_ps *rps, int index, + union pplib_clock_info *clock_info) +{ + struct rv7xx_power_info *pi = rv770_get_pi(adev); + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_power_info *si_pi = si_get_pi(adev); + struct si_ps *ps = si_get_ps(rps); + u16 leakage_voltage; + struct rv7xx_pl *pl = &ps->performance_levels[index]; + int ret; + + ps->performance_level_count = index + 1; + + pl->sclk = le16_to_cpu(clock_info->si.usEngineClockLow); + pl->sclk |= clock_info->si.ucEngineClockHigh << 16; + pl->mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); + pl->mclk |= clock_info->si.ucMemoryClockHigh << 16; + + pl->vddc = le16_to_cpu(clock_info->si.usVDDC); + pl->vddci = le16_to_cpu(clock_info->si.usVDDCI); + pl->flags = le32_to_cpu(clock_info->si.ulFlags); + pl->pcie_gen = amdgpu_get_pcie_gen_support(adev, + si_pi->sys_pcie_mask, + si_pi->boot_pcie_gen, + clock_info->si.ucPCIEGen); + + /* patch up vddc if necessary */ + ret = si_get_leakage_voltage_from_leakage_index(adev, pl->vddc, + &leakage_voltage); + if (ret == 0) + pl->vddc = leakage_voltage; + + if (rps->class & ATOM_PPLIB_CLASSIFICATION_ACPI) { + pi->acpi_vddc = pl->vddc; + eg_pi->acpi_vddci = pl->vddci; + si_pi->acpi_pcie_gen = pl->pcie_gen; + } + + if ((rps->class2 & ATOM_PPLIB_CLASSIFICATION2_ULV) && + index == 0) { + /* XXX disable for A0 tahiti */ + si_pi->ulv.supported = false; + si_pi->ulv.pl = *pl; + si_pi->ulv.one_pcie_lane_in_ulv = false; + si_pi->ulv.volt_change_delay = SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT; + si_pi->ulv.cg_ulv_parameter = SISLANDS_CGULVPARAMETER_DFLT; + si_pi->ulv.cg_ulv_control = SISLANDS_CGULVCONTROL_DFLT; + } + + if (pi->min_vddc_in_table > pl->vddc) + pi->min_vddc_in_table = pl->vddc; + + if (pi->max_vddc_in_table < pl->vddc) + pi->max_vddc_in_table = pl->vddc; + + /* patch up boot state */ + if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { + u16 vddc, vddci, mvdd; + amdgpu_atombios_get_default_voltages(adev, &vddc, &vddci, &mvdd); + pl->mclk = adev->clock.default_mclk; + pl->sclk = adev->clock.default_sclk; + pl->vddc = vddc; + pl->vddci = vddci; + si_pi->mvdd_bootup_value = mvdd; + } + + if ((rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == + ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE) { + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk = pl->sclk; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk = pl->mclk; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddc = pl->vddc; + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.vddci = pl->vddci; + } +} + +union pplib_power_state { + struct _ATOM_PPLIB_STATE v1; + struct _ATOM_PPLIB_STATE_V2 v2; +}; + +static int si_parse_power_table(struct amdgpu_device *adev) +{ + struct amdgpu_mode_info *mode_info = &adev->mode_info; + struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; + union pplib_power_state *power_state; + int i, j, k, non_clock_array_index, clock_array_index; + union pplib_clock_info *clock_info; + struct _StateArray *state_array; + struct _ClockInfoArray *clock_info_array; + struct _NonClockInfoArray *non_clock_info_array; + union power_info *power_info; + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + u16 data_offset; + u8 frev, crev; + u8 *power_state_offset; + struct si_ps *ps; + + if (!amdgpu_atom_parse_data_header(mode_info->atom_context, index, NULL, + &frev, &crev, &data_offset)) + return -EINVAL; + power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); + + amdgpu_add_thermal_controller(adev); + + state_array = (struct _StateArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usStateArrayOffset)); + clock_info_array = (struct _ClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); + non_clock_info_array = (struct _NonClockInfoArray *) + (mode_info->atom_context->bios + data_offset + + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + + adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, + sizeof(struct amdgpu_ps), + GFP_KERNEL); + if (!adev->pm.dpm.ps) + return -ENOMEM; + power_state_offset = (u8 *)state_array->states; + for (i = 0; i < state_array->ucNumEntries; i++) { + u8 *idx; + power_state = (union pplib_power_state *)power_state_offset; + non_clock_array_index = power_state->v2.nonClockInfoIndex; + non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) + &non_clock_info_array->nonClockInfo[non_clock_array_index]; + ps = kzalloc(sizeof(struct si_ps), GFP_KERNEL); + if (ps == NULL) { + kfree(adev->pm.dpm.ps); + return -ENOMEM; + } + adev->pm.dpm.ps[i].ps_priv = ps; + si_parse_pplib_non_clock_info(adev, &adev->pm.dpm.ps[i], + non_clock_info, + non_clock_info_array->ucEntrySize); + k = 0; + idx = (u8 *)&power_state->v2.clockInfoIndex[0]; + for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { + clock_array_index = idx[j]; + if (clock_array_index >= clock_info_array->ucNumEntries) + continue; + if (k >= SISLANDS_MAX_HARDWARE_POWERLEVELS) + break; + clock_info = (union pplib_clock_info *) + ((u8 *)&clock_info_array->clockInfo[0] + + (clock_array_index * clock_info_array->ucEntrySize)); + si_parse_pplib_clock_info(adev, + &adev->pm.dpm.ps[i], k, + clock_info); + k++; + } + power_state_offset += 2 + power_state->v2.ucNumDPMLevels; + } + adev->pm.dpm.num_ps = state_array->ucNumEntries; + + /* fill in the vce power states */ + for (i = 0; i < adev->pm.dpm.num_of_vce_states; i++) { + u32 sclk, mclk; + clock_array_index = adev->pm.dpm.vce_states[i].clk_idx; + clock_info = (union pplib_clock_info *) + &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; + sclk = le16_to_cpu(clock_info->si.usEngineClockLow); + sclk |= clock_info->si.ucEngineClockHigh << 16; + mclk = le16_to_cpu(clock_info->si.usMemoryClockLow); + mclk |= clock_info->si.ucMemoryClockHigh << 16; + adev->pm.dpm.vce_states[i].sclk = sclk; + adev->pm.dpm.vce_states[i].mclk = mclk; + } + + return 0; +} + +static int si_dpm_init(struct amdgpu_device *adev) +{ + struct rv7xx_power_info *pi; + struct evergreen_power_info *eg_pi; + struct ni_power_info *ni_pi; + struct si_power_info *si_pi; + struct atom_clock_dividers dividers; + int ret; + + si_pi = kzalloc(sizeof(struct si_power_info), GFP_KERNEL); + if (si_pi == NULL) + return -ENOMEM; + adev->pm.dpm.priv = si_pi; + ni_pi = &si_pi->ni; + eg_pi = &ni_pi->eg; + pi = &eg_pi->rv7xx; + + si_pi->sys_pcie_mask = + adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_MASK; + si_pi->force_pcie_gen = AMDGPU_PCIE_GEN_INVALID; + si_pi->boot_pcie_gen = si_get_current_pcie_speed(adev); + + si_set_max_cu_value(adev); + + rv770_get_max_vddc(adev); + si_get_leakage_vddc(adev); + si_patch_dependency_tables_based_on_leakage(adev); + + pi->acpi_vddc = 0; + eg_pi->acpi_vddci = 0; + pi->min_vddc_in_table = 0; + pi->max_vddc_in_table = 0; + + ret = amdgpu_get_platform_caps(adev); + if (ret) + return ret; + + ret = amdgpu_parse_extended_power_table(adev); + if (ret) + return ret; + + ret = si_parse_power_table(adev); + if (ret) + return ret; + + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries = + kcalloc(4, + sizeof(struct amdgpu_clock_voltage_dependency_entry), + GFP_KERNEL); + if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) { + amdgpu_free_extended_power_table(adev); + return -ENOMEM; + } + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.count = 4; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].clk = 0; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[0].v = 0; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].clk = 36000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[1].v = 720; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].clk = 54000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[2].v = 810; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].clk = 72000; + adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries[3].v = 900; + + if (adev->pm.dpm.voltage_response_time == 0) + adev->pm.dpm.voltage_response_time = R600_VOLTAGERESPONSETIME_DFLT; + if (adev->pm.dpm.backbias_response_time == 0) + adev->pm.dpm.backbias_response_time = R600_BACKBIASRESPONSETIME_DFLT; + + ret = amdgpu_atombios_get_clock_dividers(adev, COMPUTE_ENGINE_PLL_PARAM, + 0, false, ÷rs); + if (ret) + pi->ref_div = dividers.ref_div + 1; + else + pi->ref_div = R600_REFERENCEDIVIDER_DFLT; + + eg_pi->smu_uvd_hs = false; + + pi->mclk_strobe_mode_threshold = 40000; + if (si_is_special_1gb_platform(adev)) + pi->mclk_stutter_mode_threshold = 0; + else + pi->mclk_stutter_mode_threshold = pi->mclk_strobe_mode_threshold; + pi->mclk_edc_enable_threshold = 40000; + eg_pi->mclk_edc_wr_enable_threshold = 40000; + + ni_pi->mclk_rtt_mode_threshold = eg_pi->mclk_edc_wr_enable_threshold; + + pi->voltage_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_GPIO_LUT); + if (!pi->voltage_control) { + si_pi->voltage_control_svi2 = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_SVID2); + if (si_pi->voltage_control_svi2) + amdgpu_atombios_get_svi2_info(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + &si_pi->svd_gpio_id, &si_pi->svc_gpio_id); + } + + pi->mvdd_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_MVDDC, + VOLTAGE_OBJ_GPIO_LUT); + + eg_pi->vddci_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, + VOLTAGE_OBJ_GPIO_LUT); + if (!eg_pi->vddci_control) + si_pi->vddci_control_svi2 = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDCI, + VOLTAGE_OBJ_SVID2); + + si_pi->vddc_phase_shed_control = + amdgpu_atombios_is_voltage_gpio(adev, SET_VOLTAGE_TYPE_ASIC_VDDC, + VOLTAGE_OBJ_PHASE_LUT); + + rv770_get_engine_memory_ss(adev); + + pi->asi = RV770_ASI_DFLT; + pi->pasi = CYPRESS_HASI_DFLT; + pi->vrc = SISLANDS_VRC_DFLT; + + pi->gfx_clock_gating = true; + + eg_pi->sclk_deep_sleep = true; + si_pi->sclk_deep_sleep_above_low = false; + + if (adev->pm.int_thermal_type != THERMAL_TYPE_NONE) + pi->thermal_protection = true; + else + pi->thermal_protection = false; + + eg_pi->dynamic_ac_timing = true; + + eg_pi->light_sleep = true; +#if defined(CONFIG_ACPI) + eg_pi->pcie_performance_request = + amdgpu_acpi_is_pcie_performance_request_supported(adev); +#else + eg_pi->pcie_performance_request = false; +#endif + + si_pi->sram_end = SMC_RAM_END; + + adev->pm.dpm.dyn_state.mclk_sclk_ratio = 4; + adev->pm.dpm.dyn_state.sclk_mclk_delta = 15000; + adev->pm.dpm.dyn_state.vddc_vddci_delta = 200; + adev->pm.dpm.dyn_state.valid_sclk_values.count = 0; + adev->pm.dpm.dyn_state.valid_sclk_values.values = NULL; + adev->pm.dpm.dyn_state.valid_mclk_values.count = 0; + adev->pm.dpm.dyn_state.valid_mclk_values.values = NULL; + + si_initialize_powertune_defaults(adev); + + /* make sure dc limits are valid */ + if ((adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.sclk == 0) || + (adev->pm.dpm.dyn_state.max_clock_voltage_on_dc.mclk == 0)) + adev->pm.dpm.dyn_state.max_clock_voltage_on_dc = + adev->pm.dpm.dyn_state.max_clock_voltage_on_ac; + + si_pi->fan_ctrl_is_in_default_mode = true; + + return 0; +} + +static void si_dpm_fini(struct amdgpu_device *adev) +{ + int i; + + if (adev->pm.dpm.ps) + for (i = 0; i < adev->pm.dpm.num_ps; i++) + kfree(adev->pm.dpm.ps[i].ps_priv); + kfree(adev->pm.dpm.ps); + kfree(adev->pm.dpm.priv); + kfree(adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries); + amdgpu_free_extended_power_table(adev); +} + +static void si_dpm_debugfs_print_current_performance_level(void *handle, + struct seq_file *m) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *rps = &eg_pi->current_rps; + struct si_ps *ps = si_get_ps(rps); + struct rv7xx_pl *pl; + u32 current_index = + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> + CURRENT_STATE_INDEX_SHIFT; + + if (current_index >= ps->performance_level_count) { + seq_printf(m, "invalid dpm profile %d\n", current_index); + } else { + pl = &ps->performance_levels[current_index]; + seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + seq_printf(m, "power level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + current_index, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); + } +} + +static int si_dpm_set_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned type, + enum amdgpu_interrupt_state state) +{ + u32 cg_thermal_int; + + switch (type) { + case AMDGPU_THERMAL_IRQ_LOW_TO_HIGH: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int |= THERM_INT_MASK_HIGH; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int &= ~THERM_INT_MASK_HIGH; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + default: + break; + } + break; + + case AMDGPU_THERMAL_IRQ_HIGH_TO_LOW: + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int |= THERM_INT_MASK_LOW; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + case AMDGPU_IRQ_STATE_ENABLE: + cg_thermal_int = RREG32_SMC(CG_THERMAL_INT); + cg_thermal_int &= ~THERM_INT_MASK_LOW; + WREG32_SMC(CG_THERMAL_INT, cg_thermal_int); + break; + default: + break; + } + break; + + default: + break; + } + return 0; +} + +static int si_dpm_process_interrupt(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + bool queue_thermal = false; + + if (entry == NULL) + return -EINVAL; + + switch (entry->src_id) { + case 230: /* thermal low to high */ + DRM_DEBUG("IH: thermal low to high\n"); + adev->pm.dpm.thermal.high_to_low = false; + queue_thermal = true; + break; + case 231: /* thermal high to low */ + DRM_DEBUG("IH: thermal high to low\n"); + adev->pm.dpm.thermal.high_to_low = true; + queue_thermal = true; + break; + default: + break; + } + + if (queue_thermal) + schedule_work(&adev->pm.dpm.thermal.work); + + return 0; +} + +static int si_dpm_late_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!adev->pm.dpm_enabled) + return 0; + + ret = si_set_temperature_range(adev); + if (ret) + return ret; +#if 0 //TODO ? + si_dpm_powergate_uvd(adev, true); +#endif + return 0; +} + +/** + * si_dpm_init_microcode - load ucode images from disk + * + * @adev: amdgpu_device pointer + * + * Use the firmware interface to load the ucode images into + * the driver (not loaded into hw). + * Returns 0 on success, error on failure. + */ +static int si_dpm_init_microcode(struct amdgpu_device *adev) +{ + const char *chip_name; + char fw_name[30]; + int err; + + DRM_DEBUG("\n"); + switch (adev->asic_type) { + case CHIP_TAHITI: + chip_name = "tahiti"; + break; + case CHIP_PITCAIRN: + if ((adev->pdev->revision == 0x81) && + ((adev->pdev->device == 0x6810) || + (adev->pdev->device == 0x6811))) + chip_name = "pitcairn_k"; + else + chip_name = "pitcairn"; + break; + case CHIP_VERDE: + if (((adev->pdev->device == 0x6820) && + ((adev->pdev->revision == 0x81) || + (adev->pdev->revision == 0x83))) || + ((adev->pdev->device == 0x6821) && + ((adev->pdev->revision == 0x83) || + (adev->pdev->revision == 0x87))) || + ((adev->pdev->revision == 0x87) && + ((adev->pdev->device == 0x6823) || + (adev->pdev->device == 0x682b)))) + chip_name = "verde_k"; + else + chip_name = "verde"; + break; + case CHIP_OLAND: + if (((adev->pdev->revision == 0x81) && + ((adev->pdev->device == 0x6600) || + (adev->pdev->device == 0x6604) || + (adev->pdev->device == 0x6605) || + (adev->pdev->device == 0x6610))) || + ((adev->pdev->revision == 0x83) && + (adev->pdev->device == 0x6610))) + chip_name = "oland_k"; + else + chip_name = "oland"; + break; + case CHIP_HAINAN: + if (((adev->pdev->revision == 0x81) && + (adev->pdev->device == 0x6660)) || + ((adev->pdev->revision == 0x83) && + ((adev->pdev->device == 0x6660) || + (adev->pdev->device == 0x6663) || + (adev->pdev->device == 0x6665) || + (adev->pdev->device == 0x6667)))) + chip_name = "hainan_k"; + else if ((adev->pdev->revision == 0xc3) && + (adev->pdev->device == 0x6665)) + chip_name = "banks_k_2"; + else + chip_name = "hainan"; + break; + default: BUG(); + } + + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); + err = request_firmware(&adev->pm.fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->pm.fw); + +out: + if (err) { + DRM_ERROR("si_smc: Failed to load firmware. err = %d\"%s\"\n", + err, fw_name); + release_firmware(adev->pm.fw); + adev->pm.fw = NULL; + } + return err; + +} + +static int si_dpm_sw_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 230, &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 231, &adev->pm.dpm.thermal.irq); + if (ret) + return ret; + + /* default to balanced state */ + adev->pm.dpm.state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + adev->pm.dpm.forced_level = AMD_DPM_FORCED_LEVEL_AUTO; + adev->pm.default_sclk = adev->clock.default_sclk; + adev->pm.default_mclk = adev->clock.default_mclk; + adev->pm.current_sclk = adev->clock.default_sclk; + adev->pm.current_mclk = adev->clock.default_mclk; + adev->pm.int_thermal_type = THERMAL_TYPE_NONE; + + if (amdgpu_dpm == 0) + return 0; + + ret = si_dpm_init_microcode(adev); + if (ret) + return ret; + + INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); + mutex_lock(&adev->pm.mutex); + ret = si_dpm_init(adev); + if (ret) + goto dpm_failed; + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + if (amdgpu_dpm == 1) + amdgpu_pm_print_power_states(adev); + mutex_unlock(&adev->pm.mutex); + DRM_INFO("amdgpu: dpm initialized\n"); + + return 0; + +dpm_failed: + si_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + DRM_ERROR("amdgpu: dpm initialization failed\n"); + return ret; +} + +static int si_dpm_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + flush_work(&adev->pm.dpm.thermal.work); + + mutex_lock(&adev->pm.mutex); + si_dpm_fini(adev); + mutex_unlock(&adev->pm.mutex); + + return 0; +} + +static int si_dpm_hw_init(void *handle) +{ + int ret; + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (!amdgpu_dpm) + return 0; + + mutex_lock(&adev->pm.mutex); + si_dpm_setup_asic(adev); + ret = si_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + amdgpu_pm_compute_clocks(adev); + return ret; +} + +static int si_dpm_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + si_dpm_disable(adev); + mutex_unlock(&adev->pm.mutex); + } + + return 0; +} + +static int si_dpm_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + mutex_lock(&adev->pm.mutex); + /* disable dpm */ + si_dpm_disable(adev); + /* reset the power state */ + adev->pm.dpm.current_ps = adev->pm.dpm.requested_ps = adev->pm.dpm.boot_ps; + mutex_unlock(&adev->pm.mutex); + } + return 0; +} + +static int si_dpm_resume(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pm.dpm_enabled) { + /* asic init will reset to the boot state */ + mutex_lock(&adev->pm.mutex); + si_dpm_setup_asic(adev); + ret = si_dpm_enable(adev); + if (ret) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + mutex_unlock(&adev->pm.mutex); + if (adev->pm.dpm_enabled) + amdgpu_pm_compute_clocks(adev); + } + return 0; +} + +static bool si_dpm_is_idle(void *handle) +{ + /* XXX */ + return true; +} + +static int si_dpm_wait_for_idle(void *handle) +{ + /* XXX */ + return 0; +} + +static int si_dpm_soft_reset(void *handle) +{ + return 0; +} + +static int si_dpm_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int si_dpm_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +/* get temperature in millidegrees */ +static int si_dpm_get_temp(void *handle) +{ + u32 temp; + int actual_temp = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >> + CTF_TEMP_SHIFT; + + if (temp & 0x200) + actual_temp = 255; + else + actual_temp = temp & 0x1ff; + + actual_temp = (actual_temp * 1000); + + return actual_temp; +} + +static u32 si_dpm_get_sclk(void *handle, bool low) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + + if (low) + return requested_state->performance_levels[0].sclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].sclk; +} + +static u32 si_dpm_get_mclk(void *handle, bool low) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct si_ps *requested_state = si_get_ps(&eg_pi->requested_rps); + + if (low) + return requested_state->performance_levels[0].mclk; + else + return requested_state->performance_levels[requested_state->performance_level_count - 1].mclk; +} + +static void si_dpm_print_power_state(void *handle, + void *current_ps) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct amdgpu_ps *rps = (struct amdgpu_ps *)current_ps; + struct si_ps *ps = si_get_ps(rps); + struct rv7xx_pl *pl; + int i; + + amdgpu_dpm_print_class_info(rps->class, rps->class2); + amdgpu_dpm_print_cap_info(rps->caps); + DRM_INFO("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); + for (i = 0; i < ps->performance_level_count; i++) { + pl = &ps->performance_levels[i]; + if (adev->asic_type >= CHIP_TAHITI) + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u pcie gen: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci, pl->pcie_gen + 1); + else + DRM_INFO("\t\tpower level %d sclk: %u mclk: %u vddc: %u vddci: %u\n", + i, pl->sclk, pl->mclk, pl->vddc, pl->vddci); + } + amdgpu_dpm_print_ps_status(adev, rps); +} + +static int si_dpm_early_init(void *handle) +{ + + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + adev->powerplay.pp_funcs = &si_dpm_funcs; + adev->powerplay.pp_handle = adev; + si_dpm_set_irq_funcs(adev); + return 0; +} + +static inline bool si_are_power_levels_equal(const struct rv7xx_pl *si_cpl1, + const struct rv7xx_pl *si_cpl2) +{ + return ((si_cpl1->mclk == si_cpl2->mclk) && + (si_cpl1->sclk == si_cpl2->sclk) && + (si_cpl1->pcie_gen == si_cpl2->pcie_gen) && + (si_cpl1->vddc == si_cpl2->vddc) && + (si_cpl1->vddci == si_cpl2->vddci)); +} + +static int si_check_state_equal(void *handle, + void *current_ps, + void *request_ps, + bool *equal) +{ + struct si_ps *si_cps; + struct si_ps *si_rps; + int i; + struct amdgpu_ps *cps = (struct amdgpu_ps *)current_ps; + struct amdgpu_ps *rps = (struct amdgpu_ps *)request_ps; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev == NULL || cps == NULL || rps == NULL || equal == NULL) + return -EINVAL; + + si_cps = si_get_ps((struct amdgpu_ps *)cps); + si_rps = si_get_ps((struct amdgpu_ps *)rps); + + if (si_cps == NULL) { + printk("si_cps is NULL\n"); + *equal = false; + return 0; + } + + if (si_cps->performance_level_count != si_rps->performance_level_count) { + *equal = false; + return 0; + } + + for (i = 0; i < si_cps->performance_level_count; i++) { + if (!si_are_power_levels_equal(&(si_cps->performance_levels[i]), + &(si_rps->performance_levels[i]))) { + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((cps->vclk == rps->vclk) && (cps->dclk == rps->dclk)); + *equal &= ((cps->evclk == rps->evclk) && (cps->ecclk == rps->ecclk)); + + return 0; +} + +static int si_dpm_read_sensor(void *handle, int idx, + void *value, int *size) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct evergreen_power_info *eg_pi = evergreen_get_pi(adev); + struct amdgpu_ps *rps = &eg_pi->current_rps; + struct si_ps *ps = si_get_ps(rps); + uint32_t sclk, mclk; + u32 pl_index = + (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_INDEX_MASK) >> + CURRENT_STATE_INDEX_SHIFT; + + /* size must be at least 4 bytes for all sensors */ + if (*size < 4) + return -EINVAL; + + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + if (pl_index < ps->performance_level_count) { + sclk = ps->performance_levels[pl_index].sclk; + *((uint32_t *)value) = sclk; + *size = 4; + return 0; + } + return -EINVAL; + case AMDGPU_PP_SENSOR_GFX_MCLK: + if (pl_index < ps->performance_level_count) { + mclk = ps->performance_levels[pl_index].mclk; + *((uint32_t *)value) = mclk; + *size = 4; + return 0; + } + return -EINVAL; + case AMDGPU_PP_SENSOR_GPU_TEMP: + *((uint32_t *)value) = si_dpm_get_temp(adev); + *size = 4; + return 0; + default: + return -EINVAL; + } +} + +static const struct amd_ip_funcs si_dpm_ip_funcs = { + .name = "si_dpm", + .early_init = si_dpm_early_init, + .late_init = si_dpm_late_init, + .sw_init = si_dpm_sw_init, + .sw_fini = si_dpm_sw_fini, + .hw_init = si_dpm_hw_init, + .hw_fini = si_dpm_hw_fini, + .suspend = si_dpm_suspend, + .resume = si_dpm_resume, + .is_idle = si_dpm_is_idle, + .wait_for_idle = si_dpm_wait_for_idle, + .soft_reset = si_dpm_soft_reset, + .set_clockgating_state = si_dpm_set_clockgating_state, + .set_powergating_state = si_dpm_set_powergating_state, +}; + +const struct amdgpu_ip_block_version si_smu_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 6, + .minor = 0, + .rev = 0, + .funcs = &si_dpm_ip_funcs, +}; + +static const struct amd_pm_funcs si_dpm_funcs = { + .pre_set_power_state = &si_dpm_pre_set_power_state, + .set_power_state = &si_dpm_set_power_state, + .post_set_power_state = &si_dpm_post_set_power_state, + .display_configuration_changed = &si_dpm_display_configuration_changed, + .get_sclk = &si_dpm_get_sclk, + .get_mclk = &si_dpm_get_mclk, + .print_power_state = &si_dpm_print_power_state, + .debugfs_print_current_performance_level = &si_dpm_debugfs_print_current_performance_level, + .force_performance_level = &si_dpm_force_performance_level, + .vblank_too_short = &si_dpm_vblank_too_short, + .set_fan_control_mode = &si_dpm_set_fan_control_mode, + .get_fan_control_mode = &si_dpm_get_fan_control_mode, + .set_fan_speed_percent = &si_dpm_set_fan_speed_percent, + .get_fan_speed_percent = &si_dpm_get_fan_speed_percent, + .check_state_equal = &si_check_state_equal, + .get_vce_clock_state = amdgpu_get_vce_clock_state, + .read_sensor = &si_dpm_read_sensor, +}; + +static const struct amdgpu_irq_src_funcs si_dpm_irq_funcs = { + .set = si_dpm_set_interrupt_state, + .process = si_dpm_process_interrupt, +}; + +static void si_dpm_set_irq_funcs(struct amdgpu_device *adev) +{ + adev->pm.dpm.thermal.irq.num_types = AMDGPU_THERMAL_IRQ_LAST; + adev->pm.dpm.thermal.irq.funcs = &si_dpm_irq_funcs; +} + diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h new file mode 100644 index 000000000000..bc0be6818e21 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/si_dpm.h @@ -0,0 +1,1015 @@ +/* + * Copyright 2012 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 __SI_DPM_H__ +#define __SI_DPM_H__ + +#include "amdgpu_atombios.h" +#include "sislands_smc.h" + +#define MC_CG_CONFIG 0x96f +#define MC_ARB_CG 0x9fa +#define CG_ARB_REQ(x) ((x) << 0) +#define CG_ARB_REQ_MASK (0xff << 0) + +#define MC_ARB_DRAM_TIMING_1 0x9fc +#define MC_ARB_DRAM_TIMING_2 0x9fd +#define MC_ARB_DRAM_TIMING_3 0x9fe +#define MC_ARB_DRAM_TIMING2_1 0x9ff +#define MC_ARB_DRAM_TIMING2_2 0xa00 +#define MC_ARB_DRAM_TIMING2_3 0xa01 + +#define MAX_NO_OF_MVDD_VALUES 2 +#define MAX_NO_VREG_STEPS 32 +#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 +#define SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE 32 +#define SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 +#define RV770_ASI_DFLT 1000 +#define CYPRESS_HASI_DFLT 400000 +#define PCIE_PERF_REQ_PECI_GEN1 2 +#define PCIE_PERF_REQ_PECI_GEN2 3 +#define PCIE_PERF_REQ_PECI_GEN3 4 +#define RV770_DEFAULT_VCLK_FREQ 53300 /* 10 khz */ +#define RV770_DEFAULT_DCLK_FREQ 40000 /* 10 khz */ + +#define SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE 16 + +#define RV770_SMC_TABLE_ADDRESS 0xB000 +#define RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 3 + +#define SMC_STROBE_RATIO 0x0F +#define SMC_STROBE_ENABLE 0x10 + +#define SMC_MC_EDC_RD_FLAG 0x01 +#define SMC_MC_EDC_WR_FLAG 0x02 +#define SMC_MC_RTT_ENABLE 0x04 +#define SMC_MC_STUTTER_EN 0x08 + +#define RV770_SMC_VOLTAGEMASK_VDDC 0 +#define RV770_SMC_VOLTAGEMASK_MVDD 1 +#define RV770_SMC_VOLTAGEMASK_VDDCI 2 +#define RV770_SMC_VOLTAGEMASK_MAX 4 + +#define NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 +#define NISLANDS_SMC_STROBE_RATIO 0x0F +#define NISLANDS_SMC_STROBE_ENABLE 0x10 + +#define NISLANDS_SMC_MC_EDC_RD_FLAG 0x01 +#define NISLANDS_SMC_MC_EDC_WR_FLAG 0x02 +#define NISLANDS_SMC_MC_RTT_ENABLE 0x04 +#define NISLANDS_SMC_MC_STUTTER_EN 0x08 + +#define MAX_NO_VREG_STEPS 32 + +#define NISLANDS_SMC_VOLTAGEMASK_VDDC 0 +#define NISLANDS_SMC_VOLTAGEMASK_MVDD 1 +#define NISLANDS_SMC_VOLTAGEMASK_VDDCI 2 +#define NISLANDS_SMC_VOLTAGEMASK_MAX 4 + +#define SISLANDS_MCREGISTERTABLE_INITIAL_SLOT 0 +#define SISLANDS_MCREGISTERTABLE_ACPI_SLOT 1 +#define SISLANDS_MCREGISTERTABLE_ULV_SLOT 2 +#define SISLANDS_MCREGISTERTABLE_FIRST_DRIVERSTATE_SLOT 3 + +#define SISLANDS_LEAKAGE_INDEX0 0xff01 +#define SISLANDS_MAX_LEAKAGE_COUNT 4 + +#define SISLANDS_MAX_HARDWARE_POWERLEVELS 5 +#define SISLANDS_INITIAL_STATE_ARB_INDEX 0 +#define SISLANDS_ACPI_STATE_ARB_INDEX 1 +#define SISLANDS_ULV_STATE_ARB_INDEX 2 +#define SISLANDS_DRIVER_STATE_ARB_INDEX 3 + +#define SISLANDS_DPM2_MAX_PULSE_SKIP 256 + +#define SISLANDS_DPM2_NEAR_TDP_DEC 10 +#define SISLANDS_DPM2_ABOVE_SAFE_INC 5 +#define SISLANDS_DPM2_BELOW_SAFE_INC 20 + +#define SISLANDS_DPM2_TDP_SAFE_LIMIT_PERCENT 80 + +#define SISLANDS_DPM2_MAXPS_PERCENT_H 99 +#define SISLANDS_DPM2_MAXPS_PERCENT_M 99 + +#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define SISLANDS_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define SISLANDS_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define SISLANDS_DPM2_SQ_RAMP_STI_SIZE 0x1E +#define SISLANDS_DPM2_SQ_RAMP_LTI_RATIO 0xF + +#define SISLANDS_DPM2_PWREFFICIENCYRATIO_MARGIN 10 + +#define SISLANDS_VRC_DFLT 0xC000B3 +#define SISLANDS_ULVVOLTAGECHANGEDELAY_DFLT 1687 +#define SISLANDS_CGULVPARAMETER_DFLT 0x00040035 +#define SISLANDS_CGULVCONTROL_DFLT 0x1f007550 + +#define SI_ASI_DFLT 10000 +#define SI_BSP_DFLT 0x41EB +#define SI_BSU_DFLT 0x2 +#define SI_AH_DFLT 5 +#define SI_RLP_DFLT 25 +#define SI_RMP_DFLT 65 +#define SI_LHP_DFLT 40 +#define SI_LMP_DFLT 15 +#define SI_TD_DFLT 0 +#define SI_UTC_DFLT_00 0x24 +#define SI_UTC_DFLT_01 0x22 +#define SI_UTC_DFLT_02 0x22 +#define SI_UTC_DFLT_03 0x22 +#define SI_UTC_DFLT_04 0x22 +#define SI_UTC_DFLT_05 0x22 +#define SI_UTC_DFLT_06 0x22 +#define SI_UTC_DFLT_07 0x22 +#define SI_UTC_DFLT_08 0x22 +#define SI_UTC_DFLT_09 0x22 +#define SI_UTC_DFLT_10 0x22 +#define SI_UTC_DFLT_11 0x22 +#define SI_UTC_DFLT_12 0x22 +#define SI_UTC_DFLT_13 0x22 +#define SI_UTC_DFLT_14 0x22 +#define SI_DTC_DFLT_00 0x24 +#define SI_DTC_DFLT_01 0x22 +#define SI_DTC_DFLT_02 0x22 +#define SI_DTC_DFLT_03 0x22 +#define SI_DTC_DFLT_04 0x22 +#define SI_DTC_DFLT_05 0x22 +#define SI_DTC_DFLT_06 0x22 +#define SI_DTC_DFLT_07 0x22 +#define SI_DTC_DFLT_08 0x22 +#define SI_DTC_DFLT_09 0x22 +#define SI_DTC_DFLT_10 0x22 +#define SI_DTC_DFLT_11 0x22 +#define SI_DTC_DFLT_12 0x22 +#define SI_DTC_DFLT_13 0x22 +#define SI_DTC_DFLT_14 0x22 +#define SI_VRC_DFLT 0x0000C003 +#define SI_VOLTAGERESPONSETIME_DFLT 1000 +#define SI_BACKBIASRESPONSETIME_DFLT 1000 +#define SI_VRU_DFLT 0x3 +#define SI_SPLLSTEPTIME_DFLT 0x1000 +#define SI_SPLLSTEPUNIT_DFLT 0x3 +#define SI_TPU_DFLT 0 +#define SI_TPC_DFLT 0x200 +#define SI_SSTU_DFLT 0 +#define SI_SST_DFLT 0x00C8 +#define SI_GICST_DFLT 0x200 +#define SI_FCT_DFLT 0x0400 +#define SI_FCTU_DFLT 0 +#define SI_CTXCGTT3DRPHC_DFLT 0x20 +#define SI_CTXCGTT3DRSDC_DFLT 0x40 +#define SI_VDDC3DOORPHC_DFLT 0x100 +#define SI_VDDC3DOORSDC_DFLT 0x7 +#define SI_VDDC3DOORSU_DFLT 0 +#define SI_MPLLLOCKTIME_DFLT 100 +#define SI_MPLLRESETTIME_DFLT 150 +#define SI_VCOSTEPPCT_DFLT 20 +#define SI_ENDINGVCOSTEPPCT_DFLT 5 +#define SI_REFERENCEDIVIDER_DFLT 4 + +#define SI_PM_NUMBER_OF_TC 15 +#define SI_PM_NUMBER_OF_SCLKS 20 +#define SI_PM_NUMBER_OF_MCLKS 4 +#define SI_PM_NUMBER_OF_VOLTAGE_LEVELS 4 +#define SI_PM_NUMBER_OF_ACTIVITY_LEVELS 3 + +/* XXX are these ok? */ +#define SI_TEMP_RANGE_MIN (90 * 1000) +#define SI_TEMP_RANGE_MAX (120 * 1000) + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + +enum ni_dc_cac_level +{ + NISLANDS_DCCAC_LEVEL_0 = 0, + NISLANDS_DCCAC_LEVEL_1, + NISLANDS_DCCAC_LEVEL_2, + NISLANDS_DCCAC_LEVEL_3, + NISLANDS_DCCAC_LEVEL_4, + NISLANDS_DCCAC_LEVEL_5, + NISLANDS_DCCAC_LEVEL_6, + NISLANDS_DCCAC_LEVEL_7, + NISLANDS_DCCAC_MAX_LEVELS +}; + +enum si_cac_config_reg_type +{ + SISLANDS_CACCONFIG_MMR = 0, + SISLANDS_CACCONFIG_CGIND, + SISLANDS_CACCONFIG_MAX +}; + +enum si_power_level { + SI_POWER_LEVEL_LOW = 0, + SI_POWER_LEVEL_MEDIUM = 1, + SI_POWER_LEVEL_HIGH = 2, + SI_POWER_LEVEL_CTXSW = 3, +}; + +enum si_td { + SI_TD_AUTO, + SI_TD_UP, + SI_TD_DOWN, +}; + +enum si_display_watermark { + SI_DISPLAY_WATERMARK_LOW = 0, + SI_DISPLAY_WATERMARK_HIGH = 1, +}; + +enum si_display_gap +{ + SI_PM_DISPLAY_GAP_VBLANK_OR_WM = 0, + SI_PM_DISPLAY_GAP_VBLANK = 1, + SI_PM_DISPLAY_GAP_WATERMARK = 2, + SI_PM_DISPLAY_GAP_IGNORE = 3, +}; + +extern const struct amdgpu_ip_block_version si_smu_ip_block; + +struct ni_leakage_coeffients +{ + u32 at; + u32 bt; + u32 av; + u32 bv; + s32 t_slope; + s32 t_intercept; + u32 t_ref; +}; + +struct SMC_Evergreen_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_Evergreen_MCRegisterAddress SMC_Evergreen_MCRegisterAddress; + +struct evergreen_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +struct evergreen_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct evergreen_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_Evergreen_MCRegisterAddress mc_reg_address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +struct SMC_Evergreen_MCRegisterSet +{ + uint32_t value[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_Evergreen_MCRegisterSet SMC_Evergreen_MCRegisterSet; + +struct SMC_Evergreen_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_Evergreen_MCRegisterAddress address[SMC_EVERGREEN_MC_REGISTER_ARRAY_SIZE]; + SMC_Evergreen_MCRegisterSet data[5]; +}; + +typedef struct SMC_Evergreen_MCRegisters SMC_Evergreen_MCRegisters; + +struct SMC_NIslands_MCRegisterSet +{ + uint32_t value[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_NIslands_MCRegisterSet SMC_NIslands_MCRegisterSet; + +struct ni_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct SMC_NIslands_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_NIslands_MCRegisterAddress SMC_NIslands_MCRegisterAddress; + +struct SMC_NIslands_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_NIslands_MCRegisterAddress address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; + SMC_NIslands_MCRegisterSet data[SMC_NISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; +}; + +typedef struct SMC_NIslands_MCRegisters SMC_NIslands_MCRegisters; + +struct evergreen_ulv_param { + bool supported; + struct rv7xx_pl *pl; +}; + +struct evergreen_arb_registers { + u32 mc_arb_dram_timing; + u32 mc_arb_dram_timing2; + u32 mc_arb_rfsh_rate; + u32 mc_arb_burst_time; +}; + +struct at { + u32 rlp; + u32 rmp; + u32 lhp; + u32 lmp; +}; + +struct ni_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_ad_func_cntl; + u32 mpll_ad_func_cntl_2; + u32 mpll_dq_func_cntl; + u32 mpll_dq_func_cntl_2; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct RV770_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct RV770_SMC_SCLK_VALUE RV770_SMC_SCLK_VALUE; + +struct RV770_SMC_MCLK_VALUE +{ + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL_2; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL_2; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct RV770_SMC_MCLK_VALUE RV770_SMC_MCLK_VALUE; + + +struct RV730_SMC_MCLK_VALUE +{ + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL2; + uint32_t vMPLL_FUNC_CNTL3; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct RV730_SMC_MCLK_VALUE RV730_SMC_MCLK_VALUE; + +struct RV770_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t padding; +}; + +typedef struct RV770_SMC_VOLTAGE_VALUE RV770_SMC_VOLTAGE_VALUE; + +union RV7XX_SMC_MCLK_VALUE +{ + RV770_SMC_MCLK_VALUE mclk770; + RV730_SMC_MCLK_VALUE mclk730; +}; + +typedef union RV7XX_SMC_MCLK_VALUE RV7XX_SMC_MCLK_VALUE, *LPRV7XX_SMC_MCLK_VALUE; + +struct RV770_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t arbValue; + union{ + uint8_t seqValue; + uint8_t ACIndex; + }; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t gen2XSP; + uint8_t backbias; + uint8_t strobeMode; + uint8_t mcFlags; + uint32_t aT; + uint32_t bSP; + RV770_SMC_SCLK_VALUE sclk; + RV7XX_SMC_MCLK_VALUE mclk; + RV770_SMC_VOLTAGE_VALUE vddc; + RV770_SMC_VOLTAGE_VALUE mvdd; + RV770_SMC_VOLTAGE_VALUE vddci; + uint8_t reserved1; + uint8_t reserved2; + uint8_t stateFlags; + uint8_t padding; +}; + +typedef struct RV770_SMC_HW_PERFORMANCE_LEVEL RV770_SMC_HW_PERFORMANCE_LEVEL; + +struct RV770_SMC_SWSTATE +{ + uint8_t flags; + uint8_t padding1; + uint8_t padding2; + uint8_t padding3; + RV770_SMC_HW_PERFORMANCE_LEVEL levels[RV770_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; +}; + +typedef struct RV770_SMC_SWSTATE RV770_SMC_SWSTATE; + +struct RV770_SMC_VOLTAGEMASKTABLE +{ + uint8_t highMask[RV770_SMC_VOLTAGEMASK_MAX]; + uint32_t lowMask[RV770_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct RV770_SMC_VOLTAGEMASKTABLE RV770_SMC_VOLTAGEMASKTABLE; + +struct RV770_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint8_t highSMIO[MAX_NO_VREG_STEPS]; + uint32_t lowSMIO[MAX_NO_VREG_STEPS]; + RV770_SMC_VOLTAGEMASKTABLE voltageMaskTable; + RV770_SMC_SWSTATE initialState; + RV770_SMC_SWSTATE ACPIState; + RV770_SMC_SWSTATE driverState; + RV770_SMC_SWSTATE ULVState; +}; + +typedef struct RV770_SMC_STATETABLE RV770_SMC_STATETABLE; + +struct vddc_table_entry { + u16 vddc; + u8 vddc_index; + u8 high_smio; + u32 low_smio; +}; + +struct rv770_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mpll_ad_func_cntl; + u32 mpll_ad_func_cntl_2; + u32 mpll_dq_func_cntl; + u32 mpll_dq_func_cntl_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct rv730_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 mclk_pwrmgt_cntl; + u32 dll_cntl; + u32 mpll_func_cntl; + u32 mpll_func_cntl2; + u32 mpll_func_cntl3; + u32 mpll_ss; + u32 mpll_ss2; +}; + +union r7xx_clock_registers { + struct rv770_clock_registers rv770; + struct rv730_clock_registers rv730; +}; + +struct rv7xx_power_info { + /* flags */ + bool mem_gddr5; + bool pcie_gen2; + bool dynamic_pcie_gen2; + bool acpi_pcie_gen2; + bool boot_in_gen2; + bool voltage_control; /* vddc */ + bool mvdd_control; + bool sclk_ss; + bool mclk_ss; + bool dynamic_ss; + bool gfx_clock_gating; + bool mg_clock_gating; + bool mgcgtssm; + bool power_gating; + bool thermal_protection; + bool display_gap; + bool dcodt; + bool ulps; + /* registers */ + union r7xx_clock_registers clk_regs; + u32 s0_vid_lower_smio_cntl; + /* voltage */ + u32 vddc_mask_low; + u32 mvdd_mask_low; + u32 mvdd_split_frequency; + u32 mvdd_low_smio[MAX_NO_OF_MVDD_VALUES]; + u16 max_vddc; + u16 max_vddc_in_table; + u16 min_vddc_in_table; + struct vddc_table_entry vddc_table[MAX_NO_VREG_STEPS]; + u8 valid_vddc_entries; + /* dc odt */ + u32 mclk_odt_threshold; + u8 odt_value_0[2]; + u8 odt_value_1[2]; + /* stored values */ + u32 boot_sclk; + u16 acpi_vddc; + u32 ref_div; + u32 active_auto_throttle_sources; + u32 mclk_stutter_mode_threshold; + u32 mclk_strobe_mode_threshold; + u32 mclk_edc_enable_threshold; + u32 bsp; + u32 bsu; + u32 pbsp; + u32 pbsu; + u32 dsp; + u32 psp; + u32 asi; + u32 pasi; + u32 vrc; + u32 restricted_levels; + u32 rlp; + u32 rmp; + u32 lhp; + u32 lmp; + /* smc offsets */ + u16 state_table_start; + u16 soft_regs_start; + u16 sram_end; + /* scratch structs */ + RV770_SMC_STATETABLE smc_statetable; +}; + +struct rv7xx_pl { + u32 sclk; + u32 mclk; + u16 vddc; + u16 vddci; /* eg+ only */ + u32 flags; + enum amdgpu_pcie_gen pcie_gen; /* si+ only */ +}; + +struct rv7xx_ps { + struct rv7xx_pl high; + struct rv7xx_pl medium; + struct rv7xx_pl low; + bool dc_compatible; +}; + +struct si_ps { + u16 performance_level_count; + bool dc_compatible; + struct rv7xx_pl performance_levels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE]; +}; + +struct ni_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct ni_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_NISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ni_cac_data +{ + struct ni_leakage_coeffients leakage_coefficients; + u32 i_leakage; + s32 leakage_minimum_temperature; + u32 pwr_const; + u32 dc_cac_value; + u32 bif_cac_value; + u32 lkge_pwr; + u8 mc_wr_weight; + u8 mc_rd_weight; + u8 allow_ovrflw; + u8 num_win_tdp; + u8 l2num_win_tdp; + u8 lts_truncate_n; +}; + +struct evergreen_power_info { + /* must be first! */ + struct rv7xx_power_info rv7xx; + /* flags */ + bool vddci_control; + bool dynamic_ac_timing; + bool abm; + bool mcls; + bool light_sleep; + bool memory_transition; + bool pcie_performance_request; + bool pcie_performance_request_registered; + bool sclk_deep_sleep; + bool dll_default_on; + bool ls_clock_gating; + bool smu_uvd_hs; + bool uvd_enabled; + /* stored values */ + u16 acpi_vddci; + u8 mvdd_high_index; + u8 mvdd_low_index; + u32 mclk_edc_wr_enable_threshold; + struct evergreen_mc_reg_table mc_reg_table; + struct atom_voltage_table vddc_voltage_table; + struct atom_voltage_table vddci_voltage_table; + struct evergreen_arb_registers bootup_arb_registers; + struct evergreen_ulv_param ulv; + struct at ats[2]; + /* smc offsets */ + u16 mc_reg_table_start; + struct amdgpu_ps current_rps; + struct rv7xx_ps current_ps; + struct amdgpu_ps requested_rps; + struct rv7xx_ps requested_ps; +}; + +struct PP_NIslands_Dpm2PerfLevel +{ + uint8_t MaxPS; + uint8_t TgtAct; + uint8_t MaxPS_StepInc; + uint8_t MaxPS_StepDec; + uint8_t PSST; + uint8_t NearTDPDec; + uint8_t AboveSafeInc; + uint8_t BelowSafeInc; + uint8_t PSDeltaLimit; + uint8_t PSDeltaWin; + uint8_t Reserved[6]; +}; + +typedef struct PP_NIslands_Dpm2PerfLevel PP_NIslands_Dpm2PerfLevel; + +struct PP_NIslands_DPM2Parameters +{ + uint32_t TDPLimit; + uint32_t NearTDPLimit; + uint32_t SafePowerLimit; + uint32_t PowerBoostLimit; +}; +typedef struct PP_NIslands_DPM2Parameters PP_NIslands_DPM2Parameters; + +struct NISLANDS_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct NISLANDS_SMC_SCLK_VALUE NISLANDS_SMC_SCLK_VALUE; + +struct NISLANDS_SMC_MCLK_VALUE +{ + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL_2; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL_2; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct NISLANDS_SMC_MCLK_VALUE NISLANDS_SMC_MCLK_VALUE; + +struct NISLANDS_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t padding; +}; + +typedef struct NISLANDS_SMC_VOLTAGE_VALUE NISLANDS_SMC_VOLTAGE_VALUE; + +struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t arbValue; + uint8_t ACIndex; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t reserved1; + uint8_t reserved2; + uint8_t strobeMode; + uint8_t mcFlags; + uint32_t aT; + uint32_t bSP; + NISLANDS_SMC_SCLK_VALUE sclk; + NISLANDS_SMC_MCLK_VALUE mclk; + NISLANDS_SMC_VOLTAGE_VALUE vddc; + NISLANDS_SMC_VOLTAGE_VALUE mvdd; + NISLANDS_SMC_VOLTAGE_VALUE vddci; + NISLANDS_SMC_VOLTAGE_VALUE std_vddc; + uint32_t powergate_en; + uint8_t hUp; + uint8_t hDown; + uint8_t stateFlags; + uint8_t arbRefreshState; + uint32_t SQPowerThrottle; + uint32_t SQPowerThrottle_2; + uint32_t reserved[2]; + PP_NIslands_Dpm2PerfLevel dpm2; +}; + +typedef struct NISLANDS_SMC_HW_PERFORMANCE_LEVEL NISLANDS_SMC_HW_PERFORMANCE_LEVEL; + +struct NISLANDS_SMC_SWSTATE +{ + uint8_t flags; + uint8_t levelCount; + uint8_t padding2; + uint8_t padding3; + NISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[]; +}; + +typedef struct NISLANDS_SMC_SWSTATE NISLANDS_SMC_SWSTATE; + +struct NISLANDS_SMC_VOLTAGEMASKTABLE +{ + uint8_t highMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; + uint32_t lowMask[NISLANDS_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct NISLANDS_SMC_VOLTAGEMASKTABLE NISLANDS_SMC_VOLTAGEMASKTABLE; + +#define NISLANDS_MAX_NO_VREG_STEPS 32 + +struct NISLANDS_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint8_t highSMIO[NISLANDS_MAX_NO_VREG_STEPS]; + uint32_t lowSMIO[NISLANDS_MAX_NO_VREG_STEPS]; + NISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; + PP_NIslands_DPM2Parameters dpm2Params; + NISLANDS_SMC_SWSTATE initialState; + NISLANDS_SMC_SWSTATE ACPIState; + NISLANDS_SMC_SWSTATE ULVState; + NISLANDS_SMC_SWSTATE driverState; + NISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[NISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; +}; + +typedef struct NISLANDS_SMC_STATETABLE NISLANDS_SMC_STATETABLE; + +struct ni_power_info { + /* must be first! */ + struct evergreen_power_info eg; + struct ni_clock_registers clock_registers; + struct ni_mc_reg_table mc_reg_table; + u32 mclk_rtt_mode_threshold; + /* flags */ + bool use_power_boost_limit; + bool support_cac_long_term_average; + bool cac_enabled; + bool cac_configuration_required; + bool driver_calculate_cac_leakage; + bool pc_enabled; + bool enable_power_containment; + bool enable_cac; + bool enable_sq_ramping; + /* smc offsets */ + u16 arb_table_start; + u16 fan_table_start; + u16 cac_table_start; + u16 spll_table_start; + /* CAC stuff */ + struct ni_cac_data cac_data; + u32 dc_cac_table[NISLANDS_DCCAC_MAX_LEVELS]; + const struct ni_cac_weights *cac_weights; + u8 lta_window_size; + u8 lts_truncate; + struct si_ps current_ps; + struct si_ps requested_ps; + /* scratch structs */ + SMC_NIslands_MCRegisters smc_mc_reg_table; + NISLANDS_SMC_STATETABLE smc_statetable; +}; + +struct si_cac_config_reg +{ + u32 offset; + u32 mask; + u32 shift; + u32 value; + enum si_cac_config_reg_type type; +}; + +struct si_powertune_data +{ + u32 cac_window; + u32 l2_lta_window_size_default; + u8 lts_truncate_default; + u8 shift_n_default; + u8 operating_temp; + struct ni_leakage_coeffients leakage_coefficients; + u32 fixed_kt; + u32 lkge_lut_v0_percent; + u8 dc_cac[NISLANDS_DCCAC_MAX_LEVELS]; + bool enable_powertune_by_default; +}; + +struct si_dyn_powertune_data +{ + u32 cac_leakage; + s32 leakage_minimum_temperature; + u32 wintime; + u32 l2_lta_window_size; + u8 lts_truncate; + u8 shift_n; + u8 dc_pwr_value; + bool disable_uvd_powertune; +}; + +struct si_dte_data +{ + u32 tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + u32 r[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + u32 k; + u32 t0; + u32 max_t; + u8 window_size; + u8 temp_select; + u8 dte_mode; + u8 tdep_count; + u8 t_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 tdep_r[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + u32 t_threshold; + bool enable_dte_by_default; +}; + +struct si_clock_registers { + u32 cg_spll_func_cntl; + u32 cg_spll_func_cntl_2; + u32 cg_spll_func_cntl_3; + u32 cg_spll_func_cntl_4; + u32 cg_spll_spread_spectrum; + u32 cg_spll_spread_spectrum_2; + u32 dll_cntl; + u32 mclk_pwrmgt_cntl; + u32 mpll_ad_func_cntl; + u32 mpll_dq_func_cntl; + u32 mpll_func_cntl; + u32 mpll_func_cntl_1; + u32 mpll_func_cntl_2; + u32 mpll_ss1; + u32 mpll_ss2; +}; + +struct si_mc_reg_entry { + u32 mclk_max; + u32 mc_data[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct si_mc_reg_table { + u8 last; + u8 num_entries; + u16 valid_flag; + struct si_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMC_NIslands_MCRegisterAddress mc_reg_address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +struct si_leakage_voltage_entry +{ + u16 voltage; + u16 leakage_index; +}; + +struct si_leakage_voltage +{ + u16 count; + struct si_leakage_voltage_entry entries[SISLANDS_MAX_LEAKAGE_COUNT]; +}; + + +struct si_ulv_param { + bool supported; + u32 cg_ulv_control; + u32 cg_ulv_parameter; + u32 volt_change_delay; + struct rv7xx_pl pl; + bool one_pcie_lane_in_ulv; +}; + +struct si_power_info { + /* must be first! */ + struct ni_power_info ni; + struct si_clock_registers clock_registers; + struct si_mc_reg_table mc_reg_table; + struct atom_voltage_table mvdd_voltage_table; + struct atom_voltage_table vddc_phase_shed_table; + struct si_leakage_voltage leakage_voltage; + u16 mvdd_bootup_value; + struct si_ulv_param ulv; + u32 max_cu; + /* pcie gen */ + enum amdgpu_pcie_gen force_pcie_gen; + enum amdgpu_pcie_gen boot_pcie_gen; + enum amdgpu_pcie_gen acpi_pcie_gen; + u32 sys_pcie_mask; + /* flags */ + bool enable_dte; + bool enable_ppm; + bool vddc_phase_shed_control; + bool pspp_notify_required; + bool sclk_deep_sleep_above_low; + bool voltage_control_svi2; + bool vddci_control_svi2; + /* smc offsets */ + u32 sram_end; + u32 state_table_start; + u32 soft_regs_start; + u32 mc_reg_table_start; + u32 arb_table_start; + u32 cac_table_start; + u32 dte_table_start; + u32 spll_table_start; + u32 papm_cfg_table_start; + u32 fan_table_start; + /* CAC stuff */ + const struct si_cac_config_reg *cac_weights; + const struct si_cac_config_reg *lcac_config; + const struct si_cac_config_reg *cac_override; + const struct si_powertune_data *powertune_data; + struct si_dyn_powertune_data dyn_powertune_data; + /* DTE stuff */ + struct si_dte_data dte_data; + /* scratch structs */ + SMC_SIslands_MCRegisters smc_mc_reg_table; + SISLANDS_SMC_STATETABLE smc_statetable; + PP_SIslands_PAPMParameters papm_parm; + /* SVI2 */ + u8 svd_gpio_id; + u8 svc_gpio_id; + /* fan control */ + bool fan_ctrl_is_in_default_mode; + u32 t_min; + u32 fan_ctrl_default_mode; + bool fan_is_controlled_by_smc; +}; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/si_smc.c b/drivers/gpu/drm/amd/pm/powerplay/si_smc.c new file mode 100644 index 000000000000..8f994ffa9cd1 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/si_smc.c @@ -0,0 +1,273 @@ +/* + * Copyright 2011 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Alex Deucher + */ + +#include + +#include "amdgpu.h" +#include "sid.h" +#include "ppsmc.h" +#include "amdgpu_ucode.h" +#include "sislands_smc.h" + +static int si_set_smc_sram_address(struct amdgpu_device *adev, + u32 smc_address, u32 limit) +{ + if (smc_address & 3) + return -EINVAL; + if ((smc_address + 3) > limit) + return -EINVAL; + + WREG32(SMC_IND_INDEX_0, smc_address); + WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + + return 0; +} + +int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit) +{ + unsigned long flags; + int ret = 0; + u32 data, original_data, addr, extra_shift; + + if (smc_start_address & 3) + return -EINVAL; + if ((smc_start_address + byte_count) > limit) + return -EINVAL; + + addr = smc_start_address; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + while (byte_count >= 4) { + /* SMC address space is BE */ + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + WREG32(SMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + /* RMW for the final bytes */ + if (byte_count > 0) { + data = 0; + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + original_data = RREG32(SMC_IND_DATA_0); + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* SMC address space is BE */ + data = (data << 8) + *src++; + byte_count--; + } + + data <<= extra_shift; + data |= (original_data & ~((~0UL) << extra_shift)); + + ret = si_set_smc_sram_address(adev, addr, limit); + if (ret) + goto done; + + WREG32(SMC_IND_DATA_0, data); + } + +done: + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} + +void amdgpu_si_start_smc(struct amdgpu_device *adev) +{ + u32 tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL); + + tmp &= ~RST_REG; + + WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); +} + +void amdgpu_si_reset_smc(struct amdgpu_device *adev) +{ + u32 tmp; + + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + RREG32(CB_CGTT_SCLK_CTRL); + + tmp = RREG32_SMC(SMC_SYSCON_RESET_CNTL) | + RST_REG; + WREG32_SMC(SMC_SYSCON_RESET_CNTL, tmp); +} + +int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev) +{ + static const u8 data[] = { 0x0E, 0x00, 0x40, 0x40 }; + + return amdgpu_si_copy_bytes_to_smc(adev, 0x0, data, 4, sizeof(data)+1); +} + +void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable) +{ + u32 tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + + if (enable) + tmp &= ~CK_DISABLE; + else + tmp |= CK_DISABLE; + + WREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0, tmp); +} + +bool amdgpu_si_is_smc_running(struct amdgpu_device *adev) +{ + u32 rst = RREG32_SMC(SMC_SYSCON_RESET_CNTL); + u32 clk = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + + if (!(rst & RST_REG) && !(clk & CK_DISABLE)) + return true; + + return false; +} + +PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, + PPSMC_Msg msg) +{ + u32 tmp; + int i; + + if (!amdgpu_si_is_smc_running(adev)) + return PPSMC_Result_Failed; + + WREG32(SMC_MESSAGE_0, msg); + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32(SMC_RESP_0); + if (tmp != 0) + break; + udelay(1); + } + + return (PPSMC_Result)RREG32(SMC_RESP_0); +} + +PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev) +{ + u32 tmp; + int i; + + if (!amdgpu_si_is_smc_running(adev)) + return PPSMC_Result_OK; + + for (i = 0; i < adev->usec_timeout; i++) { + tmp = RREG32_SMC(SMC_SYSCON_CLOCK_CNTL_0); + if ((tmp & CKEN) == 0) + break; + udelay(1); + } + + return PPSMC_Result_OK; +} + +int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit) +{ + const struct smc_firmware_header_v1_0 *hdr; + unsigned long flags; + u32 ucode_start_address; + u32 ucode_size; + const u8 *src; + u32 data; + + if (!adev->pm.fw) + return -EINVAL; + + hdr = (const struct smc_firmware_header_v1_0 *)adev->pm.fw->data; + + amdgpu_ucode_print_smc_hdr(&hdr->header); + + adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); + ucode_start_address = le32_to_cpu(hdr->ucode_start_addr); + ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes); + src = (const u8 *) + (adev->pm.fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + if (ucode_size & 3) + return -EINVAL; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + WREG32(SMC_IND_INDEX_0, ucode_start_address); + WREG32_P(SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, ~AUTO_INCREMENT_IND_0); + while (ucode_size >= 4) { + /* SMC address space is BE */ + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + + WREG32(SMC_IND_DATA_0, data); + + src += 4; + ucode_size -= 4; + } + WREG32_P(SMC_IND_ACCESS_CNTL, 0, ~AUTO_INCREMENT_IND_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return 0; +} + +int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + ret = si_set_smc_sram_address(adev, smc_address, limit); + if (ret == 0) + *value = RREG32(SMC_IND_DATA_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} + +int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(&adev->smc_idx_lock, flags); + ret = si_set_smc_sram_address(adev, smc_address, limit); + if (ret == 0) + WREG32(SMC_IND_DATA_0, value); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h b/drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h new file mode 100644 index 000000000000..d2930eceaf3c --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/sislands_smc.h @@ -0,0 +1,423 @@ +/* + * Copyright 2013 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 PP_SISLANDS_SMC_H +#define PP_SISLANDS_SMC_H + +#include "ppsmc.h" + +#pragma pack(push, 1) + +#define SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE 16 + +struct PP_SIslands_Dpm2PerfLevel +{ + uint8_t MaxPS; + uint8_t TgtAct; + uint8_t MaxPS_StepInc; + uint8_t MaxPS_StepDec; + uint8_t PSSamplingTime; + uint8_t NearTDPDec; + uint8_t AboveSafeInc; + uint8_t BelowSafeInc; + uint8_t PSDeltaLimit; + uint8_t PSDeltaWin; + uint16_t PwrEfficiencyRatio; + uint8_t Reserved[4]; +}; + +typedef struct PP_SIslands_Dpm2PerfLevel PP_SIslands_Dpm2PerfLevel; + +struct PP_SIslands_DPM2Status +{ + uint32_t dpm2Flags; + uint8_t CurrPSkip; + uint8_t CurrPSkipPowerShift; + uint8_t CurrPSkipTDP; + uint8_t CurrPSkipOCP; + uint8_t MaxSPLLIndex; + uint8_t MinSPLLIndex; + uint8_t CurrSPLLIndex; + uint8_t InfSweepMode; + uint8_t InfSweepDir; + uint8_t TDPexceeded; + uint8_t reserved; + uint8_t SwitchDownThreshold; + uint32_t SwitchDownCounter; + uint32_t SysScalingFactor; +}; + +typedef struct PP_SIslands_DPM2Status PP_SIslands_DPM2Status; + +struct PP_SIslands_DPM2Parameters +{ + uint32_t TDPLimit; + uint32_t NearTDPLimit; + uint32_t SafePowerLimit; + uint32_t PowerBoostLimit; + uint32_t MinLimitDelta; +}; +typedef struct PP_SIslands_DPM2Parameters PP_SIslands_DPM2Parameters; + +struct PP_SIslands_PAPMStatus +{ + uint32_t EstimatedDGPU_T; + uint32_t EstimatedDGPU_P; + uint32_t EstimatedAPU_T; + uint32_t EstimatedAPU_P; + uint8_t dGPU_T_Limit_Exceeded; + uint8_t reserved[3]; +}; +typedef struct PP_SIslands_PAPMStatus PP_SIslands_PAPMStatus; + +struct PP_SIslands_PAPMParameters +{ + uint32_t NearTDPLimitTherm; + uint32_t NearTDPLimitPAPM; + uint32_t PlatformPowerLimit; + uint32_t dGPU_T_Limit; + uint32_t dGPU_T_Warning; + uint32_t dGPU_T_Hysteresis; +}; +typedef struct PP_SIslands_PAPMParameters PP_SIslands_PAPMParameters; + +struct SISLANDS_SMC_SCLK_VALUE +{ + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t sclk_value; +}; + +typedef struct SISLANDS_SMC_SCLK_VALUE SISLANDS_SMC_SCLK_VALUE; + +struct SISLANDS_SMC_MCLK_VALUE +{ + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vDLL_CNTL; + uint32_t vMPLL_SS; + uint32_t vMPLL_SS2; + uint32_t mclk_value; +}; + +typedef struct SISLANDS_SMC_MCLK_VALUE SISLANDS_SMC_MCLK_VALUE; + +struct SISLANDS_SMC_VOLTAGE_VALUE +{ + uint16_t value; + uint8_t index; + uint8_t phase_settings; +}; + +typedef struct SISLANDS_SMC_VOLTAGE_VALUE SISLANDS_SMC_VOLTAGE_VALUE; + +struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL +{ + uint8_t ACIndex; + uint8_t displayWatermark; + uint8_t gen2PCIE; + uint8_t UVDWatermark; + uint8_t VCEWatermark; + uint8_t strobeMode; + uint8_t mcFlags; + uint8_t padding; + uint32_t aT; + uint32_t bSP; + SISLANDS_SMC_SCLK_VALUE sclk; + SISLANDS_SMC_MCLK_VALUE mclk; + SISLANDS_SMC_VOLTAGE_VALUE vddc; + SISLANDS_SMC_VOLTAGE_VALUE mvdd; + SISLANDS_SMC_VOLTAGE_VALUE vddci; + SISLANDS_SMC_VOLTAGE_VALUE std_vddc; + uint8_t hysteresisUp; + uint8_t hysteresisDown; + uint8_t stateFlags; + uint8_t arbRefreshState; + uint32_t SQPowerThrottle; + uint32_t SQPowerThrottle_2; + uint32_t MaxPoweredUpCU; + SISLANDS_SMC_VOLTAGE_VALUE high_temp_vddc; + SISLANDS_SMC_VOLTAGE_VALUE low_temp_vddc; + uint32_t reserved[2]; + PP_SIslands_Dpm2PerfLevel dpm2; +}; + +#define SISLANDS_SMC_STROBE_RATIO 0x0F +#define SISLANDS_SMC_STROBE_ENABLE 0x10 + +#define SISLANDS_SMC_MC_EDC_RD_FLAG 0x01 +#define SISLANDS_SMC_MC_EDC_WR_FLAG 0x02 +#define SISLANDS_SMC_MC_RTT_ENABLE 0x04 +#define SISLANDS_SMC_MC_STUTTER_EN 0x08 +#define SISLANDS_SMC_MC_PG_EN 0x10 + +typedef struct SISLANDS_SMC_HW_PERFORMANCE_LEVEL SISLANDS_SMC_HW_PERFORMANCE_LEVEL; + +struct SISLANDS_SMC_SWSTATE +{ + uint8_t flags; + uint8_t levelCount; + uint8_t padding2; + uint8_t padding3; + SISLANDS_SMC_HW_PERFORMANCE_LEVEL levels[1]; +}; + +typedef struct SISLANDS_SMC_SWSTATE SISLANDS_SMC_SWSTATE; + +#define SISLANDS_SMC_VOLTAGEMASK_VDDC 0 +#define SISLANDS_SMC_VOLTAGEMASK_MVDD 1 +#define SISLANDS_SMC_VOLTAGEMASK_VDDCI 2 +#define SISLANDS_SMC_VOLTAGEMASK_VDDC_PHASE_SHEDDING 3 +#define SISLANDS_SMC_VOLTAGEMASK_MAX 4 + +struct SISLANDS_SMC_VOLTAGEMASKTABLE +{ + uint32_t lowMask[SISLANDS_SMC_VOLTAGEMASK_MAX]; +}; + +typedef struct SISLANDS_SMC_VOLTAGEMASKTABLE SISLANDS_SMC_VOLTAGEMASKTABLE; + +#define SISLANDS_MAX_NO_VREG_STEPS 32 + +struct SISLANDS_SMC_STATETABLE +{ + uint8_t thermalProtectType; + uint8_t systemFlags; + uint8_t maxVDDCIndexInPPTable; + uint8_t extraFlags; + uint32_t lowSMIO[SISLANDS_MAX_NO_VREG_STEPS]; + SISLANDS_SMC_VOLTAGEMASKTABLE voltageMaskTable; + SISLANDS_SMC_VOLTAGEMASKTABLE phaseMaskTable; + PP_SIslands_DPM2Parameters dpm2Params; + SISLANDS_SMC_SWSTATE initialState; + SISLANDS_SMC_SWSTATE ACPIState; + SISLANDS_SMC_SWSTATE ULVState; + SISLANDS_SMC_SWSTATE driverState; + SISLANDS_SMC_HW_PERFORMANCE_LEVEL dpmLevels[SISLANDS_MAX_SMC_PERFORMANCE_LEVELS_PER_SWSTATE - 1]; +}; + +typedef struct SISLANDS_SMC_STATETABLE SISLANDS_SMC_STATETABLE; + +#define SI_SMC_SOFT_REGISTER_mclk_chg_timeout 0x0 +#define SI_SMC_SOFT_REGISTER_delay_vreg 0xC +#define SI_SMC_SOFT_REGISTER_delay_acpi 0x28 +#define SI_SMC_SOFT_REGISTER_seq_index 0x5C +#define SI_SMC_SOFT_REGISTER_mvdd_chg_time 0x60 +#define SI_SMC_SOFT_REGISTER_mclk_switch_lim 0x70 +#define SI_SMC_SOFT_REGISTER_watermark_threshold 0x78 +#define SI_SMC_SOFT_REGISTER_phase_shedding_delay 0x88 +#define SI_SMC_SOFT_REGISTER_ulv_volt_change_delay 0x8C +#define SI_SMC_SOFT_REGISTER_mc_block_delay 0x98 +#define SI_SMC_SOFT_REGISTER_ticks_per_us 0xA8 +#define SI_SMC_SOFT_REGISTER_crtc_index 0xC4 +#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_min 0xC8 +#define SI_SMC_SOFT_REGISTER_mclk_change_block_cp_max 0xCC +#define SI_SMC_SOFT_REGISTER_non_ulv_pcie_link_width 0xF4 +#define SI_SMC_SOFT_REGISTER_tdr_is_about_to_happen 0xFC +#define SI_SMC_SOFT_REGISTER_vr_hot_gpio 0x100 +#define SI_SMC_SOFT_REGISTER_svi_rework_plat_type 0x118 +#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svd 0x11c +#define SI_SMC_SOFT_REGISTER_svi_rework_gpio_id_svc 0x120 + +struct PP_SIslands_FanTable +{ + uint8_t fdo_mode; + uint8_t padding; + int16_t temp_min; + int16_t temp_med; + int16_t temp_max; + int16_t slope1; + int16_t slope2; + int16_t fdo_min; + int16_t hys_up; + int16_t hys_down; + int16_t hys_slope; + int16_t temp_resp_lim; + int16_t temp_curr; + int16_t slope_curr; + int16_t pwm_curr; + uint32_t refresh_period; + int16_t fdo_max; + uint8_t temp_src; + int8_t padding2; +}; + +typedef struct PP_SIslands_FanTable PP_SIslands_FanTable; + +#define SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 +#define SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES 32 + +#define SMC_SISLANDS_SCALE_I 7 +#define SMC_SISLANDS_SCALE_R 12 + +struct PP_SIslands_CacConfig +{ + uint16_t cac_lkge_lut[SMC_SISLANDS_LKGE_LUT_NUM_OF_TEMP_ENTRIES][SMC_SISLANDS_LKGE_LUT_NUM_OF_VOLT_ENTRIES]; + uint32_t lkge_lut_V0; + uint32_t lkge_lut_Vstep; + uint32_t WinTime; + uint32_t R_LL; + uint32_t calculation_repeats; + uint32_t l2numWin_TDP; + uint32_t dc_cac; + uint8_t lts_truncate_n; + uint8_t SHIFT_N; + uint8_t log2_PG_LKG_SCALE; + uint8_t cac_temp; + uint32_t lkge_lut_T0; + uint32_t lkge_lut_Tstep; +}; + +typedef struct PP_SIslands_CacConfig PP_SIslands_CacConfig; + +#define SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE 16 +#define SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT 20 + +struct SMC_SIslands_MCRegisterAddress +{ + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMC_SIslands_MCRegisterAddress SMC_SIslands_MCRegisterAddress; + +struct SMC_SIslands_MCRegisterSet +{ + uint32_t value[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMC_SIslands_MCRegisterSet SMC_SIslands_MCRegisterSet; + +struct SMC_SIslands_MCRegisters +{ + uint8_t last; + uint8_t reserved[3]; + SMC_SIslands_MCRegisterAddress address[SMC_SISLANDS_MC_REGISTER_ARRAY_SIZE]; + SMC_SIslands_MCRegisterSet data[SMC_SISLANDS_MC_REGISTER_ARRAY_SET_COUNT]; +}; + +typedef struct SMC_SIslands_MCRegisters SMC_SIslands_MCRegisters; + +struct SMC_SIslands_MCArbDramTimingRegisterSet +{ + uint32_t mc_arb_dram_timing; + uint32_t mc_arb_dram_timing2; + uint8_t mc_arb_rfsh_rate; + uint8_t mc_arb_burst_time; + uint8_t padding[2]; +}; + +typedef struct SMC_SIslands_MCArbDramTimingRegisterSet SMC_SIslands_MCArbDramTimingRegisterSet; + +struct SMC_SIslands_MCArbDramTimingRegisters +{ + uint8_t arb_current; + uint8_t reserved[3]; + SMC_SIslands_MCArbDramTimingRegisterSet data[16]; +}; + +typedef struct SMC_SIslands_MCArbDramTimingRegisters SMC_SIslands_MCArbDramTimingRegisters; + +struct SMC_SISLANDS_SPLL_DIV_TABLE +{ + uint32_t freq[256]; + uint32_t ss[256]; +}; + +#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_MASK 0x01ffffff +#define SMC_SISLANDS_SPLL_DIV_TABLE_FBDIV_SHIFT 0 +#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_MASK 0xfe000000 +#define SMC_SISLANDS_SPLL_DIV_TABLE_PDIV_SHIFT 25 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_MASK 0x000fffff +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKV_SHIFT 0 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_MASK 0xfff00000 +#define SMC_SISLANDS_SPLL_DIV_TABLE_CLKS_SHIFT 20 + +typedef struct SMC_SISLANDS_SPLL_DIV_TABLE SMC_SISLANDS_SPLL_DIV_TABLE; + +#define SMC_SISLANDS_DTE_MAX_FILTER_STAGES 5 + +#define SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE 16 + +struct Smc_SIslands_DTE_Configuration +{ + uint32_t tau[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + uint32_t R[SMC_SISLANDS_DTE_MAX_FILTER_STAGES]; + uint32_t K; + uint32_t T0; + uint32_t MaxT; + uint8_t WindowSize; + uint8_t Tdep_count; + uint8_t temp_select; + uint8_t DTE_mode; + uint8_t T_limits[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tdep_tau[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tdep_R[SMC_SISLANDS_DTE_MAX_TEMPERATURE_DEPENDENT_ARRAY_SIZE]; + uint32_t Tthreshold; +}; + +typedef struct Smc_SIslands_DTE_Configuration Smc_SIslands_DTE_Configuration; + +#define SMC_SISLANDS_DTE_STATUS_FLAG_DTE_ON 1 + +#define SISLANDS_SMC_FIRMWARE_HEADER_LOCATION 0x10000 + +#define SISLANDS_SMC_FIRMWARE_HEADER_version 0x0 +#define SISLANDS_SMC_FIRMWARE_HEADER_flags 0x4 +#define SISLANDS_SMC_FIRMWARE_HEADER_softRegisters 0xC +#define SISLANDS_SMC_FIRMWARE_HEADER_stateTable 0x10 +#define SISLANDS_SMC_FIRMWARE_HEADER_fanTable 0x14 +#define SISLANDS_SMC_FIRMWARE_HEADER_CacConfigTable 0x18 +#define SISLANDS_SMC_FIRMWARE_HEADER_mcRegisterTable 0x24 +#define SISLANDS_SMC_FIRMWARE_HEADER_mcArbDramAutoRefreshTable 0x30 +#define SISLANDS_SMC_FIRMWARE_HEADER_spllTable 0x38 +#define SISLANDS_SMC_FIRMWARE_HEADER_DteConfiguration 0x40 +#define SISLANDS_SMC_FIRMWARE_HEADER_PAPMParameters 0x48 + +#pragma pack(pop) + +int amdgpu_si_copy_bytes_to_smc(struct amdgpu_device *adev, + u32 smc_start_address, + const u8 *src, u32 byte_count, u32 limit); +void amdgpu_si_start_smc(struct amdgpu_device *adev); +void amdgpu_si_reset_smc(struct amdgpu_device *adev); +int amdgpu_si_program_jump_on_start(struct amdgpu_device *adev); +void amdgpu_si_smc_clock(struct amdgpu_device *adev, bool enable); +bool amdgpu_si_is_smc_running(struct amdgpu_device *adev); +PPSMC_Result amdgpu_si_send_msg_to_smc(struct amdgpu_device *adev, PPSMC_Msg msg); +PPSMC_Result amdgpu_si_wait_for_smc_inactive(struct amdgpu_device *adev); +int amdgpu_si_load_smc_ucode(struct amdgpu_device *adev, u32 limit); +int amdgpu_si_read_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 *value, u32 limit); +int amdgpu_si_write_smc_sram_dword(struct amdgpu_device *adev, u32 smc_address, + u32 value, u32 limit); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile new file mode 100644 index 000000000000..6c59c61a0d81 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/Makefile @@ -0,0 +1,33 @@ +# +# Copyright 2017 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU_MGR = smumgr.o smu8_smumgr.o tonga_smumgr.o fiji_smumgr.o \ + polaris10_smumgr.o iceland_smumgr.o \ + smu7_smumgr.o vega10_smumgr.o smu10_smumgr.o ci_smumgr.o \ + vega12_smumgr.o vegam_smumgr.o smu9_smumgr.o vega20_smumgr.o + +AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR) diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c new file mode 100644 index 000000000000..c18169aa59ce --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -0,0 +1,2965 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include +#include +#include +#include "linux/delay.h" +#include +#include + +#include "smumgr.h" +#include "pp_debug.h" +#include "ci_smumgr.h" +#include "ppsmc.h" +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "cgs_common.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "bif/bif_4_1_d.h" +#include "bif/bif_4_1_sh_mask.h" + +#include "gca/gfx_7_2_d.h" +#include "gca/gfx_7_2_sh_mask.h" + +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "processpptables.h" + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define SMC_RAM_END 0x40000 + +#define CISLAND_MINIMUM_ENGINE_CLOCK 800 +#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 + +static const struct ci_pt_defaults defaults_hawaii_xt = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_hawaii_pro = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_bonaire_xt = { + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } +}; + + +static const struct ci_pt_defaults defaults_saturn_xt = { + 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, + { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, + { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } +}; + + +static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr, + uint32_t smc_addr, uint32_t limit) +{ + if ((0 != (3 & smc_addr)) + || ((smc_addr + 3) >= limit)) { + pr_err("smc_addr invalid \n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + return 0; +} + +static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + const uint8_t *src, uint32_t byte_count, uint32_t limit) +{ + int result; + uint32_t data = 0; + uint32_t original_data; + uint32_t addr = 0; + uint32_t extra_shift; + + if ((3 & smc_start_address) + || ((smc_start_address + byte_count) >= limit)) { + pr_err("smc_start_address invalid \n"); + return -EINVAL; + } + + addr = smc_start_address; + + while (byte_count >= 4) { + /* Bytes are written into the SMC address space with the MSB first. */ + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + if (0 != byte_count) { + + data = 0; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + + original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = (0x100 * data) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + } + + return 0; +} + + +static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr) +{ + static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; + + ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); + + return 0; +} + +static bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, + uint32_t *value, uint32_t limit) +{ + int result; + + result = ci_set_smc_sram_address(hwmgr, smc_addr, limit); + + if (result) + return result; + + *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + return 0; +} + +static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + int ret; + + cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); + + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); + + if (ret != 1) + pr_info("\n failed to send message %x ret is %d\n", msg, ret); + + return 0; +} + +static int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); + return ci_send_msg_to_smc(hwmgr, msg); +} + +static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + uint32_t dev_id; + + dev_id = adev->pdev->device; + + switch (dev_id) { + case 0x67BA: + case 0x67B1: + smu_data->power_tune_defaults = &defaults_hawaii_pro; + break; + case 0x67B8: + case 0x66B0: + smu_data->power_tune_defaults = &defaults_hawaii_xt; + break; + case 0x6640: + case 0x6641: + case 0x6646: + case 0x6647: + smu_data->power_tune_defaults = &defaults_saturn_xt; + break; + case 0x6649: + case 0x6650: + case 0x6651: + case 0x6658: + case 0x665C: + case 0x665D: + case 0x67A0: + case 0x67A1: + case 0x67A2: + case 0x67A8: + case 0x67A9: + case 0x67AA: + case 0x67B9: + case 0x67BE: + default: + smu_data->power_tune_defaults = &defaults_bonaire_xt; + break; + } +} + +static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, uint32_t *vol) +{ + uint32_t i = 0; + + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + *vol = allowed_clock_voltage_table->entries[i].v; + return 0; + } + } + + *vol = allowed_clock_voltage_table->entries[i - 1].v; + return 0; +} + +static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ss_info; + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ss_info)) { + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ss_info.speed_spectrum_rate); + uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, + const struct phm_phase_shedding_limits_table *pl, + uint32_t sclk, uint32_t *p_shed) +{ + unsigned int i; + + /* use the minimum phase shedding */ + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (sclk < pl->entries[i].Sclk) { + *p_shed = i; + break; + } + } +} + +static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr) +{ + uint8_t i; + uint32_t temp; + uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK); + + if (clock < min) { + pr_info("Engine clock can't satisfy stutter requirement!\n"); + return 0; + } + for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { + temp = clock >> i; + + if (temp >= min || i == 0) + break; + } + return i; +} + +static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU7_Discrete_GraphicsLevel *level) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + + result = ci_calculate_sclk_params(hwmgr, clock, level); + + /* populate graphics levels */ + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_sclk, clock, + (uint32_t *)(&level->MinVddc)); + if (result) { + pr_err("vdd_dep_on_sclk table is NULL\n"); + return result; + } + + level->SclkFrequency = clock; + level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) + ci_populate_phase_value_based_on_sclk(hwmgr, + hwmgr->dyn_state.vddc_phase_shed_limits_table, + clock, + &level->MinVddcPhases); + + level->ActivityLevel = data->current_profile_setting.sclk_activity; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + level->EnabledForThrottle = 1; + level->UpH = data->current_profile_setting.sclk_up_hyst; + level->DownH = data->current_profile_setting.sclk_down_hyst; + level->VoltageDownH = 0; + level->PowerThrottle = 0; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = + ci_get_sleep_divider_id_from_clock(clock, + CISLAND_MINIMUM_ENGINE_CLOCK); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + } + + return result; +} + +static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result = 0; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * + SMU7_MAX_LEVELS_GRAPHICS; + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = ci_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &levels[i]); + if (result) + return result; + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + if (i == (dpm_table->sclk_table.count - 1)) + smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + } + + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + result = ci_copy_bytes_to_smc(hwmgr, array, + (u8 *)levels, array_size, + SMC_RAM_END); + + return result; + +} + +static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (ci_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + uint16_t tmp; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity; + else + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp); + + return 0; +} + +static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, + "The CAC Leakage table does not exist!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, + "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, + "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); + + for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); + hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3); + } else { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage); + } + } + + return 0; +} + +static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *vid = smu_data->power_tune_table.VddCVid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, + "There should never be more than 8 entries for VddcVid!!!", + return -EINVAL); + + for (i = 0; i < (int)data->vddc_voltage_table.count; i++) + vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); + + return 0; +} + +static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + int i, min, max; + + min = max = hi_vid[0]; + for (i = 0; i < 8; i++) { + if (0 != hi_vid[i]) { + if (min > hi_vid[i]) + min = hi_vid[i]; + if (max < hi_vid[i]) + max = hi_vid[i]; + } + + if (0 != lo_vid[i]) { + if (min > lo_vid[i]) + min = lo_vid[i]; + if (max < lo_vid[i]) + max = lo_vid[i]; + } + } + + if ((min == 0) || (max == 0)) + return -EINVAL; + smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max; + smu_data->power_tune_table.GnbLPMLMinVid = (u8)min; + + return 0; +} + +static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint16_t HiSidd; + uint16_t LoSidd; + struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + int ret = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) { + pr_err("Attempt to get pm_fuse_table_offset Failed!\n"); + return -EINVAL; + } + + /* DW0 - DW3 */ + ret = ci_populate_bapm_vddc_vid_sidd(hwmgr); + /* DW4 - DW5 */ + ret |= ci_populate_vddc_vid(hwmgr); + /* DW6 */ + ret |= ci_populate_svi_load_line(hwmgr); + /* DW7 */ + ret |= ci_populate_tdc_limit(hwmgr); + /* DW8 */ + ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset); + + ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset); + + ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr); + + ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr); + if (ret) + return ret; + + ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END); + } + return ret; +} + +static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; + struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; + const uint16_t *def1, *def2; + int i, j, k; + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + dpm_table->DTETjOffset = 0; + dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + if (ppm) { + dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; + dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; + } else { + dpm_table->PPM_PkgPwrLimit = 0; + dpm_table->PPM_TemperatureLimit = 0; + } + + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); + + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + def1 = defaults->bapmti_r; + def2 = defaults->bapmti_rc; + + for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU7_DTE_SOURCES; j++) { + for (k = 0; k < SMU7_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); + dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); + def1++; + def2++; + } + } + } + + return 0; +} + +static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, + uint16_t *lo) +{ + uint16_t v_index; + bool vol_found = false; + *hi = tab->value * VOLTAGE_SCALE; + *lo = tab->value * VOLTAGE_SCALE; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, + "The SCLK/VDDC Dependency Table does not exist.\n", + return -EINVAL); + + if (NULL == hwmgr->dyn_state.cac_leakage_table) { + pr_warn("CAC Leakage Table does not exist, using vddc.\n"); + return 0; + } + + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) { + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) + pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); + } + + return 0; +} + +static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, + SMU7_Discrete_VoltageLevel *smc_voltage_tab) +{ + int result; + + result = ci_get_std_voltage_value_sidd(hwmgr, tab, + &smc_voltage_tab->StdVoltageHiSidd, + &smc_voltage_tab->StdVoltageLoSidd); + if (result) { + smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; + smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; + } + + smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd); + + return 0; +} + +static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + unsigned int count; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddc_voltage_table.entries[count]), + &(table->VddcLevel[count])); + PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); + + /* GPIO voltage control */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { + table->VddcLevel[count].Smio = (uint8_t) count; + table->Smio[count] |= data->vddc_voltage_table.entries[count].smio_low; + table->SmioMaskVddcVid |= data->vddc_voltage_table.entries[count].smio_low; + } else { + table->VddcLevel[count].Smio = 0; + } + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + + return 0; +} + +static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->VddciLevelCount = data->vddci_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddci_voltage_table.entries[count]), + &(table->VddciLevel[count])); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + table->VddciLevel[count].Smio = (uint8_t) count; + table->Smio[count] |= data->vddci_voltage_table.entries[count].smio_low; + table->SmioMaskVddciVid |= data->vddci_voltage_table.entries[count].smio_low; + } else { + table->VddciLevel[count].Smio = 0; + } + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->MvddLevelCount = data->mvdd_voltage_table.count; + + for (count = 0; count < table->MvddLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->mvdd_voltage_table.entries[count]), + &table->MvddLevel[count]); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + table->MvddLevel[count].Smio = (uint8_t) count; + table->Smio[count] |= data->mvdd_voltage_table.entries[count].smio_low; + table->SmioMaskMvddVid |= data->mvdd_voltage_table.entries[count].smio_low; + } else { + table->MvddLevel[count].Smio = 0; + } + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + + return 0; +} + + +static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result; + + result = ci_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -EINVAL); + + return 0; +} + +static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU7_Discrete_Ulv *state) +{ + uint32_t voltage_response_time, ulv_voltage; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); + PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); + + if (ulv_voltage == 0) { + data->ulv_supported = false; + return 0; + } + + if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffset = 0; + else + /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ + state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); + } else { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffsetVid = 0; + else /* used in SVI2 Mode */ + state->VddcOffsetVid = (uint8_t)( + (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) + * VOLTAGE_VID_OFFSET_SCALE2 + / VOLTAGE_VID_OFFSET_SCALE1); + } + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr, + SMU7_Discrete_Ulv *ulv_level) +{ + return ci_populate_ulv_level(hwmgr, ulv_level); +} + +static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i; + +/* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int ci_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + + return mc_para_index; +} + +static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + + return mc_para_index; +} + +static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, + uint32_t memory_clock, uint32_t *p_shed) +{ + unsigned int i; + + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (memory_clock < pl->entries[i].Mclk) { + *p_shed = i; + break; + } + } + + return 0; +} + +static int ci_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + bool dll_state_on; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddci_dependency_on_mclk, + memory_clock, + &memory_level->MinVddci); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.mvdd_dependency_on_mclk, + memory_clock, + &memory_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result); + } + + memory_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) { + ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, + memory_clock, &memory_level->MinVddcPhases); + } + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 1; + memory_level->UpH = data->current_profile_setting.mclk_up_hyst; + memory_level->DownH = data->current_profile_setting.mclk_down_hyst; + memory_level->VoltageDownH = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + /* stutter mode not support on ci */ + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (ci_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + else + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } else + dll_state_on = data->dll_default_on; + } else { + memory_level->StrobeRatio = + ci_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = ci_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (0 == result) { + memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); + memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); + memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + struct amdgpu_device *adev = hwmgr->adev; + uint32_t dev_id; + + uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY; + SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -EINVAL); + result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (0 != result) + return result; + } + + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + dev_id = adev->pdev->device; + + if ((dpm_table->mclk_table.count >= 2) + && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { + smu_data->smc_state_table.MemoryLevel[1].MinVddci = + smu_data->smc_state_table.MemoryLevel[0].MinVddci; + smu_data->smc_state_table.MemoryLevel[1].MinMvdd = + smu_data->smc_state_table.MemoryLevel[0].MinMvdd; + } + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + result = ci_copy_bytes_to_smc(hwmgr, + level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, + SMU7_Discrete_VoltageLevel *voltage) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { + if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + voltage->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -EINVAL); + + } else { + return -EINVAL; + } + + return 0; +} + +static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + + SMU7_Discrete_VoltageLevel voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (data->acpi_vddc) + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); + else + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); + + table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1; + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; + table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; + else { + if (data->acpi_vddci != 0) + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); + } + + if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpH = 0; + table->MemoryACPILevel.DownH = 100; + table->MemoryACPILevel.VoltageDownH = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + table->UvdLevelCount = (uint8_t)(uvd_table->count); + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = + uvd_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = + uvd_table->entries[count].dclk; + table->UvdLevel[count].MinVddc = + uvd_table->entries[count].v * VOLTAGE_SCALE; + table->UvdLevel[count].MinVddcPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc); + } + + return result; +} + +static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + table->VceLevelCount = (uint8_t)(vce_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = vce_table->entries[count].evclk; + table->VceLevel[count].MinVoltage = + vce_table->entries[count].v * VOLTAGE_SCALE; + table->VceLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_acp_clock_voltage_dependency_table *acp_table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + + table->AcpLevelCount = (uint8_t)(acp_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk; + table->AcpLevel[count].MinVoltage = acp_table->entries[count].v; + table->AcpLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU7_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = ci_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) + break; + } + } + + if (0 == result) { + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU7_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n"); + result = 0; + } + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + return result; +} + +static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_reg_table) +{ + const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<address[] array out of boundary", return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +static void ci_convert_mc_registers( + const struct ci_mc_reg_entry *entry, + SMU7_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int ci_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU7_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = ci_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters)); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]); + + return ci_copy_bytes_to_smc(hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters)); + result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END); +} + +static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t count, level; + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk + >= data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk + >= data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + table->SVI2Enable = 1; + else + table->SVI2Enable = 0; + return 0; +} + +static int ci_start_smc(struct pp_hwmgr *hwmgr) +{ + /* set smc instruct start point at 0x0 */ + ci_program_jump_on_start(hwmgr); + + /* enable smc clock */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, + INTERRUPTS_ENABLED, 1); + + return 0; +} + +static int ci_populate_vr_config(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t config; + + config = VR_SVI2_PLANE_1; + table->VRConfig |= (config<voltage_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= config; + } else { + pr_info("VDDCshould be on SVI2 controller!"); + } + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config<vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config<mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config<backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + u32 i; + + ci_initialize_power_tune_defaults(hwmgr); + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + ci_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (data->ulv_supported) { + result = ci_populate_ulv_state(hwmgr, &(table->Ulv)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = ci_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = ci_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = ci_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = ci_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = ci_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = ci_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = ci_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = ci_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + table->UvdBootLevel = 0; + table->VceBootLevel = 0; + table->AcpBootLevel = 0; + table->SamuBootLevel = 0; + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + result = ci_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = ci_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); + + result = ci_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + + table->UVDInterval = 1; + table->VCEInterval = 1; + table->ACPInterval = 1; + table->SAMUInterval = 1; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + + table->TemperatureLimitHigh = + (data->thermal_temp_setting.temperature_high * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + table->TemperatureLimitLow = + (data->thermal_temp_setting.temperature_low * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->VddcVddciDelta = 4000; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + + table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count; + table->PCIeGenInterval = 1; + + result = ci_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + data->vr_config = table->VRConfig; + + ci_populate_smc_svi2_config(hwmgr, table); + + for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++) + CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); + table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); + table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + result = ci_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate initialize MC Reg table!", return result); + + result = ci_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + ci_start_smc(hwmgr); + + return 0; +} + +static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == ci_data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + + return 0; +} + +static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return ci_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, + LowSclkInterruptT), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = ci_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); + + result = ci_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t ci_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU7_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU7_SoftRegisters, AverageGraphicsA); + case AverageMemoryActivity: + return offsetof(SMU7_SoftRegisters, AverageMemoryA); + case PreVBlankGap: + return offsetof(SMU7_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU7_SoftRegisters, VBlankTimeout); + case DRAM_LOG_ADDR_H: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case LowSclkInterruptThreshold: + return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT); + } + break; + } + pr_debug("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t ci_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU7_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU7_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU7_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU7_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU7_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDCI: + return SMU7_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU7_MAX_LEVELS_MVDD; + } + + pr_debug("can't get the mac of %x\n", value); + return 0; +} + +static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr) +{ + uint32_t byte_count, start_addr; + uint8_t *src; + uint32_t data; + + struct cgs_firmware_info info = {0}; + + cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info); + + hwmgr->is_kicker = info.is_kicker; + hwmgr->smu_version = info.version; + byte_count = info.image_size; + src = (uint8_t *)info.kptr; + start_addr = info.ucode_start_address; + + if (byte_count > SMC_RAM_END) { + pr_err("SMC address is beyond the SMC RAM area.\n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + for (; byte_count >= 4; byte_count -= 4) { + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + src += 4; + } + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + if (0 != byte_count) { + pr_err("SMC size must be divisible by 4\n"); + return -EINVAL; + } + + return 0; +} + +static int ci_upload_firmware(struct pp_hwmgr *hwmgr) +{ + if (ci_is_smc_ram_running(hwmgr)) { + pr_info("smc is running, no need to load smc firmware\n"); + return 0; + } + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, + boot_seq_done, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL, + pre_fetcher_en, 1); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); + return ci_load_smc_ucode(hwmgr); +} + +static int ci_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp = 0; + int result; + bool error = false; + + if (ci_upload_firmware(hwmgr)) + return -EINVAL; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->dpm_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (0 == result) { + data->soft_regs_start = tmp; + ci_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->mc_reg_table_start = tmp; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->fan_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->arb_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (0 == result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? 1 : 0; +} + +static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct ci_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct ci_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + + if (!data->is_memory_gddr5) { + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int ci_set_valid_flag(struct ci_mc_reg_table *table) +{ + uint8_t i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1 << i); + break; + } + } + } + + return 0; +} + +static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *table; + struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = ci_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = ci_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + ci_set_s0_mc_reg_index(ni_table); + result = ci_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + ci_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, + VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int ci_smu_init(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *ci_priv = NULL; + + ci_priv = kzalloc(sizeof(struct ci_smumgr), GFP_KERNEL); + + if (ci_priv == NULL) + return -ENOMEM; + + hwmgr->smu_backend = ci_priv; + + return 0; +} + +static int ci_smu_fini(struct pp_hwmgr *hwmgr) +{ + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + return 0; +} + +static int ci_start_smu(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int ci_update_dpm_settings(struct pp_hwmgr *hwmgr, + void *profile_setting) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *) + (hwmgr->smu_backend); + struct profile_mode_setting *setting; + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + + uint32_t mclk_array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); + struct SMU7_Discrete_MemoryLevel *mclk_levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; + + if (profile_setting == NULL) + return -EINVAL; + + setting = (struct profile_mode_setting *)profile_setting; + + if (setting->bupdate_sclk) { + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + if (levels[i].ActivityLevel != + cpu_to_be16(setting->sclk_activity)) { + levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); + + clk_activity_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) + + offsetof(SMU7_Discrete_GraphicsLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (levels[i].UpH != setting->sclk_up_hyst || + levels[i].DownH != setting->sclk_down_hyst) { + levels[i].UpH = setting->sclk_up_hyst; + levels[i].DownH = setting->sclk_down_hyst; + up_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) + + offsetof(SMU7_Discrete_GraphicsLevel, UpH); + down_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) + + offsetof(SMU7_Discrete_GraphicsLevel, DownH); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpH, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownH, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); + } + + if (setting->bupdate_mclk) { + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { + if (mclk_levels[i].ActivityLevel != + cpu_to_be16(setting->mclk_activity)) { + mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); + + clk_activity_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) + + offsetof(SMU7_Discrete_MemoryLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (mclk_levels[i].UpH != setting->mclk_up_hyst || + mclk_levels[i].DownH != setting->mclk_down_hyst) { + mclk_levels[i].UpH = setting->mclk_up_hyst; + mclk_levels[i].DownH = setting->mclk_down_hyst; + up_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) + + offsetof(SMU7_Discrete_MemoryLevel, UpH); + down_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) + + offsetof(SMU7_Discrete_MemoryLevel, DownH); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpH, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownH, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); + } + return 0; +} + +static int ci_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct smu7_hwmgr *data = hwmgr->backend; + struct ci_smumgr *smu_data = hwmgr->smu_backend; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; + int32_t i; + + if (PP_CAP(PHM_PlatformCaps_UVDDPM) || uvd_table->count <= 0) + smu_data->smc_state_table.UvdBootLevel = 0; + else + smu_data->smc_state_table.UvdBootLevel = uvd_table->count - 1; + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, + UvdBootLevel, smu_data->smc_state_table.UvdBootLevel); + + data->dpm_level_enable_mask.uvd_dpm_enable_mask = 0; + + for (i = uvd_table->count - 1; i >= 0; i--) { + if (uvd_table->entries[i].v <= max_vddc) + data->dpm_level_enable_mask.uvd_dpm_enable_mask |= 1 << i; + if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_UVDDPM)) + break; + } + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, + data->dpm_level_enable_mask.uvd_dpm_enable_mask, + NULL); + + return 0; +} + +static int ci_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + struct smu7_hwmgr *data = hwmgr->backend; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; + int32_t i; + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, + VceBootLevel, 0); /* temp hard code to level 0, vce can set min evclk*/ + + data->dpm_level_enable_mask.vce_dpm_enable_mask = 0; + + for (i = vce_table->count - 1; i >= 0; i--) { + if (vce_table->entries[i].v <= max_vddc) + data->dpm_level_enable_mask.vce_dpm_enable_mask |= 1 << i; + if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_VCEDPM)) + break; + } + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, + data->dpm_level_enable_mask.vce_dpm_enable_mask, + NULL); + + return 0; +} + +static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + ci_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + ci_update_vce_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +const struct pp_smumgr_func ci_smu_funcs = { + .name = "ci_smu", + .smu_init = ci_smu_init, + .smu_fini = ci_smu_fini, + .start_smu = ci_start_smu, + .check_fw_load_finish = NULL, + .request_smu_load_fw = NULL, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = ci_send_msg_to_smc, + .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .get_offsetof = ci_get_offsetof, + .process_firmware_header = ci_process_firmware_header, + .init_smc_table = ci_init_smc_table, + .update_sclk_threshold = ci_update_sclk_threshold, + .thermal_setup_fan_table = ci_thermal_setup_fan_table, + .populate_all_graphic_levels = ci_populate_all_graphic_levels, + .populate_all_memory_levels = ci_populate_all_memory_levels, + .get_mac_definition = ci_get_mac_definition, + .initialize_mc_reg_table = ci_initialize_mc_reg_table, + .is_dpm_running = ci_is_dpm_running, + .update_dpm_settings = ci_update_dpm_settings, + .update_smc_table = ci_update_smc_table, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h new file mode 100644 index 000000000000..a8282705c569 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.h @@ -0,0 +1,76 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _CI_SMUMANAGER_H_ +#define _CI_SMUMANAGER_H_ + +#define SMU__NUM_SCLK_DPM_STATE 8 +#define SMU__NUM_MCLK_DPM_LEVELS 6 +#define SMU__NUM_LCLK_DPM_LEVELS 8 +#define SMU__NUM_PCIE_DPM_LEVELS 8 + +#include "smu7_discrete.h" +#include +#include "ppatomctrl.h" + +struct ci_pt_defaults { + u8 svi_load_line_en; + u8 svi_load_line_vddc; + u8 tdc_vddc_throttle_release_limit_perc; + u8 tdc_mawt; + u8 tdc_waterfall_ctl; + u8 dte_ambient_temp_base; + u32 display_cac; + u32 bapm_temp_gradient; + u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; + u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; +}; + +struct ci_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ci_mc_reg_table { + uint8_t last; + uint8_t num_entries; + uint16_t validflag; + struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct ci_smumgr { + uint32_t soft_regs_start; + uint32_t dpm_table_start; + uint32_t mc_reg_table_start; + uint32_t fan_table_start; + uint32_t arb_table_start; + uint32_t ulv_setting_starts; + struct SMU7_Discrete_DpmTable smc_state_table; + struct SMU7_Discrete_PmFuses power_tune_table; + const struct ci_pt_defaults *power_tune_defaults; + SMU7_Discrete_MCRegisters mc_regs; + struct ci_mc_reg_table mc_reg_table; +}; + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c new file mode 100644 index 000000000000..ecb9ee46d6b3 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.c @@ -0,0 +1,2673 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include "smumgr.h" +#include "smu7_dyn_defaults.h" +#include "smu73.h" +#include "smu_ucode_xfer_vi.h" +#include "fiji_smumgr.h" +#include "fiji_ppsmc.h" +#include "smu73_discrete.h" +#include "ppatomctrl.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "oss/oss_3_0_d.h" +#include "gca/gfx_8_0_d.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" +#include "hardwaremanager.h" +#include "cgs_common.h" +#include "atombios.h" +#include "pppcielanes.h" +#include "hwmgr.h" +#include "smu7_hwmgr.h" + + +#define AVFS_EN_MSB 1568 +#define AVFS_EN_LSB 1568 + +#define FIJI_SMC_SIZE 0x20000 + +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VDDC_VDDCI_DELTA 300 +#define MC_CG_ARB_FREQ_F1 0x0b + +/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs + * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] + */ +static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = { + {600, 1050, 3, 0}, {600, 1050, 6, 1} }; + +/* [FF, SS] type, [] 4 voltage ranges, and + * [Floor Freq, Boundary Freq, VID min , VID max] + */ +static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = { + { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] + * (coming from PWR_CKS_CNTL.stretch_amount reg spec) + */ +static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = { + {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} }; + +static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ + {1, 0xF, 0xFD, + /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ + 0x19, 5, 45} +}; + +static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { + /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */ + /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ + { 0x3c0fd047, 0x30750000, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xa00fd047, 0x409c0000, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x0410d047, 0x50c30000, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000, 0, 0, 0x0e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x6810d047, 0x60ea0000, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xcc10d047, 0xe8fd0000, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x3011d047, 0x70110100, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x9411d047, 0xf8240100, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } +}; + +static int fiji_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* Wait for smc boot up */ + /* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); */ + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result) + return result; + + /* Clear status */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_STATUS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for ROM firmware to initialize interrupt hendler */ + /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND, + SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */ + + /* Set SMU Auto Start */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_INPUT_DATA, AUTO_START, 1); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, + INTERRUPTS_ENABLED, 1); + + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL); + + /* Wait for done bit to be set */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + SMU_STATUS, SMU_DONE, 0); + + /* Check pass/failed indicator */ + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_STATUS, SMU_PASS) != 1) { + PP_ASSERT_WITH_CODE(false, + "SMU Firmware start failed!", return -1); + } + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* wait for smc boot up */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + /* Assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result) + return result; + + /* Set smc instruct start point at 0x0 */ + smu7_program_jump_on_start(hwmgr); + + /* Enable clock */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + if (0 != smu_data->avfs_btc_param) { + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param, + NULL)) { + pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed"); + result = -EINVAL; + } + } + /* Soft-Reset to reset the engine before loading uCode */ + /* halt */ + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); + /* reset everything */ + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); + /* clear reset */ + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); + + return result; +} + +static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) +{ + int32_t vr_config; + uint32_t table_start; + uint32_t level_addr, vr_config_addr; + uint32_t level_size = sizeof(avfs_graphics_level); + + PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, DpmTable), + &table_start, 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not " + "communicate starting address of DPM table", + return -1;); + + /* Default value for vr_config = + * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ + vr_config = 0x01000500; /* Real value:0x50001 */ + + vr_config_addr = table_start + + offsetof(SMU73_Discrete_DpmTable, VRConfig); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_addr, + (uint8_t *)&vr_config, sizeof(int32_t), 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying " + "vr_config value over to SMC", + return -1;); + + level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, level_addr, + (uint8_t *)(&avfs_graphics_level), level_size, 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!", + return -1;); + + return 0; +} + +static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->avfs_supported) + return 0; + + PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr), + "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" + " table over to SMU", + return -EINVAL); + PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), + "[AVFS][fiji_avfs_event_mgr] Could not setup " + "Pwr Virus for AVFS ", + return -EINVAL); + PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr), + "[AVFS][fiji_avfs_event_mgr] Failure at " + "fiji_start_avfs_btc. AVFS Disabled", + return -EINVAL); + + return 0; +} + +static int fiji_start_smu(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct fiji_smumgr *priv = (struct fiji_smumgr *)(hwmgr->smu_backend); + + /* Only start SMC if SMC RAM is not running */ + if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { + /* Check if SMU is running in protected mode */ + if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, + SMU_FIRMWARE, SMU_MODE)) { + result = fiji_start_smu_in_non_protection_mode(hwmgr); + if (result) + return result; + } else { + result = fiji_start_smu_in_protection_mode(hwmgr); + if (result) + return result; + } + if (fiji_avfs_event_mgr(hwmgr)) + hwmgr->avfs_supported = false; + } + + /* Setup SoftRegsStart here for register lookup in case + * DummyBackEnd is used and ProcessFirmwareHeader is not executed + */ + smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, SoftRegisters), + &(priv->smu7_data.soft_regs_start), 0x40000); + + result = smu7_request_smu_load_fw(hwmgr); + + return result; +} + +static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) +{ + + uint32_t efuse = 0; + uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; + + if (!hwmgr->not_vf) + return false; + + if (!atomctrl_read_efuse(hwmgr, AVFS_EN_LSB, AVFS_EN_MSB, + mask, &efuse)) { + if (efuse) + return true; + } + return false; +} + +static int fiji_smu_init(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *fiji_priv = NULL; + + fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL); + + if (fiji_priv == NULL) + return -ENOMEM; + + hwmgr->smu_backend = fiji_priv; + + if (smu7_init(hwmgr)) { + kfree(fiji_priv); + return -EINVAL; + } + + return 0; +} + +static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, + uint32_t clock, uint32_t *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + *voltage = *mvdd = 0; + + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i-1].vddci) { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} + + +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) +{ + switch (line) { + case SMU7_I2CLineID_DDC1: + *scl = SMU7_I2C_DDC1CLK; + *sda = SMU7_I2C_DDC1DATA; + break; + case SMU7_I2CLineID_DDC2: + *scl = SMU7_I2C_DDC2CLK; + *sda = SMU7_I2C_DDC2DATA; + break; + case SMU7_I2CLineID_DDC3: + *scl = SMU7_I2C_DDC3CLK; + *sda = SMU7_I2C_DDC3DATA; + break; + case SMU7_I2CLineID_DDC4: + *scl = SMU7_I2C_DDC4CLK; + *sda = SMU7_I2C_DDC4DATA; + break; + case SMU7_I2CLineID_DDC5: + *scl = SMU7_I2C_DDC5CLK; + *sda = SMU7_I2C_DDC5DATA; + break; + case SMU7_I2CLineID_DDC6: + *scl = SMU7_I2C_DDC6CLK; + *sda = SMU7_I2C_DDC6DATA; + break; + case SMU7_I2CLineID_SCLSDA: + *scl = SMU7_I2C_SCL; + *sda = SMU7_I2C_SDA; + break; + case SMU7_I2CLineID_DDCVGA: + *scl = SMU7_I2C_DDCVGACLK; + *sda = SMU7_I2C_DDCVGADATA; + break; + default: + *scl = 0; + *sda = 0; + break; + } +} + +static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &fiji_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0]; + +} + +static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table = + &hwmgr->thermal_controller.advanceFanControlParameters; + uint8_t uc_scl, uc_sda; + + /* TDP number of fraction bits are changed from 8 to 7 for Fiji + * as requested by SMC team + */ + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!", + ); + + dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; + + /* The following are for new Fiji Multi-input fan/thermal control */ + dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid1 * 256); + dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid2 * 256); + dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrVddc * 256); + dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrMvdd * 256); + dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitPlx * 256); + + dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainLiquid)); + dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrVddc)); + dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); + dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainPlx)); + dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHbm)); + + dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; + dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; + dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; + dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; + + get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Liquid_I2C_LineSCL = uc_scl; + dpm_table->Liquid_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Vr_I2C_LineSCL = uc_scl; + dpm_table->Vr_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Plx_I2C_LineSCL = uc_scl; + dpm_table->Plx_I2C_LineSDA = uc_sda; + + return 0; +} + + +static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + + +static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + /* TDC number of fraction bits are changed from 8 to 7 + * for Fiji as requested by SMC team + */ + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + smu_data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + smu_data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity & (1 << 15)) || + 0 == hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity) + hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity = hwmgr->thermal_controller. + advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = + PP_HOST_TO_SMC_US(hwmgr->thermal_controller. + advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + uint32_t pm_fuse_table_offset; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + /* DW6 */ + if (fiji_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + /* DW7 */ + if (fiji_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + /* DW8 */ + if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + /* DW9-DW12 */ + if (0 != fiji_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + /* DW13-DW14 */ + if (fiji_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + /* DW15-DW18 */ + if (fiji_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + /* DW20 */ + if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + + for (count = 0; count < lookup_table->count; count++) { + index = phm_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_high); + } + + return 0; +} + +static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result; + + result = fiji_populate_cac_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate CAC voltage tables to SMC", + return -EINVAL); + + return 0; +} + +static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_Ulv *state) +{ + int result = 0; + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + state->VddcPhase = 1; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + } + return result; +} + +static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + return fiji_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ssInfo; + + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ssInfo)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + * + * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 + */ + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ssInfo.speed_spectrum_rate); + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + + result = fiji_calculate_sclk_params(hwmgr, clock, level); + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; + else + vdd_dep_table = table_info->vdd_dep_on_sclk; + + /* populate graphics levels */ + result = fiji_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, clock, + (uint32_t *)(&level->MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + + level->SclkFrequency = clock; + level->ActivityLevel = data->current_profile_setting.sclk_activity; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->UpHyst = data->current_profile_setting.sclk_up_hyst; + level->DownHyst = data->current_profile_setting.sclk_down_hyst; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + + data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, + hwmgr->display_config->min_core_set_clock_in_sr); + + + /* Default to slow, highest DPM level will be + * set to PPSMC_DISPLAY_WATERMARK_LOW later. + */ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + + return 0; +} + +static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * + SMU73_MAX_LEVELS_GRAPHICS; + struct SMU73_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = fiji_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &levels[i]); + if (result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now.*/ + levels[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + levels[dpm_table->sclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } else { + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0)) + hightest_pcie_level_enabled++; + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0)) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < + hightest_pcie_level_enabled ? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for (i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + + +/** + * MCLK Frequency Ratio + * SEQ_CG_RESP Bit[31:24] - 0x0 + * Bit[27:24] \96 DDR3 Frequency ratio + * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz + * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz + * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz + * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz + * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz + * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz + * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz + * 400 < 0x7 <= 450MHz, 800 < 0xF + */ +static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) +{ + if (mem_clock <= 10000) + return 0x0; + if (mem_clock <= 15000) + return 0x1; + if (mem_clock <= 20000) + return 0x2; + if (mem_clock <= 25000) + return 0x3; + if (mem_clock <= 30000) + return 0x4; + if (mem_clock <= 35000) + return 0x5; + if (mem_clock <= 40000) + return 0x6; + if (mem_clock <= 45000) + return 0x7; + if (mem_clock <= 50000) + return 0x8; + if (mem_clock <= 55000) + return 0x9; + if (mem_clock <= 60000) + return 0xa; + if (mem_clock <= 65000) + return 0xb; + if (mem_clock <= 70000) + return 0xc; + if (mem_clock <= 75000) + return 0xd; + if (mem_clock <= 80000) + return 0xe; + /* mem_clock > 800MHz */ + return 0xf; +} + +static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) +{ + struct pp_atomctrl_memory_clock_param mem_param; + int result; + + result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to get Memory PLL Dividers.", + ); + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = clock; + mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; + mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); + + return result; +} + +static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + uint32_t mclk_stutter_mode_threshold = 60000; + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; + else + vdd_dep_table = table_info->vdd_dep_on_mclk; + + if (vdd_dep_table) { + result = fiji_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, clock, + (uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst; + mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = data->current_profile_setting.mclk_activity; + mem_level->StutterEnable = false; + + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + /* enable stutter mode if all the follow condition applied + * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, + * &(data->DisplayTiming.numExistingDisplays)); + */ + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + if (mclk_stutter_mode_threshold && + (clock <= mclk_stutter_mode_threshold) && + (!data->is_uvd_enabled) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + return result; +} + +static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * + SMU73_MAX_LEVELS_MEMORY; + struct SMU73_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = fiji_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + if (result) + return result; + } + + /* Only enable level 0 for now. */ + levels[0].EnabledForActivity = 1; + + /* in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in + * a higher state by default such that we are not effected by + * up threshold or and MCLK DPM latency. + */ + levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; + CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high */ + levels[dpm_table->mclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct pp_atomctrl_clock_dividers_vi dividers; + SMIO_Pattern vol_level; + uint32_t mvdd; + uint16_t us_mvdd; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (!data->sclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + table->ACPILevel.SclkFrequency = + data->dpm_table.sclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + table->ACPILevel.SclkFrequency, + (uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDC voltage value " \ + "in Clock Dependency Table", + ); + } else { + table->ACPILevel.SclkFrequency = + data->vbios_boot_state.sclk_bootup_value; + table->ACPILevel.MinVoltage = + data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; + } + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, + SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + if (!data->mclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = + data->dpm_table.mclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + (uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value in Clock Dependency Table", + ); + } else { + table->MemoryACPILevel.MclkFrequency = + data->vbios_boot_state.mclk_bootup_value; + table->MemoryACPILevel.MinVoltage = + data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; + } + + us_mvdd = 0; + if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled)) + us_mvdd = data->vbios_boot_state.mvdd_bootup_value; + else { + if (!fiji_populate_mvdd_value(hwmgr, + data->dpm_table.mclk_table.dpm_levels[0].value, + &vol_level)) + us_mvdd = vol_level.Voltage; + } + + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + table->MemoryACPILevel.StutterEnable = false; + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage = 0; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + table->VceLevel[count].MinVoltage |= + ((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) * + VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->AcpLevelCount = (uint8_t)(mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burstTime; + ULONG trrds, trrdl; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); + + trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); + trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + arb_regs->TRRDS = (uint8_t)trrds; + arb_regs->TRRDL = (uint8_t)trrdl; + + return 0; +} + +static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct SMU73_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = fiji_populate_memory_timing_parameters(hwmgr, + data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result) + break; + } + } + + if (!result) + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU73_Discrete_MCArbDramTimingTable), + SMC_RAM_END); + return result; +} + +static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].MinVoltage = 0; + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + + } + return result; +} + +static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_sclk->entries[level].clk >= + data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_mclk->entries[level].clk >= + data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, + volt_with_cks, value; + uint16_t clock_freq_u16; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, + volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (146 * 4)); + efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (148 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + efuse2 &= 0xF; + + if (efuse2 == 1) + ro = (2300 - 1350) * efuse / 255 + 1350; + else + ro = (2500 - 1000) * efuse / 255 + 1000; + + if (ro >= 1660) + type = 0; + else + type = 1; + + /* Populate Stretch amount */ + smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + volt_without_cks = (uint32_t)((14041 * + (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / + (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); + volt_with_cks = (uint32_t)((13946 * + (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / + (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + STRETCH_ENABLE, 0x0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + staticEnable, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x0); + + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFC2FF87; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][0]; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][1]; + clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. + GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. + SclkFrequency) / 100); + if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < + clock_freq_u16 && + fiji_clock_stretcher_lookup_table[stretch_amount2][1] > + clock_freq_u16) { + /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; + /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; + /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ + value |= (fiji_clock_stretch_amount_conversion + [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] + [stretch_amount]) << 3; + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].minFreq); + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].maxFreq); + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = + fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= + (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + /* Populate DDT Lookup Table */ + for (i = 0; i < 4; i++) { + /* Assign the minimum and maximum VID stored + * in the last row of Clock Stretcher Voltage Table. + */ + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].minVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].maxVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; + /* Loop through each SCLK and check the frequency + * to see if it lies within the frequency for clock stretcher. + */ + for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { + cks_setting = 0; + clock_freq = PP_SMC_TO_HOST_UL( + smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); + /* Check the allowed frequency against the sclk level[j]. + * Sclk's endianness has already been converted, + * and it's in 10Khz unit, + * as opposed to Data table, which is in Mhz unit. + */ + if (clock_freq >= + (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { + cks_setting |= 0x2; + if (clock_freq < + (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) + cks_setting |= 0x1; + } + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. + ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!", + ); + } + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + +static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + + /* This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + +static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) +{ + pp_atomctrl_voltage_table param_led_dpm; + int result = 0; + u32 mask = 0; + + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT, + ¶m_led_dpm); + if (result == 0) { + int i, j; + u32 tmp = param_led_dpm.mask_low; + + for (i = 0, j = 0; i < 32; i++) { + if (tmp & 1) { + mask |= (i << (8 * j)); + if (++j >= 3) + break; + } + tmp >>= 1; + } + } + if (mask) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_LedConfig, + mask, + NULL); + return 0; +} + +static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + + fiji_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + fiji_populate_smc_voltage_tables(hwmgr, table); + + table->SystemFlags = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = fiji_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = fiji_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = fiji_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = fiji_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = fiji_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = fiji_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = fiji_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = fiji_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = fiji_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + result = fiji_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = fiji_populate_smc_initailial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot State!", return result); + + result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = fiji_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ + table->PCIeGenInterval = 1; + table->VRConfig = 0; + + result = fiji_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + data->vr_config = table->VRConfig; + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, + &gpio_pin)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), + SMC_RAM_END); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result); + + result = fiji_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload arb data to SMC memory!", return result); + + result = fiji_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + result = fiji_setup_dpm_led_config(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to setup dpm led config", return result); + + return 0; +} + +static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (smu_data->smu7_data.fan_table_start == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. + usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr-> + thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> + thermal_controller.advanceFanControlParameters.ulCycleDelay * + reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanMinPwm, + hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit, + NULL); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanSclkTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit, + NULL); + + if (res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + return 0; +} + + +static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->avfs_supported) + return 0; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); + + return 0; +} + +static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return fiji_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + result = fiji_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + return result; +} + +static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU73_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); + case AverageMemoryActivity: + return offsetof(SMU73_SoftRegisters, AverageMemoryActivity); + case PreVBlankGap: + return offsetof(SMU73_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU73_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU73_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU73_Discrete_DpmTable, VceBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); + } + break; + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t fiji_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU73_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU73_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU73_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU73_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU73_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU73_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU73_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU73_MAX_LEVELS_MVDD; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + + +static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, + UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), + NULL); + return 0; +} + +static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + else + smu_data->smc_state_table.VceBootLevel = 0; + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, + NULL); + return 0; +} + +static int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + fiji_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + fiji_update_vce_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + + /* Program additional LP registers + * that are no longer programmed by VBIOS + */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + + return 0; +} + +static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr, + void *profile_setting) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *) + (hwmgr->smu_backend); + struct profile_mode_setting *setting; + struct SMU73_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + + uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, MemoryLevel); + struct SMU73_Discrete_MemoryLevel *mclk_levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; + + if (profile_setting == NULL) + return -EINVAL; + + setting = (struct profile_mode_setting *)profile_setting; + + if (setting->bupdate_sclk) { + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + if (levels[i].ActivityLevel != + cpu_to_be16(setting->sclk_activity)) { + levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); + + clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) + + offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (levels[i].UpHyst != setting->sclk_up_hyst || + levels[i].DownHyst != setting->sclk_down_hyst) { + levels[i].UpHyst = setting->sclk_up_hyst; + levels[i].DownHyst = setting->sclk_down_hyst; + up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) + + offsetof(SMU73_Discrete_GraphicsLevel, UpHyst); + down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) + + offsetof(SMU73_Discrete_GraphicsLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); + } + + if (setting->bupdate_mclk) { + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { + if (mclk_levels[i].ActivityLevel != + cpu_to_be16(setting->mclk_activity)) { + mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); + + clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) + + offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || + mclk_levels[i].DownHyst != setting->mclk_down_hyst) { + mclk_levels[i].UpHyst = setting->mclk_up_hyst; + mclk_levels[i].DownHyst = setting->mclk_down_hyst; + up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) + + offsetof(SMU73_Discrete_MemoryLevel, UpHyst); + down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) + + offsetof(SMU73_Discrete_MemoryLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); + } + return 0; +} + +const struct pp_smumgr_func fiji_smu_funcs = { + .name = "fiji_smu", + .smu_init = &fiji_smu_init, + .smu_fini = &smu7_smu_fini, + .start_smu = &fiji_start_smu, + .check_fw_load_finish = &smu7_check_fw_load_finish, + .request_smu_load_fw = &smu7_reload_firmware, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &smu7_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .update_smc_table = fiji_update_smc_table, + .get_offsetof = fiji_get_offsetof, + .process_firmware_header = fiji_process_firmware_header, + .init_smc_table = fiji_init_smc_table, + .update_sclk_threshold = fiji_update_sclk_threshold, + .thermal_setup_fan_table = fiji_thermal_setup_fan_table, + .thermal_avfs_enable = fiji_thermal_avfs_enable, + .populate_all_graphic_levels = fiji_populate_all_graphic_levels, + .populate_all_memory_levels = fiji_populate_all_memory_levels, + .get_mac_definition = fiji_get_mac_definition, + .initialize_mc_reg_table = fiji_initialize_mc_reg_table, + .is_dpm_running = fiji_is_dpm_running, + .is_hw_avfs_present = fiji_is_hw_avfs_present, + .update_dpm_settings = fiji_update_dpm_settings, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h new file mode 100644 index 000000000000..6d3746268ccf --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/fiji_smumgr.h @@ -0,0 +1,49 @@ +/* + * Copyright 2015 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 _FIJI_SMUMANAGER_H_ +#define _FIJI_SMUMANAGER_H_ + +#include "smu73_discrete.h" +#include +#include "smu7_smumgr.h" + + +struct fiji_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; +}; + +struct fiji_smumgr { + struct smu7_smumgr smu7_data; + struct SMU73_Discrete_DpmTable smc_state_table; + struct SMU73_Discrete_Ulv ulv_setting; + struct SMU73_Discrete_PmFuses power_tune_table; + const struct fiji_pt_defaults *power_tune_defaults; +}; + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c new file mode 100644 index 000000000000..431ad2fd38df --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c @@ -0,0 +1,2686 @@ +/* + * Copyright 2016 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. + * + * Author: Huang Rui + * + */ +#include "pp_debug.h" +#include +#include +#include +#include +#include + +#include "smumgr.h" +#include "iceland_smumgr.h" + +#include "ppsmc.h" + +#include "cgs_common.h" + +#include "smu7_dyn_defaults.h" +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "pppcielanes.h" +#include "pp_endian.h" +#include "processpptables.h" + + +#include "smu/smu_7_1_1_d.h" +#include "smu/smu_7_1_1_sh_mask.h" +#include "smu71_discrete.h" + +#include "smu_ucode_xfer_vi.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + + +#define ICELAND_SMC_SIZE 0x20000 + +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define MC_CG_ARB_FREQ_F1 0x0b +#define VDDC_VDDCI_DELTA 200 + +#define DEVICE_ID_VI_ICELAND_M_6900 0x6900 +#define DEVICE_ID_VI_ICELAND_M_6901 0x6901 +#define DEVICE_ID_VI_ICELAND_M_6902 0x6902 +#define DEVICE_ID_VI_ICELAND_M_6903 0x6903 + +static const struct iceland_pt_defaults defaults_iceland = { + /* + * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, + * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } +}; + +/* 35W - XT, XTL */ +static const struct iceland_pt_defaults defaults_icelandxt = { + /* + * sviLoadLIneEn, SviLoadLineVddC, + * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, + * BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, + { 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0}, + { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} +}; + +/* 25W - PRO, LE */ +static const struct iceland_pt_defaults defaults_icelandpro = { + /* + * sviLoadLIneEn, SviLoadLineVddC, + * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, + * BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, + { 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0}, + { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} +}; + +static int iceland_start_smc(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + return 0; +} + +static void iceland_reset_smc(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, + rst_reg, 1); +} + + +static void iceland_stop_smc_clock(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, + ck_disable, 1); +} + +static void iceland_start_smc_clock(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, + ck_disable, 0); +} + +static int iceland_smu_start_smc(struct pp_hwmgr *hwmgr) +{ + /* set smc instruct start point at 0x0 */ + smu7_program_jump_on_start(hwmgr); + + /* enable smc clock */ + iceland_start_smc_clock(hwmgr); + + /* de-assert reset */ + iceland_start_smc(hwmgr); + + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, + INTERRUPTS_ENABLED, 1); + + return 0; +} + + +static int iceland_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, + uint32_t length, const uint8_t *src, + uint32_t limit, uint32_t start_addr) +{ + uint32_t byte_count = length; + uint32_t data; + + PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + while (byte_count >= 4) { + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + src += 4; + byte_count -= 4; + } + + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); + + return 0; +} + + +static int iceland_smu_upload_firmware_image(struct pp_hwmgr *hwmgr) +{ + uint32_t val; + struct cgs_firmware_info info = {0}; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + /* load SMC firmware */ + cgs_get_firmware_info(hwmgr->device, + smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); + + if (info.image_size & 3) { + pr_err("[ powerplay ] SMC ucode is not 4 bytes aligned\n"); + return -EINVAL; + } + + if (info.image_size > ICELAND_SMC_SIZE) { + pr_err("[ powerplay ] SMC address is beyond the SMC RAM area\n"); + return -EINVAL; + } + hwmgr->smu_version = info.version; + /* wait for smc boot up */ + PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); + + /* clear firmware interrupt enable flag */ + val = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMC_SYSCON_MISC_CNTL); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMC_SYSCON_MISC_CNTL, val | 1); + + /* stop smc clock */ + iceland_stop_smc_clock(hwmgr); + + /* reset smc */ + iceland_reset_smc(hwmgr); + iceland_upload_smc_firmware_data(hwmgr, info.image_size, + (uint8_t *)info.kptr, ICELAND_SMC_SIZE, + info.ucode_start_address); + + return 0; +} + +static int iceland_request_smu_load_specific_fw(struct pp_hwmgr *hwmgr, + uint32_t firmwareType) +{ + return 0; +} + +static int iceland_start_smu(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *priv = hwmgr->smu_backend; + int result; + + if (!smu7_is_smc_ram_running(hwmgr)) { + result = iceland_smu_upload_firmware_image(hwmgr); + if (result) + return result; + + iceland_smu_start_smc(hwmgr); + } + + /* Setup SoftRegsStart here to visit the register UcodeLoadStatus + * to check fw loading state + */ + smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, SoftRegisters), + &(priv->smu7_data.soft_regs_start), 0x40000); + + result = smu7_request_smu_load_fw(hwmgr); + + return result; +} + +static int iceland_smu_init(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *iceland_priv = NULL; + + iceland_priv = kzalloc(sizeof(struct iceland_smumgr), GFP_KERNEL); + + if (iceland_priv == NULL) + return -ENOMEM; + + hwmgr->smu_backend = iceland_priv; + + if (smu7_init(hwmgr)) { + kfree(iceland_priv); + return -EINVAL; + } + + return 0; +} + + +static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + uint32_t dev_id; + + dev_id = adev->pdev->device; + + switch (dev_id) { + case DEVICE_ID_VI_ICELAND_M_6900: + case DEVICE_ID_VI_ICELAND_M_6903: + smu_data->power_tune_defaults = &defaults_icelandxt; + break; + + case DEVICE_ID_VI_ICELAND_M_6901: + case DEVICE_ID_VI_ICELAND_M_6902: + smu_data->power_tune_defaults = &defaults_icelandpro; + break; + default: + smu_data->power_tune_defaults = &defaults_iceland; + pr_warn("Unknown V.I. Device ID.\n"); + break; + } + return; +} + +static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 8; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, + "The CAC Leakage table does not exist!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, + "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, + "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { + for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); + } + } else { + PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL); + } + + return 0; +} + +static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t *vid = smu_data->power_tune_table.VddCVid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, + "There should never be more than 8 entries for VddcVid!!!", + return -EINVAL); + + for (i = 0; i < (int)data->vddc_voltage_table.count; i++) { + vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); + } + + return 0; +} + + + +static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + /* DW0 - DW3 */ + if (iceland_populate_bapm_vddc_vid_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate bapm vddc vid Failed!", + return -EINVAL); + + /* DW4 - DW5 */ + if (iceland_populate_vddc_vid(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate vddc vid Failed!", + return -EINVAL); + + /* DW6 */ + if (iceland_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + /* DW7 */ + if (iceland_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + /* DW8 */ + if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + /* DW9-DW12 */ + if (0 != iceland_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + /* DW13-DW16 */ + if (iceland_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + /* DW18 */ + if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!", + return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, uint32_t *vol) +{ + uint32_t i = 0; + + /* clock - voltage dependency table is empty table */ + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + /* find first sclk bigger than request */ + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + *vol = allowed_clock_voltage_table->entries[i].v; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *vol = allowed_clock_voltage_table->entries[i - 1].v; + + return 0; +} + +static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, + uint16_t *lo) +{ + uint16_t v_index; + bool vol_found = false; + *hi = tab->value * VOLTAGE_SCALE; + *lo = tab->value * VOLTAGE_SCALE; + + /* SCLK/VDDC Dependency Table has to exist. */ + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, + "The SCLK/VDDC Dependency Table does not exist.", + return -EINVAL); + + if (NULL == hwmgr->dyn_state.cac_leakage_table) { + pr_warn("CAC Leakage Table does not exist, using vddc.\n"); + return 0; + } + + /* + * Since voltage in the sclk/vddc dependency table is not + * necessarily in ascending order because of ELB voltage + * patching, loop through entire list to find exact voltage. + */ + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + /* + * If voltage is not found in the first pass, loop again to + * find the best match, equal or higher value. + */ + if (!vol_found) { + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) + pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); + } + + return 0; +} + +static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, + SMU71_Discrete_VoltageLevel *smc_voltage_tab) +{ + int result; + + result = iceland_get_std_voltage_value_sidd(hwmgr, tab, + &smc_voltage_tab->StdVoltageHiSidd, + &smc_voltage_tab->StdVoltageLoSidd); + if (0 != result) { + smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; + smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; + } + + smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + + return 0; +} + +static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + unsigned int count; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->vddc_voltage_table.entries[count]), + &(table->VddcLevel[count])); + PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); + + /* GPIO voltage control */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) + table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + table->VddcLevel[count].Smio = 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + + return 0; +} + +static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->VddciLevelCount = data->vddci_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->vddci_voltage_table.entries[count]), + &(table->VddciLevel[count])); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; + else + table->VddciLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->MvddLevelCount = data->mvdd_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->mvdd_voltage_table.entries[count]), + &table->MvddLevel[count]); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) + table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; + else + table->MvddLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + + return 0; +} + + +static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result; + + result = iceland_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -EINVAL); + + result = iceland_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -EINVAL); + + result = iceland_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -EINVAL); + + return 0; +} + +static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU71_Discrete_Ulv *state) +{ + uint32_t voltage_response_time, ulv_voltage; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); + PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); + + if (ulv_voltage == 0) { + data->ulv_supported = false; + return 0; + } + + if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffset = 0; + else + /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ + state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); + } else { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffsetVid = 0; + else /* used in SVI2 Mode */ + state->VddcOffsetVid = (uint8_t)( + (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) + * VOLTAGE_VID_OFFSET_SCALE2 + / VOLTAGE_VID_OFFSET_SCALE1); + } + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr, + SMU71_Discrete_Ulv *ulv_level) +{ + return iceland_populate_ulv_level(hwmgr, ulv_level); +} + +static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t i; + + /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = + 1; + table->LinkLevel[i].SPC = + (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = + PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = + PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t reference_clock; + uint32_t reference_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ + reference_clock = atomctrl_get_reference_clock(hwmgr); + + reference_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider*/ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup*/ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + + uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; + if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + */ + /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ + uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); + + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); + + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = + PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); + } + } + + sclk->SclkFrequency = engine_clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, + const struct phm_phase_shedding_limits_table *pl, + uint32_t sclk, uint32_t *p_shed) +{ + unsigned int i; + + /* use the minimum phase shedding */ + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (sclk < pl->entries[i].Sclk) { + *p_shed = i; + break; + } + } + return 0; +} + +static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + SMU71_Discrete_GraphicsLevel *graphic_level) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level); + + /* populate graphics levels*/ + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock, + &graphic_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for VDDC engine clock dependency table", return result); + + /* SCLK frequency in units of 10KHz*/ + graphic_level->SclkFrequency = engine_clock; + graphic_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) + iceland_populate_phase_value_based_on_sclk(hwmgr, + hwmgr->dyn_state.vddc_phase_shed_limits_table, + engine_clock, + &graphic_level->MinVddcPhases); + + /* Indicates maximum activity level for this performance level. 50% for now*/ + graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity; + + graphic_level->CcPwrDynRm = 0; + graphic_level->CcPwrDynRm1 = 0; + /* this level can be used if activity is high enough.*/ + graphic_level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + graphic_level->EnabledForThrottle = 1; + graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst; + graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst; + graphic_level->VoltageDownHyst = 0; + graphic_level->PowerThrottle = 0; + + data->display_timing.min_clock_in_sr = + hwmgr->display_config->min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + graphic_level->DeepSleepDivId = + smu7_get_sleep_divider_id_from_clock(engine_clock, + data->display_timing.min_clock_in_sr); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); + } + + return result; +} + +static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, GraphicsLevel); + + uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) * + SMU71_MAX_LEVELS_GRAPHICS; + + SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; + + uint32_t i; + uint8_t highest_pcie_level_enabled = 0; + uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; + uint8_t count = 0; + int result = 0; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = iceland_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result != 0) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now. */ + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + if (dpm_table->sclk_table.count > 1) + smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (highest_pcie_level_enabled + 1))) != 0) { + highest_pcie_level_enabled++; + } + + while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0) { + lowest_pcie_level_enabled++; + } + + while ((count < highest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) { + count++; + } + + mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? + (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; + + + /* set pcieDpmLevel to highest_pcie_level_enabled*/ + for (i = 2; i < dpm_table->sclk_table.count; i++) { + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; + } + + /* set pcieDpmLevel to lowest_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, + (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int iceland_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU71_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + /* MPLL_FUNC_CNTL setup*/ + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + /* MPLL_FUNC_CNTL_1 setup*/ + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + /* MPLL_AD_FUNC_CNTL setup*/ + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + /* MPLL_DQ_FUNC_CNTL setup*/ + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + /* + ************************************ + Fref = Reference Frequency + NF = Feedback divider ratio + NR = Reference divider ratio + Fnom = Nominal VCO output frequency = Fref * NF / NR + Fs = Spreading Rate + D = Percentage down-spread / 2 + Fint = Reference input frequency to PFD = Fref / NR + NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) + CLKS = NS - 1 = ISS_STEP_NUM[11:0] + NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) + CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] + ************************************* + */ + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ + /* ss.Info.speed_spectrum_rate -- in unit of khz */ + /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ + /* = reference_clock * 5 / speed_spectrum_rate */ + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + + /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ + /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + /* MCLK_PWRMGT_CNTL setup */ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) { + mc_para_index = 0x00; + } else if (memory_clock > 47500) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } + } else { + if (memory_clock < 65000) { + mc_para_index = 0x00; + } else if (memory_clock > 135000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + } + + return mc_para_index; +} + +static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) { + mc_para_index = 0; + } else if (memory_clock >= 80000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + } + + return mc_para_index; +} + +static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, + uint32_t memory_clock, uint32_t *p_shed) +{ + unsigned int i; + + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (memory_clock < pl->entries[i].Mclk) { + *p_shed = i; + break; + } + } + + return 0; +} + +static int iceland_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU71_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + bool dll_state_on; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) { + memory_level->MinVddci = memory_level->MinVddc; + } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddci_dependency_on_mclk, + memory_clock, + &memory_level->MinVddci); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); + } + + memory_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) { + iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, + memory_clock, &memory_level->MinVddcPhases); + } + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 0; + memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst; + memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst; + memory_level->VoltageDownHyst = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + /* stutter mode not support on iceland */ + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + else + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } else + dll_state_on = data->dll_default_on; + } else { + memory_level->StrobeRatio = + iceland_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = iceland_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (0 == result) { + memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); + memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); + memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +static int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + + /* populate MCLK dpm table to SMU7 */ + uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY; + SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -EINVAL); + result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (0 != result) { + return result; + } + } + + /* Only enable level 0 for now.*/ + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + /* + * in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in a higher state + * by default such that we are not effected by up threshold or and MCLK DPM latency. + */ + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high*/ + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, + level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, + SMU71_Discrete_VoltageLevel *voltage) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { + if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + voltage->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -EINVAL); + + } else { + return -EINVAL; + } + + return 0; +} + +static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t vddc_phase_shed_control = 0; + + SMU71_Discrete_VoltageLevel voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (data->acpi_vddc) + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); + else + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); + + table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1; + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; + table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; + else { + if (data->acpi_vddci != 0) + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); + } + + if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU71_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = iceland_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) { + break; + } + } + } + + if (0 == result) { + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU71_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n"); + result = 0; + } + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->BootVddci = table->BootVddc; + else + table->BootVddci = data->vbios_boot_state.vddci_bootup_value; + + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + return result; +} + +static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU71_Discrete_MCRegisters *mc_reg_table) +{ + const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<address[] array out of boundary", return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +/*convert register values from driver to SMC format */ +static void iceland_convert_mc_registers( + const struct iceland_mc_reg_entry *entry, + SMU71_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU71_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU71_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = iceland_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters)); + + result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + + address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]); + + return smu7_copy_bytes_to_smc(hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters)); + result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END); +} + +static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t count, level; + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk + >= data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk + >= data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU71_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; + struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; + const uint16_t *def1, *def2; + int i, j, k; + + + /* + * TDP number of fraction bits are changed from 8 to 7 for Iceland + * as requested by SMC team + */ + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + + dpm_table->DTETjOffset = 0; + + dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + /* The following are for new Iceland Multi-input fan/thermal control */ + if (NULL != ppm) { + dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; + dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; + } else { + dpm_table->PPM_PkgPwrLimit = 0; + dpm_table->PPM_TemperatureLimit = 0; + } + + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); + + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + def1 = defaults->bapmti_r; + def2 = defaults->bapmti_rc; + + for (i = 0; i < SMU71_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU71_DTE_SOURCES; j++) { + for (k = 0; k < SMU71_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); + dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); + def1++; + def2++; + } + } + } + + return 0; +} + +static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *tab) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + tab->SVI2Enable |= VDDC_ON_SVI2; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + tab->SVI2Enable |= VDDCI_ON_SVI2; + else + tab->MergedVddci = 1; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) + tab->SVI2Enable |= MVDD_ON_SVI2; + + PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) && + (tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL); + + return 0; +} + +static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + SMU71_Discrete_DpmTable *table = &(smu_data->smc_state_table); + + + iceland_initialize_power_tune_defaults(hwmgr); + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) { + iceland_populate_smc_voltage_tables(hwmgr, table); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + + if (data->ulv_supported) { + result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result;); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = iceland_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result;); + + result = iceland_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result;); + + result = iceland_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result;); + + result = iceland_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result;); + + result = iceland_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result;); + + result = iceland_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result;); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = iceland_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result;); + + result = iceland_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result;); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + result = iceland_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result;); + + result = iceland_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); + + result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + + table->TemperatureLimitHigh = + (data->thermal_temp_setting.temperature_high * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + table->TemperatureLimitLow = + (data->thermal_temp_setting.temperature_low * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; + table->PCIeGenInterval = 1; + + result = iceland_populate_smc_svi2_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate SVI2 setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); + table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); + table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.ulv_setting_starts, + (uint8_t *)&(smu_data->ulv_setting), + sizeof(SMU71_Discrete_Ulv), + SMC_RAM_END); + + + result = iceland_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate initialize MC Reg table!", return result); + + result = iceland_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + return 0; +} + +int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == smu7_data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + /* fan_table.FanControl_GL_Flag = 1; */ + + res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + + return 0; +} + + +static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return iceland_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = iceland_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); + + result = iceland_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t iceland_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU71_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity); + case AverageMemoryActivity: + return offsetof(SMU71_SoftRegisters, AverageMemoryActivity); + case PreVBlankGap: + return offsetof(SMU71_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU71_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU71_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case LowSclkInterruptThreshold: + return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold); + } + break; + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t iceland_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU71_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU71_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU71_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU71_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU71_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDCI: + return SMU71_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU71_MAX_LEVELS_MVDD; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + +static int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->dpm_table_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (0 == result) { + data->soft_regs_start = tmp; + smu7_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->mc_reg_table_start = tmp; + } + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->fan_table_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->arb_table_start = tmp; + } + + error |= (0 != result); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (0 == result) { + hwmgr->microcode_version_info.SMC = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, UlvSettings), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->ulv_setting_starts = tmp; + } + + error |= (0 != result); + + return error ? 1 : 0; +} + +/*---------------------------MC----------------------------*/ + +static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct iceland_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) { + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + } + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct iceland_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + + PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) { + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + } + j++; + + if (!data->is_memory_gddr5) { + PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int iceland_set_valid_flag(struct iceland_mc_reg_table *table) +{ + uint8_t i, j; + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1<smu_backend); + pp_atomctrl_mc_reg_table *table; + struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = iceland_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = iceland_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + iceland_set_s0_mc_reg_index(ni_table); + result = iceland_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + iceland_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +const struct pp_smumgr_func iceland_smu_funcs = { + .name = "iceland_smu", + .smu_init = &iceland_smu_init, + .smu_fini = &smu7_smu_fini, + .start_smu = &iceland_start_smu, + .check_fw_load_finish = &smu7_check_fw_load_finish, + .request_smu_load_fw = &smu7_request_smu_load_fw, + .request_smu_load_specific_fw = &iceland_request_smu_load_specific_fw, + .send_msg_to_smc = &smu7_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .get_offsetof = iceland_get_offsetof, + .process_firmware_header = iceland_process_firmware_header, + .init_smc_table = iceland_init_smc_table, + .update_sclk_threshold = iceland_update_sclk_threshold, + .thermal_setup_fan_table = iceland_thermal_setup_fan_table, + .populate_all_graphic_levels = iceland_populate_all_graphic_levels, + .populate_all_memory_levels = iceland_populate_all_memory_levels, + .get_mac_definition = iceland_get_mac_definition, + .initialize_mc_reg_table = iceland_initialize_mc_reg_table, + .is_dpm_running = iceland_is_dpm_running, +}; + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h new file mode 100644 index 000000000000..f32c506779c9 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.h @@ -0,0 +1,70 @@ +/* + * Copyright 2016 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. + * + * Author: Huang Rui + * + */ + +#ifndef _ICELAND_SMUMGR_H_ +#define _ICELAND_SMUMGR_H_ + + +#include "smu7_smumgr.h" +#include "pp_endian.h" +#include "smu71_discrete.h" + +struct iceland_pt_defaults { + uint8_t svi_load_line_en; + uint8_t svi_load_line_vddc; + uint8_t tdc_vddc_throttle_release_limit_perc; + uint8_t tdc_mawt; + uint8_t tdc_waterfall_ctl; + uint8_t dte_ambient_temp_base; + uint32_t display_cac; + uint32_t bapm_temp_gradient; + uint16_t bapmti_r[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; + uint16_t bapmti_rc[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; +}; + +struct iceland_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct iceland_mc_reg_table { + uint8_t last; /* number of registers*/ + uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/ + uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/ + struct iceland_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMU71_Discrete_MCRegisterAddress mc_reg_address[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct iceland_smumgr { + struct smu7_smumgr smu7_data; + struct SMU71_Discrete_DpmTable smc_state_table; + struct SMU71_Discrete_PmFuses power_tune_table; + struct SMU71_Discrete_Ulv ulv_setting; + const struct iceland_pt_defaults *power_tune_defaults; + SMU71_Discrete_MCRegisters mc_regs; + struct iceland_mc_reg_table mc_reg_table; +}; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c new file mode 100644 index 000000000000..c3d2e6dcf62a --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.c @@ -0,0 +1,2590 @@ +/* + * Copyright 2015 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 + +#include "pp_debug.h" +#include "smumgr.h" +#include "smu74.h" +#include "smu_ucode_xfer_vi.h" +#include "polaris10_smumgr.h" +#include "smu74_discrete.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "oss/oss_3_0_d.h" +#include "gca/gfx_8_0_d.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "ppatomctrl.h" +#include "cgs_common.h" +#include "smu7_ppsmc.h" +#include "smu7_smumgr.h" + +#include "smu7_dyn_defaults.h" + +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#define POLARIS10_SMC_SIZE 0x20000 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VDDC_VDDCI_DELTA 200 +#define MC_CG_ARB_FREQ_F1 0x0b + +static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ + { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, +}; + +static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { + {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, + {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, + {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; + +#define PPPOLARIS10_TARGETACTIVITY_DFLT 50 + +static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { + /* Min pcie DeepSleep Activity CgSpll CgSpll CcPwr CcPwr Sclk Enabled Enabled Voltage Power */ + /* Voltage, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ + { 0x100ea446, 0x00, 0x03, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x30750000, 0x3000, 0, 0x2600, 0, 0, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } }, + { 0x400ea446, 0x01, 0x04, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x409c0000, 0x2000, 0, 0x1e00, 1, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } }, + { 0x740ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x50c30000, 0x2800, 0, 0x2000, 1, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } }, + { 0xa40ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x60ea0000, 0x3000, 0, 0x2600, 1, 1, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } }, + { 0xd80ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x70110100, 0x3800, 0, 0x2c00, 1, 1, 0x0004, 0x1203, 0xffff, 0x3600, 0xc9e2, 0x2e00 } }, + { 0x3c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x80380100, 0x2000, 0, 0x1e00, 2, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } }, + { 0x6c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x905f0100, 0x2400, 0, 0x1e00, 2, 1, 0x0004, 0x8901, 0xffff, 0x2300, 0x314c, 0x1d00 } }, + { 0xa00fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0xa0860100, 0x2800, 0, 0x2000, 2, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } } +}; + +static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = { + 0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00}; + +static int polaris10_perform_btc(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + if (0 != smu_data->avfs_btc_param) { + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param, + NULL)) { + pr_info("[AVFS][SmuPolaris10_PerformBtc] PerformBTC SMU msg failed"); + result = -1; + } + } + if (smu_data->avfs_btc_param > 1) { + /* Soft-Reset to reset the engine before loading uCode */ + /* halt */ + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); + /* reset everything */ + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); + cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); + } + return result; +} + + +static int polaris10_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) +{ + uint32_t vr_config; + uint32_t dpm_table_start; + + uint16_t u16_boot_mvdd; + uint32_t graphics_level_address, vr_config_address, graphics_level_size; + + graphics_level_size = sizeof(avfs_graphics_level_polaris10); + u16_boot_mvdd = PP_HOST_TO_SMC_US(1300 * VOLTAGE_SCALE); + + PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, DpmTable), + &dpm_table_start, 0x40000), + "[AVFS][Polaris10_SetupGfxLvlStruct] SMU could not communicate starting address of DPM table", + return -1); + + /* Default value for VRConfig = VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ + vr_config = 0x01000500; /* Real value:0x50001 */ + + vr_config_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, VRConfig); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_address, + (uint8_t *)&vr_config, sizeof(uint32_t), 0x40000), + "[AVFS][Polaris10_SetupGfxLvlStruct] Problems copying VRConfig value over to SMC", + return -1); + + graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, + (uint8_t *)(&avfs_graphics_level_polaris10), + graphics_level_size, 0x40000), + "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of SCLK DPM table failed!", + return -1); + + graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, + (uint8_t *)(&avfs_memory_level_polaris10), sizeof(avfs_memory_level_polaris10), 0x40000), + "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of MCLK DPM table failed!", + return -1); + + /* MVDD Boot value - neccessary for getting rid of the hang that occurs during Mclk DPM enablement */ + + graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, BootMVdd); + + PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, + (uint8_t *)(&u16_boot_mvdd), sizeof(u16_boot_mvdd), 0x40000), + "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of DPM table failed!", + return -1); + + return 0; +} + + +static int polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + if (!hwmgr->avfs_supported) + return 0; + + PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(hwmgr), + "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU", + return -EINVAL); + + if (smu_data->avfs_btc_param > 1) { + pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting."); + PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), + "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ", + return -EINVAL); + } + + PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(hwmgr), + "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled", + return -EINVAL); + + return 0; +} + +static int polaris10_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* Wait for smc boot up */ + /* PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ + + /* Assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result != 0) + return result; + + /* Clear status */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); + + + /* Call Test SMU message with 0x20000 offset to trigger SMU start */ + smu7_send_msg_to_smc_offset(hwmgr); + + /* Wait done bit to be set */ + /* Check pass/failed indicator */ + + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); + + if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_STATUS, SMU_PASS)) + PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int polaris10_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* wait for smc boot up */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); + + /* Clear firmware interrupt enable flag */ + /* PHM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, + rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result != 0) + return result; + + /* Set smc instruct start point at 0x0 */ + smu7_program_jump_on_start(hwmgr); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int polaris10_start_smu(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + /* Only start SMC if SMC RAM is not running */ + if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { + smu_data->protected_mode = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); + smu_data->smu7_data.security_hard_key = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); + + /* Check if SMU is running in protected mode */ + if (smu_data->protected_mode == 0) + result = polaris10_start_smu_in_non_protection_mode(hwmgr); + else + result = polaris10_start_smu_in_protection_mode(hwmgr); + + if (result != 0) + PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); + + polaris10_avfs_event_mgr(hwmgr); + } + + /* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */ + smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters), + &(smu_data->smu7_data.soft_regs_start), 0x40000); + + result = smu7_request_smu_load_fw(hwmgr); + + return result; +} + +static bool polaris10_is_hw_avfs_present(struct pp_hwmgr *hwmgr) +{ + uint32_t efuse; + + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4)); + efuse &= 0x00000001; + if (efuse) + return true; + + return false; +} + +static int polaris10_smu_init(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data; + + smu_data = kzalloc(sizeof(struct polaris10_smumgr), GFP_KERNEL); + if (smu_data == NULL) + return -ENOMEM; + + hwmgr->smu_backend = smu_data; + + if (smu7_init(hwmgr)) { + kfree(smu_data); + return -EINVAL; + } + + return 0; +} + +static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + *voltage = *mvdd = 0; + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i-1].vddci) { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} + +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table = + &hwmgr->thermal_controller.advanceFanControlParameters; + int i, j, k; + const uint16_t *pdef1; + const uint16_t *pdef2; + + table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!", + ); + + table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + + pdef1 = defaults->BAPMTI_R; + pdef2 = defaults->BAPMTI_RC; + + for (i = 0; i < SMU74_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU74_DTE_SOURCES; j++) { + for (k = 0; k < SMU74_DTE_SINKS; k++) { + table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); + table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); + pdef1++; + pdef2++; + } + } + } + + return 0; +} + +static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + smu_data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + smu_data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + +/* TO DO move to hwmgr */ + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); + + return 0; +} + +static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + if (polaris10_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + + if (polaris10_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + + if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + if (0 != polaris10_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + if (polaris10_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + if (polaris10_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count, level; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + count = data->mvdd_voltage_table.count; + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; level++) { + table->SmioTable2.Pattern[level].Voltage = + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[level].Smio = + (uint8_t) level; + table->Smio[level] |= + data->mvdd_voltage_table.entries[level].smio_low; + } + table->SmioMask2 = data->mvdd_voltage_table.mask_low; + + table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); + } + + return 0; +} + +static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + uint32_t count, level; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + count = data->vddci_voltage_table.count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; ++level) { + table->SmioTable1.Pattern[level].Voltage = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); + table->SmioTable1.Pattern[level].Smio = (uint8_t) level; + + table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + + return 0; +} + +static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + for (count = 0; count < lookup_table->count; count++) { + index = phm_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high); + } + + return 0; +} + +static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + polaris10_populate_smc_vddci_table(hwmgr, table); + polaris10_populate_smc_mvdd_table(hwmgr, table); + polaris10_populate_cac_table(hwmgr, table); + + return 0; +} + +static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_Ulv *state) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) + state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; + else + state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + return polaris10_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + +/* To Do move to hwmgr */ + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + + +static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t i, ref_clk; + + struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; + + ref_clk = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { + for (i = 0; i < NUM_SCLK_RANGE; i++) { + table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting; + table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv; + table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } + return; + } + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; + smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; + + table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; + table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; + table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } +} + +static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, SMU_SclkSetting *sclk_setting) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_clock_dividers_ai dividers; + uint32_t ref_clock; + uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; + uint8_t i; + int result; + uint64_t temp; + + sclk_setting->SclkFrequency = clock; + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); + if (result == 0) { + sclk_setting->Fcw_int = dividers.usSclk_fcw_int; + sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; + sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; + sclk_setting->PllRange = dividers.ucSclkPllRange; + sclk_setting->Sclk_slew_rate = 0x400; + sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; + sclk_setting->Pcc_down_slew_rate = 0xffff; + sclk_setting->SSc_En = dividers.ucSscEnable; + sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; + sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; + sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; + return result; + } + + ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + if (clock > smu_data->range_table[i].trans_lower_frequency + && clock <= smu_data->range_table[i].trans_upper_frequency) { + sclk_setting->PllRange = i; + break; + } + } + + sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw_frac = temp & 0xffff; + + pcc_target_percent = 10; /* Hardcode 10% for now. */ + pcc_target_freq = clock - (clock * pcc_target_percent / 100); + sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + + ss_target_percent = 2; /* Hardcode 2% for now. */ + sclk_setting->SSc_En = 0; + if (ss_target_percent) { + sclk_setting->SSc_En = 1; + ss_target_freq = clock - (clock * ss_target_percent / 100); + sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw1_frac = temp & 0xffff; + } + + return 0; +} + +static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU74_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMU_SclkSetting curr_sclk_setting = { 0 }; + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + + result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; + else + vdd_dep_table = table_info->vdd_dep_on_sclk; + + /* populate graphics levels */ + result = polaris10_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, clock, + &level->MinVoltage, &mvdd); + + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + level->ActivityLevel = data->current_profile_setting.sclk_activity; + + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->UpHyst = data->current_profile_setting.sclk_up_hyst; + level->DownHyst = data->current_profile_setting.sclk_down_hyst; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, + hwmgr->display_config->min_core_set_clock_in_sr); + + /* Default to slow, highest DPM level will be + * set to PPSMC_DISPLAY_WATERMARK_LOW later. + */ + if (data->update_up_hyst) + level->UpHyst = (uint8_t)data->up_hyst; + if (data->update_down_hyst) + level->DownHyst = (uint8_t)data->down_hyst; + + level->SclkSetting = curr_sclk_setting; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); + return 0; +} + +static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * + SMU74_MAX_LEVELS_GRAPHICS; + struct SMU74_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + + result = polaris10_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SPLLShutdownSupport)) + smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; + + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } else { + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0)) + hightest_pcie_level_enabled++; + + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0)) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < + hightest_pcie_level_enabled ? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for (i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + + +static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + uint32_t mclk_stutter_mode_threshold = 40000; + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; + else + vdd_dep_table = table_info->vdd_dep_on_mclk; + + if (vdd_dep_table) { + result = polaris10_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, clock, + &mem_level->MinVoltage, &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + mem_level->MclkFrequency = clock; + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst; + mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = data->current_profile_setting.mclk_activity; + mem_level->StutterEnable = false; + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + if (mclk_stutter_mode_threshold && + (clock <= mclk_stutter_mode_threshold) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + return result; +} + +static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) * + SMU74_MAX_LEVELS_MEMORY; + struct SMU74_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = polaris10_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + if (i == dpm_table->mclk_table.count - 1) { + levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + levels[i].EnabledForActivity = 1; + } + if (result) + return result; + } + + /* In order to prevent MC activity from stutter mode to push DPM up, + * the UVD change complements this by putting the MCLK in + * a higher state by default such that we are not affected by + * up threshold or and MCLK DPM latency. + */ + levels[0].ActivityLevel = 0x1f; + CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = 0; + uint32_t sclk_frequency; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMIO_Pattern vol_level; + uint32_t mvdd; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + sclk_frequency = data->vbios_boot_state.sclk_bootup_value; + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + sclk_frequency, + &table->ACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDC voltage value " + "in Clock Dependency Table", + ); + + result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency, &(table->ACPILevel.SclkSetting)); + PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result); + + table->ACPILevel.DeepSleepDivId = 0; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); + + + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + &table->MemoryACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value " + "in Clock Dependency Table", + ); + + if (!((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled))) + polaris10_populate_mvdd_value(hwmgr, + data->dpm_table.mclk_table.dpm_levels[0].value, + &vol_level); + + if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level)) + table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); + else + table->MemoryACPILevel.MinMvdd = 0; + + table->MemoryACPILevel.StutterEnable = false; + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage = 0; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + + table->VceLevel[count].MinVoltage |= + (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burst_time; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = (uint8_t)burst_time; + + return 0; +} + +static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct SMU74_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { + result = polaris10_populate_memory_timing_parameters(hwmgr, + hw_data->dpm_table.sclk_table.dpm_levels[i].value, + hw_data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result == 0) + result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j); + if (result != 0) + return result; + } + } + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU74_Discrete_MCArbDramTimingTable), + SMC_RAM_END); + return result; +} + +static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].MinVoltage = 0; + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + } + + return result; +} + +static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_sclk->entries[level].clk >= + hw_data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_mclk->entries[level].clk >= + hw_data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + uint8_t i, stretch_amount, volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (67 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + + if (hwmgr->chip_id == CHIP_POLARIS10) { + if (hwmgr->is_kicker) { + min = 1200; + max = 2500; + } else { + min = 1000; + max = 2300; + } + } else if (hwmgr->chip_id == CHIP_POLARIS11) { + if (hwmgr->is_kicker) { + min = 900; + max = 2100; + } else { + min = 1100; + max = 2100; + } + } else { + min = 1100; + max = 2100; + } + + ro = efuse * (max - min) / 255 + min; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + if (hwmgr->chip_id == CHIP_POLARIS10) { + volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \ + (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); + volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \ + (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); + } else { + volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \ + (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000))); + volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \ + (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000))); + } + + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); + + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; + /* Populate CKS Lookup Table */ + if (stretch_amount == 0 || stretch_amount > 5) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!", + ); + } + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + + offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + + +static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + int result = 0; + struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; + AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; + AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; + uint32_t tmp, i; + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + + if (!hwmgr->avfs_supported) + return 0; + + result = atomctrl_get_avfs_information(hwmgr, &avfs_params); + + if (0 == result) { + if (((adev->pdev->device == 0x67ef) && + ((adev->pdev->revision == 0xe0) || + (adev->pdev->revision == 0xe5))) || + ((adev->pdev->device == 0x67ff) && + ((adev->pdev->revision == 0xcf) || + (adev->pdev->revision == 0xef) || + (adev->pdev->revision == 0xff)))) { + avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; + if ((adev->pdev->device == 0x67ef && adev->pdev->revision == 0xe5) || + (adev->pdev->device == 0x67ff && adev->pdev->revision == 0xef)) { + if ((avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 == 0xEA522DD3) && + (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 == 0x5645A) && + (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 == 0x33F9E) && + (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 == 0xFFFFC5CC) && + (avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 == 0x1B1A) && + (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b == 0xFFFFFCED)) { + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF718F1D4; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x323FD; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x1E455; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; + avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x23; + } + } + } else if (hwmgr->chip_id == CHIP_POLARIS12 && !hwmgr->is_kicker) { + avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF6B024DD; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x3005E; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x18A5F; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0x315; + avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFED1; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x3B; + } else if (((adev->pdev->device == 0x67df) && + ((adev->pdev->revision == 0xe0) || + (adev->pdev->revision == 0xe3) || + (adev->pdev->revision == 0xe4) || + (adev->pdev->revision == 0xe5) || + (adev->pdev->revision == 0xe7) || + (adev->pdev->revision == 0xef))) || + ((adev->pdev->device == 0x6fdf) && + ((adev->pdev->revision == 0xef) || + (adev->pdev->revision == 0xff)))) { + avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF843B66B; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x59CB5; + avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0xFFFF287F; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; + avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFF23; + avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x58; + } + } + + if (0 == result) { + table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); + table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); + table->BTCGB_VDROOP_TABLE[0].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); + table->BTCGB_VDROOP_TABLE[1].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); + table->BTCGB_VDROOP_TABLE[1].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); + table->BTCGB_VDROOP_TABLE[1].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); + table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); + table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); + table->AVFSGB_VDROOP_TABLE[0].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); + table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24; + table->AVFSGB_VDROOP_TABLE[0].m2_shift = 12; + table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); + table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); + table->AVFSGB_VDROOP_TABLE[1].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); + table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24; + table->AVFSGB_VDROOP_TABLE[1].m2_shift = 12; + table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); + AVFS_meanNsigma.Aconstant[0] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); + AVFS_meanNsigma.Aconstant[1] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); + AVFS_meanNsigma.Aconstant[2] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); + AVFS_meanNsigma.DC_tol_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); + AVFS_meanNsigma.Platform_mean = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); + AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); + AVFS_meanNsigma.Platform_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); + + for (i = 0; i < NUM_VFT_COLUMNS; i++) { + AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); + AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100); + } + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma), + &tmp, SMC_RAM_END); + + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_meanNsigma, + sizeof(AVFS_meanNsigma_t), + SMC_RAM_END); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable), + &tmp, SMC_RAM_END); + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_SclkOffset, + sizeof(AVFS_Sclk_Offset_t), + SMC_RAM_END); + + data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); + data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; + } + return result; +} + +static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + + /* This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + +static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &polaris10_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0]; + +} + +static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + pp_atomctrl_clock_dividers_vi dividers; + + polaris10_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) + polaris10_populate_smc_voltage_tables(hwmgr, table); + + table->SystemFlags = 0; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (hw_data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = polaris10_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); + } + + result = polaris10_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = polaris10_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = polaris10_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = polaris10_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = polaris10_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = polaris10_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = polaris10_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + result = polaris10_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = polaris10_populate_smc_initailial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot State!", return result); + + result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = polaris10_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + result = polaris10_populate_avfs_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;); + + table->CurrSclkPllRange = 0xff; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; + table->PCIeGenInterval = 1; + table->VRConfig = 0; + + result = polaris10_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + hw_data->vr_config = table->VRConfig; + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, + &gpio_pin)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) + & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot) + && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + /* Populate BIF_SCLK levels into SMC DPM table */ + for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], ÷rs); + PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result); + + if (i == 0) + table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); + else + table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); + } + + for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController), + SMC_RAM_END); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result); + + result = polaris10_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload arb data to SMC memory!", return result); + + result = polaris10_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + return 0; +} + +static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return polaris10_program_memory_timing_parameters(hwmgr); + + return 0; +} + +int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (!hwmgr->avfs_supported) + return 0; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting, + NULL); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); + + /* Apply avfs cks-off voltages to avoid the overshoot + * when switching to the highest sclk frequency + */ + if (data->apply_avfs_cks_off_voltage) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ApplyAvfsCksOffVoltage, NULL); + + return 0; +} + +static int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (smu_data->smu7_data.fan_table_start == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + /* use hardware fan control */ + if (hwmgr->thermal_controller.use_hw_fan_control) + return 0; + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. + usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr-> + thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> + thermal_controller.advanceFanControlParameters.ulCycleDelay * + reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanMinPwm, + hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit, + NULL); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanSclkTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit, + NULL); + + if (res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + return 0; +} + +static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, + UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), + NULL); + return 0; +} + +static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + else + smu_data->smc_state_table.VceBootLevel = 0; + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, + NULL); + return 0; +} + +static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + int max_entry, i; + + max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ? + SMU74_MAX_LEVELS_LINK : + pcie_table->count; + /* Setup BIF_SCLK levels */ + for (i = 0; i < max_entry; i++) + smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; + return 0; +} + +static int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + polaris10_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + polaris10_update_vce_smc_table(hwmgr); + break; + case SMU_BIF_TABLE: + polaris10_update_bif_smc_table(hwmgr); + default: + break; + } + return 0; +} + +static int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + PP_ASSERT_WITH_CODE((result == 0), + "Failed to update SCLK threshold!", return result); + + result = polaris10_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU74_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity); + case AverageMemoryActivity: + return offsetof(SMU74_SoftRegisters, AverageMemoryActivity); + case PreVBlankGap: + return offsetof(SMU74_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU74_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU74_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU74_Discrete_DpmTable, VceBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold); + } + break; + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t polaris10_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU74_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU74_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU74_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU74_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU74_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU74_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU74_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU74_MAX_LEVELS_MVDD; + case SMU_UVD_MCLK_HANDSHAKE_DISABLE: + return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + +static int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int polaris10_update_dpm_settings(struct pp_hwmgr *hwmgr, + void *profile_setting) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) + (hwmgr->smu_backend); + struct profile_mode_setting *setting; + struct SMU74_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + + uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); + struct SMU74_Discrete_MemoryLevel *mclk_levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; + + if (profile_setting == NULL) + return -EINVAL; + + setting = (struct profile_mode_setting *)profile_setting; + + if (setting->bupdate_sclk) { + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + if (levels[i].ActivityLevel != + cpu_to_be16(setting->sclk_activity)) { + levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); + + clk_activity_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) + + offsetof(SMU74_Discrete_GraphicsLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (levels[i].UpHyst != setting->sclk_up_hyst || + levels[i].DownHyst != setting->sclk_down_hyst) { + levels[i].UpHyst = setting->sclk_up_hyst; + levels[i].DownHyst = setting->sclk_down_hyst; + up_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) + + offsetof(SMU74_Discrete_GraphicsLevel, UpHyst); + down_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) + + offsetof(SMU74_Discrete_GraphicsLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); + } + + if (setting->bupdate_mclk) { + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { + if (mclk_levels[i].ActivityLevel != + cpu_to_be16(setting->mclk_activity)) { + mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); + + clk_activity_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) + + offsetof(SMU74_Discrete_MemoryLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || + mclk_levels[i].DownHyst != setting->mclk_down_hyst) { + mclk_levels[i].UpHyst = setting->mclk_up_hyst; + mclk_levels[i].DownHyst = setting->mclk_down_hyst; + up_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) + + offsetof(SMU74_Discrete_MemoryLevel, UpHyst); + down_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) + + offsetof(SMU74_Discrete_MemoryLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); + } + return 0; +} + +const struct pp_smumgr_func polaris10_smu_funcs = { + .name = "polaris10_smu", + .smu_init = polaris10_smu_init, + .smu_fini = smu7_smu_fini, + .start_smu = polaris10_start_smu, + .check_fw_load_finish = smu7_check_fw_load_finish, + .request_smu_load_fw = smu7_reload_firmware, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = smu7_send_msg_to_smc, + .send_msg_to_smc_with_parameter = smu7_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .update_smc_table = polaris10_update_smc_table, + .get_offsetof = polaris10_get_offsetof, + .process_firmware_header = polaris10_process_firmware_header, + .init_smc_table = polaris10_init_smc_table, + .update_sclk_threshold = polaris10_update_sclk_threshold, + .thermal_avfs_enable = polaris10_thermal_avfs_enable, + .thermal_setup_fan_table = polaris10_thermal_setup_fan_table, + .populate_all_graphic_levels = polaris10_populate_all_graphic_levels, + .populate_all_memory_levels = polaris10_populate_all_memory_levels, + .get_mac_definition = polaris10_get_mac_definition, + .is_dpm_running = polaris10_is_dpm_running, + .is_hw_avfs_present = polaris10_is_hw_avfs_present, + .update_dpm_settings = polaris10_update_dpm_settings, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h new file mode 100644 index 000000000000..1ec425df9eda --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/polaris10_smumgr.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015 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 _POLARIS10_SMUMANAGER_H +#define _POLARIS10_SMUMANAGER_H + + +#include +#include "smu74.h" +#include "smu74_discrete.h" +#include "smu7_smumgr.h" + +#define SMC_RAM_END 0x40000 + +struct polaris10_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; + + uint32_t DisplayCac; + uint32_t BAPM_TEMP_GRADIENT; + uint16_t BAPMTI_R[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; + uint16_t BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; +}; + +struct polaris10_range_table { + uint32_t trans_lower_frequency; /* in 10khz */ + uint32_t trans_upper_frequency; +}; + +struct polaris10_smumgr { + struct smu7_smumgr smu7_data; + uint8_t protected_mode; + SMU74_Discrete_DpmTable smc_state_table; + struct SMU74_Discrete_Ulv ulv_setting; + struct SMU74_Discrete_PmFuses power_tune_table; + struct polaris10_range_table range_table[NUM_SCLK_RANGE]; + const struct polaris10_pt_defaults *power_tune_defaults; + uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK]; +}; + + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c new file mode 100644 index 000000000000..ea2279bb8cbf --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.c @@ -0,0 +1,322 @@ +/* + * Copyright 2016 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 + +#include "smumgr.h" +#include "smu10_inc.h" +#include "soc15_common.h" +#include "smu10_smumgr.h" +#include "ppatomctrl.h" +#include "rv_ppsmc.h" +#include "smu10_driver_if.h" +#include "smu10.h" +#include "pp_debug.h" + + +#define BUFFER_SIZE 80000 +#define MAX_STRING_SIZE 15 +#define BUFFER_SIZETWO 131072 + +#define MP0_Public 0x03800000 +#define MP0_SRAM 0x03900000 +#define MP1_Public 0x03b00000 +#define MP1_SRAM 0x03c00004 + +#define smnMP1_FIRMWARE_FLAGS 0x3010028 + + +static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t reg; + + reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); + + phm_wait_for_register_unequal(hwmgr, reg, + 0, MP1_C2PMSG_90__CONTENT_MASK); + + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); +} + +static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, + uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); + + return 0; +} + +static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); +} + +static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + + smu10_wait_for_response(hwmgr); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + smu10_send_msg_to_smc_without_waiting(hwmgr, msg); + + if (smu10_wait_for_response(hwmgr) == 0) + printk("Failed to send Message %x.\n", msg); + + return 0; +} + + +static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + struct amdgpu_device *adev = hwmgr->adev; + + smu10_wait_for_response(hwmgr); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); + + smu10_send_msg_to_smc_without_waiting(hwmgr, msg); + + + if (smu10_wait_for_response(hwmgr) == 0) + printk("Failed to send Message %x.\n", msg); + + return 0; +} + +static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct smu10_smumgr *priv = + (struct smu10_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, + "Invalid SMU Table ID!", return -EINVAL;); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL;); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL;); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableSmu2Dram, + priv->smu_tables.entry[table_id].table_id, + NULL); + + /* flush hdp cache */ + amdgpu_asic_flush_hdp(adev, NULL); + + memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table, + priv->smu_tables.entry[table_id].size); + + return 0; +} + +static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct smu10_smumgr *priv = + (struct smu10_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, + "Invalid SMU Table ID!", return -EINVAL;); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL;); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL;); + + memcpy(priv->smu_tables.entry[table_id].table, table, + priv->smu_tables.entry[table_id].size); + + amdgpu_asic_flush_hdp(adev, NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableDram2Smu, + priv->smu_tables.entry[table_id].table_id, + NULL); + + return 0; +} + +static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr) +{ + uint32_t smc_driver_if_version; + + smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetDriverIfVersion, + &smc_driver_if_version); + + if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) && + (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) { + pr_err("Attempt to read SMC IF Version Number Failed!\n"); + return -EINVAL; + } + + return 0; +} + +static int smu10_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct smu10_smumgr *priv = + (struct smu10_smumgr *)(hwmgr->smu_backend); + + if (priv) { + amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, + &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, + &priv->smu_tables.entry[SMU10_WMTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, + &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, + &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + } + + return 0; +} + +static int smu10_start_smu(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version); + adev->pm.fw_version = hwmgr->smu_version >> 8; + + if (!(adev->apu_flags & AMD_APU_IS_RAVEN2) && + (adev->apu_flags & AMD_APU_IS_RAVEN) && + adev->pm.fw_version < 0x1e45) + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + + if (smu10_verify_smc_interface(hwmgr)) + return -EINVAL; + + return 0; +} + +static int smu10_smu_init(struct pp_hwmgr *hwmgr) +{ + struct smu10_smumgr *priv; + int r; + + priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL); + + if (!priv) + return -ENOMEM; + + hwmgr->smu_backend = priv; + + /* allocate space for watermarks table */ + r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(Watermarks_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[SMU10_WMTABLE].handle, + &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, + &priv->smu_tables.entry[SMU10_WMTABLE].table); + + if (r) + goto err0; + + priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01; + priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t); + priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS; + + /* allocate space for watermarks table */ + r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(DpmClocks_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, + &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, + &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); + + if (r) + goto err1; + + priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01; + priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t); + priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS; + + return 0; + +err1: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, + &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, + &priv->smu_tables.entry[SMU10_WMTABLE].table); +err0: + kfree(priv); + return -EINVAL; +} + +static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) +{ + int ret; + + if (rw) + ret = smu10_copy_table_from_smc(hwmgr, table, table_id); + else + ret = smu10_copy_table_to_smc(hwmgr, table, table_id); + + return ret; +} + + +const struct pp_smumgr_func smu10_smu_funcs = { + .name = "smu10_smu", + .smu_init = &smu10_smu_init, + .smu_fini = &smu10_smu_fini, + .start_smu = &smu10_start_smu, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &smu10_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .get_argument = smu10_read_arg_from_smc, + .smc_table_manager = smu10_smc_table_manager, +}; + + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h new file mode 100644 index 000000000000..9c2be74a2b2f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu10_smumgr.h @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef PP_SMU10_SMUMANAGER_H +#define PP_SMU10_SMUMANAGER_H + +#include "rv_ppsmc.h" +#include "smu10_driver_if.h" + +#define MAX_SMU_TABLE 2 + +struct smu_table_entry { + uint32_t version; + uint32_t size; + uint32_t table_id; + uint64_t mc_addr; + void *table; + struct amdgpu_bo *handle; +}; + +struct smu_table_array { + struct smu_table_entry entry[MAX_SMU_TABLE]; +}; + +struct smu10_smumgr { + struct smu_table_array smu_tables; +}; + + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c new file mode 100644 index 000000000000..aae25243eb10 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c @@ -0,0 +1,601 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include "smumgr.h" +#include "smu_ucode_xfer_vi.h" +#include "ppatomctrl.h" +#include "cgs_common.h" +#include "smu7_ppsmc.h" +#include "smu7_smumgr.h" +#include "smu7_common.h" + +#include "polaris10_pwrvirus.h" + +#define SMU7_SMC_SIZE 0x20000 + +static int smu7_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t limit) +{ + PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL); + PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL); + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, smc_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */ + return 0; +} + + +int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit) +{ + uint32_t data; + uint32_t addr; + uint8_t *dest_byte; + uint8_t i, data_byte[4] = {0}; + uint32_t *pdata = (uint32_t *)&data_byte; + + PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL); + PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL); + + addr = smc_start_address; + + while (byte_count >= 4) { + smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); + + *dest = PP_SMC_TO_HOST_UL(data); + + dest += 1; + byte_count -= 4; + addr += 4; + } + + if (byte_count) { + smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); + *pdata = PP_SMC_TO_HOST_UL(data); + /* Cast dest into byte type in dest_byte. This way, we don't overflow if the allocated memory is not 4-byte aligned. */ + dest_byte = (uint8_t *)dest; + for (i = 0; i < byte_count; i++) + dest_byte[i] = data_byte[i]; + } + + return 0; +} + + +int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + const uint8_t *src, uint32_t byte_count, uint32_t limit) +{ + int result; + uint32_t data = 0; + uint32_t original_data; + uint32_t addr = 0; + uint32_t extra_shift; + + PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL); + PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL); + + addr = smc_start_address; + + while (byte_count >= 4) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + + result = smu7_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + if (0 != byte_count) { + + data = 0; + + result = smu7_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + + original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = (0x100 * data) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + result = smu7_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); + } + + return 0; +} + + +int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr) +{ + static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; + + smu7_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); + + return 0; +} + +bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + int ret; + + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); + + if (ret == 0xFE) + pr_debug("last message was not supported\n"); + else if (ret != 1) + pr_info("\n last message was failed ret is %d\n", ret); + + cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); + + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); + + if (ret == 0xFE) + pr_debug("message %x was not supported\n", msg); + else if (ret != 1) + pr_info("\n failed to send message %x ret is %d \n", msg, ret); + + return 0; +} + +int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) +{ + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); + + return smu7_send_msg_to_smc(hwmgr, msg); +} + +uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr) +{ + return cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); +} + +int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL); +} + +enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type) +{ + enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; + + switch (fw_type) { + case UCODE_ID_SMU: + result = CGS_UCODE_ID_SMU; + break; + case UCODE_ID_SMU_SK: + result = CGS_UCODE_ID_SMU_SK; + break; + case UCODE_ID_SDMA0: + result = CGS_UCODE_ID_SDMA0; + break; + case UCODE_ID_SDMA1: + result = CGS_UCODE_ID_SDMA1; + break; + case UCODE_ID_CP_CE: + result = CGS_UCODE_ID_CP_CE; + break; + case UCODE_ID_CP_PFP: + result = CGS_UCODE_ID_CP_PFP; + break; + case UCODE_ID_CP_ME: + result = CGS_UCODE_ID_CP_ME; + break; + case UCODE_ID_CP_MEC: + result = CGS_UCODE_ID_CP_MEC; + break; + case UCODE_ID_CP_MEC_JT1: + result = CGS_UCODE_ID_CP_MEC_JT1; + break; + case UCODE_ID_CP_MEC_JT2: + result = CGS_UCODE_ID_CP_MEC_JT2; + break; + case UCODE_ID_RLC_G: + result = CGS_UCODE_ID_RLC_G; + break; + case UCODE_ID_MEC_STORAGE: + result = CGS_UCODE_ID_STORAGE; + break; + default: + break; + } + + return result; +} + + +int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit) +{ + int result; + + result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); + + *value = result ? 0 : cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); + + return result; +} + +int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit) +{ + int result; + + result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); + + if (result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value); + + return 0; +} + +static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr, + uint32_t fw_type, + struct SMU_Entry *entry) +{ + int result = 0; + struct cgs_firmware_info info = {0}; + + result = cgs_get_firmware_info(hwmgr->device, + smu7_convert_fw_type_to_cgs(fw_type), + &info); + + if (!result) { + entry->version = info.fw_version; + entry->id = (uint16_t)fw_type; + entry->image_addr_high = upper_32_bits(info.mc_addr); + entry->image_addr_low = lower_32_bits(info.mc_addr); + entry->meta_data_addr_high = 0; + entry->meta_data_addr_low = 0; + + /* digest need be excluded out */ + if (!hwmgr->not_vf) + info.image_size -= 20; + entry->data_size_byte = info.image_size; + entry->num_register_entries = 0; + } + + if ((fw_type == UCODE_ID_RLC_G) + || (fw_type == UCODE_ID_CP_MEC)) + entry->flags = 1; + else + entry->flags = 0; + + return 0; +} + +int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + uint32_t fw_to_load; + int r = 0; + + amdgpu_ucode_init_bo(hwmgr->adev); + + if (smu_data->soft_regs_start) + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + smu_data->soft_regs_start + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, UcodeLoadStatus), + 0x0); + + if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */ + if (hwmgr->not_vf) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SMU_DRAM_ADDR_HI, + upper_32_bits(smu_data->smu_buffer.mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SMU_DRAM_ADDR_LO, + lower_32_bits(smu_data->smu_buffer.mc_addr), + NULL); + } + fw_to_load = UCODE_ID_RLC_G_MASK + + UCODE_ID_SDMA0_MASK + + UCODE_ID_SDMA1_MASK + + UCODE_ID_CP_CE_MASK + + UCODE_ID_CP_ME_MASK + + UCODE_ID_CP_PFP_MASK + + UCODE_ID_CP_MEC_MASK; + } else { + fw_to_load = UCODE_ID_RLC_G_MASK + + UCODE_ID_SDMA0_MASK + + UCODE_ID_SDMA1_MASK + + UCODE_ID_CP_CE_MASK + + UCODE_ID_CP_ME_MASK + + UCODE_ID_CP_PFP_MASK + + UCODE_ID_CP_MEC_MASK + + UCODE_ID_CP_MEC_JT1_MASK + + UCODE_ID_CP_MEC_JT2_MASK; + } + + if (!smu_data->toc) { + struct SMU_DRAMData_TOC *toc; + + smu_data->toc = kzalloc(sizeof(struct SMU_DRAMData_TOC), GFP_KERNEL); + if (!smu_data->toc) + return -ENOMEM; + toc = smu_data->toc; + toc->num_entries = 0; + toc->structure_version = 1; + + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + if (!hwmgr->not_vf) + PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, + UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); + } + memcpy_toio(smu_data->header_buffer.kaddr, smu_data->toc, + sizeof(struct SMU_DRAMData_TOC)); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DRV_DRAM_ADDR_HI, + upper_32_bits(smu_data->header_buffer.mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DRV_DRAM_ADDR_LO, + lower_32_bits(smu_data->header_buffer.mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load, NULL); + + r = smu7_check_fw_load_finish(hwmgr, fw_to_load); + if (!r) + return 0; + + pr_err("SMU load firmware failed\n"); + +failed: + kfree(smu_data->toc); + smu_data->toc = NULL; + return r; +} + +/* Check if the FW has been loaded, SMU will not return if loading has not finished. */ +int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type) +{ + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + uint32_t ret; + + ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11, + smu_data->soft_regs_start + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, UcodeLoadStatus), + fw_type, fw_type); + return ret; +} + +int smu7_reload_firmware(struct pp_hwmgr *hwmgr) +{ + return hwmgr->smumgr_funcs->start_smu(hwmgr); +} + +static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit) +{ + uint32_t byte_count = length; + + PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1); + + for (; byte_count >= 4; byte_count -= 4) + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++); + + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); + + PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); + + return 0; +} + + +int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + struct cgs_firmware_info info = {0}; + + if (smu_data->security_hard_key == 1) + cgs_get_firmware_info(hwmgr->device, + smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); + else + cgs_get_firmware_info(hwmgr->device, + smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info); + + hwmgr->is_kicker = info.is_kicker; + hwmgr->smu_version = info.version; + result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE); + + return result; +} + +static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size) +{ + int i; + uint32_t reg, data; + + for (i = 0; i < size; i++) { + reg = pvirus->reg; + data = pvirus->data; + if (reg != 0xffffffff) + cgs_write_register(hwmgr->device, reg, data); + else + break; + pvirus++; + } +} + +static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section) +{ + int i; + + cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl); + cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi); + cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo); + for (i = 0; i < section->dfy_size; i++) + cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]); +} + +int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr) +{ + execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre)); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section1); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section2); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section3); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section4); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section5); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section6); + execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post)); + + return 0; +} + +int smu7_init(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu_data; + int r; + /* Allocate memory for backend private data */ + smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + smu_data->header_buffer.data_size = + ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; + +/* Allocate FW image data structure and header buffer and + * send the header buffer address to SMU */ + r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + smu_data->header_buffer.data_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &smu_data->header_buffer.handle, + &smu_data->header_buffer.mc_addr, + &smu_data->header_buffer.kaddr); + + if (r) + return -EINVAL; + + if (!hwmgr->not_vf) + return 0; + + smu_data->smu_buffer.data_size = 200*4096; + r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + smu_data->smu_buffer.data_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &smu_data->smu_buffer.handle, + &smu_data->smu_buffer.mc_addr, + &smu_data->smu_buffer.kaddr); + + if (r) { + amdgpu_bo_free_kernel(&smu_data->header_buffer.handle, + &smu_data->header_buffer.mc_addr, + &smu_data->header_buffer.kaddr); + return -EINVAL; + } + + if (smum_is_hw_avfs_present(hwmgr) && + (hwmgr->feature_mask & PP_AVFS_MASK)) + hwmgr->avfs_supported = true; + + return 0; +} + + +int smu7_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + amdgpu_bo_free_kernel(&smu_data->header_buffer.handle, + &smu_data->header_buffer.mc_addr, + &smu_data->header_buffer.kaddr); + + if (hwmgr->not_vf) + amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle, + &smu_data->smu_buffer.mc_addr, + &smu_data->smu_buffer.kaddr); + + + kfree(smu_data->toc); + smu_data->toc = NULL; + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + return 0; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h new file mode 100644 index 000000000000..e7303dc8c260 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.h @@ -0,0 +1,83 @@ +/* + * Copyright 2015 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 _SMU7_SMUMANAGER_H +#define _SMU7_SMUMANAGER_H + + +#include + +#define SMC_RAM_END 0x40000 + +struct smu7_buffer_entry { + uint32_t data_size; + uint64_t mc_addr; + void *kaddr; + struct amdgpu_bo *handle; +}; + +struct smu7_smumgr { + struct smu7_buffer_entry smu_buffer; + struct smu7_buffer_entry header_buffer; + struct SMU_DRAMData_TOC *toc; + + uint32_t soft_regs_start; + uint32_t dpm_table_start; + uint32_t mc_reg_table_start; + uint32_t fan_table_start; + uint32_t arb_table_start; + uint32_t ulv_setting_starts; + uint8_t security_hard_key; + uint32_t acpi_optimization; + uint32_t avfs_btc_param; +}; + + +int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + uint32_t *dest, uint32_t byte_count, uint32_t limit); +int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + const uint8_t *src, uint32_t byte_count, uint32_t limit); +int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr); +bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr); +int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); +int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, + uint32_t parameter); +uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr); +int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr); + +enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type); +int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, + uint32_t *value, uint32_t limit); +int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, + uint32_t value, uint32_t limit); + +int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr); +int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type); +int smu7_reload_firmware(struct pp_hwmgr *hwmgr); +int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr); +int smu7_init(struct pp_hwmgr *hwmgr); +int smu7_smu_fini(struct pp_hwmgr *hwmgr); + +int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c new file mode 100644 index 000000000000..76d4f12ceedf --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.c @@ -0,0 +1,910 @@ +/* + * Copyright 2015 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 +#include +#include +#include +#include +#include + +#include "cgs_common.h" +#include "smu/smu_8_0_d.h" +#include "smu/smu_8_0_sh_mask.h" +#include "smu8.h" +#include "smu8_fusion.h" +#include "smu8_smumgr.h" +#include "cz_ppsmc.h" +#include "smu_ucode_xfer_cz.h" +#include "gca/gfx_8_0_d.h" +#include "gca/gfx_8_0_sh_mask.h" +#include "smumgr.h" + +#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32) + +static const enum smu8_scratch_entry firmware_list[] = { + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, +}; + +static uint32_t smu8_get_argument(struct pp_hwmgr *hwmgr) +{ + if (hwmgr == NULL || hwmgr->device == NULL) + return 0; + + return cgs_read_register(hwmgr->device, + mmSMU_MP1_SRBM2P_ARG_0); +} + +/* Send a message to the SMC, and wait for its response.*/ +static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + int result = 0; + ktime_t t_start; + s64 elapsed_us; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, + SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); + if (result != 0) { + /* Read the last message to SMU, to report actual cause */ + uint32_t val = cgs_read_register(hwmgr->device, + mmSMU_MP1_SRBM2P_MSG_0); + pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n", + __func__, msg, val); + return result; + } + t_start = ktime_get(); + + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); + + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); + cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); + + result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, + SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); + + elapsed_us = ktime_us_delta(ktime_get(), t_start); + + WARN(result, "%s(0x%04x, %#x) timed out after %lld us\n", + __func__, msg, parameter, elapsed_us); + + return result; +} + +static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + return smu8_send_msg_to_smc_with_parameter(hwmgr, msg, 0); +} + +static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr, + uint32_t smc_address, uint32_t limit) +{ + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + if (0 != (3 & smc_address)) { + pr_err("SMC address must be 4 byte aligned\n"); + return -EINVAL; + } + + if (limit <= (smc_address + 3)) { + pr_err("SMC address beyond the SMC RAM area\n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0, + SMN_MP1_SRAM_START_ADDR + smc_address); + + return 0; +} + +static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr, + uint32_t smc_address, uint32_t value, uint32_t limit) +{ + int result; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + result = smu8_set_smc_sram_address(hwmgr, smc_address, limit); + if (!result) + cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value); + + return result; +} + +static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr, + uint32_t firmware) +{ + int i; + uint32_t index = SMN_MP1_SRAM_START_ADDR + + SMU8_FIRMWARE_HEADER_LOCATION + + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); + + for (i = 0; i < hwmgr->usec_timeout; i++) { + if (firmware == + (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware)) + break; + udelay(1); + } + + if (i >= hwmgr->usec_timeout) { + pr_err("SMU check loaded firmware failed.\n"); + return -EINVAL; + } + + return 0; +} + +static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr) +{ + uint32_t reg_data; + uint32_t tmp; + int ret = 0; + struct cgs_firmware_info info = {0}; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + ret = cgs_get_firmware_info(hwmgr->device, + CGS_UCODE_ID_CP_MEC, &info); + + if (ret) + return -EINVAL; + + /* Disable MEC parsing/prefetching */ + tmp = cgs_read_register(hwmgr->device, + mmCP_MEC_CNTL); + tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); + tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); + cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp); + + tmp = cgs_read_register(hwmgr->device, + mmCP_CPC_IC_BASE_CNTL); + + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); + tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); + + reg_data = lower_32_bits(info.mc_addr) & + PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data); + + reg_data = upper_32_bits(info.mc_addr) & + PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); + cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data); + + return 0; +} + +static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr, + enum smu8_scratch_entry firmware_enum) +{ + uint8_t ret = 0; + + switch (firmware_enum) { + case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0: + ret = UCODE_ID_SDMA0; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1: + if (hwmgr->chip_id == CHIP_STONEY) + ret = UCODE_ID_SDMA0; + else + ret = UCODE_ID_SDMA1; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE: + ret = UCODE_ID_CP_CE; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP: + ret = UCODE_ID_CP_PFP; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME: + ret = UCODE_ID_CP_ME; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1: + ret = UCODE_ID_CP_MEC_JT1; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: + if (hwmgr->chip_id == CHIP_STONEY) + ret = UCODE_ID_CP_MEC_JT1; + else + ret = UCODE_ID_CP_MEC_JT2; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: + ret = UCODE_ID_GMCON_RENG; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G: + ret = UCODE_ID_RLC_G; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH: + ret = UCODE_ID_RLC_SCRATCH; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM: + ret = UCODE_ID_RLC_SRM_ARAM; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM: + ret = UCODE_ID_RLC_SRM_DRAM; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM: + ret = UCODE_ID_DMCU_ERAM; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM: + ret = UCODE_ID_DMCU_IRAM; + break; + case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING: + ret = TASK_ARG_INIT_MM_PWR_LOG; + break; + case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT: + case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING: + case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS: + case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT: + case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START: + case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS: + ret = TASK_ARG_REG_MMIO; + break; + case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE: + ret = TASK_ARG_INIT_CLK_TABLE; + break; + } + + return ret; +} + +static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type) +{ + enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; + + switch (fw_type) { + case UCODE_ID_SDMA0: + result = CGS_UCODE_ID_SDMA0; + break; + case UCODE_ID_SDMA1: + result = CGS_UCODE_ID_SDMA1; + break; + case UCODE_ID_CP_CE: + result = CGS_UCODE_ID_CP_CE; + break; + case UCODE_ID_CP_PFP: + result = CGS_UCODE_ID_CP_PFP; + break; + case UCODE_ID_CP_ME: + result = CGS_UCODE_ID_CP_ME; + break; + case UCODE_ID_CP_MEC_JT1: + result = CGS_UCODE_ID_CP_MEC_JT1; + break; + case UCODE_ID_CP_MEC_JT2: + result = CGS_UCODE_ID_CP_MEC_JT2; + break; + case UCODE_ID_RLC_G: + result = CGS_UCODE_ID_RLC_G; + break; + default: + break; + } + + return result; +} + +static int smu8_smu_populate_single_scratch_task( + struct pp_hwmgr *hwmgr, + enum smu8_scratch_entry fw_enum, + uint8_t type, bool is_last) +{ + uint8_t i; + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; + struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; + + task->type = type; + task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); + task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; + + for (i = 0; i < smu8_smu->scratch_buffer_length; i++) + if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum) + break; + + if (i >= smu8_smu->scratch_buffer_length) { + pr_err("Invalid Firmware Type\n"); + return -EINVAL; + } + + task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr); + task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr); + task->size_bytes = smu8_smu->scratch_buffer[i].data_size; + + if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) { + struct smu8_ih_meta_data *pIHReg_restore = + (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr; + pIHReg_restore->command = + METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD; + } + + return 0; +} + +static int smu8_smu_populate_single_ucode_load_task( + struct pp_hwmgr *hwmgr, + enum smu8_scratch_entry fw_enum, + bool is_last) +{ + uint8_t i; + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; + struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; + + task->type = TASK_TYPE_UCODE_LOAD; + task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); + task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; + + for (i = 0; i < smu8_smu->driver_buffer_length; i++) + if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum) + break; + + if (i >= smu8_smu->driver_buffer_length) { + pr_err("Invalid Firmware Type\n"); + return -EINVAL; + } + + task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr); + task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr); + task->size_bytes = smu8_smu->driver_buffer[i].data_size; + + return 0; +} + +static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + + smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count; + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + TASK_TYPE_UCODE_SAVE, true); + + return 0; +} + +static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr) +{ + int i; + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; + + for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) + toc->JobList[i] = (uint8_t)IGNORE_JOB; + + return 0; +} + +static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; + + toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count; + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + TASK_TYPE_UCODE_SAVE, false); + + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + TASK_TYPE_UCODE_SAVE, true); + + return 0; +} + + +static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; + + toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count; + + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + + if (hwmgr->chip_id == CHIP_STONEY) + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + else + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); + + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); + + /* populate scratch */ + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + TASK_TYPE_UCODE_LOAD, false); + + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + TASK_TYPE_UCODE_LOAD, false); + + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + TASK_TYPE_UCODE_LOAD, true); + + return 0; +} + +static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + + smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count; + + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + TASK_TYPE_INITIALIZE, true); + return 0; +} + +static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + + smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count; + + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); + if (hwmgr->chip_id != CHIP_STONEY) + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + if (hwmgr->chip_id != CHIP_STONEY) + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); + smu8_smu_populate_single_ucode_load_task(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); + + return 0; +} + +static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + + smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count; + + smu8_smu_populate_single_scratch_task(hwmgr, + SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, + TASK_TYPE_INITIALIZE, true); + + return 0; +} + +static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + + smu8_smu->toc_entry_used_count = 0; + smu8_smu_initialize_toc_empty_job_list(hwmgr); + smu8_smu_construct_toc_for_rlc_aram_save(hwmgr); + smu8_smu_construct_toc_for_vddgfx_enter(hwmgr); + smu8_smu_construct_toc_for_vddgfx_exit(hwmgr); + smu8_smu_construct_toc_for_power_profiling(hwmgr); + smu8_smu_construct_toc_for_bootup(hwmgr); + smu8_smu_construct_toc_for_clock_table(hwmgr); + + return 0; +} + +static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + uint32_t firmware_type; + uint32_t i; + int ret; + enum cgs_ucode_id ucode_id; + struct cgs_firmware_info info = {0}; + + smu8_smu->driver_buffer_length = 0; + + for (i = 0; i < ARRAY_SIZE(firmware_list); i++) { + + firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr, + firmware_list[i]); + + ucode_id = smu8_convert_fw_type_to_cgs(firmware_type); + + ret = cgs_get_firmware_info(hwmgr->device, + ucode_id, &info); + + if (ret == 0) { + smu8_smu->driver_buffer[i].mc_addr = info.mc_addr; + + smu8_smu->driver_buffer[i].data_size = info.image_size; + + smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i]; + smu8_smu->driver_buffer_length++; + } + } + + return 0; +} + +static int smu8_smu_populate_single_scratch_entry( + struct pp_hwmgr *hwmgr, + enum smu8_scratch_entry scratch_type, + uint32_t ulsize_byte, + struct smu8_buffer_entry *entry) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte); + + entry->data_size = ulsize_byte; + entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr + + smu8_smu->smu_buffer_used_bytes; + entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes; + entry->firmware_ID = scratch_type; + + smu8_smu->smu_buffer_used_bytes += ulsize_aligned; + + return 0; +} + +static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + unsigned long i; + + for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { + if (smu8_smu->scratch_buffer[i].firmware_ID + == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) + break; + } + + *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetClkTableAddrHi, + upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetClkTableAddrLo, + lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, + smu8_smu->toc_entry_clock_table, + NULL); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram, NULL); + + return 0; +} + +static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + unsigned long i; + + for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { + if (smu8_smu->scratch_buffer[i].firmware_ID + == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) + break; + } + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetClkTableAddrHi, + upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetClkTableAddrLo, + lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, + smu8_smu->toc_entry_clock_table, + NULL); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu, NULL); + + return 0; +} + +static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; + uint32_t smc_address; + uint32_t fw_to_check = 0; + int ret; + + amdgpu_ucode_init_bo(hwmgr->adev); + + smu8_smu_populate_firmware_entries(hwmgr); + + smu8_smu_construct_toc(hwmgr); + + smc_address = SMU8_FIRMWARE_HEADER_LOCATION + + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); + + smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DriverDramAddrHi, + upper_32_bits(smu8_smu->toc_buffer.mc_addr), + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DriverDramAddrLo, + lower_32_bits(smu8_smu->toc_buffer.mc_addr), + NULL); + + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs, NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_ExecuteJob, + smu8_smu->toc_entry_aram, + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, + smu8_smu->toc_entry_power_profiling_index, + NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_ExecuteJob, + smu8_smu->toc_entry_initialize_index, + NULL); + + fw_to_check = UCODE_ID_RLC_G_MASK | + UCODE_ID_SDMA0_MASK | + UCODE_ID_SDMA1_MASK | + UCODE_ID_CP_CE_MASK | + UCODE_ID_CP_ME_MASK | + UCODE_ID_CP_PFP_MASK | + UCODE_ID_CP_MEC_JT1_MASK | + UCODE_ID_CP_MEC_JT2_MASK; + + if (hwmgr->chip_id == CHIP_STONEY) + fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); + + ret = smu8_check_fw_load_finish(hwmgr, fw_to_check); + if (ret) { + pr_err("SMU firmware load failed\n"); + return ret; + } + + ret = smu8_load_mec_firmware(hwmgr); + if (ret) { + pr_err("Mec Firmware load failed\n"); + return ret; + } + + return 0; +} + +static int smu8_start_smu(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev; + + uint32_t index = SMN_MP1_SRAM_START_ADDR + + SMU8_FIRMWARE_HEADER_LOCATION + + offsetof(struct SMU8_Firmware_Header, Version); + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + adev = hwmgr->adev; + + cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); + hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA); + pr_info("smu version %02d.%02d.%02d\n", + ((hwmgr->smu_version >> 16) & 0xFF), + ((hwmgr->smu_version >> 8) & 0xFF), + (hwmgr->smu_version & 0xFF)); + adev->pm.fw_version = hwmgr->smu_version >> 8; + + return smu8_request_smu_load_fw(hwmgr); +} + +static int smu8_smu_init(struct pp_hwmgr *hwmgr) +{ + int ret = 0; + struct smu8_smumgr *smu8_smu; + + smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL); + if (smu8_smu == NULL) + return -ENOMEM; + + hwmgr->smu_backend = smu8_smu; + + smu8_smu->toc_buffer.data_size = 4096; + smu8_smu->smu_buffer.data_size = + ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) + + ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) + + ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) + + ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + + ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); + + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + smu8_smu->toc_buffer.data_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &smu8_smu->toc_buffer.handle, + &smu8_smu->toc_buffer.mc_addr, + &smu8_smu->toc_buffer.kaddr); + if (ret) + goto err2; + + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + smu8_smu->smu_buffer.data_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &smu8_smu->smu_buffer.handle, + &smu8_smu->smu_buffer.mc_addr, + &smu8_smu->smu_buffer.kaddr); + if (ret) + goto err1; + + if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + UCODE_ID_RLC_SCRATCH_SIZE_BYTE, + &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { + pr_err("Error when Populate Firmware Entry.\n"); + goto err0; + } + + if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, + &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { + pr_err("Error when Populate Firmware Entry.\n"); + goto err0; + } + if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, + &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { + pr_err("Error when Populate Firmware Entry.\n"); + goto err0; + } + + if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, + SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + sizeof(struct SMU8_MultimediaPowerLogData), + &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { + pr_err("Error when Populate Firmware Entry.\n"); + goto err0; + } + + if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, + SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, + sizeof(struct SMU8_Fusion_ClkTable), + &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { + pr_err("Error when Populate Firmware Entry.\n"); + goto err0; + } + + return 0; + +err0: + amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, + &smu8_smu->smu_buffer.mc_addr, + &smu8_smu->smu_buffer.kaddr); +err1: + amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, + &smu8_smu->toc_buffer.mc_addr, + &smu8_smu->toc_buffer.kaddr); +err2: + kfree(smu8_smu); + return -EINVAL; +} + +static int smu8_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct smu8_smumgr *smu8_smu; + + if (hwmgr == NULL || hwmgr->device == NULL) + return -EINVAL; + + smu8_smu = hwmgr->smu_backend; + if (smu8_smu) { + amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, + &smu8_smu->toc_buffer.mc_addr, + &smu8_smu->toc_buffer.kaddr); + amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, + &smu8_smu->smu_buffer.mc_addr, + &smu8_smu->smu_buffer.kaddr); + kfree(smu8_smu); + } + + return 0; +} + +static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr, + unsigned long check_feature) +{ + int result; + uint32_t features; + + result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetFeatureStatus, + 0, + &features); + if (result == 0) { + if (features & check_feature) + return true; + } + + return false; +} + +static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn)) + return true; + return false; +} + +const struct pp_smumgr_func smu8_smu_funcs = { + .name = "smu8_smu", + .smu_init = smu8_smu_init, + .smu_fini = smu8_smu_fini, + .start_smu = smu8_start_smu, + .check_fw_load_finish = smu8_check_fw_load_finish, + .request_smu_load_fw = NULL, + .request_smu_load_specific_fw = NULL, + .get_argument = smu8_get_argument, + .send_msg_to_smc = smu8_send_msg_to_smc, + .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter, + .download_pptable_settings = smu8_download_pptable_settings, + .upload_pptable_settings = smu8_upload_pptable_settings, + .is_dpm_running = smu8_is_dpm_running, +}; + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h new file mode 100644 index 000000000000..c7b61222d258 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu8_smumgr.h @@ -0,0 +1,99 @@ +/* + * Copyright 2015 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 _SMU8_SMUMGR_H_ +#define _SMU8_SMUMGR_H_ + + +#define MAX_NUM_FIRMWARE 8 +#define MAX_NUM_SCRATCH 11 +#define SMU8_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024 +#define SMU8_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048 +#define SMU8_SCRATCH_SIZE_SDMA_METADATA 1024 +#define SMU8_SCRATCH_SIZE_IH ((2*256+1)*4) + +#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000 + +enum smu8_scratch_entry { + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0, + SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, + SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, + SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM, + SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM, + SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT, + SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING, + SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS, + SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT, + SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START, + SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS, + SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE +}; + +struct smu8_buffer_entry { + uint32_t data_size; + uint64_t mc_addr; + void *kaddr; + enum smu8_scratch_entry firmware_ID; + struct amdgpu_bo *handle; /* as bo handle used when release bo */ +}; + +struct smu8_register_index_data_pair { + uint32_t offset; + uint32_t value; +}; + +struct smu8_ih_meta_data { + uint32_t command; + struct smu8_register_index_data_pair register_index_value_pair[1]; +}; + +struct smu8_smumgr { + uint8_t driver_buffer_length; + uint8_t scratch_buffer_length; + uint16_t toc_entry_used_count; + uint16_t toc_entry_initialize_index; + uint16_t toc_entry_power_profiling_index; + uint16_t toc_entry_aram; + uint16_t toc_entry_ih_register_restore_task_index; + uint16_t toc_entry_clock_table; + uint16_t ih_register_restore_task_size; + uint16_t smu_buffer_used_bytes; + + struct smu8_buffer_entry toc_buffer; + struct smu8_buffer_entry smu_buffer; + struct smu8_buffer_entry firmware_buffer; + struct smu8_buffer_entry driver_buffer[MAX_NUM_FIRMWARE]; + struct smu8_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE]; + struct smu8_buffer_entry scratch_buffer[MAX_NUM_SCRATCH]; +}; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c new file mode 100644 index 000000000000..adfbcbe5d113 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.c @@ -0,0 +1,180 @@ +/* + * Copyright 2018 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 "smumgr.h" +#include "vega10_inc.h" +#include "soc15_common.h" +#include "pp_debug.h" + + +/* MP Apertures */ +#define MP0_Public 0x03800000 +#define MP0_SRAM 0x03900000 +#define MP1_Public 0x03b00000 +#define MP1_SRAM 0x03c00004 + +#define smnMP1_FIRMWARE_FLAGS 0x3010028 + +bool smu9_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t mp1_fw_flags; + + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + + if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) + return true; + + return false; +} + +/* + * Check if SMC has responded to previous message. + * + * @param smumgr the address of the powerplay hardware manager. + * @return TRUE SMC has responded, FALSE otherwise. + */ +static uint32_t smu9_wait_for_response(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t reg; + uint32_t ret; + + /* Due to the L1 policy problem under SRIOV, we have to use + * mmMP1_SMN_C2PMSG_103 as the driver response register + */ + if (hwmgr->pp_one_vf) { + reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_103); + + ret = phm_wait_for_register_unequal(hwmgr, reg, + 0, MP1_C2PMSG_103__CONTENT_MASK); + + if (ret) + pr_err("No response from smu\n"); + + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103); + } else { + reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); + + ret = phm_wait_for_register_unequal(hwmgr, reg, + 0, MP1_C2PMSG_90__CONTENT_MASK); + + if (ret) + pr_err("No response from smu\n"); + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); + } +} + +/* + * Send a message to the SMC, and do not wait for its response. + * @param smumgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ +static int smu9_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, + uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (hwmgr->pp_one_vf) { + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_101, msg); + } else { + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); + } + + return 0; +} + +/* + * Send a message to the SMC, and wait for its response. + * @param hwmgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ +int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t ret; + + smu9_wait_for_response(hwmgr); + + if (hwmgr->pp_one_vf) + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0); + else + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + smu9_send_msg_to_smc_without_waiting(hwmgr, msg); + + ret = smu9_wait_for_response(hwmgr); + if (ret != 1) + pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret); + + return 0; +} + +/* + * Send a message to the SMC with parameter + * @param hwmgr: the address of the powerplay hardware manager. + * @param msg: the message to send. + * @param parameter: the parameter to send + * @return Always return 0. + */ +int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t ret; + + smu9_wait_for_response(hwmgr); + + /* Due to the L1 policy problem under SRIOV, we have to use + * mmMP1_SMN_C2PMSG_101 as the driver message register and + * mmMP1_SMN_C2PMSG_102 as the driver parameter register. + */ + if (hwmgr->pp_one_vf) { + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0); + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102, parameter); + } else { + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); + } + + smu9_send_msg_to_smc_without_waiting(hwmgr, msg); + + ret = smu9_wait_for_response(hwmgr); + if (ret != 1) + pr_err("Failed message: 0x%x, input parameter: 0x%x, error code: 0x%x\n", msg, parameter, ret); + + return 0; +} + +uint32_t smu9_get_argument(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + if (hwmgr->pp_one_vf) + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102); + else + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h new file mode 100644 index 000000000000..1462279ca128 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu9_smumgr.h @@ -0,0 +1,32 @@ +/* + * Copyright 2018 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 _SMU9_SMUMANAGER_H_ +#define _SMU9_SMUMANAGER_H_ + +bool smu9_is_smc_ram_running(struct pp_hwmgr *hwmgr); +int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); +int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter); +uint32_t smu9_get_argument(struct pp_hwmgr *hwmgr); + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c new file mode 100644 index 000000000000..b6fb48066841 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/smumgr.c @@ -0,0 +1,247 @@ +/* + * Copyright 2015 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 +#include +#include +#include +#include +#include +#include "smumgr.h" + +MODULE_FIRMWARE("amdgpu/bonaire_smc.bin"); +MODULE_FIRMWARE("amdgpu/bonaire_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/hawaii_smc.bin"); +MODULE_FIRMWARE("amdgpu/hawaii_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/topaz_smc.bin"); +MODULE_FIRMWARE("amdgpu/topaz_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/tonga_smc.bin"); +MODULE_FIRMWARE("amdgpu/tonga_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/fiji_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris10_k2_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris11_k2_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_smc.bin"); +MODULE_FIRMWARE("amdgpu/polaris12_k_smc.bin"); +MODULE_FIRMWARE("amdgpu/vegam_smc.bin"); +MODULE_FIRMWARE("amdgpu/vega10_smc.bin"); +MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin"); +MODULE_FIRMWARE("amdgpu/vega12_smc.bin"); +MODULE_FIRMWARE("amdgpu/vega20_smc.bin"); + +int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->thermal_avfs_enable) + return hwmgr->smumgr_funcs->thermal_avfs_enable(hwmgr); + + return 0; +} + +int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->thermal_setup_fan_table) + return hwmgr->smumgr_funcs->thermal_setup_fan_table(hwmgr); + + return 0; +} + +int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + + if (NULL != hwmgr->smumgr_funcs->update_sclk_threshold) + return hwmgr->smumgr_funcs->update_sclk_threshold(hwmgr); + + return 0; +} + +int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + + if (NULL != hwmgr->smumgr_funcs->update_smc_table) + return hwmgr->smumgr_funcs->update_smc_table(hwmgr, type); + + return 0; +} + +uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, uint32_t type, uint32_t member) +{ + if (NULL != hwmgr->smumgr_funcs->get_offsetof) + return hwmgr->smumgr_funcs->get_offsetof(type, member); + + return 0; +} + +int smum_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->process_firmware_header) + return hwmgr->smumgr_funcs->process_firmware_header(hwmgr); + return 0; +} + +uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value) +{ + if (NULL != hwmgr->smumgr_funcs->get_mac_definition) + return hwmgr->smumgr_funcs->get_mac_definition(value); + + return 0; +} + +int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table) +{ + if (NULL != hwmgr->smumgr_funcs->download_pptable_settings) + return hwmgr->smumgr_funcs->download_pptable_settings(hwmgr, + table); + return 0; +} + +int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->upload_pptable_settings) + return hwmgr->smumgr_funcs->upload_pptable_settings(hwmgr); + + return 0; +} + +int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t *resp) +{ + int ret = 0; + + if (hwmgr == NULL || + hwmgr->smumgr_funcs->send_msg_to_smc == NULL || + (resp && !hwmgr->smumgr_funcs->get_argument)) + return -EINVAL; + + mutex_lock(&hwmgr->msg_lock); + + ret = hwmgr->smumgr_funcs->send_msg_to_smc(hwmgr, msg); + if (ret) { + mutex_unlock(&hwmgr->msg_lock); + return ret; + } + + if (resp) + *resp = hwmgr->smumgr_funcs->get_argument(hwmgr); + + mutex_unlock(&hwmgr->msg_lock); + + return ret; +} + +int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, + uint32_t parameter, + uint32_t *resp) +{ + int ret = 0; + + if (hwmgr == NULL || + hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL || + (resp && !hwmgr->smumgr_funcs->get_argument)) + return -EINVAL; + + mutex_lock(&hwmgr->msg_lock); + + ret = hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter( + hwmgr, msg, parameter); + if (ret) { + mutex_unlock(&hwmgr->msg_lock); + return ret; + } + + if (resp) + *resp = hwmgr->smumgr_funcs->get_argument(hwmgr); + + mutex_unlock(&hwmgr->msg_lock); + + return ret; +} + +int smum_init_smc_table(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->init_smc_table) + return hwmgr->smumgr_funcs->init_smc_table(hwmgr); + + return 0; +} + +int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->populate_all_graphic_levels) + return hwmgr->smumgr_funcs->populate_all_graphic_levels(hwmgr); + + return 0; +} + +int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->populate_all_memory_levels) + return hwmgr->smumgr_funcs->populate_all_memory_levels(hwmgr); + + return 0; +} + +/*this interface is needed by island ci/vi */ +int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->initialize_mc_reg_table) + return hwmgr->smumgr_funcs->initialize_mc_reg_table(hwmgr); + + return 0; +} + +bool smum_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->smumgr_funcs->is_dpm_running) + return hwmgr->smumgr_funcs->is_dpm_running(hwmgr); + + return true; +} + +bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->smumgr_funcs->is_hw_avfs_present) + return hwmgr->smumgr_funcs->is_hw_avfs_present(hwmgr); + + return false; +} + +int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting) +{ + if (hwmgr->smumgr_funcs->update_dpm_settings) + return hwmgr->smumgr_funcs->update_dpm_settings(hwmgr, profile_setting); + + return -EINVAL; +} + +int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) +{ + if (hwmgr->smumgr_funcs->smc_table_manager) + return hwmgr->smumgr_funcs->smc_table_manager(hwmgr, table, table_id, rw); + + return -EINVAL; +} diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c new file mode 100644 index 000000000000..4bfadb49521b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.c @@ -0,0 +1,3268 @@ +/* + * Copyright 2015 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 "pp_debug.h" +#include +#include +#include +#include +#include + +#include "smumgr.h" +#include "tonga_smumgr.h" +#include "smu_ucode_xfer_vi.h" +#include "tonga_ppsmc.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" +#include "cgs_common.h" +#include "smu7_smumgr.h" + +#include "smu7_dyn_defaults.h" + +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" + +#include "atombios.h" + +#include "pppcielanes.h" +#include "pp_endian.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define MC_CG_ARB_FREQ_F1 0x0b +#define VDDC_VDDCI_DELTA 200 + + +static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { +/* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT + */ + {1, 0xF, 0xFD, 0x19, + 5, 45, 0, 0xB0000, + {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, + 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, + {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, + 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4} + }, +}; + +/* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */ +static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = { + {600, 1050, 3, 0}, + {600, 1050, 6, 1} +}; + +/* [FF, SS] type, [] 4 voltage ranges, + * and [Floor Freq, Boundary Freq, VID min , VID max] + */ +static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = { + { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } +}; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */ +static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = { + {0, 1, 3, 2, 4, 5}, + {0, 2, 4, 5, 6, 5} +}; + +static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result; + + /* Assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result) + return result; + + /* Clear status */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_STATUS, 0); + + /* Enable clock */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Set SMU Auto Start */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_INPUT_DATA, AUTO_START, 1); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); + + /** + * Call Test SMU message with 0x20000 offset to trigger SMU start + */ + smu7_send_msg_to_smc_offset(hwmgr); + + /* Wait for done bit to be set */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + SMU_STATUS, SMU_DONE, 0); + + /* Check pass/failed indicator */ + if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) { + pr_err("SMU Firmware start failed\n"); + return -EINVAL; + } + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return 0; +} + +static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* wait for smc boot up */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); + + /*Clear firmware interrupt enable flag*/ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + + if (result != 0) + return result; + + /* Set smc instruct start point at 0x0 */ + smu7_program_jump_on_start(hwmgr); + + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /*De-assert reset*/ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int tonga_start_smu(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *priv = hwmgr->smu_backend; + int result; + + /* Only start SMC if SMC RAM is not running */ + if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { + /*Check if SMU is running in protected mode*/ + if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_FIRMWARE, SMU_MODE)) { + result = tonga_start_in_non_protection_mode(hwmgr); + if (result) + return result; + } else { + result = tonga_start_in_protection_mode(hwmgr); + if (result) + return result; + } + } + + /* Setup SoftRegsStart here to visit the register UcodeLoadStatus + * to check fw loading state + */ + smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, SoftRegisters), + &(priv->smu7_data.soft_regs_start), 0x40000); + + result = smu7_request_smu_load_fw(hwmgr); + + return result; +} + +static int tonga_smu_init(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *tonga_priv = NULL; + + tonga_priv = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL); + if (tonga_priv == NULL) + return -ENOMEM; + + hwmgr->smu_backend = tonga_priv; + + if (smu7_init(hwmgr)) { + kfree(tonga_priv); + return -EINVAL; + } + + return 0; +} + + +static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* clock - voltage dependency table is empty table */ + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + /* find first sclk bigger than request */ + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + voltage->VddGfx = phm_get_voltage_index( + pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i].vddgfx); + voltage->Vddc = phm_get_voltage_index( + pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i].vddc); + + if (allowed_clock_voltage_table->entries[i].vddci) + voltage->Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci); + else + voltage->Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA); + + + if (allowed_clock_voltage_table->entries[i].mvdd) + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd; + + voltage->Phases = 1; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddgfx); + voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddc); + + if (allowed_clock_voltage_table->entries[i-1].vddci) + voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i-1].vddci); + + if (allowed_clock_voltage_table->entries[i-1].mvdd) + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd; + + return 0; +} + +static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + table->VddcTable[count] = + PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + } + return 0; +} + +static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + table->VddGfxLevelCount = data->vddgfx_voltage_table.count; + for (count = 0; count < data->vddgfx_voltage_table.count; count++) { + table->VddGfxTable[count] = + PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount); + } + return 0; +} + +static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + + table->VddciLevelCount = data->vddci_voltage_table.count; + for (count = 0; count < table->VddciLevelCount; count++) { + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + table->SmioTable1.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */ + table->SmioTable1.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->vddci_voltage_table.entries[count].smio_low; + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + table->MvddLevelCount = data->mvdd_voltage_table.count; + for (count = 0; count < table->MvddLevelCount; count++) { + table->SmioTable2.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->mvdd_voltage_table.entries[count].smio_low; + } + table->SmioMask2 = data->mvdd_voltage_table.mask_low; + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + } + + return 0; +} + +static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = + pptable_info->vddgfx_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = + pptable_info->vddc_lookup_table; + + /* table is already swapped, so in order to use the value from it + * we need to swap it back. + */ + uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount); + uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount); + + for (count = 0; count < vddc_level_count; count++) { + /* We are populating vddc CAC data to BapmVddc table in split and merged mode */ + index = phm_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + + if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */ + for (count = 0; count < vddgfx_level_count; count++) { + index = phm_get_voltage_index(vddgfx_lookup_table, + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid)); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high); + } + } else { + for (count = 0; count < vddc_level_count; count++) { + index = phm_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddGfxVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddGfxVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + } + + return 0; +} + +static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result; + + result = tonga_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDC voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDCI voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_vdd_gfx_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDGFX voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate MVDD voltage table to SMC", + return -EINVAL); + + result = tonga_populate_cac_tables(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate CAC voltage tables to SMC", + return -EINVAL); + + return 0; +} + +static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU72_Discrete_Ulv *state) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU72_Discrete_DpmTable *table) +{ + return tonga_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t i; + + /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = + 1; + table->LinkLevel[i].SPC = + (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = + PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = + PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t reference_clock; + uint32_t reference_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ + reference_clock = atomctrl_get_reference_clock(hwmgr); + + reference_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider*/ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup*/ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + + uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; + if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + */ + /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ + uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); + + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); + + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = + PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); + } + } + + sclk->SclkFrequency = engine_clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + SMU72_Discrete_GraphicsLevel *graphic_level) +{ + int result; + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + + result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; + else + vdd_dep_table = pptable_info->vdd_dep_on_sclk; + + /* populate graphics levels*/ + result = tonga_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, engine_clock, + &graphic_level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((!result), + "can not find VDDC voltage value for VDDC " + "engine clock dependency table", return result); + + /* SCLK frequency in units of 10KHz*/ + graphic_level->SclkFrequency = engine_clock; + /* Indicates maximum activity level for this performance level. 50% for now*/ + graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity; + + graphic_level->CcPwrDynRm = 0; + graphic_level->CcPwrDynRm1 = 0; + /* this level can be used if activity is high enough.*/ + graphic_level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + graphic_level->EnabledForThrottle = 1; + graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst; + graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst; + graphic_level->VoltageDownHyst = 0; + graphic_level->PowerThrottle = 0; + + data->display_timing.min_clock_in_sr = + hwmgr->display_config->min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + graphic_level->DeepSleepDivId = + smu7_get_sleep_divider_id_from_clock(engine_clock, + data->display_timing.min_clock_in_sr); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (!result) { + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/ + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/ + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); + } + + return result; +} + +static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; + uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count; + uint32_t level_array_address = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); + + uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) * + SMU72_MAX_LEVELS_GRAPHICS; + + SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; + + uint32_t i, max_entry; + uint8_t highest_pcie_level_enabled = 0; + uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; + uint8_t count = 0; + int result = 0; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = tonga_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result != 0) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now. */ + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + if (dpm_table->sclk_table.count > 1) + smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((pcie_entry_count >= 1), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/ + for (i = 0; i < dpm_table->sclk_table.count; i++) { + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } + } else { + if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask) + pr_err("Pcie Dpm Enablemask is 0 !"); + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(highest_pcie_level_enabled+1))) != 0)) { + highest_pcie_level_enabled++; + } + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(lowest_pcie_level_enabled+1+count))) == 0)) { + count++; + } + mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? + (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; + + + /* set pcieDpmLevel to highest_pcie_level_enabled*/ + for (i = 2; i < dpm_table->sclk_table.count; i++) + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, + (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int tonga_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE( + !result, + "Error retrieving Memory Clock Parameters from VBIOS.", + return result); + + /* MPLL_FUNC_CNTL setup*/ + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, + mpll_param.bw_ctrl); + + /* MPLL_FUNC_CNTL_1 setup*/ + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, + mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, + mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, + mpll_param.vco_mode); + + /* MPLL_AD_FUNC_CNTL setup*/ + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, + mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + /* MPLL_DQ_FUNC_CNTL setup*/ + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, + mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, + mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + /* + ************************************ + Fref = Reference Frequency + NF = Feedback divider ratio + NR = Reference divider ratio + Fnom = Nominal VCO output frequency = Fref * NF / NR + Fs = Spreading Rate + D = Percentage down-spread / 2 + Fint = Reference input frequency to PFD = Fref / NR + NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) + CLKS = NS - 1 = ISS_STEP_NUM[11:0] + NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) + CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] + ************************************* + */ + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ + /* ss.Info.speed_spectrum_rate -- in unit of khz */ + /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ + /* = reference_clock * 5 / speed_spectrum_rate */ + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + + /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ + /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + /* MCLK_PWRMGT_CNTL setup */ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + + return mc_para_index; +} + +static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + + return mc_para_index; +} + + +static int tonga_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_stutter_mode_threshold = 30000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; + int result = 0; + bool dll_state_on; + uint32_t mvdd = 0; + + if (hwmgr->od_enabled) + vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; + else + vdd_dep_table = pptable_info->vdd_dep_on_mclk; + + if (NULL != vdd_dep_table) { + result = tonga_get_dependency_volt_by_clk(hwmgr, + vdd_dep_table, + memory_clock, + &memory_level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE( + !result, + "can not find MinVddc voltage value from memory VDDC " + "voltage dependency table", + return result); + } + + if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) + memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value; + else + memory_level->MinMvdd = mvdd; + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 0; + memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst; + memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst; + memory_level->VoltageDownHyst = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + if ((mclk_stutter_mode_threshold != 0) && + (memory_clock <= mclk_stutter_mode_threshold) && + (!data->is_uvd_enabled) + && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1) + && (data->display_timing.num_existing_displays <= 2) + && (data->display_timing.num_existing_displays != 0)) + memory_level->StutterEnable = 1; + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) { + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } else { + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } + + } else { + dll_state_on = data->dll_default_on; + } + } else { + memory_level->StrobeRatio = + tonga_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = tonga_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +static int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + + /* populate MCLK dpm table to SMU7 */ + uint32_t level_array_address = + smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = + sizeof(SMU72_Discrete_MemoryLevel) * + SMU72_MAX_LEVELS_MEMORY; + SMU72_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = tonga_populate_single_memory_level( + hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (result) + return result; + } + + /* Only enable level 0 for now.*/ + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + /* + * in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in a higher state + * by default such that we are not effected by up threshold or and MCLK DPM latency. + */ + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high*/ + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, + level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pattern) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + smio_pattern->Voltage = + data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else { + return -EINVAL; + } + + return 0; +} + + +static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + + SMIO_Pattern voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + table->ACPILevel.MinVoltage = + smu_data->smc_state_table.GraphicsLevel[0].MinVoltage; + + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, + SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVoltage = + smu_data->smc_state_table.MemoryLevel[0].MinVoltage; + + /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/ + + if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->UvdLevelCount = (uint8_t) (mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->UvdLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->UvdLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->UvdLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi( + hwmgr, + table->UvdLevel[count].VclkFrequency, + ÷rs); + + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for Vclk clock", + return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for Dclk clock", + return result); + + table->UvdLevel[count].DclkDivider = + (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + } + + return result; + +} + +static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->VceLevelCount = (uint8_t) (mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = + mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->VceLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->VceLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->VceLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->AcpLevelCount = (uint8_t) (mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = + pptable_info->mm_dep_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->AcpLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->AcpLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->AcpLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU72_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = tonga_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (result) + break; + } + } + + if (!result) { + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU72_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (result != 0) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("[powerplay] VBIOS did not find boot engine " + "clock value in dependency table. " + "Using Graphics DPM level 0 !"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (result != 0) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("[powerplay] VBIOS did not find boot " + "engine clock value in dependency table." + "Using Memory DPM level 0 !"); + result = 0; + } + + table->BootVoltage.Vddc = + phm_get_voltage_id(&(data->vddc_voltage_table), + data->vbios_boot_state.vddc_bootup_value); + table->BootVoltage.VddGfx = + phm_get_voltage_id(&(data->vddgfx_voltage_table), + data->vbios_boot_state.vddgfx_bootup_value); + table->BootVoltage.Vddci = + phm_get_voltage_id(&(data->vddci_voltage_table), + data->vbios_boot_state.vddci_bootup_value); + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return result; +} + +static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, + volt_with_cks, value; + uint16_t clock_freq_u16; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, + volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + uint32_t hw_revision, dev_id; + struct amdgpu_device *adev = hwmgr->adev; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + hw_revision = adev->pdev->revision; + dev_id = adev->pdev->device; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (146 * 4)); + efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (148 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + efuse2 &= 0xF; + + if (efuse2 == 1) + ro = (2300 - 1350) * efuse / 255 + 1350; + else + ro = (2500 - 1000) * efuse / 255 + 1000; + + if (ro >= 1660) + type = 0; + else + type = 1; + + /* Populate Stretch amount */ + smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; + + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + if (ASICID_IS_TONGA_P(dev_id, hw_revision)) { + volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 * + (sclk_table->entries[i].clk/100) / 10000) * 1000 / + (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000))); + volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 * + (sclk_table->entries[i].clk/100) / 100000) * 1000 / + (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000))); + } else { + volt_without_cks = (uint32_t)((14041 * + (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / + (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); + volt_with_cks = (uint32_t)((13946 * + (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / + (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); + } + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + STRETCH_ENABLE, 0x0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + staticEnable, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x0); + + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFC2FF87; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = + tonga_clock_stretcher_lookup_table[stretch_amount2][0]; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = + tonga_clock_stretcher_lookup_table[stretch_amount2][1]; + clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. + GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. + SclkFrequency) / 100); + if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] < + clock_freq_u16 && + tonga_clock_stretcher_lookup_table[stretch_amount2][1] > + clock_freq_u16) { + /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ + value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; + /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ + value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; + /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ + value |= (tonga_clock_stretch_amount_conversion + [tonga_clock_stretcher_lookup_table[stretch_amount2][3]] + [stretch_amount]) << 3; + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].minFreq); + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].maxFreq); + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = + tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= + (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + /* Populate DDT Lookup Table */ + for (i = 0; i < 4; i++) { + /* Assign the minimum and maximum VID stored + * in the last row of Clock Stretcher Voltage Table. + */ + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].minVID = + (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2]; + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].maxVID = + (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3]; + /* Loop through each SCLK and check the frequency + * to see if it lies within the frequency for clock stretcher. + */ + for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { + cks_setting = 0; + clock_freq = PP_SMC_TO_HOST_UL( + smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); + /* Check the allowed frequency against the sclk level[j]. + * Sclk's endianness has already been converted, + * and it's in 10Khz unit, + * as opposed to Data table, which is in Mhz unit. + */ + if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) { + cks_setting |= 0x2; + if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100) + cks_setting |= 0x1; + } + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. + ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + return 0; +} + +static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t config; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + /* Splitted mode */ + config = VR_SVI2_PLANE_1; + table->VRConfig |= (config<voltage_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= config; + } else { + pr_err("VDDC and VDDGFX should " + "be both on SVI2 control in splitted mode !\n"); + } + } else { + /* Merged mode */ + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config<voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + pr_err("VDDC should be on " + "SVI2 control in merged mode !\n"); + } + } + + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config<vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config<mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config<smu_backend); + uint32_t tmp; + int result; + + /* + * This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result != 0) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + + +static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + int i, j, k; + const uint16_t *pdef1, *pdef2; + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range !", + ); + + dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + dpm_table->BAPM_TEMP_GRADIENT = + PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + pdef1 = defaults->bapmti_r; + pdef2 = defaults->bapmti_rc; + + for (i = 0; i < SMU72_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU72_DTE_SOURCES; j++) { + for (k = 0; k < SMU72_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = + PP_HOST_TO_SMC_US(*pdef1); + dpm_table->BAPMTI_RC[i][j][k] = + PP_HOST_TO_SMC_US(*pdef2); + pdef1++; + pdef2++; + } + } + } + + return 0; +} + +static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* TDC number of fraction bits are changed from 8 to 7 + * for Fiji as requested by SMC team + */ + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 " + "(SviLoadLineEn) from SMC Failed !", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity & (1 << 15)) || + (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0)) + hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity = hwmgr->thermal_controller. + advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = + PP_HOST_TO_SMC_US(hwmgr->thermal_controller. + advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); + + return 0; +} + +static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed !", + return -EINVAL); + + /* DW6 */ + if (tonga_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed !", + return -EINVAL); + /* DW7 */ + if (tonga_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed !", + return -EINVAL); + /* DW8 */ + if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl Failed !", + return -EINVAL); + + /* DW9-DW12 */ + if (tonga_populate_temperature_scaler(hwmgr) != 0) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed !", + return -EINVAL); + + /* DW13-DW14 */ + if (tonga_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan " + "Control parameters Failed !", + return -EINVAL); + + /* DW15-DW18 */ + if (tonga_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed !", + return -EINVAL); + + /* DW20 */ + if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE( + false, + "Attempt to populate BapmVddCBaseLeakage " + "Hi and Lo Sidd Failed !", + return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed !", + return -EINVAL); + } + return 0; +} + +static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU72_Discrete_MCRegisters *mc_reg_table) +{ + const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<address[] array " + "out of boundary", + return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +/*convert register values from driver to SMC format */ +static void tonga_convert_mc_registers( + const struct tonga_mc_reg_entry *entry, + SMU72_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int tonga_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU72_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU72_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = tonga_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters)); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + + address = smu_data->smu7_data.mc_reg_table_start + + (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); + + return smu7_copy_bytes_to_smc( + hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU72_Discrete_MCRegisterSet) * + data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters)); + result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize MCRegTable for the MC register addresses !", + return result;); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize MCRegTable for driver state !", + return result;); + + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END); +} + +static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &tonga_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0]; +} + +static int tonga_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + uint8_t i; + pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; + + + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + tonga_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + tonga_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN); + + if (i == 1 || i == 0) + table->SystemFlags |= 0x40; + + if (data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = tonga_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ULV state !", + return result;); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = tonga_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Link Level !", return result); + + result = tonga_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Graphics Level !", return result); + + result = tonga_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Memory Level !", return result); + + result = tonga_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ACPI Level !", return result); + + result = tonga_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize VCE Level !", return result); + + result = tonga_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ACP Level !", return result); + + /* Since only the initial state is completely set up at this + * point (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = tonga_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to Write ARB settings for the initial state.", + return result;); + + result = tonga_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize UVD Level !", return result); + + result = tonga_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Boot Level !", return result); + + tonga_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate BAPM Parameters !", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = tonga_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate Clock Stretcher Data Table !", + return result;); + } + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + /* + * Cail reads current link status and reports it as cap (we cannot + * change this due to some previous issues we had) + * SMC drops the link status to lowest level after enabling + * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again + * but this time Cail reads current link status which was set to low by + * SMC and reports it as cap to powerplay + * To avoid it, we set PCIeBootLinkLevel to highest dpm level + */ + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + + table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); + + table->PCIeGenInterval = 1; + + result = tonga_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate VRConfig setting !", return result); + data->vr_config = table->VRConfig; + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, + &gpio_pin_assignment)) { + table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin_assignment)) { + table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + + if (0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, + THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + + table->ThermOutPolarity = + (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0; + + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO*/ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)){ + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(!result, + "Failed to upload dpm data to SMC memory !", return result;); + + result = tonga_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload arb data to SMC memory !", return result); + + tonga_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE((!result), + "Failed to populate initialize pm fuses !", return result); + + result = tonga_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((!result), + "Failed to populate initialize MC Reg table !", return result); + + return 0; +} + +static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == smu_data->smu7_data.fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + fan_table.FanControl_GL_Flag = 1; + + res = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, + (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + return 0; +} + + +static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return tonga_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = tonga_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((!result), + "Failed to upload MC reg table !", + return result); + + result = tonga_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters !", + ); + + return result; +} + +static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU72_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); + case AverageMemoryActivity: + return offsetof(SMU72_SoftRegisters, AverageMemoryActivity); + case PreVBlankGap: + return offsetof(SMU72_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU72_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU72_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU72_Discrete_DpmTable, VceBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold); + } + break; + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t tonga_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU72_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU72_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU72_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU72_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU72_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU72_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU72_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU72_MAX_LEVELS_MVDD; + } + pr_warn("can't get the mac value %x\n", value); + + return 0; +} + +static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), + NULL); + return 0; +} + +static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, + NULL); + return 0; +} + +static int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + tonga_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + tonga_update_vce_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (result != 0); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (result != 0); + + return error ? 1 : 0; +} + +/*---------------------------MC----------------------------*/ + +static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, + &address) ? + address : + table->mc_reg_address[i].s1; + } + return 0; +} + +static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct tonga_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct tonga_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, + mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + + if (!data->is_memory_gddr5) { + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + j++; + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int tonga_set_valid_flag(struct tonga_mc_reg_table *table) +{ + uint8_t i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1<smu_backend); + pp_atomctrl_mc_reg_table *table; + struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = tonga_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (table == NULL) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (!result) + result = tonga_copy_vbios_smc_reg_table(table, ni_table); + + if (!result) { + tonga_set_s0_mc_reg_index(ni_table); + result = tonga_set_mc_special_registers(hwmgr, ni_table); + } + + if (!result) + tonga_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr, + void *profile_setting) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *) + (hwmgr->smu_backend); + struct profile_mode_setting *setting; + struct SMU72_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); + + uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, MemoryLevel); + struct SMU72_Discrete_MemoryLevel *mclk_levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; + + if (profile_setting == NULL) + return -EINVAL; + + setting = (struct profile_mode_setting *)profile_setting; + + if (setting->bupdate_sclk) { + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + if (levels[i].ActivityLevel != + cpu_to_be16(setting->sclk_activity)) { + levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); + + clk_activity_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) + + offsetof(SMU72_Discrete_GraphicsLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (levels[i].UpHyst != setting->sclk_up_hyst || + levels[i].DownHyst != setting->sclk_down_hyst) { + levels[i].UpHyst = setting->sclk_up_hyst; + levels[i].DownHyst = setting->sclk_down_hyst; + up_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) + + offsetof(SMU72_Discrete_GraphicsLevel, UpHyst); + down_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) + + offsetof(SMU72_Discrete_GraphicsLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->sclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); + } + + if (setting->bupdate_mclk) { + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); + for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { + if (mclk_levels[i].ActivityLevel != + cpu_to_be16(setting->mclk_activity)) { + mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); + + clk_activity_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) + + offsetof(SMU72_Discrete_MemoryLevel, ActivityLevel); + offset = clk_activity_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + + } + if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || + mclk_levels[i].DownHyst != setting->mclk_down_hyst) { + mclk_levels[i].UpHyst = setting->mclk_up_hyst; + mclk_levels[i].DownHyst = setting->mclk_down_hyst; + up_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) + + offsetof(SMU72_Discrete_MemoryLevel, UpHyst); + down_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) + + offsetof(SMU72_Discrete_MemoryLevel, DownHyst); + offset = up_hyst_offset & ~0x3; + tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); + tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); + tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); + } + } + if (!data->mclk_dpm_key_disabled) + smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); + } + return 0; +} + +const struct pp_smumgr_func tonga_smu_funcs = { + .name = "tonga_smu", + .smu_init = &tonga_smu_init, + .smu_fini = &smu7_smu_fini, + .start_smu = &tonga_start_smu, + .check_fw_load_finish = &smu7_check_fw_load_finish, + .request_smu_load_fw = &smu7_request_smu_load_fw, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &smu7_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .update_smc_table = tonga_update_smc_table, + .get_offsetof = tonga_get_offsetof, + .process_firmware_header = tonga_process_firmware_header, + .init_smc_table = tonga_init_smc_table, + .update_sclk_threshold = tonga_update_sclk_threshold, + .thermal_setup_fan_table = tonga_thermal_setup_fan_table, + .populate_all_graphic_levels = tonga_populate_all_graphic_levels, + .populate_all_memory_levels = tonga_populate_all_memory_levels, + .get_mac_definition = tonga_get_mac_definition, + .initialize_mc_reg_table = tonga_initialize_mc_reg_table, + .is_dpm_running = tonga_is_dpm_running, + .update_dpm_settings = tonga_update_dpm_settings, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h new file mode 100644 index 000000000000..d664fedd3d85 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/tonga_smumgr.h @@ -0,0 +1,74 @@ +/* + * Copyright 2015 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 _TONGA_SMUMGR_H_ +#define _TONGA_SMUMGR_H_ + +#include "smu72_discrete.h" +#include "smu7_smumgr.h" +#include "smu72.h" + + +#define ASICID_IS_TONGA_P(wDID, bRID) \ + (((wDID == 0x6930) && ((bRID == 0xF0) || (bRID == 0xF1) || (bRID == 0xFF))) \ + || ((wDID == 0x6920) && ((bRID == 0) || (bRID == 1)))) + +struct tonga_pt_defaults { + uint8_t svi_load_line_en; + uint8_t svi_load_line_vddC; + uint8_t tdc_vddc_throttle_release_limit_perc; + uint8_t tdc_mawt; + uint8_t tdc_waterfall_ctl; + uint8_t dte_ambient_temp_base; + uint32_t display_cac; + uint32_t bapm_temp_gradient; + uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; + uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; +}; + +struct tonga_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +struct tonga_mc_reg_table { + uint8_t last; /* number of registers*/ + uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/ + uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/ + struct tonga_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMU72_Discrete_MCRegisterAddress mc_reg_address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + + +struct tonga_smumgr { + + struct smu7_smumgr smu7_data; + struct SMU72_Discrete_DpmTable smc_state_table; + struct SMU72_Discrete_Ulv ulv_setting; + struct SMU72_Discrete_PmFuses power_tune_table; + const struct tonga_pt_defaults *power_tune_defaults; + SMU72_Discrete_MCRegisters mc_regs; + struct tonga_mc_reg_table mc_reg_table; +}; + +#endif diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c new file mode 100644 index 000000000000..1e222c5d91a4 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c @@ -0,0 +1,396 @@ +/* + * Copyright 2016 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 + +#include "smumgr.h" +#include "vega10_inc.h" +#include "soc15_common.h" +#include "vega10_smumgr.h" +#include "vega10_hwmgr.h" +#include "vega10_ppsmc.h" +#include "smu9_driver_if.h" +#include "smu9_smumgr.h" +#include "ppatomctrl.h" +#include "pp_debug.h" + + +static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega10_smumgr *priv = hwmgr->smu_backend; + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableSmu2Dram, + priv->smu_tables.entry[table_id].table_id, + NULL); + + /* flush hdp cache */ + amdgpu_asic_flush_hdp(adev, NULL); + + memcpy(table, priv->smu_tables.entry[table_id].table, + priv->smu_tables.entry[table_id].size); + + return 0; +} + +static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega10_smumgr *priv = hwmgr->smu_backend; + struct amdgpu_device *adev = hwmgr->adev; + + /* under sriov, vbios or hypervisor driver + * has already copy table to smc so here only skip it + */ + if (!hwmgr->not_vf) + return 0; + + PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + + memcpy(priv->smu_tables.entry[table_id].table, table, + priv->smu_tables.entry[table_id].size); + + amdgpu_asic_flush_hdp(adev, NULL); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableDram2Smu, + priv->smu_tables.entry[table_id].table_id, + NULL); + + return 0; +} + +int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint32_t feature_mask) +{ + int msg = enable ? PPSMC_MSG_EnableSmuFeatures : + PPSMC_MSG_DisableSmuFeatures; + + /* VF has no permission to change smu feature due + * to security concern even under pp one vf mode + * it still can't do it. For vega10, the smu in + * vbios will enable the appropriate features. + * */ + if (!hwmgr->not_vf) + return 0; + + return smum_send_msg_to_smc_with_parameter(hwmgr, + msg, feature_mask, NULL); +} + +int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled) +{ + uint32_t enabled_features; + + if (features_enabled == NULL) + return -EINVAL; + + smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetEnabledSmuFeatures, + &enabled_features); + *features_enabled = enabled_features; + + return 0; +} + +static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + uint64_t features_enabled = 0; + + vega10_get_enabled_smc_features(hwmgr, &features_enabled); + + if (features_enabled & SMC_DPM_FEATURES) + return true; + else + return false; +} + +static int vega10_set_tools_address(struct pp_hwmgr *hwmgr) +{ + struct vega10_smumgr *priv = hwmgr->smu_backend; + + if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) { + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr), + NULL); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr), + NULL); + } + return 0; +} + +static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr) +{ + uint32_t smc_driver_if_version; + struct amdgpu_device *adev = hwmgr->adev; + uint32_t dev_id; + uint32_t rev_id; + + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetDriverIfVersion, + &smc_driver_if_version), + "Attempt to get SMC IF Version Number Failed!", + return -EINVAL); + + dev_id = adev->pdev->device; + rev_id = adev->pdev->revision; + + if (!((dev_id == 0x687f) && + ((rev_id == 0xc0) || + (rev_id == 0xc1) || + (rev_id == 0xc3)))) { + if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { + pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n", + smc_driver_if_version, SMU9_DRIVER_IF_VERSION); + return -EINVAL; + } + } + + return 0; +} + +static int vega10_smu_init(struct pp_hwmgr *hwmgr) +{ + struct vega10_smumgr *priv; + unsigned long tools_size; + int ret; + struct cgs_firmware_info info = {0}; + + ret = cgs_get_firmware_info(hwmgr->device, + CGS_UCODE_ID_SMU, + &info); + if (ret || !info.kptr) + return -EINVAL; + + priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL); + + if (!priv) + return -ENOMEM; + + hwmgr->smu_backend = priv; + + /* allocate space for pptable */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(PPTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[PPTABLE].handle, + &priv->smu_tables.entry[PPTABLE].mc_addr, + &priv->smu_tables.entry[PPTABLE].table); + if (ret) + goto free_backend; + + priv->smu_tables.entry[PPTABLE].version = 0x01; + priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t); + priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE; + + /* allocate space for watermarks table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(Watermarks_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[WMTABLE].handle, + &priv->smu_tables.entry[WMTABLE].mc_addr, + &priv->smu_tables.entry[WMTABLE].table); + + if (ret) + goto err0; + + priv->smu_tables.entry[WMTABLE].version = 0x01; + priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t); + priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS; + + /* allocate space for AVFS table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(AvfsTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[AVFSTABLE].handle, + &priv->smu_tables.entry[AVFSTABLE].mc_addr, + &priv->smu_tables.entry[AVFSTABLE].table); + + if (ret) + goto err1; + + priv->smu_tables.entry[AVFSTABLE].version = 0x01; + priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t); + priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS; + + tools_size = 0x19000; + if (tools_size) { + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + tools_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TOOLSTABLE].handle, + &priv->smu_tables.entry[TOOLSTABLE].mc_addr, + &priv->smu_tables.entry[TOOLSTABLE].table); + if (ret) + goto err2; + priv->smu_tables.entry[TOOLSTABLE].version = 0x01; + priv->smu_tables.entry[TOOLSTABLE].size = tools_size; + priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG; + } + + /* allocate space for AVFS Fuse table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(AvfsFuseOverride_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[AVFSFUSETABLE].handle, + &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr, + &priv->smu_tables.entry[AVFSFUSETABLE].table); + if (ret) + goto err3; + + priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01; + priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t); + priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE; + + + return 0; + +err3: + if (priv->smu_tables.entry[TOOLSTABLE].table) + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle, + &priv->smu_tables.entry[TOOLSTABLE].mc_addr, + &priv->smu_tables.entry[TOOLSTABLE].table); +err2: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle, + &priv->smu_tables.entry[AVFSTABLE].mc_addr, + &priv->smu_tables.entry[AVFSTABLE].table); +err1: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle, + &priv->smu_tables.entry[WMTABLE].mc_addr, + &priv->smu_tables.entry[WMTABLE].table); +err0: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle, + &priv->smu_tables.entry[PPTABLE].mc_addr, + &priv->smu_tables.entry[PPTABLE].table); +free_backend: + kfree(hwmgr->smu_backend); + + return -EINVAL; +} + +static int vega10_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct vega10_smumgr *priv = hwmgr->smu_backend; + + if (priv) { + amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle, + &priv->smu_tables.entry[PPTABLE].mc_addr, + &priv->smu_tables.entry[PPTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle, + &priv->smu_tables.entry[WMTABLE].mc_addr, + &priv->smu_tables.entry[WMTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle, + &priv->smu_tables.entry[AVFSTABLE].mc_addr, + &priv->smu_tables.entry[AVFSTABLE].table); + if (priv->smu_tables.entry[TOOLSTABLE].table) + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle, + &priv->smu_tables.entry[TOOLSTABLE].mc_addr, + &priv->smu_tables.entry[TOOLSTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle, + &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr, + &priv->smu_tables.entry[AVFSFUSETABLE].table); + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + } + return 0; +} + +static int vega10_start_smu(struct pp_hwmgr *hwmgr) +{ + if (!smu9_is_smc_ram_running(hwmgr)) + return -EINVAL; + + PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr), + "Failed to verify SMC interface!", + return -EINVAL); + + vega10_set_tools_address(hwmgr); + + return 0; +} + +static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, + uint16_t table_id, bool rw) +{ + int ret; + + if (rw) + ret = vega10_copy_table_from_smc(hwmgr, table, table_id); + else + ret = vega10_copy_table_to_smc(hwmgr, table, table_id); + + return ret; +} + +const struct pp_smumgr_func vega10_smu_funcs = { + .name = "vega10_smu", + .smu_init = &vega10_smu_init, + .smu_fini = &vega10_smu_fini, + .start_smu = &vega10_start_smu, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &smu9_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .is_dpm_running = vega10_is_dpm_running, + .get_argument = smu9_get_argument, + .smc_table_manager = vega10_smc_table_manager, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h new file mode 100644 index 000000000000..bad760f22624 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.h @@ -0,0 +1,51 @@ +/* + * Copyright 2016 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 _VEGA10_SMUMANAGER_H_ +#define _VEGA10_SMUMANAGER_H_ + +#define MAX_SMU_TABLE 5 + +struct smu_table_entry { + uint32_t version; + uint32_t size; + uint32_t table_id; + uint64_t mc_addr; + void *table; + struct amdgpu_bo *handle; +}; + +struct smu_table_array { + struct smu_table_entry entry[MAX_SMU_TABLE]; +}; + +struct vega10_smumgr { + struct smu_table_array smu_tables; +}; + +int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint32_t feature_mask); +int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c new file mode 100644 index 000000000000..f54df76537e4 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c @@ -0,0 +1,416 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "smumgr.h" +#include "vega12_inc.h" +#include "soc15_common.h" +#include "smu9_smumgr.h" +#include "vega12_smumgr.h" +#include "vega12_ppsmc.h" +#include "vega12/smu9_driver_if.h" +#include "ppatomctrl.h" +#include "pp_debug.h" + + +/* + * Copy table from SMC into driver FB + * @param hwmgr the address of the HW manager + * @param table_id the driver's table ID to copy from + */ +static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega12_smumgr *priv = + (struct vega12_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL) == 0, + "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL) == 0, + "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", + return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableSmu2Dram, + table_id, + NULL) == 0, + "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", + return -EINVAL); + + /* flush hdp cache */ + amdgpu_asic_flush_hdp(adev, NULL); + + memcpy(table, priv->smu_tables.entry[table_id].table, + priv->smu_tables.entry[table_id].size); + + return 0; +} + +/* + * Copy table from Driver FB into SMC + * @param hwmgr the address of the HW manager + * @param table_id the table to copy from + */ +static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega12_smumgr *priv = + (struct vega12_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + + memcpy(priv->smu_tables.entry[table_id].table, table, + priv->smu_tables.entry[table_id].size); + + amdgpu_asic_flush_hdp(adev, NULL); + + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL) == 0, + "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", + return -EINVAL;); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL) == 0, + "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", + return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableDram2Smu, + table_id, + NULL) == 0, + "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", + return -EINVAL); + + return 0; +} + +int vega12_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint64_t feature_mask) +{ + uint32_t smu_features_low, smu_features_high; + + smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); + smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); + + if (enable) { + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0, + "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!", + return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0, + "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!", + return -EINVAL); + } else { + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0, + "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!", + return -EINVAL); + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0, + "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!", + return -EINVAL); + } + + return 0; +} + +int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled) +{ + uint32_t smc_features_low, smc_features_high; + + if (features_enabled == NULL) + return -EINVAL; + + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetEnabledSmuFeaturesLow, + &smc_features_low) == 0, + "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!", + return -EINVAL); + + PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetEnabledSmuFeaturesHigh, + &smc_features_high) == 0, + "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!", + return -EINVAL); + + *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | + (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); + + return 0; +} + +static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + uint64_t features_enabled = 0; + + vega12_get_enabled_smc_features(hwmgr, &features_enabled); + + if (features_enabled & SMC_DPM_FEATURES) + return true; + else + return false; +} + +static int vega12_set_tools_address(struct pp_hwmgr *hwmgr) +{ + struct vega12_smumgr *priv = + (struct vega12_smumgr *)(hwmgr->smu_backend); + + if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) { + if (!smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), + NULL)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), + NULL); + } + return 0; +} + +static int vega12_smu_init(struct pp_hwmgr *hwmgr) +{ + struct vega12_smumgr *priv; + unsigned long tools_size; + struct cgs_firmware_info info = {0}; + int ret; + + ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, + &info); + if (ret || !info.kptr) + return -EINVAL; + + priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + hwmgr->smu_backend = priv; + + /* allocate space for pptable */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(PPTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); + if (ret) + goto free_backend; + + priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01; + priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t); + + /* allocate space for watermarks table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(Watermarks_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); + + if (ret) + goto err0; + + priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01; + priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t); + + tools_size = 0x19000; + if (tools_size) { + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + tools_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); + if (ret) + goto err1; + + priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01; + priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size; + } + + /* allocate space for AVFS Fuse table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(AvfsFuseOverride_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); + + if (ret) + goto err2; + + priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01; + priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t); + + /* allocate space for OverDrive table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(OverDriveTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); + if (ret) + goto err3; + + priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01; + priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t); + + /* allocate space for SMU_METRICS table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(SmuMetrics_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_SMU_METRICS].handle, + &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, + &priv->smu_tables.entry[TABLE_SMU_METRICS].table); + if (ret) + goto err4; + + priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01; + priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t); + + return 0; + +err4: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); +err3: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); +err2: + if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table) + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); +err1: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); +err0: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); +free_backend: + kfree(hwmgr->smu_backend); + + return -EINVAL; +} + +static int vega12_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct vega12_smumgr *priv = + (struct vega12_smumgr *)(hwmgr->smu_backend); + + if (priv) { + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); + if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table) + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, + &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, + &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, + &priv->smu_tables.entry[TABLE_SMU_METRICS].table); + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + } + return 0; +} + +static int vega12_start_smu(struct pp_hwmgr *hwmgr) +{ + PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr), + "SMC is not running!", + return -EINVAL); + + vega12_set_tools_address(hwmgr); + + return 0; +} + +static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, + uint16_t table_id, bool rw) +{ + int ret; + + if (rw) + ret = vega12_copy_table_from_smc(hwmgr, table, table_id); + else + ret = vega12_copy_table_to_smc(hwmgr, table, table_id); + + return ret; +} + +const struct pp_smumgr_func vega12_smu_funcs = { + .name = "vega12_smu", + .smu_init = &vega12_smu_init, + .smu_fini = &vega12_smu_fini, + .start_smu = &vega12_start_smu, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &smu9_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .is_dpm_running = vega12_is_dpm_running, + .get_argument = smu9_get_argument, + .smc_table_manager = vega12_smc_table_manager, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h new file mode 100644 index 000000000000..aeec965ce81f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.h @@ -0,0 +1,57 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef _VEGA12_SMUMANAGER_H_ +#define _VEGA12_SMUMANAGER_H_ + +#include "hwmgr.h" +#include "vega12/smu9_driver_if.h" +#include "vega12_hwmgr.h" + +struct smu_table_entry { + uint32_t version; + uint32_t size; + uint64_t mc_addr; + void *table; + struct amdgpu_bo *handle; +}; + +struct smu_table_array { + struct smu_table_entry entry[TABLE_COUNT]; +}; + +struct vega12_smumgr { + struct smu_table_array smu_tables; +}; + +#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF +#define SMU_FEATURES_LOW_SHIFT 0 +#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 +#define SMU_FEATURES_HIGH_SHIFT 32 + +int vega12_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint64_t feature_mask); +int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c new file mode 100644 index 000000000000..cf43629d29d2 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c @@ -0,0 +1,646 @@ +/* + * Copyright 2018 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 "smumgr.h" +#include "vega20_inc.h" +#include "soc15_common.h" +#include "vega20_smumgr.h" +#include "vega20_ppsmc.h" +#include "smu11_driver_if.h" +#include "ppatomctrl.h" +#include "pp_debug.h" +#include "smu_ucode_xfer_vi.h" +#include "smu7_smumgr.h" +#include "vega20_hwmgr.h" + +#include "smu_v11_0_i2c.h" + +/* MP Apertures */ +#define MP0_Public 0x03800000 +#define MP0_SRAM 0x03900000 +#define MP1_Public 0x03b00000 +#define MP1_SRAM 0x03c00004 + +/* address block */ +#define smnMP1_FIRMWARE_FLAGS 0x3010024 +#define smnMP0_FW_INTF 0x30101c0 +#define smnMP1_PUB_CTRL 0x3010b14 + +bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t mp1_fw_flags; + + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + + if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> + MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) + return true; + + return false; +} + +/* + * Check if SMC has responded to previous message. + * + * @param smumgr the address of the powerplay hardware manager. + * @return TRUE SMC has responded, FALSE otherwise. + */ +static uint32_t vega20_wait_for_response(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + uint32_t reg; + + reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); + + phm_wait_for_register_unequal(hwmgr, reg, + 0, MP1_C2PMSG_90__CONTENT_MASK); + + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); +} + +/* + * Send a message to the SMC, and do not wait for its response. + * @param smumgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ +static int vega20_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, + uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); + + return 0; +} + +/* + * Send a message to the SMC, and wait for its response. + * @param hwmgr the address of the powerplay hardware manager. + * @param msg the message to send. + * @return Always return 0. + */ +static int vega20_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + vega20_wait_for_response(hwmgr); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + vega20_send_msg_to_smc_without_waiting(hwmgr, msg); + + ret = vega20_wait_for_response(hwmgr); + if (ret != PPSMC_Result_OK) + pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); + + return (ret == PPSMC_Result_OK) ? 0 : -EIO; +} + +/* + * Send a message to the SMC with parameter + * @param hwmgr: the address of the powerplay hardware manager. + * @param msg: the message to send. + * @param parameter: the parameter to send + * @return Always return 0. + */ +static int vega20_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + vega20_wait_for_response(hwmgr); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); + + vega20_send_msg_to_smc_without_waiting(hwmgr, msg); + + ret = vega20_wait_for_response(hwmgr); + if (ret != PPSMC_Result_OK) + pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); + + return (ret == PPSMC_Result_OK) ? 0 : -EIO; +} + +static uint32_t vega20_get_argument(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); +} + +/* + * Copy table from SMC into driver FB + * @param hwmgr the address of the HW manager + * @param table_id the driver's table ID to copy from + */ +static int vega20_copy_table_from_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL)) == 0, + "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL)) == 0, + "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableSmu2Dram, table_id, NULL)) == 0, + "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", + return ret); + + /* flush hdp cache */ + amdgpu_asic_flush_hdp(adev, NULL); + + memcpy(table, priv->smu_tables.entry[table_id].table, + priv->smu_tables.entry[table_id].size); + + return 0; +} + +/* + * Copy table from Driver FB into SMC + * @param hwmgr the address of the HW manager + * @param table_id the table to copy from + */ +static int vega20_copy_table_to_smc(struct pp_hwmgr *hwmgr, + uint8_t *table, int16_t table_id) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, + "Invalid SMU Table ID!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, + "Invalid SMU Table version!", return -EINVAL); + PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, + "Invalid SMU Table Length!", return -EINVAL); + + memcpy(priv->smu_tables.entry[table_id].table, table, + priv->smu_tables.entry[table_id].size); + + amdgpu_asic_flush_hdp(adev, NULL); + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL)) == 0, + "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), + NULL)) == 0, + "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableDram2Smu, table_id, NULL)) == 0, + "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", + return ret); + + return 0; +} + +int vega20_set_activity_monitor_coeff(struct pp_hwmgr *hwmgr, + uint8_t *table, uint16_t workload_type) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + memcpy(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, table, + priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size); + + amdgpu_asic_flush_hdp(adev, NULL); + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), + NULL)) == 0, + "[SetActivityMonitor] Attempt to Set Dram Addr High Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), + NULL)) == 0, + "[SetActivityMonitor] Attempt to Set Dram Addr Low Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableDram2Smu, + TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16), + NULL)) == 0, + "[SetActivityMonitor] Attempt to Transfer Table To SMU Failed!", + return ret); + + return 0; +} + +int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr, + uint8_t *table, uint16_t workload_type) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + int ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), + NULL)) == 0, + "[GetActivityMonitor] Attempt to Set Dram Addr High Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), + NULL)) == 0, + "[GetActivityMonitor] Attempt to Set Dram Addr Low Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_TransferTableSmu2Dram, + TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16), NULL)) == 0, + "[GetActivityMonitor] Attempt to Transfer Table From SMU Failed!", + return ret); + + /* flush hdp cache */ + amdgpu_asic_flush_hdp(adev, NULL); + + memcpy(table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, + priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size); + + return 0; +} + +int vega20_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint64_t feature_mask) +{ + uint32_t smu_features_low, smu_features_high; + int ret = 0; + + smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); + smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); + + if (enable) { + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL)) == 0, + "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL)) == 0, + "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!", + return ret); + } else { + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL)) == 0, + "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL)) == 0, + "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!", + return ret); + } + + return 0; +} + +int vega20_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled) +{ + uint32_t smc_features_low, smc_features_high; + int ret = 0; + + if (features_enabled == NULL) + return -EINVAL; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetEnabledSmuFeaturesLow, + &smc_features_low)) == 0, + "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetEnabledSmuFeaturesHigh, + &smc_features_high)) == 0, + "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!", + return ret); + + *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | + (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); + + return 0; +} + +static int vega20_set_tools_address(struct pp_hwmgr *hwmgr) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + int ret = 0; + + if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) { + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), + NULL); + if (!ret) + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetToolsDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), + NULL); + } + + return ret; +} + +int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + int ret = 0; + + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrHigh, + upper_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr), + NULL)) == 0, + "[SetPPtabeDriverAddress] Attempt to Set Dram Addr High Failed!", + return ret); + PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetDriverDramAddrLow, + lower_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr), + NULL)) == 0, + "[SetPPtabeDriverAddress] Attempt to Set Dram Addr Low Failed!", + return ret); + + return ret; +} + +static int vega20_smu_init(struct pp_hwmgr *hwmgr) +{ + struct vega20_smumgr *priv; + unsigned long tools_size = 0x19000; + int ret = 0; + struct amdgpu_device *adev = hwmgr->adev; + + struct cgs_firmware_info info = {0}; + + ret = cgs_get_firmware_info(hwmgr->device, + smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), + &info); + if (ret || !info.kptr) + return -EINVAL; + + priv = kzalloc(sizeof(struct vega20_smumgr), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + hwmgr->smu_backend = priv; + + /* allocate space for pptable */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(PPTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); + if (ret) + goto free_backend; + + priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01; + priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t); + + /* allocate space for watermarks table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(Watermarks_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); + if (ret) + goto err0; + + priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01; + priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t); + + /* allocate space for pmstatuslog table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + tools_size, + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); + if (ret) + goto err1; + + priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01; + priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size; + + /* allocate space for OverDrive table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(OverDriveTable_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); + if (ret) + goto err2; + + priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01; + priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t); + + /* allocate space for SmuMetrics table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(SmuMetrics_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_SMU_METRICS].handle, + &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, + &priv->smu_tables.entry[TABLE_SMU_METRICS].table); + if (ret) + goto err3; + + priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01; + priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t); + + /* allocate space for ActivityMonitor table */ + ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, + sizeof(DpmActivityMonitorCoeffInt_t), + PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, + &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle, + &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr, + &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table); + if (ret) + goto err4; + + priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01; + priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t); + + ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c); + if (ret) + goto err4; + + return 0; + +err4: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, + &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, + &priv->smu_tables.entry[TABLE_SMU_METRICS].table); +err3: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); +err2: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); +err1: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); +err0: + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); +free_backend: + kfree(hwmgr->smu_backend); + + return -EINVAL; +} + +static int vega20_smu_fini(struct pp_hwmgr *hwmgr) +{ + struct vega20_smumgr *priv = + (struct vega20_smumgr *)(hwmgr->smu_backend); + struct amdgpu_device *adev = hwmgr->adev; + + smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c); + + if (priv) { + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, + &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, + &priv->smu_tables.entry[TABLE_PPTABLE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, + &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, + &priv->smu_tables.entry[TABLE_WATERMARKS].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, + &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, + &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, + &priv->smu_tables.entry[TABLE_OVERDRIVE].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, + &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, + &priv->smu_tables.entry[TABLE_SMU_METRICS].table); + amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle, + &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr, + &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table); + kfree(hwmgr->smu_backend); + hwmgr->smu_backend = NULL; + } + + return 0; +} + +static int vega20_start_smu(struct pp_hwmgr *hwmgr) +{ + int ret; + + ret = vega20_is_smc_ram_running(hwmgr); + PP_ASSERT_WITH_CODE(ret, + "[Vega20StartSmu] SMC is not running!", + return -EINVAL); + + ret = vega20_set_tools_address(hwmgr); + PP_ASSERT_WITH_CODE(!ret, + "[Vega20StartSmu] Failed to set tools address!", + return ret); + + return 0; +} + +static bool vega20_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + uint64_t features_enabled = 0; + + vega20_get_enabled_smc_features(hwmgr, &features_enabled); + + if (features_enabled & SMC_DPM_FEATURES) + return true; + else + return false; +} + +static int vega20_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, + uint16_t table_id, bool rw) +{ + int ret; + + if (rw) + ret = vega20_copy_table_from_smc(hwmgr, table, table_id); + else + ret = vega20_copy_table_to_smc(hwmgr, table, table_id); + + return ret; +} + +const struct pp_smumgr_func vega20_smu_funcs = { + .name = "vega20_smu", + .smu_init = &vega20_smu_init, + .smu_fini = &vega20_smu_fini, + .start_smu = &vega20_start_smu, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = &vega20_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &vega20_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, + .is_dpm_running = vega20_is_dpm_running, + .get_argument = vega20_get_argument, + .smc_table_manager = vega20_smc_table_manager, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h new file mode 100644 index 000000000000..62ebbfd6068f --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.h @@ -0,0 +1,63 @@ +/* + * Copyright 2018 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 _VEGA20_SMUMANAGER_H_ +#define _VEGA20_SMUMANAGER_H_ + +#include "hwmgr.h" +#include "smu11_driver_if.h" + +struct smu_table_entry { + uint32_t version; + uint32_t size; + uint64_t mc_addr; + void *table; + struct amdgpu_bo *handle; +}; + +struct smu_table_array { + struct smu_table_entry entry[TABLE_COUNT]; +}; + +struct vega20_smumgr { + struct smu_table_array smu_tables; +}; + +#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF +#define SMU_FEATURES_LOW_SHIFT 0 +#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 +#define SMU_FEATURES_HIGH_SHIFT 32 + +int vega20_enable_smc_features(struct pp_hwmgr *hwmgr, + bool enable, uint64_t feature_mask); +int vega20_get_enabled_smc_features(struct pp_hwmgr *hwmgr, + uint64_t *features_enabled); +int vega20_set_activity_monitor_coeff(struct pp_hwmgr *hwmgr, + uint8_t *table, uint16_t workload_type); +int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr, + uint8_t *table, uint16_t workload_type); +int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr); + +bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr); + +#endif + diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c new file mode 100644 index 000000000000..0ecc18b55ffb --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.c @@ -0,0 +1,2302 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#include "pp_debug.h" +#include "smumgr.h" +#include "smu_ucode_xfer_vi.h" +#include "vegam_smumgr.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "oss/oss_3_0_d.h" +#include "gca/gfx_8_0_d.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "ppatomctrl.h" +#include "cgs_common.h" +#include "smu7_ppsmc.h" + +#include "smu7_dyn_defaults.h" + +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "dce/dce_11_2_d.h" +#include "dce/dce_11_2_sh_mask.h" + +#define PPVEGAM_TARGETACTIVITY_DFLT 50 + +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VDDC_VDDCI_DELTA 200 +#define MC_CG_ARB_FREQ_F1 0x0b + +#define STRAP_ASIC_RO_LSB 2168 +#define STRAP_ASIC_RO_MSB 2175 + +#define PPSMC_MSG_ApplyAvfsCksOffVoltage ((uint16_t) 0x415) +#define PPSMC_MSG_EnableModeSwitchRLCNotification ((uint16_t) 0x305) + +static const struct vegam_pt_defaults +vegam_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ + { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, +}; + +static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { + {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, + {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, + {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; + +static int vegam_smu_init(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data; + + smu_data = kzalloc(sizeof(struct vegam_smumgr), GFP_KERNEL); + if (smu_data == NULL) + return -ENOMEM; + + hwmgr->smu_backend = smu_data; + + if (smu7_init(hwmgr)) { + kfree(smu_data); + return -EINVAL; + } + + return 0; +} + +static int vegam_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* Wait for smc boot up */ + /* PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ + + /* Assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result != 0) + return result; + + /* Clear status */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); + + + /* Call Test SMU message with 0x20000 offset to trigger SMU start */ + smu7_send_msg_to_smc_offset(hwmgr); + + /* Wait done bit to be set */ + /* Check pass/failed indicator */ + + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); + + if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMU_STATUS, SMU_PASS)) + PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int vegam_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + /* wait for smc boot up */ + PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); + + /* Clear firmware interrupt enable flag */ + /* PHM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, + rst_reg, 1); + + result = smu7_upload_smu_firmware_image(hwmgr); + if (result != 0) + return result; + + /* Set smc instruct start point at 0x0 */ + smu7_program_jump_on_start(hwmgr); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + + PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int vegam_start_smu(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + /* Only start SMC if SMC RAM is not running */ + if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { + smu_data->protected_mode = (uint8_t)(PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); + smu_data->smu7_data.security_hard_key = (uint8_t)(PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); + + /* Check if SMU is running in protected mode */ + if (smu_data->protected_mode == 0) + result = vegam_start_smu_in_non_protection_mode(hwmgr); + else + result = vegam_start_smu_in_protection_mode(hwmgr); + + if (result != 0) + PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); + } + + /* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */ + smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU75_Firmware_Header, SoftRegisters), + &(smu_data->smu7_data.soft_regs_start), + 0x40000); + + result = smu7_request_smu_load_fw(hwmgr); + + return result; +} + +static int vegam_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +static bool vegam_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static uint32_t vegam_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU75_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU75_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU75_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU75_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU75_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU75_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU75_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU75_MAX_LEVELS_MVDD; + case SMU_UVD_MCLK_HANDSHAKE_DISABLE: + return SMU7_UVD_MCLK_HANDSHAKE_DISABLE | + SMU7_VCE_MCLK_HANDSHAKE_DISABLE; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + +static int vegam_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU75_Discrete_DpmTable, + UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), + NULL); + return 0; +} + +static int vegam_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + else + smu_data->smc_state_table.VceBootLevel = 0; + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU75_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, + NULL); + return 0; +} + +static int vegam_update_bif_smc_table(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + int max_entry, i; + + max_entry = (SMU75_MAX_LEVELS_LINK < pcie_table->count) ? + SMU75_MAX_LEVELS_LINK : + pcie_table->count; + /* Setup BIF_SCLK levels */ + for (i = 0; i < max_entry; i++) + smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; + return 0; +} + +static int vegam_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + vegam_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + vegam_update_vce_smc_table(hwmgr); + break; + case SMU_BIF_TABLE: + vegam_update_bif_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +static void vegam_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &vegam_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &vegam_power_tune_data_set_array[0]; + +} + +static int vegam_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU75_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count, level; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + count = data->mvdd_voltage_table.count; + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; level++) { + table->SmioTable2.Pattern[level].Voltage = PP_HOST_TO_SMC_US( + data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[level].Smio = + (uint8_t) level; + table->Smio[level] |= + data->mvdd_voltage_table.entries[level].smio_low; + } + table->SmioMask2 = data->mvdd_voltage_table.mask_low; + + table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); + } + + return 0; +} + +static int vegam_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + uint32_t count, level; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + count = data->vddci_voltage_table.count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; ++level) { + table->SmioTable1.Pattern[level].Voltage = PP_HOST_TO_SMC_US( + data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); + table->SmioTable1.Pattern[level].Smio = (uint8_t) level; + + table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + + return 0; +} + +static int vegam_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + for (count = 0; count < lookup_table->count; count++) { + index = phm_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = + convert_to_vid(lookup_table->entries[index].us_cac_high); + } + + return 0; +} + +static int vegam_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + vegam_populate_smc_vddci_table(hwmgr, table); + vegam_populate_smc_mvdd_table(hwmgr, table); + vegam_populate_cac_table(hwmgr, table); + + return 0; +} + +static int vegam_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_Ulv *state) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int vegam_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + return vegam_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int vegam_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = + (struct vegam_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + +/* To Do move to hwmgr */ + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + *voltage = *mvdd = 0; + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i - 1].vddci) + *voltage |= (dep_table->entries[i - 1].vddci * + VOLTAGE_SCALE) << VDDC_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i - 1].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} + +static void vegam_get_sclk_range_table(struct pp_hwmgr *hwmgr, + SMU75_Discrete_DpmTable *table) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + uint32_t i, ref_clk; + + struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; + + ref_clk = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { + for (i = 0; i < NUM_SCLK_RANGE; i++) { + table->SclkFcwRangeTable[i].vco_setting = + range_table_from_vbios.entry[i].ucVco_setting; + table->SclkFcwRangeTable[i].postdiv = + range_table_from_vbios.entry[i].ucPostdiv; + table->SclkFcwRangeTable[i].fcw_pcc = + range_table_from_vbios.entry[i].usFcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = + range_table_from_vbios.entry[i].usFcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = + range_table_from_vbios.entry[i].usRcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } + return; + } + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + smu_data->range_table[i].trans_lower_frequency = + (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; + smu_data->range_table[i].trans_upper_frequency = + (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; + + table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; + table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; + table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } +} + +static int vegam_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, SMU_SclkSetting *sclk_setting) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + const SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_clock_dividers_ai dividers; + uint32_t ref_clock; + uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; + uint8_t i; + int result; + uint64_t temp; + + sclk_setting->SclkFrequency = clock; + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); + if (result == 0) { + sclk_setting->Fcw_int = dividers.usSclk_fcw_int; + sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; + sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; + sclk_setting->PllRange = dividers.ucSclkPllRange; + sclk_setting->Sclk_slew_rate = 0x400; + sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; + sclk_setting->Pcc_down_slew_rate = 0xffff; + sclk_setting->SSc_En = dividers.ucSscEnable; + sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; + sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; + sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; + return result; + } + + ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + if (clock > smu_data->range_table[i].trans_lower_frequency + && clock <= smu_data->range_table[i].trans_upper_frequency) { + sclk_setting->PllRange = i; + break; + } + } + + sclk_setting->Fcw_int = (uint16_t) + ((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / + ref_clock); + temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw_frac = temp & 0xffff; + + pcc_target_percent = 10; /* Hardcode 10% for now. */ + pcc_target_freq = clock - (clock * pcc_target_percent / 100); + sclk_setting->Pcc_fcw_int = (uint16_t) + ((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / + ref_clock); + + ss_target_percent = 2; /* Hardcode 2% for now. */ + sclk_setting->SSc_En = 0; + if (ss_target_percent) { + sclk_setting->SSc_En = 1; + ss_target_freq = clock - (clock * ss_target_percent / 100); + sclk_setting->Fcw1_int = (uint16_t) + ((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / + ref_clock); + temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw1_frac = temp & 0xffff; + } + + return 0; +} + +static uint8_t vegam_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr) +{ + uint8_t i; + uint32_t temp; + uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK); + + PP_ASSERT_WITH_CODE((clock >= min), + "Engine clock can't satisfy stutter requirement!", + return 0); + for (i = 31; ; i--) { + temp = clock / (i + 1); + + if (temp >= min || i == 0) + break; + } + return i; +} + +static int vegam_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU75_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMU_SclkSetting curr_sclk_setting = { 0 }; + + result = vegam_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); + + /* populate graphics levels */ + result = vegam_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, clock, + &level->MinVoltage, &mvdd); + + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + level->ActivityLevel = (uint16_t)(SclkDPMTuning_VEGAM >> DPMTuning_Activity_Shift); + + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = vegam_get_sleep_divider_id_from_clock(clock, + hwmgr->display_config->min_core_set_clock_in_sr); + + level->SclkSetting = curr_sclk_setting; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); + return 0; +} + +static int vegam_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU75_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU75_Discrete_GraphicsLevel) * + SMU75_MAX_LEVELS_GRAPHICS; + struct SMU75_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + vegam_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + + result = vegam_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result) + return result; + + levels[i].UpHyst = (uint8_t) + (SclkDPMTuning_VEGAM >> DPMTuning_Uphyst_Shift); + levels[i].DownHyst = (uint8_t) + (SclkDPMTuning_VEGAM >> DPMTuning_Downhyst_Shift); + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SPLLShutdownSupport)) + smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].EnabledForActivity = + (hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask >> i) & 0x1; + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } else { + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0)) + hightest_pcie_level_enabled++; + + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0)) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < + hightest_pcie_level_enabled ? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for (i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int vegam_calculate_mclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU75_Discrete_MemoryLevel *mem_level) +{ + struct pp_atomctrl_memory_clock_param_ai mpll_param; + + PP_ASSERT_WITH_CODE(!atomctrl_get_memory_pll_dividers_ai(hwmgr, + clock, &mpll_param), + "Failed to retrieve memory pll parameter.", + return -EINVAL); + + mem_level->MclkFrequency = (uint32_t)mpll_param.ulClock; + mem_level->Fcw_int = (uint16_t)mpll_param.ulMclk_fcw_int; + mem_level->Fcw_frac = (uint16_t)mpll_param.ulMclk_fcw_frac; + mem_level->Postdiv = (uint8_t)mpll_param.ulPostDiv; + + return 0; +} + +static int vegam_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU75_Discrete_MemoryLevel *mem_level) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + uint32_t mclk_stutter_mode_threshold = 60000; + + + if (table_info->vdd_dep_on_mclk) { + result = vegam_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, clock, + &mem_level->MinVoltage, &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE(!result, + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + result = vegam_calculate_mclk_params(hwmgr, clock, mem_level); + PP_ASSERT_WITH_CODE(!result, + "Failed to calculate mclk params.", + return -EINVAL); + + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = (uint16_t) + (MemoryDPMTuning_VEGAM >> DPMTuning_Activity_Shift); + mem_level->StutterEnable = false; + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = hwmgr->display_config->num_display; + data->display_timing.vrefresh = hwmgr->display_config->vrefresh; + + if (mclk_stutter_mode_threshold && + (clock <= mclk_stutter_mode_threshold) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + + return result; +} + +static int vegam_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU75_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU75_Discrete_MemoryLevel) * + SMU75_MAX_LEVELS_MEMORY; + struct SMU75_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = vegam_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + + if (result) + return result; + + levels[i].UpHyst = (uint8_t) + (MemoryDPMTuning_VEGAM >> DPMTuning_Uphyst_Shift); + levels[i].DownHyst = (uint8_t) + (MemoryDPMTuning_VEGAM >> DPMTuning_Downhyst_Shift); + } + + smu_data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + + for (i = 0; i < dpm_table->mclk_table.count; i++) + levels[i].EnabledForActivity = + (hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask >> i) & 0x1; + + levels[dpm_table->mclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int vegam_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int vegam_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU75_Discrete_DpmTable *table) +{ + int result = 0; + uint32_t sclk_frequency; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMIO_Pattern vol_level; + uint32_t mvdd; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + sclk_frequency = data->vbios_boot_state.sclk_bootup_value; + result = vegam_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + sclk_frequency, + &table->ACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE(!result, + "Cannot find ACPI VDDC voltage value " + "in Clock Dependency Table", + ); + + result = vegam_calculate_sclk_params(hwmgr, sclk_frequency, + &(table->ACPILevel.SclkSetting)); + PP_ASSERT_WITH_CODE(!result, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + table->ACPILevel.DeepSleepDivId = 0; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); + + + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; + result = vegam_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + &table->MemoryACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value " + "in Clock Dependency Table", + ); + + if (!vegam_populate_mvdd_value(hwmgr, 0, &vol_level)) + table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); + else + table->MemoryACPILevel.MinMvdd = 0; + + table->MemoryACPILevel.StutterEnable = false; + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); + + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int vegam_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU75_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage = 0; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + + table->VceLevel[count].MinVoltage |= + (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int vegam_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + SMU75_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burst_time; + uint32_t rfsh_rate; + uint32_t misc3; + + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", + return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); + rfsh_rate = cgs_read_register(hwmgr->device, mmMC_ARB_RFSH_RATE); + misc3 = cgs_read_register(hwmgr->device, mmMC_ARB_MISC3); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = PP_HOST_TO_SMC_UL(burst_time); + arb_regs->McArbRfshRate = PP_HOST_TO_SMC_UL(rfsh_rate); + arb_regs->McArbMisc3 = PP_HOST_TO_SMC_UL(misc3); + + return 0; +} + +static int vegam_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct SMU75_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + memset(&arb_regs, 0, sizeof(SMU75_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { + result = vegam_populate_memory_timing_parameters(hwmgr, + hw_data->dpm_table.sclk_table.dpm_levels[i].value, + hw_data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result) + return result; + } + } + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU75_Discrete_MCArbDramTimingTable), + SMC_RAM_END); + return result; +} + +static int vegam_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].MinVoltage = 0; + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + } + + return result; +} + +static int vegam_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + if (result) + return result; + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + if (result) + return result; + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int vegam_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_sclk->entries[level].clk >= + hw_data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_mclk->entries[level].clk >= + hw_data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static int vegam_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table = + &hwmgr->thermal_controller.advanceFanControlParameters; + int i, j, k; + const uint16_t *pdef1; + const uint16_t *pdef2; + + table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!", + ); + + table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + + pdef1 = defaults->BAPMTI_R; + pdef2 = defaults->BAPMTI_RC; + + for (i = 0; i < SMU75_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU75_DTE_SOURCES; j++) { + for (k = 0; k < SMU75_DTE_SINKS; k++) { + table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); + table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); + pdef1++; + pdef2++; + } + } + } + + return 0; +} + +static int vegam_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; + struct vegam_smumgr *smu_data = + (struct vegam_smumgr *)(hwmgr->smu_backend); + + uint8_t i, stretch_amount, volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + uint32_t mask = (1 << ((STRAP_ASIC_RO_MSB - STRAP_ASIC_RO_LSB) + 1)) - 1; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + atomctrl_read_efuse(hwmgr, STRAP_ASIC_RO_LSB, STRAP_ASIC_RO_MSB, + mask, &efuse); + + min = 1200; + max = 2500; + + ro = efuse * (max - min) / 255 + min; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * + 136418 - (ro - 70) * 1000000) / + (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); + volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * + 3232 - (ro - 65) * 1000000) / + (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); + + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); + + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + smu_data->smc_state_table.LdoRefSel = + (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? + table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 5; + /* Populate CKS Lookup Table */ + if (!(stretch_amount == 1 || stretch_amount == 2 || + stretch_amount == 5 || stretch_amount == 3 || + stretch_amount == 4)) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported\n", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +static bool vegam_is_hw_avfs_present(struct pp_hwmgr *hwmgr) +{ + uint32_t efuse; + + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (49 * 4)); + efuse &= 0x00000001; + + if (efuse) + return true; + + return false; +} + +static int vegam_populate_avfs_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); + int result = 0; + struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; + AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; + AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; + uint32_t tmp, i; + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + if (!hwmgr->avfs_supported) + return 0; + + result = atomctrl_get_avfs_information(hwmgr, &avfs_params); + + if (0 == result) { + table->BTCGB_VDROOP_TABLE[0].a0 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); + table->BTCGB_VDROOP_TABLE[0].a1 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); + table->BTCGB_VDROOP_TABLE[0].a2 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); + table->BTCGB_VDROOP_TABLE[1].a0 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); + table->BTCGB_VDROOP_TABLE[1].a1 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); + table->BTCGB_VDROOP_TABLE[1].a2 = + PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); + table->AVFSGB_FUSE_TABLE[0].m1 = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); + table->AVFSGB_FUSE_TABLE[0].m2 = + PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); + table->AVFSGB_FUSE_TABLE[0].b = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); + table->AVFSGB_FUSE_TABLE[0].m1_shift = 24; + table->AVFSGB_FUSE_TABLE[0].m2_shift = 12; + table->AVFSGB_FUSE_TABLE[1].m1 = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); + table->AVFSGB_FUSE_TABLE[1].m2 = + PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); + table->AVFSGB_FUSE_TABLE[1].b = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); + table->AVFSGB_FUSE_TABLE[1].m1_shift = 24; + table->AVFSGB_FUSE_TABLE[1].m2_shift = 12; + table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); + AVFS_meanNsigma.Aconstant[0] = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); + AVFS_meanNsigma.Aconstant[1] = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); + AVFS_meanNsigma.Aconstant[2] = + PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); + AVFS_meanNsigma.DC_tol_sigma = + PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); + AVFS_meanNsigma.Platform_mean = + PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); + AVFS_meanNsigma.PSM_Age_CompFactor = + PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); + AVFS_meanNsigma.Platform_sigma = + PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); + + for (i = 0; i < sclk_table->count; i++) { + AVFS_meanNsigma.Static_Voltage_Offset[i] = + (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); + AVFS_SclkOffset.Sclk_Offset[i] = + PP_HOST_TO_SMC_US((uint16_t) + (sclk_table->entries[i].sclk_offset) / 100); + } + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, AvfsMeanNSigma), + &tmp, SMC_RAM_END); + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_meanNsigma, + sizeof(AVFS_meanNsigma_t), + SMC_RAM_END); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, AvfsSclkOffsetTable), + &tmp, SMC_RAM_END); + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_SclkOffset, + sizeof(AVFS_Sclk_Offset_t), + SMC_RAM_END); + + data->avfs_vdroop_override_setting = + (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); + data->apply_avfs_cks_off_voltage = + (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; + } + return result; +} + +static int vegam_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU75_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = + (struct vegam_smumgr *)(hwmgr->smu_backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!", + ); + } + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + if (config != VR_SVI2_PLANE_2) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + smu_data->smu7_data.soft_regs_start + + offsetof(SMU75_SoftRegisters, AllowMvddSwitch), + 0x1); + } else { + PP_ASSERT_WITH_CODE(false, + "SVI2 Plane 2 is already taken, set MVDD as Static",); + config = VR_STATIC_VOLTAGE; + table->VRConfig = (config << VRCONF_MVDD_SHIFT); + } + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig = (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + smu_data->smu7_data.soft_regs_start + + offsetof(SMU75_SoftRegisters, AllowMvddSwitch), + 0x1); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + +static int vegam_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int vegam_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int vegam_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU75_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + smu_data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + smu_data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int vegam_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int vegam_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + +/* TO DO move to hwmgr */ + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int vegam_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int vegam_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); + + return 0; +} + +static int vegam_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU75_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + if (vegam_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + + if (vegam_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + + if (vegam_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + if (0 != vegam_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + if (vegam_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + if (vegam_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + if (vegam_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + (sizeof(struct SMU75_Discrete_PmFuses) - PMFUSES_AVFSSIZE), + SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int vegam_enable_reconfig_cus(struct pp_hwmgr *hwmgr) +{ + struct amdgpu_device *adev = hwmgr->adev; + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_EnableModeSwitchRLCNotification, + adev->gfx.cu_info.number, + NULL); + + return 0; +} + +static int vegam_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + struct phm_ppt_v1_gpio_table *gpio_table = + (struct phm_ppt_v1_gpio_table *)table_info->gpio_table; + pp_atomctrl_clock_dividers_vi dividers; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + + vegam_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) + vegam_populate_smc_voltage_tables(hwmgr, table); + + table->SystemFlags = 0; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (hw_data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = vegam_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); + } + + result = vegam_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Link Level!", return result); + + result = vegam_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Graphics Level!", return result); + + result = vegam_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Memory Level!", return result); + + result = vegam_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ACPI Level!", return result); + + result = vegam_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize VCE Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = vegam_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to Write ARB settings for the initial state.", return result); + + result = vegam_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize UVD Level!", return result); + + result = vegam_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Boot Level!", return result); + + result = vegam_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Boot State!", return result); + + result = vegam_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = vegam_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + result = vegam_populate_avfs_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate AVFS Parameters!", return result;); + + table->CurrSclkPllRange = 0xff; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + PP_ASSERT_WITH_CODE(hw_data->dpm_table.pcie_speed_table.count >= 1, + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + table->PCIeBootLinkLevel = + hw_data->dpm_table.pcie_speed_table.count; + table->PCIeGenInterval = 1; + table->VRConfig = 0; + + result = vegam_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate VRConfig setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, + VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + if (gpio_table) + table->VRHotLevel = + table_info->gpio_table->vrhot_triggered_sclk_dpm_index; + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, + PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition) && + !smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UseNewGPIOScheme, NULL)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, + THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin)) { + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = + (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + /* Populate BIF_SCLK levels into SMC DPM table */ + for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + smu_data->bif_sclk_table[i], ÷rs); + PP_ASSERT_WITH_CODE(!result, + "Can not find DFS divide id for Sclk", + return result); + + if (i == 0) + table->Ulv.BifSclkDfs = + PP_HOST_TO_SMC_US((uint16_t)(dividers.pll_post_divider)); + else + table->LinkLevel[i - 1].BifSclkDfs = + PP_HOST_TO_SMC_US((uint16_t)(dividers.pll_post_divider)); + } + + for (i = 0; i < SMU75_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU75_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU75_Discrete_DpmTable) - 3 * sizeof(SMU75_PIDController), + SMC_RAM_END); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload dpm data to SMC memory!", return result); + + result = vegam_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate PM fuses to SMC memory!", return result); + + result = vegam_enable_reconfig_cus(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to enable reconfigurable CUs!", return result); + + return 0; +} + +static uint32_t vegam_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU75_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU75_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU75_SoftRegisters, AverageGraphicsActivity); + case AverageMemoryActivity: + return offsetof(SMU75_SoftRegisters, AverageMemoryActivity); + case PreVBlankGap: + return offsetof(SMU75_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU75_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU75_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU75_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU75_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU75_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU75_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU75_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + break; + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU75_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU75_Discrete_DpmTable, VceBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU75_Discrete_DpmTable, LowSclkInterruptThreshold); + } + break; + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static int vegam_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + + DPMTABLE_UPDATE_SCLK + + DPMTABLE_UPDATE_MCLK)) + return vegam_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int vegam_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct vegam_smumgr *smu_data = + (struct vegam_smumgr *)(hwmgr->smu_backend); + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (data->low_sclk_interrupt_threshold != 0)) { + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU75_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + PP_ASSERT_WITH_CODE((result == 0), + "Failed to update SCLK threshold!", return result); + + result = vegam_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +int vegam_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int ret; + + if (!hwmgr->avfs_supported) + return 0; + + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); + if (!ret) { + if (data->apply_avfs_cks_off_voltage) + ret = smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_ApplyAvfsCksOffVoltage, + NULL); + } + + return ret; +} + +static int vegam_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + PP_ASSERT_WITH_CODE(hwmgr->thermal_controller.fanInfo.bNoFan, + "VBIOS fan info is not correct!", + ); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; +} + +const struct pp_smumgr_func vegam_smu_funcs = { + .name = "vegam_smu", + .smu_init = vegam_smu_init, + .smu_fini = smu7_smu_fini, + .start_smu = vegam_start_smu, + .check_fw_load_finish = smu7_check_fw_load_finish, + .request_smu_load_fw = smu7_reload_firmware, + .request_smu_load_specific_fw = NULL, + .send_msg_to_smc = smu7_send_msg_to_smc, + .send_msg_to_smc_with_parameter = smu7_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, + .process_firmware_header = vegam_process_firmware_header, + .is_dpm_running = vegam_is_dpm_running, + .get_mac_definition = vegam_get_mac_definition, + .update_smc_table = vegam_update_smc_table, + .init_smc_table = vegam_init_smc_table, + .get_offsetof = vegam_get_offsetof, + .populate_all_graphic_levels = vegam_populate_all_graphic_levels, + .populate_all_memory_levels = vegam_populate_all_memory_levels, + .update_sclk_threshold = vegam_update_sclk_threshold, + .is_hw_avfs_present = vegam_is_hw_avfs_present, + .thermal_avfs_enable = vegam_thermal_avfs_enable, + .thermal_setup_fan_table = vegam_thermal_setup_fan_table, +}; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h new file mode 100644 index 000000000000..2b6558238500 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vegam_smumgr.h @@ -0,0 +1,75 @@ +/* + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _VEGAM_SMUMANAGER_H +#define _VEGAM_SMUMANAGER_H + + +#include +#include "smu75_discrete.h" +#include "smu7_smumgr.h" + +#define SMC_RAM_END 0x40000 + +#define DPMTuning_Uphyst_Shift 0 +#define DPMTuning_Downhyst_Shift 8 +#define DPMTuning_Activity_Shift 16 + +#define GraphicsDPMTuning_VEGAM 0x001e6400 +#define MemoryDPMTuning_VEGAM 0x000f3c0a +#define SclkDPMTuning_VEGAM 0x002d000a +#define MclkDPMTuning_VEGAM 0x001f100a + + +struct vegam_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; + + uint32_t DisplayCac; + uint32_t BAPM_TEMP_GRADIENT; + uint16_t BAPMTI_R[SMU75_DTE_ITERATIONS * SMU75_DTE_SOURCES * SMU75_DTE_SINKS]; + uint16_t BAPMTI_RC[SMU75_DTE_ITERATIONS * SMU75_DTE_SOURCES * SMU75_DTE_SINKS]; +}; + +struct vegam_range_table { + uint32_t trans_lower_frequency; /* in 10khz */ + uint32_t trans_upper_frequency; +}; + +struct vegam_smumgr { + struct smu7_smumgr smu7_data; + uint8_t protected_mode; + SMU75_Discrete_DpmTable smc_state_table; + struct SMU75_Discrete_Ulv ulv_setting; + struct SMU75_Discrete_PmFuses power_tune_table; + struct vegam_range_table range_table[NUM_SCLK_RANGE]; + const struct vegam_pt_defaults *power_tune_defaults; + uint32_t bif_sclk_table[SMU75_MAX_LEVELS_LINK]; +}; + + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/Makefile b/drivers/gpu/drm/amd/pm/swsmu/Makefile new file mode 100644 index 000000000000..6f281990b7b4 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/Makefile @@ -0,0 +1,36 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# + +AMD_SWSMU_PATH = ../pm/swsmu + +SWSMU_LIBS = smu11 smu12 + +AMD_SWSMU = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/pm/swsmu/,$(SWSMU_LIBS))) + +include $(AMD_SWSMU) + +SWSMU_MGR = amdgpu_smu.o \ + smu_cmn.o \ + +AMD_SWSMU_POWER = $(addprefix $(AMD_SWSMU_PATH)/,$(SWSMU_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_POWER) diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c new file mode 100644 index 000000000000..7d17c4f1b489 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -0,0 +1,2671 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#define SWSMU_CODE_LAYER_L1 + +#include +#include + +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "smu_internal.h" +#include "atom.h" +#include "arcturus_ppt.h" +#include "navi10_ppt.h" +#include "sienna_cichlid_ppt.h" +#include "renoir_ppt.h" +#include "amd_pcie.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf) +{ + size_t size = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + size = smu_get_pp_feature_mask(smu, buf); + + mutex_unlock(&smu->mutex); + + return size; +} + +int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + ret = smu_set_pp_feature_mask(smu, new_mask); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) +{ + int ret = 0; + struct smu_context *smu = &adev->smu; + + if (is_support_sw_smu(adev) && smu->ppt_funcs->get_gfx_off_status) + *value = smu_get_gfx_off_status(smu); + else + ret = -EINVAL; + + return ret; +} + +int smu_set_soft_freq_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) +{ + int ret = 0; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_soft_freq_limited_range) + ret = smu->ppt_funcs->set_soft_freq_limited_range(smu, + clk_type, + min, + max); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_dpm_freq_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + int ret = 0; + + if (!min && !max) + return -EINVAL; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_dpm_ultimate_freq) + ret = smu->ppt_funcs->get_dpm_ultimate_freq(smu, + clk_type, + min, + max); + + mutex_unlock(&smu->mutex); + + return ret; +} + +static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_vcn_enable) + return 0; + + if (atomic_read(&power_gate->vcn_gated) ^ enable) + return 0; + + ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->vcn_gated, !enable); + + return ret; +} + +static int smu_dpm_set_vcn_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->vcn_gate_lock); + + ret = smu_dpm_set_vcn_enable_locked(smu, enable); + + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + +static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + if (!smu->ppt_funcs->dpm_set_jpeg_enable) + return 0; + + if (atomic_read(&power_gate->jpeg_gated) ^ enable) + return 0; + + ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); + if (!ret) + atomic_set(&power_gate->jpeg_gated, !enable); + + return ret; +} + +static int smu_dpm_set_jpeg_enable(struct smu_context *smu, + bool enable) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int ret = 0; + + mutex_lock(&power_gate->jpeg_gate_lock); + + ret = smu_dpm_set_jpeg_enable_locked(smu, enable); + + mutex_unlock(&power_gate->jpeg_gate_lock); + + return ret; +} + +/** + * smu_dpm_set_power_gate - power gate/ungate the specific IP block + * + * @smu: smu_context pointer + * @block_type: the IP block to power gate/ungate + * @gate: to power gate if true, ungate otherwise + * + * This API uses no smu->mutex lock protection due to: + * 1. It is either called by other IP block(gfx/sdma/vcn/uvd/vce). + * This is guarded to be race condition free by the caller. + * 2. Or get called on user setting request of power_dpm_force_performance_level. + * Under this case, the smu->mutex lock protection is already enforced on + * the parent API smu_force_performance_level of the call path. + */ +int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type, + bool gate) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + switch (block_type) { + /* + * Some legacy code of amdgpu_vcn.c and vcn_v2*.c still uses + * AMD_IP_BLOCK_TYPE_UVD for VCN. So, here both of them are kept. + */ + case AMD_IP_BLOCK_TYPE_UVD: + case AMD_IP_BLOCK_TYPE_VCN: + ret = smu_dpm_set_vcn_enable(smu, !gate); + if (ret) + dev_err(smu->adev->dev, "Failed to power %s VCN!\n", + gate ? "gate" : "ungate"); + break; + case AMD_IP_BLOCK_TYPE_GFX: + ret = smu_gfx_off_control(smu, gate); + if (ret) + dev_err(smu->adev->dev, "Failed to %s gfxoff!\n", + gate ? "enable" : "disable"); + break; + case AMD_IP_BLOCK_TYPE_SDMA: + ret = smu_powergate_sdma(smu, gate); + if (ret) + dev_err(smu->adev->dev, "Failed to power %s SDMA!\n", + gate ? "gate" : "ungate"); + break; + case AMD_IP_BLOCK_TYPE_JPEG: + ret = smu_dpm_set_jpeg_enable(smu, !gate); + if (ret) + dev_err(smu->adev->dev, "Failed to power %s JPEG!\n", + gate ? "gate" : "ungate"); + break; + default: + dev_err(smu->adev->dev, "Unsupported block type!\n"); + return -EINVAL; + } + + return ret; +} + +int smu_get_power_num_states(struct smu_context *smu, + struct pp_states_info *state_info) +{ + if (!state_info) + return -EINVAL; + + /* not support power state */ + memset(state_info, 0, sizeof(struct pp_states_info)); + state_info->nums = 1; + state_info->states[0] = POWER_STATE_TYPE_DEFAULT; + + return 0; +} + +bool is_support_sw_smu(struct amdgpu_device *adev) +{ + if (adev->asic_type >= CHIP_ARCTURUS) + return true; + + return false; +} + +int smu_sys_get_pp_table(struct smu_context *smu, void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + uint32_t powerplay_table_size; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu_table->power_play_table && !smu_table->hardcode_pptable) + return -EINVAL; + + mutex_lock(&smu->mutex); + + if (smu_table->hardcode_pptable) + *table = smu_table->hardcode_pptable; + else + *table = smu_table->power_play_table; + + powerplay_table_size = smu_table->power_play_table_size; + + mutex_unlock(&smu->mutex); + + return powerplay_table_size; +} + +int smu_sys_set_pp_table(struct smu_context *smu, void *buf, size_t size) +{ + struct smu_table_context *smu_table = &smu->smu_table; + ATOM_COMMON_TABLE_HEADER *header = (ATOM_COMMON_TABLE_HEADER *)buf; + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (header->usStructureSize != size) { + dev_err(smu->adev->dev, "pp table size not matched !\n"); + return -EIO; + } + + mutex_lock(&smu->mutex); + if (!smu_table->hardcode_pptable) + smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); + if (!smu_table->hardcode_pptable) { + ret = -ENOMEM; + goto failed; + } + + memcpy(smu_table->hardcode_pptable, buf, size); + smu_table->power_play_table = smu_table->hardcode_pptable; + smu_table->power_play_table_size = size; + + /* + * Special hw_fini action(for Navi1x, the DPMs disablement will be + * skipped) may be needed for custom pptable uploading. + */ + smu->uploading_custom_pp_table = true; + + ret = smu_reset(smu); + if (ret) + dev_info(smu->adev->dev, "smu reset failed, ret = %d\n", ret); + + smu->uploading_custom_pp_table = false; + +failed: + mutex_unlock(&smu->mutex); + return ret; +} + +static int smu_get_driver_allowed_feature_mask(struct smu_context *smu) +{ + struct smu_feature *feature = &smu->smu_feature; + int ret = 0; + uint32_t allowed_feature_mask[SMU_FEATURE_MAX/32]; + + mutex_lock(&feature->mutex); + bitmap_zero(feature->allowed, SMU_FEATURE_MAX); + mutex_unlock(&feature->mutex); + + ret = smu_get_allowed_feature_mask(smu, allowed_feature_mask, + SMU_FEATURE_MAX/32); + if (ret) + return ret; + + mutex_lock(&feature->mutex); + bitmap_or(feature->allowed, feature->allowed, + (unsigned long *)allowed_feature_mask, + feature->feature_num); + mutex_unlock(&feature->mutex); + + return ret; +} + +static int smu_set_funcs(struct amdgpu_device *adev) +{ + struct smu_context *smu = &adev->smu; + + if (adev->pm.pp_feature & PP_OVERDRIVE_MASK) + smu->od_enabled = true; + + switch (adev->asic_type) { + case CHIP_NAVI10: + case CHIP_NAVI14: + case CHIP_NAVI12: + navi10_set_ppt_funcs(smu); + break; + case CHIP_ARCTURUS: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + arcturus_set_ppt_funcs(smu); + /* OD is not supported on Arcturus */ + smu->od_enabled =false; + break; + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + sienna_cichlid_set_ppt_funcs(smu); + break; + case CHIP_RENOIR: + renoir_set_ppt_funcs(smu); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smu_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + + smu->adev = adev; + smu->pm_enabled = !!amdgpu_dpm; + smu->is_apu = false; + mutex_init(&smu->mutex); + + return smu_set_funcs(adev); +} + +static int smu_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_power_context *smu_power = &smu->smu_power; + struct smu_power_gate *power_gate = &smu_power->power_gate; + int vcn_gate, jpeg_gate; + int ret = 0; + + if (!smu->ppt_funcs->set_default_dpm_table) + return 0; + + mutex_lock(&power_gate->vcn_gate_lock); + mutex_lock(&power_gate->jpeg_gate_lock); + + vcn_gate = atomic_read(&power_gate->vcn_gated); + jpeg_gate = atomic_read(&power_gate->jpeg_gated); + + ret = smu_dpm_set_vcn_enable_locked(smu, true); + if (ret) + goto err0_out; + + ret = smu_dpm_set_jpeg_enable_locked(smu, true); + if (ret) + goto err1_out; + + ret = smu->ppt_funcs->set_default_dpm_table(smu); + if (ret) + dev_err(smu->adev->dev, + "Failed to setup default dpm clock tables!\n"); + + smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate); +err1_out: + smu_dpm_set_vcn_enable_locked(smu, !vcn_gate); +err0_out: + mutex_unlock(&power_gate->jpeg_gate_lock); + mutex_unlock(&power_gate->vcn_gate_lock); + + return ret; +} + +static int smu_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + int ret = 0; + + if (!smu->pm_enabled) + return 0; + + ret = smu_set_default_od_settings(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup default OD settings!\n"); + return ret; + } + + /* + * Set initialized values (get from vbios) to dpm tables context such as + * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each + * type of clks. + */ + ret = smu_set_default_dpm_table(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup default dpm clock tables!\n"); + return ret; + } + + ret = smu_populate_umd_state_clk(smu); + if (ret) { + dev_err(adev->dev, "Failed to populate UMD state clocks!\n"); + return ret; + } + + ret = smu_get_asic_power_limits(smu); + if (ret) { + dev_err(adev->dev, "Failed to get asic power limits!\n"); + return ret; + } + + smu_get_unique_id(smu); + + smu_handle_task(&adev->smu, + smu->smu_dpm.dpm_level, + AMD_PP_TASK_COMPLETE_INIT, + false); + + return 0; +} + +static int smu_init_fb_allocations(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + struct smu_table *driver_table = &(smu_table->driver_table); + uint32_t max_table_size = 0; + int ret, i; + + /* VRAM allocation for tool table */ + if (tables[SMU_TABLE_PMSTATUSLOG].size) { + ret = amdgpu_bo_create_kernel(adev, + tables[SMU_TABLE_PMSTATUSLOG].size, + tables[SMU_TABLE_PMSTATUSLOG].align, + tables[SMU_TABLE_PMSTATUSLOG].domain, + &tables[SMU_TABLE_PMSTATUSLOG].bo, + &tables[SMU_TABLE_PMSTATUSLOG].mc_address, + &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); + if (ret) { + dev_err(adev->dev, "VRAM allocation for tool table failed!\n"); + return ret; + } + } + + /* VRAM allocation for driver table */ + for (i = 0; i < SMU_TABLE_COUNT; i++) { + if (tables[i].size == 0) + continue; + + if (i == SMU_TABLE_PMSTATUSLOG) + continue; + + if (max_table_size < tables[i].size) + max_table_size = tables[i].size; + } + + driver_table->size = max_table_size; + driver_table->align = PAGE_SIZE; + driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM; + + ret = amdgpu_bo_create_kernel(adev, + driver_table->size, + driver_table->align, + driver_table->domain, + &driver_table->bo, + &driver_table->mc_address, + &driver_table->cpu_addr); + if (ret) { + dev_err(adev->dev, "VRAM allocation for driver table failed!\n"); + if (tables[SMU_TABLE_PMSTATUSLOG].mc_address) + amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo, + &tables[SMU_TABLE_PMSTATUSLOG].mc_address, + &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); + } + + return ret; +} + +static int smu_fini_fb_allocations(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + struct smu_table *driver_table = &(smu_table->driver_table); + + if (!tables) + return 0; + + if (tables[SMU_TABLE_PMSTATUSLOG].mc_address) + amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo, + &tables[SMU_TABLE_PMSTATUSLOG].mc_address, + &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); + + amdgpu_bo_free_kernel(&driver_table->bo, + &driver_table->mc_address, + &driver_table->cpu_addr); + + return 0; +} + +/** + * smu_alloc_memory_pool - allocate memory pool in the system memory + * + * @smu: amdgpu_device pointer + * + * This memory pool will be used for SMC use and msg SetSystemVirtualDramAddr + * and DramLogSetDramAddr can notify it changed. + * + * Returns 0 on success, error on failure. + */ +static int smu_alloc_memory_pool(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *memory_pool = &smu_table->memory_pool; + uint64_t pool_size = smu->pool_size; + int ret = 0; + + if (pool_size == SMU_MEMORY_POOL_SIZE_ZERO) + return ret; + + memory_pool->size = pool_size; + memory_pool->align = PAGE_SIZE; + memory_pool->domain = AMDGPU_GEM_DOMAIN_GTT; + + switch (pool_size) { + case SMU_MEMORY_POOL_SIZE_256_MB: + case SMU_MEMORY_POOL_SIZE_512_MB: + case SMU_MEMORY_POOL_SIZE_1_GB: + case SMU_MEMORY_POOL_SIZE_2_GB: + ret = amdgpu_bo_create_kernel(adev, + memory_pool->size, + memory_pool->align, + memory_pool->domain, + &memory_pool->bo, + &memory_pool->mc_address, + &memory_pool->cpu_addr); + if (ret) + dev_err(adev->dev, "VRAM allocation for dramlog failed!\n"); + break; + default: + break; + } + + return ret; +} + +static int smu_free_memory_pool(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *memory_pool = &smu_table->memory_pool; + + if (memory_pool->size == SMU_MEMORY_POOL_SIZE_ZERO) + return 0; + + amdgpu_bo_free_kernel(&memory_pool->bo, + &memory_pool->mc_address, + &memory_pool->cpu_addr); + + memset(memory_pool, 0, sizeof(struct smu_table)); + + return 0; +} + +static int smu_smc_table_sw_init(struct smu_context *smu) +{ + int ret; + + /** + * Create smu_table structure, and init smc tables such as + * TABLE_PPTABLE, TABLE_WATERMARKS, TABLE_SMU_METRICS, and etc. + */ + ret = smu_init_smc_tables(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to init smc tables!\n"); + return ret; + } + + /** + * Create smu_power_context structure, and allocate smu_dpm_context and + * context size to fill the smu_power_context data. + */ + ret = smu_init_power(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to init smu_init_power!\n"); + return ret; + } + + /* + * allocate vram bos to store smc table contents. + */ + ret = smu_init_fb_allocations(smu); + if (ret) + return ret; + + ret = smu_alloc_memory_pool(smu); + if (ret) + return ret; + + ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); + if (ret) + return ret; + + return 0; +} + +static int smu_smc_table_sw_fini(struct smu_context *smu) +{ + int ret; + + smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); + + ret = smu_free_memory_pool(smu); + if (ret) + return ret; + + ret = smu_fini_fb_allocations(smu); + if (ret) + return ret; + + ret = smu_fini_power(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to init smu_fini_power!\n"); + return ret; + } + + ret = smu_fini_smc_tables(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to smu_fini_smc_tables!\n"); + return ret; + } + + return 0; +} + +static void smu_throttling_logging_work_fn(struct work_struct *work) +{ + struct smu_context *smu = container_of(work, struct smu_context, + throttling_logging_work); + + smu_log_thermal_throttling(smu); +} + +static int smu_sw_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + int ret; + + smu->pool_size = adev->pm.smu_prv_buffer_size; + smu->smu_feature.feature_num = SMU_FEATURE_MAX; + mutex_init(&smu->smu_feature.mutex); + bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX); + bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX); + bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); + + mutex_init(&smu->smu_baco.mutex); + smu->smu_baco.state = SMU_BACO_STATE_EXIT; + smu->smu_baco.platform_support = false; + + mutex_init(&smu->sensor_lock); + mutex_init(&smu->metrics_lock); + 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; + + atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); + atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); + mutex_init(&smu->smu_power.power_gate.vcn_gate_lock); + mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock); + + smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; + smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; + smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; + smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; + smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; + smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; + smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; + smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6; + + smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; + smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; + smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; + smu->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; + smu->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; + smu->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE; + smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM; + smu->display_config = &adev->pm.pm_display_cfg; + + smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; + smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; + ret = smu_init_microcode(smu); + if (ret) { + dev_err(adev->dev, "Failed to load smu firmware!\n"); + return ret; + } + + ret = smu_smc_table_sw_init(smu); + if (ret) { + dev_err(adev->dev, "Failed to sw init smc table!\n"); + return ret; + } + + ret = smu_register_irq_handler(smu); + if (ret) { + dev_err(adev->dev, "Failed to register smc irq handler!\n"); + return ret; + } + + return 0; +} + +static int smu_sw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + int ret; + + ret = smu_smc_table_sw_fini(smu); + if (ret) { + dev_err(adev->dev, "Failed to sw fini smc table!\n"); + return ret; + } + + smu_fini_microcode(smu); + + return 0; +} + +static int smu_get_thermal_temperature_range(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_temperature_range *range = + &smu->thermal_range; + int ret = 0; + + if (!smu->ppt_funcs->get_thermal_temperature_range) + return 0; + + ret = smu->ppt_funcs->get_thermal_temperature_range(smu, range); + if (ret) + return ret; + + adev->pm.dpm.thermal.min_temp = range->min; + adev->pm.dpm.thermal.max_temp = range->max; + adev->pm.dpm.thermal.max_edge_emergency_temp = range->edge_emergency_max; + adev->pm.dpm.thermal.min_hotspot_temp = range->hotspot_min; + adev->pm.dpm.thermal.max_hotspot_crit_temp = range->hotspot_crit_max; + adev->pm.dpm.thermal.max_hotspot_emergency_temp = range->hotspot_emergency_max; + adev->pm.dpm.thermal.min_mem_temp = range->mem_min; + adev->pm.dpm.thermal.max_mem_crit_temp = range->mem_crit_max; + adev->pm.dpm.thermal.max_mem_emergency_temp = range->mem_emergency_max; + + return ret; +} + +static int smu_smc_hw_setup(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t pcie_gen = 0, pcie_width = 0; + int ret; + + if (adev->in_suspend && smu_is_dpm_running(smu)) { + dev_info(adev->dev, "dpm has been enabled\n"); + return 0; + } + + ret = smu_init_display_count(smu, 0); + if (ret) { + dev_info(adev->dev, "Failed to pre-set display count as 0!\n"); + return ret; + } + + ret = smu_set_driver_table_location(smu); + if (ret) { + dev_err(adev->dev, "Failed to SetDriverDramAddr!\n"); + return ret; + } + + /* + * Set PMSTATUSLOG table bo address with SetToolsDramAddr MSG for tools. + */ + ret = smu_set_tool_table_location(smu); + if (ret) { + dev_err(adev->dev, "Failed to SetToolsDramAddr!\n"); + return ret; + } + + /* + * Use msg SetSystemVirtualDramAddr and DramLogSetDramAddr can notify + * pool location. + */ + ret = smu_notify_memory_pool_location(smu); + if (ret) { + dev_err(adev->dev, "Failed to SetDramLogDramAddr!\n"); + return ret; + } + + /* smu_dump_pptable(smu); */ + /* + * Copy pptable bo in the vram to smc with SMU MSGs such as + * SetDriverDramAddr and TransferTableDram2Smu. + */ + ret = smu_write_pptable(smu); + if (ret) { + dev_err(adev->dev, "Failed to transfer pptable to SMC!\n"); + return ret; + } + + /* issue Run*Btc msg */ + ret = smu_run_btc(smu); + if (ret) + return ret; + + ret = smu_feature_set_allowed_mask(smu); + if (ret) { + dev_err(adev->dev, "Failed to set driver allowed features mask!\n"); + return ret; + } + + ret = smu_system_features_control(smu, true); + if (ret) { + dev_err(adev->dev, "Failed to enable requested dpm features!\n"); + return ret; + } + + if (!smu_is_dpm_running(smu)) + dev_info(adev->dev, "dpm has been disabled\n"); + + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) + pcie_gen = 3; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + pcie_gen = 2; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) + pcie_gen = 1; + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) + pcie_gen = 0; + + /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 + * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 + * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 + */ + if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) + pcie_width = 6; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) + pcie_width = 5; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) + pcie_width = 4; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) + pcie_width = 3; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) + pcie_width = 2; + else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) + pcie_width = 1; + ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width); + if (ret) { + dev_err(adev->dev, "Attempt to override pcie params failed!\n"); + return ret; + } + + ret = smu_get_thermal_temperature_range(smu); + if (ret) { + dev_err(adev->dev, "Failed to get thermal temperature ranges!\n"); + return ret; + } + + ret = smu_enable_thermal_alert(smu); + if (ret) { + dev_err(adev->dev, "Failed to enable thermal alert!\n"); + return ret; + } + + ret = smu_disable_umc_cdr_12gbps_workaround(smu); + if (ret) { + dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n"); + return ret; + } + + /* + * For Navi1X, manually switch it to AC mode as PMFW + * may boot it with DC mode. + */ + ret = smu_set_power_source(smu, + adev->pm.ac_power ? SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) { + dev_err(adev->dev, "Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); + return ret; + } + + ret = smu_notify_display_change(smu); + if (ret) + return ret; + + /* + * Set min deep sleep dce fclk with bootup value from vbios via + * SetMinDeepSleepDcefclk MSG. + */ + ret = smu_set_min_dcef_deep_sleep(smu, + smu->smu_table.boot_values.dcefclk / 100); + if (ret) + return ret; + + return ret; +} + +static int smu_start_smc_engine(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { + if (adev->asic_type < CHIP_NAVI10) { + if (smu->ppt_funcs->load_microcode) { + ret = smu->ppt_funcs->load_microcode(smu); + if (ret) + return ret; + } + } + } + + if (smu->ppt_funcs->check_fw_status) { + ret = smu->ppt_funcs->check_fw_status(smu); + if (ret) { + dev_err(adev->dev, "SMC is not ready\n"); + return ret; + } + } + + /* + * Send msg GetDriverIfVersion to check if the return value is equal + * with DRIVER_IF_VERSION of smc header. + */ + ret = smu_check_fw_version(smu); + if (ret) + return ret; + + return ret; +} + +static int smu_hw_init(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + + if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { + smu->pm_enabled = false; + return 0; + } + + ret = smu_start_smc_engine(smu); + if (ret) { + dev_err(adev->dev, "SMC engine is not correctly up!\n"); + return ret; + } + + if (smu->is_apu) { + smu_powergate_sdma(&adev->smu, false); + smu_dpm_set_vcn_enable(smu, true); + smu_dpm_set_jpeg_enable(smu, true); + smu_set_gfx_cgpg(&adev->smu, true); + } + + if (!smu->pm_enabled) + return 0; + + /* get boot_values from vbios to set revision, gfxclk, and etc. */ + ret = smu_get_vbios_bootup_values(smu); + if (ret) { + dev_err(adev->dev, "Failed to get VBIOS boot clock values!\n"); + return ret; + } + + ret = smu_setup_pptable(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup pptable!\n"); + return ret; + } + + ret = smu_get_driver_allowed_feature_mask(smu); + if (ret) + return ret; + + ret = smu_smc_hw_setup(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup smc hw!\n"); + return ret; + } + + /* + * Move maximum sustainable clock retrieving here considering + * 1. It is not needed on resume(from S3). + * 2. DAL settings come between .hw_init and .late_init of SMU. + * And DAL needs to know the maximum sustainable clocks. Thus + * it cannot be put in .late_init(). + */ + ret = smu_init_max_sustainable_clocks(smu); + if (ret) { + dev_err(adev->dev, "Failed to init max sustainable clocks!\n"); + return ret; + } + + adev->pm.dpm_enabled = true; + + dev_info(adev->dev, "SMU is initialized successfully!\n"); + + return 0; +} + +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_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || + ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); + + /* + * For custom pptable uploading, skip the DPM features + * disable process on Navi1x ASICs. + * - As the gfx related features are under control of + * RLC on those ASICs. RLC reinitialization will be + * needed to reenable them. That will cost much more + * efforts. + * + * - SMU firmware can handle the DPM reenablement + * properly. + */ + if (smu->uploading_custom_pp_table && + (adev->asic_type >= CHIP_NAVI10) && + (adev->asic_type <= CHIP_NAVI12)) + return 0; + + /* + * For Sienna_Cichlid, PMFW will handle the features disablement properly + * on BACO in. Driver involvement is unnecessary. + */ + if ((adev->asic_type == CHIP_SIENNA_CICHLID) && + use_baco) + return 0; + + /* + * For gpu reset, runpm and hibernation through BACO, + * BACO feature has to be kept enabled. + */ + if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { + ret = smu_disable_all_features_with_exception(smu, + SMU_FEATURE_BACO_BIT); + if (ret) + dev_err(adev->dev, "Failed to disable smu features except BACO.\n"); + } else { + ret = smu_system_features_control(smu, false); + if (ret) + dev_err(adev->dev, "Failed to disable smu features.\n"); + } + + if (adev->asic_type >= CHIP_NAVI10 && + adev->gfx.rlc.funcs->stop) + adev->gfx.rlc.funcs->stop(adev); + + return ret; +} + +static int smu_smc_hw_cleanup(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + cancel_work_sync(&smu->throttling_logging_work); + + ret = smu_disable_thermal_alert(smu); + if (ret) { + dev_err(adev->dev, "Fail to disable thermal alert!\n"); + return ret; + } + + ret = smu_disable_dpms(smu); + if (ret) { + dev_err(adev->dev, "Fail to disable dpm features!\n"); + return ret; + } + + return 0; +} + +static int smu_hw_fini(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + int ret = 0; + + if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) + return 0; + + if (smu->is_apu) { + smu_powergate_sdma(&adev->smu, true); + smu_dpm_set_vcn_enable(smu, false); + smu_dpm_set_jpeg_enable(smu, false); + } + + if (!smu->pm_enabled) + return 0; + + adev->pm.dpm_enabled = false; + + ret = smu_smc_hw_cleanup(smu); + if (ret) + return ret; + + return 0; +} + +int smu_reset(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + ret = smu_hw_fini(adev); + if (ret) + return ret; + + ret = smu_hw_init(adev); + if (ret) + return ret; + + ret = smu_late_init(adev); + + return ret; +} + +static int smu_suspend(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + int ret; + + if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) + return 0; + + if (!smu->pm_enabled) + return 0; + + adev->pm.dpm_enabled = false; + + ret = smu_smc_hw_cleanup(smu); + if (ret) + return ret; + + smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); + + if (smu->is_apu) + smu_set_gfx_cgpg(&adev->smu, false); + + return 0; +} + +static int smu_resume(void *handle) +{ + int ret; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + struct smu_context *smu = &adev->smu; + + if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) + return 0; + + if (!smu->pm_enabled) + return 0; + + dev_info(adev->dev, "SMU is resuming...\n"); + + ret = smu_start_smc_engine(smu); + if (ret) { + dev_err(adev->dev, "SMC engine is not correctly up!\n"); + return ret; + } + + ret = smu_smc_hw_setup(smu); + if (ret) { + dev_err(adev->dev, "Failed to setup smc hw!\n"); + return ret; + } + + if (smu->is_apu) + smu_set_gfx_cgpg(&adev->smu, true); + + smu->disable_uclk_switch = 0; + + adev->pm.dpm_enabled = true; + + dev_info(adev->dev, "SMU is resumed successfully!\n"); + + return 0; +} + +int smu_display_configuration_change(struct smu_context *smu, + const struct amd_pp_display_configuration *display_config) +{ + int index = 0; + int num_of_active_display = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!display_config) + return -EINVAL; + + mutex_lock(&smu->mutex); + + smu_set_min_dcef_deep_sleep(smu, + display_config->min_dcef_deep_sleep_set_clk / 100); + + for (index = 0; index < display_config->num_path_including_non_display; index++) { + if (display_config->displays[index].controller_id != 0) + num_of_active_display++; + } + + smu_set_active_display_count(smu, num_of_active_display); + + smu_store_cc6_data(smu, display_config->cpu_pstate_separation_time, + display_config->cpu_cc6_disable, + display_config->cpu_pstate_disable, + display_config->nb_pstate_switch_disable); + + mutex_unlock(&smu->mutex); + + return 0; +} + +static int smu_get_clock_info(struct smu_context *smu, + struct smu_clock_info *clk_info, + enum smu_perf_level_designation designation) +{ + int ret; + struct smu_performance_level level = {0}; + + if (!clk_info) + return -EINVAL; + + ret = smu_get_perf_level(smu, PERF_LEVEL_ACTIVITY, &level); + if (ret) + return -EINVAL; + + clk_info->min_mem_clk = level.memory_clock; + clk_info->min_eng_clk = level.core_clock; + clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width; + + ret = smu_get_perf_level(smu, designation, &level); + if (ret) + return -EINVAL; + + clk_info->min_mem_clk = level.memory_clock; + clk_info->min_eng_clk = level.core_clock; + clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width; + + return 0; +} + +int smu_get_current_clocks(struct smu_context *smu, + struct amd_pp_clock_info *clocks) +{ + struct amd_pp_simple_clock_info simple_clocks = {0}; + struct smu_clock_info hw_clocks; + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + smu_get_dal_power_level(smu, &simple_clocks); + + if (smu->support_power_containment) + ret = smu_get_clock_info(smu, &hw_clocks, + PERF_LEVEL_POWER_CONTAINMENT); + else + ret = smu_get_clock_info(smu, &hw_clocks, PERF_LEVEL_ACTIVITY); + + if (ret) { + dev_err(smu->adev->dev, "Error in smu_get_clock_info\n"); + goto failed; + } + + clocks->min_engine_clock = hw_clocks.min_eng_clk; + clocks->max_engine_clock = hw_clocks.max_eng_clk; + clocks->min_memory_clock = hw_clocks.min_mem_clk; + clocks->max_memory_clock = hw_clocks.max_mem_clk; + clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth; + clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth; + clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; + clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; + + if (simple_clocks.level == 0) + clocks->max_clocks_state = PP_DAL_POWERLEVEL_7; + else + clocks->max_clocks_state = simple_clocks.level; + + if (!smu_get_current_shallow_sleep_clocks(smu, &hw_clocks)) { + clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; + clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; + } + +failed: + mutex_unlock(&smu->mutex); + return ret; +} + +static int smu_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int smu_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static int smu_enable_umd_pstate(void *handle, + enum amd_dpm_forced_level *level) +{ + uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; + + struct smu_context *smu = (struct smu_context*)(handle); + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + + if (!smu->is_apu && !smu_dpm_ctx->dpm_context) + return -EINVAL; + + if (!(smu_dpm_ctx->dpm_level & profile_mode_mask)) { + /* enter umd pstate, save current level, disable gfx cg*/ + if (*level & profile_mode_mask) { + smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; + smu_dpm_ctx->enable_umd_pstate = true; + amdgpu_device_ip_set_powergating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_UNGATE); + amdgpu_device_ip_set_clockgating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_UNGATE); + } + } else { + /* exit umd pstate, restore level, enable gfx cg*/ + if (!(*level & profile_mode_mask)) { + if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) + *level = smu_dpm_ctx->saved_dpm_level; + smu_dpm_ctx->enable_umd_pstate = false; + amdgpu_device_ip_set_clockgating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_CG_STATE_GATE); + amdgpu_device_ip_set_powergating_state(smu->adev, + AMD_IP_BLOCK_TYPE_GFX, + AMD_PG_STATE_GATE); + } + } + + return 0; +} + +static int smu_adjust_power_state_dynamic(struct smu_context *smu, + enum amd_dpm_forced_level level, + bool skip_display_settings) +{ + int ret = 0; + int index = 0; + long workload; + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + + if (!skip_display_settings) { + ret = smu_display_config_changed(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to change display config!"); + return ret; + } + } + + ret = smu_apply_clocks_adjust_rules(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to apply clocks adjust rules!"); + return ret; + } + + if (!skip_display_settings) { + ret = smu_notify_smc_display_config(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to notify smc display config!"); + return ret; + } + } + + if (smu_dpm_ctx->dpm_level != level) { + ret = smu_asic_set_performance_level(smu, level); + if (ret) { + dev_err(smu->adev->dev, "Failed to set performance level!"); + return ret; + } + + /* update the saved copy */ + smu_dpm_ctx->dpm_level = level; + } + + if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + index = fls(smu->workload_mask); + index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; + workload = smu->workload_setting[index]; + + if (smu->power_profile_mode != workload) + smu_set_power_profile_mode(smu, &workload, 0, false); + } + + return ret; +} + +int smu_handle_task(struct smu_context *smu, + enum amd_dpm_forced_level level, + enum amd_pp_task task_id, + bool lock_needed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (lock_needed) + mutex_lock(&smu->mutex); + + switch (task_id) { + case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: + ret = smu_pre_display_config_changed(smu); + if (ret) + goto out; + ret = smu_set_cpu_power_state(smu); + if (ret) + goto out; + ret = smu_adjust_power_state_dynamic(smu, level, false); + break; + case AMD_PP_TASK_COMPLETE_INIT: + case AMD_PP_TASK_READJUST_POWER_STATE: + ret = smu_adjust_power_state_dynamic(smu, level, true); + break; + default: + break; + } + +out: + if (lock_needed) + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_switch_power_profile(struct smu_context *smu, + enum PP_SMC_POWER_PROFILE type, + bool en) +{ + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + long workload; + uint32_t index; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) + return -EINVAL; + + mutex_lock(&smu->mutex); + + if (!en) { + smu->workload_mask &= ~(1 << smu->workload_prority[type]); + index = fls(smu->workload_mask); + index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; + workload = smu->workload_setting[index]; + } else { + smu->workload_mask |= (1 << smu->workload_prority[type]); + index = fls(smu->workload_mask); + index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; + workload = smu->workload_setting[index]; + } + + if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) + smu_set_power_profile_mode(smu, &workload, 0, false); + + mutex_unlock(&smu->mutex); + + return 0; +} + +enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + enum amd_dpm_forced_level level; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->is_apu && !smu_dpm_ctx->dpm_context) + return -EINVAL; + + mutex_lock(&(smu->mutex)); + level = smu_dpm_ctx->dpm_level; + mutex_unlock(&(smu->mutex)); + + return level; +} + +int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level) +{ + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->is_apu && !smu_dpm_ctx->dpm_context) + return -EINVAL; + + mutex_lock(&smu->mutex); + + ret = smu_enable_umd_pstate(smu, &level); + if (ret) { + mutex_unlock(&smu->mutex); + return ret; + } + + ret = smu_handle_task(smu, level, + AMD_PP_TASK_READJUST_POWER_STATE, + false); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_display_count(struct smu_context *smu, uint32_t count) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + ret = smu_init_display_count(smu, count); + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t mask) +{ + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { + dev_dbg(smu->adev->dev, "force clock level is for dpm manual mode only.\n"); + return -EINVAL; + } + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) + ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask); + + mutex_unlock(&smu->mutex); + + return ret; +} + +/* + * On system suspending or resetting, the dpm_enabled + * flag will be cleared. So that those SMU services which + * are not supported will be gated. + * However, the mp1 state setting should still be granted + * even if the dpm_enabled cleared. + */ +int smu_set_mp1_state(struct smu_context *smu, + enum pp_mp1_state mp1_state) +{ + uint16_t msg; + int ret; + + if (!smu->pm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + switch (mp1_state) { + case PP_MP1_STATE_SHUTDOWN: + msg = SMU_MSG_PrepareMp1ForShutdown; + break; + case PP_MP1_STATE_UNLOAD: + msg = SMU_MSG_PrepareMp1ForUnload; + break; + case PP_MP1_STATE_RESET: + msg = SMU_MSG_PrepareMp1ForReset; + break; + case PP_MP1_STATE_NONE: + default: + mutex_unlock(&smu->mutex); + return 0; + } + + 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"); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs || !smu->ppt_funcs->set_df_cstate) + return 0; + + mutex_lock(&smu->mutex); + + ret = smu->ppt_funcs->set_df_cstate(smu, state); + if (ret) + dev_err(smu->adev->dev, "[SetDfCstate] failed!\n"); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_allow_xgmi_power_down(struct smu_context *smu, bool en) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs || !smu->ppt_funcs->allow_xgmi_power_down) + return 0; + + mutex_lock(&smu->mutex); + + ret = smu->ppt_funcs->allow_xgmi_power_down(smu, en); + if (ret) + dev_err(smu->adev->dev, "[AllowXgmiPowerDown] failed!\n"); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_write_watermarks_table(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + ret = smu_set_watermarks_table(smu, NULL); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (!smu->disable_watermark && + smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_set_watermarks_table(smu, clock_ranges); + + if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { + smu->watermarks_bitmap |= WATERMARKS_EXIST; + smu->watermarks_bitmap &= ~WATERMARKS_LOADED; + } + } + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_ac_dc(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + /* controlled by firmware */ + if (smu->dc_controlled_by_gpio) + return 0; + + mutex_lock(&smu->mutex); + ret = smu_set_power_source(smu, + smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) + dev_err(smu->adev->dev, "Failed to switch to %s mode!\n", + smu->adev->pm.ac_power ? "AC" : "DC"); + mutex_unlock(&smu->mutex); + + return ret; +} + +const struct amd_ip_funcs smu_ip_funcs = { + .name = "smu", + .early_init = smu_early_init, + .late_init = smu_late_init, + .sw_init = smu_sw_init, + .sw_fini = smu_sw_fini, + .hw_init = smu_hw_init, + .hw_fini = smu_hw_fini, + .suspend = smu_suspend, + .resume = smu_resume, + .is_idle = NULL, + .check_soft_reset = NULL, + .wait_for_idle = NULL, + .soft_reset = NULL, + .set_clockgating_state = smu_set_clockgating_state, + .set_powergating_state = smu_set_powergating_state, + .enable_umd_pstate = smu_enable_umd_pstate, +}; + +const struct amdgpu_ip_block_version smu_v11_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 11, + .minor = 0, + .rev = 0, + .funcs = &smu_ip_funcs, +}; + +const struct amdgpu_ip_block_version smu_v12_0_ip_block = +{ + .type = AMD_IP_BLOCK_TYPE_SMC, + .major = 12, + .minor = 0, + .rev = 0, + .funcs = &smu_ip_funcs, +}; + +int smu_load_microcode(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->load_microcode) + ret = smu->ppt_funcs->load_microcode(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_check_fw_status(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->check_fw_status) + ret = smu->ppt_funcs->check_fw_status(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled) +{ + int ret = 0; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_gfx_cgpg) + ret = smu->ppt_funcs->set_gfx_cgpg(smu, enabled); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_fan_speed_rpm) + ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_power_limit(struct smu_context *smu, + uint32_t *limit, + bool max_setting) +{ + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + *limit = (max_setting ? smu->max_power_limit : smu->current_power_limit); + + mutex_unlock(&smu->mutex); + + return 0; +} + +int smu_set_power_limit(struct smu_context *smu, uint32_t limit) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (limit > smu->max_power_limit) { + dev_err(smu->adev->dev, + "New power limit (%d) is over the max allowed %d\n", + limit, smu->max_power_limit); + goto out; + } + + if (!limit) + limit = smu->current_power_limit; + + if (smu->ppt_funcs->set_power_limit) + ret = smu->ppt_funcs->set_power_limit(smu, limit); + +out: + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->print_clk_levels) + ret = smu->ppt_funcs->print_clk_levels(smu, clk_type, buf); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_od_percentage) + ret = smu->ppt_funcs->get_od_percentage(smu, type); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_od_percentage) + ret = smu->ppt_funcs->set_od_percentage(smu, type, value); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_od_edit_dpm_table(struct smu_context *smu, + enum PP_OD_DPM_TABLE_COMMAND type, + long *input, uint32_t size) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->od_edit_dpm_table) { + ret = smu->ppt_funcs->od_edit_dpm_table(smu, type, input, size); + if (!ret && (type == PP_OD_COMMIT_DPM_TABLE)) + ret = smu_handle_task(smu, + smu->smu_dpm.dpm_level, + AMD_PP_TASK_READJUST_POWER_STATE, + false); + } + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!data || !size) + return -EINVAL; + + 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; + *size = 4; + break; + case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK: + *((uint32_t *)data) = pstate_table->uclk_pstate.standard * 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: + ret = smu_feature_get_enabled_mask(smu, (uint32_t *)data, 2); + *size = 8; + break; + case AMDGPU_PP_SENSOR_UVD_POWER: + *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT) ? 1 : 0; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VCE_POWER: + *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT) ? 1 : 0; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VCN_POWER_STATE: + *(uint32_t *)data = atomic_read(&smu->smu_power.power_gate.vcn_gated) ? 0: 1; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MIN_FAN_RPM: + *(uint32_t *)data = 0; + *size = 4; + break; + default: + *size = 0; + ret = -EOPNOTSUPP; + break; + } + +unlock: + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_power_profile_mode(struct smu_context *smu, char *buf) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_power_profile_mode) + ret = smu->ppt_funcs->get_power_profile_mode(smu, buf); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_power_profile_mode(struct smu_context *smu, + long *param, + uint32_t param_size, + bool lock_needed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (lock_needed) + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_power_profile_mode) + ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size); + + if (lock_needed) + mutex_unlock(&smu->mutex); + + return ret; +} + + +int smu_get_fan_control_mode(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_fan_control_mode) + ret = smu->ppt_funcs->get_fan_control_mode(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_fan_control_mode(struct smu_context *smu, int value) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_fan_control_mode) + ret = smu->ppt_funcs->set_fan_control_mode(smu, value); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_fan_speed_percent) + ret = smu->ppt_funcs->get_fan_speed_percent(smu, speed); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_fan_speed_percent) + ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_fan_speed_rpm) + ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + ret = smu_set_min_dcef_deep_sleep(smu, clk); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_active_display_count(struct smu_context *smu, uint32_t count) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (smu->ppt_funcs->set_active_display_count) + ret = smu->ppt_funcs->set_active_display_count(smu, count); + + return ret; +} + +int smu_get_clock_by_type(struct smu_context *smu, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_clock_by_type) + ret = smu->ppt_funcs->get_clock_by_type(smu, type, clocks); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_max_high_clocks(struct smu_context *smu, + struct amd_pp_simple_clock_info *clocks) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_max_high_clocks) + ret = smu->ppt_funcs->get_max_high_clocks(smu, clocks); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_clock_by_type_with_latency(struct smu_context *smu, + enum smu_clk_type clk_type, + struct pp_clock_levels_with_latency *clocks) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_clock_by_type_with_latency) + ret = smu->ppt_funcs->get_clock_by_type_with_latency(smu, clk_type, clocks); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_clock_by_type_with_voltage(struct smu_context *smu, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_clock_by_type_with_voltage) + ret = smu->ppt_funcs->get_clock_by_type_with_voltage(smu, type, clocks); + + mutex_unlock(&smu->mutex); + + return ret; +} + + +int smu_display_clock_voltage_request(struct smu_context *smu, + struct pp_display_clock_request *clock_req) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->display_clock_voltage_request) + ret = smu->ppt_funcs->display_clock_voltage_request(smu, clock_req); + + mutex_unlock(&smu->mutex); + + return ret; +} + + +int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disable_memory_clock_switch) +{ + int ret = -EINVAL; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->display_disable_memory_clock_switch) + ret = smu->ppt_funcs->display_disable_memory_clock_switch(smu, disable_memory_clock_switch); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_notify_smu_enable_pwe(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->notify_smu_enable_pwe) + ret = smu->ppt_funcs->notify_smu_enable_pwe(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_set_xgmi_pstate(struct smu_context *smu, + uint32_t pstate) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_xgmi_pstate) + ret = smu->ppt_funcs->set_xgmi_pstate(smu, pstate); + + mutex_unlock(&smu->mutex); + + if(ret) + dev_err(smu->adev->dev, "Failed to set XGMI pstate!\n"); + + return ret; +} + +int smu_set_azalia_d3_pme(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->set_azalia_d3_pme) + ret = smu->ppt_funcs->set_azalia_d3_pme(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +/* + * On system suspending or resetting, the dpm_enabled + * flag will be cleared. So that those SMU services which + * are not supported will be gated. + * + * However, the baco/mode1 reset should still be granted + * as they are still supported and necessary. + */ +bool smu_baco_is_support(struct smu_context *smu) +{ + bool ret = false; + + if (!smu->pm_enabled) + return false; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs && smu->ppt_funcs->baco_is_support) + ret = smu->ppt_funcs->baco_is_support(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_baco_get_state(struct smu_context *smu, enum smu_baco_state *state) +{ + if (smu->ppt_funcs->baco_get_state) + return -EINVAL; + + mutex_lock(&smu->mutex); + *state = smu->ppt_funcs->baco_get_state(smu); + mutex_unlock(&smu->mutex); + + return 0; +} + +int smu_baco_enter(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->baco_enter) + ret = smu->ppt_funcs->baco_enter(smu); + + mutex_unlock(&smu->mutex); + + if (ret) + dev_err(smu->adev->dev, "Failed to enter BACO state!\n"); + + return ret; +} + +int smu_baco_exit(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->baco_exit) + ret = smu->ppt_funcs->baco_exit(smu); + + mutex_unlock(&smu->mutex); + + if (ret) + dev_err(smu->adev->dev, "Failed to exit BACO state!\n"); + + return ret; +} + +bool smu_mode1_reset_is_support(struct smu_context *smu) +{ + bool ret = false; + + if (!smu->pm_enabled) + return false; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs && smu->ppt_funcs->mode1_reset_is_support) + ret = smu->ppt_funcs->mode1_reset_is_support(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_mode1_reset(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->mode1_reset) + ret = smu->ppt_funcs->mode1_reset(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_mode2_reset(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->mode2_reset) + ret = smu->ppt_funcs->mode2_reset(smu); + + mutex_unlock(&smu->mutex); + + if (ret) + dev_err(smu->adev->dev, "Mode2 reset failed!\n"); + + return ret; +} + +int smu_get_max_sustainable_clocks_by_dc(struct smu_context *smu, + struct pp_smu_nv_clock_table *max_clocks) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_max_sustainable_clocks_by_dc) + ret = smu->ppt_funcs->get_max_sustainable_clocks_by_dc(smu, max_clocks); + + mutex_unlock(&smu->mutex); + + return ret; +} + +int smu_get_uclk_dpm_states(struct smu_context *smu, + unsigned int *clock_values_in_khz, + unsigned int *num_states) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_uclk_dpm_states) + ret = smu->ppt_funcs->get_uclk_dpm_states(smu, clock_values_in_khz, num_states); + + mutex_unlock(&smu->mutex); + + return ret; +} + +enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu) +{ + enum amd_pm_state_type pm_state = POWER_STATE_TYPE_DEFAULT; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_current_power_state) + pm_state = smu->ppt_funcs->get_current_power_state(smu); + + mutex_unlock(&smu->mutex); + + return pm_state; +} + +int smu_get_dpm_clock_table(struct smu_context *smu, + struct dpm_clocks *clock_table) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->get_dpm_clock_table) + ret = smu->ppt_funcs->get_dpm_clock_table(smu, clock_table); + + mutex_unlock(&smu->mutex); + + return ret; +} + +ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + ssize_t size; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + if (!smu->ppt_funcs->get_gpu_metrics) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + size = smu->ppt_funcs->get_gpu_metrics(smu, table); + + mutex_unlock(&smu->mutex); + + return size; +} + +int smu_enable_mgpu_fan_boost(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) + return -EOPNOTSUPP; + + mutex_lock(&smu->mutex); + + if (smu->ppt_funcs->enable_mgpu_fan_boost) + ret = smu->ppt_funcs->enable_mgpu_fan_boost(smu); + + mutex_unlock(&smu->mutex); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile new file mode 100644 index 000000000000..f98d97192635 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/Makefile @@ -0,0 +1,33 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU11_MGR = arcturus_ppt.o \ + navi10_ppt.o \ + sienna_cichlid_ppt.o \ + smu_v11_0.o + +AMD_SWSMU_SMU11MGR = $(addprefix $(AMD_SWSMU_PATH)/smu11/,$(SMU11_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_SMU11MGR) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c new file mode 100644 index 000000000000..81f43fea4d52 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -0,0 +1,2405 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "smu_v11_0.h" +#include "smu11_driver_if_arcturus.h" +#include "soc15_common.h" +#include "atom.h" +#include "power_state.h" +#include "arcturus_ppt.h" +#include "smu_v11_0_pptable.h" +#include "arcturus_ppsmc.h" +#include "nbio/nbio_7_4_offset.h" +#include "nbio/nbio_7_4_sh_mask.h" +#include "thm/thm_11_0_2_offset.h" +#include "thm/thm_11_0_2_sh_mask.h" +#include "amdgpu_xgmi.h" +#include +#include +#include "amdgpu_ras.h" +#include "smu_cmn.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) + +#define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \ + [smu_feature] = {1, (arcturus_feature)} + +#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF +#define SMU_FEATURES_LOW_SHIFT 0 +#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 +#define SMU_FEATURES_HIGH_SHIFT 32 + +#define SMC_DPM_FEATURE ( \ + FEATURE_DPM_PREFETCHER_MASK | \ + FEATURE_DPM_GFXCLK_MASK | \ + FEATURE_DPM_UCLK_MASK | \ + FEATURE_DPM_SOCCLK_MASK | \ + FEATURE_DPM_MP0CLK_MASK | \ + FEATURE_DPM_FCLK_MASK | \ + FEATURE_DPM_XGMI_MASK) + +/* possible frequency drift (1Mhz) */ +#define EPSILON 1 + +#define smnPCIE_ESM_CTRL 0x111003D0 + +static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = { + MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), + MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 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, 0), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 0), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 0), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 0), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), + MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), + MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), + MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), + MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0), + MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0), + MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), + MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), + MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), + MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), + MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 0), + MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 0), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 0), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), + MSG_MAP(SetDfSwitchType, PPSMC_MSG_SetDfSwitchType, 0), + MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), + MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), + MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), + MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), + MSG_MAP(PowerUpVcn0, PPSMC_MSG_PowerUpVcn0, 0), + MSG_MAP(PowerDownVcn0, PPSMC_MSG_PowerDownVcn0, 0), + MSG_MAP(PowerUpVcn1, PPSMC_MSG_PowerUpVcn1, 0), + MSG_MAP(PowerDownVcn1, PPSMC_MSG_PowerDownVcn1, 0), + MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), + MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0), + MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0), + MSG_MAP(SoftReset, PPSMC_MSG_SoftReset, 0), + MSG_MAP(RunAfllBtc, PPSMC_MSG_RunAfllBtc, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), + MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0), + MSG_MAP(WaflTest, PPSMC_MSG_WaflTest, 0), + MSG_MAP(SetXgmiMode, PPSMC_MSG_SetXgmiMode, 0), + MSG_MAP(SetMemoryChannelEnable, PPSMC_MSG_SetMemoryChannelEnable, 0), + MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0), + MSG_MAP(GmiPwrDnControl, PPSMC_MSG_GmiPwrDnControl, 0), + MSG_MAP(ReadSerialNumTop32, PPSMC_MSG_ReadSerialNumTop32, 1), + MSG_MAP(ReadSerialNumBottom32, PPSMC_MSG_ReadSerialNumBottom32, 1), +}; + +static const struct cmn2asic_mapping arcturus_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, PPCLK_GFXCLK), + CLK_MAP(SCLK, PPCLK_GFXCLK), + CLK_MAP(SOCCLK, PPCLK_SOCCLK), + CLK_MAP(FCLK, PPCLK_FCLK), + CLK_MAP(UCLK, PPCLK_UCLK), + CLK_MAP(MCLK, PPCLK_UCLK), + CLK_MAP(DCLK, PPCLK_DCLK), + CLK_MAP(VCLK, PPCLK_VCLK), +}; + +static const struct cmn2asic_mapping arcturus_feature_mask_map[SMU_FEATURE_COUNT] = { + FEA_MAP(DPM_PREFETCHER), + FEA_MAP(DPM_GFXCLK), + FEA_MAP(DPM_UCLK), + FEA_MAP(DPM_SOCCLK), + FEA_MAP(DPM_FCLK), + FEA_MAP(DPM_MP0CLK), + ARCTURUS_FEA_MAP(SMU_FEATURE_XGMI_BIT, FEATURE_DPM_XGMI_BIT), + FEA_MAP(DS_GFXCLK), + FEA_MAP(DS_SOCCLK), + FEA_MAP(DS_LCLK), + FEA_MAP(DS_FCLK), + FEA_MAP(DS_UCLK), + FEA_MAP(GFX_ULV), + ARCTURUS_FEA_MAP(SMU_FEATURE_VCN_PG_BIT, FEATURE_DPM_VCN_BIT), + FEA_MAP(RSMU_SMN_CG), + FEA_MAP(WAFL_CG), + FEA_MAP(PPT), + FEA_MAP(TDC), + FEA_MAP(APCC_PLUS), + FEA_MAP(VR0HOT), + FEA_MAP(VR1HOT), + FEA_MAP(FW_CTF), + FEA_MAP(FAN_CONTROL), + FEA_MAP(THERMAL), + FEA_MAP(OUT_OF_BAND_MONITOR), + FEA_MAP(TEMP_DEPENDENT_VMIN), +}; + +static const struct cmn2asic_mapping arcturus_table_map[SMU_TABLE_COUNT] = { + TAB_MAP(PPTABLE), + TAB_MAP(AVFS), + TAB_MAP(AVFS_PSM_DEBUG), + TAB_MAP(AVFS_FUSE_OVERRIDE), + TAB_MAP(PMSTATUSLOG), + TAB_MAP(SMU_METRICS), + TAB_MAP(DRIVER_SMU_CONFIG), + TAB_MAP(OVERDRIVE), + TAB_MAP(I2C_COMMANDS), + TAB_MAP(ACTIVITY_MONITOR_COEFF), +}; + +static const struct cmn2asic_mapping arcturus_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { + PWR_MAP(AC), + PWR_MAP(DC), +}; + +static const struct cmn2asic_mapping arcturus_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), +}; + +static int arcturus_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, + sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + if (!smu_table->metrics_table) + return -ENOMEM; + smu_table->metrics_time = 0; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) { + kfree(smu_table->metrics_table); + return -ENOMEM; + } + + return 0; +} + +static int arcturus_allocate_dpm_context(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), + GFP_KERNEL); + if (!smu_dpm->dpm_context) + return -ENOMEM; + smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); + + smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state), + GFP_KERNEL); + if (!smu_dpm->dpm_current_power_state) + return -ENOMEM; + + smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state), + GFP_KERNEL); + if (!smu_dpm->dpm_request_power_state) + return -ENOMEM; + + return 0; +} + +static int arcturus_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = arcturus_tables_init(smu); + if (ret) + return ret; + + ret = arcturus_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v11_0_init_smc_tables(smu); +} + +static int +arcturus_get_allowed_feature_mask(struct smu_context *smu, + uint32_t *feature_mask, uint32_t num) +{ + if (num > 2) + return -EINVAL; + + /* pptable will handle the features to enable */ + memset(feature_mask, 0xFF, sizeof(uint32_t) * num); + + return 0; +} + +static int arcturus_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table = NULL; + int ret = 0; + + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* memclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + return 0; +} + +static int arcturus_check_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + + mutex_lock(&smu_baco->mutex); + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || + powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) + smu_baco->platform_support = true; + mutex_unlock(&smu_baco->mutex); + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + return 0; +} + +static int arcturus_store_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + + memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, + sizeof(PPTable_t)); + + return 0; +} + +static int arcturus_append_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + struct atom_smc_dpm_info_v4_6 *smc_dpm_table; + int index, ret; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smc_dpm_info); + + ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table); + if (ret) + return ret; + + dev_info(smu->adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n", + smc_dpm_table->table_header.format_revision, + smc_dpm_table->table_header.content_revision); + + if ((smc_dpm_table->table_header.format_revision == 4) && + (smc_dpm_table->table_header.content_revision == 6)) + memcpy(&smc_pptable->MaxVoltageStepGfx, + &smc_dpm_table->maxvoltagestepgfx, + sizeof(*smc_dpm_table) - offsetof(struct atom_smc_dpm_info_v4_6, maxvoltagestepgfx)); + + return 0; +} + +static int arcturus_setup_pptable(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v11_0_setup_pptable(smu); + if (ret) + return ret; + + ret = arcturus_store_powerplay_table(smu); + if (ret) + return ret; + + ret = arcturus_append_powerplay_table(smu); + if (ret) + return ret; + + ret = arcturus_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; +} + +static int arcturus_run_btc(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunAfllBtc, NULL); + if (ret) { + dev_err(smu->adev->dev, "RunAfllBtc failed!\n"); + return ret; + } + + return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); +} + +static int arcturus_populate_umd_state_clk(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + if (gfx_table->count > ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL && + mem_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL && + soc_table->count > ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL) { + pstate_table->gfxclk_pstate.standard = + gfx_table->dpm_levels[ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL].value; + pstate_table->uclk_pstate.standard = + mem_table->dpm_levels[ARCTURUS_UMD_PSTATE_MCLK_LEVEL].value; + pstate_table->socclk_pstate.standard = + soc_table->dpm_levels[ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL].value; + } else { + pstate_table->gfxclk_pstate.standard = + pstate_table->gfxclk_pstate.min; + pstate_table->uclk_pstate.standard = + pstate_table->uclk_pstate.min; + pstate_table->socclk_pstate.standard = + pstate_table->socclk_pstate.min; + } + + return 0; +} + +static int arcturus_get_clk_table(struct smu_context *smu, + struct pp_clock_levels_with_latency *clocks, + struct smu_11_0_dpm_table *dpm_table) +{ + int i, count; + + count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; + clocks->num_levels = count; + + for (i = 0; i < count; i++) { + clocks->data[i].clocks_in_khz = + dpm_table->dpm_levels[i].value * 1000; + clocks->data[i].latency_in_us = 0; + } + + return 0; +} + +static int arcturus_freqs_in_same_level(int32_t frequency1, + int32_t frequency2) +{ + return (abs(frequency1 - frequency2) <= EPSILON); +} + +static int arcturus_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK]; + break; + case METRICS_CURR_FCLK: + *value = metrics->CurrClock[PPCLK_FCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + *value = metrics->AverageGfxclkFrequency; + break; + case METRICS_AVERAGE_SOCCLK: + *value = metrics->AverageSocclkFrequency; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->AverageUclkFrequency; + break; + case METRICS_AVERAGE_VCLK: + *value = metrics->AverageVclkFrequency; + break; + case METRICS_AVERAGE_DCLK: + *value = metrics->AverageDclkFrequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_VCNACTIVITY: + *value = metrics->VcnActivityPercentage; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->TemperatureEdge * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->TemperatureHotspot * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->TemperatureHBM * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->TemperatureVrGfx * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->TemperatureVrSoc * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRMEM: + *value = metrics->TemperatureVrMem * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_CURR_FANSPEED: + *value = metrics->CurrFanSpeed; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + if (!value) + return -EINVAL; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return -EINVAL; + + switch (clk_id) { + case PPCLK_GFXCLK: + /* + * CurrClock[clk_id] can provide accurate + * output only when the dpm feature is enabled. + * We can use Average_* for dpm disabled case. + * But this is available for gfxclk/uclk/socclk/vclk/dclk. + */ + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) + member_type = METRICS_CURR_GFXCLK; + else + member_type = METRICS_AVERAGE_GFXCLK; + break; + case PPCLK_UCLK: + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) + member_type = METRICS_CURR_UCLK; + else + member_type = METRICS_AVERAGE_UCLK; + break; + case PPCLK_SOCCLK: + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) + member_type = METRICS_CURR_SOCCLK; + else + member_type = METRICS_AVERAGE_SOCCLK; + break; + case PPCLK_VCLK: + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) + member_type = METRICS_CURR_VCLK; + else + member_type = METRICS_AVERAGE_VCLK; + break; + case PPCLK_DCLK: + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) + member_type = METRICS_CURR_DCLK; + else + member_type = METRICS_AVERAGE_DCLK; + break; + case PPCLK_FCLK: + member_type = METRICS_CURR_FCLK; + break; + default: + return -EINVAL; + } + + return arcturus_get_smu_metrics_data(smu, + member_type, + value); +} + +static int arcturus_print_clk_levels(struct smu_context *smu, + enum smu_clk_type type, char *buf) +{ + int i, now, size = 0; + int ret = 0; + struct pp_clock_levels_with_latency clocks; + struct smu_11_0_dpm_table *single_dpm_table; + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_11_0_dpm_context *dpm_context = NULL; + + if (amdgpu_ras_intr_triggered()) + return snprintf(buf, PAGE_SIZE, "unavailable\n"); + + dpm_context = smu_dpm->dpm_context; + + switch (type) { + case SMU_SCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!"); + return ret; + } + + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!"); + return ret; + } + + /* + * For DPM disabled case, there will be only one clock level. + * And it's safe to assume that is always the current clock. + */ + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", i, + clocks.data[i].clocks_in_khz / 1000, + (clocks.num_levels == 1) ? "*" : + (arcturus_freqs_in_same_level( + clocks.data[i].clocks_in_khz / 1000, + now) ? "*" : "")); + break; + + case SMU_MCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get current mclk Failed!"); + return ret; + } + + single_dpm_table = &(dpm_context->dpm_tables.uclk_table); + ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!"); + return ret; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.num_levels == 1) ? "*" : + (arcturus_freqs_in_same_level( + clocks.data[i].clocks_in_khz / 1000, + now) ? "*" : "")); + break; + + case SMU_SOCCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get current socclk Failed!"); + return ret; + } + + single_dpm_table = &(dpm_context->dpm_tables.soc_table); + ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!"); + return ret; + } + + for (i = 0; i < clocks.num_levels; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, clocks.data[i].clocks_in_khz / 1000, + (clocks.num_levels == 1) ? "*" : + (arcturus_freqs_in_same_level( + clocks.data[i].clocks_in_khz / 1000, + now) ? "*" : "")); + break; + + case SMU_FCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_FCLK, &now); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get current fclk Failed!"); + return ret; + } + + single_dpm_table = &(dpm_context->dpm_tables.fclk_table); + ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!"); + return ret; + } + + for (i = 0; i < single_dpm_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, single_dpm_table->dpm_levels[i].value, + (clocks.num_levels == 1) ? "*" : + (arcturus_freqs_in_same_level( + clocks.data[i].clocks_in_khz / 1000, + now) ? "*" : "")); + break; + + default: + break; + } + + return size; +} + +static int arcturus_upload_dpm_level(struct smu_context *smu, + bool max, + uint32_t feature_mask, + uint32_t level) +{ + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + uint32_t freq; + int ret = 0; + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && + (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { + freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value; + ret = smu_cmn_send_smc_msg_with_param(smu, + (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), + (PPCLK_GFXCLK << 16) | (freq & 0xffff), + NULL); + if (ret) { + dev_err(smu->adev->dev, "Failed to set soft %s gfxclk !\n", + max ? "max" : "min"); + return ret; + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && + (feature_mask & FEATURE_DPM_UCLK_MASK)) { + freq = dpm_context->dpm_tables.uclk_table.dpm_levels[level].value; + ret = smu_cmn_send_smc_msg_with_param(smu, + (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), + (PPCLK_UCLK << 16) | (freq & 0xffff), + NULL); + if (ret) { + dev_err(smu->adev->dev, "Failed to set soft %s memclk !\n", + max ? "max" : "min"); + return ret; + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) && + (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { + freq = dpm_context->dpm_tables.soc_table.dpm_levels[level].value; + ret = smu_cmn_send_smc_msg_with_param(smu, + (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), + (PPCLK_SOCCLK << 16) | (freq & 0xffff), + NULL); + if (ret) { + dev_err(smu->adev->dev, "Failed to set soft %s socclk !\n", + max ? "max" : "min"); + return ret; + } + } + + return ret; +} + +static int arcturus_force_clk_levels(struct smu_context *smu, + enum smu_clk_type type, uint32_t mask) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *single_dpm_table = NULL; + uint32_t soft_min_level, soft_max_level; + uint32_t smu_version; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) { + dev_err(smu->adev->dev, "Failed to get smu version!\n"); + return ret; + } + + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { + dev_err(smu->adev->dev, "Forcing clock level is not supported with " + "54.18 - 54.26(included) SMU firmwares\n"); + return -EOPNOTSUPP; + } + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + switch (type) { + case SMU_SCLK: + single_dpm_table = &(dpm_context->dpm_tables.gfx_table); + if (soft_max_level >= single_dpm_table->count) { + dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n", + soft_max_level, single_dpm_table->count - 1); + ret = -EINVAL; + break; + } + + ret = arcturus_upload_dpm_level(smu, + false, + FEATURE_DPM_GFXCLK_MASK, + soft_min_level); + if (ret) { + dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n"); + break; + } + + ret = arcturus_upload_dpm_level(smu, + true, + FEATURE_DPM_GFXCLK_MASK, + soft_max_level); + if (ret) + dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n"); + + break; + + case SMU_MCLK: + case SMU_SOCCLK: + case SMU_FCLK: + /* + * Should not arrive here since Arcturus does not + * support mclk/socclk/fclk softmin/softmax settings + */ + ret = -EINVAL; + break; + + default: + break; + } + + return ret; +} + +static int arcturus_get_thermal_temperature_range(struct smu_context *smu, + struct smu_temperature_range *range) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + if (!range) + return -EINVAL; + + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->TedgeLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->ThotspotLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->TmemLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; + + return 0; +} + +static int arcturus_get_current_activity_percent(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + value); + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); + return -EINVAL; + } + + return ret; +} + +static int arcturus_get_gpu_power(struct smu_context *smu, uint32_t *value) +{ + if (!value) + return -EINVAL; + + return arcturus_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + value); +} + +static int arcturus_thermal_get_temperature(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + value); + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + value); + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = arcturus_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); + return -EINVAL; + } + + return ret; +} + +static int arcturus_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + int ret = 0; + + if (amdgpu_ras_intr_triggered()) + return 0; + + if (!data || !size) + return -EINVAL; + + mutex_lock(&smu->sensor_lock); + switch (sensor) { + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *(uint32_t *)data = pptable->FanMaximumRpm; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = arcturus_get_current_activity_percent(smu, + sensor, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = arcturus_get_gpu_power(smu, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + case AMDGPU_PP_SENSOR_EDGE_TEMP: + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = arcturus_thermal_get_temperature(smu, sensor, + (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + /* the output clock frequency in 10K unit */ + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + mutex_unlock(&smu->sensor_lock); + + return ret; +} + +static int arcturus_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + if (!speed) + return -EINVAL; + + return arcturus_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); +} + +static int arcturus_get_fan_speed_percent(struct smu_context *smu, + uint32_t *speed) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t percent, current_rpm; + int ret = 0; + + if (!speed) + return -EINVAL; + + ret = arcturus_get_fan_speed_rpm(smu, ¤t_rpm); + if (ret) + return ret; + + percent = current_rpm * 100 / pptable->FanMaximumRpm; + *speed = percent > 100 ? 100 : percent; + + return ret; +} + +static int arcturus_get_power_limit(struct smu_context *smu) +{ + struct smu_11_0_powerplay_table *powerplay_table = + (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t power_limit, od_percent; + + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; + } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; + + if (smu->od_enabled) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); + + power_limit *= (100 + od_percent); + power_limit /= 100; + } + smu->max_power_limit = power_limit; + + return 0; +} + +static int arcturus_get_power_profile_mode(struct smu_context *smu, + char *buf) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + static const char *profile_name[] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + static const char *title[] = { + "PROFILE_INDEX(NAME)", + "CLOCK_TYPE(NAME)", + "FPS", + "UseRlcBusy", + "MinActiveFreqType", + "MinActiveFreq", + "BoosterFreqType", + "BoosterFreq", + "PD_Data_limit_c", + "PD_Data_error_coeff", + "PD_Data_error_rate_coeff"}; + uint32_t i, size = 0; + int16_t workload_type = 0; + int result = 0; + uint32_t smu_version; + + if (!buf) + return -EINVAL; + + result = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (result) + return result; + + if (smu_version >= 0x360d00) + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9], title[10]); + else + size += sprintf(buf + size, "%16s\n", + title[0]); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { + /* + * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT + * Not all profile modes are supported on arcturus. + */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type < 0) + continue; + + if (smu_version >= 0x360d00) { + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + workload_type, + (void *)(&activity_monitor), + false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return result; + } + } + + size += sprintf(buf + size, "%2d %14s%s\n", + i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + + if (smu_version >= 0x360d00) { + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 0, + "GFXCLK", + activity_monitor.Gfx_FPS, + activity_monitor.Gfx_UseRlcBusy, + activity_monitor.Gfx_MinActiveFreqType, + activity_monitor.Gfx_MinActiveFreq, + activity_monitor.Gfx_BoosterFreqType, + activity_monitor.Gfx_BoosterFreq, + activity_monitor.Gfx_PD_Data_limit_c, + activity_monitor.Gfx_PD_Data_error_coeff, + activity_monitor.Gfx_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 1, + "UCLK", + activity_monitor.Mem_FPS, + activity_monitor.Mem_UseRlcBusy, + activity_monitor.Mem_MinActiveFreqType, + activity_monitor.Mem_MinActiveFreq, + activity_monitor.Mem_BoosterFreqType, + activity_monitor.Mem_BoosterFreq, + activity_monitor.Mem_PD_Data_limit_c, + activity_monitor.Mem_PD_Data_error_coeff, + activity_monitor.Mem_PD_Data_error_rate_coeff); + } + } + + return size; +} + +static int arcturus_set_power_profile_mode(struct smu_context *smu, + long *input, + uint32_t size) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + int workload_type = 0; + uint32_t profile_mode = input[size]; + int ret = 0; + uint32_t smu_version; + + if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); + return -EINVAL; + } + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) + return ret; + + if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) && + (smu_version >=0x360d00)) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), + false); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return ret; + } + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor.Gfx_FPS = input[1]; + activity_monitor.Gfx_UseRlcBusy = input[2]; + activity_monitor.Gfx_MinActiveFreqType = input[3]; + activity_monitor.Gfx_MinActiveFreq = input[4]; + activity_monitor.Gfx_BoosterFreqType = input[5]; + activity_monitor.Gfx_BoosterFreq = input[6]; + activity_monitor.Gfx_PD_Data_limit_c = input[7]; + activity_monitor.Gfx_PD_Data_error_coeff = input[8]; + activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; + break; + case 1: /* Uclk */ + activity_monitor.Mem_FPS = input[1]; + activity_monitor.Mem_UseRlcBusy = input[2]; + activity_monitor.Mem_MinActiveFreqType = input[3]; + activity_monitor.Mem_MinActiveFreq = input[4]; + activity_monitor.Mem_BoosterFreqType = input[5]; + activity_monitor.Mem_BoosterFreq = input[6]; + activity_monitor.Mem_PD_Data_limit_c = input[7]; + activity_monitor.Mem_PD_Data_error_coeff = input[8]; + activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; + break; + } + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, + WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), + true); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); + return ret; + } + } + + /* + * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT + * Not all profile modes are supported on arcturus. + */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + profile_mode); + if (workload_type < 0) { + dev_err(smu->adev->dev, "Unsupported power profile mode %d on arcturus\n", profile_mode); + return -EINVAL; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetWorkloadMask, + 1 << workload_type, + NULL); + if (ret) { + dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type); + return ret; + } + + smu->power_profile_mode = profile_mode; + + return 0; +} + +static int arcturus_set_performance_level(struct smu_context *smu, + enum amd_dpm_forced_level level) +{ + uint32_t smu_version; + int ret; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) { + dev_err(smu->adev->dev, "Failed to get smu version!\n"); + return ret; + } + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + case AMD_DPM_FORCED_LEVEL_LOW: + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + if ((smu_version >= 0x361200) && + (smu_version <= 0x361a00)) { + dev_err(smu->adev->dev, "Forcing clock level is not supported with " + "54.18 - 54.26(included) SMU firmwares\n"); + return -EOPNOTSUPP; + } + break; + default: + break; + } + + return smu_v11_0_set_performance_level(smu, level); +} + +static void arcturus_dump_pptable(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + int i; + + dev_info(smu->adev->dev, "Dumped PPTable:\n"); + + dev_info(smu->adev->dev, "Version = 0x%08x\n", pptable->Version); + + dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); + dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); + + for (i = 0; i < PPT_THROTTLER_COUNT; i++) { + dev_info(smu->adev->dev, "SocketPowerLimitAc[%d] = %d\n", i, pptable->SocketPowerLimitAc[i]); + dev_info(smu->adev->dev, "SocketPowerLimitAcTau[%d] = %d\n", i, pptable->SocketPowerLimitAcTau[i]); + } + + dev_info(smu->adev->dev, "TdcLimitSoc = %d\n", pptable->TdcLimitSoc); + dev_info(smu->adev->dev, "TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau); + dev_info(smu->adev->dev, "TdcLimitGfx = %d\n", pptable->TdcLimitGfx); + dev_info(smu->adev->dev, "TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau); + + dev_info(smu->adev->dev, "TedgeLimit = %d\n", pptable->TedgeLimit); + dev_info(smu->adev->dev, "ThotspotLimit = %d\n", pptable->ThotspotLimit); + dev_info(smu->adev->dev, "TmemLimit = %d\n", pptable->TmemLimit); + dev_info(smu->adev->dev, "Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit); + dev_info(smu->adev->dev, "Tvr_memLimit = %d\n", pptable->Tvr_memLimit); + dev_info(smu->adev->dev, "Tvr_socLimit = %d\n", pptable->Tvr_socLimit); + dev_info(smu->adev->dev, "FitLimit = %d\n", pptable->FitLimit); + + dev_info(smu->adev->dev, "PpmPowerLimit = %d\n", pptable->PpmPowerLimit); + dev_info(smu->adev->dev, "PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold); + + dev_info(smu->adev->dev, "ThrottlerControlMask = %d\n", pptable->ThrottlerControlMask); + + dev_info(smu->adev->dev, "UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx); + dev_info(smu->adev->dev, "UlvPadding = 0x%08x\n", pptable->UlvPadding); + + dev_info(smu->adev->dev, "UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass); + dev_info(smu->adev->dev, "Padding234[0] = 0x%02x\n", pptable->Padding234[0]); + dev_info(smu->adev->dev, "Padding234[1] = 0x%02x\n", pptable->Padding234[1]); + dev_info(smu->adev->dev, "Padding234[2] = 0x%02x\n", pptable->Padding234[2]); + + dev_info(smu->adev->dev, "MinVoltageGfx = %d\n", pptable->MinVoltageGfx); + dev_info(smu->adev->dev, "MinVoltageSoc = %d\n", pptable->MinVoltageSoc); + dev_info(smu->adev->dev, "MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx); + dev_info(smu->adev->dev, "MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc); + + dev_info(smu->adev->dev, "LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx); + dev_info(smu->adev->dev, "LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc); + + dev_info(smu->adev->dev, "[PPCLK_GFXCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_GFXCLK].padding, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_GFXCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_VCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_VCLK].padding, + pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_VCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_VCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_DCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DCLK].padding, + pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_DCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_DCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_SOCCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_SOCCLK].padding, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_SOCCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_UCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_UCLK].padding, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_UCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_UCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_FCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_FCLK].padding, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_FCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_FCLK].Padding16); + + + dev_info(smu->adev->dev, "FreqTableGfx\n"); + for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableGfx[i]); + + dev_info(smu->adev->dev, "FreqTableVclk\n"); + for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableVclk[i]); + + dev_info(smu->adev->dev, "FreqTableDclk\n"); + for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableDclk[i]); + + dev_info(smu->adev->dev, "FreqTableSocclk\n"); + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]); + + dev_info(smu->adev->dev, "FreqTableUclk\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableUclk[i]); + + dev_info(smu->adev->dev, "FreqTableFclk\n"); + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableFclk[i]); + + dev_info(smu->adev->dev, "Mp0clkFreq\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->Mp0clkFreq[i]); + + dev_info(smu->adev->dev, "Mp0DpmVoltage\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]); + + dev_info(smu->adev->dev, "GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); + dev_info(smu->adev->dev, "GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate); + dev_info(smu->adev->dev, "Padding567[0] = 0x%x\n", pptable->Padding567[0]); + dev_info(smu->adev->dev, "Padding567[1] = 0x%x\n", pptable->Padding567[1]); + dev_info(smu->adev->dev, "Padding567[2] = 0x%x\n", pptable->Padding567[2]); + dev_info(smu->adev->dev, "Padding567[3] = 0x%x\n", pptable->Padding567[3]); + dev_info(smu->adev->dev, "GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq); + dev_info(smu->adev->dev, "GfxclkSource = 0x%x\n", pptable->GfxclkSource); + dev_info(smu->adev->dev, "Padding456 = 0x%x\n", pptable->Padding456); + + dev_info(smu->adev->dev, "EnableTdpm = %d\n", pptable->EnableTdpm); + dev_info(smu->adev->dev, "TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature); + dev_info(smu->adev->dev, "TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature); + dev_info(smu->adev->dev, "GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit); + + dev_info(smu->adev->dev, "FanStopTemp = %d\n", pptable->FanStopTemp); + dev_info(smu->adev->dev, "FanStartTemp = %d\n", pptable->FanStartTemp); + + dev_info(smu->adev->dev, "FanGainEdge = %d\n", pptable->FanGainEdge); + dev_info(smu->adev->dev, "FanGainHotspot = %d\n", pptable->FanGainHotspot); + dev_info(smu->adev->dev, "FanGainVrGfx = %d\n", pptable->FanGainVrGfx); + dev_info(smu->adev->dev, "FanGainVrSoc = %d\n", pptable->FanGainVrSoc); + dev_info(smu->adev->dev, "FanGainVrMem = %d\n", pptable->FanGainVrMem); + dev_info(smu->adev->dev, "FanGainHbm = %d\n", pptable->FanGainHbm); + + dev_info(smu->adev->dev, "FanPwmMin = %d\n", pptable->FanPwmMin); + dev_info(smu->adev->dev, "FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm); + dev_info(smu->adev->dev, "FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm); + dev_info(smu->adev->dev, "FanMaximumRpm = %d\n", pptable->FanMaximumRpm); + dev_info(smu->adev->dev, "FanTargetTemperature = %d\n", pptable->FanTargetTemperature); + dev_info(smu->adev->dev, "FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk); + dev_info(smu->adev->dev, "FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable); + dev_info(smu->adev->dev, "FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev); + dev_info(smu->adev->dev, "FanTempInputSelect = %d\n", pptable->FanTempInputSelect); + + dev_info(smu->adev->dev, "FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved); + + dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]); + dev_info(smu->adev->dev, "Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]); + + dev_info(smu->adev->dev, "dBtcGbGfxPll{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxPll.a, + pptable->dBtcGbGfxPll.b, + pptable->dBtcGbGfxPll.c); + dev_info(smu->adev->dev, "dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxAfll.a, + pptable->dBtcGbGfxAfll.b, + pptable->dBtcGbGfxAfll.c); + dev_info(smu->adev->dev, "dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbSoc.a, + pptable->dBtcGbSoc.b, + pptable->dBtcGbSoc.c); + + dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, + pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); + dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, + pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); + + dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); + dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); + + dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); + dev_info(smu->adev->dev, "Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); + + dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "XgmiDpmPstates\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiDpmPstates[i]); + dev_info(smu->adev->dev, "XgmiDpmSpare[0] = 0x%02x\n", pptable->XgmiDpmSpare[0]); + dev_info(smu->adev->dev, "XgmiDpmSpare[1] = 0x%02x\n", pptable->XgmiDpmSpare[1]); + + dev_info(smu->adev->dev, "VDDGFX_TVmin = %d\n", pptable->VDDGFX_TVmin); + dev_info(smu->adev->dev, "VDDSOC_TVmin = %d\n", pptable->VDDSOC_TVmin); + dev_info(smu->adev->dev, "VDDGFX_Vmin_HiTemp = %d\n", pptable->VDDGFX_Vmin_HiTemp); + dev_info(smu->adev->dev, "VDDGFX_Vmin_LoTemp = %d\n", pptable->VDDGFX_Vmin_LoTemp); + dev_info(smu->adev->dev, "VDDSOC_Vmin_HiTemp = %d\n", pptable->VDDSOC_Vmin_HiTemp); + dev_info(smu->adev->dev, "VDDSOC_Vmin_LoTemp = %d\n", pptable->VDDSOC_Vmin_LoTemp); + dev_info(smu->adev->dev, "VDDGFX_TVminHystersis = %d\n", pptable->VDDGFX_TVminHystersis); + dev_info(smu->adev->dev, "VDDSOC_TVminHystersis = %d\n", pptable->VDDSOC_TVminHystersis); + + dev_info(smu->adev->dev, "DebugOverrides = 0x%x\n", pptable->DebugOverrides); + dev_info(smu->adev->dev, "ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation0.a, + pptable->ReservedEquation0.b, + pptable->ReservedEquation0.c); + dev_info(smu->adev->dev, "ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation1.a, + pptable->ReservedEquation1.b, + pptable->ReservedEquation1.c); + dev_info(smu->adev->dev, "ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation2.a, + pptable->ReservedEquation2.b, + pptable->ReservedEquation2.c); + dev_info(smu->adev->dev, "ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation3.a, + pptable->ReservedEquation3.b, + pptable->ReservedEquation3.c); + + dev_info(smu->adev->dev, "MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx); + dev_info(smu->adev->dev, "PaddingUlv = %d\n", pptable->PaddingUlv); + + dev_info(smu->adev->dev, "TotalPowerConfig = %d\n", pptable->TotalPowerConfig); + dev_info(smu->adev->dev, "TotalPowerSpare1 = %d\n", pptable->TotalPowerSpare1); + dev_info(smu->adev->dev, "TotalPowerSpare2 = %d\n", pptable->TotalPowerSpare2); + + dev_info(smu->adev->dev, "PccThresholdLow = %d\n", pptable->PccThresholdLow); + dev_info(smu->adev->dev, "PccThresholdHigh = %d\n", pptable->PccThresholdHigh); + + dev_info(smu->adev->dev, "Board Parameters:\n"); + dev_info(smu->adev->dev, "MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx); + dev_info(smu->adev->dev, "MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc); + + dev_info(smu->adev->dev, "VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); + dev_info(smu->adev->dev, "VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); + dev_info(smu->adev->dev, "VddMemVrMapping = 0x%x\n", pptable->VddMemVrMapping); + dev_info(smu->adev->dev, "BoardVrMapping = 0x%x\n", pptable->BoardVrMapping); + + dev_info(smu->adev->dev, "GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); + dev_info(smu->adev->dev, "ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent); + + dev_info(smu->adev->dev, "GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); + dev_info(smu->adev->dev, "GfxOffset = 0x%x\n", pptable->GfxOffset); + dev_info(smu->adev->dev, "Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); + + dev_info(smu->adev->dev, "SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); + dev_info(smu->adev->dev, "SocOffset = 0x%x\n", pptable->SocOffset); + dev_info(smu->adev->dev, "Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); + + dev_info(smu->adev->dev, "MemMaxCurrent = 0x%x\n", pptable->MemMaxCurrent); + dev_info(smu->adev->dev, "MemOffset = 0x%x\n", pptable->MemOffset); + dev_info(smu->adev->dev, "Padding_TelemetryMem = 0x%x\n", pptable->Padding_TelemetryMem); + + dev_info(smu->adev->dev, "BoardMaxCurrent = 0x%x\n", pptable->BoardMaxCurrent); + dev_info(smu->adev->dev, "BoardOffset = 0x%x\n", pptable->BoardOffset); + dev_info(smu->adev->dev, "Padding_TelemetryBoardInput = 0x%x\n", pptable->Padding_TelemetryBoardInput); + + dev_info(smu->adev->dev, "VR0HotGpio = %d\n", pptable->VR0HotGpio); + dev_info(smu->adev->dev, "VR0HotPolarity = %d\n", pptable->VR0HotPolarity); + dev_info(smu->adev->dev, "VR1HotGpio = %d\n", pptable->VR1HotGpio); + dev_info(smu->adev->dev, "VR1HotPolarity = %d\n", pptable->VR1HotPolarity); + + dev_info(smu->adev->dev, "PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled); + dev_info(smu->adev->dev, "PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent); + dev_info(smu->adev->dev, "PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq); + + dev_info(smu->adev->dev, "UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled); + dev_info(smu->adev->dev, "UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent); + dev_info(smu->adev->dev, "UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq); + + dev_info(smu->adev->dev, "FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled); + dev_info(smu->adev->dev, "FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent); + dev_info(smu->adev->dev, "FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq); + + dev_info(smu->adev->dev, "FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled); + dev_info(smu->adev->dev, "FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent); + dev_info(smu->adev->dev, "FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq); + + for (i = 0; i < NUM_I2C_CONTROLLERS; i++) { + dev_info(smu->adev->dev, "I2cControllers[%d]:\n", i); + dev_info(smu->adev->dev, " .Enabled = %d\n", + pptable->I2cControllers[i].Enabled); + dev_info(smu->adev->dev, " .SlaveAddress = 0x%x\n", + pptable->I2cControllers[i].SlaveAddress); + dev_info(smu->adev->dev, " .ControllerPort = %d\n", + pptable->I2cControllers[i].ControllerPort); + dev_info(smu->adev->dev, " .ControllerName = %d\n", + pptable->I2cControllers[i].ControllerName); + dev_info(smu->adev->dev, " .ThermalThrottler = %d\n", + pptable->I2cControllers[i].ThermalThrotter); + dev_info(smu->adev->dev, " .I2cProtocol = %d\n", + pptable->I2cControllers[i].I2cProtocol); + dev_info(smu->adev->dev, " .Speed = %d\n", + pptable->I2cControllers[i].Speed); + } + + dev_info(smu->adev->dev, "MemoryChannelEnabled = %d\n", pptable->MemoryChannelEnabled); + dev_info(smu->adev->dev, "DramBitWidth = %d\n", pptable->DramBitWidth); + + dev_info(smu->adev->dev, "TotalBoardPower = %d\n", pptable->TotalBoardPower); + + dev_info(smu->adev->dev, "XgmiLinkSpeed\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]); + dev_info(smu->adev->dev, "XgmiLinkWidth\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]); + dev_info(smu->adev->dev, "XgmiFclkFreq\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]); + dev_info(smu->adev->dev, "XgmiSocVoltage\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]); + +} + +static bool arcturus_is_dpm_running(struct smu_context *smu) +{ + int ret = 0; + uint32_t feature_mask[2]; + unsigned long feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | + ((uint64_t)feature_mask[1] << 32)); + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 1); + if (ret) { + dev_err(smu->adev->dev, "[EnableVCNDPM] failed!\n"); + return ret; + } + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0); + if (ret) { + dev_err(smu->adev->dev, "[DisableVCNDPM] failed!\n"); + return ret; + } + } + } + + return ret; +} + +static void arcturus_fill_i2c_req(SwI2cRequest_t *req, bool write, + uint8_t address, uint32_t numbytes, + uint8_t *data) +{ + int i; + + req->I2CcontrollerPort = 0; + req->I2CSpeed = 2; + req->SlaveAddress = address; + req->NumCmds = numbytes; + + for (i = 0; i < numbytes; i++) { + SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; + + /* First 2 bytes are always write for lower 2b EEPROM address */ + if (i < 2) + cmd->Cmd = 1; + else + cmd->Cmd = write; + + + /* Add RESTART for read after address filled */ + cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; + + /* Add STOP in the end */ + cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; + + /* Fill with data regardless if read or write to simplify code */ + cmd->RegisterAddr = data[i]; + } +} + +static int arcturus_i2c_read_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t i, ret = 0; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_table *table = &smu_table->driver_table; + + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + + memset(&req, 0, sizeof(req)); + arcturus_fill_i2c_req(&req, false, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + /* Now read data starting with that address */ + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, + true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; + + /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ + for (i = 0; i < numbytes; i++) + data[i] = res->SwI2cCmds[i].Data; + + dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes = %d, data :", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + } else + dev_err(adev->dev, "arcturus_i2c_read_data - error occurred :%x", ret); + + return ret; +} + +static int arcturus_i2c_write_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t ret; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + + if (numbytes > MAX_SW_I2C_COMMANDS) { + dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", + numbytes, MAX_SW_I2C_COMMANDS); + return -EINVAL; + } + + memset(&req, 0, sizeof(req)); + arcturus_fill_i2c_req(&req, true, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + dev_dbg(adev->dev, "arcturus_i2c_write(), address = %x, bytes = %d , data: ", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + /* + * According to EEPROM spec there is a MAX of 10 ms required for + * EEPROM to flush internal RX buffer after STOP was issued at the + * end of write transaction. During this time the EEPROM will not be + * responsive to any more commands - so wait a bit more. + */ + msleep(10); + + } else + dev_err(adev->dev, "arcturus_i2c_write- error occurred :%x", ret); + + return ret; +} + +static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; + uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; + + for (i = 0; i < num; i++) { + /* + * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at + * once and hence the data needs to be spliced into chunks and sent each + * chunk separately + */ + data_size = msgs[i].len - 2; + data_chunk_size = MAX_SW_I2C_COMMANDS - 2; + next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); + data_ptr = msgs[i].buf + 2; + + for (j = 0; j < data_size / data_chunk_size; j++) { + /* Insert the EEPROM dest addess, bits 0-15 */ + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = arcturus_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + + memcpy(data_ptr, data_chunk + 2, data_chunk_size); + } else { + + memcpy(data_chunk + 2, data_ptr, data_chunk_size); + + ret = arcturus_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + } + + if (ret) { + num = -EIO; + goto fail; + } + + next_eeprom_addr += data_chunk_size; + data_ptr += data_chunk_size; + } + + if (data_size % data_chunk_size) { + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = arcturus_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + + memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); + } else { + memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); + + ret = arcturus_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + } + + if (ret) { + num = -EIO; + goto fail; + } + } + } + +fail: + return num; +} + +static u32 arcturus_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + + +static const struct i2c_algorithm arcturus_i2c_algo = { + .master_xfer = arcturus_i2c_xfer, + .functionality = arcturus_i2c_func, +}; + +static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + int res; + + control->owner = THIS_MODULE; + control->class = I2C_CLASS_SPD; + control->dev.parent = &adev->pdev->dev; + control->algo = &arcturus_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + + res = i2c_add_adapter(control); + if (res) + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + + return res; +} + +static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +{ + i2c_del_adapter(control); +} + +static void arcturus_get_unique_id(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t top32 = 0, bottom32 = 0, smu_version; + uint64_t id; + + if (smu_cmn_get_smc_version(smu, NULL, &smu_version)) { + dev_warn(adev->dev, "Failed to get smu version, cannot get unique_id or serial_number\n"); + return; + } + + /* PPSMC_MSG_ReadSerial* is supported by 54.23.0 and onwards */ + if (smu_version < 0x361700) { + dev_warn(adev->dev, "ReadSerial is only supported by PMFW 54.23.0 and onwards\n"); + return; + } + + /* Get the SN to turn into a Unique ID */ + smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumTop32, &top32); + smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumBottom32, &bottom32); + + id = ((uint64_t)bottom32 << 32) | top32; + adev->unique_id = id; + /* For Arcturus-and-later, unique_id == serial_number, so convert it to a + * 16-digit HEX string for convenience and backwards-compatibility + */ + sprintf(adev->serial, "%llx", id); +} + +static bool arcturus_is_baco_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + + if (!smu_v11_0_baco_is_support(smu) || amdgpu_sriov_vf(adev)) + return false; + + val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); + return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; +} + +static int arcturus_set_df_cstate(struct smu_context *smu, + enum pp_df_cstate state) +{ + uint32_t smu_version; + int ret; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) { + dev_err(smu->adev->dev, "Failed to get smu version!\n"); + return ret; + } + + /* PPSMC_MSG_DFCstateControl is supported by 54.15.0 and onwards */ + if (smu_version < 0x360F00) { + dev_err(smu->adev->dev, "DFCstateControl is only supported by PMFW 54.15.0 and onwards\n"); + return -EINVAL; + } + + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL); +} + +static int arcturus_allow_xgmi_power_down(struct smu_context *smu, bool en) +{ + uint32_t smu_version; + int ret; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) { + dev_err(smu->adev->dev, "Failed to get smu version!\n"); + return ret; + } + + /* PPSMC_MSG_GmiPwrDnControl is supported by 54.23.0 and onwards */ + if (smu_version < 0x00361700) { + dev_err(smu->adev->dev, "XGMI power down control is only supported by PMFW 54.23.0 and onwards\n"); + return -EINVAL; + } + + if (en) + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GmiPwrDnControl, + 1, + NULL); + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GmiPwrDnControl, + 0, + NULL); +} + +static const struct throttling_logging_label { + uint32_t feature_mask; + const char *label; +} logging_label[] = { + {(1U << THROTTLER_TEMP_HOTSPOT_BIT), "GPU"}, + {(1U << THROTTLER_TEMP_MEM_BIT), "HBM"}, + {(1U << THROTTLER_TEMP_VR_GFX_BIT), "VR of GFX rail"}, + {(1U << THROTTLER_TEMP_VR_MEM_BIT), "VR of HBM rail"}, + {(1U << THROTTLER_TEMP_VR_SOC_BIT), "VR of SOC rail"}, + {(1U << THROTTLER_VRHOT0_BIT), "VR0 HOT"}, + {(1U << THROTTLER_VRHOT1_BIT), "VR1 HOT"}, +}; +static void arcturus_log_thermal_throttling_event(struct smu_context *smu) +{ + int ret; + int throttler_idx, throtting_events = 0, buf_idx = 0; + struct amdgpu_device *adev = smu->adev; + uint32_t throttler_status; + char log_buf[256]; + + ret = arcturus_get_smu_metrics_data(smu, + METRICS_THROTTLER_STATUS, + &throttler_status); + if (ret) + return; + + memset(log_buf, 0, sizeof(log_buf)); + for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label); + throttler_idx++) { + if (throttler_status & logging_label[throttler_idx].feature_mask) { + throtting_events++; + buf_idx += snprintf(log_buf + buf_idx, + sizeof(log_buf) - buf_idx, + "%s%s", + throtting_events > 1 ? " and " : "", + logging_label[throttler_idx].label); + if (buf_idx >= sizeof(log_buf)) { + dev_err(adev->dev, "buffer overflow!\n"); + log_buf[sizeof(log_buf) - 1] = '\0'; + break; + } + } + } + + 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 int arcturus_get_current_pcie_link_speed(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t esm_ctrl; + + /* TODO: confirm this on real target */ + esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL); + if ((esm_ctrl >> 15) & 0x1FFFF) + return (((esm_ctrl >> 8) & 0x3F) + 128); + + return smu_v11_0_get_current_pcie_link_speed(smu); +} + +static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); + if (ret) + return ret; + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureHBM; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + arcturus_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + +static const struct pptable_funcs arcturus_ppt_funcs = { + /* init dpm */ + .get_allowed_feature_mask = arcturus_get_allowed_feature_mask, + /* btc */ + .run_btc = arcturus_run_btc, + /* dpm/clk tables */ + .set_default_dpm_table = arcturus_set_default_dpm_table, + .populate_umd_state_clk = arcturus_populate_umd_state_clk, + .get_thermal_temperature_range = arcturus_get_thermal_temperature_range, + .print_clk_levels = arcturus_print_clk_levels, + .force_clk_levels = arcturus_force_clk_levels, + .read_sensor = arcturus_read_sensor, + .get_fan_speed_percent = arcturus_get_fan_speed_percent, + .get_fan_speed_rpm = arcturus_get_fan_speed_rpm, + .get_power_profile_mode = arcturus_get_power_profile_mode, + .set_power_profile_mode = arcturus_set_power_profile_mode, + .set_performance_level = arcturus_set_performance_level, + /* debug (internal used) */ + .dump_pptable = arcturus_dump_pptable, + .get_power_limit = arcturus_get_power_limit, + .is_dpm_running = arcturus_is_dpm_running, + .dpm_set_vcn_enable = arcturus_dpm_set_vcn_enable, + .i2c_init = arcturus_i2c_control_init, + .i2c_fini = arcturus_i2c_control_fini, + .get_unique_id = arcturus_get_unique_id, + .init_microcode = smu_v11_0_init_microcode, + .load_microcode = smu_v11_0_load_microcode, + .fini_microcode = smu_v11_0_fini_microcode, + .init_smc_tables = arcturus_init_smc_tables, + .fini_smc_tables = smu_v11_0_fini_smc_tables, + .init_power = smu_v11_0_init_power, + .fini_power = smu_v11_0_fini_power, + .check_fw_status = smu_v11_0_check_fw_status, + /* pptable related */ + .setup_pptable = arcturus_setup_pptable, + .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, + .check_fw_version = smu_v11_0_check_fw_version, + .write_pptable = smu_cmn_write_pptable, + .set_driver_table_location = smu_v11_0_set_driver_table_location, + .set_tool_table_location = smu_v11_0_set_tool_table_location, + .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, + .system_features_control = smu_v11_0_system_features_control, + .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, + .send_smc_msg = smu_cmn_send_smc_msg, + .init_display_count = NULL, + .set_allowed_mask = smu_v11_0_set_allowed_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, + .notify_display_change = NULL, + .set_power_limit = smu_v11_0_set_power_limit, + .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, + .enable_thermal_alert = smu_v11_0_enable_thermal_alert, + .disable_thermal_alert = smu_v11_0_disable_thermal_alert, + .set_min_dcef_deep_sleep = NULL, + .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, + .get_fan_control_mode = smu_v11_0_get_fan_control_mode, + .set_fan_control_mode = smu_v11_0_set_fan_control_mode, + .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, + .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, + .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, + .gfx_off_control = smu_v11_0_gfx_off_control, + .register_irq_handler = smu_v11_0_register_irq_handler, + .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, + .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, + .baco_is_support= arcturus_is_baco_supported, + .baco_get_state = smu_v11_0_baco_get_state, + .baco_set_state = smu_v11_0_baco_set_state, + .baco_enter = smu_v11_0_baco_enter, + .baco_exit = smu_v11_0_baco_exit, + .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, + .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .set_df_cstate = arcturus_set_df_cstate, + .allow_xgmi_power_down = arcturus_allow_xgmi_power_down, + .log_thermal_throttling_event = arcturus_log_thermal_throttling_event, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = arcturus_get_gpu_metrics, +}; + +void arcturus_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &arcturus_ppt_funcs; + smu->message_map = arcturus_message_map; + smu->clock_map = arcturus_clk_map; + smu->feature_map = arcturus_feature_mask_map; + smu->table_map = arcturus_table_map; + smu->pwr_src_map = arcturus_pwr_src_map; + smu->workload_map = arcturus_workload_map; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h new file mode 100644 index 000000000000..d756b16924b8 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.h @@ -0,0 +1,72 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __ARCTURUS_PPT_H__ +#define __ARCTURUS_PPT_H__ + +#define ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL 0x3 +#define ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL 0x3 +#define ARCTURUS_UMD_PSTATE_MCLK_LEVEL 0x2 + +#define MAX_DPM_NUMBER 16 +#define MAX_PCIE_CONF 2 + +struct arcturus_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +struct arcturus_dpm_state { + uint32_t soft_min_level; + uint32_t soft_max_level; + uint32_t hard_min_level; + uint32_t hard_max_level; +}; + +struct arcturus_single_dpm_table { + uint32_t count; + struct arcturus_dpm_state dpm_state; + struct arcturus_dpm_level dpm_levels[MAX_DPM_NUMBER]; +}; + +struct arcturus_pcie_table { + uint16_t count; + uint8_t pcie_gen[MAX_PCIE_CONF]; + uint8_t pcie_lane[MAX_PCIE_CONF]; + uint32_t lclk[MAX_PCIE_CONF]; +}; + +struct arcturus_dpm_table { + struct arcturus_single_dpm_table soc_table; + struct arcturus_single_dpm_table gfx_table; + struct arcturus_single_dpm_table mem_table; + struct arcturus_single_dpm_table eclk_table; + struct arcturus_single_dpm_table vclk_table; + struct arcturus_single_dpm_table dclk_table; + struct arcturus_single_dpm_table fclk_table; + struct arcturus_pcie_table pcie_table; +}; + +extern void arcturus_set_ppt_funcs(struct smu_context *smu); + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c new file mode 100644 index 000000000000..4b4d461899df --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -0,0 +1,2674 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include +#include +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "soc15_common.h" +#include "smu_v11_0.h" +#include "smu11_driver_if_navi10.h" +#include "atom.h" +#include "navi10_ppt.h" +#include "smu_v11_0_pptable.h" +#include "smu_v11_0_ppsmc.h" +#include "nbio/nbio_2_3_offset.h" +#include "nbio/nbio_2_3_sh_mask.h" +#include "thm/thm_11_0_2_offset.h" +#include "thm/thm_11_0_2_sh_mask.h" + +#include "asic_reg/mp/mp_11_0_sh_mask.h" +#include "smu_cmn.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) + +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ + FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \ + FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) + +static struct cmn2asic_msg_mapping navi10_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, 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), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), + MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), + MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), + MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 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(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), + MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 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, 0), + MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), + MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), + MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), + MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0), + 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(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 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(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), + MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), + MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), + MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0), + MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0), + MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0), + MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0), + 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(GetDebugData, PPSMC_MSG_GetDebugData, 0), + MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), + MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0), + MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 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(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange, 0), + MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0), + MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), + MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), +}; + +static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, PPCLK_GFXCLK), + CLK_MAP(SCLK, PPCLK_GFXCLK), + CLK_MAP(SOCCLK, PPCLK_SOCCLK), + CLK_MAP(FCLK, PPCLK_SOCCLK), + CLK_MAP(UCLK, PPCLK_UCLK), + CLK_MAP(MCLK, PPCLK_UCLK), + CLK_MAP(DCLK, PPCLK_DCLK), + CLK_MAP(VCLK, PPCLK_VCLK), + CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), + CLK_MAP(DISPCLK, PPCLK_DISPCLK), + CLK_MAP(PIXCLK, PPCLK_PIXCLK), + CLK_MAP(PHYCLK, PPCLK_PHYCLK), +}; + +static struct cmn2asic_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = { + FEA_MAP(DPM_PREFETCHER), + FEA_MAP(DPM_GFXCLK), + FEA_MAP(DPM_GFX_PACE), + FEA_MAP(DPM_UCLK), + FEA_MAP(DPM_SOCCLK), + FEA_MAP(DPM_MP0CLK), + FEA_MAP(DPM_LINK), + FEA_MAP(DPM_DCEFCLK), + FEA_MAP(MEM_VDDCI_SCALING), + FEA_MAP(MEM_MVDD_SCALING), + FEA_MAP(DS_GFXCLK), + FEA_MAP(DS_SOCCLK), + FEA_MAP(DS_LCLK), + FEA_MAP(DS_DCEFCLK), + FEA_MAP(DS_UCLK), + FEA_MAP(GFX_ULV), + FEA_MAP(FW_DSTATE), + FEA_MAP(GFXOFF), + FEA_MAP(BACO), + FEA_MAP(VCN_PG), + FEA_MAP(JPEG_PG), + FEA_MAP(USB_PG), + FEA_MAP(RSMU_SMN_CG), + FEA_MAP(PPT), + FEA_MAP(TDC), + FEA_MAP(GFX_EDC), + FEA_MAP(APCC_PLUS), + FEA_MAP(GTHR), + FEA_MAP(ACDC), + FEA_MAP(VR0HOT), + FEA_MAP(VR1HOT), + FEA_MAP(FW_CTF), + FEA_MAP(FAN_CONTROL), + FEA_MAP(THERMAL), + FEA_MAP(GFX_DCS), + FEA_MAP(RM), + FEA_MAP(LED_DISPLAY), + FEA_MAP(GFX_SS), + FEA_MAP(OUT_OF_BAND_MONITOR), + FEA_MAP(TEMP_DEPENDENT_VMIN), + FEA_MAP(MMHUB_PG), + FEA_MAP(ATHUB_PG), + FEA_MAP(APCC_DFLL), +}; + +static struct cmn2asic_mapping navi10_table_map[SMU_TABLE_COUNT] = { + TAB_MAP(PPTABLE), + TAB_MAP(WATERMARKS), + TAB_MAP(AVFS), + TAB_MAP(AVFS_PSM_DEBUG), + TAB_MAP(AVFS_FUSE_OVERRIDE), + TAB_MAP(PMSTATUSLOG), + TAB_MAP(SMU_METRICS), + TAB_MAP(DRIVER_SMU_CONFIG), + TAB_MAP(ACTIVITY_MONITOR_COEFF), + TAB_MAP(OVERDRIVE), + TAB_MAP(I2C_COMMANDS), + TAB_MAP(PACE), +}; + +static struct cmn2asic_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { + PWR_MAP(AC), + PWR_MAP(DC), +}; + +static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), +}; + +static bool is_asic_secure(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + bool is_secure = true; + uint32_t mp0_fw_intf; + + mp0_fw_intf = RREG32_PCIE(MP0_Public | + (smnMP0_FW_INTF & 0xffffffff)); + + if (!(mp0_fw_intf & (1 << 19))) + is_secure = false; + + return is_secure; +} + +static int +navi10_get_allowed_feature_mask(struct smu_context *smu, + uint32_t *feature_mask, uint32_t num) +{ + struct amdgpu_device *adev = smu->adev; + + if (num > 2) + return -EINVAL; + + memset(feature_mask, 0, sizeof(uint32_t) * num); + + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) + | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) + | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) + | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) + | FEATURE_MASK(FEATURE_PPT_BIT) + | FEATURE_MASK(FEATURE_TDC_BIT) + | FEATURE_MASK(FEATURE_GFX_EDC_BIT) + | FEATURE_MASK(FEATURE_APCC_PLUS_BIT) + | FEATURE_MASK(FEATURE_VR0HOT_BIT) + | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) + | FEATURE_MASK(FEATURE_THERMAL_BIT) + | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) + | FEATURE_MASK(FEATURE_DS_LCLK_BIT) + | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) + | FEATURE_MASK(FEATURE_FW_DSTATE_BIT) + | FEATURE_MASK(FEATURE_BACO_BIT) + | FEATURE_MASK(FEATURE_GFX_SS_BIT) + | FEATURE_MASK(FEATURE_APCC_DFLL_BIT) + | FEATURE_MASK(FEATURE_FW_CTF_BIT) + | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT); + + if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); + + if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT); + + if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT); + + if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) + | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) + | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); + + if (adev->pm.pp_feature & PP_ULV_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT); + + if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT); + + if (smu->dc_controlled_by_gpio) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT); + + /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ + if (is_asic_secure(smu)) { + /* only for navi10 A0 */ + if ((adev->asic_type == CHIP_NAVI10) && + (adev->rev_id == 0)) { + *(uint64_t *)feature_mask &= + ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT) + | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) + | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT)); + *(uint64_t *)feature_mask &= + ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); + } + } + + return 0; +} + +static int navi10_check_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) + smu->dc_controlled_by_gpio = true; + + mutex_lock(&smu_baco->mutex); + if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || + powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) + smu_baco->platform_support = true; + mutex_unlock(&smu_baco->mutex); + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + /* + * Instead of having its own buffer space and get overdrive_table copied, + * smu->od_settings just points to the actual overdrive_table + */ + smu->od_settings = &powerplay_table->overdrive_table; + + return 0; +} + +static int navi10_append_powerplay_table(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + struct atom_smc_dpm_info_v4_5 *smc_dpm_table; + struct atom_smc_dpm_info_v4_7 *smc_dpm_table_v4_7; + int index, ret; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smc_dpm_info); + + ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table); + if (ret) + return ret; + + dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n", + smc_dpm_table->table_header.format_revision, + smc_dpm_table->table_header.content_revision); + + if (smc_dpm_table->table_header.format_revision != 4) { + dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n"); + return -EINVAL; + } + + switch (smc_dpm_table->table_header.content_revision) { + case 5: /* nv10 and nv14 */ + memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers, + sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); + break; + case 7: /* nv12 */ + ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table_v4_7); + if (ret) + return ret; + memcpy(smc_pptable->I2cControllers, smc_dpm_table_v4_7->I2cControllers, + sizeof(*smc_dpm_table_v4_7) - sizeof(smc_dpm_table_v4_7->table_header)); + break; + default: + dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n", + smc_dpm_table->table_header.content_revision); + return -EINVAL; + } + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) { + /* TODO: remove it once SMU fw fix it */ + smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN; + } + + return 0; +} + +static int navi10_store_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + + memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, + sizeof(PPTable_t)); + + return 0; +} + +static int navi10_setup_pptable(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v11_0_setup_pptable(smu); + if (ret) + return ret; + + ret = navi10_store_powerplay_table(smu); + if (ret) + return ret; + + ret = navi10_append_powerplay_table(smu); + if (ret) + return ret; + + ret = navi10_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; +} + +static int navi10_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + struct amdgpu_device *adev = smu->adev; + + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + if (adev->asic_type == CHIP_NAVI12) + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV12_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + else + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, + sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(adev->asic_type == CHIP_NAVI12 ? + sizeof(SmuMetrics_NV12_t) : + sizeof(SmuMetrics_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err0_out; + smu_table->metrics_time = 0; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); + if (!smu_table->watermarks_table) + goto err2_out; + + return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; +} + +static int navi10_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + /* + * This works for NV12 also. As although NV12 uses a different + * SmuMetrics structure from other NV1X ASICs, they share the + * same offsets for the heading parts(those members used here). + */ + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK]; + break; + case METRICS_CURR_DCEFCLK: + *value = metrics->CurrClock[PPCLK_DCEFCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + *value = metrics->AverageGfxclkFrequency; + break; + case METRICS_AVERAGE_SOCCLK: + *value = metrics->AverageSocclkFrequency; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->AverageUclkFrequency; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->TemperatureEdge * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->TemperatureHotspot * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->TemperatureMem * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->TemperatureVrGfx * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->TemperatureVrSoc * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_CURR_FANSPEED: + *value = metrics->CurrFanSpeed; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; +} + +static int navi10_allocate_dpm_context(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), + GFP_KERNEL); + if (!smu_dpm->dpm_context) + return -ENOMEM; + + smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); + + return 0; +} + +static int navi10_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = navi10_tables_init(smu); + if (ret) + return ret; + + ret = navi10_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v11_0_init_smc_tables(smu); +} + +static int navi10_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table; + int ret = 0; + + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* vclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* dclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* dcefclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dcef_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCEFCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* pixelclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.pixel_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PIXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* displayclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.display_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DISPCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* phyclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.phy_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PHYCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + return 0; +} + +static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + /* vcn dpm on is a prerequisite for vcn power gate messages */ + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL); + if (ret) + return ret; + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); + if (ret) + return ret; + } + } + + return ret; +} + +static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL); + if (ret) + return ret; + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); + if (ret) + return ret; + } + } + + return ret; +} + +static int navi10_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + switch (clk_id) { + case PPCLK_GFXCLK: + member_type = METRICS_CURR_GFXCLK; + break; + case PPCLK_UCLK: + member_type = METRICS_CURR_UCLK; + break; + case PPCLK_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case PPCLK_VCLK: + member_type = METRICS_CURR_VCLK; + break; + case PPCLK_DCLK: + member_type = METRICS_CURR_DCLK; + break; + case PPCLK_DCEFCLK: + member_type = METRICS_CURR_DCEFCLK; + break; + default: + return -EINVAL; + } + + return navi10_get_smu_metrics_data(smu, + member_type, + value); +} + +static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + DpmDescriptor_t *dpm_desc = NULL; + uint32_t clk_index = 0; + + clk_index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + dpm_desc = &pptable->DpmDescriptor[clk_index]; + + /* 0 - Fine grained DPM, 1 - Discrete DPM */ + return dpm_desc->SnapToDiscrete == 0 ? true : false; +} + +static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_CAP cap) +{ + return od_table->cap[cap]; +} + +static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_table, + enum SMU_11_0_ODSETTING_ID setting, + uint32_t *min, uint32_t *max) +{ + if (min) + *min = od_table->min[setting]; + if (max) + *max = od_table->max[setting]; +} + +static int navi10_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) +{ + uint16_t *curve_settings; + int i, size = 0, ret = 0; + uint32_t cur_value = 0, value = 0, count = 0; + uint32_t freq_values[3] = {0}; + uint32_t mark_index = 0; + struct smu_table_context *table_context = &smu->smu_table; + uint32_t gen_speed, lane_width; + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; + OverDriveTable_t *od_table = + (OverDriveTable_t *)table_context->overdrive_table; + struct smu_11_0_overdrive_table *od_settings = smu->od_settings; + uint32_t min_value, max_value; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_FCLK: + case SMU_DCEFCLK: + ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value); + if (ret) + return size; + + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); + if (ret) + return size; + + if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) { + for (i = 0; i < count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); + if (ret) + return size; + + size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, + cur_value == value ? "*" : ""); + } + } else { + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); + if (ret) + return size; + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); + if (ret) + return size; + + freq_values[1] = cur_value; + mark_index = cur_value == freq_values[0] ? 0 : + cur_value == freq_values[2] ? 2 : 1; + if (mark_index != 1) + freq_values[1] = (freq_values[0] + freq_values[2]) / 2; + + for (i = 0; i < 3; i++) { + size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i], + i == mark_index ? "*" : ""); + } + + } + break; + case SMU_PCIE: + gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu); + lane_width = smu_v11_0_get_current_pcie_link_width_level(smu); + for (i = 0; i < NUM_LINK_LEVELS; i++) + size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "", + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "", + pptable->LclkFreq[i], + (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) && + (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ? + "*" : ""); + break; + case SMU_OD_SCLK: + if (!smu->od_enabled || !od_table || !od_settings) + break; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) + break; + size += sprintf(buf + size, "OD_SCLK:\n"); + size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax); + break; + case SMU_OD_MCLK: + if (!smu->od_enabled || !od_table || !od_settings) + break; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) + break; + size += sprintf(buf + size, "OD_MCLK:\n"); + size += sprintf(buf + size, "1: %uMHz\n", od_table->UclkFmax); + break; + case SMU_OD_VDDC_CURVE: + if (!smu->od_enabled || !od_table || !od_settings) + break; + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) + break; + size += sprintf(buf + size, "OD_VDDC_CURVE:\n"); + for (i = 0; i < 3; i++) { + switch (i) { + case 0: + curve_settings = &od_table->GfxclkFreq1; + break; + case 1: + curve_settings = &od_table->GfxclkFreq2; + break; + case 2: + curve_settings = &od_table->GfxclkFreq3; + break; + default: + break; + } + size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); + } + break; + case SMU_OD_RANGE: + if (!smu->od_enabled || !od_table || !od_settings) + break; + size = sprintf(buf, "%s:\n", "OD_RANGE"); + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, + &min_value, NULL); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX, + NULL, &max_value); + size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", + min_value, max_value); + } + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, + &min_value, &max_value); + size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", + min_value, max_value); + } + + if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", + min_value, max_value); + navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3, + &min_value, &max_value); + size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", + min_value, max_value); + } + + break; + default: + break; + } + + return size; +} + +static int navi10_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, uint32_t mask) +{ + + int ret = 0, size = 0; + uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_DCEFCLK: + case SMU_FCLK: + /* There is only 2 levels for fine grained DPM */ + if (navi10_is_support_fine_grained_dpm(smu, clk_type)) { + soft_max_level = (soft_max_level >= 1 ? 1 : 0); + soft_min_level = (soft_min_level >= 1 ? 1 : 0); + } + + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + if (ret) + return size; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + if (ret) + return size; + + ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); + if (ret) + return size; + break; + default: + break; + } + + return size; +} + +static int navi10_populate_umd_state_clk(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; + uint32_t sclk_freq; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + switch (adev->asic_type) { + case CHIP_NAVI10: + switch (adev->pdev->revision) { + case 0xf0: /* XTX */ + case 0xc0: + sclk_freq = NAVI10_PEAK_SCLK_XTX; + break; + case 0xf1: /* XT */ + case 0xc1: + sclk_freq = NAVI10_PEAK_SCLK_XT; + break; + default: /* XL */ + sclk_freq = NAVI10_PEAK_SCLK_XL; + break; + } + break; + case CHIP_NAVI14: + switch (adev->pdev->revision) { + case 0xc7: /* XT */ + case 0xf4: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; + break; + case 0xc1: /* XTM */ + case 0xf2: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; + break; + case 0xc3: /* XLM */ + case 0xf3: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + case 0xc5: /* XTX */ + case 0xf6: + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; + break; + default: /* XL */ + sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; + break; + } + break; + case CHIP_NAVI12: + sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; + break; + default: + sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value; + break; + } + pstate_table->gfxclk_pstate.peak = sclk_freq; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK && + mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK && + soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) { + pstate_table->gfxclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_GFXCLK; + pstate_table->uclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_MEMCLK; + pstate_table->socclk_pstate.standard = + NAVI10_UMD_PSTATE_PROFILING_SOCCLK; + } else { + pstate_table->gfxclk_pstate.standard = + pstate_table->gfxclk_pstate.min; + pstate_table->uclk_pstate.standard = + pstate_table->uclk_pstate.min; + pstate_table->socclk_pstate.standard = + pstate_table->socclk_pstate.min; + } + + return 0; +} + +static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, + enum smu_clk_type clk_type, + struct pp_clock_levels_with_latency *clocks) +{ + int ret = 0, i = 0; + uint32_t level_count = 0, freq = 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_DCEFCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count); + if (ret) + return ret; + + level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS); + clocks->num_levels = level_count; + + for (i = 0; i < level_count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq); + if (ret) + return ret; + + clocks->data[i].clocks_in_khz = freq * 1000; + clocks->data[i].latency_in_us = 0; + } + break; + default: + break; + } + + return ret; +} + +static int navi10_pre_display_config_changed(struct smu_context *smu) +{ + int ret = 0; + uint32_t max_freq = 0; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); + if (ret) + return ret; + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); + if (ret) + return ret; + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); + if (ret) + return ret; + } + + return ret; +} + +static int navi10_display_config_changed(struct smu_context *smu) +{ + int ret = 0; + + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, + smu->display_config->num_display, + NULL); + if (ret) + return ret; + } + + return ret; +} + +static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value) +{ + if (!value) + return -EINVAL; + + return navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + value); +} + +static int navi10_get_current_activity_percent(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + value); + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = navi10_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); + return -EINVAL; + } + + return ret; +} + +static bool navi10_is_dpm_running(struct smu_context *smu) +{ + int ret = 0; + uint32_t feature_mask[2]; + unsigned long feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | + ((uint64_t)feature_mask[1] << 32)); + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static int navi10_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + if (!speed) + return -EINVAL; + + return navi10_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); +} + +static int navi10_get_fan_speed_percent(struct smu_context *smu, + uint32_t *speed) +{ + int ret = 0; + uint32_t percent = 0; + uint32_t current_rpm; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + ret = navi10_get_fan_speed_rpm(smu, ¤t_rpm); + if (ret) + return ret; + + percent = current_rpm * 100 / pptable->FanMaximumRpm; + *speed = percent > 100 ? 100 : percent; + + return ret; +} + +static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + uint32_t i, size = 0; + int16_t workload_type = 0; + static const char *profile_name[] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + static const char *title[] = { + "PROFILE_INDEX(NAME)", + "CLOCK_TYPE(NAME)", + "FPS", + "MinFreqType", + "MinActiveFreqType", + "MinActiveFreq", + "BoosterFreqType", + "BoosterFreq", + "PD_Data_limit_c", + "PD_Data_error_coeff", + "PD_Data_error_rate_coeff"}; + int result = 0; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9], title[10]); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type < 0) + return -EINVAL; + + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, + (void *)(&activity_monitor), false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return result; + } + + size += sprintf(buf + size, "%2d %14s%s:\n", + i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 0, + "GFXCLK", + activity_monitor.Gfx_FPS, + activity_monitor.Gfx_MinFreqStep, + activity_monitor.Gfx_MinActiveFreqType, + activity_monitor.Gfx_MinActiveFreq, + activity_monitor.Gfx_BoosterFreqType, + activity_monitor.Gfx_BoosterFreq, + activity_monitor.Gfx_PD_Data_limit_c, + activity_monitor.Gfx_PD_Data_error_coeff, + activity_monitor.Gfx_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 1, + "SOCCLK", + activity_monitor.Soc_FPS, + activity_monitor.Soc_MinFreqStep, + activity_monitor.Soc_MinActiveFreqType, + activity_monitor.Soc_MinActiveFreq, + activity_monitor.Soc_BoosterFreqType, + activity_monitor.Soc_BoosterFreq, + activity_monitor.Soc_PD_Data_limit_c, + activity_monitor.Soc_PD_Data_error_coeff, + activity_monitor.Soc_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 2, + "MEMLK", + activity_monitor.Mem_FPS, + activity_monitor.Mem_MinFreqStep, + activity_monitor.Mem_MinActiveFreqType, + activity_monitor.Mem_MinActiveFreq, + activity_monitor.Mem_BoosterFreqType, + activity_monitor.Mem_BoosterFreq, + activity_monitor.Mem_PD_Data_limit_c, + activity_monitor.Mem_PD_Data_error_coeff, + activity_monitor.Mem_PD_Data_error_rate_coeff); + } + + return size; +} + +static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + int workload_type, ret = 0; + + smu->power_profile_mode = input[size]; + + if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); + return -EINVAL; + } + + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), false); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return ret; + } + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor.Gfx_FPS = input[1]; + activity_monitor.Gfx_MinFreqStep = input[2]; + activity_monitor.Gfx_MinActiveFreqType = input[3]; + activity_monitor.Gfx_MinActiveFreq = input[4]; + activity_monitor.Gfx_BoosterFreqType = input[5]; + activity_monitor.Gfx_BoosterFreq = input[6]; + activity_monitor.Gfx_PD_Data_limit_c = input[7]; + activity_monitor.Gfx_PD_Data_error_coeff = input[8]; + activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; + break; + case 1: /* Socclk */ + activity_monitor.Soc_FPS = input[1]; + activity_monitor.Soc_MinFreqStep = input[2]; + activity_monitor.Soc_MinActiveFreqType = input[3]; + activity_monitor.Soc_MinActiveFreq = input[4]; + activity_monitor.Soc_BoosterFreqType = input[5]; + activity_monitor.Soc_BoosterFreq = input[6]; + activity_monitor.Soc_PD_Data_limit_c = input[7]; + activity_monitor.Soc_PD_Data_error_coeff = input[8]; + activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; + break; + case 2: /* Memlk */ + activity_monitor.Mem_FPS = input[1]; + activity_monitor.Mem_MinFreqStep = input[2]; + activity_monitor.Mem_MinActiveFreqType = input[3]; + activity_monitor.Mem_MinActiveFreq = input[4]; + activity_monitor.Mem_BoosterFreqType = input[5]; + activity_monitor.Mem_BoosterFreq = input[6]; + activity_monitor.Mem_PD_Data_limit_c = input[7]; + activity_monitor.Mem_PD_Data_error_coeff = input[8]; + activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; + break; + } + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), true); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); + return ret; + } + } + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + smu->power_profile_mode); + if (workload_type < 0) + return -EINVAL; + smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, + 1 << workload_type, NULL); + + return ret; +} + +static int navi10_notify_smc_display_config(struct smu_context *smu) +{ + struct smu_clocks min_clocks = {0}; + struct pp_display_clock_request clock_req; + int ret = 0; + + min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; + min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; + min_clocks.memory_clock = smu->display_config->min_mem_set_clock; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + clock_req.clock_type = amd_pp_dcef_clock; + clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; + + ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); + if (!ret) { + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMinDeepSleepDcefclk, + min_clocks.dcef_clock_in_sr/100, + NULL); + if (ret) { + dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!"); + return ret; + } + } + } else { + dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!"); + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); + if (ret) { + dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); + return ret; + } + } + + return 0; +} + +static int navi10_set_watermarks_table(struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) +{ + Watermarks_t *table = smu->smu_table.watermarks_table; + int ret = 0; + int i; + + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; + + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[1][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } + + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[0][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } + + smu->watermarks_bitmap |= WATERMARKS_EXIST; + } + + /* pass data to smu controller */ + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + ret = smu_cmn_write_watermarks_table(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to update WMTABLE!"); + return ret; + } + smu->watermarks_bitmap |= WATERMARKS_LOADED; + } + + return 0; +} + +static int navi10_thermal_get_temperature(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + value); + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + value); + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = navi10_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); + return -EINVAL; + } + + return ret; +} + +static int navi10_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + + if(!data || !size) + return -EINVAL; + + mutex_lock(&smu->sensor_lock); + switch (sensor) { + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *(uint32_t *)data = pptable->FanMaximumRpm; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = navi10_get_gpu_power(smu, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + case AMDGPU_PP_SENSOR_EDGE_TEMP: + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + mutex_unlock(&smu->sensor_lock); + + return ret; +} + +static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states) +{ + uint32_t num_discrete_levels = 0; + uint16_t *dpm_levels = NULL; + uint16_t i = 0; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *driver_ppt = NULL; + + if (!clocks_in_khz || !num_states || !table_context->driver_pptable) + return -EINVAL; + + driver_ppt = table_context->driver_pptable; + num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; + dpm_levels = driver_ppt->FreqTableUclk; + + if (num_discrete_levels == 0 || dpm_levels == NULL) + return -EINVAL; + + *num_states = num_discrete_levels; + for (i = 0; i < num_discrete_levels; i++) { + /* convert to khz */ + *clocks_in_khz = (*dpm_levels) * 1000; + clocks_in_khz++; + dpm_levels++; + } + + return 0; +} + +static int navi10_get_thermal_temperature_range(struct smu_context *smu, + struct smu_temperature_range *range) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + if (!range) + return -EINVAL; + + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->TedgeLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->ThotspotLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->TmemLimit * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; + + return 0; +} + +static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, + bool disable_memory_clock_switch) +{ + int ret = 0; + struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = + (struct smu_11_0_max_sustainable_clocks *) + smu->smu_table.max_sustainable_clocks; + uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal; + uint32_t max_memory_clock = max_sustainable_clocks->uclock; + + if(smu->disable_uclk_switch == disable_memory_clock_switch) + return 0; + + if(disable_memory_clock_switch) + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); + else + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); + + if(!ret) + smu->disable_uclk_switch = disable_memory_clock_switch; + + return ret; +} + +static int navi10_get_power_limit(struct smu_context *smu) +{ + struct smu_11_0_powerplay_table *powerplay_table = + (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; + struct smu_11_0_overdrive_table *od_settings = smu->od_settings; + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t power_limit, od_percent; + + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; + } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; + + if (smu->od_enabled && + navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); + + power_limit *= (100 + od_percent); + power_limit /= 100; + } + smu->max_power_limit = power_limit; + + return 0; +} + +static int navi10_update_pcie_parameters(struct smu_context *smu, + uint32_t pcie_gen_cap, + uint32_t pcie_width_cap) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t smu_pcie_arg; + int ret, i; + + /* lclk dpm table setup */ + for (i = 0; i < MAX_PCIE_CONF; i++) { + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; + } + + for (i = 0; i < NUM_LINK_LEVELS; i++) { + smu_pcie_arg = (i << 16) | + ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : + (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? + pptable->PcieLaneCount[i] : pcie_width_cap); + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, + NULL); + + if (ret) + return ret; + + if (pptable->PcieGenSpeed[i] > pcie_gen_cap) + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap; + if (pptable->PcieLaneCount[i] > pcie_width_cap) + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap; + } + + return 0; +} + +static inline void navi10_dump_od_table(struct smu_context *smu, + OverDriveTable_t *od_table) +{ + dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax); + dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1); + dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2); + dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3); + dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax); + dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct); +} + +static int navi10_od_setting_check_range(struct smu_context *smu, + struct smu_11_0_overdrive_table *od_table, + enum SMU_11_0_ODSETTING_ID setting, + uint32_t value) +{ + if (value < od_table->min[setting]) { + dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]); + return -EINVAL; + } + if (value > od_table->max[setting]) { + dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]); + return -EINVAL; + } + return 0; +} + +static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, + uint16_t *voltage, + uint32_t freq) +{ + uint32_t param = (freq & 0xFFFF) | (PPCLK_GFXCLK << 16); + uint32_t value = 0; + int ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetVoltageByDpm, + param, + &value); + if (ret) { + dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); + return ret; + } + + *voltage = (uint16_t)value; + + return 0; +} + +static bool navi10_is_baco_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + + if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) + return false; + + val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); + return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; +} + +static int navi10_set_default_od_settings(struct smu_context *smu) +{ + OverDriveTable_t *od_table = + (OverDriveTable_t *)smu->smu_table.overdrive_table; + OverDriveTable_t *boot_od_table = + (OverDriveTable_t *)smu->smu_table.boot_overdrive_table; + int ret = 0; + + ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false); + if (ret) { + dev_err(smu->adev->dev, "Failed to get overdrive table!\n"); + return ret; + } + + if (!od_table->GfxclkVolt1) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt1, + od_table->GfxclkFreq1); + if (ret) + return ret; + } + + if (!od_table->GfxclkVolt2) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt2, + od_table->GfxclkFreq2); + if (ret) + return ret; + } + + if (!od_table->GfxclkVolt3) { + ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, + &od_table->GfxclkVolt3, + od_table->GfxclkFreq3); + if (ret) + return ret; + } + + memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t)); + + navi10_dump_od_table(smu, od_table); + + return 0; +} + +static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) { + int i; + int ret = 0; + struct smu_table_context *table_context = &smu->smu_table; + OverDriveTable_t *od_table; + struct smu_11_0_overdrive_table *od_settings; + enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting; + uint16_t *freq_ptr, *voltage_ptr; + od_table = (OverDriveTable_t *)table_context->overdrive_table; + + if (!smu->od_enabled) { + dev_warn(smu->adev->dev, "OverDrive is not enabled!\n"); + return -EINVAL; + } + + if (!smu->od_settings) { + dev_err(smu->adev->dev, "OD board limits are not set!\n"); + return -ENOENT; + } + + od_settings = smu->od_settings; + + switch (type) { + case PP_OD_EDIT_SCLK_VDDC_TABLE: + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { + dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n"); + return -ENOTSUPP; + } + if (!table_context->overdrive_table) { + dev_err(smu->adev->dev, "Overdrive is not initialized\n"); + return -EINVAL; + } + for (i = 0; i < size; i += 2) { + if (i + 2 > size) { + dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size); + return -EINVAL; + } + switch (input[i]) { + case 0: + freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN; + freq_ptr = &od_table->GfxclkFmin; + if (input[i + 1] > od_table->GfxclkFmax) { + dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n", + input[i + 1], + od_table->GfxclkFmin); + return -EINVAL; + } + break; + case 1: + freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX; + freq_ptr = &od_table->GfxclkFmax; + if (input[i + 1] < od_table->GfxclkFmin) { + dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n", + input[i + 1], + od_table->GfxclkFmax); + return -EINVAL; + } + break; + default: + dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]); + dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n"); + return -EINVAL; + } + ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]); + if (ret) + return ret; + *freq_ptr = input[i + 1]; + } + break; + case PP_OD_EDIT_MCLK_VDDC_TABLE: + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { + dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n"); + return -ENOTSUPP; + } + if (size < 2) { + dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); + return -EINVAL; + } + if (input[0] != 1) { + dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]); + dev_info(smu->adev->dev, "Supported indices: [1:max]\n"); + return -EINVAL; + } + ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]); + if (ret) + return ret; + od_table->UclkFmax = input[1]; + break; + case PP_OD_RESTORE_DEFAULT_TABLE: + if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) { + dev_err(smu->adev->dev, "Overdrive table was not initialized!\n"); + return -EINVAL; + } + memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t)); + break; + case PP_OD_COMMIT_DPM_TABLE: + navi10_dump_od_table(smu, od_table); + ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true); + if (ret) { + dev_err(smu->adev->dev, "Failed to import overdrive table!\n"); + return ret; + } + break; + case PP_OD_EDIT_VDDC_CURVE: + if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { + dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n"); + return -ENOTSUPP; + } + if (size < 3) { + dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); + return -EINVAL; + } + if (!od_table) { + dev_info(smu->adev->dev, "Overdrive is not initialized\n"); + return -EINVAL; + } + + switch (input[0]) { + case 0: + freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1; + voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1; + freq_ptr = &od_table->GfxclkFreq1; + voltage_ptr = &od_table->GfxclkVolt1; + break; + case 1: + freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2; + voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2; + freq_ptr = &od_table->GfxclkFreq2; + voltage_ptr = &od_table->GfxclkVolt2; + break; + case 2: + freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3; + voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3; + freq_ptr = &od_table->GfxclkFreq3; + voltage_ptr = &od_table->GfxclkVolt3; + break; + default: + dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]); + dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n"); + return -EINVAL; + } + ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]); + if (ret) + return ret; + // Allow setting zero to disable the OverDrive VDDC curve + if (input[2] != 0) { + ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]); + if (ret) + return ret; + *freq_ptr = input[1]; + *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE; + dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr); + } else { + // If setting 0, disable all voltage curve settings + od_table->GfxclkVolt1 = 0; + od_table->GfxclkVolt2 = 0; + od_table->GfxclkVolt3 = 0; + } + navi10_dump_od_table(smu, od_table); + break; + default: + return -ENOSYS; + } + return ret; +} + +static int navi10_run_btc(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunBtc, NULL); + if (ret) + dev_err(smu->adev->dev, "RunBtc failed!\n"); + + return ret; +} + +static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable) +{ + int result = 0; + + if (!enable) + result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); + else + result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); + + return result; +} + +static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev) +{ + if (adev->asic_type != CHIP_NAVI10) + return false; + + if (adev->pdev->device == 0x731f && + (adev->pdev->revision == 0xc2 || + adev->pdev->revision == 0xc3 || + adev->pdev->revision == 0xca || + adev->pdev->revision == 0xcb)) + return true; + else + return false; +} + +static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) +{ + uint32_t uclk_count, uclk_min, uclk_max; + uint32_t smu_version; + int ret = 0; + + if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) + return 0; + + ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (ret) + return ret; + + /* This workaround is available only for 42.50 or later SMC firmwares */ + if (smu_version < 0x2A3200) + return 0; + + ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); + if (ret) + return ret; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); + if (ret) + return ret; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); + if (ret) + return ret; + + /* Force UCLK out of the highest DPM */ + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min); + if (ret) + return ret; + + /* Revert the UCLK Hardmax */ + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max); + if (ret) + return ret; + + /* + * In this case, SMU already disabled dummy pstate during enablement + * of UCLK DPM, we have to re-enabled it. + * */ + return navi10_dummy_pstate_control(smu, true); +} + +static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, + uint8_t address, uint32_t numbytes, + uint8_t *data) +{ + int i; + + BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); + + req->I2CcontrollerPort = 0; + req->I2CSpeed = 2; + req->SlaveAddress = address; + req->NumCmds = numbytes; + + for (i = 0; i < numbytes; i++) { + SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; + + /* First 2 bytes are always write for lower 2b EEPROM address */ + if (i < 2) + cmd->Cmd = 1; + else + cmd->Cmd = write; + + + /* Add RESTART for read after address filled */ + cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; + + /* Add STOP in the end */ + cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; + + /* Fill with data regardless if read or write to simplify code */ + cmd->RegisterAddr = data[i]; + } +} + +static int navi10_i2c_read_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t i, ret = 0; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_table *table = &smu_table->driver_table; + + memset(&req, 0, sizeof(req)); + navi10_fill_i2c_req(&req, false, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + /* Now read data starting with that address */ + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, + true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; + + /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ + for (i = 0; i < numbytes; i++) + data[i] = res->SwI2cCmds[i].Data; + + dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + } else + dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret); + + return ret; +} + +static int navi10_i2c_write_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t ret; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + + memset(&req, 0, sizeof(req)); + navi10_fill_i2c_req(&req, true, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + /* + * According to EEPROM spec there is a MAX of 10 ms required for + * EEPROM to flush internal RX buffer after STOP was issued at the + * end of write transaction. During this time the EEPROM will not be + * responsive to any more commands - so wait a bit more. + */ + msleep(10); + + } else + dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret); + + return ret; +} + +static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; + uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; + + for (i = 0; i < num; i++) { + /* + * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at + * once and hence the data needs to be spliced into chunks and sent each + * chunk separately + */ + data_size = msgs[i].len - 2; + data_chunk_size = MAX_SW_I2C_COMMANDS - 2; + next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); + data_ptr = msgs[i].buf + 2; + + for (j = 0; j < data_size / data_chunk_size; j++) { + /* Insert the EEPROM dest addess, bits 0-15 */ + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = navi10_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + + memcpy(data_ptr, data_chunk + 2, data_chunk_size); + } else { + + memcpy(data_chunk + 2, data_ptr, data_chunk_size); + + ret = navi10_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + } + + if (ret) { + num = -EIO; + goto fail; + } + + next_eeprom_addr += data_chunk_size; + data_ptr += data_chunk_size; + } + + if (data_size % data_chunk_size) { + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = navi10_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + + memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); + } else { + memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); + + ret = navi10_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + } + + if (ret) { + num = -EIO; + goto fail; + } + } + } + +fail: + return num; +} + +static u32 navi10_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + + +static const struct i2c_algorithm navi10_i2c_algo = { + .master_xfer = navi10_i2c_xfer, + .functionality = navi10_i2c_func, +}; + +static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + int res; + + control->owner = THIS_MODULE; + control->class = I2C_CLASS_SPD; + control->dev.parent = &adev->pdev->dev; + control->algo = &navi10_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + + res = i2c_add_adapter(control); + if (res) + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + + return res; +} + +static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +{ + i2c_del_adapter(control); +} + +static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + struct amdgpu_device *adev = smu->adev; + SmuMetrics_NV12_t nv12_metrics = { 0 }; + SmuMetrics_t metrics; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + true); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); + if (adev->asic_type == CHIP_NAVI12) + memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); + + mutex_unlock(&smu->metrics_lock); + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; + + if (adev->asic_type == CHIP_NAVI12) { + gpu_metrics->energy_accumulator = nv12_metrics.EnergyAccumulator; + gpu_metrics->average_vclk0_frequency = nv12_metrics.AverageVclkFrequency; + gpu_metrics->average_dclk0_frequency = nv12_metrics.AverageDclkFrequency; + gpu_metrics->average_mm_activity = nv12_metrics.VcnActivityPercentage; + } + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + +static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t param = 0; + + /* Navi12 does not support this */ + if (adev->asic_type == CHIP_NAVI12) + return 0; + + /* Workaround for WS SKU */ + if (adev->pdev->device == 0x7312 && + adev->pdev->revision == 0) + param = 0xD188; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + param, + NULL); +} + +static const struct pptable_funcs navi10_ppt_funcs = { + .get_allowed_feature_mask = navi10_get_allowed_feature_mask, + .set_default_dpm_table = navi10_set_default_dpm_table, + .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable, + .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable, + .i2c_init = navi10_i2c_control_init, + .i2c_fini = navi10_i2c_control_fini, + .print_clk_levels = navi10_print_clk_levels, + .force_clk_levels = navi10_force_clk_levels, + .populate_umd_state_clk = navi10_populate_umd_state_clk, + .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency, + .pre_display_config_changed = navi10_pre_display_config_changed, + .display_config_changed = navi10_display_config_changed, + .notify_smc_display_config = navi10_notify_smc_display_config, + .is_dpm_running = navi10_is_dpm_running, + .get_fan_speed_percent = navi10_get_fan_speed_percent, + .get_fan_speed_rpm = navi10_get_fan_speed_rpm, + .get_power_profile_mode = navi10_get_power_profile_mode, + .set_power_profile_mode = navi10_set_power_profile_mode, + .set_watermarks_table = navi10_set_watermarks_table, + .read_sensor = navi10_read_sensor, + .get_uclk_dpm_states = navi10_get_uclk_dpm_states, + .set_performance_level = smu_v11_0_set_performance_level, + .get_thermal_temperature_range = navi10_get_thermal_temperature_range, + .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, + .get_power_limit = navi10_get_power_limit, + .update_pcie_parameters = navi10_update_pcie_parameters, + .init_microcode = smu_v11_0_init_microcode, + .load_microcode = smu_v11_0_load_microcode, + .fini_microcode = smu_v11_0_fini_microcode, + .init_smc_tables = navi10_init_smc_tables, + .fini_smc_tables = smu_v11_0_fini_smc_tables, + .init_power = smu_v11_0_init_power, + .fini_power = smu_v11_0_fini_power, + .check_fw_status = smu_v11_0_check_fw_status, + .setup_pptable = navi10_setup_pptable, + .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, + .check_fw_version = smu_v11_0_check_fw_version, + .write_pptable = smu_cmn_write_pptable, + .set_driver_table_location = smu_v11_0_set_driver_table_location, + .set_tool_table_location = smu_v11_0_set_tool_table_location, + .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, + .system_features_control = smu_v11_0_system_features_control, + .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, + .send_smc_msg = smu_cmn_send_smc_msg, + .init_display_count = smu_v11_0_init_display_count, + .set_allowed_mask = smu_v11_0_set_allowed_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, + .notify_display_change = smu_v11_0_notify_display_change, + .set_power_limit = smu_v11_0_set_power_limit, + .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, + .enable_thermal_alert = smu_v11_0_enable_thermal_alert, + .disable_thermal_alert = smu_v11_0_disable_thermal_alert, + .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk, + .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, + .get_fan_control_mode = smu_v11_0_get_fan_control_mode, + .set_fan_control_mode = smu_v11_0_set_fan_control_mode, + .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, + .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, + .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, + .gfx_off_control = smu_v11_0_gfx_off_control, + .register_irq_handler = smu_v11_0_register_irq_handler, + .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, + .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, + .baco_is_support= navi10_is_baco_supported, + .baco_get_state = smu_v11_0_baco_get_state, + .baco_set_state = smu_v11_0_baco_set_state, + .baco_enter = smu_v11_0_baco_enter, + .baco_exit = smu_v11_0_baco_exit, + .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, + .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .set_default_od_settings = navi10_set_default_od_settings, + .od_edit_dpm_table = navi10_od_edit_dpm_table, + .run_btc = navi10_run_btc, + .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround, + .set_power_source = smu_v11_0_set_power_source, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = navi10_get_gpu_metrics, + .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, +}; + +void navi10_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &navi10_ppt_funcs; + smu->message_map = navi10_message_map; + smu->clock_map = navi10_clk_map; + smu->feature_map = navi10_feature_mask_map; + smu->table_map = navi10_table_map; + smu->pwr_src_map = navi10_pwr_src_map; + smu->workload_map = navi10_workload_map; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h new file mode 100644 index 000000000000..84dc5a1b6830 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.h @@ -0,0 +1,54 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __NAVI10_PPT_H__ +#define __NAVI10_PPT_H__ + +#define NAVI10_PEAK_SCLK_XTX (1830) +#define NAVI10_PEAK_SCLK_XT (1755) +#define NAVI10_PEAK_SCLK_XL (1625) + +#define NAVI10_UMD_PSTATE_PROFILING_GFXCLK (1300) +#define NAVI10_UMD_PSTATE_PROFILING_SOCCLK (980) +#define NAVI10_UMD_PSTATE_PROFILING_MEMCLK (625) +#define NAVI10_UMD_PSTATE_PROFILING_VCLK (980) +#define NAVI10_UMD_PSTATE_PROFILING_DCLK (850) + +#define NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK (1670) +#define NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK (1448) +#define NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK (1181) +#define NAVI14_UMD_PSTATE_PEAK_XTX_GFXCLK (1717) +#define NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK (1448) + +#define NAVI14_UMD_PSTATE_PROFILING_GFXCLK (1200) +#define NAVI14_UMD_PSTATE_PROFILING_SOCCLK (900) +#define NAVI14_UMD_PSTATE_PROFILING_MEMCLK (600) +#define NAVI14_UMD_PSTATE_PROFILING_VCLK (900) +#define NAVI14_UMD_PSTATE_PROFILING_DCLK (800) + +#define NAVI12_UMD_PSTATE_PEAK_GFXCLK (1100) + +#define NAVI10_VOLTAGE_SCALE (4) + +extern void navi10_set_ppt_funcs(struct smu_context *smu); + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c new file mode 100644 index 000000000000..407a11c2826b --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -0,0 +1,2810 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include +#include +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "smu_v11_0.h" +#include "smu11_driver_if_sienna_cichlid.h" +#include "soc15_common.h" +#include "atom.h" +#include "sienna_cichlid_ppt.h" +#include "smu_v11_0_7_pptable.h" +#include "smu_v11_0_7_ppsmc.h" +#include "nbio/nbio_2_3_offset.h" +#include "nbio/nbio_2_3_sh_mask.h" +#include "thm/thm_11_0_2_offset.h" +#include "thm/thm_11_0_2_sh_mask.h" +#include "mp/mp_11_0_offset.h" +#include "mp/mp_11_0_sh_mask.h" + +#include "asic_reg/mp/mp_11_0_sh_mask.h" +#include "smu_cmn.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) + +#define FEATURE_MASK(feature) (1ULL << feature) +#define SMC_DPM_FEATURE ( \ + FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ + FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ + 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), + MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 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), + MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), + 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, 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, 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, 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, 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, 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), + MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), +}; + +static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, PPCLK_GFXCLK), + CLK_MAP(SCLK, PPCLK_GFXCLK), + CLK_MAP(SOCCLK, PPCLK_SOCCLK), + CLK_MAP(FCLK, PPCLK_FCLK), + CLK_MAP(UCLK, PPCLK_UCLK), + CLK_MAP(MCLK, PPCLK_UCLK), + CLK_MAP(DCLK, PPCLK_DCLK_0), + CLK_MAP(DCLK1, PPCLK_DCLK_1), + CLK_MAP(VCLK, PPCLK_VCLK_0), + CLK_MAP(VCLK1, PPCLK_VCLK_1), + CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), + CLK_MAP(DISPCLK, PPCLK_DISPCLK), + CLK_MAP(PIXCLK, PPCLK_PIXCLK), + CLK_MAP(PHYCLK, PPCLK_PHYCLK), +}; + +static struct cmn2asic_mapping sienna_cichlid_feature_mask_map[SMU_FEATURE_COUNT] = { + FEA_MAP(DPM_PREFETCHER), + FEA_MAP(DPM_GFXCLK), + FEA_MAP(DPM_GFX_GPO), + FEA_MAP(DPM_UCLK), + FEA_MAP(DPM_SOCCLK), + FEA_MAP(DPM_MP0CLK), + FEA_MAP(DPM_LINK), + FEA_MAP(DPM_DCEFCLK), + FEA_MAP(MEM_VDDCI_SCALING), + FEA_MAP(MEM_MVDD_SCALING), + FEA_MAP(DS_GFXCLK), + FEA_MAP(DS_SOCCLK), + FEA_MAP(DS_LCLK), + FEA_MAP(DS_DCEFCLK), + FEA_MAP(DS_UCLK), + FEA_MAP(GFX_ULV), + FEA_MAP(FW_DSTATE), + FEA_MAP(GFXOFF), + FEA_MAP(BACO), + FEA_MAP(MM_DPM_PG), + FEA_MAP(RSMU_SMN_CG), + FEA_MAP(PPT), + FEA_MAP(TDC), + FEA_MAP(APCC_PLUS), + FEA_MAP(GTHR), + FEA_MAP(ACDC), + FEA_MAP(VR0HOT), + FEA_MAP(VR1HOT), + FEA_MAP(FW_CTF), + FEA_MAP(FAN_CONTROL), + FEA_MAP(THERMAL), + FEA_MAP(GFX_DCS), + FEA_MAP(RM), + FEA_MAP(LED_DISPLAY), + FEA_MAP(GFX_SS), + FEA_MAP(OUT_OF_BAND_MONITOR), + FEA_MAP(TEMP_DEPENDENT_VMIN), + FEA_MAP(MMHUB_PG), + FEA_MAP(ATHUB_PG), + FEA_MAP(APCC_DFLL), +}; + +static struct cmn2asic_mapping sienna_cichlid_table_map[SMU_TABLE_COUNT] = { + TAB_MAP(PPTABLE), + TAB_MAP(WATERMARKS), + TAB_MAP(AVFS_PSM_DEBUG), + TAB_MAP(AVFS_FUSE_OVERRIDE), + TAB_MAP(PMSTATUSLOG), + TAB_MAP(SMU_METRICS), + TAB_MAP(DRIVER_SMU_CONFIG), + TAB_MAP(ACTIVITY_MONITOR_COEFF), + TAB_MAP(OVERDRIVE), + TAB_MAP(I2C_COMMANDS), + TAB_MAP(PACE), +}; + +static struct cmn2asic_mapping sienna_cichlid_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { + PWR_MAP(AC), + PWR_MAP(DC), +}; + +static struct cmn2asic_mapping sienna_cichlid_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), +}; + +static int +sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, + uint32_t *feature_mask, uint32_t num) +{ + struct amdgpu_device *adev = smu->adev; + + if (num > 2) + return -EINVAL; + + memset(feature_mask, 0, sizeof(uint32_t) * num); + + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) + | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) + | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) + | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) + | FEATURE_MASK(FEATURE_DS_FCLK_BIT) + | FEATURE_MASK(FEATURE_DS_UCLK_BIT) + | FEATURE_MASK(FEATURE_FW_DSTATE_BIT) + | FEATURE_MASK(FEATURE_DF_CSTATE_BIT) + | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) + | FEATURE_MASK(FEATURE_GFX_SS_BIT) + | FEATURE_MASK(FEATURE_VR0HOT_BIT) + | FEATURE_MASK(FEATURE_PPT_BIT) + | FEATURE_MASK(FEATURE_TDC_BIT) + | FEATURE_MASK(FEATURE_BACO_BIT) + | FEATURE_MASK(FEATURE_APCC_DFLL_BIT) + | FEATURE_MASK(FEATURE_FW_CTF_BIT) + | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) + | FEATURE_MASK(FEATURE_THERMAL_BIT) + | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT); + + if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) { + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_GPO_BIT); + } + + if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) + | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) + | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); + + if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT); + + if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT); + + if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); + + if (adev->pm.pp_feature & PP_ULV_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT); + + if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); + + if (adev->pm.pp_feature & PP_GFXOFF_MASK) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT); + + if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN || + smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG) + *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_PG_BIT); + + return 0; +} + +static int sienna_cichlid_check_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_7_powerplay_table *powerplay_table = + table_context->power_play_table; + struct smu_baco_context *smu_baco = &smu->smu_baco; + + mutex_lock(&smu_baco->mutex); + if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO || + powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) + smu_baco->platform_support = true; + mutex_unlock(&smu_baco->mutex); + + table_context->thermal_controller_type = + powerplay_table->thermal_controller_type; + + return 0; +} + +static int sienna_cichlid_append_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *smc_pptable = table_context->driver_pptable; + struct atom_smc_dpm_info_v4_9 *smc_dpm_table; + int index, ret; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + smc_dpm_info); + + ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, + (uint8_t **)&smc_dpm_table); + if (ret) + return ret; + + memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers, + sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); + + return 0; +} + +static int sienna_cichlid_store_powerplay_table(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_7_powerplay_table *powerplay_table = + table_context->power_play_table; + + memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, + sizeof(PPTable_t)); + + return 0; +} + +static int sienna_cichlid_setup_pptable(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v11_0_setup_pptable(smu); + if (ret) + return ret; + + ret = sienna_cichlid_store_powerplay_table(smu); + if (ret) + return ret; + + ret = sienna_cichlid_append_powerplay_table(smu); + if (ret) + return ret; + + ret = sienna_cichlid_check_powerplay_table(smu); + if (ret) + return ret; + + return ret; +} + +static int sienna_cichlid_tables_init(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, + sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err0_out; + smu_table->metrics_time = 0; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err1_out; + + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); + if (!smu_table->watermarks_table) + goto err2_out; + + return 0; + +err2_out: + kfree(smu_table->gpu_metrics_table); +err1_out: + kfree(smu_table->metrics_table); +err0_out: + return -ENOMEM; +} + +static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, + MetricsMember_t member, + uint32_t *value) +{ + struct smu_table_context *smu_table= &smu->smu_table; + SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; + int ret = 0; + + mutex_lock(&smu->metrics_lock); + + ret = smu_cmn_get_metrics_table_locked(smu, + NULL, + false); + if (ret) { + mutex_unlock(&smu->metrics_lock); + return ret; + } + + switch (member) { + case METRICS_CURR_GFXCLK: + *value = metrics->CurrClock[PPCLK_GFXCLK]; + break; + case METRICS_CURR_SOCCLK: + *value = metrics->CurrClock[PPCLK_SOCCLK]; + break; + case METRICS_CURR_UCLK: + *value = metrics->CurrClock[PPCLK_UCLK]; + break; + case METRICS_CURR_VCLK: + *value = metrics->CurrClock[PPCLK_VCLK_0]; + break; + case METRICS_CURR_VCLK1: + *value = metrics->CurrClock[PPCLK_VCLK_1]; + break; + case METRICS_CURR_DCLK: + *value = metrics->CurrClock[PPCLK_DCLK_0]; + break; + case METRICS_CURR_DCLK1: + *value = metrics->CurrClock[PPCLK_DCLK_1]; + break; + case METRICS_CURR_DCEFCLK: + *value = metrics->CurrClock[PPCLK_DCEFCLK]; + break; + case METRICS_AVERAGE_GFXCLK: + if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) + *value = metrics->AverageGfxclkFrequencyPostDs; + else + *value = metrics->AverageGfxclkFrequencyPreDs; + break; + case METRICS_AVERAGE_FCLK: + *value = metrics->AverageFclkFrequencyPostDs; + break; + case METRICS_AVERAGE_UCLK: + *value = metrics->AverageUclkFrequencyPostDs; + break; + case METRICS_AVERAGE_GFXACTIVITY: + *value = metrics->AverageGfxActivity; + break; + case METRICS_AVERAGE_MEMACTIVITY: + *value = metrics->AverageUclkActivity; + break; + case METRICS_AVERAGE_SOCKETPOWER: + *value = metrics->AverageSocketPower << 8; + break; + case METRICS_TEMPERATURE_EDGE: + *value = metrics->TemperatureEdge * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_HOTSPOT: + *value = metrics->TemperatureHotspot * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_MEM: + *value = metrics->TemperatureMem * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRGFX: + *value = metrics->TemperatureVrGfx * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_TEMPERATURE_VRSOC: + *value = metrics->TemperatureVrSoc * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + break; + case METRICS_THROTTLER_STATUS: + *value = metrics->ThrottlerStatus; + break; + case METRICS_CURR_FANSPEED: + *value = metrics->CurrFanSpeed; + break; + default: + *value = UINT_MAX; + break; + } + + mutex_unlock(&smu->metrics_lock); + + return ret; + +} + +static int sienna_cichlid_allocate_dpm_context(struct smu_context *smu) +{ + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), + GFP_KERNEL); + if (!smu_dpm->dpm_context) + return -ENOMEM; + + smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); + + return 0; +} + +static int sienna_cichlid_init_smc_tables(struct smu_context *smu) +{ + int ret = 0; + + ret = sienna_cichlid_tables_init(smu); + if (ret) + return ret; + + ret = sienna_cichlid_allocate_dpm_context(smu); + if (ret) + return ret; + + return smu_v11_0_init_smc_tables(smu); +} + +static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *driver_ppt = smu->smu_table.driver_pptable; + struct smu_11_0_dpm_table *dpm_table; + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + /* socclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.soc_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_SOCCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* gfxclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.gfx_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_GFXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* uclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.uclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_UCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* fclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.fclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_FCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* vclk0 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.vclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK_0].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* vclk1 dpm table setup */ + if (adev->vcn.num_vcn_inst > 1) { + dpm_table = &dpm_context->dpm_tables.vclk1_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_VCLK1, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_VCLK_1].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = + smu->smu_table.boot_values.vclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + } + + /* dclk0 dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dclk_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK_0].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* dclk1 dpm table setup */ + if (adev->vcn.num_vcn_inst > 1) { + dpm_table = &dpm_context->dpm_tables.dclk1_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCLK1, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCLK_1].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = + smu->smu_table.boot_values.dclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + } + + /* dcefclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.dcef_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DCEFCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* pixelclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.pixel_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PIXCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* displayclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.display_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_DISPCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + /* phyclk dpm table setup */ + dpm_table = &dpm_context->dpm_tables.phy_table; + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_set_single_dpm_table(smu, + SMU_PHYCLK, + dpm_table); + if (ret) + return ret; + dpm_table->is_fine_grained = + !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; + } else { + dpm_table->count = 1; + dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; + dpm_table->dpm_levels[0].enabled = true; + dpm_table->min = dpm_table->dpm_levels[0].value; + dpm_table->max = dpm_table->dpm_levels[0].value; + } + + return 0; +} + +static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enable) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if (enable) { + /* vcn dpm on is a prerequisite for vcn power gate messages */ + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); + if (ret) + return ret; + if (adev->asic_type == CHIP_SIENNA_CICHLID) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, + 0x10000, NULL); + if (ret) + return ret; + } + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); + if (ret) + return ret; + if (adev->asic_type == CHIP_SIENNA_CICHLID) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, + 0x10000, NULL); + if (ret) + return ret; + } + } + } + + return ret; +} + +static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); + if (ret) + return ret; + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); + if (ret) + return ret; + } + } + + return ret; +} + +static int sienna_cichlid_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + MetricsMember_t member_type; + int clk_id = 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + switch (clk_id) { + case PPCLK_GFXCLK: + member_type = METRICS_CURR_GFXCLK; + break; + case PPCLK_UCLK: + member_type = METRICS_CURR_UCLK; + break; + case PPCLK_SOCCLK: + member_type = METRICS_CURR_SOCCLK; + break; + case PPCLK_FCLK: + member_type = METRICS_CURR_FCLK; + break; + case PPCLK_VCLK_0: + member_type = METRICS_CURR_VCLK; + break; + case PPCLK_VCLK_1: + member_type = METRICS_CURR_VCLK1; + break; + case PPCLK_DCLK_0: + member_type = METRICS_CURR_DCLK; + break; + case PPCLK_DCLK_1: + member_type = METRICS_CURR_DCLK1; + break; + case PPCLK_DCEFCLK: + member_type = METRICS_CURR_DCEFCLK; + break; + default: + return -EINVAL; + } + + return sienna_cichlid_get_smu_metrics_data(smu, + member_type, + value); + +} + +static bool sienna_cichlid_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + DpmDescriptor_t *dpm_desc = NULL; + uint32_t clk_index = 0; + + clk_index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + dpm_desc = &pptable->DpmDescriptor[clk_index]; + + /* 0 - Fine grained DPM, 1 - Discrete DPM */ + return dpm_desc->SnapToDiscrete == 0 ? true : false; +} + +static int sienna_cichlid_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) +{ + struct amdgpu_device *adev = smu->adev; + struct smu_table_context *table_context = &smu->smu_table; + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; + PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; + int i, size = 0, ret = 0; + uint32_t cur_value = 0, value = 0, count = 0; + uint32_t freq_values[3] = {0}; + uint32_t mark_index = 0; + uint32_t gen_speed, lane_width; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_FCLK: + case SMU_DCEFCLK: + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, clk_type, &cur_value); + if (ret) + goto print_clk_out; + + /* no need to disable gfxoff when retrieving the current gfxclk */ + if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) + amdgpu_gfx_off_ctrl(adev, false); + + ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); + if (ret) + goto print_clk_out; + + if (!sienna_cichlid_is_support_fine_grained_dpm(smu, clk_type)) { + for (i = 0; i < count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); + if (ret) + goto print_clk_out; + + size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, + cur_value == value ? "*" : ""); + } + } else { + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); + if (ret) + goto print_clk_out; + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); + if (ret) + goto print_clk_out; + + freq_values[1] = cur_value; + mark_index = cur_value == freq_values[0] ? 0 : + cur_value == freq_values[2] ? 2 : 1; + if (mark_index != 1) + freq_values[1] = (freq_values[0] + freq_values[2]) / 2; + + for (i = 0; i < 3; i++) { + size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i], + i == mark_index ? "*" : ""); + } + + } + break; + case SMU_PCIE: + gen_speed = smu_v11_0_get_current_pcie_link_speed(smu); + lane_width = smu_v11_0_get_current_pcie_link_width(smu); + for (i = 0; i < NUM_LINK_LEVELS; i++) + size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," : + (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "", + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" : + (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "", + pptable->LclkFreq[i], + (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) && + (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ? + "*" : ""); + break; + default: + break; + } + +print_clk_out: + if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) + amdgpu_gfx_off_ctrl(adev, true); + + return size; +} + +static int sienna_cichlid_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, uint32_t mask) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0, size = 0; + uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) + amdgpu_gfx_off_ctrl(adev, false); + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + case SMU_SOCCLK: + case SMU_MCLK: + case SMU_UCLK: + case SMU_DCEFCLK: + case SMU_FCLK: + /* There is only 2 levels for fine grained DPM */ + if (sienna_cichlid_is_support_fine_grained_dpm(smu, clk_type)) { + soft_max_level = (soft_max_level >= 1 ? 1 : 0); + soft_min_level = (soft_min_level >= 1 ? 1 : 0); + } + + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); + if (ret) + goto forec_level_out; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); + if (ret) + goto forec_level_out; + + ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); + if (ret) + goto forec_level_out; + break; + default: + break; + } + +forec_level_out: + if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) + amdgpu_gfx_off_ctrl(adev, true); + + return size; +} + +static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu) +{ + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + + pstate_table->gfxclk_pstate.min = gfx_table->min; + pstate_table->gfxclk_pstate.peak = gfx_table->max; + + pstate_table->uclk_pstate.min = mem_table->min; + pstate_table->uclk_pstate.peak = mem_table->max; + + pstate_table->socclk_pstate.min = soc_table->min; + pstate_table->socclk_pstate.peak = soc_table->max; + + return 0; +} + +static int sienna_cichlid_pre_display_config_changed(struct smu_context *smu) +{ + int ret = 0; + uint32_t max_freq = 0; + + /* Sienna_Cichlid do not support to change display num currently */ + return 0; +#if 0 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); + if (ret) + return ret; +#endif + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); + if (ret) + return ret; + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); + if (ret) + return ret; + } + + return ret; +} + +static int sienna_cichlid_display_config_changed(struct smu_context *smu) +{ + int ret = 0; + + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && + smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { +#if 0 + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, + smu->display_config->num_display, + NULL); +#endif + if (ret) + return ret; + } + + return ret; +} + +static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value) +{ + if (!value) + return -EINVAL; + + return sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_SOCKETPOWER, + value); +} + +static int sienna_cichlid_get_current_activity_percent(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_GFXACTIVITY, + value); + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_AVERAGE_MEMACTIVITY, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); + return -EINVAL; + } + + return ret; +} + +static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) +{ + int ret = 0; + uint32_t feature_mask[2]; + unsigned long feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | + ((uint64_t)feature_mask[1] << 32)); + return !!(feature_enabled & SMC_DPM_FEATURE); +} + +static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + if (!speed) + return -EINVAL; + + return sienna_cichlid_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); +} + +static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, + uint32_t *speed) +{ + int ret = 0; + uint32_t percent = 0; + uint32_t current_rpm; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + ret = sienna_cichlid_get_fan_speed_rpm(smu, ¤t_rpm); + if (ret) + return ret; + + percent = current_rpm * 100 / pptable->FanMaximumRpm; + *speed = percent > 100 ? 100 : percent; + + return ret; +} + +static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *buf) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + uint32_t i, size = 0; + int16_t workload_type = 0; + static const char *profile_name[] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + static const char *title[] = { + "PROFILE_INDEX(NAME)", + "CLOCK_TYPE(NAME)", + "FPS", + "MinFreqType", + "MinActiveFreqType", + "MinActiveFreq", + "BoosterFreqType", + "BoosterFreq", + "PD_Data_limit_c", + "PD_Data_error_coeff", + "PD_Data_error_rate_coeff"}; + int result = 0; + + if (!buf) + return -EINVAL; + + size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", + title[0], title[1], title[2], title[3], title[4], title[5], + title[6], title[7], title[8], title[9], title[10]); + + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type < 0) + return -EINVAL; + + result = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, + (void *)(&activity_monitor), false); + if (result) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return result; + } + + size += sprintf(buf + size, "%2d %14s%s:\n", + i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 0, + "GFXCLK", + activity_monitor.Gfx_FPS, + activity_monitor.Gfx_MinFreqStep, + activity_monitor.Gfx_MinActiveFreqType, + activity_monitor.Gfx_MinActiveFreq, + activity_monitor.Gfx_BoosterFreqType, + activity_monitor.Gfx_BoosterFreq, + activity_monitor.Gfx_PD_Data_limit_c, + activity_monitor.Gfx_PD_Data_error_coeff, + activity_monitor.Gfx_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 1, + "SOCCLK", + activity_monitor.Fclk_FPS, + activity_monitor.Fclk_MinFreqStep, + activity_monitor.Fclk_MinActiveFreqType, + activity_monitor.Fclk_MinActiveFreq, + activity_monitor.Fclk_BoosterFreqType, + activity_monitor.Fclk_BoosterFreq, + activity_monitor.Fclk_PD_Data_limit_c, + activity_monitor.Fclk_PD_Data_error_coeff, + activity_monitor.Fclk_PD_Data_error_rate_coeff); + + size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", + " ", + 2, + "MEMLK", + activity_monitor.Mem_FPS, + activity_monitor.Mem_MinFreqStep, + activity_monitor.Mem_MinActiveFreqType, + activity_monitor.Mem_MinActiveFreq, + activity_monitor.Mem_BoosterFreqType, + activity_monitor.Mem_BoosterFreq, + activity_monitor.Mem_PD_Data_limit_c, + activity_monitor.Mem_PD_Data_error_coeff, + activity_monitor.Mem_PD_Data_error_rate_coeff); + } + + return size; +} + +static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) +{ + DpmActivityMonitorCoeffInt_t activity_monitor; + int workload_type, ret = 0; + + smu->power_profile_mode = input[size]; + + if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); + return -EINVAL; + } + + if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), false); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); + return ret; + } + + switch (input[0]) { + case 0: /* Gfxclk */ + activity_monitor.Gfx_FPS = input[1]; + activity_monitor.Gfx_MinFreqStep = input[2]; + activity_monitor.Gfx_MinActiveFreqType = input[3]; + activity_monitor.Gfx_MinActiveFreq = input[4]; + activity_monitor.Gfx_BoosterFreqType = input[5]; + activity_monitor.Gfx_BoosterFreq = input[6]; + activity_monitor.Gfx_PD_Data_limit_c = input[7]; + activity_monitor.Gfx_PD_Data_error_coeff = input[8]; + activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; + break; + case 1: /* Socclk */ + activity_monitor.Fclk_FPS = input[1]; + activity_monitor.Fclk_MinFreqStep = input[2]; + activity_monitor.Fclk_MinActiveFreqType = input[3]; + activity_monitor.Fclk_MinActiveFreq = input[4]; + activity_monitor.Fclk_BoosterFreqType = input[5]; + activity_monitor.Fclk_BoosterFreq = input[6]; + activity_monitor.Fclk_PD_Data_limit_c = input[7]; + activity_monitor.Fclk_PD_Data_error_coeff = input[8]; + activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; + break; + case 2: /* Memlk */ + activity_monitor.Mem_FPS = input[1]; + activity_monitor.Mem_MinFreqStep = input[2]; + activity_monitor.Mem_MinActiveFreqType = input[3]; + activity_monitor.Mem_MinActiveFreq = input[4]; + activity_monitor.Mem_BoosterFreqType = input[5]; + activity_monitor.Mem_BoosterFreq = input[6]; + activity_monitor.Mem_PD_Data_limit_c = input[7]; + activity_monitor.Mem_PD_Data_error_coeff = input[8]; + activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; + break; + } + + ret = smu_cmn_update_table(smu, + SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, + (void *)(&activity_monitor), true); + if (ret) { + dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); + return ret; + } + } + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + smu->power_profile_mode); + if (workload_type < 0) + return -EINVAL; + smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, + 1 << workload_type, NULL); + + return ret; +} + +static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) +{ + struct smu_clocks min_clocks = {0}; + struct pp_display_clock_request clock_req; + int ret = 0; + + min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; + min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; + min_clocks.memory_clock = smu->display_config->min_mem_set_clock; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + clock_req.clock_type = amd_pp_dcef_clock; + clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; + + ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); + if (!ret) { + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMinDeepSleepDcefclk, + min_clocks.dcef_clock_in_sr/100, + NULL); + if (ret) { + dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!"); + return ret; + } + } + } else { + dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!"); + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); + if (ret) { + dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); + return ret; + } + } + + return 0; +} + +static int sienna_cichlid_set_watermarks_table(struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 + *clock_ranges) +{ + Watermarks_t *table = smu->smu_table.watermarks_table; + int ret = 0; + int i; + + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; + + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[1][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[1][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } + + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[0][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MinUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].MaxUclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / + 1000)); + table->WatermarkRow[0][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } + + smu->watermarks_bitmap |= WATERMARKS_EXIST; + } + + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + ret = smu_cmn_write_watermarks_table(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to update WMTABLE!"); + return ret; + } + smu->watermarks_bitmap |= WATERMARKS_LOADED; + } + + return 0; +} + +static int sienna_cichlid_thermal_get_temperature(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + + if (!value) + return -EINVAL; + + switch (sensor) { + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_HOTSPOT, + value); + break; + case AMDGPU_PP_SENSOR_EDGE_TEMP: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_EDGE, + value); + break; + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = sienna_cichlid_get_smu_metrics_data(smu, + METRICS_TEMPERATURE_MEM, + value); + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); + return -EINVAL; + } + + return ret; +} + +static int sienna_cichlid_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + + if(!data || !size) + return -EINVAL; + + mutex_lock(&smu->sensor_lock); + switch (sensor) { + case AMDGPU_PP_SENSOR_MAX_FAN_RPM: + *(uint32_t *)data = pptable->FanMaximumRpm; + *size = 4; + break; + case AMDGPU_PP_SENSOR_MEM_LOAD: + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = sienna_cichlid_get_current_activity_percent(smu, sensor, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = sienna_cichlid_get_gpu_power(smu, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: + case AMDGPU_PP_SENSOR_EDGE_TEMP: + case AMDGPU_PP_SENSOR_MEM_TEMP: + ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + mutex_unlock(&smu->sensor_lock); + + return ret; +} + +static int sienna_cichlid_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states) +{ + uint32_t num_discrete_levels = 0; + uint16_t *dpm_levels = NULL; + uint16_t i = 0; + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *driver_ppt = NULL; + + if (!clocks_in_khz || !num_states || !table_context->driver_pptable) + return -EINVAL; + + driver_ppt = table_context->driver_pptable; + num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; + dpm_levels = driver_ppt->FreqTableUclk; + + if (num_discrete_levels == 0 || dpm_levels == NULL) + return -EINVAL; + + *num_states = num_discrete_levels; + for (i = 0; i < num_discrete_levels; i++) { + /* convert to khz */ + *clocks_in_khz = (*dpm_levels) * 1000; + clocks_in_khz++; + dpm_levels++; + } + + return 0; +} + +static int sienna_cichlid_get_thermal_temperature_range(struct smu_context *smu, + struct smu_temperature_range *range) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_7_powerplay_table *powerplay_table = + table_context->power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + + if (!range) + return -EINVAL; + + memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); + + range->max = pptable->TemperatureLimit[TEMP_EDGE] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->edge_emergency_max = (pptable->TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_crit_max = pptable->TemperatureLimit[TEMP_HOTSPOT] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->hotspot_emergency_max = (pptable->TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_crit_max = pptable->TemperatureLimit[TEMP_MEM] * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->mem_emergency_max = (pptable->TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + range->software_shutdown_temp = powerplay_table->software_shutdown_temp; + + return 0; +} + +static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context *smu, + bool disable_memory_clock_switch) +{ + int ret = 0; + struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = + (struct smu_11_0_max_sustainable_clocks *) + smu->smu_table.max_sustainable_clocks; + uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal; + uint32_t max_memory_clock = max_sustainable_clocks->uclock; + + if(smu->disable_uclk_switch == disable_memory_clock_switch) + return 0; + + if(disable_memory_clock_switch) + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); + else + ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); + + if(!ret) + smu->disable_uclk_switch = disable_memory_clock_switch; + + return ret; +} + +static int sienna_cichlid_get_power_limit(struct smu_context *smu) +{ + struct smu_11_0_7_powerplay_table *powerplay_table = + (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table; + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t power_limit, od_percent; + + if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { + /* the last hope to figure out the ppt limit */ + if (!pptable) { + dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); + return -EINVAL; + } + power_limit = + pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; + } + smu->current_power_limit = power_limit; + + if (smu->od_enabled) { + od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); + + dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); + + power_limit *= (100 + od_percent); + power_limit /= 100; + } + smu->max_power_limit = power_limit; + + return 0; +} + +static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, + uint32_t pcie_gen_cap, + uint32_t pcie_width_cap) +{ + struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; + PPTable_t *pptable = smu->smu_table.driver_pptable; + uint32_t smu_pcie_arg; + int ret, i; + + /* lclk dpm table setup */ + for (i = 0; i < MAX_PCIE_CONF; i++) { + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; + } + + for (i = 0; i < NUM_LINK_LEVELS; i++) { + smu_pcie_arg = (i << 16) | + ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? + (pptable->PcieGenSpeed[i] << 8) : + (pcie_gen_cap << 8)) | + ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? + pptable->PcieLaneCount[i] : + pcie_width_cap); + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_OverridePcieParameters, + smu_pcie_arg, + NULL); + + if (ret) + return ret; + + if (pptable->PcieGenSpeed[i] > pcie_gen_cap) + dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap; + if (pptable->PcieLaneCount[i] > pcie_width_cap) + dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap; + } + + return 0; +} + +static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, uint32_t *max) +{ + struct amdgpu_device *adev = smu->adev; + int ret; + + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, false); + ret = smu_v11_0_get_dpm_ultimate_freq(smu, clk_type, min, max); + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, true); + + return ret; +} + +static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + + if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) + return false; + + val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); + return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; +} + +static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t val; + u32 smu_version; + + /** + * SRIOV env will not support SMU mode1 reset + * PM FW support mode1 reset from 58.26 + */ + smu_cmn_get_smc_version(smu, NULL, &smu_version); + if (amdgpu_sriov_vf(adev) || (smu_version < 0x003a1a00)) + return false; + + /** + * mode1 reset relies on PSP, so we should check if + * PSP is alive. + */ + val = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); + return val != 0x0; +} + +static void sienna_cichlid_dump_pptable(struct smu_context *smu) +{ + struct smu_table_context *table_context = &smu->smu_table; + PPTable_t *pptable = table_context->driver_pptable; + int i; + + dev_info(smu->adev->dev, "Dumped PPTable:\n"); + + dev_info(smu->adev->dev, "Version = 0x%08x\n", pptable->Version); + dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); + dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); + + for (i = 0; i < PPT_THROTTLER_COUNT; i++) { + dev_info(smu->adev->dev, "SocketPowerLimitAc[%d] = 0x%x\n", i, pptable->SocketPowerLimitAc[i]); + dev_info(smu->adev->dev, "SocketPowerLimitAcTau[%d] = 0x%x\n", i, pptable->SocketPowerLimitAcTau[i]); + dev_info(smu->adev->dev, "SocketPowerLimitDc[%d] = 0x%x\n", i, pptable->SocketPowerLimitDc[i]); + dev_info(smu->adev->dev, "SocketPowerLimitDcTau[%d] = 0x%x\n", i, pptable->SocketPowerLimitDcTau[i]); + } + + for (i = 0; i < TDC_THROTTLER_COUNT; i++) { + dev_info(smu->adev->dev, "TdcLimit[%d] = 0x%x\n", i, pptable->TdcLimit[i]); + dev_info(smu->adev->dev, "TdcLimitTau[%d] = 0x%x\n", i, pptable->TdcLimitTau[i]); + } + + for (i = 0; i < TEMP_COUNT; i++) { + dev_info(smu->adev->dev, "TemperatureLimit[%d] = 0x%x\n", i, pptable->TemperatureLimit[i]); + } + + dev_info(smu->adev->dev, "FitLimit = 0x%x\n", pptable->FitLimit); + dev_info(smu->adev->dev, "TotalPowerConfig = 0x%x\n", pptable->TotalPowerConfig); + dev_info(smu->adev->dev, "TotalPowerPadding[0] = 0x%x\n", pptable->TotalPowerPadding[0]); + dev_info(smu->adev->dev, "TotalPowerPadding[1] = 0x%x\n", pptable->TotalPowerPadding[1]); + dev_info(smu->adev->dev, "TotalPowerPadding[2] = 0x%x\n", pptable->TotalPowerPadding[2]); + + dev_info(smu->adev->dev, "ApccPlusResidencyLimit = 0x%x\n", pptable->ApccPlusResidencyLimit); + for (i = 0; i < NUM_SMNCLK_DPM_LEVELS; i++) { + dev_info(smu->adev->dev, "SmnclkDpmFreq[%d] = 0x%x\n", i, pptable->SmnclkDpmFreq[i]); + dev_info(smu->adev->dev, "SmnclkDpmVoltage[%d] = 0x%x\n", i, pptable->SmnclkDpmVoltage[i]); + } + dev_info(smu->adev->dev, "PaddingAPCC[0] = 0x%x\n", pptable->PaddingAPCC[0]); + dev_info(smu->adev->dev, "PaddingAPCC[1] = 0x%x\n", pptable->PaddingAPCC[1]); + dev_info(smu->adev->dev, "PaddingAPCC[2] = 0x%x\n", pptable->PaddingAPCC[2]); + dev_info(smu->adev->dev, "PaddingAPCC[3] = 0x%x\n", pptable->PaddingAPCC[3]); + + dev_info(smu->adev->dev, "ThrottlerControlMask = 0x%x\n", pptable->ThrottlerControlMask); + + dev_info(smu->adev->dev, "FwDStateMask = 0x%x\n", pptable->FwDStateMask); + + dev_info(smu->adev->dev, "UlvVoltageOffsetSoc = 0x%x\n", pptable->UlvVoltageOffsetSoc); + dev_info(smu->adev->dev, "UlvVoltageOffsetGfx = 0x%x\n", pptable->UlvVoltageOffsetGfx); + dev_info(smu->adev->dev, "MinVoltageUlvGfx = 0x%x\n", pptable->MinVoltageUlvGfx); + dev_info(smu->adev->dev, "MinVoltageUlvSoc = 0x%x\n", pptable->MinVoltageUlvSoc); + + dev_info(smu->adev->dev, "SocLIVmin = 0x%x\n", pptable->SocLIVmin); + dev_info(smu->adev->dev, "PaddingLIVmin = 0x%x\n", pptable->PaddingLIVmin); + + dev_info(smu->adev->dev, "GceaLinkMgrIdleThreshold = 0x%x\n", pptable->GceaLinkMgrIdleThreshold); + dev_info(smu->adev->dev, "paddingRlcUlvParams[0] = 0x%x\n", pptable->paddingRlcUlvParams[0]); + dev_info(smu->adev->dev, "paddingRlcUlvParams[1] = 0x%x\n", pptable->paddingRlcUlvParams[1]); + dev_info(smu->adev->dev, "paddingRlcUlvParams[2] = 0x%x\n", pptable->paddingRlcUlvParams[2]); + + dev_info(smu->adev->dev, "MinVoltageGfx = 0x%x\n", pptable->MinVoltageGfx); + dev_info(smu->adev->dev, "MinVoltageSoc = 0x%x\n", pptable->MinVoltageSoc); + dev_info(smu->adev->dev, "MaxVoltageGfx = 0x%x\n", pptable->MaxVoltageGfx); + dev_info(smu->adev->dev, "MaxVoltageSoc = 0x%x\n", pptable->MaxVoltageSoc); + + dev_info(smu->adev->dev, "LoadLineResistanceGfx = 0x%x\n", pptable->LoadLineResistanceGfx); + dev_info(smu->adev->dev, "LoadLineResistanceSoc = 0x%x\n", pptable->LoadLineResistanceSoc); + + dev_info(smu->adev->dev, "VDDGFX_TVmin = 0x%x\n", pptable->VDDGFX_TVmin); + dev_info(smu->adev->dev, "VDDSOC_TVmin = 0x%x\n", pptable->VDDSOC_TVmin); + dev_info(smu->adev->dev, "VDDGFX_Vmin_HiTemp = 0x%x\n", pptable->VDDGFX_Vmin_HiTemp); + dev_info(smu->adev->dev, "VDDGFX_Vmin_LoTemp = 0x%x\n", pptable->VDDGFX_Vmin_LoTemp); + dev_info(smu->adev->dev, "VDDSOC_Vmin_HiTemp = 0x%x\n", pptable->VDDSOC_Vmin_HiTemp); + dev_info(smu->adev->dev, "VDDSOC_Vmin_LoTemp = 0x%x\n", pptable->VDDSOC_Vmin_LoTemp); + dev_info(smu->adev->dev, "VDDGFX_TVminHystersis = 0x%x\n", pptable->VDDGFX_TVminHystersis); + dev_info(smu->adev->dev, "VDDSOC_TVminHystersis = 0x%x\n", pptable->VDDSOC_TVminHystersis); + + dev_info(smu->adev->dev, "[PPCLK_GFXCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_GFXCLK].Padding, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_GFXCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_GFXCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_SOCCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_SOCCLK].Padding, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_SOCCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_SOCCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_UCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_UCLK].Padding, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_UCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_UCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_FCLK]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, + pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_FCLK].Padding, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, + pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c, + pptable->DpmDescriptor[PPCLK_FCLK].SsFmin, + pptable->DpmDescriptor[PPCLK_FCLK].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_DCLK_0]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_DCLK_0].VoltageMode, + pptable->DpmDescriptor[PPCLK_DCLK_0].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DCLK_0].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DCLK_0].Padding, + pptable->DpmDescriptor[PPCLK_DCLK_0].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DCLK_0].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.c, + pptable->DpmDescriptor[PPCLK_DCLK_0].SsFmin, + pptable->DpmDescriptor[PPCLK_DCLK_0].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_VCLK_0]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_VCLK_0].VoltageMode, + pptable->DpmDescriptor[PPCLK_VCLK_0].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_VCLK_0].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_VCLK_0].Padding, + pptable->DpmDescriptor[PPCLK_VCLK_0].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_VCLK_0].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.a, + pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.b, + pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.c, + pptable->DpmDescriptor[PPCLK_VCLK_0].SsFmin, + pptable->DpmDescriptor[PPCLK_VCLK_0].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_DCLK_1]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_DCLK_1].VoltageMode, + pptable->DpmDescriptor[PPCLK_DCLK_1].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_DCLK_1].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_DCLK_1].Padding, + pptable->DpmDescriptor[PPCLK_DCLK_1].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_DCLK_1].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.a, + pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.b, + pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.c, + pptable->DpmDescriptor[PPCLK_DCLK_1].SsFmin, + pptable->DpmDescriptor[PPCLK_DCLK_1].Padding16); + + dev_info(smu->adev->dev, "[PPCLK_VCLK_1]\n" + " .VoltageMode = 0x%02x\n" + " .SnapToDiscrete = 0x%02x\n" + " .NumDiscreteLevels = 0x%02x\n" + " .padding = 0x%02x\n" + " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" + " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" + " .SsFmin = 0x%04x\n" + " .Padding_16 = 0x%04x\n", + pptable->DpmDescriptor[PPCLK_VCLK_1].VoltageMode, + pptable->DpmDescriptor[PPCLK_VCLK_1].SnapToDiscrete, + pptable->DpmDescriptor[PPCLK_VCLK_1].NumDiscreteLevels, + pptable->DpmDescriptor[PPCLK_VCLK_1].Padding, + pptable->DpmDescriptor[PPCLK_VCLK_1].ConversionToAvfsClk.m, + pptable->DpmDescriptor[PPCLK_VCLK_1].ConversionToAvfsClk.b, + pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.a, + pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.b, + pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.c, + pptable->DpmDescriptor[PPCLK_VCLK_1].SsFmin, + pptable->DpmDescriptor[PPCLK_VCLK_1].Padding16); + + dev_info(smu->adev->dev, "FreqTableGfx\n"); + for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableGfx[i]); + + dev_info(smu->adev->dev, "FreqTableVclk\n"); + for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableVclk[i]); + + dev_info(smu->adev->dev, "FreqTableDclk\n"); + for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableDclk[i]); + + dev_info(smu->adev->dev, "FreqTableSocclk\n"); + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableSocclk[i]); + + dev_info(smu->adev->dev, "FreqTableUclk\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableUclk[i]); + + dev_info(smu->adev->dev, "FreqTableFclk\n"); + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableFclk[i]); + + dev_info(smu->adev->dev, "Paddingclks[0] = 0x%x\n", pptable->Paddingclks[0]); + dev_info(smu->adev->dev, "Paddingclks[1] = 0x%x\n", pptable->Paddingclks[1]); + dev_info(smu->adev->dev, "Paddingclks[2] = 0x%x\n", pptable->Paddingclks[2]); + dev_info(smu->adev->dev, "Paddingclks[3] = 0x%x\n", pptable->Paddingclks[3]); + dev_info(smu->adev->dev, "Paddingclks[4] = 0x%x\n", pptable->Paddingclks[4]); + dev_info(smu->adev->dev, "Paddingclks[5] = 0x%x\n", pptable->Paddingclks[5]); + dev_info(smu->adev->dev, "Paddingclks[6] = 0x%x\n", pptable->Paddingclks[6]); + dev_info(smu->adev->dev, "Paddingclks[7] = 0x%x\n", pptable->Paddingclks[7]); + dev_info(smu->adev->dev, "Paddingclks[8] = 0x%x\n", pptable->Paddingclks[8]); + dev_info(smu->adev->dev, "Paddingclks[9] = 0x%x\n", pptable->Paddingclks[9]); + dev_info(smu->adev->dev, "Paddingclks[10] = 0x%x\n", pptable->Paddingclks[10]); + dev_info(smu->adev->dev, "Paddingclks[11] = 0x%x\n", pptable->Paddingclks[11]); + dev_info(smu->adev->dev, "Paddingclks[12] = 0x%x\n", pptable->Paddingclks[12]); + dev_info(smu->adev->dev, "Paddingclks[13] = 0x%x\n", pptable->Paddingclks[13]); + dev_info(smu->adev->dev, "Paddingclks[14] = 0x%x\n", pptable->Paddingclks[14]); + dev_info(smu->adev->dev, "Paddingclks[15] = 0x%x\n", pptable->Paddingclks[15]); + + dev_info(smu->adev->dev, "DcModeMaxFreq\n"); + dev_info(smu->adev->dev, " .PPCLK_GFXCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]); + dev_info(smu->adev->dev, " .PPCLK_SOCCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]); + dev_info(smu->adev->dev, " .PPCLK_UCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_UCLK]); + dev_info(smu->adev->dev, " .PPCLK_FCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_FCLK]); + dev_info(smu->adev->dev, " .PPCLK_DCLK_0 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_DCLK_0]); + dev_info(smu->adev->dev, " .PPCLK_VCLK_0 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_VCLK_0]); + dev_info(smu->adev->dev, " .PPCLK_DCLK_1 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_DCLK_1]); + dev_info(smu->adev->dev, " .PPCLK_VCLK_1 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_VCLK_1]); + + dev_info(smu->adev->dev, "FreqTableUclkDiv\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FreqTableUclkDiv[i]); + + dev_info(smu->adev->dev, "FclkBoostFreq = 0x%x\n", pptable->FclkBoostFreq); + dev_info(smu->adev->dev, "FclkParamPadding = 0x%x\n", pptable->FclkParamPadding); + + dev_info(smu->adev->dev, "Mp0clkFreq\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->Mp0clkFreq[i]); + + dev_info(smu->adev->dev, "Mp0DpmVoltage\n"); + for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->Mp0DpmVoltage[i]); + + dev_info(smu->adev->dev, "MemVddciVoltage\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->MemVddciVoltage[i]); + + dev_info(smu->adev->dev, "MemMvddVoltage\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->MemMvddVoltage[i]); + + dev_info(smu->adev->dev, "GfxclkFgfxoffEntry = 0x%x\n", pptable->GfxclkFgfxoffEntry); + dev_info(smu->adev->dev, "GfxclkFinit = 0x%x\n", pptable->GfxclkFinit); + dev_info(smu->adev->dev, "GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); + dev_info(smu->adev->dev, "GfxclkSource = 0x%x\n", pptable->GfxclkSource); + dev_info(smu->adev->dev, "GfxclkPadding = 0x%x\n", pptable->GfxclkPadding); + + dev_info(smu->adev->dev, "GfxGpoSubFeatureMask = 0x%x\n", pptable->GfxGpoSubFeatureMask); + + dev_info(smu->adev->dev, "GfxGpoEnabledWorkPolicyMask = 0x%x\n", pptable->GfxGpoEnabledWorkPolicyMask); + dev_info(smu->adev->dev, "GfxGpoDisabledWorkPolicyMask = 0x%x\n", pptable->GfxGpoDisabledWorkPolicyMask); + dev_info(smu->adev->dev, "GfxGpoPadding[0] = 0x%x\n", pptable->GfxGpoPadding[0]); + dev_info(smu->adev->dev, "GfxGpoVotingAllow = 0x%x\n", pptable->GfxGpoVotingAllow); + dev_info(smu->adev->dev, "GfxGpoPadding32[0] = 0x%x\n", pptable->GfxGpoPadding32[0]); + dev_info(smu->adev->dev, "GfxGpoPadding32[1] = 0x%x\n", pptable->GfxGpoPadding32[1]); + dev_info(smu->adev->dev, "GfxGpoPadding32[2] = 0x%x\n", pptable->GfxGpoPadding32[2]); + dev_info(smu->adev->dev, "GfxGpoPadding32[3] = 0x%x\n", pptable->GfxGpoPadding32[3]); + dev_info(smu->adev->dev, "GfxDcsFopt = 0x%x\n", pptable->GfxDcsFopt); + dev_info(smu->adev->dev, "GfxDcsFclkFopt = 0x%x\n", pptable->GfxDcsFclkFopt); + dev_info(smu->adev->dev, "GfxDcsUclkFopt = 0x%x\n", pptable->GfxDcsUclkFopt); + + dev_info(smu->adev->dev, "DcsGfxOffVoltage = 0x%x\n", pptable->DcsGfxOffVoltage); + dev_info(smu->adev->dev, "DcsMinGfxOffTime = 0x%x\n", pptable->DcsMinGfxOffTime); + dev_info(smu->adev->dev, "DcsMaxGfxOffTime = 0x%x\n", pptable->DcsMaxGfxOffTime); + dev_info(smu->adev->dev, "DcsMinCreditAccum = 0x%x\n", pptable->DcsMinCreditAccum); + dev_info(smu->adev->dev, "DcsExitHysteresis = 0x%x\n", pptable->DcsExitHysteresis); + dev_info(smu->adev->dev, "DcsTimeout = 0x%x\n", pptable->DcsTimeout); + + dev_info(smu->adev->dev, "DcsParamPadding[0] = 0x%x\n", pptable->DcsParamPadding[0]); + dev_info(smu->adev->dev, "DcsParamPadding[1] = 0x%x\n", pptable->DcsParamPadding[1]); + dev_info(smu->adev->dev, "DcsParamPadding[2] = 0x%x\n", pptable->DcsParamPadding[2]); + dev_info(smu->adev->dev, "DcsParamPadding[3] = 0x%x\n", pptable->DcsParamPadding[3]); + dev_info(smu->adev->dev, "DcsParamPadding[4] = 0x%x\n", pptable->DcsParamPadding[4]); + + dev_info(smu->adev->dev, "FlopsPerByteTable\n"); + for (i = 0; i < RLC_PACE_TABLE_NUM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FlopsPerByteTable[i]); + + dev_info(smu->adev->dev, "LowestUclkReservedForUlv = 0x%x\n", pptable->LowestUclkReservedForUlv); + dev_info(smu->adev->dev, "vddingMem[0] = 0x%x\n", pptable->PaddingMem[0]); + dev_info(smu->adev->dev, "vddingMem[1] = 0x%x\n", pptable->PaddingMem[1]); + dev_info(smu->adev->dev, "vddingMem[2] = 0x%x\n", pptable->PaddingMem[2]); + + dev_info(smu->adev->dev, "UclkDpmPstates\n"); + for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->UclkDpmPstates[i]); + + dev_info(smu->adev->dev, "UclkDpmSrcFreqRange\n"); + dev_info(smu->adev->dev, " .Fmin = 0x%x\n", + pptable->UclkDpmSrcFreqRange.Fmin); + dev_info(smu->adev->dev, " .Fmax = 0x%x\n", + pptable->UclkDpmSrcFreqRange.Fmax); + dev_info(smu->adev->dev, "UclkDpmTargFreqRange\n"); + dev_info(smu->adev->dev, " .Fmin = 0x%x\n", + pptable->UclkDpmTargFreqRange.Fmin); + dev_info(smu->adev->dev, " .Fmax = 0x%x\n", + pptable->UclkDpmTargFreqRange.Fmax); + dev_info(smu->adev->dev, "UclkDpmMidstepFreq = 0x%x\n", pptable->UclkDpmMidstepFreq); + dev_info(smu->adev->dev, "UclkMidstepPadding = 0x%x\n", pptable->UclkMidstepPadding); + + dev_info(smu->adev->dev, "PcieGenSpeed\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->PcieGenSpeed[i]); + + dev_info(smu->adev->dev, "PcieLaneCount\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->PcieLaneCount[i]); + + dev_info(smu->adev->dev, "LclkFreq\n"); + for (i = 0; i < NUM_LINK_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->LclkFreq[i]); + + dev_info(smu->adev->dev, "FanStopTemp = 0x%x\n", pptable->FanStopTemp); + dev_info(smu->adev->dev, "FanStartTemp = 0x%x\n", pptable->FanStartTemp); + + dev_info(smu->adev->dev, "FanGain\n"); + for (i = 0; i < TEMP_COUNT; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FanGain[i]); + + dev_info(smu->adev->dev, "FanPwmMin = 0x%x\n", pptable->FanPwmMin); + dev_info(smu->adev->dev, "FanAcousticLimitRpm = 0x%x\n", pptable->FanAcousticLimitRpm); + dev_info(smu->adev->dev, "FanThrottlingRpm = 0x%x\n", pptable->FanThrottlingRpm); + dev_info(smu->adev->dev, "FanMaximumRpm = 0x%x\n", pptable->FanMaximumRpm); + dev_info(smu->adev->dev, "MGpuFanBoostLimitRpm = 0x%x\n", pptable->MGpuFanBoostLimitRpm); + dev_info(smu->adev->dev, "FanTargetTemperature = 0x%x\n", pptable->FanTargetTemperature); + dev_info(smu->adev->dev, "FanTargetGfxclk = 0x%x\n", pptable->FanTargetGfxclk); + dev_info(smu->adev->dev, "FanPadding16 = 0x%x\n", pptable->FanPadding16); + dev_info(smu->adev->dev, "FanTempInputSelect = 0x%x\n", pptable->FanTempInputSelect); + dev_info(smu->adev->dev, "FanPadding = 0x%x\n", pptable->FanPadding); + dev_info(smu->adev->dev, "FanZeroRpmEnable = 0x%x\n", pptable->FanZeroRpmEnable); + dev_info(smu->adev->dev, "FanTachEdgePerRev = 0x%x\n", pptable->FanTachEdgePerRev); + + dev_info(smu->adev->dev, "FuzzyFan_ErrorSetDelta = 0x%x\n", pptable->FuzzyFan_ErrorSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_ErrorRateSetDelta = 0x%x\n", pptable->FuzzyFan_ErrorRateSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_PwmSetDelta = 0x%x\n", pptable->FuzzyFan_PwmSetDelta); + dev_info(smu->adev->dev, "FuzzyFan_Reserved = 0x%x\n", pptable->FuzzyFan_Reserved); + + dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "dBtcGbGfxDfllModelSelect = 0x%x\n", pptable->dBtcGbGfxDfllModelSelect); + dev_info(smu->adev->dev, "Padding8_Avfs = 0x%x\n", pptable->Padding8_Avfs); + + dev_info(smu->adev->dev, "qAvfsGb[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].a, + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].b, + pptable->qAvfsGb[AVFS_VOLTAGE_GFX].c); + dev_info(smu->adev->dev, "qAvfsGb[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].a, + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].b, + pptable->qAvfsGb[AVFS_VOLTAGE_SOC].c); + dev_info(smu->adev->dev, "dBtcGbGfxPll{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxPll.a, + pptable->dBtcGbGfxPll.b, + pptable->dBtcGbGfxPll.c); + dev_info(smu->adev->dev, "dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbGfxDfll.a, + pptable->dBtcGbGfxDfll.b, + pptable->dBtcGbGfxDfll.c); + dev_info(smu->adev->dev, "dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->dBtcGbSoc.a, + pptable->dBtcGbSoc.b, + pptable->dBtcGbSoc.c); + dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, + pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); + dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", + pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, + pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); + + dev_info(smu->adev->dev, "PiecewiseLinearDroopIntGfxDfll\n"); + for (i = 0; i < NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS; i++) { + dev_info(smu->adev->dev, " Fset[%d] = 0x%x\n", + i, pptable->PiecewiseLinearDroopIntGfxDfll.Fset[i]); + dev_info(smu->adev->dev, " Vdroop[%d] = 0x%x\n", + i, pptable->PiecewiseLinearDroopIntGfxDfll.Vdroop[i]); + } + + dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); + dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, + pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); + + dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); + dev_info(smu->adev->dev, "Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); + + dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); + dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); + dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); + + dev_info(smu->adev->dev, "XgmiDpmPstates\n"); + for (i = 0; i < NUM_XGMI_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiDpmPstates[i]); + dev_info(smu->adev->dev, "XgmiDpmSpare[0] = 0x%02x\n", pptable->XgmiDpmSpare[0]); + dev_info(smu->adev->dev, "XgmiDpmSpare[1] = 0x%02x\n", pptable->XgmiDpmSpare[1]); + + dev_info(smu->adev->dev, "DebugOverrides = 0x%x\n", pptable->DebugOverrides); + dev_info(smu->adev->dev, "ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation0.a, + pptable->ReservedEquation0.b, + pptable->ReservedEquation0.c); + dev_info(smu->adev->dev, "ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation1.a, + pptable->ReservedEquation1.b, + pptable->ReservedEquation1.c); + dev_info(smu->adev->dev, "ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation2.a, + pptable->ReservedEquation2.b, + pptable->ReservedEquation2.c); + dev_info(smu->adev->dev, "ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", + pptable->ReservedEquation3.a, + pptable->ReservedEquation3.b, + pptable->ReservedEquation3.c); + + dev_info(smu->adev->dev, "SkuReserved[0] = 0x%x\n", pptable->SkuReserved[0]); + dev_info(smu->adev->dev, "SkuReserved[1] = 0x%x\n", pptable->SkuReserved[1]); + dev_info(smu->adev->dev, "SkuReserved[2] = 0x%x\n", pptable->SkuReserved[2]); + dev_info(smu->adev->dev, "SkuReserved[3] = 0x%x\n", pptable->SkuReserved[3]); + dev_info(smu->adev->dev, "SkuReserved[4] = 0x%x\n", pptable->SkuReserved[4]); + dev_info(smu->adev->dev, "SkuReserved[5] = 0x%x\n", pptable->SkuReserved[5]); + dev_info(smu->adev->dev, "SkuReserved[6] = 0x%x\n", pptable->SkuReserved[6]); + dev_info(smu->adev->dev, "SkuReserved[7] = 0x%x\n", pptable->SkuReserved[7]); + dev_info(smu->adev->dev, "SkuReserved[8] = 0x%x\n", pptable->SkuReserved[8]); + dev_info(smu->adev->dev, "SkuReserved[9] = 0x%x\n", pptable->SkuReserved[9]); + dev_info(smu->adev->dev, "SkuReserved[10] = 0x%x\n", pptable->SkuReserved[10]); + dev_info(smu->adev->dev, "SkuReserved[11] = 0x%x\n", pptable->SkuReserved[11]); + dev_info(smu->adev->dev, "SkuReserved[12] = 0x%x\n", pptable->SkuReserved[12]); + dev_info(smu->adev->dev, "SkuReserved[13] = 0x%x\n", pptable->SkuReserved[13]); + + dev_info(smu->adev->dev, "GamingClk[0] = 0x%x\n", pptable->GamingClk[0]); + dev_info(smu->adev->dev, "GamingClk[1] = 0x%x\n", pptable->GamingClk[1]); + dev_info(smu->adev->dev, "GamingClk[2] = 0x%x\n", pptable->GamingClk[2]); + dev_info(smu->adev->dev, "GamingClk[3] = 0x%x\n", pptable->GamingClk[3]); + dev_info(smu->adev->dev, "GamingClk[4] = 0x%x\n", pptable->GamingClk[4]); + dev_info(smu->adev->dev, "GamingClk[5] = 0x%x\n", pptable->GamingClk[5]); + + for (i = 0; i < NUM_I2C_CONTROLLERS; i++) { + dev_info(smu->adev->dev, "I2cControllers[%d]:\n", i); + dev_info(smu->adev->dev, " .Enabled = 0x%x\n", + pptable->I2cControllers[i].Enabled); + dev_info(smu->adev->dev, " .Speed = 0x%x\n", + pptable->I2cControllers[i].Speed); + dev_info(smu->adev->dev, " .SlaveAddress = 0x%x\n", + pptable->I2cControllers[i].SlaveAddress); + dev_info(smu->adev->dev, " .ControllerPort = 0x%x\n", + pptable->I2cControllers[i].ControllerPort); + dev_info(smu->adev->dev, " .ControllerName = 0x%x\n", + pptable->I2cControllers[i].ControllerName); + dev_info(smu->adev->dev, " .ThermalThrottler = 0x%x\n", + pptable->I2cControllers[i].ThermalThrotter); + dev_info(smu->adev->dev, " .I2cProtocol = 0x%x\n", + pptable->I2cControllers[i].I2cProtocol); + dev_info(smu->adev->dev, " .PaddingConfig = 0x%x\n", + pptable->I2cControllers[i].PaddingConfig); + } + + dev_info(smu->adev->dev, "GpioScl = 0x%x\n", pptable->GpioScl); + dev_info(smu->adev->dev, "GpioSda = 0x%x\n", pptable->GpioSda); + dev_info(smu->adev->dev, "FchUsbPdSlaveAddr = 0x%x\n", pptable->FchUsbPdSlaveAddr); + dev_info(smu->adev->dev, "I2cSpare[0] = 0x%x\n", pptable->I2cSpare[0]); + + dev_info(smu->adev->dev, "Board Parameters:\n"); + dev_info(smu->adev->dev, "VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); + dev_info(smu->adev->dev, "VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); + dev_info(smu->adev->dev, "VddMem0VrMapping = 0x%x\n", pptable->VddMem0VrMapping); + dev_info(smu->adev->dev, "VddMem1VrMapping = 0x%x\n", pptable->VddMem1VrMapping); + dev_info(smu->adev->dev, "GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); + dev_info(smu->adev->dev, "SocUlvPhaseSheddingMask = 0x%x\n", pptable->SocUlvPhaseSheddingMask); + dev_info(smu->adev->dev, "VddciUlvPhaseSheddingMask = 0x%x\n", pptable->VddciUlvPhaseSheddingMask); + dev_info(smu->adev->dev, "MvddUlvPhaseSheddingMask = 0x%x\n", pptable->MvddUlvPhaseSheddingMask); + + dev_info(smu->adev->dev, "GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); + dev_info(smu->adev->dev, "GfxOffset = 0x%x\n", pptable->GfxOffset); + dev_info(smu->adev->dev, "Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); + + dev_info(smu->adev->dev, "SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); + dev_info(smu->adev->dev, "SocOffset = 0x%x\n", pptable->SocOffset); + dev_info(smu->adev->dev, "Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); + + dev_info(smu->adev->dev, "Mem0MaxCurrent = 0x%x\n", pptable->Mem0MaxCurrent); + dev_info(smu->adev->dev, "Mem0Offset = 0x%x\n", pptable->Mem0Offset); + dev_info(smu->adev->dev, "Padding_TelemetryMem0 = 0x%x\n", pptable->Padding_TelemetryMem0); + + dev_info(smu->adev->dev, "Mem1MaxCurrent = 0x%x\n", pptable->Mem1MaxCurrent); + dev_info(smu->adev->dev, "Mem1Offset = 0x%x\n", pptable->Mem1Offset); + dev_info(smu->adev->dev, "Padding_TelemetryMem1 = 0x%x\n", pptable->Padding_TelemetryMem1); + + dev_info(smu->adev->dev, "MvddRatio = 0x%x\n", pptable->MvddRatio); + + dev_info(smu->adev->dev, "AcDcGpio = 0x%x\n", pptable->AcDcGpio); + dev_info(smu->adev->dev, "AcDcPolarity = 0x%x\n", pptable->AcDcPolarity); + dev_info(smu->adev->dev, "VR0HotGpio = 0x%x\n", pptable->VR0HotGpio); + dev_info(smu->adev->dev, "VR0HotPolarity = 0x%x\n", pptable->VR0HotPolarity); + dev_info(smu->adev->dev, "VR1HotGpio = 0x%x\n", pptable->VR1HotGpio); + dev_info(smu->adev->dev, "VR1HotPolarity = 0x%x\n", pptable->VR1HotPolarity); + dev_info(smu->adev->dev, "GthrGpio = 0x%x\n", pptable->GthrGpio); + dev_info(smu->adev->dev, "GthrPolarity = 0x%x\n", pptable->GthrPolarity); + dev_info(smu->adev->dev, "LedPin0 = 0x%x\n", pptable->LedPin0); + dev_info(smu->adev->dev, "LedPin1 = 0x%x\n", pptable->LedPin1); + dev_info(smu->adev->dev, "LedPin2 = 0x%x\n", pptable->LedPin2); + dev_info(smu->adev->dev, "LedEnableMask = 0x%x\n", pptable->LedEnableMask); + dev_info(smu->adev->dev, "LedPcie = 0x%x\n", pptable->LedPcie); + dev_info(smu->adev->dev, "LedError = 0x%x\n", pptable->LedError); + dev_info(smu->adev->dev, "LedSpare1[0] = 0x%x\n", pptable->LedSpare1[0]); + dev_info(smu->adev->dev, "LedSpare1[1] = 0x%x\n", pptable->LedSpare1[1]); + + dev_info(smu->adev->dev, "PllGfxclkSpreadEnabled = 0x%x\n", pptable->PllGfxclkSpreadEnabled); + dev_info(smu->adev->dev, "PllGfxclkSpreadPercent = 0x%x\n", pptable->PllGfxclkSpreadPercent); + dev_info(smu->adev->dev, "PllGfxclkSpreadFreq = 0x%x\n", pptable->PllGfxclkSpreadFreq); + + dev_info(smu->adev->dev, "DfllGfxclkSpreadEnabled = 0x%x\n", pptable->DfllGfxclkSpreadEnabled); + dev_info(smu->adev->dev, "DfllGfxclkSpreadPercent = 0x%x\n", pptable->DfllGfxclkSpreadPercent); + dev_info(smu->adev->dev, "DfllGfxclkSpreadFreq = 0x%x\n", pptable->DfllGfxclkSpreadFreq); + + dev_info(smu->adev->dev, "UclkSpreadPadding = 0x%x\n", pptable->UclkSpreadPadding); + dev_info(smu->adev->dev, "UclkSpreadFreq = 0x%x\n", pptable->UclkSpreadFreq); + + dev_info(smu->adev->dev, "FclkSpreadEnabled = 0x%x\n", pptable->FclkSpreadEnabled); + dev_info(smu->adev->dev, "FclkSpreadPercent = 0x%x\n", pptable->FclkSpreadPercent); + dev_info(smu->adev->dev, "FclkSpreadFreq = 0x%x\n", pptable->FclkSpreadFreq); + + dev_info(smu->adev->dev, "MemoryChannelEnabled = 0x%x\n", pptable->MemoryChannelEnabled); + dev_info(smu->adev->dev, "DramBitWidth = 0x%x\n", pptable->DramBitWidth); + dev_info(smu->adev->dev, "PaddingMem1[0] = 0x%x\n", pptable->PaddingMem1[0]); + dev_info(smu->adev->dev, "PaddingMem1[1] = 0x%x\n", pptable->PaddingMem1[1]); + dev_info(smu->adev->dev, "PaddingMem1[2] = 0x%x\n", pptable->PaddingMem1[2]); + + dev_info(smu->adev->dev, "TotalBoardPower = 0x%x\n", pptable->TotalBoardPower); + dev_info(smu->adev->dev, "BoardPowerPadding = 0x%x\n", pptable->BoardPowerPadding); + + dev_info(smu->adev->dev, "XgmiLinkSpeed\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiLinkSpeed[i]); + dev_info(smu->adev->dev, "XgmiLinkWidth\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiLinkWidth[i]); + dev_info(smu->adev->dev, "XgmiFclkFreq\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiFclkFreq[i]); + dev_info(smu->adev->dev, "XgmiSocVoltage\n"); + for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) + dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiSocVoltage[i]); + + dev_info(smu->adev->dev, "HsrEnabled = 0x%x\n", pptable->HsrEnabled); + dev_info(smu->adev->dev, "VddqOffEnabled = 0x%x\n", pptable->VddqOffEnabled); + dev_info(smu->adev->dev, "PaddingUmcFlags[0] = 0x%x\n", pptable->PaddingUmcFlags[0]); + dev_info(smu->adev->dev, "PaddingUmcFlags[1] = 0x%x\n", pptable->PaddingUmcFlags[1]); + + dev_info(smu->adev->dev, "BoardReserved[0] = 0x%x\n", pptable->BoardReserved[0]); + dev_info(smu->adev->dev, "BoardReserved[1] = 0x%x\n", pptable->BoardReserved[1]); + dev_info(smu->adev->dev, "BoardReserved[2] = 0x%x\n", pptable->BoardReserved[2]); + dev_info(smu->adev->dev, "BoardReserved[3] = 0x%x\n", pptable->BoardReserved[3]); + dev_info(smu->adev->dev, "BoardReserved[4] = 0x%x\n", pptable->BoardReserved[4]); + dev_info(smu->adev->dev, "BoardReserved[5] = 0x%x\n", pptable->BoardReserved[5]); + dev_info(smu->adev->dev, "BoardReserved[6] = 0x%x\n", pptable->BoardReserved[6]); + dev_info(smu->adev->dev, "BoardReserved[7] = 0x%x\n", pptable->BoardReserved[7]); + dev_info(smu->adev->dev, "BoardReserved[8] = 0x%x\n", pptable->BoardReserved[8]); + dev_info(smu->adev->dev, "BoardReserved[9] = 0x%x\n", pptable->BoardReserved[9]); + dev_info(smu->adev->dev, "BoardReserved[10] = 0x%x\n", pptable->BoardReserved[10]); + + dev_info(smu->adev->dev, "MmHubPadding[0] = 0x%x\n", pptable->MmHubPadding[0]); + dev_info(smu->adev->dev, "MmHubPadding[1] = 0x%x\n", pptable->MmHubPadding[1]); + dev_info(smu->adev->dev, "MmHubPadding[2] = 0x%x\n", pptable->MmHubPadding[2]); + dev_info(smu->adev->dev, "MmHubPadding[3] = 0x%x\n", pptable->MmHubPadding[3]); + dev_info(smu->adev->dev, "MmHubPadding[4] = 0x%x\n", pptable->MmHubPadding[4]); + dev_info(smu->adev->dev, "MmHubPadding[5] = 0x%x\n", pptable->MmHubPadding[5]); + dev_info(smu->adev->dev, "MmHubPadding[6] = 0x%x\n", pptable->MmHubPadding[6]); + dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]); +} + +static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t *req, bool write, + uint8_t address, uint32_t numbytes, + uint8_t *data) +{ + int i; + + BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); + + req->I2CcontrollerPort = 0; + req->I2CSpeed = 2; + req->SlaveAddress = address; + req->NumCmds = numbytes; + + for (i = 0; i < numbytes; i++) { + SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; + + /* First 2 bytes are always write for lower 2b EEPROM address */ + if (i < 2) + cmd->CmdConfig = CMDCONFIG_READWRITE_MASK; + else + cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0; + + + /* Add RESTART for read after address filled */ + cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; + + /* Add STOP in the end */ + cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; + + /* Fill with data regardless if read or write to simplify code */ + cmd->ReadWriteData = data[i]; + } +} + +static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t i, ret = 0; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + struct smu_table_context *smu_table = &adev->smu.smu_table; + struct smu_table *table = &smu_table->driver_table; + + memset(&req, 0, sizeof(req)); + sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + /* Now read data starting with that address */ + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, + true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; + + /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ + for (i = 0; i < numbytes; i++) + data[i] = res->SwI2cCmds[i].ReadWriteData; + + dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + } else + dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret); + + return ret; +} + +static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control, + uint8_t address, + uint8_t *data, + uint32_t numbytes) +{ + uint32_t ret; + SwI2cRequest_t req; + struct amdgpu_device *adev = to_amdgpu_device(control); + + memset(&req, 0, sizeof(req)); + sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data); + + mutex_lock(&adev->smu.mutex); + ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); + mutex_unlock(&adev->smu.mutex); + + if (!ret) { + dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ", + (uint16_t)address, numbytes); + + print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, + 8, 1, data, numbytes, false); + /* + * According to EEPROM spec there is a MAX of 10 ms required for + * EEPROM to flush internal RX buffer after STOP was issued at the + * end of write transaction. During this time the EEPROM will not be + * responsive to any more commands - so wait a bit more. + */ + msleep(10); + + } else + dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret); + + return ret; +} + +static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, + struct i2c_msg *msgs, int num) +{ + uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; + uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; + + for (i = 0; i < num; i++) { + /* + * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at + * once and hence the data needs to be spliced into chunks and sent each + * chunk separately + */ + data_size = msgs[i].len - 2; + data_chunk_size = MAX_SW_I2C_COMMANDS - 2; + next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); + data_ptr = msgs[i].buf + 2; + + for (j = 0; j < data_size / data_chunk_size; j++) { + /* Insert the EEPROM dest addess, bits 0-15 */ + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = sienna_cichlid_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + + memcpy(data_ptr, data_chunk + 2, data_chunk_size); + } else { + + memcpy(data_chunk + 2, data_ptr, data_chunk_size); + + ret = sienna_cichlid_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, MAX_SW_I2C_COMMANDS); + } + + if (ret) { + num = -EIO; + goto fail; + } + + next_eeprom_addr += data_chunk_size; + data_ptr += data_chunk_size; + } + + if (data_size % data_chunk_size) { + data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); + data_chunk[1] = (next_eeprom_addr & 0xff); + + if (msgs[i].flags & I2C_M_RD) { + ret = sienna_cichlid_i2c_read_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + + memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); + } else { + memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); + + ret = sienna_cichlid_i2c_write_data(i2c_adap, + (uint8_t)msgs[i].addr, + data_chunk, (data_size % data_chunk_size) + 2); + } + + if (ret) { + num = -EIO; + goto fail; + } + } + } + +fail: + return num; +} + +static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap) +{ + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + + +static const struct i2c_algorithm sienna_cichlid_i2c_algo = { + .master_xfer = sienna_cichlid_i2c_xfer, + .functionality = sienna_cichlid_i2c_func, +}; + +static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) +{ + struct amdgpu_device *adev = to_amdgpu_device(control); + int res; + + control->owner = THIS_MODULE; + control->class = I2C_CLASS_SPD; + control->dev.parent = &adev->pdev->dev; + control->algo = &sienna_cichlid_i2c_algo; + snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); + + res = i2c_add_adapter(control); + if (res) + DRM_ERROR("Failed to register hw i2c, err: %d\n", res); + + return res; +} + +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) +{ + i2c_del_adapter(control); +} + +static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v1_0 *gpu_metrics = + (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, + &metrics, + true); + if (ret) + return ret; + + smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); + + gpu_metrics->temperature_edge = metrics.TemperatureEdge; + gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; + gpu_metrics->temperature_mem = metrics.TemperatureMem; + gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; + gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; + gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; + gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; + + gpu_metrics->average_socket_power = metrics.AverageSocketPower; + gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; + + if (metrics.AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs; + else + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs; + gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs; + gpu_metrics->average_vclk0_frequency = metrics.AverageVclk0Frequency; + gpu_metrics->average_dclk0_frequency = metrics.AverageDclk0Frequency; + gpu_metrics->average_vclk1_frequency = metrics.AverageVclk1Frequency; + gpu_metrics->average_dclk1_frequency = metrics.AverageDclk1Frequency; + + gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; + gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; + gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; + gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK_0]; + gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK_0]; + gpu_metrics->current_vclk1 = metrics.CurrClock[PPCLK_VCLK_1]; + gpu_metrics->current_dclk1 = metrics.CurrClock[PPCLK_DCLK_1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; + + gpu_metrics->pcie_link_width = + smu_v11_0_get_current_pcie_link_width(smu); + gpu_metrics->pcie_link_speed = + smu_v11_0_get_current_pcie_link_speed(smu); + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v1_0); +} + +static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMGpuFanBoostLimitRpm, + 0, + NULL); +} + +static const struct pptable_funcs sienna_cichlid_ppt_funcs = { + .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, + .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, + .dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable, + .dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable, + .i2c_init = sienna_cichlid_i2c_control_init, + .i2c_fini = sienna_cichlid_i2c_control_fini, + .print_clk_levels = sienna_cichlid_print_clk_levels, + .force_clk_levels = sienna_cichlid_force_clk_levels, + .populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk, + .pre_display_config_changed = sienna_cichlid_pre_display_config_changed, + .display_config_changed = sienna_cichlid_display_config_changed, + .notify_smc_display_config = sienna_cichlid_notify_smc_display_config, + .is_dpm_running = sienna_cichlid_is_dpm_running, + .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent, + .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm, + .get_power_profile_mode = sienna_cichlid_get_power_profile_mode, + .set_power_profile_mode = sienna_cichlid_set_power_profile_mode, + .set_watermarks_table = sienna_cichlid_set_watermarks_table, + .read_sensor = sienna_cichlid_read_sensor, + .get_uclk_dpm_states = sienna_cichlid_get_uclk_dpm_states, + .set_performance_level = smu_v11_0_set_performance_level, + .get_thermal_temperature_range = sienna_cichlid_get_thermal_temperature_range, + .display_disable_memory_clock_switch = sienna_cichlid_display_disable_memory_clock_switch, + .get_power_limit = sienna_cichlid_get_power_limit, + .update_pcie_parameters = sienna_cichlid_update_pcie_parameters, + .dump_pptable = sienna_cichlid_dump_pptable, + .init_microcode = smu_v11_0_init_microcode, + .load_microcode = smu_v11_0_load_microcode, + .init_smc_tables = sienna_cichlid_init_smc_tables, + .fini_smc_tables = smu_v11_0_fini_smc_tables, + .init_power = smu_v11_0_init_power, + .fini_power = smu_v11_0_fini_power, + .check_fw_status = smu_v11_0_check_fw_status, + .setup_pptable = sienna_cichlid_setup_pptable, + .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, + .check_fw_version = smu_v11_0_check_fw_version, + .write_pptable = smu_cmn_write_pptable, + .set_driver_table_location = smu_v11_0_set_driver_table_location, + .set_tool_table_location = smu_v11_0_set_tool_table_location, + .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, + .system_features_control = smu_v11_0_system_features_control, + .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, + .send_smc_msg = smu_cmn_send_smc_msg, + .init_display_count = NULL, + .set_allowed_mask = smu_v11_0_set_allowed_mask, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, + .notify_display_change = NULL, + .set_power_limit = smu_v11_0_set_power_limit, + .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, + .enable_thermal_alert = smu_v11_0_enable_thermal_alert, + .disable_thermal_alert = smu_v11_0_disable_thermal_alert, + .set_min_dcef_deep_sleep = NULL, + .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, + .get_fan_control_mode = smu_v11_0_get_fan_control_mode, + .set_fan_control_mode = smu_v11_0_set_fan_control_mode, + .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, + .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, + .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, + .gfx_off_control = smu_v11_0_gfx_off_control, + .register_irq_handler = smu_v11_0_register_irq_handler, + .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, + .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, + .baco_is_support= sienna_cichlid_is_baco_supported, + .baco_get_state = smu_v11_0_baco_get_state, + .baco_set_state = smu_v11_0_baco_set_state, + .baco_enter = smu_v11_0_baco_enter, + .baco_exit = smu_v11_0_baco_exit, + .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, + .mode1_reset = smu_v11_0_mode1_reset, + .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, + .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, + .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, +}; + +void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &sienna_cichlid_ppt_funcs; + smu->message_map = sienna_cichlid_message_map; + smu->clock_map = sienna_cichlid_clk_map; + smu->feature_map = sienna_cichlid_feature_mask_map; + smu->table_map = sienna_cichlid_table_map; + smu->pwr_src_map = sienna_cichlid_pwr_src_map; + smu->workload_map = sienna_cichlid_workload_map; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h new file mode 100644 index 000000000000..57e120c440ea --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.h @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __SIENNA_CICHLID_PPT_H__ +#define __SIENNA_CICHLID_PPT_H__ + +typedef enum { + POWER_SOURCE_AC, + POWER_SOURCE_DC, + POWER_SOURCE_COUNT, +} POWER_SOURCE_e; + +extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c new file mode 100644 index 000000000000..ff574ebc179e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -0,0 +1,1987 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#define SMU_11_0_PARTIAL_PPTABLE +#define SWSMU_CODE_LAYER_L3 + +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "amdgpu_atombios.h" +#include "smu_v11_0.h" +#include "soc15_common.h" +#include "atom.h" +#include "amdgpu_ras.h" +#include "smu_cmn.h" + +#include "asic_reg/thm/thm_11_0_2_offset.h" +#include "asic_reg/thm/thm_11_0_2_sh_mask.h" +#include "asic_reg/mp/mp_11_0_offset.h" +#include "asic_reg/mp/mp_11_0_sh_mask.h" +#include "asic_reg/smuio/smuio_11_0_0_offset.h" +#include "asic_reg/smuio/smuio_11_0_0_sh_mask.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +MODULE_FIRMWARE("amdgpu/arcturus_smc.bin"); +MODULE_FIRMWARE("amdgpu/navi10_smc.bin"); +MODULE_FIRMWARE("amdgpu/navi14_smc.bin"); +MODULE_FIRMWARE("amdgpu/navi12_smc.bin"); +MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin"); +MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin"); + +#define SMU11_VOLTAGE_SCALE 4 + +#define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms + +#define LINK_WIDTH_MAX 6 +#define LINK_SPEED_MAX 3 + +#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L +#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4 +#define smnPCIE_LC_SPEED_CNTL 0x11140290 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000 +#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE + +static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; +static int link_speed[] = {25, 50, 80, 160}; + +int smu_v11_0_init_microcode(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + const char *chip_name; + char fw_name[30]; + int err = 0; + const struct smc_firmware_header_v1_0 *hdr; + const struct common_firmware_header *header; + struct amdgpu_firmware_info *ucode = NULL; + + switch (adev->asic_type) { + case CHIP_ARCTURUS: + chip_name = "arcturus"; + break; + case CHIP_NAVI10: + chip_name = "navi10"; + break; + case CHIP_NAVI14: + chip_name = "navi14"; + break; + case CHIP_NAVI12: + chip_name = "navi12"; + break; + case CHIP_SIENNA_CICHLID: + chip_name = "sienna_cichlid"; + break; + case CHIP_NAVY_FLOUNDER: + chip_name = "navy_flounder"; + break; + default: + dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type); + return -EINVAL; + } + + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); + + err = request_firmware(&adev->pm.fw, fw_name, adev->dev); + if (err) + goto out; + err = amdgpu_ucode_validate(adev->pm.fw); + if (err) + goto out; + + hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; + amdgpu_ucode_print_smc_hdr(&hdr->header); + adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); + + if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { + ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; + ucode->ucode_id = AMDGPU_UCODE_ID_SMC; + ucode->fw = adev->pm.fw; + header = (const struct common_firmware_header *)ucode->fw->data; + adev->firmware.fw_size += + ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); + } + +out: + if (err) { + DRM_ERROR("smu_v11_0: Failed to load firmware \"%s\"\n", + fw_name); + release_firmware(adev->pm.fw); + adev->pm.fw = NULL; + } + return err; +} + +void smu_v11_0_fini_microcode(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + release_firmware(adev->pm.fw); + adev->pm.fw = NULL; + adev->pm.fw_version = 0; +} + +int smu_v11_0_load_microcode(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + const uint32_t *src; + const struct smc_firmware_header_v1_0 *hdr; + uint32_t addr_start = MP1_SRAM; + uint32_t i; + uint32_t smc_fw_size; + uint32_t mp1_fw_flags; + + hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; + src = (const uint32_t *)(adev->pm.fw->data + + le32_to_cpu(hdr->header.ucode_array_offset_bytes)); + smc_fw_size = hdr->header.ucode_size_bytes; + + for (i = 1; i < smc_fw_size/4 - 1; i++) { + WREG32_PCIE(addr_start, src[i]); + addr_start += 4; + } + + WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff), + 1 & MP1_SMN_PUB_CTRL__RESET_MASK); + WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff), + 1 & ~MP1_SMN_PUB_CTRL__RESET_MASK); + + for (i = 0; i < adev->usec_timeout; i++) { + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> + MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) + break; + udelay(1); + } + + if (i == adev->usec_timeout) + return -ETIME; + + return 0; +} + +int smu_v11_0_check_fw_status(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t mp1_fw_flags; + + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + + if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> + MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) + return 0; + + return -EIO; +} + +int smu_v11_0_check_fw_version(struct smu_context *smu) +{ + uint32_t if_version = 0xff, smu_version = 0xff; + uint16_t smu_major; + uint8_t smu_minor, smu_debug; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); + if (ret) + return ret; + + smu_major = (smu_version >> 16) & 0xffff; + smu_minor = (smu_version >> 8) & 0xff; + smu_debug = (smu_version >> 0) & 0xff; + + switch (smu->adev->asic_type) { + case CHIP_ARCTURUS: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT; + break; + case CHIP_NAVI10: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10; + break; + case CHIP_NAVI12: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12; + break; + case CHIP_NAVI14: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14; + break; + case CHIP_SIENNA_CICHLID: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid; + break; + case CHIP_NAVY_FLOUNDER: + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder; + break; + default: + dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type); + smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV; + break; + } + + /* + * 1. if_version mismatch is not critical as our fw is designed + * to be backward compatible. + * 2. New fw usually brings some optimizations. But that's visible + * only on the paired driver. + * Considering above, we just leave user a warning message instead + * of halt driver loading. + */ + if (if_version != smu->smc_driver_if_version) { + dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " + "smu fw version = 0x%08x (%d.%d.%d)\n", + smu->smc_driver_if_version, if_version, + smu_version, smu_major, smu_minor, smu_debug); + dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); + } + + return ret; +} + +static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t ppt_offset_bytes; + const struct smc_firmware_header_v2_0 *v2; + + v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data; + + ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes); + *size = le32_to_cpu(v2->ppt_size_bytes); + *table = (uint8_t *)v2 + ppt_offset_bytes; + + return 0; +} + +static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table, + uint32_t *size, uint32_t pptable_id) +{ + struct amdgpu_device *adev = smu->adev; + const struct smc_firmware_header_v2_1 *v2_1; + struct smc_soft_pptable_entry *entries; + uint32_t pptable_count = 0; + int i = 0; + + v2_1 = (const struct smc_firmware_header_v2_1 *) adev->pm.fw->data; + entries = (struct smc_soft_pptable_entry *) + ((uint8_t *)v2_1 + le32_to_cpu(v2_1->pptable_entry_offset)); + pptable_count = le32_to_cpu(v2_1->pptable_count); + for (i = 0; i < pptable_count; i++) { + if (le32_to_cpu(entries[i].id) == pptable_id) { + *table = ((uint8_t *)v2_1 + le32_to_cpu(entries[i].ppt_offset_bytes)); + *size = le32_to_cpu(entries[i].ppt_size_bytes); + break; + } + } + + if (i == pptable_count) + return -EINVAL; + + return 0; +} + +int smu_v11_0_setup_pptable(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + const struct smc_firmware_header_v1_0 *hdr; + int ret, index; + uint32_t size = 0; + uint16_t atom_table_size; + uint8_t frev, crev; + void *table; + uint16_t version_major, version_minor; + + hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; + version_major = le16_to_cpu(hdr->header.header_version_major); + version_minor = le16_to_cpu(hdr->header.header_version_minor); + if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || + adev->asic_type == CHIP_NAVY_FLOUNDER) { + dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); + switch (version_minor) { + case 0: + ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size); + break; + case 1: + ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size, + smu->smu_table.boot_values.pp_table_id); + break; + default: + ret = -EINVAL; + break; + } + if (ret) + return ret; + + } else { + dev_info(adev->dev, "use vbios provided pptable\n"); + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + powerplayinfo); + + ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev, + (uint8_t **)&table); + if (ret) + return ret; + size = atom_table_size; + } + + if (!smu->smu_table.power_play_table) + smu->smu_table.power_play_table = table; + if (!smu->smu_table.power_play_table_size) + smu->smu_table.power_play_table_size = size; + + return 0; +} + +int smu_v11_0_init_smc_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + int ret = 0; + + smu_table->driver_pptable = + kzalloc(tables[SMU_TABLE_PPTABLE].size, GFP_KERNEL); + if (!smu_table->driver_pptable) { + ret = -ENOMEM; + goto err0_out; + } + + smu_table->max_sustainable_clocks = + kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), GFP_KERNEL); + if (!smu_table->max_sustainable_clocks) { + ret = -ENOMEM; + goto err1_out; + } + + /* Arcturus does not support OVERDRIVE */ + if (tables[SMU_TABLE_OVERDRIVE].size) { + smu_table->overdrive_table = + kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL); + if (!smu_table->overdrive_table) { + ret = -ENOMEM; + goto err2_out; + } + + smu_table->boot_overdrive_table = + kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL); + if (!smu_table->boot_overdrive_table) { + ret = -ENOMEM; + goto err3_out; + } + } + + return 0; + +err3_out: + kfree(smu_table->overdrive_table); +err2_out: + kfree(smu_table->max_sustainable_clocks); +err1_out: + kfree(smu_table->driver_pptable); +err0_out: + return ret; +} + +int smu_v11_0_fini_smc_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_dpm_context *smu_dpm = &smu->smu_dpm; + + kfree(smu_table->gpu_metrics_table); + kfree(smu_table->boot_overdrive_table); + kfree(smu_table->overdrive_table); + kfree(smu_table->max_sustainable_clocks); + kfree(smu_table->driver_pptable); + smu_table->gpu_metrics_table = NULL; + smu_table->boot_overdrive_table = NULL; + smu_table->overdrive_table = NULL; + smu_table->max_sustainable_clocks = NULL; + smu_table->driver_pptable = NULL; + kfree(smu_table->hardcode_pptable); + smu_table->hardcode_pptable = NULL; + + kfree(smu_table->metrics_table); + kfree(smu_table->watermarks_table); + smu_table->metrics_table = NULL; + smu_table->watermarks_table = NULL; + smu_table->metrics_time = 0; + + kfree(smu_dpm->dpm_context); + kfree(smu_dpm->golden_dpm_context); + kfree(smu_dpm->dpm_current_power_state); + kfree(smu_dpm->dpm_request_power_state); + smu_dpm->dpm_context = NULL; + smu_dpm->golden_dpm_context = NULL; + smu_dpm->dpm_context_size = 0; + smu_dpm->dpm_current_power_state = NULL; + smu_dpm->dpm_request_power_state = NULL; + + return 0; +} + +int smu_v11_0_init_power(struct smu_context *smu) +{ + struct smu_power_context *smu_power = &smu->smu_power; + + if (smu_power->power_context || smu_power->power_context_size != 0) + return -EINVAL; + + smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context), + GFP_KERNEL); + if (!smu_power->power_context) + return -ENOMEM; + smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context); + + return 0; +} + +int smu_v11_0_fini_power(struct smu_context *smu) +{ + struct smu_power_context *smu_power = &smu->smu_power; + + if (!smu_power->power_context || smu_power->power_context_size == 0) + return -EINVAL; + + kfree(smu_power->power_context); + smu_power->power_context = NULL; + smu_power->power_context_size = 0; + + return 0; +} + +static int smu_v11_0_atom_get_smu_clockinfo(struct amdgpu_device *adev, + uint8_t clk_id, + uint8_t syspll_id, + uint32_t *clk_freq) +{ + struct atom_get_smu_clock_info_parameters_v3_1 input = {0}; + struct atom_get_smu_clock_info_output_parameters_v3_1 *output; + int ret, index; + + input.clk_id = clk_id; + input.syspll_id = syspll_id; + input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ; + index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1, + getsmuclockinfo); + + ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index, + (uint32_t *)&input); + if (ret) + return -EINVAL; + + output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input; + *clk_freq = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000; + + return 0; +} + +int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu) +{ + int ret, index; + uint16_t size; + uint8_t frev, crev; + struct atom_common_table_header *header; + struct atom_firmware_info_v3_3 *v_3_3; + struct atom_firmware_info_v3_1 *v_3_1; + + index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, + firmwareinfo); + + ret = amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev, + (uint8_t **)&header); + if (ret) + return ret; + + if (header->format_revision != 3) { + dev_err(smu->adev->dev, "unknown atom_firmware_info version! for smu11\n"); + return -EINVAL; + } + + switch (header->content_revision) { + case 0: + case 1: + case 2: + v_3_1 = (struct atom_firmware_info_v3_1 *)header; + smu->smu_table.boot_values.revision = v_3_1->firmware_revision; + smu->smu_table.boot_values.gfxclk = v_3_1->bootup_sclk_in10khz; + smu->smu_table.boot_values.uclk = v_3_1->bootup_mclk_in10khz; + smu->smu_table.boot_values.socclk = 0; + smu->smu_table.boot_values.dcefclk = 0; + smu->smu_table.boot_values.vddc = v_3_1->bootup_vddc_mv; + smu->smu_table.boot_values.vddci = v_3_1->bootup_vddci_mv; + smu->smu_table.boot_values.mvddc = v_3_1->bootup_mvddc_mv; + smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv; + smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id; + smu->smu_table.boot_values.pp_table_id = 0; + break; + case 3: + default: + v_3_3 = (struct atom_firmware_info_v3_3 *)header; + smu->smu_table.boot_values.revision = v_3_3->firmware_revision; + smu->smu_table.boot_values.gfxclk = v_3_3->bootup_sclk_in10khz; + smu->smu_table.boot_values.uclk = v_3_3->bootup_mclk_in10khz; + smu->smu_table.boot_values.socclk = 0; + smu->smu_table.boot_values.dcefclk = 0; + smu->smu_table.boot_values.vddc = v_3_3->bootup_vddc_mv; + smu->smu_table.boot_values.vddci = v_3_3->bootup_vddci_mv; + smu->smu_table.boot_values.mvddc = v_3_3->bootup_mvddc_mv; + smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv; + smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id; + smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id; + } + + smu->smu_table.boot_values.format_revision = header->format_revision; + smu->smu_table.boot_values.content_revision = header->content_revision; + + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL0_SOCCLK_ID, + (uint8_t)0, + &smu->smu_table.boot_values.socclk); + + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL0_DCEFCLK_ID, + (uint8_t)0, + &smu->smu_table.boot_values.dcefclk); + + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL0_ECLK_ID, + (uint8_t)0, + &smu->smu_table.boot_values.eclk); + + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL0_VCLK_ID, + (uint8_t)0, + &smu->smu_table.boot_values.vclk); + + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL0_DCLK_ID, + (uint8_t)0, + &smu->smu_table.boot_values.dclk); + + if ((smu->smu_table.boot_values.format_revision == 3) && + (smu->smu_table.boot_values.content_revision >= 2)) + smu_v11_0_atom_get_smu_clockinfo(smu->adev, + (uint8_t)SMU11_SYSPLL1_0_FCLK_ID, + (uint8_t)SMU11_SYSPLL1_2_ID, + &smu->smu_table.boot_values.fclk); + + return 0; +} + +int smu_v11_0_notify_memory_pool_location(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *memory_pool = &smu_table->memory_pool; + int ret = 0; + uint64_t address; + uint32_t address_low, address_high; + + if (memory_pool->size == 0 || memory_pool->cpu_addr == NULL) + return ret; + + address = (uintptr_t)memory_pool->cpu_addr; + address_high = (uint32_t)upper_32_bits(address); + address_low = (uint32_t)lower_32_bits(address); + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSystemVirtualDramAddrHigh, + address_high, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetSystemVirtualDramAddrLow, + address_low, + NULL); + if (ret) + return ret; + + address = memory_pool->mc_address; + address_high = (uint32_t)upper_32_bits(address); + address_low = (uint32_t)lower_32_bits(address); + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh, + address_high, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow, + address_low, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize, + (uint32_t)memory_pool->size, NULL); + if (ret) + return ret; + + return ret; +} + +int smu_v11_0_set_min_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk) +{ + int ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetMinDeepSleepDcefclk, clk, NULL); + if (ret) + dev_err(smu->adev->dev, "SMU11 attempt to set divider for DCEFCLK Failed!"); + + return ret; +} + +int smu_v11_0_set_driver_table_location(struct smu_context *smu) +{ + struct smu_table *driver_table = &smu->smu_table.driver_table; + int ret = 0; + + if (driver_table->mc_address) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetDriverDramAddrHigh, + upper_32_bits(driver_table->mc_address), + NULL); + if (!ret) + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetDriverDramAddrLow, + lower_32_bits(driver_table->mc_address), + NULL); + } + + return ret; +} + +int smu_v11_0_set_tool_table_location(struct smu_context *smu) +{ + int ret = 0; + struct smu_table *tool_table = &smu->smu_table.tables[SMU_TABLE_PMSTATUSLOG]; + + if (tool_table->mc_address) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetToolsDramAddrHigh, + upper_32_bits(tool_table->mc_address), + NULL); + if (!ret) + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetToolsDramAddrLow, + lower_32_bits(tool_table->mc_address), + NULL); + } + + return ret; +} + +int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) +{ + int ret = 0; + struct amdgpu_device *adev = smu->adev; + + /* Navy_Flounder do not support to change display num currently */ + if (adev->asic_type == CHIP_NAVY_FLOUNDER) + return 0; + + if (!smu->pm_enabled) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, count, NULL); + return ret; +} + + +int smu_v11_0_set_allowed_mask(struct smu_context *smu) +{ + struct smu_feature *feature = &smu->smu_feature; + int ret = 0; + uint32_t feature_mask[2]; + + mutex_lock(&feature->mutex); + if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || feature->feature_num < 64) + goto failed; + + bitmap_copy((unsigned long *)feature_mask, feature->allowed, 64); + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskHigh, + feature_mask[1], NULL); + if (ret) + goto failed; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskLow, + feature_mask[0], NULL); + if (ret) + goto failed; + +failed: + mutex_unlock(&feature->mutex); + return ret; +} + +int smu_v11_0_system_features_control(struct smu_context *smu, + bool en) +{ + struct smu_feature *feature = &smu->smu_feature; + uint32_t feature_mask[2]; + int ret = 0; + + ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : + SMU_MSG_DisableAllSmuFeatures), NULL); + if (ret) + return ret; + + bitmap_zero(feature->enabled, feature->feature_num); + bitmap_zero(feature->supported, feature->feature_num); + + if (en) { + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); + if (ret) + return ret; + + bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, + feature->feature_num); + bitmap_copy(feature->supported, (unsigned long *)&feature_mask, + feature->feature_num); + } + + return ret; +} + +int smu_v11_0_notify_display_change(struct smu_context *smu) +{ + int ret = 0; + + if (!smu->pm_enabled) + return ret; + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && + smu->adev->gmc.vram_type == AMDGPU_VRAM_TYPE_HBM) + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1, NULL); + + return ret; +} + +static int +smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock, + enum smu_clk_type clock_select) +{ + int ret = 0; + int clk_id; + + if ((smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetDcModeMaxDpmFreq) < 0) || + (smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetMaxDpmFreq) < 0)) + return 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clock_select); + if (clk_id < 0) + return -EINVAL; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq, + clk_id << 16, clock); + if (ret) { + dev_err(smu->adev->dev, "[GetMaxSustainableClock] Failed to get max DC clock from SMC!"); + return ret; + } + + if (*clock != 0) + return 0; + + /* if DC limit is zero, return AC limit */ + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, + clk_id << 16, clock); + if (ret) { + dev_err(smu->adev->dev, "[GetMaxSustainableClock] failed to get max AC clock from SMC!"); + return ret; + } + + return 0; +} + +int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) +{ + struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = + smu->smu_table.max_sustainable_clocks; + int ret = 0; + + max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100; + max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100; + max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100; + max_sustainable_clocks->display_clock = 0xFFFFFFFF; + max_sustainable_clocks->phy_clock = 0xFFFFFFFF; + max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->uclock), + SMU_UCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max UCLK from SMC!", + __func__); + return ret; + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->soc_clock), + SMU_SOCCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max SOCCLK from SMC!", + __func__); + return ret; + } + } + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->dcef_clock), + SMU_DCEFCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max DCEFCLK from SMC!", + __func__); + return ret; + } + + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->display_clock), + SMU_DISPCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max DISPCLK from SMC!", + __func__); + return ret; + } + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->phy_clock), + SMU_PHYCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max PHYCLK from SMC!", + __func__); + return ret; + } + ret = smu_v11_0_get_max_sustainable_clock(smu, + &(max_sustainable_clocks->pixel_clock), + SMU_PIXCLK); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get max PIXCLK from SMC!", + __func__); + return ret; + } + } + + if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) + max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; + + return 0; +} + +int smu_v11_0_get_current_power_limit(struct smu_context *smu, + uint32_t *power_limit) +{ + int power_src; + int ret = 0; + + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) + return -EINVAL; + + power_src = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_PWR, + smu->adev->pm.ac_power ? + SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (power_src < 0) + return -EINVAL; + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetPptLimit, + power_src << 16, + power_limit); + if (ret) + dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); + + return ret; +} + +int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) +{ + int ret = 0; + + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { + dev_err(smu->adev->dev, "Setting new power limit is not supported!\n"); + return -EOPNOTSUPP; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL); + if (ret) { + dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__); + return ret; + } + + smu->current_power_limit = n; + + return 0; +} + +int smu_v11_0_enable_thermal_alert(struct smu_context *smu) +{ + if (smu->smu_table.thermal_controller_type) + return amdgpu_irq_get(smu->adev, &smu->irq_source, 0); + + return 0; +} + +int smu_v11_0_disable_thermal_alert(struct smu_context *smu) +{ + return amdgpu_irq_put(smu->adev, &smu->irq_source, 0); +} + +static uint16_t convert_to_vddc(uint8_t vid) +{ + return (uint16_t) ((6200 - (vid * 25)) / SMU11_VOLTAGE_SCALE); +} + +int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t vdd = 0, val_vid = 0; + + if (!value) + return -EINVAL; + val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & + SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> + SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; + + vdd = (uint32_t)convert_to_vddc((uint8_t)val_vid); + + *value = vdd; + + return 0; + +} + +int +smu_v11_0_display_clock_voltage_request(struct smu_context *smu, + struct pp_display_clock_request + *clock_req) +{ + enum amd_pp_clock_type clk_type = clock_req->clock_type; + int ret = 0; + enum smu_clk_type clk_select = 0; + uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; + + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) || + smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { + switch (clk_type) { + case amd_pp_dcef_clock: + clk_select = SMU_DCEFCLK; + break; + case amd_pp_disp_clock: + clk_select = SMU_DISPCLK; + break; + case amd_pp_pixel_clock: + clk_select = SMU_PIXCLK; + break; + case amd_pp_phy_clock: + clk_select = SMU_PHYCLK; + break; + case amd_pp_mem_clock: + clk_select = SMU_UCLK; + break; + default: + dev_info(smu->adev->dev, "[%s] Invalid Clock Type!", __func__); + ret = -EINVAL; + break; + } + + if (ret) + goto failed; + + if (clk_select == SMU_UCLK && smu->disable_uclk_switch) + return 0; + + ret = smu_v11_0_set_hard_freq_limited_range(smu, clk_select, clk_freq, 0); + + if(clk_select == SMU_UCLK) + smu->hard_min_uclk_req_from_dal = clk_freq; + } + +failed: + return ret; +} + +int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) +{ + int ret = 0; + struct amdgpu_device *adev = smu->adev; + + switch (adev->asic_type) { + case CHIP_NAVI10: + case CHIP_NAVI14: + case CHIP_NAVI12: + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) + return 0; + if (enable) + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); + else + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); + break; + default: + break; + } + + return ret; +} + +uint32_t +smu_v11_0_get_fan_control_mode(struct smu_context *smu) +{ + if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) + return AMD_FAN_CTRL_MANUAL; + else + return AMD_FAN_CTRL_AUTO; +} + +static int +smu_v11_0_auto_fan_control(struct smu_context *smu, bool auto_fan_control) +{ + int ret = 0; + + if (!smu_cmn_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT)) + return 0; + + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, auto_fan_control); + if (ret) + dev_err(smu->adev->dev, "[%s]%s smc FAN CONTROL feature failed!", + __func__, (auto_fan_control ? "Start" : "Stop")); + + return ret; +} + +static int +smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode) +{ + struct amdgpu_device *adev = smu->adev; + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, TMIN, 0)); + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), + CG_FDO_CTRL2, FDO_PWM_MODE, mode)); + + return 0; +} + +int +smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t duty100, duty; + uint64_t tmp64; + + if (speed > 100) + speed = 100; + + if (smu_v11_0_auto_fan_control(smu, 0)) + return -EINVAL; + + duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), + CG_FDO_CTRL1, FMAX_DUTY100); + if (!duty100) + return -EINVAL; + + tmp64 = (uint64_t)speed * duty100; + do_div(tmp64, 100); + duty = (uint32_t)tmp64; + + WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); + + return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC); +} + +int +smu_v11_0_set_fan_control_mode(struct smu_context *smu, + uint32_t mode) +{ + int ret = 0; + + switch (mode) { + case AMD_FAN_CTRL_NONE: + ret = smu_v11_0_set_fan_speed_percent(smu, 100); + break; + case AMD_FAN_CTRL_MANUAL: + ret = smu_v11_0_auto_fan_control(smu, 0); + break; + case AMD_FAN_CTRL_AUTO: + ret = smu_v11_0_auto_fan_control(smu, 1); + break; + default: + break; + } + + if (ret) { + dev_err(smu->adev->dev, "[%s]Set fan control mode failed!", __func__); + return -EINVAL; + } + + return ret; +} + +int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, + uint32_t speed) +{ + struct amdgpu_device *adev = smu->adev; + int ret; + uint32_t tach_period, crystal_clock_freq; + + if (!speed) + return -EINVAL; + + ret = smu_v11_0_auto_fan_control(smu, 0); + if (ret) + return ret; + + crystal_clock_freq = amdgpu_asic_get_xclk(adev); + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); + WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, + REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, TARGET_PERIOD, + tach_period)); + + ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM); + + return ret; +} + +int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, + uint32_t pstate) +{ + int ret = 0; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetXgmiMode, + pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, + NULL); + return ret; +} + +static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned tyep, + enum amdgpu_interrupt_state state) +{ + struct smu_context *smu = &adev->smu; + uint32_t low, high; + uint32_t val = 0; + + switch (state) { + case AMDGPU_IRQ_STATE_DISABLE: + /* For THM irqs */ + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 1); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 1); + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); + + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); + + /* For MP1 SW irqs */ + val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); + WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val); + + break; + case AMDGPU_IRQ_STATE_ENABLE: + /* For THM irqs */ + low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, + smu->thermal_range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); + high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, + smu->thermal_range.software_shutdown_temp); + + val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); + val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); + + val = (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); + val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); + WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); + + /* For MP1 SW irqs */ + val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); + WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT, val); + + val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); + val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0); + WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val); + + break; + default: + break; + } + + return 0; +} + +static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg(smu, + SMU_MSG_ReenableAcDcInterrupt, + NULL); +} + +#define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ +#define THM_11_0__SRCID__THM_DIG_THERM_H2L 1 /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL */ + +#define SMUIO_11_0__SRCID__SMUIO_GPIO19 83 + +static int smu_v11_0_irq_process(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + struct amdgpu_iv_entry *entry) +{ + struct smu_context *smu = &adev->smu; + uint32_t client_id = entry->client_id; + uint32_t src_id = entry->src_id; + /* + * ctxid is used to distinguish different + * events for SMCToHost interrupt. + */ + uint32_t ctxid = entry->src_data[0]; + uint32_t data; + + if (client_id == SOC15_IH_CLIENTID_THM) { + switch (src_id) { + case THM_11_0__SRCID__THM_DIG_THERM_L2H: + dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); + /* + * SW CTF just occurred. + * Try to do a graceful shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); + orderly_poweroff(true); + break; + case THM_11_0__SRCID__THM_DIG_THERM_H2L: + dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n"); + break; + default: + dev_emerg(adev->dev, "ERROR: GPU under temperature range unknown src id (%d)\n", + src_id); + break; + } + } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) { + dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); + /* + * HW CTF just occurred. Shutdown to prevent further damage. + */ + dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); + orderly_poweroff(true); + } else if (client_id == SOC15_IH_CLIENTID_MP1) { + if (src_id == 0xfe) { + /* ACK SMUToHost interrupt */ + data = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); + data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1); + WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, data); + + switch (ctxid) { + case 0x3: + dev_dbg(adev->dev, "Switched to AC mode!\n"); + smu_v11_0_ack_ac_dc_interrupt(&adev->smu); + break; + case 0x4: + dev_dbg(adev->dev, "Switched to DC mode!\n"); + 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; + + if (__ratelimit(&adev->throttling_logging_rs)) + schedule_work(&smu->throttling_logging_work); + + break; + } + } + } + + return 0; +} + +static const struct amdgpu_irq_src_funcs smu_v11_0_irq_funcs = +{ + .set = smu_v11_0_set_irq_state, + .process = smu_v11_0_irq_process, +}; + +int smu_v11_0_register_irq_handler(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + struct amdgpu_irq_src *irq_src = &smu->irq_source; + int ret = 0; + + irq_src->num_types = 1; + irq_src->funcs = &smu_v11_0_irq_funcs; + + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, + THM_11_0__SRCID__THM_DIG_THERM_L2H, + irq_src); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, + THM_11_0__SRCID__THM_DIG_THERM_H2L, + irq_src); + if (ret) + return ret; + + /* Register CTF(GPIO_19) interrupt */ + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_ROM_SMUIO, + SMUIO_11_0__SRCID__SMUIO_GPIO19, + irq_src); + if (ret) + return ret; + + ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1, + 0xfe, + irq_src); + if (ret) + return ret; + + return ret; +} + +int smu_v11_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, + struct pp_smu_nv_clock_table *max_clocks) +{ + struct smu_table_context *table_context = &smu->smu_table; + struct smu_11_0_max_sustainable_clocks *sustainable_clocks = NULL; + + if (!max_clocks || !table_context->max_sustainable_clocks) + return -EINVAL; + + sustainable_clocks = table_context->max_sustainable_clocks; + + max_clocks->dcfClockInKhz = + (unsigned int) sustainable_clocks->dcef_clock * 1000; + max_clocks->displayClockInKhz = + (unsigned int) sustainable_clocks->display_clock * 1000; + max_clocks->phyClockInKhz = + (unsigned int) sustainable_clocks->phy_clock * 1000; + max_clocks->pixelClockInKhz = + (unsigned int) sustainable_clocks->pixel_clock * 1000; + max_clocks->uClockInKhz = + (unsigned int) sustainable_clocks->uclock * 1000; + max_clocks->socClockInKhz = + (unsigned int) sustainable_clocks->soc_clock * 1000; + max_clocks->dscClockInKhz = 0; + max_clocks->dppClockInKhz = 0; + max_clocks->fabricClockInKhz = 0; + + return 0; +} + +int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); + + return ret; +} + +static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v11_0_baco_seq baco_seq) +{ + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); +} + +bool smu_v11_0_baco_is_support(struct smu_context *smu) +{ + struct smu_baco_context *smu_baco = &smu->smu_baco; + bool baco_support; + + mutex_lock(&smu_baco->mutex); + baco_support = smu_baco->platform_support; + mutex_unlock(&smu_baco->mutex); + + if (!baco_support) + return false; + + /* Arcturus does not support this bit mask */ + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && + !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) + return false; + + return true; +} + +enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) +{ + struct smu_baco_context *smu_baco = &smu->smu_baco; + enum smu_baco_state baco_state; + + mutex_lock(&smu_baco->mutex); + baco_state = smu_baco->state; + mutex_unlock(&smu_baco->mutex); + + return baco_state; +} + +int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) +{ + struct smu_baco_context *smu_baco = &smu->smu_baco; + struct amdgpu_device *adev = smu->adev; + struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); + uint32_t data; + int ret = 0; + + if (smu_v11_0_baco_get_state(smu) == state) + return 0; + + mutex_lock(&smu_baco->mutex); + + if (state == SMU_BACO_STATE_ENTER) { + if (!ras || !ras->supported) { + data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); + data |= 0x80000000; + WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL); + } else { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL); + } + } else { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL); + if (ret) + goto out; + + /* clear vbios scratch 6 and 7 for coming asic reinit */ + WREG32(adev->bios_scratch_reg_offset + 6, 0); + WREG32(adev->bios_scratch_reg_offset + 7, 0); + } + if (ret) + goto out; + + smu_baco->state = state; +out: + mutex_unlock(&smu_baco->mutex); + return ret; +} + +int smu_v11_0_baco_enter(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + /* Arcturus does not need this audio workaround */ + if (adev->asic_type != CHIP_ARCTURUS) { + ret = smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); + if (ret) + return ret; + } + + ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); + if (ret) + return ret; + + msleep(10); + + return ret; +} + +int smu_v11_0_baco_exit(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT); + if (ret) + return ret; + + return ret; +} + +int smu_v11_0_mode1_reset(struct smu_context *smu) +{ + int ret = 0; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL); + if (!ret) + msleep(SMU11_MODE1_RESET_WAIT_TIME_IN_MS); + + return ret; +} + +int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t *min, uint32_t *max) +{ + int ret = 0, clk_id = 0; + uint32_t param = 0; + uint32_t clock_limit; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) { + ret = -EINVAL; + goto failed; + } + param = (clk_id & 0xffff) << 16; + + if (max) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max); + if (ret) + goto failed; + } + + if (min) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param, min); + if (ret) + goto failed; + } + +failed: + return ret; +} + +int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0, clk_id = 0; + uint32_t param; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, false); + + if (max > 0) { + param = (uint32_t)((clk_id << 16) | (max & 0xffff)); + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, + param, NULL); + if (ret) + goto out; + } + + if (min > 0) { + param = (uint32_t)((clk_id << 16) | (min & 0xffff)); + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq, + param, NULL); + if (ret) + goto out; + } + +out: + if (clk_type == SMU_GFXCLK) + amdgpu_gfx_off_ctrl(adev, true); + + return ret; +} + +int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t min, + uint32_t max) +{ + int ret = 0, clk_id = 0; + uint32_t param; + + if (min <= 0 && max <= 0) + return -EINVAL; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + if (max > 0) { + param = (uint32_t)((clk_id << 16) | (max & 0xffff)); + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq, + param, NULL); + if (ret) + return ret; + } + + if (min > 0) { + param = (uint32_t)((clk_id << 16) | (min & 0xffff)); + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, + param, NULL); + if (ret) + return ret; + } + + return ret; +} + +int smu_v11_0_set_performance_level(struct smu_context *smu, + enum amd_dpm_forced_level level) +{ + struct smu_11_0_dpm_context *dpm_context = + smu->smu_dpm.dpm_context; + struct smu_11_0_dpm_table *gfx_table = + &dpm_context->dpm_tables.gfx_table; + struct smu_11_0_dpm_table *mem_table = + &dpm_context->dpm_tables.uclk_table; + struct smu_11_0_dpm_table *soc_table = + &dpm_context->dpm_tables.soc_table; + struct smu_umd_pstate_table *pstate_table = + &smu->pstate_table; + struct amdgpu_device *adev = smu->adev; + uint32_t sclk_min = 0, sclk_max = 0; + uint32_t mclk_min = 0, mclk_max = 0; + uint32_t socclk_min = 0, socclk_max = 0; + int ret = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + sclk_min = sclk_max = gfx_table->max; + mclk_min = mclk_max = mem_table->max; + socclk_min = socclk_max = soc_table->max; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + sclk_min = sclk_max = gfx_table->min; + mclk_min = mclk_max = mem_table->min; + socclk_min = socclk_max = soc_table->min; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + sclk_min = gfx_table->min; + sclk_max = gfx_table->max; + mclk_min = mem_table->min; + mclk_max = mem_table->max; + socclk_min = soc_table->min; + socclk_max = soc_table->max; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard; + mclk_min = mclk_max = pstate_table->uclk_pstate.standard; + socclk_min = socclk_max = pstate_table->socclk_pstate.standard; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + sclk_min = sclk_max = pstate_table->gfxclk_pstate.min; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + mclk_min = mclk_max = pstate_table->uclk_pstate.min; + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak; + mclk_min = mclk_max = pstate_table->uclk_pstate.peak; + socclk_min = socclk_max = pstate_table->socclk_pstate.peak; + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + return 0; + default: + dev_err(adev->dev, "Invalid performance level %d\n", level); + return -EINVAL; + } + + /* + * Separate MCLK and SOCCLK soft min/max settings are not allowed + * on Arcturus. + */ + if (adev->asic_type == CHIP_ARCTURUS) { + mclk_min = mclk_max = 0; + socclk_min = socclk_max = 0; + } + + if (sclk_min && sclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_GFXCLK, + sclk_min, + sclk_max); + if (ret) + return ret; + } + + if (mclk_min && mclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_MCLK, + mclk_min, + mclk_max); + if (ret) + return ret; + } + + if (socclk_min && socclk_max) { + ret = smu_v11_0_set_soft_freq_limited_range(smu, + SMU_SOCCLK, + socclk_min, + socclk_max); + if (ret) + return ret; + } + + return ret; +} + +int smu_v11_0_set_power_source(struct smu_context *smu, + enum smu_power_src_type power_src) +{ + int pwr_source; + + pwr_source = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_PWR, + (uint32_t)power_src); + if (pwr_source < 0) + return -EINVAL; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_NotifyPowerSource, + pwr_source, + NULL); +} + +int smu_v11_0_get_dpm_freq_by_index(struct smu_context *smu, + enum smu_clk_type clk_type, + uint16_t level, + uint32_t *value) +{ + int ret = 0, clk_id = 0; + uint32_t param; + + if (!value) + return -EINVAL; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff)); + + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_GetDpmFreqByIndex, + param, + value); + if (ret) + return ret; + + /* + * BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM + * now, we un-support it + */ + *value = *value & 0x7fffffff; + + return ret; +} + +int smu_v11_0_get_dpm_level_count(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + return smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + 0xff, + value); +} + +int smu_v11_0_set_single_dpm_table(struct smu_context *smu, + enum smu_clk_type clk_type, + struct smu_11_0_dpm_table *single_dpm_table) +{ + int ret = 0; + uint32_t clk; + int i; + + ret = smu_v11_0_get_dpm_level_count(smu, + clk_type, + &single_dpm_table->count); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get dpm levels!\n", __func__); + return ret; + } + + for (i = 0; i < single_dpm_table->count; i++) { + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + i, + &clk); + if (ret) { + dev_err(smu->adev->dev, "[%s] failed to get dpm freq by index!\n", __func__); + return ret; + } + + single_dpm_table->dpm_levels[i].value = clk; + single_dpm_table->dpm_levels[i].enabled = true; + + if (i == 0) + single_dpm_table->min = clk; + else if (i == single_dpm_table->count - 1) + single_dpm_table->max = clk; + } + + return 0; +} + +int smu_v11_0_get_dpm_level_range(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min_value, + uint32_t *max_value) +{ + uint32_t level_count = 0; + int ret = 0; + + if (!min_value && !max_value) + return -EINVAL; + + if (min_value) { + /* by default, level 0 clock value as min value */ + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + 0, + min_value); + if (ret) + return ret; + } + + if (max_value) { + ret = smu_v11_0_get_dpm_level_count(smu, + clk_type, + &level_count); + if (ret) + return ret; + + ret = smu_v11_0_get_dpm_freq_by_index(smu, + clk_type, + level_count - 1, + max_value); + if (ret) + return ret; + } + + return ret; +} + +int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & + PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) + >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu) +{ + uint32_t width_level; + + width_level = smu_v11_0_get_current_pcie_link_width_level(smu); + if (width_level > LINK_WIDTH_MAX) + width_level = 0; + + return link_width[width_level]; +} + +int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & + PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) + >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; +} + +int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) +{ + uint32_t speed_level; + + speed_level = smu_v11_0_get_current_pcie_link_speed_level(smu); + if (speed_level > LINK_SPEED_MAX) + speed_level = 0; + + return link_speed[speed_level]; +} + +void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v1_0); + gpu_metrics->common_header.format_revision = 1; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile b/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile new file mode 100644 index 000000000000..67e53f7da3ce --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/Makefile @@ -0,0 +1,31 @@ +# +# Copyright 2020 Advanced Micro Devices, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU12_MGR = renoir_ppt.o \ + smu_v12_0.o + +AMD_SWSMU_SMU12MGR = $(addprefix $(AMD_SWSMU_PATH)/smu12/,$(SMU12_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_SWSMU_SMU12MGR) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c new file mode 100644 index 000000000000..186929c31e9e --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -0,0 +1,1085 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#define SWSMU_CODE_LAYER_L2 + +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "smu_v12_0_ppsmc.h" +#include "smu12_driver_if.h" +#include "smu_v12_0.h" +#include "renoir_ppt.h" +#include "smu_cmn.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +static struct cmn2asic_msg_mapping renoir_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(PowerUpGfx, PPSMC_MSG_PowerUpGfx, 1), + MSG_MAP(AllowGfxOff, PPSMC_MSG_EnableGfxOff, 1), + MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 1), + MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 1), + MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 1), + MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), + MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), + MSG_MAP(PowerDownSdma, PPSMC_MSG_PowerDownSdma, 1), + MSG_MAP(PowerUpSdma, PPSMC_MSG_PowerUpSdma, 1), + MSG_MAP(SetHardMinIspclkByFreq, PPSMC_MSG_SetHardMinIspclkByFreq, 1), + MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1), + MSG_MAP(Spare1, PPSMC_MSG_spare1, 1), + MSG_MAP(Spare2, PPSMC_MSG_spare2, 1), + MSG_MAP(SetAllowFclkSwitch, PPSMC_MSG_SetAllowFclkSwitch, 1), + MSG_MAP(SetMinVideoGfxclkFreq, PPSMC_MSG_SetMinVideoGfxclkFreq, 1), + MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 1), + MSG_MAP(SetCustomPolicy, PPSMC_MSG_SetCustomPolicy, 1), + MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 1), + MSG_MAP(NumOfDisplays, PPSMC_MSG_SetDisplayCount, 1), + MSG_MAP(QueryPowerLimit, PPSMC_MSG_QueryPowerLimit, 1), + MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), + MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), + MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), + MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1), + MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1), + MSG_MAP(SetGfxclkOverdriveByFreqVid, PPSMC_MSG_SetGfxclkOverdriveByFreqVid, 1), + MSG_MAP(SetHardMinDcfclkByFreq, PPSMC_MSG_SetHardMinDcfclkByFreq, 1), + MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1), + MSG_MAP(ControlIgpuATS, PPSMC_MSG_ControlIgpuATS, 1), + MSG_MAP(SetMinVideoFclkFreq, PPSMC_MSG_SetMinVideoFclkFreq, 1), + MSG_MAP(SetMinDeepSleepDcfclk, PPSMC_MSG_SetMinDeepSleepDcfclk, 1), + MSG_MAP(ForcePowerDownGfx, PPSMC_MSG_ForcePowerDownGfx, 1), + MSG_MAP(SetPhyclkVoltageByFreq, PPSMC_MSG_SetPhyclkVoltageByFreq, 1), + MSG_MAP(SetDppclkVoltageByFreq, PPSMC_MSG_SetDppclkVoltageByFreq, 1), + MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1), + MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 1), + MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1), + MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1), + MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxclkFrequency, 1), + MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxclkFrequency, 1), + MSG_MAP(SoftReset, PPSMC_MSG_SoftReset, 1), + MSG_MAP(SetGfxCGPG, PPSMC_MSG_SetGfxCGPG, 1), + MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), + MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1), + MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1), + MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1), + MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1), + MSG_MAP(PowerGateMmHub, PPSMC_MSG_PowerGateMmHub, 1), + MSG_MAP(UpdatePmeRestore, PPSMC_MSG_UpdatePmeRestore, 1), + MSG_MAP(GpuChangeState, PPSMC_MSG_GpuChangeState, 1), + MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1), + MSG_MAP(ForceGfxContentSave, PPSMC_MSG_ForceGfxContentSave, 1), + MSG_MAP(EnableTmdp48MHzRefclkPwrDown, PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown, 1), + MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), + MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), + MSG_MAP(PowerGateAtHub, PPSMC_MSG_PowerGateAtHub, 1), + MSG_MAP(SetSoftMinJpeg, PPSMC_MSG_SetSoftMinJpeg, 1), + MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1), +}; + +static struct cmn2asic_mapping renoir_clk_map[SMU_CLK_COUNT] = { + CLK_MAP(GFXCLK, CLOCK_GFXCLK), + CLK_MAP(SCLK, CLOCK_GFXCLK), + CLK_MAP(SOCCLK, CLOCK_SOCCLK), + CLK_MAP(UCLK, CLOCK_FCLK), + CLK_MAP(MCLK, CLOCK_FCLK), +}; + +static struct cmn2asic_mapping renoir_table_map[SMU_TABLE_COUNT] = { + TAB_MAP_VALID(WATERMARKS), + TAB_MAP_INVALID(CUSTOM_DPM), + TAB_MAP_VALID(DPMCLOCKS), + TAB_MAP_VALID(SMU_METRICS), +}; + +static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), + WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), +}; + +static int renoir_init_smc_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct smu_table *tables = smu_table->tables; + + SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), + PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); + + smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); + if (!smu_table->clocks_table) + goto err0_out; + + smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); + if (!smu_table->metrics_table) + goto err1_out; + smu_table->metrics_time = 0; + + smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); + if (!smu_table->watermarks_table) + goto err2_out; + + smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); + smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); + if (!smu_table->gpu_metrics_table) + goto err3_out; + + return 0; + +err3_out: + kfree(smu_table->watermarks_table); +err2_out: + kfree(smu_table->metrics_table); +err1_out: + kfree(smu_table->clocks_table); +err0_out: + return -ENOMEM; +} + +/** + * This interface just for getting uclk ultimate freq and should't introduce + * other likewise function result in overmuch callback. + */ +static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t dpm_level, uint32_t *freq) +{ + DpmClocks_t *clk_table = smu->smu_table.clocks_table; + + if (!clk_table || clk_type >= SMU_CLK_COUNT) + return -EINVAL; + + switch (clk_type) { + case SMU_SOCCLK: + if (dpm_level >= NUM_SOCCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->SocClocks[dpm_level].Freq; + break; + case SMU_MCLK: + if (dpm_level >= NUM_FCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->FClocks[dpm_level].Freq; + break; + case SMU_DCEFCLK: + if (dpm_level >= NUM_DCFCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->DcfClocks[dpm_level].Freq; + break; + case SMU_FCLK: + if (dpm_level >= NUM_FCLK_DPM_LEVELS) + return -EINVAL; + *freq = clk_table->FClocks[dpm_level].Freq; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int renoir_get_profiling_clk_mask(struct smu_context *smu, + enum amd_dpm_forced_level level, + uint32_t *sclk_mask, + uint32_t *mclk_mask, + uint32_t *soc_mask) +{ + + if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { + if (sclk_mask) + *sclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { + if (mclk_mask) + *mclk_mask = 0; + } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { + if(sclk_mask) + /* The sclk as gfxclk and has three level about max/min/current */ + *sclk_mask = 3 - 1; + + if(mclk_mask) + *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; + + if(soc_mask) + *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; + } + + return 0; +} + +static int renoir_get_dpm_ultimate_freq(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *min, + uint32_t *max) +{ + int ret = 0; + uint32_t mclk_mask, soc_mask; + uint32_t clock_limit; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) { + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + clock_limit = smu->smu_table.boot_values.uclk; + break; + case SMU_GFXCLK: + case SMU_SCLK: + clock_limit = smu->smu_table.boot_values.gfxclk; + break; + case SMU_SOCCLK: + clock_limit = smu->smu_table.boot_values.socclk; + break; + default: + clock_limit = 0; + break; + } + + /* clock in Mhz unit */ + if (min) + *min = clock_limit / 100; + if (max) + *max = clock_limit / 100; + + return 0; + } + + if (max) { + ret = renoir_get_profiling_clk_mask(smu, + AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, + NULL, + &mclk_mask, + &soc_mask); + if (ret) + goto failed; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n"); + goto failed; + } + break; + case SMU_UCLK: + case SMU_FCLK: + case SMU_MCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); + if (ret) + goto failed; + break; + case SMU_SOCCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, soc_mask, max); + if (ret) + goto failed; + break; + default: + ret = -EINVAL; + goto failed; + } + } + + if (min) { + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); + if (ret) { + dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n"); + goto failed; + } + break; + case SMU_UCLK: + case SMU_FCLK: + case SMU_MCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); + if (ret) + goto failed; + break; + case SMU_SOCCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); + if (ret) + goto failed; + break; + default: + ret = -EINVAL; + goto failed; + } + } +failed: + return ret; +} + +static int renoir_print_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, char *buf) +{ + int i, size = 0, ret = 0; + uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0; + SmuMetrics_t metrics; + bool cur_value_match_level = false; + + memset(&metrics, 0, sizeof(metrics)); + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + /* retirve table returned paramters unit is MHz */ + cur_value = metrics.ClockFrequency[CLOCK_GFXCLK]; + ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min, &max); + if (!ret) { + /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ + if (cur_value == max) + i = 2; + else if (cur_value == min) + i = 0; + else + i = 1; + + size += sprintf(buf + size, "0: %uMhz %s\n", min, + i == 0 ? "*" : ""); + size += sprintf(buf + size, "1: %uMhz %s\n", + i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK, + i == 1 ? "*" : ""); + size += sprintf(buf + size, "2: %uMhz %s\n", max, + i == 2 ? "*" : ""); + } + return size; + case SMU_SOCCLK: + count = NUM_SOCCLK_DPM_LEVELS; + cur_value = metrics.ClockFrequency[CLOCK_SOCCLK]; + break; + case SMU_MCLK: + count = NUM_MEMCLK_DPM_LEVELS; + cur_value = metrics.ClockFrequency[CLOCK_FCLK]; + break; + case SMU_DCEFCLK: + count = NUM_DCFCLK_DPM_LEVELS; + cur_value = metrics.ClockFrequency[CLOCK_DCFCLK]; + break; + case SMU_FCLK: + count = NUM_FCLK_DPM_LEVELS; + cur_value = metrics.ClockFrequency[CLOCK_FCLK]; + break; + default: + return -EINVAL; + } + + for (i = 0; i < count; i++) { + ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value); + if (ret) + return ret; + if (!value) + continue; + size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, + cur_value == value ? "*" : ""); + if (cur_value == value) + cur_value_match_level = true; + } + + if (!cur_value_match_level) + size += sprintf(buf + size, " %uMhz *\n", cur_value); + + return size; +} + +static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu) +{ + enum amd_pm_state_type pm_type; + struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); + + if (!smu_dpm_ctx->dpm_context || + !smu_dpm_ctx->dpm_current_power_state) + return -EINVAL; + + switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) { + case SMU_STATE_UI_LABEL_BATTERY: + pm_type = POWER_STATE_TYPE_BATTERY; + break; + case SMU_STATE_UI_LABEL_BALLANCED: + pm_type = POWER_STATE_TYPE_BALANCED; + break; + case SMU_STATE_UI_LABEL_PERFORMANCE: + pm_type = POWER_STATE_TYPE_PERFORMANCE; + break; + default: + if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) + pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; + else + pm_type = POWER_STATE_TYPE_DEFAULT; + break; + } + + return pm_type; +} + +static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + /* vcn dpm on is a prerequisite for vcn power gate messages */ + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); + if (ret) + return ret; + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); + if (ret) + return ret; + } + } + + return ret; +} + +static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) +{ + int ret = 0; + + if (enable) { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); + if (ret) + return ret; + } + } else { + if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); + if (ret) + return ret; + } + } + + return ret; +} + +static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, + enum smu_clk_type clk_type, + uint32_t *value) +{ + int ret = 0, clk_id = 0; + SmuMetrics_t metrics; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + clk_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_CLK, + clk_type); + if (clk_id < 0) + return clk_id; + + *value = metrics.ClockFrequency[clk_id]; + + return ret; +} + +static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) +{ + int ret = 0, i = 0; + uint32_t min_freq, max_freq, force_freq; + enum smu_clk_type clk_type; + + enum smu_clk_type clks[] = { + SMU_GFXCLK, + SMU_MCLK, + SMU_SOCCLK, + }; + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + clk_type = clks[i]; + ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); + if (ret) + return ret; + + force_freq = highest ? max_freq : min_freq; + ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq); + if (ret) + return ret; + } + + return ret; +} + +static int renoir_unforce_dpm_levels(struct smu_context *smu) { + + int ret = 0, i = 0; + uint32_t min_freq, max_freq; + enum smu_clk_type clk_type; + + struct clk_feature_map { + enum smu_clk_type clk_type; + uint32_t feature; + } clk_feature_map[] = { + {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT}, + {SMU_MCLK, SMU_FEATURE_DPM_UCLK_BIT}, + {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, + }; + + for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { + if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature)) + continue; + + clk_type = clk_feature_map[i].clk_type; + + ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); + if (ret) + return ret; + + ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); + if (ret) + return ret; + } + + return ret; +} + +static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + *value = (metrics.GfxTemperature / 100) * + SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return 0; +} + +static int renoir_get_current_activity_percent(struct smu_context *smu, + enum amd_pp_sensors sensor, + uint32_t *value) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + switch (sensor) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + *value = metrics.AverageGfxActivity / 100; + break; + default: + dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); + return -EINVAL; + } + + return 0; +} + +/** + * This interface get dpm clock table for dc + */ +static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) +{ + DpmClocks_t *table = smu->smu_table.clocks_table; + int i; + + if (!clock_table || !table) + return -EINVAL; + + for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) { + clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq; + clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol; + } + + for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { + clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq; + clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol; + } + + for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { + clock_table->FClocks[i].Freq = table->FClocks[i].Freq; + clock_table->FClocks[i].Vol = table->FClocks[i].Vol; + } + + for (i = 0; i< NUM_MEMCLK_DPM_LEVELS; i++) { + clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq; + clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol; + } + + return 0; +} + +static int renoir_force_clk_levels(struct smu_context *smu, + enum smu_clk_type clk_type, uint32_t mask) +{ + + int ret = 0 ; + uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; + + soft_min_level = mask ? (ffs(mask) - 1) : 0; + soft_max_level = mask ? (fls(mask) - 1) : 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + if (soft_min_level > 2 || soft_max_level > 2) { + dev_info(smu->adev->dev, "Currently sclk only support 3 levels on APU\n"); + return -EINVAL; + } + + ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min_freq, &max_freq); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, + soft_max_level == 0 ? min_freq : + soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq, + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, + soft_min_level == 2 ? max_freq : + soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq, + NULL); + if (ret) + return ret; + break; + case SMU_SOCCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); + if (ret) + return ret; + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq, NULL); + if (ret) + return ret; + break; + case SMU_MCLK: + case SMU_FCLK: + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); + if (ret) + return ret; + ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq, NULL); + if (ret) + return ret; + break; + default: + break; + } + + return ret; +} + +static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) +{ + int workload_type, ret; + uint32_t profile_mode = input[size]; + + if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { + dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); + return -EINVAL; + } + + /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + profile_mode); + if (workload_type < 0) { + /* + * TODO: If some case need switch to powersave/default power mode + * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving. + */ + dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode); + return -EINVAL; + } + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, + 1 << workload_type, + NULL); + if (ret) { + dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type); + return ret; + } + + smu->power_profile_mode = profile_mode; + + return 0; +} + +static int renoir_set_peak_clock_by_device(struct smu_context *smu) +{ + int ret = 0; + uint32_t sclk_freq = 0, uclk_freq = 0; + + ret = renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_freq); + if (ret) + return ret; + + ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq); + if (ret) + return ret; + + ret = renoir_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &uclk_freq); + if (ret) + return ret; + + ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq); + if (ret) + return ret; + + return ret; +} + +static int renoir_set_performance_level(struct smu_context *smu, + enum amd_dpm_forced_level level) +{ + int ret = 0; + uint32_t sclk_mask, mclk_mask, soc_mask; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = renoir_force_dpm_limit_value(smu, true); + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = renoir_force_dpm_limit_value(smu, false); + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: + ret = renoir_unforce_dpm_levels(smu); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: + case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: + ret = renoir_get_profiling_clk_mask(smu, level, + &sclk_mask, + &mclk_mask, + &soc_mask); + if (ret) + return ret; + renoir_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask); + renoir_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask); + renoir_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); + break; + case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: + ret = renoir_set_peak_clock_by_device(smu); + break; + case AMD_DPM_FORCED_LEVEL_MANUAL: + case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: + default: + break; + } + return ret; +} + +/* save watermark settings into pplib smu structure, + * also pass data to smu controller + */ +static int renoir_set_watermarks_table( + struct smu_context *smu, + struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) +{ + Watermarks_t *table = smu->smu_table.watermarks_table; + int ret = 0; + int i; + + if (clock_ranges) { + if (clock_ranges->num_wm_dmif_sets > 4 || + clock_ranges->num_wm_mcif_sets > 4) + return -EINVAL; + + /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ + for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { + table->WatermarkRow[WM_DCFCLK][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MinMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].MaxMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz)); + table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t) + clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; + } + + for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { + table->WatermarkRow[WM_SOCCLK][i].MinClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MaxClock = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MinMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].MaxMclk = + cpu_to_le16((uint16_t) + (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz)); + table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t) + clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; + } + + smu->watermarks_bitmap |= WATERMARKS_EXIST; + } + + /* pass data to smu controller */ + if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && + !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { + ret = smu_cmn_write_watermarks_table(smu); + if (ret) { + dev_err(smu->adev->dev, "Failed to update WMTABLE!"); + return ret; + } + smu->watermarks_bitmap |= WATERMARKS_LOADED; + } + + return 0; +} + +static int renoir_get_power_profile_mode(struct smu_context *smu, + char *buf) +{ + static const char *profile_name[] = { + "BOOTUP_DEFAULT", + "3D_FULL_SCREEN", + "POWER_SAVING", + "VIDEO", + "VR", + "COMPUTE", + "CUSTOM"}; + uint32_t i, size = 0; + int16_t workload_type = 0; + + if (!buf) + return -EINVAL; + + for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { + /* + * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT + * Not all profile modes are supported on arcturus. + */ + workload_type = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_WORKLOAD, + i); + if (workload_type < 0) + continue; + + size += sprintf(buf + size, "%2d %14s%s\n", + i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); + } + + return size; +} + +static int renoir_read_sensor(struct smu_context *smu, + enum amd_pp_sensors sensor, + void *data, uint32_t *size) +{ + int ret = 0; + + if (!data || !size) + return -EINVAL; + + mutex_lock(&smu->sensor_lock); + switch (sensor) { + case AMDGPU_PP_SENSOR_GPU_LOAD: + ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GPU_TEMP: + ret = renoir_get_gpu_temperature(smu, (uint32_t *)data); + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); + *(uint32_t *)data *= 100; + *size = 4; + break; + default: + ret = -EOPNOTSUPP; + break; + } + mutex_unlock(&smu->sensor_lock); + + return ret; +} + +static bool renoir_is_dpm_running(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + + /* + * Until now, the pmfw hasn't exported the interface of SMU + * feature mask to APU SKU so just force on all the feature + * at early initial stage. + */ + if (adev->in_suspend) + return false; + else + return true; + +} + +static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, + void **table) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct gpu_metrics_v2_0 *gpu_metrics = + (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; + SmuMetrics_t metrics; + int ret = 0; + + ret = smu_cmn_get_metrics_table(smu, &metrics, true); + if (ret) + return ret; + + smu_v12_0_init_gpu_metrics_v2_0(gpu_metrics); + + gpu_metrics->temperature_gfx = metrics.GfxTemperature; + gpu_metrics->temperature_soc = metrics.SocTemperature; + memcpy(&gpu_metrics->temperature_core[0], + &metrics.CoreTemperature[0], + sizeof(uint16_t) * 8); + gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; + gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; + + gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; + gpu_metrics->average_mm_activity = metrics.AverageUvdActivity; + + gpu_metrics->average_socket_power = metrics.CurrentSocketPower; + gpu_metrics->average_cpu_power = metrics.Power[0]; + gpu_metrics->average_soc_power = metrics.Power[1]; + memcpy(&gpu_metrics->average_core_power[0], + &metrics.CorePower[0], + sizeof(uint16_t) * 8); + + gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; + gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; + gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency; + gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency; + + gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK]; + gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK]; + gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK]; + gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK]; + gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK]; + gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK]; + memcpy(&gpu_metrics->current_coreclk[0], + &metrics.CoreFrequency[0], + sizeof(uint16_t) * 8); + gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; + gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; + + gpu_metrics->throttle_status = metrics.ThrottlerStatus; + + gpu_metrics->fan_pwm = metrics.FanPwm; + + *table = (void *)gpu_metrics; + + return sizeof(struct gpu_metrics_v2_0); +} + +static const struct pptable_funcs renoir_ppt_funcs = { + .set_power_state = NULL, + .print_clk_levels = renoir_print_clk_levels, + .get_current_power_state = renoir_get_current_power_state, + .dpm_set_vcn_enable = renoir_dpm_set_vcn_enable, + .dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable, + .force_clk_levels = renoir_force_clk_levels, + .set_power_profile_mode = renoir_set_power_profile_mode, + .set_performance_level = renoir_set_performance_level, + .get_dpm_clock_table = renoir_get_dpm_clock_table, + .set_watermarks_table = renoir_set_watermarks_table, + .get_power_profile_mode = renoir_get_power_profile_mode, + .read_sensor = renoir_read_sensor, + .check_fw_status = smu_v12_0_check_fw_status, + .check_fw_version = smu_v12_0_check_fw_version, + .powergate_sdma = smu_v12_0_powergate_sdma, + .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, + .send_smc_msg = smu_cmn_send_smc_msg, + .set_gfx_cgpg = smu_v12_0_set_gfx_cgpg, + .gfx_off_control = smu_v12_0_gfx_off_control, + .get_gfx_off_status = smu_v12_0_get_gfxoff_status, + .init_smc_tables = renoir_init_smc_tables, + .fini_smc_tables = smu_v12_0_fini_smc_tables, + .set_default_dpm_table = smu_v12_0_set_default_dpm_tables, + .get_enabled_mask = smu_cmn_get_enabled_mask, + .feature_is_enabled = smu_cmn_feature_is_enabled, + .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, + .get_dpm_ultimate_freq = renoir_get_dpm_ultimate_freq, + .mode2_reset = smu_v12_0_mode2_reset, + .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range, + .set_driver_table_location = smu_v12_0_set_driver_table_location, + .is_dpm_running = renoir_is_dpm_running, + .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, + .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, + .get_gpu_metrics = renoir_get_gpu_metrics, +}; + +void renoir_set_ppt_funcs(struct smu_context *smu) +{ + smu->ppt_funcs = &renoir_ppt_funcs; + smu->message_map = renoir_message_map; + smu->clock_map = renoir_clk_map; + smu->table_map = renoir_table_map; + smu->workload_map = renoir_workload_map; + smu->smc_driver_if_version = SMU12_DRIVER_IF_VERSION; + smu->is_apu = true; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h new file mode 100644 index 000000000000..8c3f004cdf8d --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.h @@ -0,0 +1,33 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ +#ifndef __RENOIR_PPT_H__ +#define __RENOIR_PPT_H__ + +extern void renoir_set_ppt_funcs(struct smu_context *smu); + +/* UMD PState Renoir Msg Parameters in MHz */ +#define RENOIR_UMD_PSTATE_GFXCLK 700 +#define RENOIR_UMD_PSTATE_SOCCLK 678 +#define RENOIR_UMD_PSTATE_FCLK 800 + +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c new file mode 100644 index 000000000000..660f403d5770 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/smu_v12_0.c @@ -0,0 +1,288 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#define SWSMU_CODE_LAYER_L3 + +#include +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "atomfirmware.h" +#include "amdgpu_atomfirmware.h" +#include "smu_v12_0.h" +#include "soc15_common.h" +#include "atom.h" +#include "smu_cmn.h" + +#include "asic_reg/mp/mp_12_0_0_offset.h" +#include "asic_reg/mp/mp_12_0_0_sh_mask.h" +#include "asic_reg/smuio/smuio_12_0_0_offset.h" +#include "asic_reg/smuio/smuio_12_0_0_sh_mask.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +// because some SMU12 based ASICs use older ip offset tables +// we should undefine this register from the smuio12 header +// to prevent confusion down the road +#undef mmPWR_MISC_CNTL_STATUS + +#define smnMP1_FIRMWARE_FLAGS 0x3010024 + +int smu_v12_0_check_fw_status(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t mp1_fw_flags; + + mp1_fw_flags = RREG32_PCIE(MP1_Public | + (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); + + if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> + MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) + return 0; + + return -EIO; +} + +int smu_v12_0_check_fw_version(struct smu_context *smu) +{ + uint32_t if_version = 0xff, smu_version = 0xff; + uint16_t smu_major; + uint8_t smu_minor, smu_debug; + int ret = 0; + + ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); + if (ret) + return ret; + + smu_major = (smu_version >> 16) & 0xffff; + smu_minor = (smu_version >> 8) & 0xff; + smu_debug = (smu_version >> 0) & 0xff; + + /* + * 1. if_version mismatch is not critical as our fw is designed + * to be backward compatible. + * 2. New fw usually brings some optimizations. But that's visible + * only on the paired driver. + * Considering above, we just leave user a warning message instead + * of halt driver loading. + */ + if (if_version != smu->smc_driver_if_version) { + dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " + "smu fw version = 0x%08x (%d.%d.%d)\n", + smu->smc_driver_if_version, if_version, + smu_version, smu_major, smu_minor, smu_debug); + dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); + } + + return ret; +} + +int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate) +{ + if (!smu->is_apu) + return 0; + + if (gate) + return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownSdma, NULL); + else + return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpSdma, NULL); +} + +int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) +{ + if (!(smu->adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) + return 0; + + return smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetGfxCGPG, + enable ? 1 : 0, + NULL); +} + +/** + * smu_v12_0_get_gfxoff_status - get gfxoff status + * + * @smu: amdgpu_device pointer + * + * This function will be used to get gfxoff status + * + * Returns 0=GFXOFF(default). + * Returns 1=Transition out of GFX State. + * Returns 2=Not in GFXOFF. + * Returns 3=Transition into GFXOFF. + */ +uint32_t smu_v12_0_get_gfxoff_status(struct smu_context *smu) +{ + uint32_t reg; + uint32_t gfxOff_Status = 0; + struct amdgpu_device *adev = smu->adev; + + reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_GFX_MISC_CNTL); + gfxOff_Status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK) + >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT; + + return gfxOff_Status; +} + +int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable) +{ + int ret = 0, timeout = 500; + + if (enable) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); + + } else { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); + + /* confirm gfx is back to "on" state, timeout is 0.5 second */ + while (!(smu_v12_0_get_gfxoff_status(smu) == 2)) { + msleep(1); + timeout--; + if (timeout == 0) { + DRM_ERROR("disable gfxoff timeout and failed!\n"); + break; + } + } + } + + return ret; +} + +int smu_v12_0_fini_smc_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + + kfree(smu_table->clocks_table); + smu_table->clocks_table = NULL; + + kfree(smu_table->metrics_table); + smu_table->metrics_table = NULL; + + kfree(smu_table->watermarks_table); + smu_table->watermarks_table = NULL; + + return 0; +} + +int smu_v12_0_set_default_dpm_tables(struct smu_context *smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + + return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); +} + +int smu_v12_0_mode2_reset(struct smu_context *smu){ + return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2, NULL); +} + +int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, + uint32_t min, uint32_t max) +{ + int ret = 0; + + if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) + return 0; + + switch (clk_type) { + case SMU_GFXCLK: + case SMU_SCLK: + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min, NULL); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max, NULL); + if (ret) + return ret; + break; + case SMU_FCLK: + case SMU_MCLK: + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min, NULL); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max, NULL); + if (ret) + return ret; + break; + case SMU_SOCCLK: + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min, NULL); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max, NULL); + if (ret) + return ret; + break; + case SMU_VCLK: + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min, NULL); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max, NULL); + if (ret) + return ret; + break; + default: + return -EINVAL; + } + + return ret; +} + +int smu_v12_0_set_driver_table_location(struct smu_context *smu) +{ + struct smu_table *driver_table = &smu->smu_table.driver_table; + int ret = 0; + + if (driver_table->mc_address) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetDriverDramAddrHigh, + upper_32_bits(driver_table->mc_address), + NULL); + if (!ret) + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_SetDriverDramAddrLow, + lower_32_bits(driver_table->mc_address), + NULL); + } + + return ret; +} + +void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics) +{ + memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0)); + + gpu_metrics->common_header.structure_size = + sizeof(struct gpu_metrics_v2_0); + gpu_metrics->common_header.format_revision = 2; + gpu_metrics->common_header.content_revision = 0; + + gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c new file mode 100644 index 000000000000..a58ea08cd115 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c @@ -0,0 +1,678 @@ +/* + * 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. + */ + +#define SWSMU_CODE_LAYER_L4 + +#include "amdgpu.h" +#include "amdgpu_smu.h" +#include "smu_cmn.h" +#include "soc15_common.h" + +/* + * DO NOT use these for err/warn/info/debug messages. + * Use dev_err, dev_warn, dev_info and dev_dbg instead. + * They are more MGPU friendly. + */ +#undef pr_err +#undef pr_warn +#undef pr_info +#undef pr_debug + +/* + * Although these are defined in each ASIC's specific header file. + * They share the same definitions and values. That makes common + * APIs for SMC messages issuing for all ASICs possible. + */ +#define mmMP1_SMN_C2PMSG_66 0x0282 +#define mmMP1_SMN_C2PMSG_66_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_82 0x0292 +#define mmMP1_SMN_C2PMSG_82_BASE_IDX 0 + +#define mmMP1_SMN_C2PMSG_90 0x029a +#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0 + +#define MP1_C2PMSG_90__CONTENT_MASK 0xFFFFFFFFL + +#undef __SMU_DUMMY_MAP +#define __SMU_DUMMY_MAP(type) #type +static const char* __smu_message_names[] = { + SMU_MESSAGE_TYPES +}; + +static const char *smu_get_message_name(struct smu_context *smu, + enum smu_message_type type) +{ + if (type < 0 || type >= SMU_MSG_MAX_COUNT) + return "unknown smu message"; + + return __smu_message_names[type]; +} + +static void smu_cmn_send_msg_without_waiting(struct smu_context *smu, + uint16_t msg) +{ + struct amdgpu_device *adev = smu->adev; + + WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); +} + +static void smu_cmn_read_arg(struct smu_context *smu, + uint32_t *arg) +{ + struct amdgpu_device *adev = smu->adev; + + *arg = RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_82); +} + +static int smu_cmn_wait_for_response(struct smu_context *smu) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t cur_value, i, timeout = adev->usec_timeout * 10; + + for (i = 0; i < timeout; i++) { + cur_value = RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90); + if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0) + return cur_value == 0x1 ? 0 : -EIO; + + udelay(1); + } + + /* timeout means wrong logic */ + if (i == timeout) + return -ETIME; + + return RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90) == 0x1 ? 0 : -EIO; +} + +int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, + enum smu_message_type msg, + uint32_t param, + uint32_t *read_arg) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0, index = 0; + + index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_MSG, + msg); + if (index < 0) + return index == -EACCES ? 0 : index; + + mutex_lock(&smu->message_lock); + ret = smu_cmn_wait_for_response(smu); + if (ret) { + dev_err(adev->dev, "Msg issuing pre-check failed and " + "SMU may be not in the right state!\n"); + goto out; + } + + WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); + + WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_82, param); + + smu_cmn_send_msg_without_waiting(smu, (uint16_t)index); + + ret = smu_cmn_wait_for_response(smu); + if (ret) { + dev_err(adev->dev, "failed send message: %10s (%d) \tparam: 0x%08x response %#x\n", + smu_get_message_name(smu, msg), index, param, ret); + goto out; + } + + if (read_arg) + smu_cmn_read_arg(smu, read_arg); + +out: + mutex_unlock(&smu->message_lock); + return ret; +} + +int smu_cmn_send_smc_msg(struct smu_context *smu, + enum smu_message_type msg, + uint32_t *read_arg) +{ + return smu_cmn_send_smc_msg_with_param(smu, + msg, + 0, + read_arg); +} + +int smu_cmn_to_asic_specific_index(struct smu_context *smu, + enum smu_cmn2asic_mapping_type type, + uint32_t index) +{ + struct cmn2asic_msg_mapping msg_mapping; + struct cmn2asic_mapping mapping; + + switch (type) { + case CMN2ASIC_MAPPING_MSG: + if (index >= SMU_MSG_MAX_COUNT || + !smu->message_map) + return -EINVAL; + + msg_mapping = smu->message_map[index]; + if (!msg_mapping.valid_mapping) + return -EINVAL; + + if (amdgpu_sriov_vf(smu->adev) && + !msg_mapping.valid_in_vf) + return -EACCES; + + return msg_mapping.map_to; + + case CMN2ASIC_MAPPING_CLK: + if (index >= SMU_CLK_COUNT || + !smu->clock_map) + return -EINVAL; + + mapping = smu->clock_map[index]; + if (!mapping.valid_mapping) + return -EINVAL; + + return mapping.map_to; + + case CMN2ASIC_MAPPING_FEATURE: + if (index >= SMU_FEATURE_COUNT || + !smu->feature_map) + return -EINVAL; + + mapping = smu->feature_map[index]; + if (!mapping.valid_mapping) + return -EINVAL; + + return mapping.map_to; + + case CMN2ASIC_MAPPING_TABLE: + if (index >= SMU_TABLE_COUNT || + !smu->table_map) + return -EINVAL; + + mapping = smu->table_map[index]; + if (!mapping.valid_mapping) + return -EINVAL; + + return mapping.map_to; + + case CMN2ASIC_MAPPING_PWR: + if (index >= SMU_POWER_SOURCE_COUNT || + !smu->pwr_src_map) + return -EINVAL; + + mapping = smu->pwr_src_map[index]; + if (!mapping.valid_mapping) + return -EINVAL; + + return mapping.map_to; + + case CMN2ASIC_MAPPING_WORKLOAD: + if (index > PP_SMC_POWER_PROFILE_CUSTOM || + !smu->workload_map) + return -EINVAL; + + mapping = smu->workload_map[index]; + if (!mapping.valid_mapping) + return -EINVAL; + + return mapping.map_to; + + default: + return -EINVAL; + } +} + +int smu_cmn_feature_is_supported(struct smu_context *smu, + enum smu_feature_mask mask) +{ + struct smu_feature *feature = &smu->smu_feature; + int feature_id; + int ret = 0; + + feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + mask); + if (feature_id < 0) + return 0; + + WARN_ON(feature_id > feature->feature_num); + + mutex_lock(&feature->mutex); + ret = test_bit(feature_id, feature->supported); + mutex_unlock(&feature->mutex); + + return ret; +} + +int smu_cmn_feature_is_enabled(struct smu_context *smu, + enum smu_feature_mask mask) +{ + struct smu_feature *feature = &smu->smu_feature; + int feature_id; + int ret = 0; + + if (smu->is_apu) + return 1; + feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + mask); + if (feature_id < 0) + return 0; + + WARN_ON(feature_id > feature->feature_num); + + mutex_lock(&feature->mutex); + ret = test_bit(feature_id, feature->enabled); + mutex_unlock(&feature->mutex); + + return ret; +} + +bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, + enum smu_clk_type clk_type) +{ + enum smu_feature_mask feature_id = 0; + + switch (clk_type) { + case SMU_MCLK: + case SMU_UCLK: + feature_id = SMU_FEATURE_DPM_UCLK_BIT; + break; + case SMU_GFXCLK: + case SMU_SCLK: + feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; + break; + case SMU_SOCCLK: + feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; + break; + default: + return true; + } + + if (!smu_cmn_feature_is_enabled(smu, feature_id)) + return false; + + return true; +} + +int smu_cmn_get_enabled_mask(struct smu_context *smu, + uint32_t *feature_mask, + uint32_t num) +{ + uint32_t feature_mask_high = 0, feature_mask_low = 0; + struct smu_feature *feature = &smu->smu_feature; + int ret = 0; + + if (!feature_mask || num < 2) + return -EINVAL; + + if (bitmap_empty(feature->enabled, feature->feature_num)) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &feature_mask_high); + if (ret) + return ret; + + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow, &feature_mask_low); + if (ret) + return ret; + + feature_mask[0] = feature_mask_low; + feature_mask[1] = feature_mask_high; + } else { + bitmap_copy((unsigned long *)feature_mask, feature->enabled, + feature->feature_num); + } + + return ret; +} + +static int smu_cmn_feature_update_enable_state(struct smu_context *smu, + uint64_t feature_mask, + bool enabled) +{ + struct smu_feature *feature = &smu->smu_feature; + int ret = 0; + + if (enabled) { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_EnableSmuFeaturesLow, + lower_32_bits(feature_mask), + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_EnableSmuFeaturesHigh, + upper_32_bits(feature_mask), + NULL); + if (ret) + return ret; + } else { + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_DisableSmuFeaturesLow, + lower_32_bits(feature_mask), + NULL); + if (ret) + return ret; + ret = smu_cmn_send_smc_msg_with_param(smu, + SMU_MSG_DisableSmuFeaturesHigh, + upper_32_bits(feature_mask), + NULL); + if (ret) + return ret; + } + + mutex_lock(&feature->mutex); + if (enabled) + bitmap_or(feature->enabled, feature->enabled, + (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); + else + bitmap_andnot(feature->enabled, feature->enabled, + (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); + mutex_unlock(&feature->mutex); + + return ret; +} + +int smu_cmn_feature_set_enabled(struct smu_context *smu, + enum smu_feature_mask mask, + bool enable) +{ + struct smu_feature *feature = &smu->smu_feature; + int feature_id; + + feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + mask); + if (feature_id < 0) + return -EINVAL; + + WARN_ON(feature_id > feature->feature_num); + + return smu_cmn_feature_update_enable_state(smu, + 1ULL << feature_id, + enable); +} + +#undef __SMU_DUMMY_MAP +#define __SMU_DUMMY_MAP(fea) #fea +static const char* __smu_feature_names[] = { + SMU_FEATURE_MASKS +}; + +static const char *smu_get_feature_name(struct smu_context *smu, + enum smu_feature_mask feature) +{ + if (feature < 0 || feature >= SMU_FEATURE_COUNT) + return "unknown smu feature"; + return __smu_feature_names[feature]; +} + +size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, + char *buf) +{ + uint32_t feature_mask[2] = { 0 }; + int32_t feature_index = 0; + uint32_t count = 0; + uint32_t sort_feature[SMU_FEATURE_COUNT]; + uint64_t hw_feature_count = 0; + size_t size = 0; + int ret = 0, i; + + ret = smu_cmn_get_enabled_mask(smu, + feature_mask, + 2); + if (ret) + return 0; + + size = sprintf(buf + size, "features high: 0x%08x low: 0x%08x\n", + feature_mask[1], feature_mask[0]); + + for (i = 0; i < SMU_FEATURE_COUNT; i++) { + feature_index = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + i); + if (feature_index < 0) + continue; + sort_feature[feature_index] = i; + hw_feature_count++; + } + + for (i = 0; i < hw_feature_count; i++) { + size += sprintf(buf + size, "%02d. %-20s (%2d) : %s\n", + count++, + smu_get_feature_name(smu, sort_feature[i]), + i, + !!smu_cmn_feature_is_enabled(smu, sort_feature[i]) ? + "enabled" : "disabled"); + } + + return size; +} + +int smu_cmn_set_pp_feature_mask(struct smu_context *smu, + uint64_t new_mask) +{ + int ret = 0; + uint32_t feature_mask[2] = { 0 }; + uint64_t feature_2_enabled = 0; + uint64_t feature_2_disabled = 0; + uint64_t feature_enables = 0; + + ret = smu_cmn_get_enabled_mask(smu, + feature_mask, + 2); + if (ret) + return ret; + + feature_enables = ((uint64_t)feature_mask[1] << 32 | + (uint64_t)feature_mask[0]); + + feature_2_enabled = ~feature_enables & new_mask; + feature_2_disabled = feature_enables & ~new_mask; + + if (feature_2_enabled) { + ret = smu_cmn_feature_update_enable_state(smu, + feature_2_enabled, + true); + if (ret) + return ret; + } + if (feature_2_disabled) { + ret = smu_cmn_feature_update_enable_state(smu, + feature_2_disabled, + false); + if (ret) + return ret; + } + + return ret; +} + +int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, + enum smu_feature_mask mask) +{ + uint64_t features_to_disable = U64_MAX; + int skipped_feature_id; + + skipped_feature_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_FEATURE, + mask); + if (skipped_feature_id < 0) + return -EINVAL; + + features_to_disable &= ~(1ULL << skipped_feature_id); + + return smu_cmn_feature_update_enable_state(smu, + features_to_disable, + 0); +} + +int smu_cmn_get_smc_version(struct smu_context *smu, + uint32_t *if_version, + uint32_t *smu_version) +{ + int ret = 0; + + if (!if_version && !smu_version) + return -EINVAL; + + if (smu->smc_fw_if_version && smu->smc_fw_version) + { + if (if_version) + *if_version = smu->smc_fw_if_version; + + if (smu_version) + *smu_version = smu->smc_fw_version; + + return 0; + } + + if (if_version) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version); + if (ret) + return ret; + + smu->smc_fw_if_version = *if_version; + } + + if (smu_version) { + ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version); + if (ret) + return ret; + + smu->smc_fw_version = *smu_version; + } + + return ret; +} + +int smu_cmn_update_table(struct smu_context *smu, + enum smu_table_id table_index, + int argument, + void *table_data, + bool drv2smu) +{ + struct smu_table_context *smu_table = &smu->smu_table; + struct amdgpu_device *adev = smu->adev; + struct smu_table *table = &smu_table->driver_table; + int table_id = smu_cmn_to_asic_specific_index(smu, + CMN2ASIC_MAPPING_TABLE, + table_index); + uint32_t table_size; + int ret = 0; + if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0) + return -EINVAL; + + table_size = smu_table->tables[table_index].size; + + if (drv2smu) { + memcpy(table->cpu_addr, table_data, table_size); + /* + * Flush hdp cache: to guard the content seen by + * GPU is consitent with CPU. + */ + amdgpu_asic_flush_hdp(adev, NULL); + } + + ret = smu_cmn_send_smc_msg_with_param(smu, drv2smu ? + SMU_MSG_TransferTableDram2Smu : + SMU_MSG_TransferTableSmu2Dram, + table_id | ((argument & 0xFFFF) << 16), + NULL); + if (ret) + return ret; + + if (!drv2smu) { + amdgpu_asic_flush_hdp(adev, NULL); + memcpy(table_data, table->cpu_addr, table_size); + } + + return 0; +} + +int smu_cmn_write_watermarks_table(struct smu_context *smu) +{ + void *watermarks_table = smu->smu_table.watermarks_table; + + if (!watermarks_table) + return -EINVAL; + + return smu_cmn_update_table(smu, + SMU_TABLE_WATERMARKS, + 0, + watermarks_table, + true); +} + +int smu_cmn_write_pptable(struct smu_context *smu) +{ + void *pptable = smu->smu_table.driver_pptable; + + return smu_cmn_update_table(smu, + SMU_TABLE_PPTABLE, + 0, + pptable, + true); +} + +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + struct smu_table_context *smu_table= &smu->smu_table; + uint32_t table_size = + smu_table->tables[SMU_TABLE_SMU_METRICS].size; + int ret = 0; + + if (bypass_cache || + !smu_table->metrics_time || + time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { + ret = smu_cmn_update_table(smu, + SMU_TABLE_SMU_METRICS, + 0, + smu_table->metrics_table, + false); + if (ret) { + dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); + return ret; + } + smu_table->metrics_time = jiffies; + } + + if (metrics_table) + memcpy(metrics_table, smu_table->metrics_table, table_size); + + return 0; +} + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache) +{ + int ret = 0; + + mutex_lock(&smu->metrics_lock); + ret = smu_cmn_get_metrics_table_locked(smu, + metrics_table, + bypass_cache); + mutex_unlock(&smu->metrics_lock); + + return ret; +} diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h new file mode 100644 index 000000000000..6d00ad740c27 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h @@ -0,0 +1,91 @@ +/* + * Copyright 2020 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SMU_CMN_H__ +#define __SMU_CMN_H__ + +#include "amdgpu_smu.h" + +#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, + uint32_t *read_arg); + +int smu_cmn_send_smc_msg(struct smu_context *smu, + enum smu_message_type msg, + uint32_t *read_arg); + +int smu_cmn_to_asic_specific_index(struct smu_context *smu, + enum smu_cmn2asic_mapping_type type, + uint32_t index); + +int smu_cmn_feature_is_supported(struct smu_context *smu, + enum smu_feature_mask mask); + +int smu_cmn_feature_is_enabled(struct smu_context *smu, + enum smu_feature_mask mask); + +bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, + enum smu_clk_type clk_type); + +int smu_cmn_get_enabled_mask(struct smu_context *smu, + uint32_t *feature_mask, + uint32_t num); + +int smu_cmn_feature_set_enabled(struct smu_context *smu, + enum smu_feature_mask mask, + bool enable); + +size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, + char *buf); + +int smu_cmn_set_pp_feature_mask(struct smu_context *smu, + uint64_t new_mask); + +int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, + enum smu_feature_mask mask); + +int smu_cmn_get_smc_version(struct smu_context *smu, + uint32_t *if_version, + uint32_t *smu_version); + +int smu_cmn_update_table(struct smu_context *smu, + enum smu_table_id table_index, + int argument, + void *table_data, + bool drv2smu); + +int smu_cmn_write_watermarks_table(struct smu_context *smu); + +int smu_cmn_write_pptable(struct smu_context *smu); + +int smu_cmn_get_metrics_table_locked(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + +int smu_cmn_get_metrics_table(struct smu_context *smu, + void *metrics_table, + bool bypass_cache); + +#endif +#endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h new file mode 100644 index 000000000000..264073d4e263 --- /dev/null +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -0,0 +1,97 @@ +/* + * Copyright 2019 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef __SMU_INTERNAL_H__ +#define __SMU_INTERNAL_H__ + +#include "amdgpu_smu.h" + +#if defined(SWSMU_CODE_LAYER_L1) + +#define smu_ppt_funcs(intf, ret, smu, args...) \ + ((smu)->ppt_funcs ? ((smu)->ppt_funcs->intf ? (smu)->ppt_funcs->intf(smu, ##args) : ret) : -EINVAL) + +#define smu_init_microcode(smu) smu_ppt_funcs(init_microcode, 0, smu) +#define smu_fini_microcode(smu) smu_ppt_funcs(fini_microcode, 0, smu) +#define smu_init_smc_tables(smu) smu_ppt_funcs(init_smc_tables, 0, smu) +#define smu_fini_smc_tables(smu) smu_ppt_funcs(fini_smc_tables, 0, smu) +#define smu_init_power(smu) smu_ppt_funcs(init_power, 0, smu) +#define smu_fini_power(smu) smu_ppt_funcs(fini_power, 0, smu) +#define smu_setup_pptable(smu) smu_ppt_funcs(setup_pptable, 0, smu) +#define smu_powergate_sdma(smu, gate) smu_ppt_funcs(powergate_sdma, 0, smu, gate) +#define smu_get_vbios_bootup_values(smu) smu_ppt_funcs(get_vbios_bootup_values, 0, smu) +#define smu_check_fw_version(smu) smu_ppt_funcs(check_fw_version, 0, smu) +#define smu_write_pptable(smu) smu_ppt_funcs(write_pptable, 0, smu) +#define smu_set_min_dcef_deep_sleep(smu, clk) smu_ppt_funcs(set_min_dcef_deep_sleep, 0, smu, clk) +#define smu_set_driver_table_location(smu) smu_ppt_funcs(set_driver_table_location, 0, smu) +#define smu_set_tool_table_location(smu) smu_ppt_funcs(set_tool_table_location, 0, smu) +#define smu_notify_memory_pool_location(smu) smu_ppt_funcs(notify_memory_pool_location, 0, smu) +#define smu_gfx_off_control(smu, enable) smu_ppt_funcs(gfx_off_control, 0, smu, enable) +#define smu_get_gfx_off_status(smu) smu_ppt_funcs(get_gfx_off_status, 0, smu) +#define smu_set_last_dcef_min_deep_sleep_clk(smu) smu_ppt_funcs(set_last_dcef_min_deep_sleep_clk, 0, smu) +#define smu_system_features_control(smu, en) smu_ppt_funcs(system_features_control, 0, smu, en) +#define smu_init_max_sustainable_clocks(smu) smu_ppt_funcs(init_max_sustainable_clocks, 0, smu) +#define smu_set_default_od_settings(smu) smu_ppt_funcs(set_default_od_settings, 0, smu) +#define smu_send_smc_msg_with_param(smu, msg, param, read_arg) smu_ppt_funcs(send_smc_msg_with_param, 0, smu, msg, param, read_arg) +#define smu_send_smc_msg(smu, msg, read_arg) smu_ppt_funcs(send_smc_msg, 0, smu, msg, read_arg) +#define smu_init_display_count(smu, count) smu_ppt_funcs(init_display_count, 0, smu, count) +#define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) +#define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) +#define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) +#define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) +#define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) +#define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) +#define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) +#define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu) +#define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu) +#define smu_disable_thermal_alert(smu) smu_ppt_funcs(disable_thermal_alert, 0, smu) +#define smu_smc_read_sensor(smu, sensor, data, size) smu_ppt_funcs(read_sensor, -EINVAL, smu, sensor, data, size) +#define smu_pre_display_config_changed(smu) smu_ppt_funcs(pre_display_config_changed, 0, smu) +#define smu_display_config_changed(smu) smu_ppt_funcs(display_config_changed, 0 , smu) +#define smu_apply_clocks_adjust_rules(smu) smu_ppt_funcs(apply_clocks_adjust_rules, 0, smu) +#define smu_notify_smc_display_config(smu) smu_ppt_funcs(notify_smc_display_config, 0, smu) +#define smu_set_cpu_power_state(smu) smu_ppt_funcs(set_cpu_power_state, 0, smu) +#define smu_run_btc(smu) smu_ppt_funcs(run_btc, 0, smu) +#define smu_get_allowed_feature_mask(smu, feature_mask, num) smu_ppt_funcs(get_allowed_feature_mask, 0, smu, feature_mask, num) +#define smu_store_cc6_data(smu, st, cc6_dis, pst_dis, pst_sw_dis) smu_ppt_funcs(store_cc6_data, 0, smu, st, cc6_dis, pst_dis, pst_sw_dis) +#define smu_get_dal_power_level(smu, clocks) smu_ppt_funcs(get_dal_power_level, 0, smu, clocks) +#define smu_get_perf_level(smu, designation, level) smu_ppt_funcs(get_perf_level, 0, smu, designation, level) +#define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks) +#define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges) +#define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) +#define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) +#define smu_get_dpm_ultimate_freq(smu, param, min, max) smu_ppt_funcs(get_dpm_ultimate_freq, 0, smu, param, min, max) +#define smu_asic_set_performance_level(smu, level) smu_ppt_funcs(set_performance_level, -EINVAL, smu, level) +#define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) +#define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) +#define smu_disable_umc_cdr_12gbps_workaround(smu) smu_ppt_funcs(disable_umc_cdr_12gbps_workaround, 0, smu) +#define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) +#define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control) +#define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) +#define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) +#define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) +#define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) +#define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) +#define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) + +#endif +#endif diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile deleted file mode 100644 index e9c48f99f71b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2017 Advanced Micro Devices, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# - -subdir-ccflags-y += \ - -I$(FULL_AMD_PATH)/powerplay/inc/ \ - -I$(FULL_AMD_PATH)/include/asic_reg \ - -I$(FULL_AMD_PATH)/include \ - -I$(FULL_AMD_PATH)/powerplay/smumgr\ - -I$(FULL_AMD_PATH)/powerplay/hwmgr - -AMD_PP_PATH = ../powerplay - -PP_LIBS = smumgr hwmgr - -AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix $(FULL_AMD_PATH)/powerplay/,$(PP_LIBS))) - -include $(AMD_POWERPLAY) - -POWER_MGR = amd_powerplay.o amdgpu_smu.o smu_v11_0.o \ - smu_v12_0.o arcturus_ppt.o navi10_ppt.o \ - renoir_ppt.o sienna_cichlid_ppt.o smu_cmn.o - -AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR)) - -AMD_POWERPLAY_FILES += $(AMD_PP_POWER) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c deleted file mode 100644 index a6321f2063c1..000000000000 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ /dev/null @@ -1,1680 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include -#include -#include "amd_shared.h" -#include "amd_powerplay.h" -#include "power_state.h" -#include "amdgpu.h" -#include "hwmgr.h" - - -static const struct amd_pm_funcs pp_dpm_funcs; - -static int amd_powerplay_create(struct amdgpu_device *adev) -{ - struct pp_hwmgr *hwmgr; - - if (adev == NULL) - return -EINVAL; - - hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL); - if (hwmgr == NULL) - return -ENOMEM; - - hwmgr->adev = adev; - hwmgr->not_vf = !amdgpu_sriov_vf(adev); - hwmgr->device = amdgpu_cgs_create_device(adev); - mutex_init(&hwmgr->smu_lock); - mutex_init(&hwmgr->msg_lock); - hwmgr->chip_family = adev->family; - hwmgr->chip_id = adev->asic_type; - hwmgr->feature_mask = adev->pm.pp_feature; - hwmgr->display_config = &adev->pm.pm_display_cfg; - adev->powerplay.pp_handle = hwmgr; - adev->powerplay.pp_funcs = &pp_dpm_funcs; - return 0; -} - - -static void amd_powerplay_destroy(struct amdgpu_device *adev) -{ - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - mutex_destroy(&hwmgr->msg_lock); - - kfree(hwmgr->hardcode_pp_table); - hwmgr->hardcode_pp_table = NULL; - - kfree(hwmgr); - hwmgr = NULL; -} - -static int pp_early_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = handle; - - ret = amd_powerplay_create(adev); - - if (ret != 0) - return ret; - - ret = hwmgr_early_init(adev->powerplay.pp_handle); - if (ret) - return -EINVAL; - - return 0; -} - -static int pp_sw_init(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - int ret = 0; - - ret = hwmgr_sw_init(hwmgr); - - pr_debug("powerplay sw init %s\n", ret ? "failed" : "successfully"); - - return ret; -} - -static int pp_sw_fini(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - hwmgr_sw_fini(hwmgr); - - release_firmware(adev->pm.fw); - adev->pm.fw = NULL; - - return 0; -} - -static int pp_hw_init(void *handle) -{ - int ret = 0; - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - ret = hwmgr_hw_init(hwmgr); - - if (ret) - pr_err("powerplay hw init failed\n"); - - return ret; -} - -static int pp_hw_fini(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - hwmgr_hw_fini(hwmgr); - - return 0; -} - -static void pp_reserve_vram_for_smu(struct amdgpu_device *adev) -{ - int r = -EINVAL; - void *cpu_ptr = NULL; - uint64_t gpu_addr; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (amdgpu_bo_create_kernel(adev, adev->pm.smu_prv_buffer_size, - PAGE_SIZE, AMDGPU_GEM_DOMAIN_GTT, - &adev->pm.smu_prv_buffer, - &gpu_addr, - &cpu_ptr)) { - DRM_ERROR("amdgpu: failed to create smu prv buffer\n"); - return; - } - - if (hwmgr->hwmgr_func->notify_cac_buffer_info) - r = hwmgr->hwmgr_func->notify_cac_buffer_info(hwmgr, - lower_32_bits((unsigned long)cpu_ptr), - upper_32_bits((unsigned long)cpu_ptr), - lower_32_bits(gpu_addr), - upper_32_bits(gpu_addr), - adev->pm.smu_prv_buffer_size); - - if (r) { - amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL); - adev->pm.smu_prv_buffer = NULL; - DRM_ERROR("amdgpu: failed to notify SMU buffer address\n"); - } -} - -static int pp_late_init(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - if (hwmgr && hwmgr->pm_en) { - mutex_lock(&hwmgr->smu_lock); - hwmgr_handle_task(hwmgr, - AMD_PP_TASK_COMPLETE_INIT, NULL); - mutex_unlock(&hwmgr->smu_lock); - } - if (adev->pm.smu_prv_buffer_size != 0) - pp_reserve_vram_for_smu(adev); - - return 0; -} - -static void pp_late_fini(void *handle) -{ - struct amdgpu_device *adev = handle; - - if (adev->pm.smu_prv_buffer) - amdgpu_bo_free_kernel(&adev->pm.smu_prv_buffer, NULL, NULL); - amd_powerplay_destroy(adev); -} - - -static bool pp_is_idle(void *handle) -{ - return false; -} - -static int pp_wait_for_idle(void *handle) -{ - return 0; -} - -static int pp_sw_reset(void *handle) -{ - return 0; -} - -static int pp_set_powergating_state(void *handle, - enum amd_powergating_state state) -{ - return 0; -} - -static int pp_suspend(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - return hwmgr_suspend(hwmgr); -} - -static int pp_resume(void *handle) -{ - struct amdgpu_device *adev = handle; - struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle; - - return hwmgr_resume(hwmgr); -} - -static int pp_set_clockgating_state(void *handle, - enum amd_clockgating_state state) -{ - return 0; -} - -static const struct amd_ip_funcs pp_ip_funcs = { - .name = "powerplay", - .early_init = pp_early_init, - .late_init = pp_late_init, - .sw_init = pp_sw_init, - .sw_fini = pp_sw_fini, - .hw_init = pp_hw_init, - .hw_fini = pp_hw_fini, - .late_fini = pp_late_fini, - .suspend = pp_suspend, - .resume = pp_resume, - .is_idle = pp_is_idle, - .wait_for_idle = pp_wait_for_idle, - .soft_reset = pp_sw_reset, - .set_clockgating_state = pp_set_clockgating_state, - .set_powergating_state = pp_set_powergating_state, -}; - -const struct amdgpu_ip_block_version pp_smu_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 1, - .minor = 0, - .rev = 0, - .funcs = &pp_ip_funcs, -}; - -/* This interface only be supported On Vi, - * because only smu7/8 can help to load gfx/sdma fw, - * smu need to be enabled before load other ip's fw. - * so call start smu to load smu7 fw and other ip's fw - */ -static int pp_dpm_load_fw(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu) - return -EINVAL; - - if (hwmgr->smumgr_funcs->start_smu(hwmgr)) { - pr_err("fw load failed\n"); - return -EINVAL; - } - - return 0; -} - -static int pp_dpm_fw_loading_complete(void *handle) -{ - return 0; -} - -static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id); -} - -static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level *level) -{ - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - if (!(hwmgr->dpm_level & profile_mode_mask)) { - /* enter umd pstate, save current level, disable gfx cg*/ - if (*level & profile_mode_mask) { - hwmgr->saved_dpm_level = hwmgr->dpm_level; - hwmgr->en_umd_pstate = true; - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit umd pstate, restore level, enable gfx cg*/ - if (!(*level & profile_mode_mask)) { - if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - *level = hwmgr->saved_dpm_level; - hwmgr->en_umd_pstate = false; - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); - } - } -} - -static int pp_dpm_force_performance_level(void *handle, - enum amd_dpm_forced_level level) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (level == hwmgr->dpm_level) - return 0; - - mutex_lock(&hwmgr->smu_lock); - pp_dpm_en_umd_pstate(hwmgr, &level); - hwmgr->request_dpm_level = level; - hwmgr_handle_task(hwmgr, AMD_PP_TASK_READJUST_POWER_STATE, NULL); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static enum amd_dpm_forced_level pp_dpm_get_performance_level( - void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - enum amd_dpm_forced_level level; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - level = hwmgr->dpm_level; - mutex_unlock(&hwmgr->smu_lock); - return level; -} - -static uint32_t pp_dpm_get_sclk(void *handle, bool low) -{ - struct pp_hwmgr *hwmgr = handle; - uint32_t clk = 0; - - if (!hwmgr || !hwmgr->pm_en) - return 0; - - if (hwmgr->hwmgr_func->get_sclk == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - clk = hwmgr->hwmgr_func->get_sclk(hwmgr, low); - mutex_unlock(&hwmgr->smu_lock); - return clk; -} - -static uint32_t pp_dpm_get_mclk(void *handle, bool low) -{ - struct pp_hwmgr *hwmgr = handle; - uint32_t clk = 0; - - if (!hwmgr || !hwmgr->pm_en) - return 0; - - if (hwmgr->hwmgr_func->get_mclk == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - clk = hwmgr->hwmgr_func->get_mclk(hwmgr, low); - mutex_unlock(&hwmgr->smu_lock); - return clk; -} - -static void pp_dpm_powergate_vce(void *handle, bool gate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return; - - if (hwmgr->hwmgr_func->powergate_vce == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); - mutex_unlock(&hwmgr->smu_lock); -} - -static void pp_dpm_powergate_uvd(void *handle, bool gate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return; - - if (hwmgr->hwmgr_func->powergate_uvd == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); - mutex_unlock(&hwmgr->smu_lock); -} - -static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, - enum amd_pm_state_type *user_state) -{ - int ret = 0; - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr_handle_task(hwmgr, task_id, user_state); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - struct pp_power_state *state; - enum amd_pm_state_type pm_type; - - if (!hwmgr || !hwmgr->pm_en || !hwmgr->current_ps) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - state = hwmgr->current_ps; - - switch (state->classification.ui_label) { - case PP_StateUILabel_Battery: - pm_type = POWER_STATE_TYPE_BATTERY; - break; - case PP_StateUILabel_Balanced: - pm_type = POWER_STATE_TYPE_BALANCED; - break; - case PP_StateUILabel_Performance: - pm_type = POWER_STATE_TYPE_PERFORMANCE; - break; - default: - if (state->classification.flags & PP_StateClassificationFlag_Boot) - pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; - else - pm_type = POWER_STATE_TYPE_DEFAULT; - break; - } - mutex_unlock(&hwmgr->smu_lock); - - return pm_type; -} - -static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return; - - if (hwmgr->hwmgr_func->set_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); - mutex_unlock(&hwmgr->smu_lock); -} - -static uint32_t pp_dpm_get_fan_control_mode(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - uint32_t mode = 0; - - if (!hwmgr || !hwmgr->pm_en) - return 0; - - if (hwmgr->hwmgr_func->get_fan_control_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - mode = hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - return mode; -} - -static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_fan_speed_percent == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_fan_speed_percent == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_fan_speed_rpm == NULL) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_fan_speed_rpm(hwmgr, rpm); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_get_pp_num_states(void *handle, - struct pp_states_info *data) -{ - struct pp_hwmgr *hwmgr = handle; - int i; - - memset(data, 0, sizeof(*data)); - - if (!hwmgr || !hwmgr->pm_en ||!hwmgr->ps) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - data->nums = hwmgr->num_ps; - - for (i = 0; i < hwmgr->num_ps; i++) { - struct pp_power_state *state = (struct pp_power_state *) - ((unsigned long)hwmgr->ps + i * hwmgr->ps_size); - switch (state->classification.ui_label) { - case PP_StateUILabel_Battery: - data->states[i] = POWER_STATE_TYPE_BATTERY; - break; - case PP_StateUILabel_Balanced: - data->states[i] = POWER_STATE_TYPE_BALANCED; - break; - case PP_StateUILabel_Performance: - data->states[i] = POWER_STATE_TYPE_PERFORMANCE; - break; - default: - if (state->classification.flags & PP_StateClassificationFlag_Boot) - data->states[i] = POWER_STATE_TYPE_INTERNAL_BOOT; - else - data->states[i] = POWER_STATE_TYPE_DEFAULT; - } - } - mutex_unlock(&hwmgr->smu_lock); - return 0; -} - -static int pp_dpm_get_pp_table(void *handle, char **table) -{ - struct pp_hwmgr *hwmgr = handle; - int size = 0; - - if (!hwmgr || !hwmgr->pm_en ||!hwmgr->soft_pp_table) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - *table = (char *)hwmgr->soft_pp_table; - size = hwmgr->soft_pp_table_size; - mutex_unlock(&hwmgr->smu_lock); - return size; -} - -static int amd_powerplay_reset(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - int ret; - - ret = hwmgr_hw_fini(hwmgr); - if (ret) - return ret; - - ret = hwmgr_hw_init(hwmgr); - if (ret) - return ret; - - return hwmgr_handle_task(hwmgr, AMD_PP_TASK_COMPLETE_INIT, NULL); -} - -static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = -ENOMEM; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - if (!hwmgr->hardcode_pp_table) { - hwmgr->hardcode_pp_table = kmemdup(hwmgr->soft_pp_table, - hwmgr->soft_pp_table_size, - GFP_KERNEL); - if (!hwmgr->hardcode_pp_table) - goto err; - } - - memcpy(hwmgr->hardcode_pp_table, buf, size); - - hwmgr->soft_pp_table = hwmgr->hardcode_pp_table; - - ret = amd_powerplay_reset(handle); - if (ret) - goto err; - - if (hwmgr->hwmgr_func->avfs_control) { - ret = hwmgr->hwmgr_func->avfs_control(hwmgr, false); - if (ret) - goto err; - } - mutex_unlock(&hwmgr->smu_lock); - return 0; -err: - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_force_clock_level(void *handle, - enum pp_clock_type type, uint32_t mask) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->force_clock_level == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { - pr_debug("force clock level is for dpm manual mode only.\n"); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_print_clock_levels(void *handle, - enum pp_clock_type type, char *buf) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->print_clock_levels == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->print_clock_levels(hwmgr, type, buf); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_get_sclk_od(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_sclk_od == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_sclk_od(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_set_sclk_od(void *handle, uint32_t value) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_sclk_od == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_sclk_od(hwmgr, value); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_get_mclk_od(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_mclk_od == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_mclk_od(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_set_mclk_od(void *handle, uint32_t value) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_mclk_od == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_mclk_od(hwmgr, value); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_read_sensor(void *handle, int idx, - void *value, int *size) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en || !value) - return -EINVAL; - - switch (idx) { - case AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK: - *((uint32_t *)value) = hwmgr->pstate_sclk; - return 0; - case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK: - *((uint32_t *)value) = hwmgr->pstate_mclk; - return 0; - case AMDGPU_PP_SENSOR_MIN_FAN_RPM: - *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM; - return 0; - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: - *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM; - return 0; - default: - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size); - mutex_unlock(&hwmgr->smu_lock); - return ret; - } -} - -static struct amd_vce_state* -pp_dpm_get_vce_clock_state(void *handle, unsigned idx) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return NULL; - - if (idx < hwmgr->num_vce_state_tables) - return &hwmgr->vce_states[idx]; - return NULL; -} - -static int pp_get_power_profile_mode(void *handle, char *buf) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en || !buf) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_power_profile_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return snprintf(buf, PAGE_SIZE, "\n"); - } - - return hwmgr->hwmgr_func->get_power_profile_mode(hwmgr, buf); -} - -static int pp_set_power_profile_mode(void *handle, long *input, uint32_t size) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = -EINVAL; - - if (!hwmgr || !hwmgr->pm_en) - return ret; - - if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return ret; - } - - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { - pr_debug("power profile setting is for manual dpm mode only.\n"); - return ret; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, input, size); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->odn_edit_dpm_table == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - return hwmgr->hwmgr_func->odn_edit_dpm_table(hwmgr, type, input, size); -} - -static int pp_dpm_set_mp1_state(void *handle, enum pp_mp1_state mp1_state) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en) - return 0; - - if (hwmgr->hwmgr_func->set_mp1_state) - return hwmgr->hwmgr_func->set_mp1_state(hwmgr, mp1_state); - - return 0; -} - -static int pp_dpm_switch_power_profile(void *handle, - enum PP_SMC_POWER_PROFILE type, bool en) -{ - struct pp_hwmgr *hwmgr = handle; - long workload; - uint32_t index; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_power_profile_mode == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - if (!en) { - hwmgr->workload_mask &= ~(1 << hwmgr->workload_prority[type]); - index = fls(hwmgr->workload_mask); - index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; - workload = hwmgr->workload_setting[index]; - } else { - hwmgr->workload_mask |= (1 << hwmgr->workload_prority[type]); - index = fls(hwmgr->workload_mask); - index = index <= Workload_Policy_Max ? index - 1 : 0; - workload = hwmgr->workload_setting[index]; - } - - if (type == PP_SMC_POWER_PROFILE_COMPUTE && - hwmgr->hwmgr_func->disable_power_features_for_compute_performance) { - if (hwmgr->hwmgr_func->disable_power_features_for_compute_performance(hwmgr, en)) { - mutex_unlock(&hwmgr->smu_lock); - return -EINVAL; - } - } - - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) - hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_power_limit(void *handle, uint32_t limit) -{ - struct pp_hwmgr *hwmgr = handle; - uint32_t max_power_limit; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_power_limit == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - if (limit == 0) - limit = hwmgr->default_power_limit; - - max_power_limit = hwmgr->default_power_limit; - if (hwmgr->od_enabled) { - max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); - max_power_limit /= 100; - } - - if (limit > max_power_limit) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_power_limit(hwmgr, limit); - hwmgr->power_limit = limit; - mutex_unlock(&hwmgr->smu_lock); - return 0; -} - -static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en ||!limit) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - if (default_limit) { - *limit = hwmgr->default_power_limit; - if (hwmgr->od_enabled) { - *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); - *limit /= 100; - } - } - else - *limit = hwmgr->power_limit; - - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_display_configuration_change(void *handle, - const struct amd_pp_display_configuration *display_config) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - phm_store_dal_configuration_data(hwmgr, display_config); - mutex_unlock(&hwmgr->smu_lock); - return 0; -} - -static int pp_get_display_power_level(void *handle, - struct amd_pp_simple_clock_info *output) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en ||!output) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_dal_power_level(hwmgr, output); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_get_current_clocks(void *handle, - struct amd_pp_clock_info *clocks) -{ - struct amd_pp_simple_clock_info simple_clocks = { 0 }; - struct pp_clock_info hw_clocks; - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - phm_get_dal_power_level(hwmgr, &simple_clocks); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) - ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, - &hw_clocks, PHM_PerformanceLevelDesignation_PowerContainment); - else - ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, - &hw_clocks, PHM_PerformanceLevelDesignation_Activity); - - if (ret) { - pr_debug("Error in phm_get_clock_info \n"); - mutex_unlock(&hwmgr->smu_lock); - return -EINVAL; - } - - clocks->min_engine_clock = hw_clocks.min_eng_clk; - clocks->max_engine_clock = hw_clocks.max_eng_clk; - clocks->min_memory_clock = hw_clocks.min_mem_clk; - clocks->max_memory_clock = hw_clocks.max_mem_clk; - clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth; - clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth; - - clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; - clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; - - if (simple_clocks.level == 0) - clocks->max_clocks_state = PP_DAL_POWERLEVEL_7; - else - clocks->max_clocks_state = simple_clocks.level; - - if (0 == phm_get_current_shallow_sleep_clocks(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks)) { - clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; - clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; - } - mutex_unlock(&hwmgr->smu_lock); - return 0; -} - -static int pp_get_clock_by_type(void *handle, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (clocks == NULL) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_clock_by_type(hwmgr, type, clocks); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_get_clock_by_type_with_latency(void *handle, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en ||!clocks) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_get_clock_by_type_with_latency(hwmgr, type, clocks); - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_get_clock_by_type_with_voltage(void *handle, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en ||!clocks) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - - ret = phm_get_clock_by_type_with_voltage(hwmgr, type, clocks); - - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_set_watermarks_for_clocks_ranges(void *handle, - void *clock_ranges) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en || !clock_ranges) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_set_watermarks_for_clocks_ranges(hwmgr, - clock_ranges); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_display_clock_voltage_request(void *handle, - struct pp_display_clock_request *clock) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en ||!clock) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_display_clock_voltage_request(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_get_display_mode_validation_clocks(void *handle, - struct amd_pp_simple_clock_info *clocks) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en ||!clocks) - return -EINVAL; - - clocks->level = PP_DAL_POWERLEVEL_7; - - mutex_lock(&hwmgr->smu_lock); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) - ret = phm_get_max_high_clocks(hwmgr, clocks); - - mutex_unlock(&hwmgr->smu_lock); - return ret; -} - -static int pp_dpm_powergate_mmhub(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->powergate_mmhub == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - return hwmgr->hwmgr_func->powergate_mmhub(hwmgr); -} - -static int pp_dpm_powergate_gfx(void *handle, bool gate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return 0; - - if (hwmgr->hwmgr_func->powergate_gfx == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return 0; - } - - return hwmgr->hwmgr_func->powergate_gfx(hwmgr, gate); -} - -static void pp_dpm_powergate_acp(void *handle, bool gate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return; - - if (hwmgr->hwmgr_func->powergate_acp == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } - - hwmgr->hwmgr_func->powergate_acp(hwmgr, gate); -} - -static void pp_dpm_powergate_sdma(void *handle, bool gate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return; - - if (hwmgr->hwmgr_func->powergate_sdma == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return; - } - - hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate); -} - -static int pp_set_powergating_by_smu(void *handle, - uint32_t block_type, bool gate) -{ - int ret = 0; - - switch (block_type) { - case AMD_IP_BLOCK_TYPE_UVD: - case AMD_IP_BLOCK_TYPE_VCN: - pp_dpm_powergate_uvd(handle, gate); - break; - case AMD_IP_BLOCK_TYPE_VCE: - pp_dpm_powergate_vce(handle, gate); - break; - case AMD_IP_BLOCK_TYPE_GMC: - pp_dpm_powergate_mmhub(handle); - break; - case AMD_IP_BLOCK_TYPE_GFX: - ret = pp_dpm_powergate_gfx(handle, gate); - break; - case AMD_IP_BLOCK_TYPE_ACP: - pp_dpm_powergate_acp(handle, gate); - break; - case AMD_IP_BLOCK_TYPE_SDMA: - pp_dpm_powergate_sdma(handle, gate); - break; - default: - break; - } - return ret; -} - -static int pp_notify_smu_enable_pwe(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->smus_notify_pwe == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->smus_notify_pwe(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_enable_mgpu_fan_boost(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en || - hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_min_deep_sleep_dcefclk(void *handle, uint32_t clock) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk == NULL) { - pr_debug("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_hard_min_dcefclk_by_freq(void *handle, uint32_t clock) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq == NULL) { - pr_debug("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_hard_min_fclk_by_freq(void *handle, uint32_t clock) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_hard_min_fclk_by_freq == NULL) { - pr_debug("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_active_display_count(void *handle, uint32_t count) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - mutex_lock(&hwmgr->smu_lock); - ret = phm_set_active_display_count(hwmgr, count); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_get_asic_baco_capability(void *handle, bool *cap) -{ - struct pp_hwmgr *hwmgr = handle; - - *cap = false; - if (!hwmgr) - return -EINVAL; - - if (!(hwmgr->not_vf && amdgpu_dpm) || - !hwmgr->hwmgr_func->get_asic_baco_capability) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->get_asic_baco_capability(hwmgr, cap); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_get_asic_baco_state(void *handle, int *state) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_asic_baco_state) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->get_asic_baco_state(hwmgr, (enum BACO_STATE *)state); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_asic_baco_state(void *handle, int state) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!(hwmgr->not_vf && amdgpu_dpm) || - !hwmgr->hwmgr_func->set_asic_baco_state) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_asic_baco_state(hwmgr, (enum BACO_STATE)state); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_get_ppfeature_status(void *handle, char *buf) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en || !buf) - return -EINVAL; - - if (hwmgr->hwmgr_func->get_ppfeature_status == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->get_ppfeature_status(hwmgr, buf); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_set_ppfeature_status(void *handle, uint64_t ppfeature_masks) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->set_ppfeature_status == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->set_ppfeature_status(hwmgr, ppfeature_masks); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_asic_reset_mode_2(void *handle) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->asic_reset == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->asic_reset(hwmgr, SMU_ASIC_RESET_MODE_2); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_smu_i2c_bus_access(void *handle, bool acquire) -{ - struct pp_hwmgr *hwmgr = handle; - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en) - return -EINVAL; - - if (hwmgr->hwmgr_func->smu_i2c_bus_access == NULL) { - pr_info_ratelimited("%s was not implemented.\n", __func__); - return -EINVAL; - } - - mutex_lock(&hwmgr->smu_lock); - ret = hwmgr->hwmgr_func->smu_i2c_bus_access(hwmgr, acquire); - mutex_unlock(&hwmgr->smu_lock); - - return ret; -} - -static int pp_set_df_cstate(void *handle, enum pp_df_cstate state) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_df_cstate) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_df_cstate(hwmgr, state); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static int pp_set_xgmi_pstate(void *handle, uint32_t pstate) -{ - struct pp_hwmgr *hwmgr = handle; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->set_xgmi_pstate) - return 0; - - mutex_lock(&hwmgr->smu_lock); - hwmgr->hwmgr_func->set_xgmi_pstate(hwmgr, pstate); - mutex_unlock(&hwmgr->smu_lock); - - return 0; -} - -static ssize_t pp_get_gpu_metrics(void *handle, void **table) -{ - struct pp_hwmgr *hwmgr = handle; - ssize_t size; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->pm_en || !hwmgr->hwmgr_func->get_gpu_metrics) - return -EOPNOTSUPP; - - mutex_lock(&hwmgr->smu_lock); - size = hwmgr->hwmgr_func->get_gpu_metrics(hwmgr, table); - mutex_unlock(&hwmgr->smu_lock); - - return size; -} - -static const struct amd_pm_funcs pp_dpm_funcs = { - .load_firmware = pp_dpm_load_fw, - .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, - .force_performance_level = pp_dpm_force_performance_level, - .get_performance_level = pp_dpm_get_performance_level, - .get_current_power_state = pp_dpm_get_current_power_state, - .dispatch_tasks = pp_dpm_dispatch_tasks, - .set_fan_control_mode = pp_dpm_set_fan_control_mode, - .get_fan_control_mode = pp_dpm_get_fan_control_mode, - .set_fan_speed_percent = pp_dpm_set_fan_speed_percent, - .get_fan_speed_percent = pp_dpm_get_fan_speed_percent, - .get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm, - .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm, - .get_pp_num_states = pp_dpm_get_pp_num_states, - .get_pp_table = pp_dpm_get_pp_table, - .set_pp_table = pp_dpm_set_pp_table, - .force_clock_level = pp_dpm_force_clock_level, - .print_clock_levels = pp_dpm_print_clock_levels, - .get_sclk_od = pp_dpm_get_sclk_od, - .set_sclk_od = pp_dpm_set_sclk_od, - .get_mclk_od = pp_dpm_get_mclk_od, - .set_mclk_od = pp_dpm_set_mclk_od, - .read_sensor = pp_dpm_read_sensor, - .get_vce_clock_state = pp_dpm_get_vce_clock_state, - .switch_power_profile = pp_dpm_switch_power_profile, - .set_clockgating_by_smu = pp_set_clockgating_by_smu, - .set_powergating_by_smu = pp_set_powergating_by_smu, - .get_power_profile_mode = pp_get_power_profile_mode, - .set_power_profile_mode = pp_set_power_profile_mode, - .odn_edit_dpm_table = pp_odn_edit_dpm_table, - .set_mp1_state = pp_dpm_set_mp1_state, - .set_power_limit = pp_set_power_limit, - .get_power_limit = pp_get_power_limit, -/* export to DC */ - .get_sclk = pp_dpm_get_sclk, - .get_mclk = pp_dpm_get_mclk, - .display_configuration_change = pp_display_configuration_change, - .get_display_power_level = pp_get_display_power_level, - .get_current_clocks = pp_get_current_clocks, - .get_clock_by_type = pp_get_clock_by_type, - .get_clock_by_type_with_latency = pp_get_clock_by_type_with_latency, - .get_clock_by_type_with_voltage = pp_get_clock_by_type_with_voltage, - .set_watermarks_for_clocks_ranges = pp_set_watermarks_for_clocks_ranges, - .display_clock_voltage_request = pp_display_clock_voltage_request, - .get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks, - .notify_smu_enable_pwe = pp_notify_smu_enable_pwe, - .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost, - .set_active_display_count = pp_set_active_display_count, - .set_min_deep_sleep_dcefclk = pp_set_min_deep_sleep_dcefclk, - .set_hard_min_dcefclk_by_freq = pp_set_hard_min_dcefclk_by_freq, - .set_hard_min_fclk_by_freq = pp_set_hard_min_fclk_by_freq, - .get_asic_baco_capability = pp_get_asic_baco_capability, - .get_asic_baco_state = pp_get_asic_baco_state, - .set_asic_baco_state = pp_set_asic_baco_state, - .get_ppfeature_status = pp_get_ppfeature_status, - .set_ppfeature_status = pp_set_ppfeature_status, - .asic_reset_mode_2 = pp_asic_reset_mode_2, - .smu_i2c_bus_access = pp_smu_i2c_bus_access, - .set_df_cstate = pp_set_df_cstate, - .set_xgmi_pstate = pp_set_xgmi_pstate, - .get_gpu_metrics = pp_get_gpu_metrics, -}; diff --git a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c b/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c deleted file mode 100644 index 7d17c4f1b489..000000000000 --- a/drivers/gpu/drm/amd/powerplay/amdgpu_smu.c +++ /dev/null @@ -1,2671 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#define SWSMU_CODE_LAYER_L1 - -#include -#include - -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "smu_internal.h" -#include "atom.h" -#include "arcturus_ppt.h" -#include "navi10_ppt.h" -#include "sienna_cichlid_ppt.h" -#include "renoir_ppt.h" -#include "amd_pcie.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf) -{ - size_t size = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - size = smu_get_pp_feature_mask(smu, buf); - - mutex_unlock(&smu->mutex); - - return size; -} - -int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - ret = smu_set_pp_feature_mask(smu, new_mask); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value) -{ - int ret = 0; - struct smu_context *smu = &adev->smu; - - if (is_support_sw_smu(adev) && smu->ppt_funcs->get_gfx_off_status) - *value = smu_get_gfx_off_status(smu); - else - ret = -EINVAL; - - return ret; -} - -int smu_set_soft_freq_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t min, - uint32_t max) -{ - int ret = 0; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_soft_freq_limited_range) - ret = smu->ppt_funcs->set_soft_freq_limited_range(smu, - clk_type, - min, - max); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_dpm_freq_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *min, - uint32_t *max) -{ - int ret = 0; - - if (!min && !max) - return -EINVAL; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_dpm_ultimate_freq) - ret = smu->ppt_funcs->get_dpm_ultimate_freq(smu, - clk_type, - min, - max); - - mutex_unlock(&smu->mutex); - - return ret; -} - -static int smu_dpm_set_vcn_enable_locked(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - if (!smu->ppt_funcs->dpm_set_vcn_enable) - return 0; - - if (atomic_read(&power_gate->vcn_gated) ^ enable) - return 0; - - ret = smu->ppt_funcs->dpm_set_vcn_enable(smu, enable); - if (!ret) - atomic_set(&power_gate->vcn_gated, !enable); - - return ret; -} - -static int smu_dpm_set_vcn_enable(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - mutex_lock(&power_gate->vcn_gate_lock); - - ret = smu_dpm_set_vcn_enable_locked(smu, enable); - - mutex_unlock(&power_gate->vcn_gate_lock); - - return ret; -} - -static int smu_dpm_set_jpeg_enable_locked(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - if (!smu->ppt_funcs->dpm_set_jpeg_enable) - return 0; - - if (atomic_read(&power_gate->jpeg_gated) ^ enable) - return 0; - - ret = smu->ppt_funcs->dpm_set_jpeg_enable(smu, enable); - if (!ret) - atomic_set(&power_gate->jpeg_gated, !enable); - - return ret; -} - -static int smu_dpm_set_jpeg_enable(struct smu_context *smu, - bool enable) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int ret = 0; - - mutex_lock(&power_gate->jpeg_gate_lock); - - ret = smu_dpm_set_jpeg_enable_locked(smu, enable); - - mutex_unlock(&power_gate->jpeg_gate_lock); - - return ret; -} - -/** - * smu_dpm_set_power_gate - power gate/ungate the specific IP block - * - * @smu: smu_context pointer - * @block_type: the IP block to power gate/ungate - * @gate: to power gate if true, ungate otherwise - * - * This API uses no smu->mutex lock protection due to: - * 1. It is either called by other IP block(gfx/sdma/vcn/uvd/vce). - * This is guarded to be race condition free by the caller. - * 2. Or get called on user setting request of power_dpm_force_performance_level. - * Under this case, the smu->mutex lock protection is already enforced on - * the parent API smu_force_performance_level of the call path. - */ -int smu_dpm_set_power_gate(struct smu_context *smu, uint32_t block_type, - bool gate) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - switch (block_type) { - /* - * Some legacy code of amdgpu_vcn.c and vcn_v2*.c still uses - * AMD_IP_BLOCK_TYPE_UVD for VCN. So, here both of them are kept. - */ - case AMD_IP_BLOCK_TYPE_UVD: - case AMD_IP_BLOCK_TYPE_VCN: - ret = smu_dpm_set_vcn_enable(smu, !gate); - if (ret) - dev_err(smu->adev->dev, "Failed to power %s VCN!\n", - gate ? "gate" : "ungate"); - break; - case AMD_IP_BLOCK_TYPE_GFX: - ret = smu_gfx_off_control(smu, gate); - if (ret) - dev_err(smu->adev->dev, "Failed to %s gfxoff!\n", - gate ? "enable" : "disable"); - break; - case AMD_IP_BLOCK_TYPE_SDMA: - ret = smu_powergate_sdma(smu, gate); - if (ret) - dev_err(smu->adev->dev, "Failed to power %s SDMA!\n", - gate ? "gate" : "ungate"); - break; - case AMD_IP_BLOCK_TYPE_JPEG: - ret = smu_dpm_set_jpeg_enable(smu, !gate); - if (ret) - dev_err(smu->adev->dev, "Failed to power %s JPEG!\n", - gate ? "gate" : "ungate"); - break; - default: - dev_err(smu->adev->dev, "Unsupported block type!\n"); - return -EINVAL; - } - - return ret; -} - -int smu_get_power_num_states(struct smu_context *smu, - struct pp_states_info *state_info) -{ - if (!state_info) - return -EINVAL; - - /* not support power state */ - memset(state_info, 0, sizeof(struct pp_states_info)); - state_info->nums = 1; - state_info->states[0] = POWER_STATE_TYPE_DEFAULT; - - return 0; -} - -bool is_support_sw_smu(struct amdgpu_device *adev) -{ - if (adev->asic_type >= CHIP_ARCTURUS) - return true; - - return false; -} - -int smu_sys_get_pp_table(struct smu_context *smu, void **table) -{ - struct smu_table_context *smu_table = &smu->smu_table; - uint32_t powerplay_table_size; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu_table->power_play_table && !smu_table->hardcode_pptable) - return -EINVAL; - - mutex_lock(&smu->mutex); - - if (smu_table->hardcode_pptable) - *table = smu_table->hardcode_pptable; - else - *table = smu_table->power_play_table; - - powerplay_table_size = smu_table->power_play_table_size; - - mutex_unlock(&smu->mutex); - - return powerplay_table_size; -} - -int smu_sys_set_pp_table(struct smu_context *smu, void *buf, size_t size) -{ - struct smu_table_context *smu_table = &smu->smu_table; - ATOM_COMMON_TABLE_HEADER *header = (ATOM_COMMON_TABLE_HEADER *)buf; - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (header->usStructureSize != size) { - dev_err(smu->adev->dev, "pp table size not matched !\n"); - return -EIO; - } - - mutex_lock(&smu->mutex); - if (!smu_table->hardcode_pptable) - smu_table->hardcode_pptable = kzalloc(size, GFP_KERNEL); - if (!smu_table->hardcode_pptable) { - ret = -ENOMEM; - goto failed; - } - - memcpy(smu_table->hardcode_pptable, buf, size); - smu_table->power_play_table = smu_table->hardcode_pptable; - smu_table->power_play_table_size = size; - - /* - * Special hw_fini action(for Navi1x, the DPMs disablement will be - * skipped) may be needed for custom pptable uploading. - */ - smu->uploading_custom_pp_table = true; - - ret = smu_reset(smu); - if (ret) - dev_info(smu->adev->dev, "smu reset failed, ret = %d\n", ret); - - smu->uploading_custom_pp_table = false; - -failed: - mutex_unlock(&smu->mutex); - return ret; -} - -static int smu_get_driver_allowed_feature_mask(struct smu_context *smu) -{ - struct smu_feature *feature = &smu->smu_feature; - int ret = 0; - uint32_t allowed_feature_mask[SMU_FEATURE_MAX/32]; - - mutex_lock(&feature->mutex); - bitmap_zero(feature->allowed, SMU_FEATURE_MAX); - mutex_unlock(&feature->mutex); - - ret = smu_get_allowed_feature_mask(smu, allowed_feature_mask, - SMU_FEATURE_MAX/32); - if (ret) - return ret; - - mutex_lock(&feature->mutex); - bitmap_or(feature->allowed, feature->allowed, - (unsigned long *)allowed_feature_mask, - feature->feature_num); - mutex_unlock(&feature->mutex); - - return ret; -} - -static int smu_set_funcs(struct amdgpu_device *adev) -{ - struct smu_context *smu = &adev->smu; - - if (adev->pm.pp_feature & PP_OVERDRIVE_MASK) - smu->od_enabled = true; - - switch (adev->asic_type) { - case CHIP_NAVI10: - case CHIP_NAVI14: - case CHIP_NAVI12: - navi10_set_ppt_funcs(smu); - break; - case CHIP_ARCTURUS: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - arcturus_set_ppt_funcs(smu); - /* OD is not supported on Arcturus */ - smu->od_enabled =false; - break; - case CHIP_SIENNA_CICHLID: - case CHIP_NAVY_FLOUNDER: - sienna_cichlid_set_ppt_funcs(smu); - break; - case CHIP_RENOIR: - renoir_set_ppt_funcs(smu); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int smu_early_init(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - - smu->adev = adev; - smu->pm_enabled = !!amdgpu_dpm; - smu->is_apu = false; - mutex_init(&smu->mutex); - - return smu_set_funcs(adev); -} - -static int smu_set_default_dpm_table(struct smu_context *smu) -{ - struct smu_power_context *smu_power = &smu->smu_power; - struct smu_power_gate *power_gate = &smu_power->power_gate; - int vcn_gate, jpeg_gate; - int ret = 0; - - if (!smu->ppt_funcs->set_default_dpm_table) - return 0; - - mutex_lock(&power_gate->vcn_gate_lock); - mutex_lock(&power_gate->jpeg_gate_lock); - - vcn_gate = atomic_read(&power_gate->vcn_gated); - jpeg_gate = atomic_read(&power_gate->jpeg_gated); - - ret = smu_dpm_set_vcn_enable_locked(smu, true); - if (ret) - goto err0_out; - - ret = smu_dpm_set_jpeg_enable_locked(smu, true); - if (ret) - goto err1_out; - - ret = smu->ppt_funcs->set_default_dpm_table(smu); - if (ret) - dev_err(smu->adev->dev, - "Failed to setup default dpm clock tables!\n"); - - smu_dpm_set_jpeg_enable_locked(smu, !jpeg_gate); -err1_out: - smu_dpm_set_vcn_enable_locked(smu, !vcn_gate); -err0_out: - mutex_unlock(&power_gate->jpeg_gate_lock); - mutex_unlock(&power_gate->vcn_gate_lock); - - return ret; -} - -static int smu_late_init(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - int ret = 0; - - if (!smu->pm_enabled) - return 0; - - ret = smu_set_default_od_settings(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup default OD settings!\n"); - return ret; - } - - /* - * Set initialized values (get from vbios) to dpm tables context such as - * gfxclk, memclk, dcefclk, and etc. And enable the DPM feature for each - * type of clks. - */ - ret = smu_set_default_dpm_table(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup default dpm clock tables!\n"); - return ret; - } - - ret = smu_populate_umd_state_clk(smu); - if (ret) { - dev_err(adev->dev, "Failed to populate UMD state clocks!\n"); - return ret; - } - - ret = smu_get_asic_power_limits(smu); - if (ret) { - dev_err(adev->dev, "Failed to get asic power limits!\n"); - return ret; - } - - smu_get_unique_id(smu); - - smu_handle_task(&adev->smu, - smu->smu_dpm.dpm_level, - AMD_PP_TASK_COMPLETE_INIT, - false); - - return 0; -} - -static int smu_init_fb_allocations(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - struct smu_table *driver_table = &(smu_table->driver_table); - uint32_t max_table_size = 0; - int ret, i; - - /* VRAM allocation for tool table */ - if (tables[SMU_TABLE_PMSTATUSLOG].size) { - ret = amdgpu_bo_create_kernel(adev, - tables[SMU_TABLE_PMSTATUSLOG].size, - tables[SMU_TABLE_PMSTATUSLOG].align, - tables[SMU_TABLE_PMSTATUSLOG].domain, - &tables[SMU_TABLE_PMSTATUSLOG].bo, - &tables[SMU_TABLE_PMSTATUSLOG].mc_address, - &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); - if (ret) { - dev_err(adev->dev, "VRAM allocation for tool table failed!\n"); - return ret; - } - } - - /* VRAM allocation for driver table */ - for (i = 0; i < SMU_TABLE_COUNT; i++) { - if (tables[i].size == 0) - continue; - - if (i == SMU_TABLE_PMSTATUSLOG) - continue; - - if (max_table_size < tables[i].size) - max_table_size = tables[i].size; - } - - driver_table->size = max_table_size; - driver_table->align = PAGE_SIZE; - driver_table->domain = AMDGPU_GEM_DOMAIN_VRAM; - - ret = amdgpu_bo_create_kernel(adev, - driver_table->size, - driver_table->align, - driver_table->domain, - &driver_table->bo, - &driver_table->mc_address, - &driver_table->cpu_addr); - if (ret) { - dev_err(adev->dev, "VRAM allocation for driver table failed!\n"); - if (tables[SMU_TABLE_PMSTATUSLOG].mc_address) - amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo, - &tables[SMU_TABLE_PMSTATUSLOG].mc_address, - &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); - } - - return ret; -} - -static int smu_fini_fb_allocations(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - struct smu_table *driver_table = &(smu_table->driver_table); - - if (!tables) - return 0; - - if (tables[SMU_TABLE_PMSTATUSLOG].mc_address) - amdgpu_bo_free_kernel(&tables[SMU_TABLE_PMSTATUSLOG].bo, - &tables[SMU_TABLE_PMSTATUSLOG].mc_address, - &tables[SMU_TABLE_PMSTATUSLOG].cpu_addr); - - amdgpu_bo_free_kernel(&driver_table->bo, - &driver_table->mc_address, - &driver_table->cpu_addr); - - return 0; -} - -/** - * smu_alloc_memory_pool - allocate memory pool in the system memory - * - * @smu: amdgpu_device pointer - * - * This memory pool will be used for SMC use and msg SetSystemVirtualDramAddr - * and DramLogSetDramAddr can notify it changed. - * - * Returns 0 on success, error on failure. - */ -static int smu_alloc_memory_pool(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *memory_pool = &smu_table->memory_pool; - uint64_t pool_size = smu->pool_size; - int ret = 0; - - if (pool_size == SMU_MEMORY_POOL_SIZE_ZERO) - return ret; - - memory_pool->size = pool_size; - memory_pool->align = PAGE_SIZE; - memory_pool->domain = AMDGPU_GEM_DOMAIN_GTT; - - switch (pool_size) { - case SMU_MEMORY_POOL_SIZE_256_MB: - case SMU_MEMORY_POOL_SIZE_512_MB: - case SMU_MEMORY_POOL_SIZE_1_GB: - case SMU_MEMORY_POOL_SIZE_2_GB: - ret = amdgpu_bo_create_kernel(adev, - memory_pool->size, - memory_pool->align, - memory_pool->domain, - &memory_pool->bo, - &memory_pool->mc_address, - &memory_pool->cpu_addr); - if (ret) - dev_err(adev->dev, "VRAM allocation for dramlog failed!\n"); - break; - default: - break; - } - - return ret; -} - -static int smu_free_memory_pool(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *memory_pool = &smu_table->memory_pool; - - if (memory_pool->size == SMU_MEMORY_POOL_SIZE_ZERO) - return 0; - - amdgpu_bo_free_kernel(&memory_pool->bo, - &memory_pool->mc_address, - &memory_pool->cpu_addr); - - memset(memory_pool, 0, sizeof(struct smu_table)); - - return 0; -} - -static int smu_smc_table_sw_init(struct smu_context *smu) -{ - int ret; - - /** - * Create smu_table structure, and init smc tables such as - * TABLE_PPTABLE, TABLE_WATERMARKS, TABLE_SMU_METRICS, and etc. - */ - ret = smu_init_smc_tables(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to init smc tables!\n"); - return ret; - } - - /** - * Create smu_power_context structure, and allocate smu_dpm_context and - * context size to fill the smu_power_context data. - */ - ret = smu_init_power(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to init smu_init_power!\n"); - return ret; - } - - /* - * allocate vram bos to store smc table contents. - */ - ret = smu_init_fb_allocations(smu); - if (ret) - return ret; - - ret = smu_alloc_memory_pool(smu); - if (ret) - return ret; - - ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c); - if (ret) - return ret; - - return 0; -} - -static int smu_smc_table_sw_fini(struct smu_context *smu) -{ - int ret; - - smu_i2c_fini(smu, &smu->adev->pm.smu_i2c); - - ret = smu_free_memory_pool(smu); - if (ret) - return ret; - - ret = smu_fini_fb_allocations(smu); - if (ret) - return ret; - - ret = smu_fini_power(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to init smu_fini_power!\n"); - return ret; - } - - ret = smu_fini_smc_tables(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to smu_fini_smc_tables!\n"); - return ret; - } - - return 0; -} - -static void smu_throttling_logging_work_fn(struct work_struct *work) -{ - struct smu_context *smu = container_of(work, struct smu_context, - throttling_logging_work); - - smu_log_thermal_throttling(smu); -} - -static int smu_sw_init(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - int ret; - - smu->pool_size = adev->pm.smu_prv_buffer_size; - smu->smu_feature.feature_num = SMU_FEATURE_MAX; - mutex_init(&smu->smu_feature.mutex); - bitmap_zero(smu->smu_feature.supported, SMU_FEATURE_MAX); - bitmap_zero(smu->smu_feature.enabled, SMU_FEATURE_MAX); - bitmap_zero(smu->smu_feature.allowed, SMU_FEATURE_MAX); - - mutex_init(&smu->smu_baco.mutex); - smu->smu_baco.state = SMU_BACO_STATE_EXIT; - smu->smu_baco.platform_support = false; - - mutex_init(&smu->sensor_lock); - mutex_init(&smu->metrics_lock); - 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; - - atomic_set(&smu->smu_power.power_gate.vcn_gated, 1); - atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1); - mutex_init(&smu->smu_power.power_gate.vcn_gate_lock); - mutex_init(&smu->smu_power.power_gate.jpeg_gate_lock); - - smu->workload_mask = 1 << smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; - smu->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; - smu->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; - smu->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; - smu->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; - smu->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; - smu->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; - smu->workload_prority[PP_SMC_POWER_PROFILE_CUSTOM] = 6; - - smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; - smu->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; - smu->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; - smu->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE; - smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM; - smu->display_config = &adev->pm.pm_display_cfg; - - smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - smu->smu_dpm.requested_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - ret = smu_init_microcode(smu); - if (ret) { - dev_err(adev->dev, "Failed to load smu firmware!\n"); - return ret; - } - - ret = smu_smc_table_sw_init(smu); - if (ret) { - dev_err(adev->dev, "Failed to sw init smc table!\n"); - return ret; - } - - ret = smu_register_irq_handler(smu); - if (ret) { - dev_err(adev->dev, "Failed to register smc irq handler!\n"); - return ret; - } - - return 0; -} - -static int smu_sw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - int ret; - - ret = smu_smc_table_sw_fini(smu); - if (ret) { - dev_err(adev->dev, "Failed to sw fini smc table!\n"); - return ret; - } - - smu_fini_microcode(smu); - - return 0; -} - -static int smu_get_thermal_temperature_range(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_temperature_range *range = - &smu->thermal_range; - int ret = 0; - - if (!smu->ppt_funcs->get_thermal_temperature_range) - return 0; - - ret = smu->ppt_funcs->get_thermal_temperature_range(smu, range); - if (ret) - return ret; - - adev->pm.dpm.thermal.min_temp = range->min; - adev->pm.dpm.thermal.max_temp = range->max; - adev->pm.dpm.thermal.max_edge_emergency_temp = range->edge_emergency_max; - adev->pm.dpm.thermal.min_hotspot_temp = range->hotspot_min; - adev->pm.dpm.thermal.max_hotspot_crit_temp = range->hotspot_crit_max; - adev->pm.dpm.thermal.max_hotspot_emergency_temp = range->hotspot_emergency_max; - adev->pm.dpm.thermal.min_mem_temp = range->mem_min; - adev->pm.dpm.thermal.max_mem_crit_temp = range->mem_crit_max; - adev->pm.dpm.thermal.max_mem_emergency_temp = range->mem_emergency_max; - - return ret; -} - -static int smu_smc_hw_setup(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t pcie_gen = 0, pcie_width = 0; - int ret; - - if (adev->in_suspend && smu_is_dpm_running(smu)) { - dev_info(adev->dev, "dpm has been enabled\n"); - return 0; - } - - ret = smu_init_display_count(smu, 0); - if (ret) { - dev_info(adev->dev, "Failed to pre-set display count as 0!\n"); - return ret; - } - - ret = smu_set_driver_table_location(smu); - if (ret) { - dev_err(adev->dev, "Failed to SetDriverDramAddr!\n"); - return ret; - } - - /* - * Set PMSTATUSLOG table bo address with SetToolsDramAddr MSG for tools. - */ - ret = smu_set_tool_table_location(smu); - if (ret) { - dev_err(adev->dev, "Failed to SetToolsDramAddr!\n"); - return ret; - } - - /* - * Use msg SetSystemVirtualDramAddr and DramLogSetDramAddr can notify - * pool location. - */ - ret = smu_notify_memory_pool_location(smu); - if (ret) { - dev_err(adev->dev, "Failed to SetDramLogDramAddr!\n"); - return ret; - } - - /* smu_dump_pptable(smu); */ - /* - * Copy pptable bo in the vram to smc with SMU MSGs such as - * SetDriverDramAddr and TransferTableDram2Smu. - */ - ret = smu_write_pptable(smu); - if (ret) { - dev_err(adev->dev, "Failed to transfer pptable to SMC!\n"); - return ret; - } - - /* issue Run*Btc msg */ - ret = smu_run_btc(smu); - if (ret) - return ret; - - ret = smu_feature_set_allowed_mask(smu); - if (ret) { - dev_err(adev->dev, "Failed to set driver allowed features mask!\n"); - return ret; - } - - ret = smu_system_features_control(smu, true); - if (ret) { - dev_err(adev->dev, "Failed to enable requested dpm features!\n"); - return ret; - } - - if (!smu_is_dpm_running(smu)) - dev_info(adev->dev, "dpm has been disabled\n"); - - if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) - pcie_gen = 3; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) - pcie_gen = 2; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) - pcie_gen = 1; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) - pcie_gen = 0; - - /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 - * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 - * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 - */ - if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) - pcie_width = 6; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) - pcie_width = 5; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) - pcie_width = 4; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) - pcie_width = 3; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) - pcie_width = 2; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) - pcie_width = 1; - ret = smu_update_pcie_parameters(smu, pcie_gen, pcie_width); - if (ret) { - dev_err(adev->dev, "Attempt to override pcie params failed!\n"); - return ret; - } - - ret = smu_get_thermal_temperature_range(smu); - if (ret) { - dev_err(adev->dev, "Failed to get thermal temperature ranges!\n"); - return ret; - } - - ret = smu_enable_thermal_alert(smu); - if (ret) { - dev_err(adev->dev, "Failed to enable thermal alert!\n"); - return ret; - } - - ret = smu_disable_umc_cdr_12gbps_workaround(smu); - if (ret) { - dev_err(adev->dev, "Workaround failed to disable UMC CDR feature on 12Gbps SKU!\n"); - return ret; - } - - /* - * For Navi1X, manually switch it to AC mode as PMFW - * may boot it with DC mode. - */ - ret = smu_set_power_source(smu, - adev->pm.ac_power ? SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) { - dev_err(adev->dev, "Failed to switch to %s mode!\n", adev->pm.ac_power ? "AC" : "DC"); - return ret; - } - - ret = smu_notify_display_change(smu); - if (ret) - return ret; - - /* - * Set min deep sleep dce fclk with bootup value from vbios via - * SetMinDeepSleepDcefclk MSG. - */ - ret = smu_set_min_dcef_deep_sleep(smu, - smu->smu_table.boot_values.dcefclk / 100); - if (ret) - return ret; - - return ret; -} - -static int smu_start_smc_engine(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) { - if (adev->asic_type < CHIP_NAVI10) { - if (smu->ppt_funcs->load_microcode) { - ret = smu->ppt_funcs->load_microcode(smu); - if (ret) - return ret; - } - } - } - - if (smu->ppt_funcs->check_fw_status) { - ret = smu->ppt_funcs->check_fw_status(smu); - if (ret) { - dev_err(adev->dev, "SMC is not ready\n"); - return ret; - } - } - - /* - * Send msg GetDriverIfVersion to check if the return value is equal - * with DRIVER_IF_VERSION of smc header. - */ - ret = smu_check_fw_version(smu); - if (ret) - return ret; - - return ret; -} - -static int smu_hw_init(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - - if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) { - smu->pm_enabled = false; - return 0; - } - - ret = smu_start_smc_engine(smu); - if (ret) { - dev_err(adev->dev, "SMC engine is not correctly up!\n"); - return ret; - } - - if (smu->is_apu) { - smu_powergate_sdma(&adev->smu, false); - smu_dpm_set_vcn_enable(smu, true); - smu_dpm_set_jpeg_enable(smu, true); - smu_set_gfx_cgpg(&adev->smu, true); - } - - if (!smu->pm_enabled) - return 0; - - /* get boot_values from vbios to set revision, gfxclk, and etc. */ - ret = smu_get_vbios_bootup_values(smu); - if (ret) { - dev_err(adev->dev, "Failed to get VBIOS boot clock values!\n"); - return ret; - } - - ret = smu_setup_pptable(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup pptable!\n"); - return ret; - } - - ret = smu_get_driver_allowed_feature_mask(smu); - if (ret) - return ret; - - ret = smu_smc_hw_setup(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup smc hw!\n"); - return ret; - } - - /* - * Move maximum sustainable clock retrieving here considering - * 1. It is not needed on resume(from S3). - * 2. DAL settings come between .hw_init and .late_init of SMU. - * And DAL needs to know the maximum sustainable clocks. Thus - * it cannot be put in .late_init(). - */ - ret = smu_init_max_sustainable_clocks(smu); - if (ret) { - dev_err(adev->dev, "Failed to init max sustainable clocks!\n"); - return ret; - } - - adev->pm.dpm_enabled = true; - - dev_info(adev->dev, "SMU is initialized successfully!\n"); - - return 0; -} - -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_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || - ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); - - /* - * For custom pptable uploading, skip the DPM features - * disable process on Navi1x ASICs. - * - As the gfx related features are under control of - * RLC on those ASICs. RLC reinitialization will be - * needed to reenable them. That will cost much more - * efforts. - * - * - SMU firmware can handle the DPM reenablement - * properly. - */ - if (smu->uploading_custom_pp_table && - (adev->asic_type >= CHIP_NAVI10) && - (adev->asic_type <= CHIP_NAVI12)) - return 0; - - /* - * For Sienna_Cichlid, PMFW will handle the features disablement properly - * on BACO in. Driver involvement is unnecessary. - */ - if ((adev->asic_type == CHIP_SIENNA_CICHLID) && - use_baco) - return 0; - - /* - * For gpu reset, runpm and hibernation through BACO, - * BACO feature has to be kept enabled. - */ - if (use_baco && smu_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) { - ret = smu_disable_all_features_with_exception(smu, - SMU_FEATURE_BACO_BIT); - if (ret) - dev_err(adev->dev, "Failed to disable smu features except BACO.\n"); - } else { - ret = smu_system_features_control(smu, false); - if (ret) - dev_err(adev->dev, "Failed to disable smu features.\n"); - } - - if (adev->asic_type >= CHIP_NAVI10 && - adev->gfx.rlc.funcs->stop) - adev->gfx.rlc.funcs->stop(adev); - - return ret; -} - -static int smu_smc_hw_cleanup(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - cancel_work_sync(&smu->throttling_logging_work); - - ret = smu_disable_thermal_alert(smu); - if (ret) { - dev_err(adev->dev, "Fail to disable thermal alert!\n"); - return ret; - } - - ret = smu_disable_dpms(smu); - if (ret) { - dev_err(adev->dev, "Fail to disable dpm features!\n"); - return ret; - } - - return 0; -} - -static int smu_hw_fini(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - int ret = 0; - - if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) - return 0; - - if (smu->is_apu) { - smu_powergate_sdma(&adev->smu, true); - smu_dpm_set_vcn_enable(smu, false); - smu_dpm_set_jpeg_enable(smu, false); - } - - if (!smu->pm_enabled) - return 0; - - adev->pm.dpm_enabled = false; - - ret = smu_smc_hw_cleanup(smu); - if (ret) - return ret; - - return 0; -} - -int smu_reset(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - ret = smu_hw_fini(adev); - if (ret) - return ret; - - ret = smu_hw_init(adev); - if (ret) - return ret; - - ret = smu_late_init(adev); - - return ret; -} - -static int smu_suspend(void *handle) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - int ret; - - if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) - return 0; - - if (!smu->pm_enabled) - return 0; - - adev->pm.dpm_enabled = false; - - ret = smu_smc_hw_cleanup(smu); - if (ret) - return ret; - - smu->watermarks_bitmap &= ~(WATERMARKS_LOADED); - - if (smu->is_apu) - smu_set_gfx_cgpg(&adev->smu, false); - - return 0; -} - -static int smu_resume(void *handle) -{ - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - struct smu_context *smu = &adev->smu; - - if (amdgpu_sriov_vf(adev)&& !amdgpu_sriov_is_pp_one_vf(adev)) - return 0; - - if (!smu->pm_enabled) - return 0; - - dev_info(adev->dev, "SMU is resuming...\n"); - - ret = smu_start_smc_engine(smu); - if (ret) { - dev_err(adev->dev, "SMC engine is not correctly up!\n"); - return ret; - } - - ret = smu_smc_hw_setup(smu); - if (ret) { - dev_err(adev->dev, "Failed to setup smc hw!\n"); - return ret; - } - - if (smu->is_apu) - smu_set_gfx_cgpg(&adev->smu, true); - - smu->disable_uclk_switch = 0; - - adev->pm.dpm_enabled = true; - - dev_info(adev->dev, "SMU is resumed successfully!\n"); - - return 0; -} - -int smu_display_configuration_change(struct smu_context *smu, - const struct amd_pp_display_configuration *display_config) -{ - int index = 0; - int num_of_active_display = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!display_config) - return -EINVAL; - - mutex_lock(&smu->mutex); - - smu_set_min_dcef_deep_sleep(smu, - display_config->min_dcef_deep_sleep_set_clk / 100); - - for (index = 0; index < display_config->num_path_including_non_display; index++) { - if (display_config->displays[index].controller_id != 0) - num_of_active_display++; - } - - smu_set_active_display_count(smu, num_of_active_display); - - smu_store_cc6_data(smu, display_config->cpu_pstate_separation_time, - display_config->cpu_cc6_disable, - display_config->cpu_pstate_disable, - display_config->nb_pstate_switch_disable); - - mutex_unlock(&smu->mutex); - - return 0; -} - -static int smu_get_clock_info(struct smu_context *smu, - struct smu_clock_info *clk_info, - enum smu_perf_level_designation designation) -{ - int ret; - struct smu_performance_level level = {0}; - - if (!clk_info) - return -EINVAL; - - ret = smu_get_perf_level(smu, PERF_LEVEL_ACTIVITY, &level); - if (ret) - return -EINVAL; - - clk_info->min_mem_clk = level.memory_clock; - clk_info->min_eng_clk = level.core_clock; - clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width; - - ret = smu_get_perf_level(smu, designation, &level); - if (ret) - return -EINVAL; - - clk_info->min_mem_clk = level.memory_clock; - clk_info->min_eng_clk = level.core_clock; - clk_info->min_bus_bandwidth = level.non_local_mem_freq * level.non_local_mem_width; - - return 0; -} - -int smu_get_current_clocks(struct smu_context *smu, - struct amd_pp_clock_info *clocks) -{ - struct amd_pp_simple_clock_info simple_clocks = {0}; - struct smu_clock_info hw_clocks; - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - smu_get_dal_power_level(smu, &simple_clocks); - - if (smu->support_power_containment) - ret = smu_get_clock_info(smu, &hw_clocks, - PERF_LEVEL_POWER_CONTAINMENT); - else - ret = smu_get_clock_info(smu, &hw_clocks, PERF_LEVEL_ACTIVITY); - - if (ret) { - dev_err(smu->adev->dev, "Error in smu_get_clock_info\n"); - goto failed; - } - - clocks->min_engine_clock = hw_clocks.min_eng_clk; - clocks->max_engine_clock = hw_clocks.max_eng_clk; - clocks->min_memory_clock = hw_clocks.min_mem_clk; - clocks->max_memory_clock = hw_clocks.max_mem_clk; - clocks->min_bus_bandwidth = hw_clocks.min_bus_bandwidth; - clocks->max_bus_bandwidth = hw_clocks.max_bus_bandwidth; - clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; - clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; - - if (simple_clocks.level == 0) - clocks->max_clocks_state = PP_DAL_POWERLEVEL_7; - else - clocks->max_clocks_state = simple_clocks.level; - - if (!smu_get_current_shallow_sleep_clocks(smu, &hw_clocks)) { - clocks->max_engine_clock_in_sr = hw_clocks.max_eng_clk; - clocks->min_engine_clock_in_sr = hw_clocks.min_eng_clk; - } - -failed: - mutex_unlock(&smu->mutex); - return ret; -} - -static int smu_set_clockgating_state(void *handle, - enum amd_clockgating_state state) -{ - return 0; -} - -static int smu_set_powergating_state(void *handle, - enum amd_powergating_state state) -{ - return 0; -} - -static int smu_enable_umd_pstate(void *handle, - enum amd_dpm_forced_level *level) -{ - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - - struct smu_context *smu = (struct smu_context*)(handle); - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - - if (!smu->is_apu && !smu_dpm_ctx->dpm_context) - return -EINVAL; - - if (!(smu_dpm_ctx->dpm_level & profile_mode_mask)) { - /* enter umd pstate, save current level, disable gfx cg*/ - if (*level & profile_mode_mask) { - smu_dpm_ctx->saved_dpm_level = smu_dpm_ctx->dpm_level; - smu_dpm_ctx->enable_umd_pstate = true; - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_UNGATE); - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_UNGATE); - } - } else { - /* exit umd pstate, restore level, enable gfx cg*/ - if (!(*level & profile_mode_mask)) { - if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) - *level = smu_dpm_ctx->saved_dpm_level; - smu_dpm_ctx->enable_umd_pstate = false; - amdgpu_device_ip_set_clockgating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_CG_STATE_GATE); - amdgpu_device_ip_set_powergating_state(smu->adev, - AMD_IP_BLOCK_TYPE_GFX, - AMD_PG_STATE_GATE); - } - } - - return 0; -} - -static int smu_adjust_power_state_dynamic(struct smu_context *smu, - enum amd_dpm_forced_level level, - bool skip_display_settings) -{ - int ret = 0; - int index = 0; - long workload; - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - - if (!skip_display_settings) { - ret = smu_display_config_changed(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to change display config!"); - return ret; - } - } - - ret = smu_apply_clocks_adjust_rules(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to apply clocks adjust rules!"); - return ret; - } - - if (!skip_display_settings) { - ret = smu_notify_smc_display_config(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to notify smc display config!"); - return ret; - } - } - - if (smu_dpm_ctx->dpm_level != level) { - ret = smu_asic_set_performance_level(smu, level); - if (ret) { - dev_err(smu->adev->dev, "Failed to set performance level!"); - return ret; - } - - /* update the saved copy */ - smu_dpm_ctx->dpm_level = level; - } - - if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { - index = fls(smu->workload_mask); - index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; - workload = smu->workload_setting[index]; - - if (smu->power_profile_mode != workload) - smu_set_power_profile_mode(smu, &workload, 0, false); - } - - return ret; -} - -int smu_handle_task(struct smu_context *smu, - enum amd_dpm_forced_level level, - enum amd_pp_task task_id, - bool lock_needed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (lock_needed) - mutex_lock(&smu->mutex); - - switch (task_id) { - case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: - ret = smu_pre_display_config_changed(smu); - if (ret) - goto out; - ret = smu_set_cpu_power_state(smu); - if (ret) - goto out; - ret = smu_adjust_power_state_dynamic(smu, level, false); - break; - case AMD_PP_TASK_COMPLETE_INIT: - case AMD_PP_TASK_READJUST_POWER_STATE: - ret = smu_adjust_power_state_dynamic(smu, level, true); - break; - default: - break; - } - -out: - if (lock_needed) - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_switch_power_profile(struct smu_context *smu, - enum PP_SMC_POWER_PROFILE type, - bool en) -{ - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - long workload; - uint32_t index; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!(type < PP_SMC_POWER_PROFILE_CUSTOM)) - return -EINVAL; - - mutex_lock(&smu->mutex); - - if (!en) { - smu->workload_mask &= ~(1 << smu->workload_prority[type]); - index = fls(smu->workload_mask); - index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; - workload = smu->workload_setting[index]; - } else { - smu->workload_mask |= (1 << smu->workload_prority[type]); - index = fls(smu->workload_mask); - index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0; - workload = smu->workload_setting[index]; - } - - if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) - smu_set_power_profile_mode(smu, &workload, 0, false); - - mutex_unlock(&smu->mutex); - - return 0; -} - -enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu) -{ - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - enum amd_dpm_forced_level level; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu->is_apu && !smu_dpm_ctx->dpm_context) - return -EINVAL; - - mutex_lock(&(smu->mutex)); - level = smu_dpm_ctx->dpm_level; - mutex_unlock(&(smu->mutex)); - - return level; -} - -int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level) -{ - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu->is_apu && !smu_dpm_ctx->dpm_context) - return -EINVAL; - - mutex_lock(&smu->mutex); - - ret = smu_enable_umd_pstate(smu, &level); - if (ret) { - mutex_unlock(&smu->mutex); - return ret; - } - - ret = smu_handle_task(smu, level, - AMD_PP_TASK_READJUST_POWER_STATE, - false); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_display_count(struct smu_context *smu, uint32_t count) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - ret = smu_init_display_count(smu, count); - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_force_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t mask) -{ - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { - dev_dbg(smu->adev->dev, "force clock level is for dpm manual mode only.\n"); - return -EINVAL; - } - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs && smu->ppt_funcs->force_clk_levels) - ret = smu->ppt_funcs->force_clk_levels(smu, clk_type, mask); - - mutex_unlock(&smu->mutex); - - return ret; -} - -/* - * On system suspending or resetting, the dpm_enabled - * flag will be cleared. So that those SMU services which - * are not supported will be gated. - * However, the mp1 state setting should still be granted - * even if the dpm_enabled cleared. - */ -int smu_set_mp1_state(struct smu_context *smu, - enum pp_mp1_state mp1_state) -{ - uint16_t msg; - int ret; - - if (!smu->pm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - switch (mp1_state) { - case PP_MP1_STATE_SHUTDOWN: - msg = SMU_MSG_PrepareMp1ForShutdown; - break; - case PP_MP1_STATE_UNLOAD: - msg = SMU_MSG_PrepareMp1ForUnload; - break; - case PP_MP1_STATE_RESET: - msg = SMU_MSG_PrepareMp1ForReset; - break; - case PP_MP1_STATE_NONE: - default: - mutex_unlock(&smu->mutex); - return 0; - } - - 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"); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_df_cstate(struct smu_context *smu, - enum pp_df_cstate state) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu->ppt_funcs || !smu->ppt_funcs->set_df_cstate) - return 0; - - mutex_lock(&smu->mutex); - - ret = smu->ppt_funcs->set_df_cstate(smu, state); - if (ret) - dev_err(smu->adev->dev, "[SetDfCstate] failed!\n"); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_allow_xgmi_power_down(struct smu_context *smu, bool en) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu->ppt_funcs || !smu->ppt_funcs->allow_xgmi_power_down) - return 0; - - mutex_lock(&smu->mutex); - - ret = smu->ppt_funcs->allow_xgmi_power_down(smu, en); - if (ret) - dev_err(smu->adev->dev, "[AllowXgmiPowerDown] failed!\n"); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_write_watermarks_table(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - ret = smu_set_watermarks_table(smu, NULL); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_watermarks_for_clock_ranges(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (!smu->disable_watermark && - smu_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_set_watermarks_table(smu, clock_ranges); - - if (!(smu->watermarks_bitmap & WATERMARKS_EXIST)) { - smu->watermarks_bitmap |= WATERMARKS_EXIST; - smu->watermarks_bitmap &= ~WATERMARKS_LOADED; - } - } - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_ac_dc(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - /* controlled by firmware */ - if (smu->dc_controlled_by_gpio) - return 0; - - mutex_lock(&smu->mutex); - ret = smu_set_power_source(smu, - smu->adev->pm.ac_power ? SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) - dev_err(smu->adev->dev, "Failed to switch to %s mode!\n", - smu->adev->pm.ac_power ? "AC" : "DC"); - mutex_unlock(&smu->mutex); - - return ret; -} - -const struct amd_ip_funcs smu_ip_funcs = { - .name = "smu", - .early_init = smu_early_init, - .late_init = smu_late_init, - .sw_init = smu_sw_init, - .sw_fini = smu_sw_fini, - .hw_init = smu_hw_init, - .hw_fini = smu_hw_fini, - .suspend = smu_suspend, - .resume = smu_resume, - .is_idle = NULL, - .check_soft_reset = NULL, - .wait_for_idle = NULL, - .soft_reset = NULL, - .set_clockgating_state = smu_set_clockgating_state, - .set_powergating_state = smu_set_powergating_state, - .enable_umd_pstate = smu_enable_umd_pstate, -}; - -const struct amdgpu_ip_block_version smu_v11_0_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 11, - .minor = 0, - .rev = 0, - .funcs = &smu_ip_funcs, -}; - -const struct amdgpu_ip_block_version smu_v12_0_ip_block = -{ - .type = AMD_IP_BLOCK_TYPE_SMC, - .major = 12, - .minor = 0, - .rev = 0, - .funcs = &smu_ip_funcs, -}; - -int smu_load_microcode(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->load_microcode) - ret = smu->ppt_funcs->load_microcode(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_check_fw_status(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->check_fw_status) - ret = smu->ppt_funcs->check_fw_status(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled) -{ - int ret = 0; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_gfx_cgpg) - ret = smu->ppt_funcs->set_gfx_cgpg(smu, enabled); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_fan_speed_rpm) - ret = smu->ppt_funcs->set_fan_speed_rpm(smu, speed); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_power_limit(struct smu_context *smu, - uint32_t *limit, - bool max_setting) -{ - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - *limit = (max_setting ? smu->max_power_limit : smu->current_power_limit); - - mutex_unlock(&smu->mutex); - - return 0; -} - -int smu_set_power_limit(struct smu_context *smu, uint32_t limit) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (limit > smu->max_power_limit) { - dev_err(smu->adev->dev, - "New power limit (%d) is over the max allowed %d\n", - limit, smu->max_power_limit); - goto out; - } - - if (!limit) - limit = smu->current_power_limit; - - if (smu->ppt_funcs->set_power_limit) - ret = smu->ppt_funcs->set_power_limit(smu, limit); - -out: - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->print_clk_levels) - ret = smu->ppt_funcs->print_clk_levels(smu, clk_type, buf); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_od_percentage) - ret = smu->ppt_funcs->get_od_percentage(smu, type); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_od_percentage) - ret = smu->ppt_funcs->set_od_percentage(smu, type, value); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_od_edit_dpm_table(struct smu_context *smu, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->od_edit_dpm_table) { - ret = smu->ppt_funcs->od_edit_dpm_table(smu, type, input, size); - if (!ret && (type == PP_OD_COMMIT_DPM_TABLE)) - ret = smu_handle_task(smu, - smu->smu_dpm.dpm_level, - AMD_PP_TASK_READJUST_POWER_STATE, - false); - } - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - struct smu_umd_pstate_table *pstate_table = - &smu->pstate_table; - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!data || !size) - return -EINVAL; - - 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; - *size = 4; - break; - case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK: - *((uint32_t *)data) = pstate_table->uclk_pstate.standard * 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: - ret = smu_feature_get_enabled_mask(smu, (uint32_t *)data, 2); - *size = 8; - break; - case AMDGPU_PP_SENSOR_UVD_POWER: - *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_UVD_BIT) ? 1 : 0; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VCE_POWER: - *(uint32_t *)data = smu_feature_is_enabled(smu, SMU_FEATURE_DPM_VCE_BIT) ? 1 : 0; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VCN_POWER_STATE: - *(uint32_t *)data = atomic_read(&smu->smu_power.power_gate.vcn_gated) ? 0: 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MIN_FAN_RPM: - *(uint32_t *)data = 0; - *size = 4; - break; - default: - *size = 0; - ret = -EOPNOTSUPP; - break; - } - -unlock: - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_power_profile_mode(struct smu_context *smu, char *buf) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_power_profile_mode) - ret = smu->ppt_funcs->get_power_profile_mode(smu, buf); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_power_profile_mode(struct smu_context *smu, - long *param, - uint32_t param_size, - bool lock_needed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (lock_needed) - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_power_profile_mode) - ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size); - - if (lock_needed) - mutex_unlock(&smu->mutex); - - return ret; -} - - -int smu_get_fan_control_mode(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_fan_control_mode) - ret = smu->ppt_funcs->get_fan_control_mode(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_fan_control_mode(struct smu_context *smu, int value) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_fan_control_mode) - ret = smu->ppt_funcs->set_fan_control_mode(smu, value); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_fan_speed_percent) - ret = smu->ppt_funcs->get_fan_speed_percent(smu, speed); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_fan_speed_percent) - ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_fan_speed_rpm) - ret = smu->ppt_funcs->get_fan_speed_rpm(smu, speed); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - ret = smu_set_min_dcef_deep_sleep(smu, clk); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_active_display_count(struct smu_context *smu, uint32_t count) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (smu->ppt_funcs->set_active_display_count) - ret = smu->ppt_funcs->set_active_display_count(smu, count); - - return ret; -} - -int smu_get_clock_by_type(struct smu_context *smu, - enum amd_pp_clock_type type, - struct amd_pp_clocks *clocks) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_clock_by_type) - ret = smu->ppt_funcs->get_clock_by_type(smu, type, clocks); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_max_high_clocks(struct smu_context *smu, - struct amd_pp_simple_clock_info *clocks) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_max_high_clocks) - ret = smu->ppt_funcs->get_max_high_clocks(smu, clocks); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_clock_by_type_with_latency(struct smu_context *smu, - enum smu_clk_type clk_type, - struct pp_clock_levels_with_latency *clocks) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_clock_by_type_with_latency) - ret = smu->ppt_funcs->get_clock_by_type_with_latency(smu, clk_type, clocks); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_clock_by_type_with_voltage(struct smu_context *smu, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_clock_by_type_with_voltage) - ret = smu->ppt_funcs->get_clock_by_type_with_voltage(smu, type, clocks); - - mutex_unlock(&smu->mutex); - - return ret; -} - - -int smu_display_clock_voltage_request(struct smu_context *smu, - struct pp_display_clock_request *clock_req) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->display_clock_voltage_request) - ret = smu->ppt_funcs->display_clock_voltage_request(smu, clock_req); - - mutex_unlock(&smu->mutex); - - return ret; -} - - -int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disable_memory_clock_switch) -{ - int ret = -EINVAL; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->display_disable_memory_clock_switch) - ret = smu->ppt_funcs->display_disable_memory_clock_switch(smu, disable_memory_clock_switch); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_notify_smu_enable_pwe(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->notify_smu_enable_pwe) - ret = smu->ppt_funcs->notify_smu_enable_pwe(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_set_xgmi_pstate(struct smu_context *smu, - uint32_t pstate) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_xgmi_pstate) - ret = smu->ppt_funcs->set_xgmi_pstate(smu, pstate); - - mutex_unlock(&smu->mutex); - - if(ret) - dev_err(smu->adev->dev, "Failed to set XGMI pstate!\n"); - - return ret; -} - -int smu_set_azalia_d3_pme(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->set_azalia_d3_pme) - ret = smu->ppt_funcs->set_azalia_d3_pme(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -/* - * On system suspending or resetting, the dpm_enabled - * flag will be cleared. So that those SMU services which - * are not supported will be gated. - * - * However, the baco/mode1 reset should still be granted - * as they are still supported and necessary. - */ -bool smu_baco_is_support(struct smu_context *smu) -{ - bool ret = false; - - if (!smu->pm_enabled) - return false; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs && smu->ppt_funcs->baco_is_support) - ret = smu->ppt_funcs->baco_is_support(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_baco_get_state(struct smu_context *smu, enum smu_baco_state *state) -{ - if (smu->ppt_funcs->baco_get_state) - return -EINVAL; - - mutex_lock(&smu->mutex); - *state = smu->ppt_funcs->baco_get_state(smu); - mutex_unlock(&smu->mutex); - - return 0; -} - -int smu_baco_enter(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->baco_enter) - ret = smu->ppt_funcs->baco_enter(smu); - - mutex_unlock(&smu->mutex); - - if (ret) - dev_err(smu->adev->dev, "Failed to enter BACO state!\n"); - - return ret; -} - -int smu_baco_exit(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->baco_exit) - ret = smu->ppt_funcs->baco_exit(smu); - - mutex_unlock(&smu->mutex); - - if (ret) - dev_err(smu->adev->dev, "Failed to exit BACO state!\n"); - - return ret; -} - -bool smu_mode1_reset_is_support(struct smu_context *smu) -{ - bool ret = false; - - if (!smu->pm_enabled) - return false; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs && smu->ppt_funcs->mode1_reset_is_support) - ret = smu->ppt_funcs->mode1_reset_is_support(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_mode1_reset(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->mode1_reset) - ret = smu->ppt_funcs->mode1_reset(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_mode2_reset(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->mode2_reset) - ret = smu->ppt_funcs->mode2_reset(smu); - - mutex_unlock(&smu->mutex); - - if (ret) - dev_err(smu->adev->dev, "Mode2 reset failed!\n"); - - return ret; -} - -int smu_get_max_sustainable_clocks_by_dc(struct smu_context *smu, - struct pp_smu_nv_clock_table *max_clocks) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_max_sustainable_clocks_by_dc) - ret = smu->ppt_funcs->get_max_sustainable_clocks_by_dc(smu, max_clocks); - - mutex_unlock(&smu->mutex); - - return ret; -} - -int smu_get_uclk_dpm_states(struct smu_context *smu, - unsigned int *clock_values_in_khz, - unsigned int *num_states) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_uclk_dpm_states) - ret = smu->ppt_funcs->get_uclk_dpm_states(smu, clock_values_in_khz, num_states); - - mutex_unlock(&smu->mutex); - - return ret; -} - -enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu) -{ - enum amd_pm_state_type pm_state = POWER_STATE_TYPE_DEFAULT; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_current_power_state) - pm_state = smu->ppt_funcs->get_current_power_state(smu); - - mutex_unlock(&smu->mutex); - - return pm_state; -} - -int smu_get_dpm_clock_table(struct smu_context *smu, - struct dpm_clocks *clock_table) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->get_dpm_clock_table) - ret = smu->ppt_funcs->get_dpm_clock_table(smu, clock_table); - - mutex_unlock(&smu->mutex); - - return ret; -} - -ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, - void **table) -{ - ssize_t size; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - if (!smu->ppt_funcs->get_gpu_metrics) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - size = smu->ppt_funcs->get_gpu_metrics(smu, table); - - mutex_unlock(&smu->mutex); - - return size; -} - -int smu_enable_mgpu_fan_boost(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) - return -EOPNOTSUPP; - - mutex_lock(&smu->mutex); - - if (smu->ppt_funcs->enable_mgpu_fan_boost) - ret = smu->ppt_funcs->enable_mgpu_fan_boost(smu); - - mutex_unlock(&smu->mutex); - - return ret; -} diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c deleted file mode 100644 index 81f43fea4d52..000000000000 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ /dev/null @@ -1,2405 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#define SWSMU_CODE_LAYER_L2 - -#include -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "atomfirmware.h" -#include "amdgpu_atomfirmware.h" -#include "amdgpu_atombios.h" -#include "smu_v11_0.h" -#include "smu11_driver_if_arcturus.h" -#include "soc15_common.h" -#include "atom.h" -#include "power_state.h" -#include "arcturus_ppt.h" -#include "smu_v11_0_pptable.h" -#include "arcturus_ppsmc.h" -#include "nbio/nbio_7_4_offset.h" -#include "nbio/nbio_7_4_sh_mask.h" -#include "thm/thm_11_0_2_offset.h" -#include "thm/thm_11_0_2_sh_mask.h" -#include "amdgpu_xgmi.h" -#include -#include -#include "amdgpu_ras.h" -#include "smu_cmn.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - -#define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \ - [smu_feature] = {1, (arcturus_feature)} - -#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF -#define SMU_FEATURES_LOW_SHIFT 0 -#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 -#define SMU_FEATURES_HIGH_SHIFT 32 - -#define SMC_DPM_FEATURE ( \ - FEATURE_DPM_PREFETCHER_MASK | \ - FEATURE_DPM_GFXCLK_MASK | \ - FEATURE_DPM_UCLK_MASK | \ - FEATURE_DPM_SOCCLK_MASK | \ - FEATURE_DPM_MP0CLK_MASK | \ - FEATURE_DPM_FCLK_MASK | \ - FEATURE_DPM_XGMI_MASK) - -/* possible frequency drift (1Mhz) */ -#define EPSILON 1 - -#define smnPCIE_ESM_CTRL 0x111003D0 - -static const struct cmn2asic_msg_mapping arcturus_message_map[SMU_MSG_MAX_COUNT] = { - MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 0), - MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1), - MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 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, 0), - MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 0), - MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 0), - MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 0), - MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), - MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), - MSG_MAP(SetToolsDramAddrHigh, PPSMC_MSG_SetToolsDramAddrHigh, 0), - MSG_MAP(SetToolsDramAddrLow, PPSMC_MSG_SetToolsDramAddrLow, 0), - MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), - MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), - MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), - MSG_MAP(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), - MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0), - MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0), - MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), - MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), - MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), - MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), - MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), - MSG_MAP(SetHardMinByFreq, PPSMC_MSG_SetHardMinByFreq, 0), - MSG_MAP(SetHardMaxByFreq, PPSMC_MSG_SetHardMaxByFreq, 0), - MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 0), - MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 0), - MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), - MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 1), - MSG_MAP(SetDfSwitchType, PPSMC_MSG_SetDfSwitchType, 0), - MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), - MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), - MSG_MAP(SetPptLimit, PPSMC_MSG_SetPptLimit, 0), - MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 1), - MSG_MAP(PowerUpVcn0, PPSMC_MSG_PowerUpVcn0, 0), - MSG_MAP(PowerDownVcn0, PPSMC_MSG_PowerDownVcn0, 0), - MSG_MAP(PowerUpVcn1, PPSMC_MSG_PowerUpVcn1, 0), - MSG_MAP(PowerDownVcn1, PPSMC_MSG_PowerDownVcn1, 0), - MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0), - MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0), - MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 0), - MSG_MAP(SoftReset, PPSMC_MSG_SoftReset, 0), - MSG_MAP(RunAfllBtc, PPSMC_MSG_RunAfllBtc, 0), - MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), - MSG_MAP(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), - MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), - MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), - MSG_MAP(GetDebugData, PPSMC_MSG_GetDebugData, 0), - MSG_MAP(WaflTest, PPSMC_MSG_WaflTest, 0), - MSG_MAP(SetXgmiMode, PPSMC_MSG_SetXgmiMode, 0), - MSG_MAP(SetMemoryChannelEnable, PPSMC_MSG_SetMemoryChannelEnable, 0), - MSG_MAP(DFCstateControl, PPSMC_MSG_DFCstateControl, 0), - MSG_MAP(GmiPwrDnControl, PPSMC_MSG_GmiPwrDnControl, 0), - MSG_MAP(ReadSerialNumTop32, PPSMC_MSG_ReadSerialNumTop32, 1), - MSG_MAP(ReadSerialNumBottom32, PPSMC_MSG_ReadSerialNumBottom32, 1), -}; - -static const struct cmn2asic_mapping arcturus_clk_map[SMU_CLK_COUNT] = { - CLK_MAP(GFXCLK, PPCLK_GFXCLK), - CLK_MAP(SCLK, PPCLK_GFXCLK), - CLK_MAP(SOCCLK, PPCLK_SOCCLK), - CLK_MAP(FCLK, PPCLK_FCLK), - CLK_MAP(UCLK, PPCLK_UCLK), - CLK_MAP(MCLK, PPCLK_UCLK), - CLK_MAP(DCLK, PPCLK_DCLK), - CLK_MAP(VCLK, PPCLK_VCLK), -}; - -static const struct cmn2asic_mapping arcturus_feature_mask_map[SMU_FEATURE_COUNT] = { - FEA_MAP(DPM_PREFETCHER), - FEA_MAP(DPM_GFXCLK), - FEA_MAP(DPM_UCLK), - FEA_MAP(DPM_SOCCLK), - FEA_MAP(DPM_FCLK), - FEA_MAP(DPM_MP0CLK), - ARCTURUS_FEA_MAP(SMU_FEATURE_XGMI_BIT, FEATURE_DPM_XGMI_BIT), - FEA_MAP(DS_GFXCLK), - FEA_MAP(DS_SOCCLK), - FEA_MAP(DS_LCLK), - FEA_MAP(DS_FCLK), - FEA_MAP(DS_UCLK), - FEA_MAP(GFX_ULV), - ARCTURUS_FEA_MAP(SMU_FEATURE_VCN_PG_BIT, FEATURE_DPM_VCN_BIT), - FEA_MAP(RSMU_SMN_CG), - FEA_MAP(WAFL_CG), - FEA_MAP(PPT), - FEA_MAP(TDC), - FEA_MAP(APCC_PLUS), - FEA_MAP(VR0HOT), - FEA_MAP(VR1HOT), - FEA_MAP(FW_CTF), - FEA_MAP(FAN_CONTROL), - FEA_MAP(THERMAL), - FEA_MAP(OUT_OF_BAND_MONITOR), - FEA_MAP(TEMP_DEPENDENT_VMIN), -}; - -static const struct cmn2asic_mapping arcturus_table_map[SMU_TABLE_COUNT] = { - TAB_MAP(PPTABLE), - TAB_MAP(AVFS), - TAB_MAP(AVFS_PSM_DEBUG), - TAB_MAP(AVFS_FUSE_OVERRIDE), - TAB_MAP(PMSTATUSLOG), - TAB_MAP(SMU_METRICS), - TAB_MAP(DRIVER_SMU_CONFIG), - TAB_MAP(OVERDRIVE), - TAB_MAP(I2C_COMMANDS), - TAB_MAP(ACTIVITY_MONITOR_COEFF), -}; - -static const struct cmn2asic_mapping arcturus_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { - PWR_MAP(AC), - PWR_MAP(DC), -}; - -static const struct cmn2asic_mapping arcturus_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), -}; - -static int arcturus_tables_init(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - - SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - - SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - - SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - - SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, - sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM); - - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); - if (!smu_table->metrics_table) - return -ENOMEM; - smu_table->metrics_time = 0; - - smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); - smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); - if (!smu_table->gpu_metrics_table) { - kfree(smu_table->metrics_table); - return -ENOMEM; - } - - return 0; -} - -static int arcturus_allocate_dpm_context(struct smu_context *smu) -{ - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - - smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), - GFP_KERNEL); - if (!smu_dpm->dpm_context) - return -ENOMEM; - smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); - - smu_dpm->dpm_current_power_state = kzalloc(sizeof(struct smu_power_state), - GFP_KERNEL); - if (!smu_dpm->dpm_current_power_state) - return -ENOMEM; - - smu_dpm->dpm_request_power_state = kzalloc(sizeof(struct smu_power_state), - GFP_KERNEL); - if (!smu_dpm->dpm_request_power_state) - return -ENOMEM; - - return 0; -} - -static int arcturus_init_smc_tables(struct smu_context *smu) -{ - int ret = 0; - - ret = arcturus_tables_init(smu); - if (ret) - return ret; - - ret = arcturus_allocate_dpm_context(smu); - if (ret) - return ret; - - return smu_v11_0_init_smc_tables(smu); -} - -static int -arcturus_get_allowed_feature_mask(struct smu_context *smu, - uint32_t *feature_mask, uint32_t num) -{ - if (num > 2) - return -EINVAL; - - /* pptable will handle the features to enable */ - memset(feature_mask, 0xFF, sizeof(uint32_t) * num); - - return 0; -} - -static int arcturus_set_default_dpm_table(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - PPTable_t *driver_ppt = smu->smu_table.driver_pptable; - struct smu_11_0_dpm_table *dpm_table = NULL; - int ret = 0; - - /* socclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.soc_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_SOCCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* gfxclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.gfx_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_GFXCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* memclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.uclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_UCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* fclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.fclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_FCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - return 0; -} - -static int arcturus_check_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - struct smu_baco_context *smu_baco = &smu->smu_baco; - - mutex_lock(&smu_baco->mutex); - if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || - powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) - smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); - - table_context->thermal_controller_type = - powerplay_table->thermal_controller_type; - - return 0; -} - -static int arcturus_store_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - - memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, - sizeof(PPTable_t)); - - return 0; -} - -static int arcturus_append_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *smc_pptable = table_context->driver_pptable; - struct atom_smc_dpm_info_v4_6 *smc_dpm_table; - int index, ret; - - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - smc_dpm_info); - - ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, - (uint8_t **)&smc_dpm_table); - if (ret) - return ret; - - dev_info(smu->adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n", - smc_dpm_table->table_header.format_revision, - smc_dpm_table->table_header.content_revision); - - if ((smc_dpm_table->table_header.format_revision == 4) && - (smc_dpm_table->table_header.content_revision == 6)) - memcpy(&smc_pptable->MaxVoltageStepGfx, - &smc_dpm_table->maxvoltagestepgfx, - sizeof(*smc_dpm_table) - offsetof(struct atom_smc_dpm_info_v4_6, maxvoltagestepgfx)); - - return 0; -} - -static int arcturus_setup_pptable(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_v11_0_setup_pptable(smu); - if (ret) - return ret; - - ret = arcturus_store_powerplay_table(smu); - if (ret) - return ret; - - ret = arcturus_append_powerplay_table(smu); - if (ret) - return ret; - - ret = arcturus_check_powerplay_table(smu); - if (ret) - return ret; - - return ret; -} - -static int arcturus_run_btc(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunAfllBtc, NULL); - if (ret) { - dev_err(smu->adev->dev, "RunAfllBtc failed!\n"); - return ret; - } - - return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); -} - -static int arcturus_populate_umd_state_clk(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = - smu->smu_dpm.dpm_context; - struct smu_11_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_11_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_11_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_umd_pstate_table *pstate_table = - &smu->pstate_table; - - pstate_table->gfxclk_pstate.min = gfx_table->min; - pstate_table->gfxclk_pstate.peak = gfx_table->max; - - pstate_table->uclk_pstate.min = mem_table->min; - pstate_table->uclk_pstate.peak = mem_table->max; - - pstate_table->socclk_pstate.min = soc_table->min; - pstate_table->socclk_pstate.peak = soc_table->max; - - if (gfx_table->count > ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL && - mem_table->count > ARCTURUS_UMD_PSTATE_MCLK_LEVEL && - soc_table->count > ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL) { - pstate_table->gfxclk_pstate.standard = - gfx_table->dpm_levels[ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL].value; - pstate_table->uclk_pstate.standard = - mem_table->dpm_levels[ARCTURUS_UMD_PSTATE_MCLK_LEVEL].value; - pstate_table->socclk_pstate.standard = - soc_table->dpm_levels[ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL].value; - } else { - pstate_table->gfxclk_pstate.standard = - pstate_table->gfxclk_pstate.min; - pstate_table->uclk_pstate.standard = - pstate_table->uclk_pstate.min; - pstate_table->socclk_pstate.standard = - pstate_table->socclk_pstate.min; - } - - return 0; -} - -static int arcturus_get_clk_table(struct smu_context *smu, - struct pp_clock_levels_with_latency *clocks, - struct smu_11_0_dpm_table *dpm_table) -{ - int i, count; - - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = count; - - for (i = 0; i < count; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - clocks->data[i].latency_in_us = 0; - } - - return 0; -} - -static int arcturus_freqs_in_same_level(int32_t frequency1, - int32_t frequency2) -{ - return (abs(frequency1 - frequency2) <= EPSILON); -} - -static int arcturus_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) -{ - struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); - return ret; - } - - switch (member) { - case METRICS_CURR_GFXCLK: - *value = metrics->CurrClock[PPCLK_GFXCLK]; - break; - case METRICS_CURR_SOCCLK: - *value = metrics->CurrClock[PPCLK_SOCCLK]; - break; - case METRICS_CURR_UCLK: - *value = metrics->CurrClock[PPCLK_UCLK]; - break; - case METRICS_CURR_VCLK: - *value = metrics->CurrClock[PPCLK_VCLK]; - break; - case METRICS_CURR_DCLK: - *value = metrics->CurrClock[PPCLK_DCLK]; - break; - case METRICS_CURR_FCLK: - *value = metrics->CurrClock[PPCLK_FCLK]; - break; - case METRICS_AVERAGE_GFXCLK: - *value = metrics->AverageGfxclkFrequency; - break; - case METRICS_AVERAGE_SOCCLK: - *value = metrics->AverageSocclkFrequency; - break; - case METRICS_AVERAGE_UCLK: - *value = metrics->AverageUclkFrequency; - break; - case METRICS_AVERAGE_VCLK: - *value = metrics->AverageVclkFrequency; - break; - case METRICS_AVERAGE_DCLK: - *value = metrics->AverageDclkFrequency; - break; - case METRICS_AVERAGE_GFXACTIVITY: - *value = metrics->AverageGfxActivity; - break; - case METRICS_AVERAGE_MEMACTIVITY: - *value = metrics->AverageUclkActivity; - break; - case METRICS_AVERAGE_VCNACTIVITY: - *value = metrics->VcnActivityPercentage; - break; - case METRICS_AVERAGE_SOCKETPOWER: - *value = metrics->AverageSocketPower << 8; - break; - case METRICS_TEMPERATURE_EDGE: - *value = metrics->TemperatureEdge * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_HOTSPOT: - *value = metrics->TemperatureHotspot * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_MEM: - *value = metrics->TemperatureHBM * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRGFX: - *value = metrics->TemperatureVrGfx * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRSOC: - *value = metrics->TemperatureVrSoc * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRMEM: - *value = metrics->TemperatureVrMem * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_THROTTLER_STATUS: - *value = metrics->ThrottlerStatus; - break; - case METRICS_CURR_FANSPEED: - *value = metrics->CurrFanSpeed; - break; - default: - *value = UINT_MAX; - break; - } - - mutex_unlock(&smu->metrics_lock); - - return ret; -} - -static int arcturus_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - MetricsMember_t member_type; - int clk_id = 0; - - if (!value) - return -EINVAL; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return -EINVAL; - - switch (clk_id) { - case PPCLK_GFXCLK: - /* - * CurrClock[clk_id] can provide accurate - * output only when the dpm feature is enabled. - * We can use Average_* for dpm disabled case. - * But this is available for gfxclk/uclk/socclk/vclk/dclk. - */ - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) - member_type = METRICS_CURR_GFXCLK; - else - member_type = METRICS_AVERAGE_GFXCLK; - break; - case PPCLK_UCLK: - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) - member_type = METRICS_CURR_UCLK; - else - member_type = METRICS_AVERAGE_UCLK; - break; - case PPCLK_SOCCLK: - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) - member_type = METRICS_CURR_SOCCLK; - else - member_type = METRICS_AVERAGE_SOCCLK; - break; - case PPCLK_VCLK: - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) - member_type = METRICS_CURR_VCLK; - else - member_type = METRICS_AVERAGE_VCLK; - break; - case PPCLK_DCLK: - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) - member_type = METRICS_CURR_DCLK; - else - member_type = METRICS_AVERAGE_DCLK; - break; - case PPCLK_FCLK: - member_type = METRICS_CURR_FCLK; - break; - default: - return -EINVAL; - } - - return arcturus_get_smu_metrics_data(smu, - member_type, - value); -} - -static int arcturus_print_clk_levels(struct smu_context *smu, - enum smu_clk_type type, char *buf) -{ - int i, now, size = 0; - int ret = 0; - struct pp_clock_levels_with_latency clocks; - struct smu_11_0_dpm_table *single_dpm_table; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = NULL; - - if (amdgpu_ras_intr_triggered()) - return snprintf(buf, PAGE_SIZE, "unavailable\n"); - - dpm_context = smu_dpm->dpm_context; - - switch (type) { - case SMU_SCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, &now); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get current gfx clk Failed!"); - return ret; - } - - single_dpm_table = &(dpm_context->dpm_tables.gfx_table); - ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get gfx clk levels Failed!"); - return ret; - } - - /* - * For DPM disabled case, there will be only one clock level. - * And it's safe to assume that is always the current clock. - */ - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", i, - clocks.data[i].clocks_in_khz / 1000, - (clocks.num_levels == 1) ? "*" : - (arcturus_freqs_in_same_level( - clocks.data[i].clocks_in_khz / 1000, - now) ? "*" : "")); - break; - - case SMU_MCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, &now); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get current mclk Failed!"); - return ret; - } - - single_dpm_table = &(dpm_context->dpm_tables.uclk_table); - ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get memory clk levels Failed!"); - return ret; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.num_levels == 1) ? "*" : - (arcturus_freqs_in_same_level( - clocks.data[i].clocks_in_khz / 1000, - now) ? "*" : "")); - break; - - case SMU_SOCCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_SOCCLK, &now); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get current socclk Failed!"); - return ret; - } - - single_dpm_table = &(dpm_context->dpm_tables.soc_table); - ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get socclk levels Failed!"); - return ret; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.num_levels == 1) ? "*" : - (arcturus_freqs_in_same_level( - clocks.data[i].clocks_in_khz / 1000, - now) ? "*" : "")); - break; - - case SMU_FCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_FCLK, &now); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get current fclk Failed!"); - return ret; - } - - single_dpm_table = &(dpm_context->dpm_tables.fclk_table); - ret = arcturus_get_clk_table(smu, &clocks, single_dpm_table); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get fclk levels Failed!"); - return ret; - } - - for (i = 0; i < single_dpm_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, single_dpm_table->dpm_levels[i].value, - (clocks.num_levels == 1) ? "*" : - (arcturus_freqs_in_same_level( - clocks.data[i].clocks_in_khz / 1000, - now) ? "*" : "")); - break; - - default: - break; - } - - return size; -} - -static int arcturus_upload_dpm_level(struct smu_context *smu, - bool max, - uint32_t feature_mask, - uint32_t level) -{ - struct smu_11_0_dpm_context *dpm_context = - smu->smu_dpm.dpm_context; - uint32_t freq; - int ret = 0; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT) && - (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { - freq = dpm_context->dpm_tables.gfx_table.dpm_levels[level].value; - ret = smu_cmn_send_smc_msg_with_param(smu, - (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_GFXCLK << 16) | (freq & 0xffff), - NULL); - if (ret) { - dev_err(smu->adev->dev, "Failed to set soft %s gfxclk !\n", - max ? "max" : "min"); - return ret; - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && - (feature_mask & FEATURE_DPM_UCLK_MASK)) { - freq = dpm_context->dpm_tables.uclk_table.dpm_levels[level].value; - ret = smu_cmn_send_smc_msg_with_param(smu, - (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_UCLK << 16) | (freq & 0xffff), - NULL); - if (ret) { - dev_err(smu->adev->dev, "Failed to set soft %s memclk !\n", - max ? "max" : "min"); - return ret; - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT) && - (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { - freq = dpm_context->dpm_tables.soc_table.dpm_levels[level].value; - ret = smu_cmn_send_smc_msg_with_param(smu, - (max ? SMU_MSG_SetSoftMaxByFreq : SMU_MSG_SetSoftMinByFreq), - (PPCLK_SOCCLK << 16) | (freq & 0xffff), - NULL); - if (ret) { - dev_err(smu->adev->dev, "Failed to set soft %s socclk !\n", - max ? "max" : "min"); - return ret; - } - } - - return ret; -} - -static int arcturus_force_clk_levels(struct smu_context *smu, - enum smu_clk_type type, uint32_t mask) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - struct smu_11_0_dpm_table *single_dpm_table = NULL; - uint32_t soft_min_level, soft_max_level; - uint32_t smu_version; - int ret = 0; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) { - dev_err(smu->adev->dev, "Failed to get smu version!\n"); - return ret; - } - - if ((smu_version >= 0x361200) && - (smu_version <= 0x361a00)) { - dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 - 54.26(included) SMU firmwares\n"); - return -EOPNOTSUPP; - } - - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - switch (type) { - case SMU_SCLK: - single_dpm_table = &(dpm_context->dpm_tables.gfx_table); - if (soft_max_level >= single_dpm_table->count) { - dev_err(smu->adev->dev, "Clock level specified %d is over max allowed %d\n", - soft_max_level, single_dpm_table->count - 1); - ret = -EINVAL; - break; - } - - ret = arcturus_upload_dpm_level(smu, - false, - FEATURE_DPM_GFXCLK_MASK, - soft_min_level); - if (ret) { - dev_err(smu->adev->dev, "Failed to upload boot level to lowest!\n"); - break; - } - - ret = arcturus_upload_dpm_level(smu, - true, - FEATURE_DPM_GFXCLK_MASK, - soft_max_level); - if (ret) - dev_err(smu->adev->dev, "Failed to upload dpm max level to highest!\n"); - - break; - - case SMU_MCLK: - case SMU_SOCCLK: - case SMU_FCLK: - /* - * Should not arrive here since Arcturus does not - * support mclk/socclk/fclk softmin/softmax settings - */ - ret = -EINVAL; - break; - - default: - break; - } - - return ret; -} - -static int arcturus_get_thermal_temperature_range(struct smu_context *smu, - struct smu_temperature_range *range) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - if (!range) - return -EINVAL; - - memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); - - range->max = pptable->TedgeLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_crit_max = pptable->ThotspotLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_crit_max = pptable->TmemLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->software_shutdown_temp = powerplay_table->software_shutdown_temp; - - return 0; -} - -static int arcturus_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static int arcturus_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return arcturus_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int arcturus_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = arcturus_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - -static int arcturus_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *pptable = table_context->driver_pptable; - int ret = 0; - - if (amdgpu_ras_intr_triggered()) - return 0; - - if (!data || !size) - return -EINVAL; - - mutex_lock(&smu->sensor_lock); - switch (sensor) { - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: - *(uint32_t *)data = pptable->FanMaximumRpm; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = arcturus_get_current_activity_percent(smu, - sensor, - (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - ret = arcturus_get_gpu_power(smu, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - case AMDGPU_PP_SENSOR_EDGE_TEMP: - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = arcturus_thermal_get_temperature(smu, sensor, - (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); - /* the output clock frequency in 10K unit */ - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = arcturus_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VDDGFX: - ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - mutex_unlock(&smu->sensor_lock); - - return ret; -} - -static int arcturus_get_fan_speed_rpm(struct smu_context *smu, - uint32_t *speed) -{ - if (!speed) - return -EINVAL; - - return arcturus_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); -} - -static int arcturus_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t percent, current_rpm; - int ret = 0; - - if (!speed) - return -EINVAL; - - ret = arcturus_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - -static int arcturus_get_power_limit(struct smu_context *smu) -{ - struct smu_11_0_powerplay_table *powerplay_table = - (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t power_limit, od_percent; - - if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; - } - smu->current_power_limit = power_limit; - - if (smu->od_enabled) { - od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); - - dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - - power_limit *= (100 + od_percent); - power_limit /= 100; - } - smu->max_power_limit = power_limit; - - return 0; -} - -static int arcturus_get_power_profile_mode(struct smu_context *smu, - char *buf) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - static const char *profile_name[] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - static const char *title[] = { - "PROFILE_INDEX(NAME)", - "CLOCK_TYPE(NAME)", - "FPS", - "UseRlcBusy", - "MinActiveFreqType", - "MinActiveFreq", - "BoosterFreqType", - "BoosterFreq", - "PD_Data_limit_c", - "PD_Data_error_coeff", - "PD_Data_error_rate_coeff"}; - uint32_t i, size = 0; - int16_t workload_type = 0; - int result = 0; - uint32_t smu_version; - - if (!buf) - return -EINVAL; - - result = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (result) - return result; - - if (smu_version >= 0x360d00) - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", - title[0], title[1], title[2], title[3], title[4], title[5], - title[6], title[7], title[8], title[9], title[10]); - else - size += sprintf(buf + size, "%16s\n", - title[0]); - - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { - /* - * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT - * Not all profile modes are supported on arcturus. - */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - i); - if (workload_type < 0) - continue; - - if (smu_version >= 0x360d00) { - result = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, - workload_type, - (void *)(&activity_monitor), - false); - if (result) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return result; - } - } - - size += sprintf(buf + size, "%2d %14s%s\n", - i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); - - if (smu_version >= 0x360d00) { - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 0, - "GFXCLK", - activity_monitor.Gfx_FPS, - activity_monitor.Gfx_UseRlcBusy, - activity_monitor.Gfx_MinActiveFreqType, - activity_monitor.Gfx_MinActiveFreq, - activity_monitor.Gfx_BoosterFreqType, - activity_monitor.Gfx_BoosterFreq, - activity_monitor.Gfx_PD_Data_limit_c, - activity_monitor.Gfx_PD_Data_error_coeff, - activity_monitor.Gfx_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 1, - "UCLK", - activity_monitor.Mem_FPS, - activity_monitor.Mem_UseRlcBusy, - activity_monitor.Mem_MinActiveFreqType, - activity_monitor.Mem_MinActiveFreq, - activity_monitor.Mem_BoosterFreqType, - activity_monitor.Mem_BoosterFreq, - activity_monitor.Mem_PD_Data_limit_c, - activity_monitor.Mem_PD_Data_error_coeff, - activity_monitor.Mem_PD_Data_error_rate_coeff); - } - } - - return size; -} - -static int arcturus_set_power_profile_mode(struct smu_context *smu, - long *input, - uint32_t size) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - int workload_type = 0; - uint32_t profile_mode = input[size]; - int ret = 0; - uint32_t smu_version; - - if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); - return -EINVAL; - } - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) - return ret; - - if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) && - (smu_version >=0x360d00)) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, - WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), - false); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return ret; - } - - switch (input[0]) { - case 0: /* Gfxclk */ - activity_monitor.Gfx_FPS = input[1]; - activity_monitor.Gfx_UseRlcBusy = input[2]; - activity_monitor.Gfx_MinActiveFreqType = input[3]; - activity_monitor.Gfx_MinActiveFreq = input[4]; - activity_monitor.Gfx_BoosterFreqType = input[5]; - activity_monitor.Gfx_BoosterFreq = input[6]; - activity_monitor.Gfx_PD_Data_limit_c = input[7]; - activity_monitor.Gfx_PD_Data_error_coeff = input[8]; - activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; - break; - case 1: /* Uclk */ - activity_monitor.Mem_FPS = input[1]; - activity_monitor.Mem_UseRlcBusy = input[2]; - activity_monitor.Mem_MinActiveFreqType = input[3]; - activity_monitor.Mem_MinActiveFreq = input[4]; - activity_monitor.Mem_BoosterFreqType = input[5]; - activity_monitor.Mem_BoosterFreq = input[6]; - activity_monitor.Mem_PD_Data_limit_c = input[7]; - activity_monitor.Mem_PD_Data_error_coeff = input[8]; - activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; - break; - } - - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, - WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), - true); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); - return ret; - } - } - - /* - * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT - * Not all profile modes are supported on arcturus. - */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - profile_mode); - if (workload_type < 0) { - dev_err(smu->adev->dev, "Unsupported power profile mode %d on arcturus\n", profile_mode); - return -EINVAL; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetWorkloadMask, - 1 << workload_type, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type); - return ret; - } - - smu->power_profile_mode = profile_mode; - - return 0; -} - -static int arcturus_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - uint32_t smu_version; - int ret; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) { - dev_err(smu->adev->dev, "Failed to get smu version!\n"); - return ret; - } - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - case AMD_DPM_FORCED_LEVEL_LOW: - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - if ((smu_version >= 0x361200) && - (smu_version <= 0x361a00)) { - dev_err(smu->adev->dev, "Forcing clock level is not supported with " - "54.18 - 54.26(included) SMU firmwares\n"); - return -EOPNOTSUPP; - } - break; - default: - break; - } - - return smu_v11_0_set_performance_level(smu, level); -} - -static void arcturus_dump_pptable(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *pptable = table_context->driver_pptable; - int i; - - dev_info(smu->adev->dev, "Dumped PPTable:\n"); - - dev_info(smu->adev->dev, "Version = 0x%08x\n", pptable->Version); - - dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); - dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); - - for (i = 0; i < PPT_THROTTLER_COUNT; i++) { - dev_info(smu->adev->dev, "SocketPowerLimitAc[%d] = %d\n", i, pptable->SocketPowerLimitAc[i]); - dev_info(smu->adev->dev, "SocketPowerLimitAcTau[%d] = %d\n", i, pptable->SocketPowerLimitAcTau[i]); - } - - dev_info(smu->adev->dev, "TdcLimitSoc = %d\n", pptable->TdcLimitSoc); - dev_info(smu->adev->dev, "TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau); - dev_info(smu->adev->dev, "TdcLimitGfx = %d\n", pptable->TdcLimitGfx); - dev_info(smu->adev->dev, "TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau); - - dev_info(smu->adev->dev, "TedgeLimit = %d\n", pptable->TedgeLimit); - dev_info(smu->adev->dev, "ThotspotLimit = %d\n", pptable->ThotspotLimit); - dev_info(smu->adev->dev, "TmemLimit = %d\n", pptable->TmemLimit); - dev_info(smu->adev->dev, "Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit); - dev_info(smu->adev->dev, "Tvr_memLimit = %d\n", pptable->Tvr_memLimit); - dev_info(smu->adev->dev, "Tvr_socLimit = %d\n", pptable->Tvr_socLimit); - dev_info(smu->adev->dev, "FitLimit = %d\n", pptable->FitLimit); - - dev_info(smu->adev->dev, "PpmPowerLimit = %d\n", pptable->PpmPowerLimit); - dev_info(smu->adev->dev, "PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold); - - dev_info(smu->adev->dev, "ThrottlerControlMask = %d\n", pptable->ThrottlerControlMask); - - dev_info(smu->adev->dev, "UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx); - dev_info(smu->adev->dev, "UlvPadding = 0x%08x\n", pptable->UlvPadding); - - dev_info(smu->adev->dev, "UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass); - dev_info(smu->adev->dev, "Padding234[0] = 0x%02x\n", pptable->Padding234[0]); - dev_info(smu->adev->dev, "Padding234[1] = 0x%02x\n", pptable->Padding234[1]); - dev_info(smu->adev->dev, "Padding234[2] = 0x%02x\n", pptable->Padding234[2]); - - dev_info(smu->adev->dev, "MinVoltageGfx = %d\n", pptable->MinVoltageGfx); - dev_info(smu->adev->dev, "MinVoltageSoc = %d\n", pptable->MinVoltageSoc); - dev_info(smu->adev->dev, "MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx); - dev_info(smu->adev->dev, "MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc); - - dev_info(smu->adev->dev, "LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx); - dev_info(smu->adev->dev, "LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc); - - dev_info(smu->adev->dev, "[PPCLK_GFXCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_GFXCLK].padding, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_GFXCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_VCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_VCLK].padding, - pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_VCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_VCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_DCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DCLK].padding, - pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_DCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_DCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_SOCCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_SOCCLK].padding, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_SOCCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_UCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_UCLK].padding, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_UCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_UCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_FCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_FCLK].padding, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_FCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_FCLK].Padding16); - - - dev_info(smu->adev->dev, "FreqTableGfx\n"); - for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableGfx[i]); - - dev_info(smu->adev->dev, "FreqTableVclk\n"); - for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableVclk[i]); - - dev_info(smu->adev->dev, "FreqTableDclk\n"); - for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableDclk[i]); - - dev_info(smu->adev->dev, "FreqTableSocclk\n"); - for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]); - - dev_info(smu->adev->dev, "FreqTableUclk\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableUclk[i]); - - dev_info(smu->adev->dev, "FreqTableFclk\n"); - for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = %d\n", i, pptable->FreqTableFclk[i]); - - dev_info(smu->adev->dev, "Mp0clkFreq\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->Mp0clkFreq[i]); - - dev_info(smu->adev->dev, "Mp0DpmVoltage\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]); - - dev_info(smu->adev->dev, "GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); - dev_info(smu->adev->dev, "GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate); - dev_info(smu->adev->dev, "Padding567[0] = 0x%x\n", pptable->Padding567[0]); - dev_info(smu->adev->dev, "Padding567[1] = 0x%x\n", pptable->Padding567[1]); - dev_info(smu->adev->dev, "Padding567[2] = 0x%x\n", pptable->Padding567[2]); - dev_info(smu->adev->dev, "Padding567[3] = 0x%x\n", pptable->Padding567[3]); - dev_info(smu->adev->dev, "GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq); - dev_info(smu->adev->dev, "GfxclkSource = 0x%x\n", pptable->GfxclkSource); - dev_info(smu->adev->dev, "Padding456 = 0x%x\n", pptable->Padding456); - - dev_info(smu->adev->dev, "EnableTdpm = %d\n", pptable->EnableTdpm); - dev_info(smu->adev->dev, "TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature); - dev_info(smu->adev->dev, "TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature); - dev_info(smu->adev->dev, "GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit); - - dev_info(smu->adev->dev, "FanStopTemp = %d\n", pptable->FanStopTemp); - dev_info(smu->adev->dev, "FanStartTemp = %d\n", pptable->FanStartTemp); - - dev_info(smu->adev->dev, "FanGainEdge = %d\n", pptable->FanGainEdge); - dev_info(smu->adev->dev, "FanGainHotspot = %d\n", pptable->FanGainHotspot); - dev_info(smu->adev->dev, "FanGainVrGfx = %d\n", pptable->FanGainVrGfx); - dev_info(smu->adev->dev, "FanGainVrSoc = %d\n", pptable->FanGainVrSoc); - dev_info(smu->adev->dev, "FanGainVrMem = %d\n", pptable->FanGainVrMem); - dev_info(smu->adev->dev, "FanGainHbm = %d\n", pptable->FanGainHbm); - - dev_info(smu->adev->dev, "FanPwmMin = %d\n", pptable->FanPwmMin); - dev_info(smu->adev->dev, "FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm); - dev_info(smu->adev->dev, "FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm); - dev_info(smu->adev->dev, "FanMaximumRpm = %d\n", pptable->FanMaximumRpm); - dev_info(smu->adev->dev, "FanTargetTemperature = %d\n", pptable->FanTargetTemperature); - dev_info(smu->adev->dev, "FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk); - dev_info(smu->adev->dev, "FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable); - dev_info(smu->adev->dev, "FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev); - dev_info(smu->adev->dev, "FanTempInputSelect = %d\n", pptable->FanTempInputSelect); - - dev_info(smu->adev->dev, "FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved); - - dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]); - dev_info(smu->adev->dev, "Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]); - - dev_info(smu->adev->dev, "dBtcGbGfxPll{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxPll.a, - pptable->dBtcGbGfxPll.b, - pptable->dBtcGbGfxPll.c); - dev_info(smu->adev->dev, "dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxAfll.a, - pptable->dBtcGbGfxAfll.b, - pptable->dBtcGbGfxAfll.c); - dev_info(smu->adev->dev, "dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbSoc.a, - pptable->dBtcGbSoc.b, - pptable->dBtcGbSoc.c); - - dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, - pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); - dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, - pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); - - dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); - dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); - - dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); - dev_info(smu->adev->dev, "Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); - - dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "XgmiDpmPstates\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiDpmPstates[i]); - dev_info(smu->adev->dev, "XgmiDpmSpare[0] = 0x%02x\n", pptable->XgmiDpmSpare[0]); - dev_info(smu->adev->dev, "XgmiDpmSpare[1] = 0x%02x\n", pptable->XgmiDpmSpare[1]); - - dev_info(smu->adev->dev, "VDDGFX_TVmin = %d\n", pptable->VDDGFX_TVmin); - dev_info(smu->adev->dev, "VDDSOC_TVmin = %d\n", pptable->VDDSOC_TVmin); - dev_info(smu->adev->dev, "VDDGFX_Vmin_HiTemp = %d\n", pptable->VDDGFX_Vmin_HiTemp); - dev_info(smu->adev->dev, "VDDGFX_Vmin_LoTemp = %d\n", pptable->VDDGFX_Vmin_LoTemp); - dev_info(smu->adev->dev, "VDDSOC_Vmin_HiTemp = %d\n", pptable->VDDSOC_Vmin_HiTemp); - dev_info(smu->adev->dev, "VDDSOC_Vmin_LoTemp = %d\n", pptable->VDDSOC_Vmin_LoTemp); - dev_info(smu->adev->dev, "VDDGFX_TVminHystersis = %d\n", pptable->VDDGFX_TVminHystersis); - dev_info(smu->adev->dev, "VDDSOC_TVminHystersis = %d\n", pptable->VDDSOC_TVminHystersis); - - dev_info(smu->adev->dev, "DebugOverrides = 0x%x\n", pptable->DebugOverrides); - dev_info(smu->adev->dev, "ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation0.a, - pptable->ReservedEquation0.b, - pptable->ReservedEquation0.c); - dev_info(smu->adev->dev, "ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation1.a, - pptable->ReservedEquation1.b, - pptable->ReservedEquation1.c); - dev_info(smu->adev->dev, "ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation2.a, - pptable->ReservedEquation2.b, - pptable->ReservedEquation2.c); - dev_info(smu->adev->dev, "ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation3.a, - pptable->ReservedEquation3.b, - pptable->ReservedEquation3.c); - - dev_info(smu->adev->dev, "MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx); - dev_info(smu->adev->dev, "PaddingUlv = %d\n", pptable->PaddingUlv); - - dev_info(smu->adev->dev, "TotalPowerConfig = %d\n", pptable->TotalPowerConfig); - dev_info(smu->adev->dev, "TotalPowerSpare1 = %d\n", pptable->TotalPowerSpare1); - dev_info(smu->adev->dev, "TotalPowerSpare2 = %d\n", pptable->TotalPowerSpare2); - - dev_info(smu->adev->dev, "PccThresholdLow = %d\n", pptable->PccThresholdLow); - dev_info(smu->adev->dev, "PccThresholdHigh = %d\n", pptable->PccThresholdHigh); - - dev_info(smu->adev->dev, "Board Parameters:\n"); - dev_info(smu->adev->dev, "MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx); - dev_info(smu->adev->dev, "MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc); - - dev_info(smu->adev->dev, "VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); - dev_info(smu->adev->dev, "VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); - dev_info(smu->adev->dev, "VddMemVrMapping = 0x%x\n", pptable->VddMemVrMapping); - dev_info(smu->adev->dev, "BoardVrMapping = 0x%x\n", pptable->BoardVrMapping); - - dev_info(smu->adev->dev, "GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); - dev_info(smu->adev->dev, "ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent); - - dev_info(smu->adev->dev, "GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); - dev_info(smu->adev->dev, "GfxOffset = 0x%x\n", pptable->GfxOffset); - dev_info(smu->adev->dev, "Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); - - dev_info(smu->adev->dev, "SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); - dev_info(smu->adev->dev, "SocOffset = 0x%x\n", pptable->SocOffset); - dev_info(smu->adev->dev, "Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); - - dev_info(smu->adev->dev, "MemMaxCurrent = 0x%x\n", pptable->MemMaxCurrent); - dev_info(smu->adev->dev, "MemOffset = 0x%x\n", pptable->MemOffset); - dev_info(smu->adev->dev, "Padding_TelemetryMem = 0x%x\n", pptable->Padding_TelemetryMem); - - dev_info(smu->adev->dev, "BoardMaxCurrent = 0x%x\n", pptable->BoardMaxCurrent); - dev_info(smu->adev->dev, "BoardOffset = 0x%x\n", pptable->BoardOffset); - dev_info(smu->adev->dev, "Padding_TelemetryBoardInput = 0x%x\n", pptable->Padding_TelemetryBoardInput); - - dev_info(smu->adev->dev, "VR0HotGpio = %d\n", pptable->VR0HotGpio); - dev_info(smu->adev->dev, "VR0HotPolarity = %d\n", pptable->VR0HotPolarity); - dev_info(smu->adev->dev, "VR1HotGpio = %d\n", pptable->VR1HotGpio); - dev_info(smu->adev->dev, "VR1HotPolarity = %d\n", pptable->VR1HotPolarity); - - dev_info(smu->adev->dev, "PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled); - dev_info(smu->adev->dev, "PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent); - dev_info(smu->adev->dev, "PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq); - - dev_info(smu->adev->dev, "UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled); - dev_info(smu->adev->dev, "UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent); - dev_info(smu->adev->dev, "UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq); - - dev_info(smu->adev->dev, "FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled); - dev_info(smu->adev->dev, "FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent); - dev_info(smu->adev->dev, "FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq); - - dev_info(smu->adev->dev, "FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled); - dev_info(smu->adev->dev, "FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent); - dev_info(smu->adev->dev, "FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq); - - for (i = 0; i < NUM_I2C_CONTROLLERS; i++) { - dev_info(smu->adev->dev, "I2cControllers[%d]:\n", i); - dev_info(smu->adev->dev, " .Enabled = %d\n", - pptable->I2cControllers[i].Enabled); - dev_info(smu->adev->dev, " .SlaveAddress = 0x%x\n", - pptable->I2cControllers[i].SlaveAddress); - dev_info(smu->adev->dev, " .ControllerPort = %d\n", - pptable->I2cControllers[i].ControllerPort); - dev_info(smu->adev->dev, " .ControllerName = %d\n", - pptable->I2cControllers[i].ControllerName); - dev_info(smu->adev->dev, " .ThermalThrottler = %d\n", - pptable->I2cControllers[i].ThermalThrotter); - dev_info(smu->adev->dev, " .I2cProtocol = %d\n", - pptable->I2cControllers[i].I2cProtocol); - dev_info(smu->adev->dev, " .Speed = %d\n", - pptable->I2cControllers[i].Speed); - } - - dev_info(smu->adev->dev, "MemoryChannelEnabled = %d\n", pptable->MemoryChannelEnabled); - dev_info(smu->adev->dev, "DramBitWidth = %d\n", pptable->DramBitWidth); - - dev_info(smu->adev->dev, "TotalBoardPower = %d\n", pptable->TotalBoardPower); - - dev_info(smu->adev->dev, "XgmiLinkSpeed\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]); - dev_info(smu->adev->dev, "XgmiLinkWidth\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]); - dev_info(smu->adev->dev, "XgmiFclkFreq\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]); - dev_info(smu->adev->dev, "XgmiSocVoltage\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]); - -} - -static bool arcturus_is_dpm_running(struct smu_context *smu) -{ - int ret = 0; - uint32_t feature_mask[2]; - unsigned long feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); - return !!(feature_enabled & SMC_DPM_FEATURE); -} - -static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 1); - if (ret) { - dev_err(smu->adev->dev, "[EnableVCNDPM] failed!\n"); - return ret; - } - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_VCN_PG_BIT, 0); - if (ret) { - dev_err(smu->adev->dev, "[DisableVCNDPM] failed!\n"); - return ret; - } - } - } - - return ret; -} - -static void arcturus_fill_i2c_req(SwI2cRequest_t *req, bool write, - uint8_t address, uint32_t numbytes, - uint8_t *data) -{ - int i; - - req->I2CcontrollerPort = 0; - req->I2CSpeed = 2; - req->SlaveAddress = address; - req->NumCmds = numbytes; - - for (i = 0; i < numbytes; i++) { - SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; - - /* First 2 bytes are always write for lower 2b EEPROM address */ - if (i < 2) - cmd->Cmd = 1; - else - cmd->Cmd = write; - - - /* Add RESTART for read after address filled */ - cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; - - /* Add STOP in the end */ - cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; - - /* Fill with data regardless if read or write to simplify code */ - cmd->RegisterAddr = data[i]; - } -} - -static int arcturus_i2c_read_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t i, ret = 0; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - struct smu_table_context *smu_table = &adev->smu.smu_table; - struct smu_table *table = &smu_table->driver_table; - - if (numbytes > MAX_SW_I2C_COMMANDS) { - dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", - numbytes, MAX_SW_I2C_COMMANDS); - return -EINVAL; - } - - memset(&req, 0, sizeof(req)); - arcturus_fill_i2c_req(&req, false, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - /* Now read data starting with that address */ - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, - true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; - - /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ - for (i = 0; i < numbytes; i++) - data[i] = res->SwI2cCmds[i].Data; - - dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes = %d, data :", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - } else - dev_err(adev->dev, "arcturus_i2c_read_data - error occurred :%x", ret); - - return ret; -} - -static int arcturus_i2c_write_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t ret; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - - if (numbytes > MAX_SW_I2C_COMMANDS) { - dev_err(adev->dev, "numbytes requested %d is over max allowed %d\n", - numbytes, MAX_SW_I2C_COMMANDS); - return -EINVAL; - } - - memset(&req, 0, sizeof(req)); - arcturus_fill_i2c_req(&req, true, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - dev_dbg(adev->dev, "arcturus_i2c_write(), address = %x, bytes = %d , data: ", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - /* - * According to EEPROM spec there is a MAX of 10 ms required for - * EEPROM to flush internal RX buffer after STOP was issued at the - * end of write transaction. During this time the EEPROM will not be - * responsive to any more commands - so wait a bit more. - */ - msleep(10); - - } else - dev_err(adev->dev, "arcturus_i2c_write- error occurred :%x", ret); - - return ret; -} - -static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; - uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; - - for (i = 0; i < num; i++) { - /* - * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at - * once and hence the data needs to be spliced into chunks and sent each - * chunk separately - */ - data_size = msgs[i].len - 2; - data_chunk_size = MAX_SW_I2C_COMMANDS - 2; - next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); - data_ptr = msgs[i].buf + 2; - - for (j = 0; j < data_size / data_chunk_size; j++) { - /* Insert the EEPROM dest addess, bits 0-15 */ - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = arcturus_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - - memcpy(data_ptr, data_chunk + 2, data_chunk_size); - } else { - - memcpy(data_chunk + 2, data_ptr, data_chunk_size); - - ret = arcturus_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - } - - if (ret) { - num = -EIO; - goto fail; - } - - next_eeprom_addr += data_chunk_size; - data_ptr += data_chunk_size; - } - - if (data_size % data_chunk_size) { - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = arcturus_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - - memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); - } else { - memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); - - ret = arcturus_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - } - - if (ret) { - num = -EIO; - goto fail; - } - } - } - -fail: - return num; -} - -static u32 arcturus_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - - -static const struct i2c_algorithm arcturus_i2c_algo = { - .master_xfer = arcturus_i2c_xfer, - .functionality = arcturus_i2c_func, -}; - -static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; - - control->owner = THIS_MODULE; - control->class = I2C_CLASS_SPD; - control->dev.parent = &adev->pdev->dev; - control->algo = &arcturus_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); - - return res; -} - -static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) -{ - i2c_del_adapter(control); -} - -static void arcturus_get_unique_id(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t top32 = 0, bottom32 = 0, smu_version; - uint64_t id; - - if (smu_cmn_get_smc_version(smu, NULL, &smu_version)) { - dev_warn(adev->dev, "Failed to get smu version, cannot get unique_id or serial_number\n"); - return; - } - - /* PPSMC_MSG_ReadSerial* is supported by 54.23.0 and onwards */ - if (smu_version < 0x361700) { - dev_warn(adev->dev, "ReadSerial is only supported by PMFW 54.23.0 and onwards\n"); - return; - } - - /* Get the SN to turn into a Unique ID */ - smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumTop32, &top32); - smu_cmn_send_smc_msg(smu, SMU_MSG_ReadSerialNumBottom32, &bottom32); - - id = ((uint64_t)bottom32 << 32) | top32; - adev->unique_id = id; - /* For Arcturus-and-later, unique_id == serial_number, so convert it to a - * 16-digit HEX string for convenience and backwards-compatibility - */ - sprintf(adev->serial, "%llx", id); -} - -static bool arcturus_is_baco_supported(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t val; - - if (!smu_v11_0_baco_is_support(smu) || amdgpu_sriov_vf(adev)) - return false; - - val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); - return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; -} - -static int arcturus_set_df_cstate(struct smu_context *smu, - enum pp_df_cstate state) -{ - uint32_t smu_version; - int ret; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) { - dev_err(smu->adev->dev, "Failed to get smu version!\n"); - return ret; - } - - /* PPSMC_MSG_DFCstateControl is supported by 54.15.0 and onwards */ - if (smu_version < 0x360F00) { - dev_err(smu->adev->dev, "DFCstateControl is only supported by PMFW 54.15.0 and onwards\n"); - return -EINVAL; - } - - return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DFCstateControl, state, NULL); -} - -static int arcturus_allow_xgmi_power_down(struct smu_context *smu, bool en) -{ - uint32_t smu_version; - int ret; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) { - dev_err(smu->adev->dev, "Failed to get smu version!\n"); - return ret; - } - - /* PPSMC_MSG_GmiPwrDnControl is supported by 54.23.0 and onwards */ - if (smu_version < 0x00361700) { - dev_err(smu->adev->dev, "XGMI power down control is only supported by PMFW 54.23.0 and onwards\n"); - return -EINVAL; - } - - if (en) - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GmiPwrDnControl, - 1, - NULL); - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GmiPwrDnControl, - 0, - NULL); -} - -static const struct throttling_logging_label { - uint32_t feature_mask; - const char *label; -} logging_label[] = { - {(1U << THROTTLER_TEMP_HOTSPOT_BIT), "GPU"}, - {(1U << THROTTLER_TEMP_MEM_BIT), "HBM"}, - {(1U << THROTTLER_TEMP_VR_GFX_BIT), "VR of GFX rail"}, - {(1U << THROTTLER_TEMP_VR_MEM_BIT), "VR of HBM rail"}, - {(1U << THROTTLER_TEMP_VR_SOC_BIT), "VR of SOC rail"}, - {(1U << THROTTLER_VRHOT0_BIT), "VR0 HOT"}, - {(1U << THROTTLER_VRHOT1_BIT), "VR1 HOT"}, -}; -static void arcturus_log_thermal_throttling_event(struct smu_context *smu) -{ - int ret; - int throttler_idx, throtting_events = 0, buf_idx = 0; - struct amdgpu_device *adev = smu->adev; - uint32_t throttler_status; - char log_buf[256]; - - ret = arcturus_get_smu_metrics_data(smu, - METRICS_THROTTLER_STATUS, - &throttler_status); - if (ret) - return; - - memset(log_buf, 0, sizeof(log_buf)); - for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label); - throttler_idx++) { - if (throttler_status & logging_label[throttler_idx].feature_mask) { - throtting_events++; - buf_idx += snprintf(log_buf + buf_idx, - sizeof(log_buf) - buf_idx, - "%s%s", - throtting_events > 1 ? " and " : "", - logging_label[throttler_idx].label); - if (buf_idx >= sizeof(log_buf)) { - dev_err(adev->dev, "buffer overflow!\n"); - log_buf[sizeof(log_buf) - 1] = '\0'; - break; - } - } - } - - 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 int arcturus_get_current_pcie_link_speed(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t esm_ctrl; - - /* TODO: confirm this on real target */ - esm_ctrl = RREG32_PCIE(smnPCIE_ESM_CTRL); - if ((esm_ctrl >> 15) & 0x1FFFF) - return (((esm_ctrl >> 8) & 0x3F) + 128); - - return smu_v11_0_get_current_pcie_link_speed(smu); -} - -static ssize_t arcturus_get_gpu_metrics(struct smu_context *smu, - void **table) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct gpu_metrics_v1_0 *gpu_metrics = - (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; - SmuMetrics_t metrics; - int ret = 0; - - ret = smu_cmn_get_metrics_table(smu, - &metrics, - true); - if (ret) - return ret; - - smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); - - gpu_metrics->temperature_edge = metrics.TemperatureEdge; - gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; - gpu_metrics->temperature_mem = metrics.TemperatureHBM; - gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; - gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; - gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; - gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; - - gpu_metrics->average_socket_power = metrics.AverageSocketPower; - gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; - - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; - gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; - gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; - gpu_metrics->average_vclk0_frequency = metrics.AverageVclkFrequency; - gpu_metrics->average_dclk0_frequency = metrics.AverageDclkFrequency; - - gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; - gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; - gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; - gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; - gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; - - gpu_metrics->pcie_link_width = - smu_v11_0_get_current_pcie_link_width(smu); - gpu_metrics->pcie_link_speed = - arcturus_get_current_pcie_link_speed(smu); - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v1_0); -} - -static const struct pptable_funcs arcturus_ppt_funcs = { - /* init dpm */ - .get_allowed_feature_mask = arcturus_get_allowed_feature_mask, - /* btc */ - .run_btc = arcturus_run_btc, - /* dpm/clk tables */ - .set_default_dpm_table = arcturus_set_default_dpm_table, - .populate_umd_state_clk = arcturus_populate_umd_state_clk, - .get_thermal_temperature_range = arcturus_get_thermal_temperature_range, - .print_clk_levels = arcturus_print_clk_levels, - .force_clk_levels = arcturus_force_clk_levels, - .read_sensor = arcturus_read_sensor, - .get_fan_speed_percent = arcturus_get_fan_speed_percent, - .get_fan_speed_rpm = arcturus_get_fan_speed_rpm, - .get_power_profile_mode = arcturus_get_power_profile_mode, - .set_power_profile_mode = arcturus_set_power_profile_mode, - .set_performance_level = arcturus_set_performance_level, - /* debug (internal used) */ - .dump_pptable = arcturus_dump_pptable, - .get_power_limit = arcturus_get_power_limit, - .is_dpm_running = arcturus_is_dpm_running, - .dpm_set_vcn_enable = arcturus_dpm_set_vcn_enable, - .i2c_init = arcturus_i2c_control_init, - .i2c_fini = arcturus_i2c_control_fini, - .get_unique_id = arcturus_get_unique_id, - .init_microcode = smu_v11_0_init_microcode, - .load_microcode = smu_v11_0_load_microcode, - .fini_microcode = smu_v11_0_fini_microcode, - .init_smc_tables = arcturus_init_smc_tables, - .fini_smc_tables = smu_v11_0_fini_smc_tables, - .init_power = smu_v11_0_init_power, - .fini_power = smu_v11_0_fini_power, - .check_fw_status = smu_v11_0_check_fw_status, - /* pptable related */ - .setup_pptable = arcturus_setup_pptable, - .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, - .check_fw_version = smu_v11_0_check_fw_version, - .write_pptable = smu_cmn_write_pptable, - .set_driver_table_location = smu_v11_0_set_driver_table_location, - .set_tool_table_location = smu_v11_0_set_tool_table_location, - .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, - .system_features_control = smu_v11_0_system_features_control, - .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, - .send_smc_msg = smu_cmn_send_smc_msg, - .init_display_count = NULL, - .set_allowed_mask = smu_v11_0_set_allowed_mask, - .get_enabled_mask = smu_cmn_get_enabled_mask, - .feature_is_enabled = smu_cmn_feature_is_enabled, - .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, - .notify_display_change = NULL, - .set_power_limit = smu_v11_0_set_power_limit, - .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, - .enable_thermal_alert = smu_v11_0_enable_thermal_alert, - .disable_thermal_alert = smu_v11_0_disable_thermal_alert, - .set_min_dcef_deep_sleep = NULL, - .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, - .get_fan_control_mode = smu_v11_0_get_fan_control_mode, - .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, - .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, - .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, - .gfx_off_control = smu_v11_0_gfx_off_control, - .register_irq_handler = smu_v11_0_register_irq_handler, - .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, - .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= arcturus_is_baco_supported, - .baco_get_state = smu_v11_0_baco_get_state, - .baco_set_state = smu_v11_0_baco_set_state, - .baco_enter = smu_v11_0_baco_enter, - .baco_exit = smu_v11_0_baco_exit, - .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, - .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .set_df_cstate = arcturus_set_df_cstate, - .allow_xgmi_power_down = arcturus_allow_xgmi_power_down, - .log_thermal_throttling_event = arcturus_log_thermal_throttling_event, - .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, - .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, - .get_gpu_metrics = arcturus_get_gpu_metrics, -}; - -void arcturus_set_ppt_funcs(struct smu_context *smu) -{ - smu->ppt_funcs = &arcturus_ppt_funcs; - smu->message_map = arcturus_message_map; - smu->clock_map = arcturus_clk_map; - smu->feature_map = arcturus_feature_mask_map; - smu->table_map = arcturus_table_map; - smu->pwr_src_map = arcturus_pwr_src_map; - smu->workload_map = arcturus_workload_map; -} diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.h b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.h deleted file mode 100644 index d756b16924b8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __ARCTURUS_PPT_H__ -#define __ARCTURUS_PPT_H__ - -#define ARCTURUS_UMD_PSTATE_GFXCLK_LEVEL 0x3 -#define ARCTURUS_UMD_PSTATE_SOCCLK_LEVEL 0x3 -#define ARCTURUS_UMD_PSTATE_MCLK_LEVEL 0x2 - -#define MAX_DPM_NUMBER 16 -#define MAX_PCIE_CONF 2 - -struct arcturus_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -struct arcturus_dpm_state { - uint32_t soft_min_level; - uint32_t soft_max_level; - uint32_t hard_min_level; - uint32_t hard_max_level; -}; - -struct arcturus_single_dpm_table { - uint32_t count; - struct arcturus_dpm_state dpm_state; - struct arcturus_dpm_level dpm_levels[MAX_DPM_NUMBER]; -}; - -struct arcturus_pcie_table { - uint16_t count; - uint8_t pcie_gen[MAX_PCIE_CONF]; - uint8_t pcie_lane[MAX_PCIE_CONF]; - uint32_t lclk[MAX_PCIE_CONF]; -}; - -struct arcturus_dpm_table { - struct arcturus_single_dpm_table soc_table; - struct arcturus_single_dpm_table gfx_table; - struct arcturus_single_dpm_table mem_table; - struct arcturus_single_dpm_table eclk_table; - struct arcturus_single_dpm_table vclk_table; - struct arcturus_single_dpm_table dclk_table; - struct arcturus_single_dpm_table fclk_table; - struct arcturus_pcie_table pcie_table; -}; - -extern void arcturus_set_ppt_funcs(struct smu_context *smu); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile deleted file mode 100644 index 2773966ae434..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# Copyright 2017 Advanced Micro Devices, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# -# Makefile for the 'hw manager' sub-component of powerplay. -# It provides the hardware management services for the driver. - -HARDWARE_MGR = hwmgr.o processpptables.o \ - hardwaremanager.o smu8_hwmgr.o \ - pppcielanes.o\ - process_pptables_v1_0.o ppatomctrl.o ppatomfwctrl.o \ - smu7_hwmgr.o smu7_powertune.o smu7_thermal.o \ - smu7_clockpowergating.o \ - vega10_processpptables.o vega10_hwmgr.o vega10_powertune.o \ - vega10_thermal.o smu10_hwmgr.o pp_psm.o\ - vega12_processpptables.o vega12_hwmgr.o \ - vega12_thermal.o \ - pp_overdriver.o smu_helper.o \ - vega20_processpptables.o vega20_hwmgr.o vega20_powertune.o \ - vega20_thermal.o common_baco.o vega10_baco.o vega20_baco.o \ - vega12_baco.o smu9_baco.o tonga_baco.o polaris_baco.o fiji_baco.o \ - ci_baco.o smu7_baco.o - -AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) - -AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c deleted file mode 100644 index 3be40114e63d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "ci_baco.h" - -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -#include "bif/bif_4_1_d.h" -#include "bif/bif_4_1_sh_mask.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "smu/smu_7_0_1_d.h" -#include "smu/smu_7_0_1_sh_mask.h" - -#include "gca/gfx_7_2_d.h" -#include "gca/gfx_7_2_sh_mask.h" - -static const struct baco_cmd_entry gpio_tbl[] = -{ - { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, - { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, - { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, - { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } -}; - -static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } -}; - -static const struct baco_cmd_entry use_bclk_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } -}; - -static const struct baco_cmd_entry turn_off_plls_tbl[] = -{ - { CMD_READMODIFYWRITE, mmDISPPLL_BG_CNTL, DISPPLL_BG_CNTL__DISPPLL_BG_PDN_MASK, DISPPLL_BG_CNTL__DISPPLL_BG_PDN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_DC }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__OSC_EN_MASK, CG_CLKPIN_CNTL_DC__OSC_EN__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_DC__XTALIN_SEL_MASK, CG_CLKPIN_CNTL_DC__XTALIN_SEL__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_RESET_MASK, PLL_CNTL__PLL_RESET__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_POWER_DOWN_MASK, PLL_CNTL__PLL_POWER_DOWN__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmPLL_CNTL, PLL_CNTL__PLL_BYPASS_CAL_MASK, PLL_CNTL__PLL_BYPASS_CAL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 }, - { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL_MASK, MISC_CLK_CTRL__DFT_SMS_PG_CLK_SEL__SHIFT, 0, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x2 } -}; - -static const struct baco_cmd_entry enter_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } -}; - -#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK - -static const struct baco_cmd_entry exit_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, - { CMD_DELAY_MS, 0, 0, 0, 20, 0 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x20 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x10 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } -}; - -static const struct baco_cmd_entry clean_baco_tbl[] = -{ - { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, - { CMD_WRITE, mmCP_PFP_UCODE_ADDR, 0, 0, 0, 0 } -}; - -int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu7_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); - baco_program_registers(hwmgr, enable_fb_req_rej_tbl, - ARRAY_SIZE(enable_fb_req_rej_tbl)); - baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); - baco_program_registers(hwmgr, turn_off_plls_tbl, - ARRAY_SIZE(turn_off_plls_tbl)); - if (baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h deleted file mode 100644 index 17041f187020..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ci_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __CI_BACO_H__ -#define __CI_BACO_H__ -#include "smu7_baco.h" - -extern int ci_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c deleted file mode 100644 index 1c73776bd606..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2018 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 "common_baco.h" - - -static bool baco_wait_register(struct pp_hwmgr *hwmgr, u32 reg, u32 mask, u32 value) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - u32 timeout = 5000, data; - - do { - msleep(1); - data = RREG32(reg); - timeout--; - } while (value != (data & mask) && (timeout != 0)); - - if (timeout == 0) - return false; - - return true; -} - -static bool baco_cmd_handler(struct pp_hwmgr *hwmgr, u32 command, u32 reg, u32 mask, - u32 shift, u32 value, u32 timeout) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - u32 data; - bool ret = true; - - switch (command) { - case CMD_WRITE: - WREG32(reg, value << shift); - break; - case CMD_READMODIFYWRITE: - data = RREG32(reg); - data = (data & (~mask)) | (value << shift); - WREG32(reg, data); - break; - case CMD_WAITFOR: - ret = baco_wait_register(hwmgr, reg, mask, value); - break; - case CMD_DELAY_MS: - if (timeout) - /* Delay in milli Seconds */ - msleep(timeout); - break; - case CMD_DELAY_US: - if (timeout) - /* Delay in micro Seconds */ - udelay(timeout); - break; - - default: - dev_warn(adev->dev, "Invalid BACO command.\n"); - ret = false; - } - - return ret; -} - -bool baco_program_registers(struct pp_hwmgr *hwmgr, - const struct baco_cmd_entry *entry, - const u32 array_size) -{ - u32 i, reg = 0; - - for (i = 0; i < array_size; i++) { - if ((entry[i].cmd == CMD_WRITE) || - (entry[i].cmd == CMD_READMODIFYWRITE) || - (entry[i].cmd == CMD_WAITFOR)) - reg = entry[i].reg_offset; - if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask, - entry[i].shift, entry[i].val, entry[i].timeout)) - return false; - } - - return true; -} - -bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr, - const struct soc15_baco_cmd_entry *entry, - const u32 array_size) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - u32 i, reg = 0; - - for (i = 0; i < array_size; i++) { - if ((entry[i].cmd == CMD_WRITE) || - (entry[i].cmd == CMD_READMODIFYWRITE) || - (entry[i].cmd == CMD_WAITFOR)) - reg = adev->reg_offset[entry[i].hwip][entry[i].inst][entry[i].seg] - + entry[i].reg_offset; - if (!baco_cmd_handler(hwmgr, entry[i].cmd, reg, entry[i].mask, - entry[i].shift, entry[i].val, entry[i].timeout)) - return false; - } - - return true; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h deleted file mode 100644 index 8393eb62706d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/common_baco.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 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 __COMMON_BOCO_H__ -#define __COMMON_BOCO_H__ -#include "hwmgr.h" - - -enum baco_cmd_type { - CMD_WRITE = 0, - CMD_READMODIFYWRITE, - CMD_WAITFOR, - CMD_DELAY_MS, - CMD_DELAY_US, -}; - -struct baco_cmd_entry { - enum baco_cmd_type cmd; - uint32_t reg_offset; - uint32_t mask; - uint32_t shift; - uint32_t timeout; - uint32_t val; -}; - -struct soc15_baco_cmd_entry { - enum baco_cmd_type cmd; - uint32_t hwip; - uint32_t inst; - uint32_t seg; - uint32_t reg_offset; - uint32_t mask; - uint32_t shift; - uint32_t timeout; - uint32_t val; -}; - -extern bool baco_program_registers(struct pp_hwmgr *hwmgr, - const struct baco_cmd_entry *entry, - const u32 array_size); -extern bool soc15_baco_program_registers(struct pp_hwmgr *hwmgr, - const struct soc15_baco_cmd_entry *entry, - const u32 array_size); -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c deleted file mode 100644 index c0368f2dfb21..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "fiji_baco.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" - - -static const struct baco_cmd_entry gpio_tbl[] = -{ - { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, - { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, - { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, - { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } -}; - -static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } -}; - -static const struct baco_cmd_entry use_bclk_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 } -}; - -static const struct baco_cmd_entry turn_off_plls_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 } -}; - -static const struct baco_cmd_entry clk_req_b_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 } -}; - -static const struct baco_cmd_entry enter_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } -}; - -#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK - -static const struct baco_cmd_entry exit_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } -}; - -static const struct baco_cmd_entry clean_baco_tbl[] = -{ - { CMD_WRITE, mmBIOS_SCRATCH_0, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_1, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_2, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_3, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_4, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_5, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_8, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_9, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_10, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_11, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_12, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_13, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_14, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_15, 0, 0, 0, 0 } -}; - -int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu7_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); - baco_program_registers(hwmgr, enable_fb_req_rej_tbl, - ARRAY_SIZE(enable_fb_req_rej_tbl)); - baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); - baco_program_registers(hwmgr, turn_off_plls_tbl, - ARRAY_SIZE(turn_off_plls_tbl)); - baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl)); - if (baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h deleted file mode 100644 index 47f402900bdb..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __FIJI_BACO_H__ -#define __FIJI_BACO_H__ -#include "smu7_baco.h" - -extern int fiji_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c deleted file mode 100644 index 9454ab50f9a1..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include "hwmgr.h" -#include "hardwaremanager.h" -#include "power_state.h" - - -#define TEMP_RANGE_MIN (0) -#define TEMP_RANGE_MAX (80 * 1000) - -#define PHM_FUNC_CHECK(hw) \ - do { \ - if ((hw) == NULL || (hw)->hwmgr_func == NULL) \ - return -EINVAL; \ - } while (0) - -int phm_setup_asic(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->asic_setup) - return hwmgr->hwmgr_func->asic_setup(hwmgr); - - return 0; -} - -int phm_power_down_asic(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->power_off_asic) - return hwmgr->hwmgr_func->power_off_asic(hwmgr); - - return 0; -} - -int phm_set_power_state(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pcurrent_state, - const struct pp_hw_power_state *pnew_power_state) -{ - struct phm_set_power_state_input states; - - PHM_FUNC_CHECK(hwmgr); - - states.pcurrent_state = pcurrent_state; - states.pnew_state = pnew_power_state; - - if (NULL != hwmgr->hwmgr_func->power_state_set) - return hwmgr->hwmgr_func->power_state_set(hwmgr, &states); - - return 0; -} - -int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = NULL; - int ret = -EINVAL; - PHM_FUNC_CHECK(hwmgr); - adev = hwmgr->adev; - - /* Skip for suspend/resume case */ - if (!hwmgr->pp_one_vf && smum_is_dpm_running(hwmgr) - && !amdgpu_passthrough(adev) && adev->in_suspend) { - pr_info("dpm has been enabled\n"); - return 0; - } - - if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) - ret = hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); - - return ret; -} - -int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr) -{ - int ret = -EINVAL; - - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->not_vf) - return 0; - - if (!smum_is_dpm_running(hwmgr)) { - pr_info("dpm has been disabled\n"); - return 0; - } - - if (hwmgr->hwmgr_func->dynamic_state_management_disable) - ret = hwmgr->hwmgr_func->dynamic_state_management_disable(hwmgr); - - return ret; -} - -int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) -{ - int ret = 0; - - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->force_dpm_level != NULL) - ret = hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); - - return ret; -} - -int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *adjusted_ps, - const struct pp_power_state *current_ps) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL) - return hwmgr->hwmgr_func->apply_state_adjust_rules( - hwmgr, - adjusted_ps, - current_ps); - return 0; -} - -int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->apply_clocks_adjust_rules != NULL) - return hwmgr->hwmgr_func->apply_clocks_adjust_rules(hwmgr); - return 0; -} - -int phm_powerdown_uvd(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->powerdown_uvd != NULL) - return hwmgr->hwmgr_func->powerdown_uvd(hwmgr); - return 0; -} - - -int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->disable_clock_power_gating) - return hwmgr->hwmgr_func->disable_clock_power_gating(hwmgr); - - return 0; -} - -int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->pre_display_config_changed) - hwmgr->hwmgr_func->pre_display_config_changed(hwmgr); - - return 0; - -} - -int phm_display_configuration_changed(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->display_config_changed) - hwmgr->hwmgr_func->display_config_changed(hwmgr); - - return 0; -} - -int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment) - hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr); - - return 0; -} - -int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->not_vf) - return 0; - - if (hwmgr->hwmgr_func->stop_thermal_controller == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr); -} - -int phm_register_irq_handlers(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->register_irq_handlers != NULL) - return hwmgr->hwmgr_func->register_irq_handlers(hwmgr); - - return 0; -} - -/** -* Initializes the thermal controller subsystem. -* -* @param pHwMgr the address of the powerplay hardware manager. -* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher. -*/ -int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - struct PP_TemperatureRange range = { - TEMP_RANGE_MIN, - TEMP_RANGE_MAX, - TEMP_RANGE_MAX, - TEMP_RANGE_MIN, - TEMP_RANGE_MAX, - TEMP_RANGE_MAX, - TEMP_RANGE_MIN, - TEMP_RANGE_MAX, - TEMP_RANGE_MAX}; - struct amdgpu_device *adev = hwmgr->adev; - - if (!hwmgr->not_vf) - return 0; - - if (hwmgr->hwmgr_func->get_thermal_temperature_range) - hwmgr->hwmgr_func->get_thermal_temperature_range( - hwmgr, &range); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController) - && hwmgr->hwmgr_func->start_thermal_controller != NULL) - ret = hwmgr->hwmgr_func->start_thermal_controller(hwmgr, &range); - - adev->pm.dpm.thermal.min_temp = range.min; - adev->pm.dpm.thermal.max_temp = range.max; - adev->pm.dpm.thermal.max_edge_emergency_temp = range.edge_emergency_max; - adev->pm.dpm.thermal.min_hotspot_temp = range.hotspot_min; - adev->pm.dpm.thermal.max_hotspot_crit_temp = range.hotspot_crit_max; - adev->pm.dpm.thermal.max_hotspot_emergency_temp = range.hotspot_emergency_max; - adev->pm.dpm.thermal.min_mem_temp = range.mem_min; - adev->pm.dpm.thermal.max_mem_crit_temp = range.mem_crit_max; - adev->pm.dpm.thermal.max_mem_emergency_temp = range.mem_emergency_max; - - return ret; -} - - -bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - if (hwmgr->pp_one_vf) - return false; - - if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL) - return false; - - return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr); -} - - -int phm_check_states_equal(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pstate1, - const struct pp_hw_power_state *pstate2, - bool *equal) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->check_states_equal == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal); -} - -int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, - const struct amd_pp_display_configuration *display_config) -{ - int index = 0; - int number_of_active_display = 0; - - PHM_FUNC_CHECK(hwmgr); - - if (display_config == NULL) - return -EINVAL; - - if (NULL != hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) - hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, display_config->min_dcef_deep_sleep_set_clk); - - for (index = 0; index < display_config->num_path_including_non_display; index++) { - if (display_config->displays[index].controller_id != 0) - number_of_active_display++; - } - - if (NULL != hwmgr->hwmgr_func->set_active_display_count) - hwmgr->hwmgr_func->set_active_display_count(hwmgr, number_of_active_display); - - if (hwmgr->hwmgr_func->store_cc6_data == NULL) - return -EINVAL; - - /* TODO: pass other display configuration in the future */ - - if (hwmgr->hwmgr_func->store_cc6_data) - hwmgr->hwmgr_func->store_cc6_data(hwmgr, - display_config->cpu_pstate_separation_time, - display_config->cpu_cc6_disable, - display_config->cpu_pstate_disable, - display_config->nb_pstate_switch_disable); - - return 0; -} - -int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ - PHM_FUNC_CHECK(hwmgr); - - if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL) - return -EINVAL; - return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info); -} - -int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->set_cpu_power_state != NULL) - return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr); - - return 0; -} - - -int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - PHM_FUNC_CHECK(hwmgr); - if (hwmgr->hwmgr_func->get_performance_level == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_performance_level(hwmgr, state, designation, index, level); - - -} - - -/** -* Gets Clock Info. -* -* @param pHwMgr the address of the powerplay hardware manager. -* @param pPowerState the address of the Power State structure. -* @param pClockInfo the address of PP_ClockInfo structure where the result will be returned. -* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the back-end. -*/ -int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *pclock_info, - PHM_PerformanceLevelDesignation designation) -{ - int result; - PHM_PerformanceLevel performance_level = {0}; - - PHM_FUNC_CHECK(hwmgr); - - PP_ASSERT_WITH_CODE((NULL != state), "Invalid Input!", return -EINVAL); - PP_ASSERT_WITH_CODE((NULL != pclock_info), "Invalid Input!", return -EINVAL); - - result = phm_get_performance_level(hwmgr, state, PHM_PerformanceLevelDesignation_Activity, 0, &performance_level); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve minimum clocks.", return result); - - - pclock_info->min_mem_clk = performance_level.memory_clock; - pclock_info->min_eng_clk = performance_level.coreClock; - pclock_info->min_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth; - - - result = phm_get_performance_level(hwmgr, state, designation, - (hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1), &performance_level); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to retrieve maximum clocks.", return result); - - pclock_info->max_mem_clk = performance_level.memory_clock; - pclock_info->max_eng_clk = performance_level.coreClock; - pclock_info->max_bus_bandwidth = performance_level.nonLocalMemoryFreq * performance_level.nonLocalMemoryWidth; - - return 0; -} - -int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->get_current_shallow_sleep_clocks == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_current_shallow_sleep_clocks(hwmgr, state, clock_info); - -} - -int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->get_clock_by_type == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_clock_by_type(hwmgr, type, clocks); - -} - -int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->get_clock_by_type_with_latency == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_clock_by_type_with_latency(hwmgr, type, clocks); - -} - -int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->get_clock_by_type_with_voltage == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_clock_by_type_with_voltage(hwmgr, type, clocks); - -} - -int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_ranges) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges) - return -EINVAL; - - return hwmgr->hwmgr_func->set_watermarks_for_clocks_ranges(hwmgr, - clock_ranges); -} - -int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->display_clock_voltage_request) - return -EINVAL; - - return hwmgr->hwmgr_func->display_clock_voltage_request(hwmgr, clock); -} - -int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) -{ - PHM_FUNC_CHECK(hwmgr); - - if (hwmgr->hwmgr_func->get_max_high_clocks == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks); -} - -int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->not_vf) - return 0; - - if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL) - return -EINVAL; - - return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr); -} - -int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_active_display_count) - return -EINVAL; - - return hwmgr->hwmgr_func->set_active_display_count(hwmgr, count); -} - -int phm_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk) - return -EINVAL; - - return hwmgr->hwmgr_func->set_min_deep_sleep_dcefclk(hwmgr, clock); -} - -int phm_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq) - return -EINVAL; - - return hwmgr->hwmgr_func->set_hard_min_dcefclk_by_freq(hwmgr, clock); -} - -int phm_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - PHM_FUNC_CHECK(hwmgr); - - if (!hwmgr->hwmgr_func->set_hard_min_fclk_by_freq) - return -EINVAL; - - return hwmgr->hwmgr_func->set_hard_min_fclk_by_freq(hwmgr, clock); -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c deleted file mode 100644 index f48fdc7f0382..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ /dev/null @@ -1,564 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include -#include -#include -#include "power_state.h" -#include "hwmgr.h" -#include "ppsmc.h" -#include "amd_acpi.h" -#include "pp_psm.h" - -extern const struct pp_smumgr_func ci_smu_funcs; -extern const struct pp_smumgr_func smu8_smu_funcs; -extern const struct pp_smumgr_func iceland_smu_funcs; -extern const struct pp_smumgr_func tonga_smu_funcs; -extern const struct pp_smumgr_func fiji_smu_funcs; -extern const struct pp_smumgr_func polaris10_smu_funcs; -extern const struct pp_smumgr_func vegam_smu_funcs; -extern const struct pp_smumgr_func vega10_smu_funcs; -extern const struct pp_smumgr_func vega12_smu_funcs; -extern const struct pp_smumgr_func smu10_smu_funcs; -extern const struct pp_smumgr_func vega20_smu_funcs; - -extern int smu7_init_function_pointers(struct pp_hwmgr *hwmgr); -extern int smu8_init_function_pointers(struct pp_hwmgr *hwmgr); -extern int vega10_hwmgr_init(struct pp_hwmgr *hwmgr); -extern int vega12_hwmgr_init(struct pp_hwmgr *hwmgr); -extern int vega20_hwmgr_init(struct pp_hwmgr *hwmgr); -extern int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); - -static int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr); -static void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr); -static int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr); -static int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr); -static int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr); -static int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr); -static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr); - - -static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr) -{ - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4; - hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5; - - hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING; - hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO; - hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR; - hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE; -} - -int hwmgr_early_init(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev; - - if (!hwmgr) - return -EINVAL; - - hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; - hwmgr->pp_table_version = PP_TABLE_V1; - hwmgr->dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - hwmgr->request_dpm_level = AMD_DPM_FORCED_LEVEL_AUTO; - hwmgr_init_default_caps(hwmgr); - hwmgr_set_user_specify_caps(hwmgr); - hwmgr->fan_ctrl_is_in_default_mode = true; - hwmgr_init_workload_prority(hwmgr); - hwmgr->gfxoff_state_changed_by_workload = false; - - adev = hwmgr->adev; - - switch (hwmgr->chip_family) { - case AMDGPU_FAMILY_CI: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - hwmgr->smumgr_funcs = &ci_smu_funcs; - ci_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~(PP_VBI_TIME_SUPPORT_MASK | - PP_ENABLE_GFX_CG_THRU_SMU | - PP_GFXOFF_MASK); - hwmgr->pp_table_version = PP_TABLE_V0; - hwmgr->od_enabled = false; - smu7_init_function_pointers(hwmgr); - break; - case AMDGPU_FAMILY_CZ: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - hwmgr->od_enabled = false; - hwmgr->smumgr_funcs = &smu8_smu_funcs; - hwmgr->feature_mask &= ~PP_GFXOFF_MASK; - smu8_init_function_pointers(hwmgr); - break; - case AMDGPU_FAMILY_VI: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - hwmgr->feature_mask &= ~PP_GFXOFF_MASK; - switch (hwmgr->chip_id) { - case CHIP_TOPAZ: - hwmgr->smumgr_funcs = &iceland_smu_funcs; - topaz_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | - PP_ENABLE_GFX_CG_THRU_SMU); - hwmgr->pp_table_version = PP_TABLE_V0; - hwmgr->od_enabled = false; - break; - case CHIP_TONGA: - hwmgr->smumgr_funcs = &tonga_smu_funcs; - tonga_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~PP_VBI_TIME_SUPPORT_MASK; - break; - case CHIP_FIJI: - hwmgr->smumgr_funcs = &fiji_smu_funcs; - fiji_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~ (PP_VBI_TIME_SUPPORT_MASK | - PP_ENABLE_GFX_CG_THRU_SMU); - break; - case CHIP_POLARIS11: - case CHIP_POLARIS10: - case CHIP_POLARIS12: - hwmgr->smumgr_funcs = &polaris10_smu_funcs; - polaris_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK); - break; - case CHIP_VEGAM: - hwmgr->smumgr_funcs = &vegam_smu_funcs; - polaris_set_asic_special_caps(hwmgr); - hwmgr->feature_mask &= ~(PP_UVD_HANDSHAKE_MASK); - break; - default: - return -EINVAL; - } - smu7_init_function_pointers(hwmgr); - break; - case AMDGPU_FAMILY_AI: - switch (hwmgr->chip_id) { - case CHIP_VEGA10: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - hwmgr->feature_mask &= ~PP_GFXOFF_MASK; - hwmgr->smumgr_funcs = &vega10_smu_funcs; - vega10_hwmgr_init(hwmgr); - break; - case CHIP_VEGA12: - hwmgr->smumgr_funcs = &vega12_smu_funcs; - vega12_hwmgr_init(hwmgr); - break; - case CHIP_VEGA20: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - hwmgr->feature_mask &= ~PP_GFXOFF_MASK; - hwmgr->smumgr_funcs = &vega20_smu_funcs; - vega20_hwmgr_init(hwmgr); - break; - default: - return -EINVAL; - } - break; - case AMDGPU_FAMILY_RV: - switch (hwmgr->chip_id) { - case CHIP_RAVEN: - hwmgr->od_enabled = false; - hwmgr->smumgr_funcs = &smu10_smu_funcs; - smu10_init_function_pointers(hwmgr); - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -int hwmgr_sw_init(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr|| !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->smu_init) - return -EINVAL; - - phm_register_irq_handlers(hwmgr); - pr_info("hwmgr_sw_init smu backed is %s\n", hwmgr->smumgr_funcs->name); - - return hwmgr->smumgr_funcs->smu_init(hwmgr); -} - - -int hwmgr_sw_fini(struct pp_hwmgr *hwmgr) -{ - if (hwmgr && hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->smu_fini) - hwmgr->smumgr_funcs->smu_fini(hwmgr); - - return 0; -} - -int hwmgr_hw_init(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - hwmgr->pp_one_vf = amdgpu_sriov_is_pp_one_vf((struct amdgpu_device *)hwmgr->adev); - hwmgr->pm_en = (amdgpu_dpm && (hwmgr->not_vf || hwmgr->pp_one_vf)) - ? true : false; - if (!hwmgr->pm_en) - return 0; - - if (!hwmgr->pptable_func || - !hwmgr->pptable_func->pptable_init || - !hwmgr->hwmgr_func->backend_init) { - hwmgr->pm_en = false; - pr_info("dpm not supported \n"); - return 0; - } - - ret = hwmgr->pptable_func->pptable_init(hwmgr); - if (ret) - goto err; - - ((struct amdgpu_device *)hwmgr->adev)->pm.no_fan = - hwmgr->thermal_controller.fanInfo.bNoFan; - - ret = hwmgr->hwmgr_func->backend_init(hwmgr); - if (ret) - goto err1; - /* make sure dc limits are valid */ - if ((hwmgr->dyn_state.max_clock_voltage_on_dc.sclk == 0) || - (hwmgr->dyn_state.max_clock_voltage_on_dc.mclk == 0)) - hwmgr->dyn_state.max_clock_voltage_on_dc = - hwmgr->dyn_state.max_clock_voltage_on_ac; - - ret = psm_init_power_state_table(hwmgr); - if (ret) - goto err2; - - ret = phm_setup_asic(hwmgr); - if (ret) - goto err2; - - ret = phm_enable_dynamic_state_management(hwmgr); - if (ret) - goto err2; - ret = phm_start_thermal_controller(hwmgr); - ret |= psm_set_performance_states(hwmgr); - if (ret) - goto err2; - - ((struct amdgpu_device *)hwmgr->adev)->pm.dpm_enabled = true; - - return 0; -err2: - if (hwmgr->hwmgr_func->backend_fini) - hwmgr->hwmgr_func->backend_fini(hwmgr); -err1: - if (hwmgr->pptable_func->pptable_fini) - hwmgr->pptable_func->pptable_fini(hwmgr); -err: - return ret; -} - -int hwmgr_hw_fini(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf) - return 0; - - phm_stop_thermal_controller(hwmgr); - psm_set_boot_states(hwmgr); - psm_adjust_power_state_dynamic(hwmgr, true, NULL); - phm_disable_dynamic_state_management(hwmgr); - phm_disable_clock_power_gatings(hwmgr); - - if (hwmgr->hwmgr_func->backend_fini) - hwmgr->hwmgr_func->backend_fini(hwmgr); - if (hwmgr->pptable_func->pptable_fini) - hwmgr->pptable_func->pptable_fini(hwmgr); - return psm_fini_power_state_table(hwmgr); -} - -int hwmgr_suspend(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - if (!hwmgr || !hwmgr->pm_en || !hwmgr->not_vf) - return 0; - - phm_disable_smc_firmware_ctf(hwmgr); - ret = psm_set_boot_states(hwmgr); - if (ret) - return ret; - ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL); - if (ret) - return ret; - ret = phm_power_down_asic(hwmgr); - - return ret; -} - -int hwmgr_resume(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - if (!hwmgr) - return -EINVAL; - - if (!hwmgr->not_vf || !hwmgr->pm_en) - return 0; - - ret = phm_setup_asic(hwmgr); - if (ret) - return ret; - - ret = phm_enable_dynamic_state_management(hwmgr); - if (ret) - return ret; - ret = phm_start_thermal_controller(hwmgr); - ret |= psm_set_performance_states(hwmgr); - if (ret) - return ret; - - ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); - - return ret; -} - -static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) -{ - switch (state) { - case POWER_STATE_TYPE_BATTERY: - return PP_StateUILabel_Battery; - case POWER_STATE_TYPE_BALANCED: - return PP_StateUILabel_Balanced; - case POWER_STATE_TYPE_PERFORMANCE: - return PP_StateUILabel_Performance; - default: - return PP_StateUILabel_None; - } -} - -int hwmgr_handle_task(struct pp_hwmgr *hwmgr, enum amd_pp_task task_id, - enum amd_pm_state_type *user_state) -{ - int ret = 0; - - if (hwmgr == NULL) - return -EINVAL; - - switch (task_id) { - case AMD_PP_TASK_DISPLAY_CONFIG_CHANGE: - if (!hwmgr->not_vf) - return ret; - ret = phm_pre_display_configuration_changed(hwmgr); - if (ret) - return ret; - ret = phm_set_cpu_power_state(hwmgr); - if (ret) - return ret; - ret = psm_set_performance_states(hwmgr); - if (ret) - return ret; - ret = psm_adjust_power_state_dynamic(hwmgr, false, NULL); - break; - case AMD_PP_TASK_ENABLE_USER_STATE: - { - enum PP_StateUILabel requested_ui_label; - struct pp_power_state *requested_ps = NULL; - - if (!hwmgr->not_vf) - return ret; - if (user_state == NULL) { - ret = -EINVAL; - break; - } - - requested_ui_label = power_state_convert(*user_state); - ret = psm_set_user_performance_state(hwmgr, requested_ui_label, &requested_ps); - if (ret) - return ret; - ret = psm_adjust_power_state_dynamic(hwmgr, true, requested_ps); - break; - } - case AMD_PP_TASK_COMPLETE_INIT: - case AMD_PP_TASK_READJUST_POWER_STATE: - ret = psm_adjust_power_state_dynamic(hwmgr, true, NULL); - break; - default: - break; - } - return ret; -} - -void hwmgr_init_default_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEDPM); - -#if defined(CONFIG_ACPI) - if (amdgpu_acpi_is_pcie_performance_request_supported(hwmgr->adev)) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); -#endif - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPatchPowerState); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableSMU7ThermalManagement); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPowerManagement); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMC); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicUVDState); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM); - return; -} - -int hwmgr_set_user_specify_caps(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - - if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CAC); - } else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CAC); - } - - if (hwmgr->feature_mask & PP_OVERDRIVE_MASK) - hwmgr->od_enabled = true; - - return 0; -} - -int polaris_set_asic_special_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - - if (hwmgr->chip_id != CHIP_POLARIS10) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport); - - if (hwmgr->chip_id != CHIP_POLARIS11) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - } - return 0; -} - -int fiji_set_asic_special_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - return 0; -} - -int tonga_set_asic_special_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - return 0; -} - -int topaz_set_asic_special_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - return 0; -} - -int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr) -{ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport); - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h deleted file mode 100644 index c0193e09d58a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2015 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 PP_HWMGR_PPT_H -#define PP_HWMGR_PPT_H - -#include "hardwaremanager.h" -#include "smumgr.h" -#include "atom-types.h" - -struct phm_ppt_v1_clock_voltage_dependency_record { - uint32_t clk; - uint8_t vddInd; - uint8_t vddciInd; - uint8_t mvddInd; - uint16_t vdd_offset; - uint16_t vddc; - uint16_t vddgfx; - uint16_t vddci; - uint16_t mvdd; - uint8_t phases; - uint8_t cks_enable; - uint8_t cks_voffset; - uint32_t sclk_offset; -}; - -typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record; - -struct phm_ppt_v1_clock_voltage_dependency_table { - uint32_t count; /* Number of entries. */ - phm_ppt_v1_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table; - - -/* Multimedia Clock Voltage Dependency records and table */ -struct phm_ppt_v1_mm_clock_voltage_dependency_record { - uint32_t dclk; /* UVD D-clock */ - uint32_t vclk; /* UVD V-clock */ - uint32_t eclk; /* VCE clock */ - uint32_t aclk; /* ACP clock */ - uint32_t samclock; /* SAMU clock */ - uint8_t vddcInd; - uint16_t vddgfx_offset; - uint16_t vddc; - uint16_t vddgfx; - uint8_t phases; -}; -typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock_voltage_dependency_record; - -struct phm_ppt_v1_mm_clock_voltage_dependency_table { - uint32_t count; /* Number of entries. */ - phm_ppt_v1_mm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; -typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table; - -struct phm_ppt_v1_voltage_lookup_record { - uint16_t us_calculated; - uint16_t us_vdd; /* Base voltage */ - uint16_t us_cac_low; - uint16_t us_cac_mid; - uint16_t us_cac_high; -}; -typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record; - -struct phm_ppt_v1_voltage_lookup_table { - uint32_t count; - phm_ppt_v1_voltage_lookup_record entries[1]; /* Dynamically allocate count entries. */ -}; -typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table; - -/* PCIE records and Table */ - -struct phm_ppt_v1_pcie_record { - uint8_t gen_speed; - uint8_t lane_width; - uint16_t usreserved; - uint16_t reserved; - uint32_t pcie_sclk; -}; -typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; - -struct phm_ppt_v1_pcie_table { - uint32_t count; /* Number of entries. */ - phm_ppt_v1_pcie_record entries[1]; /* Dynamically allocate count entries. */ -}; -typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table; - -struct phm_ppt_v1_gpio_table { - uint8_t vrhot_triggered_sclk_dpm_index; /* SCLK DPM level index to switch to when VRHot is triggered */ -}; -typedef struct phm_ppt_v1_gpio_table phm_ppt_v1_gpio_table; - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c deleted file mode 100644 index 8f8e296f2fe9..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "polaris_baco.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_11_0_d.h" -#include "dce/dce_11_0_sh_mask.h" - -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" - -static const struct baco_cmd_entry gpio_tbl[] = -{ - { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, - { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, - { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, - { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } -}; - -static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } -}; - -static const struct baco_cmd_entry use_bclk_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } -}; - -static const struct baco_cmd_entry turn_off_plls_tbl[] = -{ - { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 }, - { CMD_DELAY_US, 0, 0, 0, 1, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_READMODIFYWRITE, 0xda2, 0x40, 0x6, 0, 0x0 }, - { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, - { CMD_READMODIFYWRITE, 0xda2, 0x8, 0x3, 0, 0x0 }, - { CMD_READMODIFYWRITE, 0xda2, 0x3fff00, 0x8, 0, 0x32 }, - { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, - { CMD_READMODIFYWRITE, mmMPLL_FUNC_CNTL_2, MPLL_FUNC_CNTL_2__ISO_DIS_P_MASK, MPLL_FUNC_CNTL_2__ISO_DIS_P__SHIFT, 0, 0x0 }, - { CMD_DELAY_US, 0, 0, 0, 5, 0x0 } -}; - -static const struct baco_cmd_entry clk_req_b_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 } -}; - -static const struct baco_cmd_entry enter_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } -}; - -#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK - -static const struct baco_cmd_entry exit_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } -}; - -static const struct baco_cmd_entry clean_baco_tbl[] = -{ - { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } -}; - -static const struct baco_cmd_entry use_bclk_tbl_vg[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixGCK_DFS_BYPASS_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, GCK_DFS_BYPASS_CNTL__BYPASSACLK_MASK, GCK_DFS_BYPASS_CNTL__BYPASSACLK__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 } -}; - -static const struct baco_cmd_entry turn_off_plls_tbl_vg[] = -{ - { CMD_READMODIFYWRITE, mmDC_GPIO_PAD_STRENGTH_1, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP_MASK, DC_GPIO_PAD_STRENGTH_1__GENLK_STRENGTH_SP__SHIFT, 0, 0x1 }, - { CMD_DELAY_US, 0, 0, 0, 1, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_DRAM, MC_SEQ_DRAM__RST_CTL_MASK, MC_SEQ_DRAM__RST_CTL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC05002B0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC050032C }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x10, 0x4, 0, 0x1 }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, 0x10, 0, 1, 0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500080 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, - { CMD_DELAY_US, 0, 0, 0, 3, 0x0 }, - { CMD_DELAY_US, 0, 0, 0, 5, 0x0 } -}; - -int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu7_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); - baco_program_registers(hwmgr, enable_fb_req_rej_tbl, - ARRAY_SIZE(enable_fb_req_rej_tbl)); - if (hwmgr->chip_id == CHIP_VEGAM) { - baco_program_registers(hwmgr, use_bclk_tbl_vg, ARRAY_SIZE(use_bclk_tbl_vg)); - baco_program_registers(hwmgr, turn_off_plls_tbl_vg, - ARRAY_SIZE(turn_off_plls_tbl_vg)); - } else { - baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); - baco_program_registers(hwmgr, turn_off_plls_tbl, - ARRAY_SIZE(turn_off_plls_tbl)); - } - baco_program_registers(hwmgr, clk_req_b_tbl, ARRAY_SIZE(clk_req_b_tbl)); - if (baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h deleted file mode 100644 index 87a5fa0a157a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/polaris_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __POLARIS_BACO_H__ -#define __POLARIS_BACO_H__ -#include "smu7_baco.h" - -extern int polaris_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c deleted file mode 100644 index 8de384bf9a8f..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c +++ /dev/null @@ -1,1288 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "pp_overdriver.h" -#include - -static const struct phm_fuses_default vega10_fuses_default[] = { - { 0x0213EA94DE0E4964, 0x00003C96, 0xFFFFE226, 0x00000656, 0x00002203, 0xFFFFF201, 0x000003FF, 0x00002203, 0xFFFFF201, 0x000003FF }, - { 0x0213EA94DE0A1884, 0x00003CC5, 0xFFFFE23A, 0x0000064E, 0x00002258, 0xFFFFF1F7, 0x000003FC, 0x00002258, 0xFFFFF1F7, 0x000003FC }, - { 0x0213EA94DE0E31A4, 0x00003CAF, 0xFFFFE36E, 0x00000602, 0x00001E98, 0xFFFFF569, 0x00000357, 0x00001E98, 0xFFFFF569, 0x00000357 }, - { 0x0213EA94DE2C1144, 0x0000391A, 0xFFFFE548, 0x000005C9, 0x00001B98, 0xFFFFF707, 0x00000324, 0x00001B98, 0xFFFFF707, 0x00000324 }, - { 0x0213EA94DE2C18C4, 0x00003821, 0xFFFFE674, 0x00000597, 0x00002196, 0xFFFFF361, 0x000003C0, 0x00002196, 0xFFFFF361, 0x000003C0 }, - { 0x0213EA94DE263884, 0x000044A2, 0xFFFFDCB7, 0x00000738, 0x0000325C, 0xFFFFE6A7, 0x000005E6, 0x0000325C, 0xFFFFE6A7, 0x000005E6 }, - { 0x0213EA94DE082924, 0x00004057, 0xFFFFE1CF, 0x0000063C, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, - { 0x0213EA94DE284924, 0x00003FD0, 0xFFFFDF0F, 0x000006E5, 0x0000267C, 0xFFFFEE2D, 0x000004AB, 0x0000267C, 0xFFFFEE2D, 0x000004AB }, - { 0x0213EA94DE280904, 0x00003F13, 0xFFFFE010, 0x000006AD, 0x000020E7, 0xFFFFF266, 0x000003EC, 0x000020E7, 0xFFFFF266, 0x000003EC }, - { 0x0213EA94DE082044, 0x00004088, 0xFFFFDFAB, 0x000006B6, 0x0000252B, 0xFFFFEFDB, 0x00000458, 0x0000252B, 0xFFFFEFDB, 0x00000458 }, - { 0x0213EA94DE283884, 0x00003EF6, 0xFFFFE017, 0x000006AA, 0x00001F67, 0xFFFFF369, 0x000003BE, 0x00001F67, 0xFFFFF369, 0x000003BE }, - { 0x0213EA94DE2C2184, 0x00003CDD, 0xFFFFE2A7, 0x0000063C, 0x000026C6, 0xFFFFEF38, 0x00000478, 0x000026C6, 0xFFFFEF38, 0x00000478 }, - { 0x0213EA94DE105124, 0x00003FA8, 0xFFFFDF02, 0x000006F0, 0x000027FE, 0xFFFFECF6, 0x000004EA, 0x000027FE, 0xFFFFECF6, 0x000004EA }, - { 0x0213EA94DE2638C4, 0x00004670, 0xFFFFDC40, 0x00000742, 0x00003A7A, 0xFFFFE1A7, 0x000006B6, 0x00003A7A, 0xFFFFE1A7, 0x000006B6 }, - { 0x0213EA94DE2C3024, 0x00003CDC, 0xFFFFE18C, 0x00000683, 0x00002A69, 0xFFFFEBE7, 0x00000515, 0x00002A69, 0xFFFFEBE7, 0x00000515 }, - { 0x0213EA94DE0E38C4, 0x00003CEC, 0xFFFFE38E, 0x00000601, 0x00002752, 0xFFFFEFA7, 0x00000453, 0x00002752, 0xFFFFEFA7, 0x00000453 }, - { 0x0213EA94DE2C1124, 0x000037D0, 0xFFFFE634, 0x000005A7, 0x00001CD2, 0xFFFFF644, 0x00000348, 0x00001CD2, 0xFFFFF644, 0x00000348 }, - { 0x0213EA94DE283964, 0x00003DF5, 0xFFFFE0A5, 0x00000698, 0x00001FD5, 0xFFFFF30E, 0x000003D1, 0x00001FD5, 0xFFFFF30E, 0x000003D1 }, - { 0x0213EA94DE0828C4, 0x00004201, 0xFFFFE03E, 0x00000688, 0x00003206, 0xFFFFE852, 0x0000058A, 0x00003206, 0xFFFFE852, 0x0000058A }, - { 0x0213EA94DE2C1864, 0x00003BED, 0xFFFFE2F5, 0x00000638, 0x0000270D, 0xFFFFEED0, 0x0000048E, 0x0000270D, 0xFFFFEED0, 0x0000048E }, - { 0x0213EA94DE0A1904, 0x00003E82, 0xFFFFE1BE, 0x00000654, 0x000025FB, 0xFFFFEFFA, 0x00000448, 0x000025FB, 0xFFFFEFFA, 0x00000448 }, - { 0x0213EA94DE2C40C4, 0x00003962, 0xFFFFE4B9, 0x000005EF, 0x00002385, 0xFFFFF156, 0x00000423, 0x00002385, 0xFFFFF156, 0x00000423 }, - { 0x0213EA94DE2C0944, 0x00003D88, 0xFFFFE21A, 0x00000655, 0x0000295A, 0xFFFFED68, 0x000004C4, 0x0000295A, 0xFFFFED68, 0x000004C4 }, - { 0x0213EA94DE2C1104, 0x00003AA4, 0xFFFFE4A3, 0x000005E0, 0x000022EF, 0xFFFFF250, 0x000003EB, 0x000022EF, 0xFFFFF250, 0x000003EB }, - { 0x0213EA94DE0E29A4, 0x00003D97, 0xFFFFE30D, 0x0000060D, 0x0000205D, 0xFFFFF45D, 0x00000380, 0x0000205D, 0xFFFFF45D, 0x00000380 }, - { 0x0213EA94DE2C40A4, 0x000039B6, 0xFFFFE446, 0x00000605, 0x00002325, 0xFFFFF16C, 0x0000041F, 0x00002325, 0xFFFFF16C, 0x0000041F }, - { 0x0213EA94DE263904, 0x0000457E, 0xFFFFDCF6, 0x00000722, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, - { 0x0213EA94DE0A1924, 0x00003FB8, 0xFFFFE101, 0x00000670, 0x00002787, 0xFFFFEEF5, 0x00000471, 0x00002787, 0xFFFFEEF5, 0x00000471 }, - { 0x0213EA94DE0E38A4, 0x00003BB2, 0xFFFFE430, 0x000005EA, 0x000024A5, 0xFFFFF162, 0x00000409, 0x000024A5, 0xFFFFF162, 0x00000409 }, - { 0x0213EA94DE082144, 0x00003EC5, 0xFFFFE1BD, 0x0000064F, 0x000022F0, 0xFFFFF227, 0x000003E8, 0x000022F0, 0xFFFFF227, 0x000003E8 }, - { 0x0213EA94DE2C3164, 0x000038A7, 0xFFFFE59F, 0x000005C1, 0x000021CC, 0xFFFFF2DF, 0x000003D9, 0x000021CC, 0xFFFFF2DF, 0x000003D9 }, - { 0x0213EA94DE324184, 0x00002995, 0xFFFFEF7A, 0x0000044C, 0x00001552, 0xFFFFFB5D, 0x00000292, 0x00001552, 0xFFFFFB5D, 0x00000292 }, - { 0x0213EA94DE2C4064, 0x00003B26, 0xFFFFE2D3, 0x00000649, 0x000023B4, 0xFFFFF09B, 0x00000449, 0x000023B4, 0xFFFFF09B, 0x00000449 }, - { 0x0213EA94DE081124, 0x000040D2, 0xFFFFE00A, 0x00000696, 0x000022DA, 0xFFFFF1E9, 0x000003F2, 0x000022DA, 0xFFFFF1E9, 0x000003F2 }, - { 0x0213EA94DE2C3924, 0x00003C98, 0xFFFFE365, 0x00000618, 0x00002D5D, 0xFFFFEB3A, 0x0000051D, 0x00002D5D, 0xFFFFEB3A, 0x0000051D }, - { 0x0213EA94DE2C10A4, 0x00003BBD, 0xFFFFE37E, 0x00000617, 0x0000252E, 0xFFFFF06E, 0x00000441, 0x0000252E, 0xFFFFF06E, 0x00000441 }, - { 0x0213EA94DE262924, 0x00004363, 0xFFFFDF7A, 0x000006A0, 0x000031F5, 0xFFFFE880, 0x0000057B, 0x000031F5, 0xFFFFE880, 0x0000057B }, - { 0x0213EA94DE0E3844, 0x00003CFC, 0xFFFFE2AF, 0x0000062E, 0x0000212A, 0xFFFFF335, 0x000003BF, 0x0000212A, 0xFFFFF335, 0x000003BF }, - { 0x0213EA94DE1C4924, 0x0000252D, 0xFFFFF31B, 0x000003C3, 0x00001A1A, 0xFFFFF882, 0x00000325, 0x00001A1A, 0xFFFFF882, 0x00000325 }, - { 0x0213EA94DE0A29A4, 0x00003FE2, 0xFFFFDFEF, 0x000006AC, 0x000025A2, 0xFFFFEF84, 0x00000462, 0x000025A2, 0xFFFFEF84, 0x00000462 }, - { 0x0213EA94DE0820E4, 0x000040A5, 0xFFFFE13B, 0x0000065B, 0x00002C13, 0xFFFFEC75, 0x000004D7, 0x00002C13, 0xFFFFEC75, 0x000004D7 }, - { 0x0213EA94DE0E48A4, 0x00003E42, 0xFFFFE1B3, 0x00000657, 0x0000221D, 0xFFFFF273, 0x000003DE, 0x0000221D, 0xFFFFF273, 0x000003DE }, - { 0x0213EA94DE0A20E4, 0x00003E7F, 0xFFFFE255, 0x00000638, 0x00002D30, 0xFFFFEB8A, 0x00000503, 0x00002D30, 0xFFFFEB8A, 0x00000503 }, - { 0x0213EA94DE2C29C4, 0x00003E56, 0xFFFFE16D, 0x00000670, 0x000028DC, 0xFFFFEDA0, 0x000004BA, 0x000028DC, 0xFFFFEDA0, 0x000004BA }, - { 0x0213EA94DE2630A4, 0x000044AD, 0xFFFFDE24, 0x000006DD, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, - { 0x0213EA94DE2C20E4, 0x00003AF3, 0xFFFFE5B0, 0x000005A6, 0x00002CF6, 0xFFFFEC75, 0x000004DD, 0x00002CF6, 0xFFFFEC75, 0x000004DD }, - { 0x0213EA94DE0A2084, 0x00003E66, 0xFFFFE19E, 0x0000065B, 0x00002332, 0xFFFFF1B9, 0x000003FD, 0x00002332, 0xFFFFF1B9, 0x000003FD }, - { 0x0213EA94DE082884, 0x00003FB4, 0xFFFFE0A5, 0x00000686, 0x0000253E, 0xFFFFF02E, 0x00000444, 0x0000253E, 0xFFFFF02E, 0x00000444 }, - { 0x0213EA94DE2818A4, 0x00003E28, 0xFFFFE14D, 0x0000066E, 0x00001FE2, 0xFFFFF39A, 0x000003B1, 0x00001FE2, 0xFFFFF39A, 0x000003B1 }, - { 0x0213EA94DE2C0904, 0x000039E6, 0xFFFFE44B, 0x000005FE, 0x0000210C, 0xFFFFF2F4, 0x000003DA, 0x0000210C, 0xFFFFF2F4, 0x000003DA }, - { 0x0213EA94DE2C5104, 0x00003A4D, 0xFFFFE252, 0x0000067A, 0x000027E2, 0xFFFFECED, 0x000004FA, 0x000027E2, 0xFFFFECED, 0x000004FA }, - { 0x0213EA94DE0A2964, 0x00004065, 0xFFFFE02F, 0x0000069B, 0x0000299D, 0xFFFFED38, 0x000004C2, 0x0000299D, 0xFFFFED38, 0x000004C2 }, - { 0x0213EA94DE0E20A4, 0x000039EE, 0xFFFFE603, 0x00000594, 0x0000214F, 0xFFFFF429, 0x0000038E, 0x0000214F, 0xFFFFF429, 0x0000038E }, - { 0x0213EA94DE0E48E4, 0x00003BD2, 0xFFFFE351, 0x00000618, 0x000020B8, 0xFFFFF377, 0x000003B4, 0x000020B8, 0xFFFFF377, 0x000003B4 }, - { 0x0213EA94DE0A3124, 0x00003FAA, 0xFFFFE183, 0x0000065E, 0x000032AE, 0xFFFFE7C2, 0x000005A6, 0x000032AE, 0xFFFFE7C2, 0x000005A6 }, - { 0x0213EA94DE2C2984, 0x00003AFB, 0xFFFFE3E4, 0x00000608, 0x00002293, 0xFFFFF21F, 0x000003FA, 0x00002293, 0xFFFFF21F, 0x000003FA }, - { 0x0213EA94DE262064, 0x0000448B, 0xFFFFDD5D, 0x0000070D, 0x00002E4E, 0xFFFFE9DF, 0x00000551, 0x00002E4E, 0xFFFFE9DF, 0x00000551 }, - { 0x0213EA94DE0E2184, 0x00003D46, 0xFFFFE39B, 0x000005F3, 0x0000218E, 0xFFFFF3CD, 0x00000398, 0x0000218E, 0xFFFFF3CD, 0x00000398 }, - { 0x0213EA94DE0848E4, 0x00003F01, 0xFFFFDFD9, 0x000006BF, 0x000023AF, 0xFFFFF04E, 0x0000044C, 0x000023AF, 0xFFFFF04E, 0x0000044C }, - { 0x0213EA94DE1029A4, 0x0000403D, 0xFFFFDF6B, 0x000006C9, 0x0000270D, 0xFFFFEE4B, 0x0000049E, 0x0000270D, 0xFFFFEE4B, 0x0000049E }, - { 0x0213EA94DE0E3964, 0x00003C11, 0xFFFFE35C, 0x00000613, 0x000020F9, 0xFFFFF365, 0x000003B9, 0x000020F9, 0xFFFFF365, 0x000003B9 }, - { 0x0213EA94DE2C3884, 0x00003B58, 0xFFFFE37D, 0x0000061F, 0x00002698, 0xFFFFEF46, 0x00000478, 0x00002698, 0xFFFFEF46, 0x00000478 }, - { 0x0213EA94DE2841A4, 0x00003EBC, 0xFFFFDF7A, 0x000006D6, 0x0000212B, 0xFFFFF195, 0x0000041B, 0x0000212B, 0xFFFFF195, 0x0000041B }, - { 0x0213EA94DE0848C4, 0x00004050, 0xFFFFDEB3, 0x000006FE, 0x00002D6C, 0xFFFFE961, 0x00000582, 0x00002D6C, 0xFFFFE961, 0x00000582 }, - { 0x0213EA94DE262044, 0x000043F0, 0xFFFFDD9C, 0x00000702, 0x00002B31, 0xFFFFEBEA, 0x000004F7, 0x00002B31, 0xFFFFEBEA, 0x000004F7 }, - { 0x0213EA94DE100924, 0x00003EFA, 0xFFFFE093, 0x00000696, 0x000026DB, 0xFFFFEEB3, 0x00000489, 0x000026DB, 0xFFFFEEB3, 0x00000489 }, - { 0x0213EA94DE082064, 0x0000425D, 0xFFFFDE8D, 0x000006E6, 0x00002CA4, 0xFFFFEAD2, 0x00000531, 0x00002CA4, 0xFFFFEAD2, 0x00000531 }, - { 0x0213EA94DE2639A4, 0x000043B0, 0xFFFFDD03, 0x00000728, 0x00002946, 0xFFFFECA6, 0x000004DE, 0x00002946, 0xFFFFECA6, 0x000004DE }, - { 0x0213EA94DE282864, 0x00003F6A, 0xFFFFE03A, 0x0000069D, 0x00002208, 0xFFFFF1F8, 0x000003F6, 0x00002208, 0xFFFFF1F8, 0x000003F6 }, - { 0x0213EA94DE2C2964, 0x00003A94, 0xFFFFE4A7, 0x000005E2, 0x000024D0, 0xFFFFF100, 0x00000426, 0x000024D0, 0xFFFFF100, 0x00000426 }, - { 0x0213EA94DE2810C4, 0x00003F2F, 0xFFFFE0A3, 0x00000688, 0x00002198, 0xFFFFF271, 0x000003E2, 0x00002198, 0xFFFFF271, 0x000003E2 }, - { 0x0213EA94DE1048E4, 0x00003EA5, 0xFFFFE032, 0x000006AE, 0x0000227C, 0xFFFFF130, 0x00000426, 0x0000227C, 0xFFFFF130, 0x00000426 }, - { 0x0213EA94DE264144, 0x0000442F, 0xFFFFDBC4, 0x0000078B, 0x00003CD6, 0xFFFFDE6C, 0x0000076C, 0x00003CD6, 0xFFFFDE6C, 0x0000076C }, - { 0x0213EA94DE282884, 0x00003DDE, 0xFFFFE174, 0x00000668, 0x00001FF4, 0xFFFFF38F, 0x000003B1, 0x00001FF4, 0xFFFFF38F, 0x000003B1 }, - { 0x0213EA94DE0A3144, 0x000040B0, 0xFFFFE016, 0x000006A0, 0x00002DBB, 0xFFFFEA7F, 0x00000537, 0x00002DBB, 0xFFFFEA7F, 0x00000537 }, - { 0x0213EA94DE2C3104, 0x00003429, 0xFFFFEA97, 0x000004DD, 0x000024D5, 0xFFFFF26F, 0x000003DF, 0x000024D5, 0xFFFFF26F, 0x000003DF }, - { 0x0213EA94DE0E1904, 0x00003AEB, 0xFFFFE590, 0x000005A3, 0x000022CB, 0xFFFFF347, 0x000003B2, 0x000022CB, 0xFFFFF347, 0x000003B2 }, - { 0x0213EA94DE283904, 0x00003B8E, 0xFFFFE2EF, 0x00000636, 0x00002351, 0xFFFFF143, 0x0000041C, 0x00002351, 0xFFFFF143, 0x0000041C }, - { 0x0213EA94DE3240C4, 0x00002926, 0xFFFFF0B0, 0x00000410, 0x0000194E, 0xFFFFF94E, 0x000002E9, 0x0000194E, 0xFFFFF94E, 0x000002E9 }, - { 0x0213EA94DE283184, 0x0000402B, 0xFFFFDF78, 0x000006C2, 0x00002273, 0xFFFFF16C, 0x00000414, 0x00002273, 0xFFFFF16C, 0x00000414 }, - { 0x0213EA94DE0A10A4, 0x00003D6A, 0xFFFFE1D3, 0x00000659, 0x00002006, 0xFFFFF394, 0x000003B1, 0x00002006, 0xFFFFF394, 0x000003B1 }, - { 0x0213EA94DE284064, 0x00004042, 0xFFFFDFD8, 0x000006A8, 0x00002135, 0xFFFFF29F, 0x000003D9, 0x00002135, 0xFFFFF29F, 0x000003D9 }, - { 0x0213EA94DE0820A4, 0x0000405B, 0xFFFFE093, 0x00000682, 0x0000288F, 0xFFFFEE3A, 0x00000491, 0x0000288F, 0xFFFFEE3A, 0x00000491 }, - { 0x0213EA94DE2C48A4, 0x00003A49, 0xFFFFE30C, 0x00000648, 0x000023F9, 0xFFFFF02D, 0x00000460, 0x000023F9, 0xFFFFF02D, 0x00000460 }, - { 0x0213EA94DE282964, 0x00003D59, 0xFFFFE1CC, 0x0000065B, 0x00002013, 0xFFFFF37D, 0x000003B6, 0x00002013, 0xFFFFF37D, 0x000003B6 }, - { 0x0213EA94DE2C3984, 0x000040C1, 0xFFFFDF8C, 0x000006CA, 0x00003271, 0xFFFFE6CA, 0x000005EA, 0x00003271, 0xFFFFE6CA, 0x000005EA }, - { 0x0213EA94DE2620E4, 0x000042E9, 0xFFFFDFDC, 0x0000068C, 0x00002ED9, 0xFFFFEAAF, 0x0000051B, 0x00002ED9, 0xFFFFEAAF, 0x0000051B }, - { 0x0213EA94DE083084, 0x000042ED, 0xFFFFDE50, 0x000006F0, 0x00002FCF, 0xFFFFE8BB, 0x0000058C, 0x00002FCF, 0xFFFFE8BB, 0x0000058C }, - { 0x0213EA94DE0A4104, 0x00003EBD, 0xFFFFE099, 0x00000698, 0x00002709, 0xFFFFEE7B, 0x00000495, 0x00002709, 0xFFFFEE7B, 0x00000495 }, - { 0x0213EA94DE284904, 0x00003F71, 0xFFFFDF82, 0x000006C9, 0x0000219B, 0xFFFFF1AD, 0x0000040F, 0x0000219B, 0xFFFFF1AD, 0x0000040F }, - { 0x0213EA94DE2808E4, 0x00003E73, 0xFFFFE080, 0x0000069B, 0x000020E7, 0xFFFFF273, 0x000003E9, 0x000020E7, 0xFFFFF273, 0x000003E9 }, - { 0x0213EA94DE0E3184, 0x00003E14, 0xFFFFE278, 0x0000062C, 0x00002275, 0xFFFFF2B3, 0x000003CE, 0x00002275, 0xFFFFF2B3, 0x000003CE }, - { 0x0213EA94DE2C21A4, 0x00003ABB, 0xFFFFE3B9, 0x00000615, 0x00002192, 0xFFFFF28F, 0x000003EB, 0x00002192, 0xFFFFF28F, 0x000003EB }, - { 0x0213EA94DE283124, 0x00003D53, 0xFFFFE255, 0x00000643, 0x0000275B, 0xFFFFEEED, 0x00000479, 0x0000275B, 0xFFFFEEED, 0x00000479 }, - { 0x0213EA94DE262864, 0x000043E3, 0xFFFFDDC3, 0x000006FB, 0x00002B6B, 0xFFFFEBD6, 0x000004FA, 0x00002B6B, 0xFFFFEBD6, 0x000004FA }, - { 0x0213EA94DE0E2144, 0x00003BDE, 0xFFFFE507, 0x000005B4, 0x000022CE, 0xFFFFF358, 0x000003AB, 0x000022CE, 0xFFFFF358, 0x000003AB }, - { 0x0213EA94DE323164, 0x00002460, 0xFFFFF3B5, 0x000003A2, 0x000014E7, 0xFFFFFC32, 0x0000027C, 0x000014E7, 0xFFFFFC32, 0x0000027C }, - { 0x0213EA94DE2820C4, 0x00003D20, 0xFFFFE298, 0x0000062F, 0x00002080, 0xFFFFF3AF, 0x000003A8, 0x00002080, 0xFFFFF3AF, 0x000003A8 }, - { 0x0213EA94DE081904, 0x00003E14, 0xFFFFE221, 0x00000641, 0x000021BB, 0xFFFFF2EA, 0x000003CA, 0x000021BB, 0xFFFFF2EA, 0x000003CA }, - { 0x0213EA94DE0A40C4, 0x00003DE1, 0xFFFFE14E, 0x00000677, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, - { 0x0213EA94DE261084, 0x00004372, 0xFFFFDDF8, 0x000006F5, 0x00002B3F, 0xFFFFEBE8, 0x000004F8, 0x00002B3F, 0xFFFFEBE8, 0x000004F8 }, - { 0x0213EA94DE0A28C4, 0x00003E4F, 0xFFFFE2A3, 0x0000062B, 0x00002F5A, 0xFFFFEA37, 0x0000053B, 0x00002F5A, 0xFFFFEA37, 0x0000053B }, - { 0x0213EA94DE2850E4, 0x00003E07, 0xFFFFE02F, 0x000006B6, 0x0000216B, 0xFFFFF1A3, 0x00000416, 0x0000216B, 0xFFFFF1A3, 0x00000416 }, - { 0x0213EA94DE2838A4, 0x00003DAB, 0xFFFFE128, 0x0000067F, 0x0000216F, 0xFFFFF236, 0x000003F3, 0x0000216F, 0xFFFFF236, 0x000003F3 }, - { 0x0213EA94DE2C2924, 0x0000364B, 0xFFFFE8CB, 0x0000052A, 0x00002568, 0xFFFFF1B2, 0x00000400, 0x00002568, 0xFFFFF1B2, 0x00000400 }, - { 0x0213EA94DE261064, 0x00004219, 0xFFFFDE87, 0x000006E8, 0x00002C59, 0xFFFFEAEE, 0x00000529, 0x00002C59, 0xFFFFEAEE, 0x00000529 }, - { 0x0213EA94DE0E1944, 0x000039A8, 0xFFFFE602, 0x00000594, 0x00001D06, 0xFFFFF6F0, 0x00000316, 0x00001D06, 0xFFFFF6F0, 0x00000316 }, - { 0x0213EA94DE2610E4, 0x00004052, 0xFFFFE01C, 0x00000698, 0x00002310, 0xFFFFF1A1, 0x000003FE, 0x00002310, 0xFFFFF1A1, 0x000003FE }, - { 0x0213EA94DE0E2824, 0x00003C1C, 0xFFFFE3EB, 0x000005F1, 0x00002289, 0xFFFFF2CF, 0x000003C9, 0x00002289, 0xFFFFF2CF, 0x000003C9 }, - { 0x0213EA94DE0E5124, 0x00003F19, 0xFFFFE085, 0x0000069E, 0x00002B94, 0xFFFFEB72, 0x0000051D, 0x00002B94, 0xFFFFEB72, 0x0000051D }, - { 0x0213EA94DE0E41A4, 0x00003C51, 0xFFFFE2AD, 0x00000638, 0x0000206B, 0xFFFFF361, 0x000003BE, 0x0000206B, 0xFFFFF361, 0x000003BE }, - { 0x0213EA94DE2610C4, 0x000040B9, 0xFFFFDFBB, 0x000006AB, 0x0000241F, 0xFFFFF0CC, 0x00000425, 0x0000241F, 0xFFFFF0CC, 0x00000425 }, - { 0x0213EA94DE0A2064, 0x00003E62, 0xFFFFE12C, 0x00000678, 0x00002445, 0xFFFFF09E, 0x00000435, 0x00002445, 0xFFFFF09E, 0x00000435 }, - { 0x0213EA94DE0E1984, 0x00003C97, 0xFFFFE399, 0x000005FB, 0x0000209D, 0xFFFFF41D, 0x0000038F, 0x0000209D, 0xFFFFF41D, 0x0000038F }, - { 0x0213EA94DE0E3144, 0x00003FF9, 0xFFFFE1E9, 0x0000063E, 0x00002E96, 0xFFFFEAF5, 0x00000516, 0x00002E96, 0xFFFFEAF5, 0x00000516 }, - { 0x0213EA94DE0A3084, 0x00003F04, 0xFFFFE109, 0x0000067A, 0x000026E1, 0xFFFFEF0B, 0x00000476, 0x000026E1, 0xFFFFEF0B, 0x00000476 }, - { 0x0213EA94DE101124, 0x00003E3E, 0xFFFFE187, 0x00000660, 0x00002049, 0xFFFFF38D, 0x000003B0, 0x00002049, 0xFFFFF38D, 0x000003B0 }, - { 0x0213EA94DE282944, 0x00003D58, 0xFFFFE253, 0x0000063D, 0x00002158, 0xFFFFF308, 0x000003C3, 0x00002158, 0xFFFFF308, 0x000003C3 }, - { 0x0213EA94DE0840C4, 0x00004074, 0xFFFFDF8D, 0x000006C0, 0x00002799, 0xFFFFEE19, 0x000004A5, 0x00002799, 0xFFFFEE19, 0x000004A5 }, - { 0x0213EA94DE281924, 0x00003DAF, 0xFFFFE1C9, 0x00000659, 0x000020E5, 0xFFFFF313, 0x000003C6, 0x000020E5, 0xFFFFF313, 0x000003C6 }, - { 0x0213EA94DE0A3964, 0x000041DD, 0xFFFFDDFA, 0x0000071B, 0x0000348D, 0xFFFFE4B4, 0x0000064C, 0x0000348D, 0xFFFFE4B4, 0x0000064C }, - { 0x0213EA94DE2C2884, 0x00003947, 0xFFFFE5AE, 0x000005B8, 0x000024A6, 0xFFFFF140, 0x0000041D, 0x000024A6, 0xFFFFF140, 0x0000041D }, - { 0x0213EA94DE101844, 0x00003D35, 0xFFFFE197, 0x0000066E, 0x00002248, 0xFFFFF1BC, 0x00000408, 0x00002248, 0xFFFFF1BC, 0x00000408 }, - { 0x0213EA94DE0A18E4, 0x00003F4F, 0xFFFFE13E, 0x0000066D, 0x00002AF0, 0xFFFFEC99, 0x000004DB, 0x00002AF0, 0xFFFFEC99, 0x000004DB }, - { 0x0213EA94DE263944, 0x0000430F, 0xFFFFDDFB, 0x000006FC, 0x00002D4D, 0xFFFFEA55, 0x00000540, 0x00002D4D, 0xFFFFEA55, 0x00000540 }, - { 0x0213EA94DE0E2944, 0x00003B22, 0xFFFFE543, 0x000005B1, 0x000022E1, 0xFFFFF31B, 0x000003B9, 0x000022E1, 0xFFFFF31B, 0x000003B9 }, - { 0x0213EA94DE0E2084, 0x00003978, 0xFFFFE611, 0x00000592, 0x00001C36, 0xFFFFF771, 0x00000302, 0x00001C36, 0xFFFFF771, 0x00000302 }, - { 0x0213EA94DE262164, 0x000044DF, 0xFFFFDDAB, 0x000006F2, 0x00002CEA, 0xFFFFEB47, 0x00000507, 0x00002CEA, 0xFFFFEB47, 0x00000507 }, - { 0x0213EA94DE0A38C4, 0x00003E9B, 0xFFFFE12C, 0x0000067C, 0x00002B79, 0xFFFFEBD9, 0x00000503, 0x00002B79, 0xFFFFEBD9, 0x00000503 }, - { 0x0213EA94DE263044, 0x00004464, 0xFFFFDCD3, 0x00000731, 0x00002D14, 0xFFFFEA2D, 0x0000054E, 0x00002D14, 0xFFFFEA2D, 0x0000054E }, - { 0x0213EA94DE281124, 0x00003FB3, 0xFFFFE052, 0x00000693, 0x000020AC, 0xFFFFF311, 0x000003C6, 0x000020AC, 0xFFFFF311, 0x000003C6 }, - { 0x0213EA94DE2C1084, 0x00003BDA, 0xFFFFE2FB, 0x00000636, 0x0000261E, 0xFFFFEF72, 0x00000471, 0x0000261E, 0xFFFFEF72, 0x00000471 }, - { 0x0213EA94DE2C1964, 0x00003D72, 0xFFFFE28A, 0x0000063E, 0x000029D8, 0xFFFFED54, 0x000004C7, 0x000029D8, 0xFFFFED54, 0x000004C7 }, - { 0x0213EA94DE2C2824, 0x00003E26, 0xFFFFE102, 0x00000694, 0x00002DD1, 0xFFFFE9CA, 0x0000056D, 0x00002DD1, 0xFFFFE9CA, 0x0000056D }, - { 0x0213EA94DE104124, 0x000041CD, 0xFFFFDE97, 0x000006ED, 0x00002DE5, 0xFFFFE9B9, 0x00000565, 0x00002DE5, 0xFFFFE9B9, 0x00000565 }, - { 0x0213EA94DE0A2984, 0x00003F30, 0xFFFFE06E, 0x00000698, 0x000024FF, 0xFFFFEFFC, 0x0000044F, 0x000024FF, 0xFFFFEFFC, 0x0000044F }, - { 0x0213EA94DE2C38C4, 0x0000378B, 0xFFFFE6B4, 0x00000594, 0x000023A7, 0xFFFFF1DC, 0x00000407, 0x000023A7, 0xFFFFF1DC, 0x00000407 }, - { 0x0213EA94DE0E4164, 0x00003CD7, 0xFFFFE28D, 0x00000636, 0x00002036, 0xFFFFF3B5, 0x000003AA, 0x00002036, 0xFFFFF3B5, 0x000003AA }, - { 0x0213EA94DE0A3884, 0x00003EF9, 0xFFFFE0AA, 0x0000068D, 0x000024D3, 0xFFFFF02F, 0x00000445, 0x000024D3, 0xFFFFF02F, 0x00000445 }, - { 0x0213EA94DE283944, 0x00003D08, 0xFFFFE1BB, 0x00000665, 0x00002159, 0xFFFFF26F, 0x000003E6, 0x00002159, 0xFFFFF26F, 0x000003E6 }, - { 0x0213EA94DE2C20C4, 0x000038A9, 0xFFFFE6CA, 0x00000580, 0x000025D3, 0xFFFFF101, 0x00000421, 0x000025D3, 0xFFFFF101, 0x00000421 }, - { 0x0213EA94DE0A20A4, 0x00003E45, 0xFFFFE1F8, 0x0000064D, 0x000027E3, 0xFFFFEEBB, 0x0000047F, 0x000027E3, 0xFFFFEEBB, 0x0000047F }, - { 0x0213EA94DE0E3864, 0x00003F76, 0xFFFFE128, 0x0000066E, 0x0000286B, 0xFFFFEE4C, 0x00000493, 0x0000286B, 0xFFFFEE4C, 0x00000493 }, - { 0x0213EA94DE264104, 0x0000440D, 0xFFFFDCA2, 0x0000074F, 0x00003817, 0xFFFFE256, 0x000006AF, 0x00003817, 0xFFFFE256, 0x000006AF }, - { 0x0213EA94DE105104, 0x00003EE1, 0xFFFFDFA7, 0x000006D4, 0x000027EA, 0xFFFFED2B, 0x000004DE, 0x000027EA, 0xFFFFED2B, 0x000004DE }, - { 0x0213EA94DE2C3864, 0x00003C62, 0xFFFFE285, 0x0000064A, 0x00002520, 0xFFFFF001, 0x0000045C, 0x00002520, 0xFFFFF001, 0x0000045C }, - { 0x0213EA94DE323964, 0x0000272E, 0xFFFFF17A, 0x000003FA, 0x0000150B, 0xFFFFFBD5, 0x00000284, 0x0000150B, 0xFFFFFBD5, 0x00000284 }, - { 0x0213EA94DE261924, 0x00004275, 0xFFFFDF69, 0x000006A5, 0x000025AA, 0xFFFFF05C, 0x0000042B, 0x000025AA, 0xFFFFF05C, 0x0000042B }, - { 0x0213EA94DE0E40E4, 0x00003CAA, 0xFFFFE392, 0x000005FF, 0x000023A8, 0xFFFFF20E, 0x000003E9, 0x000023A8, 0xFFFFF20E, 0x000003E9 }, - { 0x0213EA94DE2C50C4, 0x00003CF8, 0xFFFFE0FB, 0x000006A6, 0x00002CA7, 0xFFFFE9FF, 0x0000056E, 0x00002CA7, 0xFFFFE9FF, 0x0000056E }, - { 0x0213EA94DE282124, 0x00003D00, 0xFFFFE296, 0x00000633, 0x000021C1, 0xFFFFF2C8, 0x000003CF, 0x000021C1, 0xFFFFF2C8, 0x000003CF }, - { 0x0213EA94DE2838E4, 0x00003B46, 0xFFFFE301, 0x00000632, 0x0000204C, 0xFFFFF33B, 0x000003C8, 0x0000204C, 0xFFFFF33B, 0x000003C8 }, - { 0x0213EA94DE204164, 0x00002026, 0xFFFFF5CE, 0x00000368, 0x00001598, 0xFFFFFB29, 0x000002C3, 0x00001598, 0xFFFFFB29, 0x000002C3 }, - { 0x0213EA94DE283164, 0x00003DCA, 0xFFFFE178, 0x00000668, 0x00001FDB, 0xFFFFF39D, 0x000003AF, 0x00001FDB, 0xFFFFF39D, 0x000003AF }, - { 0x0213EA94DE2C48C4, 0x00003A59, 0xFFFFE327, 0x00000642, 0x000024B9, 0xFFFFEFC4, 0x00000471, 0x000024B9, 0xFFFFEFC4, 0x00000471 }, - { 0x0213EA94DE2C2944, 0x00003C26, 0xFFFFE440, 0x000005EB, 0x00002C0F, 0xFFFFEC88, 0x000004E0, 0x00002C0F, 0xFFFFEC88, 0x000004E0 }, - { 0x0213EA94DE083884, 0x00004149, 0xFFFFDEB8, 0x000006E7, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, - { 0x0213EA94DE0E4124, 0x00003EB4, 0xFFFFE1E5, 0x0000064D, 0x0000299F, 0xFFFFEDB3, 0x000004A9, 0x0000299F, 0xFFFFEDB3, 0x000004A9 }, - { 0x0213EA94DE2C39A4, 0x00003BBF, 0xFFFFE268, 0x0000065A, 0x00002504, 0xFFFFEFB0, 0x00000470, 0x00002504, 0xFFFFEFB0, 0x00000470 }, - { 0x0213EA94DE084904, 0x00004203, 0xFFFFDDC6, 0x00000720, 0x0000303B, 0xFFFFE78F, 0x000005D0, 0x0000303B, 0xFFFFE78F, 0x000005D0 }, - { 0x0213EA94DE0E3984, 0x00003DA3, 0xFFFFE244, 0x0000063E, 0x000021B4, 0xFFFFF2DA, 0x000003CD, 0x000021B4, 0xFFFFF2DA, 0x000003CD }, - { 0x0213EA94DE0A38E4, 0x00004035, 0xFFFFE065, 0x0000069B, 0x00003323, 0xFFFFE6D6, 0x000005D8, 0x00003323, 0xFFFFE6D6, 0x000005D8 }, - { 0x0213EA94DE2C1164, 0x00003944, 0xFFFFE4E5, 0x000005E2, 0x00001F3C, 0xFFFFF456, 0x0000039D, 0x00001F3C, 0xFFFFF456, 0x0000039D }, - { 0x0213EA94DE061904, 0x000032D8, 0xFFFFEAE8, 0x000004E6, 0x00001812, 0xFFFFFA1C, 0x000002BC, 0x00001812, 0xFFFFFA1C, 0x000002BC }, - { 0x0213F0FD42D22944, 0x000041F6, 0xFFFFE025, 0x0000069A, 0x0000241E, 0xFFFFF1B4, 0x00000402, 0x0000241E, 0xFFFFF1B4, 0x00000402 }, - { 0x0213F0FE990C30A4, 0x00003300, 0xFFFFEB60, 0x000004C1, 0x00001E15, 0xFFFFF6A6, 0x0000033B, 0x00001E15, 0xFFFFF6A6, 0x0000033B }, - { 0x0213EA94DE0408A4, 0x000037F0, 0xFFFFE68F, 0x0000059B, 0x00001F8A, 0xFFFFF467, 0x000003A3, 0x00001F8A, 0xFFFFF467, 0x000003A3 }, - { 0x0213F0FE99182984, 0x000025D8, 0xFFFFF2AA, 0x000003C3, 0x000018A8, 0xFFFFF9BE, 0x000002D2, 0x000018A8, 0xFFFFF9BE, 0x000002D2 }, - { 0x0213F0FE990620C4, 0x0000364F, 0xFFFFE988, 0x000004FC, 0x00001E51, 0xFFFFF633, 0x0000034F, 0x00001E51, 0xFFFFF633, 0x0000034F }, - { 0x0213EA94DE061144, 0x00002288, 0xFFFFF483, 0x0000036C, 0x0000280F, 0xFFFFEF39, 0x0000047B, 0x0000280F, 0xFFFFEF39, 0x0000047B }, - { 0x0213F0FE99082084, 0x00003322, 0xFFFFEA7E, 0x000004ED, 0x00001DAD, 0xFFFFF62B, 0x00000355, 0x00001DAD, 0xFFFFF62B, 0x00000355 }, - { 0x0213EA94DE0250E4, 0x00002B7B, 0xFFFFEE4F, 0x0000045B, 0x00001AA2, 0xFFFFF710, 0x0000033E, 0x00001AA2, 0xFFFFF710, 0x0000033E }, - { 0x0213F0FE990420C4, 0x000034CC, 0xFFFFEA79, 0x000004E4, 0x00001B05, 0xFFFFF8B3, 0x000002EC, 0x00001B05, 0xFFFFF8B3, 0x000002EC }, - { 0x0213F0FD42DC2864, 0x00003837, 0xFFFFE5ED, 0x000005C3, 0x00001ACB, 0xFFFFF7B2, 0x00000314, 0x00001ACB, 0xFFFFF7B2, 0x00000314 }, - { 0x0213F0FE99044164, 0x0000352D, 0xFFFFE88F, 0x00000548, 0x000021E6, 0xFFFFF3B5, 0x000003AA, 0x000021E6, 0xFFFFF3B5, 0x000003AA }, - { 0x0213F0FE990A4884, 0x00003300, 0xFFFFE835, 0x0000057B, 0x00001A85, 0xFFFFF715, 0x00000336, 0x00001A85, 0xFFFFF715, 0x00000336 }, - { 0x0213EA94DE0448A4, 0x000033FA, 0xFFFFE851, 0x00000565, 0x00001A8E, 0xFFFFF727, 0x0000033B, 0x00001A8E, 0xFFFFF727, 0x0000033B }, - { 0x0213F0FD42DA3924, 0x000039D3, 0xFFFFE5D3, 0x000005B0, 0x00001888, 0xFFFFF978, 0x000002C8, 0x00001888, 0xFFFFF978, 0x000002C8 }, - { 0x0213F0FE990E4864, 0x00002F6B, 0xFFFFEC53, 0x000004B9, 0x00001C15, 0xFFFFF71B, 0x00000337, 0x00001C15, 0xFFFFF71B, 0x00000337 }, - { 0x0213F0FE99064144, 0x0000384D, 0xFFFFE737, 0x00000569, 0x00001D2D, 0xFFFFF673, 0x00000343, 0x00001D2D, 0xFFFFF673, 0x00000343 }, - { 0x0213F0FE990620A4, 0x00003A49, 0xFFFFE70B, 0x0000055F, 0x00001A63, 0xFFFFF8CD, 0x000002E2, 0x00001A63, 0xFFFFF8CD, 0x000002E2 }, - { 0x0213F0FE99042984, 0x0000311E, 0xFFFFEB97, 0x000004C6, 0x00001EAE, 0xFFFFF5A9, 0x00000367, 0x00001EAE, 0xFFFFF5A9, 0x00000367 }, - { 0x0213F0FE990E1124, 0x000027D3, 0xFFFFF075, 0x00000417, 0x00002001, 0xFFFFF44A, 0x000003A2, 0x00002001, 0xFFFFF44A, 0x000003A2 }, - { 0x0213F0FE99064904, 0x00003B72, 0xFFFFE4BD, 0x000005DC, 0x00001D76, 0xFFFFF606, 0x0000035A, 0x00001D76, 0xFFFFF606, 0x0000035A }, - { 0x0213F0FE99101124, 0x00002E0F, 0xFFFFECA7, 0x000004AE, 0x00001DC6, 0xFFFFF5BF, 0x0000036A, 0x00001DC6, 0xFFFFF5BF, 0x0000036A }, - { 0x0213F0FE990238A4, 0x000032C7, 0xFFFFEA7A, 0x000004F0, 0x00001A7B, 0xFFFFF827, 0x00000301, 0x00001A7B, 0xFFFFF827, 0x00000301 }, - { 0x0213EA94DE044884, 0x0000312D, 0xFFFFEA39, 0x00000515, 0x00001948, 0xFFFFF800, 0x00000318, 0x00001948, 0xFFFFF800, 0x00000318 }, - { 0x0213EA94DE062084, 0x00003611, 0xFFFFE8D7, 0x00000533, 0x00001929, 0xFFFFF965, 0x000002D2, 0x00001929, 0xFFFFF965, 0x000002D2 }, - { 0x0213F0FE992C30E4, 0x00002FE2, 0xFFFFED89, 0x00000470, 0x00001A3C, 0xFFFFF955, 0x000002D5, 0x00001A3C, 0xFFFFF955, 0x000002D5 }, - { 0x0213EA94DE0208A4, 0x000035FF, 0xFFFFE884, 0x00000548, 0x0000182A, 0xFFFFF9AB, 0x000002CF, 0x0000182A, 0xFFFFF9AB, 0x000002CF }, - { 0x0213F0FE990220E4, 0x00003597, 0xFFFFE904, 0x00000528, 0x00001A94, 0xFFFFF840, 0x00000300, 0x00001A94, 0xFFFFF840, 0x00000300 }, - { 0x0213F0FE99181944, 0x000026CB, 0xFFFFF1FB, 0x000003E4, 0x000017CC, 0xFFFFFA25, 0x000002C8, 0x000017CC, 0xFFFFFA25, 0x000002C8 }, - { 0x0213EA94DE0608C4, 0x00003274, 0xFFFFEA39, 0x0000050C, 0x00001B20, 0xFFFFF7C1, 0x00000314, 0x00001B20, 0xFFFFF7C1, 0x00000314 }, - { 0x0213F0FD42D82924, 0x0000280B, 0xFFFFF283, 0x000003B5, 0x000018D0, 0xFFFFF992, 0x000002EC, 0x000018D0, 0xFFFFF992, 0x000002EC }, - { 0x0213F0FE99062104, 0x000033AB, 0xFFFFEB1B, 0x000004C4, 0x00001FEE, 0xFFFFF53A, 0x00000378, 0x00001FEE, 0xFFFFF53A, 0x00000378 }, - { 0x0213F0FE990A3964, 0x00002F79, 0xFFFFEB0C, 0x000004FA, 0x00001E57, 0xFFFFF4BF, 0x0000039B, 0x00001E57, 0xFFFFF4BF, 0x0000039B }, - { 0x0213F0FE990448E4, 0x00003487, 0xFFFFE8F2, 0x00000539, 0x0000185B, 0xFFFFF9AE, 0x000002BA, 0x0000185B, 0xFFFFF9AE, 0x000002BA }, - { 0x0213F0FE990A18A4, 0x00003500, 0xFFFFE793, 0x0000058A, 0x00001AA2, 0xFFFFF792, 0x0000031D, 0x00001AA2, 0xFFFFF792, 0x0000031D }, - { 0x0213F0FE99081164, 0x00003943, 0xFFFFE54D, 0x000005D9, 0x00001BC8, 0xFFFFF6E0, 0x00000339, 0x00001BC8, 0xFFFFF6E0, 0x00000339 }, - { 0x0213EA94DE0430A4, 0x0000306D, 0xFFFFEC5E, 0x000004A5, 0x00001A3A, 0xFFFFF85F, 0x00000304, 0x00001A3A, 0xFFFFF85F, 0x00000304 }, - { 0x0213F0FD42D83084, 0x00002BA4, 0xFFFFEE8D, 0x0000046A, 0x0000198C, 0xFFFFF88E, 0x00000307, 0x0000198C, 0xFFFFF88E, 0x00000307 }, - { 0x0213F0FD42D218E4, 0x00003D30, 0xFFFFE2F6, 0x0000062A, 0x000025DC, 0xFFFFF074, 0x00000435, 0x000025DC, 0xFFFFF074, 0x00000435 }, - { 0x0213F0FD42D83964, 0x00002CD6, 0xFFFFED79, 0x0000049B, 0x000016D0, 0xFFFFFA53, 0x000002BB, 0x000016D0, 0xFFFFFA53, 0x000002BB }, - { 0x0213F0FE99163164, 0x00002484, 0xFFFFF3BD, 0x000003A0, 0x000015B8, 0xFFFFFB6B, 0x000002A4, 0x000015B8, 0xFFFFFB6B, 0x000002A4 }, - { 0x0213F0FE990E3944, 0x000038AE, 0xFFFFE6D1, 0x00000587, 0x00001A2A, 0xFFFFF8F1, 0x000002D4, 0x00001A2A, 0xFFFFF8F1, 0x000002D4 }, - { 0x0213F0FE99044944, 0x000036FD, 0xFFFFE76C, 0x00000576, 0x00001EE4, 0xFFFFF58D, 0x00000361, 0x00001EE4, 0xFFFFF58D, 0x00000361 }, - { 0x0213F0FD42D830A4, 0x00002BCF, 0xFFFFEF28, 0x00000448, 0x00001B93, 0xFFFFF7BA, 0x00000327, 0x00001B93, 0xFFFFF7BA, 0x00000327 }, - { 0x0213F0FE99062884, 0x00003834, 0xFFFFE818, 0x0000053B, 0x00001AFE, 0xFFFFF85C, 0x000002F3, 0x00001AFE, 0xFFFFF85C, 0x000002F3 }, - { 0x0213F0FE993231A4, 0x00002EF7, 0xFFFFEBFC, 0x000004CE, 0x00001897, 0xFFFFF8EF, 0x000002EC, 0x00001897, 0xFFFFF8EF, 0x000002EC }, - { 0x0213F0FE992C18C4, 0x000035BD, 0xFFFFE8BB, 0x0000053B, 0x00001F22, 0xFFFFF561, 0x00000373, 0x00001F22, 0xFFFFF561, 0x00000373 }, - { 0x0213F0FE99183984, 0x00002D42, 0xFFFFEE1D, 0x00000478, 0x000016F0, 0xFFFFFAAE, 0x000002B3, 0x000016F0, 0xFFFFFAAE, 0x000002B3 }, - { 0x0213EA94DE045124, 0x00002F98, 0xFFFFEB3C, 0x000004F0, 0x00001903, 0xFFFFF818, 0x00000319, 0x00001903, 0xFFFFF818, 0x00000319 }, - { 0x0213F0FD42D42144, 0x00004081, 0xFFFFDF13, 0x000006F3, 0x00002A6D, 0xFFFFEC1B, 0x00000509, 0x00002A6D, 0xFFFFEC1B, 0x00000509 }, - { 0x0213EA94DE040904, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001FF6, 0xFFFFF427, 0x000003B0, 0x00001FF6, 0xFFFFF427, 0x000003B0 }, - { 0x0213F0FE99023884, 0x00003243, 0xFFFFEA5C, 0x000004FD, 0x000020FB, 0xFFFFF39E, 0x000003C0, 0x000020FB, 0xFFFFF39E, 0x000003C0 }, - { 0x0213F0FD42D848A4, 0x00002F20, 0xFFFFEC19, 0x000004C6, 0x00001748, 0xFFFFF99F, 0x000002DA, 0x00001748, 0xFFFFF99F, 0x000002DA }, - { 0x0213F0FE99103984, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001A43, 0xFFFFF843, 0x000002F9, 0x00001A43, 0xFFFFF843, 0x000002F9 }, - { 0x0213F0FE990220A4, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x00001A51, 0xFFFFF850, 0x000002FA, 0x00001A51, 0xFFFFF850, 0x000002FA }, - { 0x0213F0FE99043144, 0x0000305C, 0xFFFFED4B, 0x0000046C, 0x00001CF9, 0xFFFFF7BA, 0x00000304, 0x00001CF9, 0xFFFFF7BA, 0x00000304 }, - { 0x0213F0FD42DA4164, 0x0000343C, 0xFFFFE869, 0x00000559, 0x00001CE2, 0xFFFFF614, 0x00000359, 0x00001CE2, 0xFFFFF614, 0x00000359 }, - { 0x0213F0FE99183964, 0x00002782, 0xFFFFF1FE, 0x000003D9, 0x000015DC, 0xFFFFFB8B, 0x00000290, 0x000015DC, 0xFFFFFB8B, 0x00000290 }, - { 0x0213F0FE991818C4, 0x00002B9C, 0xFFFFEF63, 0x00000443, 0x00001369, 0xFFFFFD51, 0x00000244, 0x00001369, 0xFFFFFD51, 0x00000244 }, - { 0x0213F0FE990A2084, 0x000035F8, 0xFFFFE743, 0x00000592, 0x000018D8, 0xFFFFF8EE, 0x000002E4, 0x000018D8, 0xFFFFF8EE, 0x000002E4 }, - { 0x0213EA94DE062844, 0x00002B72, 0xFFFFEF1E, 0x0000043C, 0x00002647, 0xFFFFF092, 0x0000043E, 0x00002647, 0xFFFFF092, 0x0000043E }, - { 0x0213F0FE99102184, 0x00002EC9, 0xFFFFEC5F, 0x000004B8, 0x000018B6, 0xFFFFF936, 0x000002D8, 0x000018B6, 0xFFFFF936, 0x000002D8 }, - { 0x0213F0FE99064084, 0x000038A7, 0xFFFFE6AC, 0x00000589, 0x00001C42, 0xFFFFF70B, 0x00000329, 0x00001C42, 0xFFFFF70B, 0x00000329 }, - { 0x0213F0FE993008A4, 0x00002F6B, 0xFFFFEBF6, 0x000004CF, 0x000018AE, 0xFFFFF928, 0x000002E3, 0x000018AE, 0xFFFFF928, 0x000002E3 }, - { 0x0213F0FD42DA5104, 0x000029CD, 0xFFFFEEE1, 0x00000459, 0x00001AB5, 0xFFFFF76F, 0x00000324, 0x00001AB5, 0xFFFFF76F, 0x00000324 }, - { 0x0213EA94DE0638C4, 0x00003921, 0xFFFFE71D, 0x00000577, 0x00001646, 0xFFFFFB24, 0x00000293, 0x00001646, 0xFFFFFB24, 0x00000293 }, - { 0x0213EA94DE044164, 0x00003940, 0xFFFFE521, 0x000005E8, 0x00001947, 0xFFFFF839, 0x0000030D, 0x00001947, 0xFFFFF839, 0x0000030D }, - { 0x0213F0FD42D24164, 0x00003DCA, 0xFFFFE211, 0x00000659, 0x0000250E, 0xFFFFF072, 0x00000443, 0x0000250E, 0xFFFFF072, 0x00000443 }, - { 0x0213F0FE990C0904, 0x00002E95, 0xFFFFEC20, 0x000004C9, 0x000015B4, 0xFFFFFAD3, 0x0000029D, 0x000015B4, 0xFFFFFAD3, 0x0000029D }, - { 0x0213F0FE99041084, 0x00002C11, 0xFFFFEE6E, 0x00000468, 0x00001901, 0xFFFFF924, 0x000002E7, 0x00001901, 0xFFFFF924, 0x000002E7 }, - { 0x0213EA94DE062104, 0x0000293F, 0xFFFFF158, 0x000003E6, 0x0000183F, 0xFFFFF9F6, 0x000002D2, 0x0000183F, 0xFFFFF9F6, 0x000002D2 }, - { 0x0213F0FE990E1104, 0x00002A67, 0xFFFFEF34, 0x0000043E, 0x00001C6F, 0xFFFFF6F1, 0x0000032B, 0x00001C6F, 0xFFFFF6F1, 0x0000032B }, - { 0x0213EA94DE065124, 0x00002F8D, 0xFFFFEB77, 0x000004DA, 0x00001C0D, 0xFFFFF627, 0x00000365, 0x00001C0D, 0xFFFFF627, 0x00000365 }, - { 0x0213F0FE990C38C4, 0x00003476, 0xFFFFEA5B, 0x000004E7, 0x00001DBF, 0xFFFFF6C7, 0x00000333, 0x00001DBF, 0xFFFFF6C7, 0x00000333 }, - { 0x0213F0FE990E0944, 0x00003336, 0xFFFFE92F, 0x00000546, 0x00001614, 0xFFFFFAE0, 0x00000296, 0x00001614, 0xFFFFFAE0, 0x00000296 }, - { 0x0213F0FE99162164, 0x00002513, 0xFFFFF323, 0x000003BC, 0x000016DB, 0xFFFFFA79, 0x000002CD, 0x000016DB, 0xFFFFFA79, 0x000002CD }, - { 0x0213F0FE990A2944, 0x000035A7, 0xFFFFE78E, 0x00000584, 0x00001B0D, 0xFFFFF77D, 0x0000031F, 0x00001B0D, 0xFFFFF77D, 0x0000031F }, - { 0x0213F0FE993238E4, 0x00003171, 0xFFFFEB98, 0x000004C6, 0x00001C76, 0xFFFFF71F, 0x0000032F, 0x00001C76, 0xFFFFF71F, 0x0000032F }, - { 0x0213F0FD42DA1084, 0x00002C52, 0xFFFFED2E, 0x000004A7, 0x00002182, 0xFFFFF2F4, 0x000003E4, 0x00002182, 0xFFFFF2F4, 0x000003E4 }, - { 0x0213F0FE99102924, 0x000032E1, 0xFFFFEB39, 0x000004D0, 0x00001B55, 0xFFFFF859, 0x000002FA, 0x00001B55, 0xFFFFF859, 0x000002FA }, - { 0x0213F0FE991848A4, 0x000029B6, 0xFFFFEFF7, 0x00000430, 0x0000151B, 0xFFFFFBC6, 0x0000027F, 0x0000151B, 0xFFFFFBC6, 0x0000027F }, - { 0x0213F0FD42DA1964, 0x00002FF7, 0xFFFFEB67, 0x000004DA, 0x000020E9, 0xFFFFF363, 0x000003CE, 0x000020E9, 0xFFFFF363, 0x000003CE }, - { 0x0213F0FD42DA5124, 0x00003CDD, 0xFFFFE2B2, 0x00000649, 0x00001B18, 0xFFFFF739, 0x00000329, 0x00001B18, 0xFFFFF739, 0x00000329 }, - { 0x0213F0FE990628A4, 0x00003C82, 0xFFFFE5C6, 0x0000058E, 0x00001F3F, 0xFFFFF5AD, 0x00000361, 0x00001F3F, 0xFFFFF5AD, 0x00000361 }, - { 0x0213F0FD42DC4084, 0x0000319B, 0xFFFFEA15, 0x0000051B, 0x00001CC9, 0xFFFFF62E, 0x00000358, 0x00001CC9, 0xFFFFF62E, 0x00000358 }, - { 0x0213EA94DE0638E4, 0x000032B6, 0xFFFFEB2B, 0x000004D6, 0x000018E0, 0xFFFFF966, 0x000002DE, 0x000018E0, 0xFFFFF966, 0x000002DE }, - { 0x0213EA94DE023984, 0x0000300A, 0xFFFFEBA6, 0x000004D1, 0x00001CFD, 0xFFFFF5F6, 0x0000036D, 0x00001CFD, 0xFFFFF5F6, 0x0000036D }, - { 0x0213F0FD42D82984, 0x000026A9, 0xFFFFF15D, 0x00000400, 0x00001561, 0xFFFFFB1F, 0x000002A0, 0x00001561, 0xFFFFFB1F, 0x000002A0 }, - { 0x0213F0FE990E5124, 0x00003123, 0xFFFFEAD2, 0x000004FA, 0x000018CB, 0xFFFFF8F5, 0x000002EC, 0x000018CB, 0xFFFFF8F5, 0x000002EC }, - { 0x0213F0FE991840C4, 0x00003577, 0xFFFFE935, 0x00000533, 0x000016CD, 0xFFFFFB44, 0x00000289, 0x000016CD, 0xFFFFFB44, 0x00000289 }, - { 0x0213F0FE99282184, 0x00002875, 0xFFFFF170, 0x000003F3, 0x00001567, 0xFFFFFBD5, 0x00000289, 0x00001567, 0xFFFFFBD5, 0x00000289 }, - { 0x0213F0FE99084084, 0x00003AE2, 0xFFFFE538, 0x000005C1, 0x00001CB4, 0xFFFFF6A3, 0x0000033C, 0x00001CB4, 0xFFFFF6A3, 0x0000033C }, - { 0x0213F0FE990C38E4, 0x000031DF, 0xFFFFEC2A, 0x000004A3, 0x00001EF0, 0xFFFFF626, 0x00000352, 0x00001EF0, 0xFFFFF626, 0x00000352 }, - { 0x0213F0FD42D25144, 0x00004A6A, 0xFFFFDB15, 0x00000758, 0x000027F3, 0xFFFFEEEE, 0x00000479, 0x000027F3, 0xFFFFEEEE, 0x00000479 }, - { 0x0213EA94DE063904, 0x00002BB9, 0xFFFFEF5D, 0x00000433, 0x00001589, 0xFFFFFB57, 0x00000295, 0x00001589, 0xFFFFFB57, 0x00000295 }, - { 0x0213F0FE99042164, 0x000033A0, 0xFFFFE98F, 0x00000528, 0x00001CB4, 0xFFFFF706, 0x0000032D, 0x00001CB4, 0xFFFFF706, 0x0000032D }, - { 0x0213F0FE99163064, 0x0000248E, 0xFFFFF380, 0x000003AC, 0x000016EA, 0xFFFFFA6C, 0x000002CE, 0x000016EA, 0xFFFFFA6C, 0x000002CE }, - { 0x0213F0FE990221A4, 0x00002FE2, 0xFFFFEB2F, 0x000004E9, 0x00001D4E, 0xFFFFF56B, 0x00000380, 0x00001D4E, 0xFFFFF56B, 0x00000380 }, - { 0x0213F0FE990A2884, 0x00003283, 0xFFFFE9E7, 0x0000051D, 0x00000694, 0xFFFFFD32, 0x000003C3, 0x00000694, 0xFFFFFD32, 0x000003C3 }, - { 0x0213F0FD42D850C4, 0x00002EE4, 0xFFFFEBFD, 0x000004D3, 0x0000151A, 0xFFFFFAF6, 0x000002A4, 0x0000151A, 0xFFFFFAF6, 0x000002A4 }, - { 0x0213F0FD42DC18E4, 0x0000302D, 0xFFFFEB7F, 0x000004DA, 0x00001E6D, 0xFFFFF54B, 0x00000380, 0x00001E6D, 0xFFFFF54B, 0x00000380 }, - { 0x0213F0FD42DA50C4, 0x000033DA, 0xFFFFE7FB, 0x0000057F, 0x00001DED, 0xFFFFF50E, 0x0000038D, 0x00001DED, 0xFFFFF50E, 0x0000038D }, - { 0x0213F0FE992C4084, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001C3F, 0xFFFFF726, 0x0000032A, 0x00001C3F, 0xFFFFF726, 0x0000032A }, - { 0x0213F0FE990831C4, 0x00003BBD, 0xFFFFE55C, 0x000005B8, 0x000019DB, 0xFFFFF8BB, 0x000002EF, 0x000019DB, 0xFFFFF8BB, 0x000002EF }, - { 0x0213F0FE990E3884, 0x00002964, 0xFFFFF051, 0x0000040E, 0x000025CD, 0xFFFFF11B, 0x0000041F, 0x000025CD, 0xFFFFF11B, 0x0000041F }, - { 0x0213F0FD42DC4884, 0x000033F5, 0xFFFFE863, 0x00000560, 0x00001BCE, 0xFFFFF689, 0x0000034B, 0x00001BCE, 0xFFFFF689, 0x0000034B }, - { 0x0213F0FE990A2864, 0x00003294, 0xFFFFE924, 0x00000548, 0x00001D41, 0xFFFFF580, 0x0000037D, 0x00001D41, 0xFFFFF580, 0x0000037D }, - { 0x0213F0FD42DC39A4, 0x000034FB, 0xFFFFE7FE, 0x0000056D, 0x00001CB1, 0xFFFFF635, 0x00000357, 0x00001CB1, 0xFFFFF635, 0x00000357 }, - { 0x0213F0FE990A10A4, 0x00002E28, 0xFFFFEBB9, 0x000004E0, 0x00001B20, 0xFFFFF6E3, 0x0000033C, 0x00001B20, 0xFFFFF6E3, 0x0000033C }, - { 0x0213F0FD42DA1904, 0x00002799, 0xFFFFF0F4, 0x000003FC, 0x00001C9D, 0xFFFFF6A1, 0x00000345, 0x00001C9D, 0xFFFFF6A1, 0x00000345 }, - { 0x0213F0FE99064104, 0x00003AEA, 0xFFFFE5DB, 0x0000059D, 0x00001B61, 0xFFFFF7F0, 0x00000301, 0x00001B61, 0xFFFFF7F0, 0x00000301 }, - { 0x0213EA94DE041984, 0x000031F6, 0xFFFFEAB8, 0x000004F3, 0x00001D90, 0xFFFFF622, 0x00000359, 0x00001D90, 0xFFFFF622, 0x00000359 }, - { 0x0213F0FE990C4064, 0x000031B8, 0xFFFFEA61, 0x0000050F, 0x0000199D, 0xFFFFF87C, 0x000002FD, 0x0000199D, 0xFFFFF87C, 0x000002FD }, - { 0x0213F0FD42D23144, 0x00004514, 0xFFFFDDFF, 0x000006F6, 0x000022CD, 0xFFFFF29F, 0x000003D9, 0x000022CD, 0xFFFFF29F, 0x000003D9 }, - { 0x0213EA94DE043164, 0x00002F30, 0xFFFFECB8, 0x000004A0, 0x00001B07, 0xFFFFF7E2, 0x00000313, 0x00001B07, 0xFFFFF7E2, 0x00000313 }, - { 0x0213F0FD42DC30A4, 0x0000383B, 0xFFFFE702, 0x00000581, 0x00001A08, 0xFFFFF8CA, 0x000002E2, 0x00001A08, 0xFFFFF8CA, 0x000002E2 }, - { 0x0213F0FE99022164, 0x00002CC5, 0xFFFFEDF8, 0x00000465, 0x00001F47, 0xFFFFF4B2, 0x00000393, 0x00001F47, 0xFFFFF4B2, 0x00000393 }, - { 0x0213F0FE991621C4, 0x00002304, 0xFFFFF453, 0x00000384, 0x0000170A, 0xFFFFFA3F, 0x000002CE, 0x0000170A, 0xFFFFFA3F, 0x000002CE }, - { 0x0213F0FE990A5124, 0x0000337E, 0xFFFFE850, 0x0000056E, 0x00001BDD, 0xFFFFF668, 0x00000353, 0x00001BDD, 0xFFFFF668, 0x00000353 }, - { 0x0213F0FE990E4924, 0x00002E2F, 0xFFFFEC9B, 0x000004AE, 0x00001C4D, 0xFFFFF6D3, 0x00000338, 0x00001C4D, 0xFFFFF6D3, 0x00000338 }, - { 0x0213EA94DE061124, 0x00002DDD, 0xFFFFEDA4, 0x00000477, 0x00002010, 0xFFFFF4BB, 0x00000390, 0x00002010, 0xFFFFF4BB, 0x00000390 }, - { 0x0213F0FD42DA48E4, 0x0000290C, 0xFFFFEF61, 0x00000445, 0x00002133, 0xFFFFF324, 0x000003D8, 0x00002133, 0xFFFFF324, 0x000003D8 }, - { 0x0213F0FE99062924, 0x0000371E, 0xFFFFE8D5, 0x00000524, 0x00001C3A, 0xFFFFF7AE, 0x00000314, 0x00001C3A, 0xFFFFF7AE, 0x00000314 }, - { 0x0213F0FD42D838E4, 0x00002A58, 0xFFFFF007, 0x00000429, 0x000018A6, 0xFFFFF98F, 0x000002E1, 0x000018A6, 0xFFFFF98F, 0x000002E1 }, - { 0x0213F0FE99023084, 0x00002FED, 0xFFFFEC48, 0x000004AA, 0x00001E9D, 0xFFFFF584, 0x00000370, 0x00001E9D, 0xFFFFF584, 0x00000370 }, - { 0x0213F0FE99181884, 0x00002829, 0xFFFFF15F, 0x000003F7, 0x0000157E, 0xFFFFFBD4, 0x00000282, 0x0000157E, 0xFFFFFBD4, 0x00000282 }, - { 0x0213F0FE99101924, 0x000030CF, 0xFFFFEB8D, 0x000004CE, 0x00001A4C, 0xFFFFF868, 0x000002F7, 0x00001A4C, 0xFFFFF868, 0x000002F7 }, - { 0x0213F0FD42DA2084, 0x00002C8F, 0xFFFFEDD2, 0x0000047D, 0x00001CCE, 0xFFFFF6A1, 0x00000343, 0x00001CCE, 0xFFFFF6A1, 0x00000343 }, - { 0x0213F0FE99182164, 0x00002A84, 0xFFFFEFBA, 0x0000043E, 0x000015EF, 0xFFFFFB4B, 0x0000029E, 0x000015EF, 0xFFFFFB4B, 0x0000029E }, - { 0x0213F0FE990C28A4, 0x000034CA, 0xFFFFEA08, 0x000004FF, 0x00001C19, 0xFFFFF7ED, 0x00000309, 0x00001C19, 0xFFFFF7ED, 0x00000309 }, - { 0x0213F0FE991639A4, 0x00002187, 0xFFFFF4B0, 0x0000037E, 0x0000154A, 0xFFFFFB0C, 0x000002AE, 0x0000154A, 0xFFFFFB0C, 0x000002AE }, - { 0x0213F0FD42DA3844, 0x00002F4F, 0xFFFFEB3C, 0x000004F8, 0x0000181F, 0xFFFFF92D, 0x000002DF, 0x0000181F, 0xFFFFF92D, 0x000002DF }, - { 0x0213F0FE990410E4, 0x0000290C, 0xFFFFF0B1, 0x000003FC, 0x00001DB0, 0xFFFFF636, 0x00000355, 0x00001DB0, 0xFFFFF636, 0x00000355 }, - { 0x0213F0FE990A1064, 0x000034C1, 0xFFFFE888, 0x0000055A, 0x000019BF, 0xFFFFF881, 0x000002FB, 0x000019BF, 0xFFFFF881, 0x000002FB }, - { 0x0213F0FD42DC18C4, 0x00003139, 0xFFFFEA98, 0x00000504, 0x000019F2, 0xFFFFF820, 0x0000030B, 0x000019F2, 0xFFFFF820, 0x0000030B }, - { 0x0213F0FD42D83144, 0x00002CAC, 0xFFFFEEB2, 0x00000458, 0x0000152C, 0xFFFFFBEF, 0x0000027B, 0x0000152C, 0xFFFFFBEF, 0x0000027B }, - { 0x0213F0FE992C38E4, 0x00003577, 0xFFFFE99C, 0x0000050D, 0x00001E64, 0xFFFFF679, 0x0000033F, 0x00001E64, 0xFFFFF679, 0x0000033F }, - { 0x0213F0FD42DA4104, 0x0000263A, 0xFFFFF1E4, 0x000003D4, 0x00001F68, 0xFFFFF4ED, 0x00000386, 0x00001F68, 0xFFFFF4ED, 0x00000386 }, - { 0x0213F0FD42D81984, 0x00002CE9, 0xFFFFED63, 0x00000497, 0x00001810, 0xFFFFF94D, 0x000002E3, 0x00001810, 0xFFFFF94D, 0x000002E3 }, - { 0x0213EA94DE044104, 0x0000318A, 0xFFFFEAC8, 0x000004F5, 0x0000195C, 0xFFFFF896, 0x000002FB, 0x0000195C, 0xFFFFF896, 0x000002FB }, - { 0x0213F0FD42D83904, 0x00002C41, 0xFFFFEEC6, 0x0000045D, 0x000017DD, 0xFFFFFA16, 0x000002CB, 0x000017DD, 0xFFFFFA16, 0x000002CB }, - { 0x0213F0FE990231A4, 0x00002DD4, 0xFFFFEC98, 0x000004AD, 0x00001BD7, 0xFFFFF69F, 0x00000347, 0x00001BD7, 0xFFFFF69F, 0x00000347 }, - { 0x0213F0FD42DA3944, 0x00003351, 0xFFFFE9B2, 0x0000051A, 0x00001CA1, 0xFFFFF6A4, 0x00000341, 0x00001CA1, 0xFFFFF6A4, 0x00000341 }, - { 0x0213F0FE99021104, 0x0000322D, 0xFFFFE9BE, 0x00000527, 0x00001CF9, 0xFFFFF5EB, 0x00000366, 0x00001CF9, 0xFFFFF5EB, 0x00000366 }, - { 0x0213F0FE990C28C4, 0x00003678, 0xFFFFE9A8, 0x00000503, 0x00001AD4, 0xFFFFF8F6, 0x000002E3, 0x00001AD4, 0xFFFFF8F6, 0x000002E3 }, - { 0x0213F0FE99161924, 0x0000260E, 0xFFFFF2C1, 0x000003CA, 0x00001139, 0xFFFFFE48, 0x00000236, 0x00001139, 0xFFFFFE48, 0x00000236 }, - { 0x0213F0FE990A2164, 0x000033D3, 0xFFFFE872, 0x00000565, 0x00001B72, 0xFFFFF713, 0x00000332, 0x00001B72, 0xFFFFF713, 0x00000332 }, - { 0x0213F0FE99323844, 0x0000309B, 0xFFFFEB42, 0x000004E4, 0x00001918, 0xFFFFF8C8, 0x000002F2, 0x00001918, 0xFFFFF8C8, 0x000002F2 }, - { 0x0213F0FE99182864, 0x000028B8, 0xFFFFF105, 0x00000402, 0x000018BB, 0xFFFFF9BC, 0x000002D3, 0x000018BB, 0xFFFFF9BC, 0x000002D3 }, - { 0x0213F0FE990A1884, 0x00003123, 0xFFFFE9D1, 0x00000534, 0x00001B19, 0xFFFFF6FE, 0x0000033C, 0x00001B19, 0xFFFFF6FE, 0x0000033C }, - { 0x0213F0FE99022144, 0x00003216, 0xFFFFEA8E, 0x000004F6, 0x00001F72, 0xFFFFF4CE, 0x0000038B, 0x00001F72, 0xFFFFF4CE, 0x0000038B }, - { 0x0213F0FE99162964, 0x00002564, 0xFFFFF32D, 0x000003B6, 0x00001685, 0xFFFFFADB, 0x000002BB, 0x00001685, 0xFFFFFADB, 0x000002BB }, - { 0x0213F0FD42DA2924, 0x00002E60, 0xFFFFED13, 0x00000497, 0x00001CA5, 0xFFFFF6B9, 0x00000346, 0x00001CA5, 0xFFFFF6B9, 0x00000346 }, - { 0x0213F0FE990E39A4, 0x0000336D, 0xFFFFE934, 0x0000053B, 0x00001B3E, 0xFFFFF763, 0x00000327, 0x00001B3E, 0xFFFFF763, 0x00000327 }, - { 0x0213F0FE99101084, 0x0000274A, 0xFFFFF119, 0x000003FA, 0x00001D75, 0xFFFFF5CD, 0x0000036F, 0x00001D75, 0xFFFFF5CD, 0x0000036F }, - { 0x0213F0FD42DA2164, 0x0000366B, 0xFFFFE70A, 0x0000059A, 0x00001ED8, 0xFFFFF501, 0x00000389, 0x00001ED8, 0xFFFFF501, 0x00000389 }, - { 0x0213F0FE99223964, 0x00003164, 0xFFFFEAB4, 0x000004FA, 0x00001C52, 0xFFFFF6E0, 0x00000336, 0x00001C52, 0xFFFFF6E0, 0x00000336 }, - { 0x0213F0FD42D23064, 0x00004224, 0xFFFFDF7F, 0x000006C1, 0x00002A52, 0xFFFFED5E, 0x000004BB, 0x00002A52, 0xFFFFED5E, 0x000004BB }, - { 0x0213F0FE99102864, 0x000030E3, 0xFFFFEB07, 0x000004ED, 0x00001FD3, 0xFFFFF46D, 0x000003A1, 0x00001FD3, 0xFFFFF46D, 0x000003A1 }, - { 0x0213F0FD42D82884, 0x00002AEB, 0xFFFFEF1B, 0x00000454, 0x00001829, 0xFFFFF995, 0x000002DD, 0x00001829, 0xFFFFF995, 0x000002DD }, - { 0x0213F0FD42DC50E4, 0x0000346B, 0xFFFFE7A2, 0x0000058B, 0x000020C5, 0xFFFFF2E8, 0x000003EC, 0x000020C5, 0xFFFFF2E8, 0x000003EC }, - { 0x0213F0FD42DC4164, 0x000039CF, 0xFFFFE5D7, 0x000005A9, 0x00001D66, 0xFFFFF5D6, 0x00000366, 0x00001D66, 0xFFFFF5D6, 0x00000366 }, - { 0x0213F0FE990418E4, 0x000034AC, 0xFFFFE9AE, 0x00000515, 0x00001A28, 0xFFFFF904, 0x000002DC, 0x00001A28, 0xFFFFF904, 0x000002DC }, - { 0x0213F0FD42DC2084, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001C6F, 0xFFFFF686, 0x0000034C, 0x00001C6F, 0xFFFFF686, 0x0000034C }, - { 0x0213F0FE990820C4, 0x0000328B, 0xFFFFEBA1, 0x000004B4, 0x00001DA3, 0xFFFFF683, 0x00000349, 0x00001DA3, 0xFFFFF683, 0x00000349 }, - { 0x0213F0FE991828C4, 0x000027DC, 0xFFFFF295, 0x000003BF, 0x000019C1, 0xFFFFF98E, 0x000002E8, 0x000019C1, 0xFFFFF98E, 0x000002E8 }, - { 0x0213F0FE99184084, 0x00002756, 0xFFFFF1D7, 0x000003DF, 0x000015D9, 0xFFFFFB51, 0x00000298, 0x000015D9, 0xFFFFFB51, 0x00000298 }, - { 0x0213F0FE99083884, 0x00003526, 0xFFFFE907, 0x00000526, 0x000017AB, 0xFFFFFA12, 0x000002AB, 0x000017AB, 0xFFFFFA12, 0x000002AB }, - { 0x0213F0FD42DA18E4, 0x0000351B, 0xFFFFE8B7, 0x00000540, 0x00001A86, 0xFFFFF821, 0x00000303, 0x00001A86, 0xFFFFF821, 0x00000303 }, - { 0x0213F0FE99164144, 0x000024B2, 0xFFFFF34E, 0x000003B1, 0x000018E2, 0xFFFFF926, 0x000002FC, 0x000018E2, 0xFFFFF926, 0x000002FC }, - { 0x0213F0FD42D828A4, 0x00002F36, 0xFFFFED5D, 0x00000486, 0x0000157A, 0xFFFFFB85, 0x00000293, 0x0000157A, 0xFFFFFB85, 0x00000293 }, - { 0x0213F0FD42DC50C4, 0x00003A6E, 0xFFFFE456, 0x000005FD, 0x00001F68, 0xFFFFF3D1, 0x000003C3, 0x00001F68, 0xFFFFF3D1, 0x000003C3 }, - { 0x0213F0FE990A31A4, 0x00002BC3, 0xFFFFED2D, 0x000004A7, 0x00001C3F, 0xFFFFF609, 0x00000364, 0x00001C3F, 0xFFFFF609, 0x00000364 }, - { 0x0213F0FE990E2084, 0x000032E1, 0xFFFFEA83, 0x000004F6, 0x00001B37, 0xFFFFF842, 0x000002F5, 0x00001B37, 0xFFFFF842, 0x000002F5 }, - { 0x0213F0FD42D83184, 0x000028E3, 0xFFFFF07F, 0x00000412, 0x00001676, 0xFFFFFA68, 0x000002BE, 0x00001676, 0xFFFFFA68, 0x000002BE }, - { 0x0213F0FD42D21104, 0x0000444C, 0xFFFFDDAD, 0x00000712, 0x00002634, 0xFFFFEF89, 0x0000046C, 0x00002634, 0xFFFFEF89, 0x0000046C }, - { 0x0213F0FE990418C4, 0x00003121, 0xFFFFEBBB, 0x000004C6, 0x00001C98, 0xFFFFF72B, 0x0000032D, 0x00001C98, 0xFFFFF72B, 0x0000032D }, - { 0x0213F0FD42D840A4, 0x00002C31, 0xFFFFEDC4, 0x00000490, 0x0000162D, 0xFFFFFA8E, 0x000002B4, 0x0000162D, 0xFFFFFA8E, 0x000002B4 }, - { 0x0213F0FD42DA18C4, 0x00002749, 0xFFFFF112, 0x000003FC, 0x00001C85, 0xFFFFF6B8, 0x00000342, 0x00001C85, 0xFFFFF6B8, 0x00000342 }, - { 0x0213F0FE99044104, 0x00003159, 0xFFFFEB99, 0x000004C2, 0x00001BD0, 0xFFFFF7CA, 0x00000307, 0x00001BD0, 0xFFFFF7CA, 0x00000307 }, - { 0x0213F0FE99164164, 0x00002610, 0xFFFFF1FD, 0x000003EC, 0x000016BE, 0xFFFFFA53, 0x000002CB, 0x000016BE, 0xFFFFFA53, 0x000002CB }, - { 0x0213F0FE99023184, 0x000037B5, 0xFFFFE63D, 0x000005B5, 0x00002285, 0xFFFFF25D, 0x000003F7, 0x00002285, 0xFFFFF25D, 0x000003F7 }, - { 0x0213F0FE990A28A4, 0x00002FEE, 0xFFFFEB47, 0x000004EF, 0x00001CBE, 0xFFFFF64E, 0x00000358, 0x00001CBE, 0xFFFFF64E, 0x00000358 }, - { 0x0213F0FE99105104, 0x00002E90, 0xFFFFEC48, 0x000004C0, 0x00001A47, 0xFFFFF7D1, 0x0000031A, 0x00001A47, 0xFFFFF7D1, 0x0000031A }, - { 0x0213F0FD42DA4084, 0x000034AB, 0xFFFFE84A, 0x00000559, 0x00001A72, 0xFFFFF79A, 0x0000031C, 0x00001A72, 0xFFFFF79A, 0x0000031C }, - { 0x0213F0FE99183884, 0x00002F7B, 0xFFFFECFC, 0x0000049C, 0x00001814, 0xFFFFFA22, 0x000002C2, 0x00001814, 0xFFFFFA22, 0x000002C2 }, - { 0x0213F0FE99021964, 0x00003618, 0xFFFFE709, 0x00000596, 0x00001EBF, 0xFFFFF482, 0x000003A5, 0x00001EBF, 0xFFFFF482, 0x000003A5 }, - { 0x0213EA94DE024904, 0x0000341B, 0xFFFFE8B2, 0x0000054F, 0x00001D26, 0xFFFFF578, 0x00000388, 0x00001D26, 0xFFFFF578, 0x00000388 }, - { 0x0213F0FE99102144, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x000019C0, 0xFFFFF8CC, 0x000002E6, 0x000019C0, 0xFFFFF8CC, 0x000002E6 }, - { 0x0213F0FE992841A4, 0x00002B76, 0xFFFFEF6C, 0x00000444, 0x00001563, 0xFFFFFBBE, 0x0000028D, 0x00001563, 0xFFFFFBBE, 0x0000028D }, - { 0x0213F0FD42D81864, 0x00002BA2, 0xFFFFEE31, 0x0000047F, 0x00001A3D, 0xFFFFF7F3, 0x00000320, 0x00001A3D, 0xFFFFF7F3, 0x00000320 }, - { 0x0213F0FE992C48E4, 0x00003545, 0xFFFFE87A, 0x0000054A, 0x00001B5A, 0xFFFFF7B0, 0x0000030C, 0x00001B5A, 0xFFFFF7B0, 0x0000030C }, - { 0x0213EA94DE042944, 0x00003879, 0xFFFFE73F, 0x00000578, 0x00001649, 0xFFFFFB57, 0x00000283, 0x00001649, 0xFFFFFB57, 0x00000283 }, - { 0x0213F0FD42D840C4, 0x00002772, 0xFFFFF0F1, 0x00000410, 0x0000142F, 0xFFFFFBCF, 0x00000287, 0x0000142F, 0xFFFFFBCF, 0x00000287 }, - { 0x0213F0FD42DA3184, 0x00003228, 0xFFFFE98E, 0x00000535, 0x00001F48, 0xFFFFF495, 0x00000399, 0x00001F48, 0xFFFFF495, 0x00000399 }, - { 0x0213F0FE990E40E4, 0x00002887, 0xFFFFF119, 0x000003E8, 0x000021AA, 0xFFFFF3F5, 0x000003A5, 0x000021AA, 0xFFFFF3F5, 0x000003A5 }, - { 0x0213F0FD42DA28A4, 0x0000301F, 0xFFFFEBB2, 0x000004D2, 0x00001C02, 0xFFFFF736, 0x0000032B, 0x00001C02, 0xFFFFF736, 0x0000032B }, - { 0x0213F0FE991820A4, 0x00002E13, 0xFFFFEE3F, 0x00000468, 0x000016AC, 0xFFFFFB32, 0x0000029E, 0x000016AC, 0xFFFFFB32, 0x0000029E }, - { 0x0213F0FE99044924, 0x00003478, 0xFFFFE8F9, 0x00000538, 0x00001DAB, 0xFFFFF645, 0x00000345, 0x00001DAB, 0xFFFFF645, 0x00000345 }, - { 0x0213F0FE990608C4, 0x000030C6, 0xFFFFEB6C, 0x000004D4, 0x0000184A, 0xFFFFF934, 0x000002E1, 0x0000184A, 0xFFFFF934, 0x000002E1 }, - { 0x0213F0FE990A2044, 0x00002F1B, 0xFFFFEBD3, 0x000004D3, 0x000019E7, 0xFFFFF813, 0x0000030D, 0x000019E7, 0xFFFFF813, 0x0000030D }, - { 0x0213F0FE99023904, 0x00003214, 0xFFFFEAE9, 0x000004E0, 0x0000178F, 0xFFFFFA1C, 0x000002B1, 0x0000178F, 0xFFFFFA1C, 0x000002B1 }, - { 0x0213F0FD42DC3144, 0x0000399C, 0xFFFFE738, 0x0000055E, 0x00001EA1, 0xFFFFF5E7, 0x0000035A, 0x00001EA1, 0xFFFFF5E7, 0x0000035A }, - { 0x0213F0FE990650C4, 0x00003A01, 0xFFFFE5B2, 0x000005B6, 0x00001D95, 0xFFFFF5D2, 0x0000036A, 0x00001D95, 0xFFFFF5D2, 0x0000036A }, - { 0x0213F0FE99043884, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001C06, 0xFFFFF76E, 0x0000031A, 0x00001C06, 0xFFFFF76E, 0x0000031A }, - { 0x0213F0FE99063864, 0x00003CD1, 0xFFFFE42F, 0x000005EB, 0x00001933, 0xFFFFF91F, 0x000002D4, 0x00001933, 0xFFFFF91F, 0x000002D4 }, - { 0x0213F0FD42DA3164, 0x00003119, 0xFFFFEB1B, 0x000004E1, 0x00001FC7, 0xFFFFF46A, 0x000003A2, 0x00001FC7, 0xFFFFF46A, 0x000003A2 }, - { 0x0213EA94DE0648A4, 0x0000390D, 0xFFFFE566, 0x000005D8, 0x00001EC6, 0xFFFFF4DC, 0x00000391, 0x00001EC6, 0xFFFFF4DC, 0x00000391 }, - { 0x0213F0FD42DA10C4, 0x00003446, 0xFFFFE858, 0x00000561, 0x00001FDB, 0xFFFFF3FF, 0x000003B9, 0x00001FDB, 0xFFFFF3FF, 0x000003B9 }, - { 0x0213F0FE99044904, 0x000032BA, 0xFFFFEA07, 0x00000511, 0x00001B25, 0xFFFFF7C9, 0x0000030D, 0x00001B25, 0xFFFFF7C9, 0x0000030D }, - { 0x0213F0FE990E1864, 0x00002CCF, 0xFFFFEDE5, 0x00000478, 0x00001BC8, 0xFFFFF761, 0x00000326, 0x00001BC8, 0xFFFFF761, 0x00000326 }, - { 0x0213F0FE99062984, 0x0000400E, 0xFFFFE1CB, 0x00000652, 0x00001AF8, 0xFFFFF7B9, 0x00000312, 0x00001AF8, 0xFFFFF7B9, 0x00000312 }, - { 0x0213F0FE990408E4, 0x00002F24, 0xFFFFEC2A, 0x000004C7, 0x00001B94, 0xFFFFF748, 0x00000333, 0x00001B94, 0xFFFFF748, 0x00000333 }, - { 0x0213F0FD42D21924, 0x00003FDA, 0xFFFFE1C1, 0x0000064B, 0x00002427, 0xFFFFF180, 0x0000040C, 0x00002427, 0xFFFFF180, 0x0000040C }, - { 0x0213F0FE990A18C4, 0x00002F6B, 0xFFFFEBA7, 0x000004DD, 0x00001C25, 0xFFFFF6C1, 0x00000344, 0x00001C25, 0xFFFFF6C1, 0x00000344 }, - { 0x0213F0FE99182104, 0x00002A53, 0xFFFFF0EE, 0x00000402, 0x000017C6, 0xFFFFFAA0, 0x000002BF, 0x000017C6, 0xFFFFFAA0, 0x000002BF }, - { 0x0213F0FE99105144, 0x000031F4, 0xFFFFEA34, 0x00000517, 0x000016FF, 0xFFFFFA4E, 0x000002AC, 0x000016FF, 0xFFFFFA4E, 0x000002AC }, - { 0x0213F0FE99322144, 0x00002E24, 0xFFFFED46, 0x00000489, 0x00001712, 0xFFFFFA5D, 0x000002AC, 0x00001712, 0xFFFFFA5D, 0x000002AC }, - { 0x0213F0FE99182824, 0x000028CD, 0xFFFFF0E3, 0x0000040E, 0x00001606, 0xFFFFFB37, 0x000002A4, 0x00001606, 0xFFFFFB37, 0x000002A4 }, - { 0x0213F0FE990220C4, 0x00003184, 0xFFFFEB88, 0x000004C3, 0x000018DA, 0xFFFFF939, 0x000002DB, 0x000018DA, 0xFFFFF939, 0x000002DB }, - { 0x0213F0FE99162124, 0x0000239B, 0xFFFFF470, 0x00000386, 0x00001714, 0xFFFFFA9F, 0x000002C8, 0x00001714, 0xFFFFFA9F, 0x000002C8 }, - { 0x0213F0FD42DC38E4, 0x00003641, 0xFFFFE92B, 0x00000515, 0x00001BE2, 0xFFFFF795, 0x0000031B, 0x00001BE2, 0xFFFFF795, 0x0000031B }, - { 0x0213F0FE992C1144, 0x00003278, 0xFFFFEA17, 0x00000510, 0x00001B71, 0xFFFFF778, 0x0000031D, 0x00001B71, 0xFFFFF778, 0x0000031D }, - { 0x0213F0FE99062844, 0x000035B9, 0xFFFFE8DA, 0x0000052D, 0x00001A6A, 0xFFFFF83B, 0x000002FF, 0x00001A6A, 0xFFFFF83B, 0x000002FF }, - { 0x0213F0FE990E18C4, 0x00002E5E, 0xFFFFED32, 0x0000048B, 0x00001E7D, 0xFFFFF60E, 0x0000034E, 0x00001E7D, 0xFFFFF60E, 0x0000034E }, - { 0x0213F0FE991019A4, 0x00003178, 0xFFFFEA52, 0x00000513, 0x00001AD0, 0xFFFFF793, 0x0000031F, 0x00001AD0, 0xFFFFF793, 0x0000031F }, - { 0x0213F0FD42D44104, 0x00003A2C, 0xFFFFE346, 0x00000641, 0x000023D0, 0xFFFFF0CE, 0x00000433, 0x000023D0, 0xFFFFF0CE, 0x00000433 }, - { 0x0213F0FD42D818C4, 0x000028FD, 0xFFFFF02A, 0x0000042B, 0x0000152B, 0xFFFFFB90, 0x00000289, 0x0000152B, 0xFFFFFB90, 0x00000289 }, - { 0x0213F0FE990E3084, 0x000030DE, 0xFFFFEBDF, 0x000004BE, 0x00001CDC, 0xFFFFF747, 0x0000031C, 0x00001CDC, 0xFFFFF747, 0x0000031C }, - { 0x0213F0FE99021944, 0x000036CB, 0xFFFFE6EE, 0x00000596, 0x00002096, 0xFFFFF3C2, 0x000003BB, 0x00002096, 0xFFFFF3C2, 0x000003BB }, - { 0x0213F0FE990C48C4, 0x00003172, 0xFFFFEAC1, 0x000004F4, 0x00001C87, 0xFFFFF6CD, 0x00000337, 0x00001C87, 0xFFFFF6CD, 0x00000337 }, - { 0x0213F0FD42D24864, 0x00004A18, 0xFFFFDB34, 0x00000758, 0x0000213C, 0xFFFFF3A2, 0x000003AC, 0x0000213C, 0xFFFFF3A2, 0x000003AC }, - { 0x0213F0FE99022104, 0x000031F3, 0xFFFFEB73, 0x000004C6, 0x00001B23, 0xFFFFF7CB, 0x0000031A, 0x00001B23, 0xFFFFF7CB, 0x0000031A }, - { 0x0213F0FE990A2924, 0x000031C0, 0xFFFFEABA, 0x000004F7, 0x00001A5A, 0xFFFFF845, 0x000002FF, 0x00001A5A, 0xFFFFF845, 0x000002FF }, - { 0x0213F0FE99104944, 0x00003B77, 0xFFFFE3B3, 0x00000623, 0x00001BCA, 0xFFFFF6F8, 0x00000333, 0x00001BCA, 0xFFFFF6F8, 0x00000333 }, - { 0x0213F0FE990A3944, 0x000035AF, 0xFFFFE76D, 0x00000588, 0x00001C16, 0xFFFFF6AB, 0x00000341, 0x00001C16, 0xFFFFF6AB, 0x00000341 }, - { 0x0213EA94DE0438C4, 0x000032AD, 0xFFFFEA8E, 0x000004F8, 0x00001A3A, 0xFFFFF832, 0x0000030E, 0x00001A3A, 0xFFFFF832, 0x0000030E }, - { 0x0213F0FE99104884, 0x00002E92, 0xFFFFEBD2, 0x000004DA, 0x00001E04, 0xFFFFF51E, 0x0000038A, 0x00001E04, 0xFFFFF51E, 0x0000038A }, - { 0x0213F0FD42D440A4, 0x00003E57, 0xFFFFE0F7, 0x0000068F, 0x000021F1, 0xFFFFF1C6, 0x00000411, 0x000021F1, 0xFFFFF1C6, 0x00000411 }, - { 0x0213F0FE990821A4, 0x00003598, 0xFFFFE8BB, 0x00000535, 0x00001B62, 0xFFFFF764, 0x00000326, 0x00001B62, 0xFFFFF764, 0x00000326 }, - { 0x0213F0FE990A3884, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x00001E8B, 0xFFFFF4AB, 0x0000039F, 0x00001E8B, 0xFFFFF4AB, 0x0000039F }, - { 0x0213EA94DE060904, 0x0000267E, 0xFFFFF1A7, 0x000003E1, 0x000021C1, 0xFFFFF2E9, 0x000003EA, 0x000021C1, 0xFFFFF2E9, 0x000003EA }, - { 0x0213EA94DE0239A4, 0x00002ED7, 0xFFFFEC88, 0x000004A6, 0x00001DEC, 0xFFFFF57C, 0x00000378, 0x00001DEC, 0xFFFFF57C, 0x00000378 }, - { 0x0213EA94DE0441A4, 0x00003365, 0xFFFFE946, 0x00000536, 0x000019E9, 0xFFFFF7E0, 0x0000031D, 0x000019E9, 0xFFFFF7E0, 0x0000031D }, - { 0x0213F0FE991818E4, 0x000029A4, 0xFFFFF0FD, 0x000003FE, 0x0000163F, 0xFFFFFB68, 0x00000299, 0x0000163F, 0xFFFFFB68, 0x00000299 }, - { 0x0213EA94DE021904, 0x0000348D, 0xFFFFE9F7, 0x00000509, 0x000017A0, 0xFFFFFA59, 0x000002B6, 0x000017A0, 0xFFFFFA59, 0x000002B6 }, - { 0x0213F0FE990610C4, 0x00003144, 0xFFFFEB23, 0x000004D9, 0x00001C9B, 0xFFFFF664, 0x00000351, 0x00001C9B, 0xFFFFF664, 0x00000351 }, - { 0x0213EA94DE0620E4, 0x00002E95, 0xFFFFEE1A, 0x00000463, 0x00001707, 0xFFFFFAB7, 0x000002B3, 0x00001707, 0xFFFFFAB7, 0x000002B3 }, - { 0x0213F0FD42D41864, 0x0000489C, 0xFFFFDA43, 0x000007AC, 0x00002866, 0xFFFFED6B, 0x000004D0, 0x00002866, 0xFFFFED6B, 0x000004D0 }, - { 0x0213F0FE99161844, 0x00002895, 0xFFFFF10A, 0x0000040A, 0x000013E9, 0xFFFFFC9F, 0x0000026E, 0x000013E9, 0xFFFFFC9F, 0x0000026E }, - { 0x0213F0FE99061964, 0x000033A0, 0xFFFFE9B1, 0x00000510, 0x00001D96, 0xFFFFF5AE, 0x0000036F, 0x00001D96, 0xFFFFF5AE, 0x0000036F }, - { 0x0213F0FE99083984, 0x0000327C, 0xFFFFEAEA, 0x000004DD, 0x00001D45, 0xFFFFF649, 0x00000356, 0x00001D45, 0xFFFFF649, 0x00000356 }, - { 0x0213EA94DE0248A4, 0x000031DF, 0xFFFFE9AB, 0x0000052F, 0x000019C8, 0xFFFFF7B7, 0x00000321, 0x000019C8, 0xFFFFF7B7, 0x00000321 }, - { 0x0213F0FE991640A4, 0x00002BCC, 0xFFFFEEF4, 0x0000045C, 0x000015CD, 0xFFFFFB58, 0x0000029E, 0x000015CD, 0xFFFFFB58, 0x0000029E }, - { 0x0213F0FE990638E4, 0x00003534, 0xFFFFEA10, 0x000004EB, 0x00001BB6, 0xFFFFF7B9, 0x00000314, 0x00001BB6, 0xFFFFF7B9, 0x00000314 }, - { 0x0213F0FE99041984, 0x00002F4F, 0xFFFFEC35, 0x000004B9, 0x0000205D, 0xFFFFF47F, 0x00000392, 0x0000205D, 0xFFFFF47F, 0x00000392 }, - { 0x0213F0FE990C20A4, 0x00003295, 0xFFFFEB1C, 0x000004D6, 0x000019C1, 0xFFFFF931, 0x000002D5, 0x000019C1, 0xFFFFF931, 0x000002D5 }, - { 0x0213F0FE99024144, 0x00003557, 0xFFFFE7F7, 0x00000568, 0x00002342, 0xFFFFF1F9, 0x00000405, 0x00002342, 0xFFFFF1F9, 0x00000405 }, - { 0x0213F0FE990450C4, 0x00003487, 0xFFFFE872, 0x0000055D, 0x000019D7, 0xFFFFF823, 0x0000030C, 0x000019D7, 0xFFFFF823, 0x0000030C }, - { 0x0213F0FE992C3944, 0x0000378F, 0xFFFFE7A6, 0x00000566, 0x00001875, 0xFFFFFA04, 0x000002AF, 0x00001875, 0xFFFFFA04, 0x000002AF }, - { 0x0213EA94DE0230E4, 0x00002A67, 0xFFFFF157, 0x000003DD, 0x000017BD, 0xFFFFFA53, 0x000002D1, 0x000017BD, 0xFFFFFA53, 0x000002D1 }, - { 0x0213F0FD42D220E4, 0x000030B5, 0xFFFFEB32, 0x000004D9, 0x00002129, 0xFFFFF38A, 0x000003BB, 0x00002129, 0xFFFFF38A, 0x000003BB }, - { 0x0213F0FE990610A4, 0x00003786, 0xFFFFE703, 0x00000584, 0x00001D63, 0xFFFFF5DC, 0x00000367, 0x00001D63, 0xFFFFF5DC, 0x00000367 }, - { 0x0213F0FD42DA20C4, 0x0000346A, 0xFFFFE93E, 0x0000052C, 0x00001B27, 0xFFFFF79D, 0x0000031F, 0x00001B27, 0xFFFFF79D, 0x0000031F }, - { 0x0213F0FE990E3024, 0x0000294E, 0xFFFFF0A5, 0x00000409, 0x00001928, 0xFFFFF93B, 0x000002E6, 0x00001928, 0xFFFFF93B, 0x000002E6 }, - { 0x0213F0FD42D410C4, 0x00003E09, 0xFFFFE0FF, 0x00000694, 0x000025A0, 0xFFFFEF0F, 0x0000048F, 0x000025A0, 0xFFFFEF0F, 0x0000048F }, - { 0x0213F0FE990A2964, 0x00003197, 0xFFFFEA06, 0x00000520, 0x00001B42, 0xFFFFF73B, 0x0000032A, 0x00001B42, 0xFFFFF73B, 0x0000032A }, - { 0x0213F0FE99161864, 0x000022CB, 0xFFFFF3FC, 0x000003A3, 0x00001449, 0xFFFFFBD0, 0x00000297, 0x00001449, 0xFFFFFBD0, 0x00000297 }, - { 0x0213F0FD42D82944, 0x00002A79, 0xFFFFEFD2, 0x00000433, 0x00001585, 0xFFFFFB92, 0x0000028E, 0x00001585, 0xFFFFFB92, 0x0000028E }, - { 0x0213F0FE990C4184, 0x00003249, 0xFFFFEA92, 0x000004F4, 0x000019CB, 0xFFFFF8CF, 0x000002E1, 0x000019CB, 0xFFFFF8CF, 0x000002E1 }, - { 0x0213EA94DE0218A4, 0x00002CEA, 0xFFFFEE46, 0x00000463, 0x00001A5E, 0xFFFFF83C, 0x0000030D, 0x00001A5E, 0xFFFFF83C, 0x0000030D }, - { 0x0213F0FD42DC5144, 0x00003AE2, 0xFFFFE422, 0x00000600, 0x00001C65, 0xFFFFF62F, 0x0000034B, 0x00001C65, 0xFFFFF62F, 0x0000034B }, - { 0x0213F0FE99181184, 0x000026A0, 0xFFFFF1C2, 0x000003F8, 0x000010E5, 0xFFFFFE56, 0x0000022A, 0x000010E5, 0xFFFFFE56, 0x0000022A }, - { 0x0213F0FE992829A4, 0x00002A7B, 0xFFFFF063, 0x00000417, 0x000016FC, 0xFFFFFAD7, 0x000002B1, 0x000016FC, 0xFFFFFAD7, 0x000002B1 }, - { 0x0213F0FE993210C4, 0x00003092, 0xFFFFEAB9, 0x00000507, 0x00001AE3, 0xFFFFF783, 0x00000323, 0x00001AE3, 0xFFFFF783, 0x00000323 }, - { 0x0213F0FE990438E4, 0x00003265, 0xFFFFEBE8, 0x000004AA, 0x00001D65, 0xFFFFF73F, 0x00000321, 0x00001D65, 0xFFFFF73F, 0x00000321 }, - { 0x0213EA94DE023084, 0x00002F14, 0xFFFFECC2, 0x000004A4, 0x00001A8D, 0xFFFFF7F3, 0x0000031D, 0x00001A8D, 0xFFFFF7F3, 0x0000031D }, - { 0x0213F0FD42DC10E4, 0x000035FB, 0xFFFFE6D3, 0x000005AC, 0x00001B19, 0xFFFFF712, 0x00000338, 0x00001B19, 0xFFFFF712, 0x00000338 }, - { 0x0213F0FD42DA2124, 0x00003519, 0xFFFFE8CC, 0x0000053A, 0x00001A0F, 0xFFFFF86E, 0x000002F5, 0x00001A0F, 0xFFFFF86E, 0x000002F5 }, - { 0x0213F0FE992C2144, 0x0000364C, 0xFFFFE879, 0x00000541, 0x00001A42, 0xFFFFF8BA, 0x000002E2, 0x00001A42, 0xFFFFF8BA, 0x000002E2 }, - { 0x0213EA94DE0218C4, 0x000029BA, 0xFFFFF09A, 0x00000408, 0x00001986, 0xFFFFF8D9, 0x000002FE, 0x00001986, 0xFFFFF8D9, 0x000002FE }, - { 0x0213F0FD42DA38E4, 0x00003507, 0xFFFFE961, 0x00000518, 0x00001B79, 0xFFFFF775, 0x00000325, 0x00001B79, 0xFFFFF775, 0x00000325 }, - { 0x0213F0FD42DC3184, 0x00003AD5, 0xFFFFE415, 0x00000613, 0x00001CB4, 0xFFFFF66D, 0x00000348, 0x00001CB4, 0xFFFFF66D, 0x00000348 }, - { 0x0213F0FE991640E4, 0x000023D1, 0xFFFFF42B, 0x0000038F, 0x00001546, 0xFFFFFBA0, 0x0000029F, 0x00001546, 0xFFFFFBA0, 0x0000029F }, - { 0x0213F0FE990A1924, 0x0000399E, 0xFFFFE518, 0x000005E7, 0x00001990, 0xFFFFF871, 0x000002FB, 0x00001990, 0xFFFFF871, 0x000002FB }, - { 0x0213F0FD42D82964, 0x00002EDE, 0xFFFFEC93, 0x000004B8, 0x0000152C, 0xFFFFFBB3, 0x0000027E, 0x0000152C, 0xFFFFFBB3, 0x0000027E }, - { 0x0213EA94DE042964, 0x00003140, 0xFFFFEBC9, 0x000004BB, 0x000016BE, 0xFFFFFB0A, 0x00000288, 0x000016BE, 0xFFFFFB0A, 0x00000288 }, - { 0x0213F0FE99064064, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x0000185D, 0xFFFFF95A, 0x000002D9, 0x0000185D, 0xFFFFF95A, 0x000002D9 }, - { 0x0213F0FE99023844, 0x0000389C, 0xFFFFE65A, 0x000005A2, 0x0000195D, 0xFFFFF8C8, 0x000002E8, 0x0000195D, 0xFFFFF8C8, 0x000002E8 }, - { 0x0213F0FE99042104, 0x0000362B, 0xFFFFE9EC, 0x000004F6, 0x00001605, 0xFFFFFC1C, 0x00000263, 0x00001605, 0xFFFFFC1C, 0x00000263 }, - { 0x0213F0FE992A1964, 0x00002946, 0xFFFFF04F, 0x00000426, 0x000015BA, 0xFFFFFB2F, 0x000002A3, 0x000015BA, 0xFFFFFB2F, 0x000002A3 }, - { 0x0213F0FE99082184, 0x0000368E, 0xFFFFE837, 0x0000054A, 0x000017D7, 0xFFFFF9EB, 0x000002BA, 0x000017D7, 0xFFFFF9EB, 0x000002BA }, - { 0x0213F0FD42DA2844, 0x00002E74, 0xFFFFEBE8, 0x000004DA, 0x00001DD6, 0xFFFFF57E, 0x00000379, 0x00001DD6, 0xFFFFF57E, 0x00000379 }, - { 0x0213F0FE99041944, 0x0000322D, 0xFFFFEAA8, 0x000004F5, 0x00001B55, 0xFFFFF7DD, 0x0000030B, 0x00001B55, 0xFFFFF7DD, 0x0000030B }, - { 0x0213F0FE99181904, 0x00002A29, 0xFFFFF07B, 0x00000416, 0x00001671, 0xFFFFFB3E, 0x0000029F, 0x00001671, 0xFFFFFB3E, 0x0000029F }, - { 0x0213F0FD42DA2104, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x00001815, 0xFFFFF9AE, 0x000002C9, 0x00001815, 0xFFFFF9AE, 0x000002C9 }, - { 0x0213F0FE990E10E4, 0x0000265F, 0xFFFFF1CB, 0x000003D5, 0x00001ED2, 0xFFFFF539, 0x0000037A, 0x00001ED2, 0xFFFFF539, 0x0000037A }, - { 0x0213F0FE99162184, 0x000027A8, 0xFFFFF10D, 0x00000413, 0x000014B5, 0xFFFFFBA1, 0x00000299, 0x000014B5, 0xFFFFFBA1, 0x00000299 }, - { 0x0213F0FE99043064, 0x00002CEE, 0xFFFFEDF6, 0x00000476, 0x00001A99, 0xFFFFF83E, 0x00000305, 0x00001A99, 0xFFFFF83E, 0x00000305 }, - { 0x0213F0FE990640C4, 0x0000346C, 0xFFFFEA17, 0x000004EF, 0x00001D38, 0xFFFFF69F, 0x0000033D, 0x00001D38, 0xFFFFF69F, 0x0000033D }, - { 0x0213F0FD42DA2944, 0x00002DBB, 0xFFFFED35, 0x00000490, 0x000018C1, 0xFFFFF930, 0x000002DA, 0x000018C1, 0xFFFFF930, 0x000002DA }, - { 0x0213F0FE99042924, 0x000038DF, 0xFFFFE8A7, 0x0000051E, 0x00001B59, 0xFFFFF915, 0x000002D3, 0x00001B59, 0xFFFFF915, 0x000002D3 }, - { 0x0213F0FE99080944, 0x00003384, 0xFFFFE979, 0x00000524, 0x00001AF3, 0xFFFFF74C, 0x0000032F, 0x00001AF3, 0xFFFFF74C, 0x0000032F }, - { 0x0213F0FE99181864, 0x0000258B, 0xFFFFF2AE, 0x000003CB, 0x0000190C, 0xFFFFF93E, 0x000002EF, 0x0000190C, 0xFFFFF93E, 0x000002EF }, - { 0x0213F0FE99103884, 0x000034F1, 0xFFFFE84B, 0x0000055E, 0x00001CB8, 0xFFFFF670, 0x0000034A, 0x00001CB8, 0xFFFFF670, 0x0000034A }, - { 0x0213F0FE990C2104, 0x000030FB, 0xFFFFECD2, 0x00000488, 0x00001BF4, 0xFFFFF821, 0x00000302, 0x00001BF4, 0xFFFFF821, 0x00000302 }, - { 0x0213F0FE99063044, 0x000036A6, 0xFFFFE815, 0x00000556, 0x000018FD, 0xFFFFF925, 0x000002DF, 0x000018FD, 0xFFFFF925, 0x000002DF }, - { 0x0213EA94DE023044, 0x0000302A, 0xFFFFEB79, 0x000004E0, 0x00001C11, 0xFFFFF694, 0x00000358, 0x00001C11, 0xFFFFF694, 0x00000358 }, - { 0x0213F0FE99181124, 0x00002555, 0xFFFFF2C4, 0x000003CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB }, - { 0x0213F0FE990A3164, 0x000032A3, 0xFFFFE933, 0x00000544, 0x000019D3, 0xFFFFF81A, 0x00000306, 0x000019D3, 0xFFFFF81A, 0x00000306 }, - { 0x0213F0FD42D85104, 0x00002B91, 0xFFFFED81, 0x000004A9, 0x0000158B, 0xFFFFFAB9, 0x000002AC, 0x0000158B, 0xFFFFFAB9, 0x000002AC }, - { 0x0213F0FE990E20C4, 0x00003537, 0xFFFFE912, 0x0000052C, 0x00001C8A, 0xFFFFF754, 0x0000031B, 0x00001C8A, 0xFFFFF754, 0x0000031B }, - { 0x0213EA94DE063184, 0x000032E1, 0xFFFFEA5A, 0x000004F9, 0x000017B4, 0xFFFFF9D9, 0x000002C2, 0x000017B4, 0xFFFFF9D9, 0x000002C2 }, - { 0x0213F0FD42D210C4, 0x00003B76, 0xFFFFE330, 0x00000636, 0x000026FB, 0xFFFFEF06, 0x00000481, 0x000026FB, 0xFFFFEF06, 0x00000481 }, - { 0x0213F0FE99042144, 0x0000320C, 0xFFFFEB84, 0x000004C3, 0x00001A3A, 0xFFFFF8E9, 0x000002DF, 0x00001A3A, 0xFFFFF8E9, 0x000002DF }, - { 0x0213F0FE99023984, 0x0000317D, 0xFFFFEA1F, 0x00000515, 0x00002100, 0xFFFFF31B, 0x000003DD, 0x00002100, 0xFFFFF31B, 0x000003DD }, - { 0x0213F0FD42D43164, 0x00003DCB, 0xFFFFE0B4, 0x000006B4, 0x00002160, 0xFFFFF269, 0x000003F0, 0x00002160, 0xFFFFF269, 0x000003F0 }, - { 0x0213F0FE991618C4, 0x00002737, 0xFFFFF218, 0x000003E1, 0x000015B5, 0xFFFFFB8F, 0x0000029C, 0x000015B5, 0xFFFFFB8F, 0x0000029C }, - { 0x0213EA94DE023184, 0x0000318F, 0xFFFFEB3F, 0x000004D8, 0x00001938, 0xFFFFF8E9, 0x000002EB, 0x00001938, 0xFFFFF8E9, 0x000002EB }, - { 0x0213F0FE991048C4, 0x000031BD, 0xFFFFE9DE, 0x00000527, 0x000018A7, 0xFFFFF8CA, 0x000002ED, 0x000018A7, 0xFFFFF8CA, 0x000002ED }, - { 0x0213F0FD42DA3884, 0x00002F77, 0xFFFFEC2F, 0x000004B4, 0x00001D25, 0xFFFFF61B, 0x0000035D, 0x00001D25, 0xFFFFF61B, 0x0000035D }, - { 0x0213F0FE990E4904, 0x00002CCA, 0xFFFFEDB3, 0x0000047C, 0x00001FBD, 0xFFFFF4A7, 0x00000391, 0x00001FBD, 0xFFFFF4A7, 0x00000391 }, - { 0x0213F0FD42D438A4, 0x00003FF6, 0xFFFFE058, 0x000006A2, 0x000024CD, 0xFFFFF026, 0x00000452, 0x000024CD, 0xFFFFF026, 0x00000452 }, - { 0x0213F0FE990A38E4, 0x00003161, 0xFFFFEAC8, 0x000004F3, 0x00001BB6, 0xFFFFF72A, 0x0000032B, 0x00001BB6, 0xFFFFF72A, 0x0000032B }, - { 0x0213F0FD42D838A4, 0x00002EA0, 0xFFFFECA6, 0x000004B7, 0x000018C2, 0xFFFFF94E, 0x000002E1, 0x000018C2, 0xFFFFF94E, 0x000002E1 }, - { 0x0213F0FE99182184, 0x00002F62, 0xFFFFEC9E, 0x000004B8, 0x00001531, 0xFFFFFBCD, 0x00000285, 0x00001531, 0xFFFFFBCD, 0x00000285 }, - { 0x0213F0FE990440A4, 0x00003013, 0xFFFFEBD6, 0x000004C2, 0x00001B01, 0xFFFFF802, 0x000002FF, 0x00001B01, 0xFFFFF802, 0x000002FF }, - { 0x0213F0FE99183064, 0x00002972, 0xFFFFF08D, 0x00000417, 0x00001A32, 0xFFFFF8A4, 0x00000305, 0x00001A32, 0xFFFFF8A4, 0x00000305 }, - { 0x0213F0FD42D820E4, 0x00002E95, 0xFFFFED94, 0x00000487, 0x00001529, 0xFFFFFC26, 0x00000271, 0x00001529, 0xFFFFFC26, 0x00000271 }, - { 0x0213F0FE990A1084, 0x00002D6A, 0xFFFFEC79, 0x000004C1, 0x00001AE2, 0xFFFFF725, 0x00000337, 0x00001AE2, 0xFFFFF725, 0x00000337 }, - { 0x0213F0FE99021884, 0x000036B4, 0xFFFFE704, 0x00000591, 0x00001E7E, 0xFFFFF51C, 0x00000383, 0x00001E7E, 0xFFFFF51C, 0x00000383 }, - { 0x0213F0FE99041844, 0x00002A6F, 0xFFFFEF70, 0x00000443, 0x00001BAA, 0xFFFFF752, 0x00000336, 0x00001BAA, 0xFFFFF752, 0x00000336 }, - { 0x0213F0FE99183944, 0x00002C66, 0xFFFFEF5F, 0x0000043A, 0x000019F7, 0xFFFFF931, 0x000002EC, 0x000019F7, 0xFFFFF931, 0x000002EC }, - { 0x0213EA94DE0631C4, 0x00003852, 0xFFFFE6AB, 0x00000590, 0x000019C1, 0xFFFFF8B1, 0x000002E5, 0x000019C1, 0xFFFFF8B1, 0x000002E5 }, - { 0x0213F0FD42DA3124, 0x00003521, 0xFFFFE932, 0x00000523, 0x000018A9, 0xFFFFF96B, 0x000002D0, 0x000018A9, 0xFFFFF96B, 0x000002D0 }, - { 0x0213F0FE99062164, 0x000031B9, 0xFFFFEB36, 0x000004D0, 0x00001D65, 0xFFFFF612, 0x0000035D, 0x00001D65, 0xFFFFF612, 0x0000035D }, - { 0x0213F0FD42D41064, 0x00003ED0, 0xFFFFE135, 0x00000679, 0x00002351, 0xFFFFF0FE, 0x00000433, 0x00002351, 0xFFFFF0FE, 0x00000433 }, - { 0x0213F0FE990A20E4, 0x000033ED, 0xFFFFE91A, 0x00000541, 0x00001C93, 0xFFFFF6A0, 0x0000034A, 0x00001C93, 0xFFFFF6A0, 0x0000034A }, - { 0x0213EA94DE021844, 0x0000356F, 0xFFFFE8F7, 0x00000530, 0x000016BF, 0xFFFFFA85, 0x000002AB, 0x000016BF, 0xFFFFFA85, 0x000002AB }, - { 0x0213F0FE991840E4, 0x00002304, 0xFFFFF4F3, 0x00000364, 0x000017CC, 0xFFFFFA41, 0x000002CA, 0x000017CC, 0xFFFFFA41, 0x000002CA }, - { 0x0213F0FE99161164, 0x00002887, 0xFFFFEFD7, 0x00000450, 0x00001474, 0xFFFFFB94, 0x00000299, 0x00001474, 0xFFFFFB94, 0x00000299 }, - { 0x0213F0FE99063064, 0x00003D0B, 0xFFFFE416, 0x000005EF, 0x00001C7E, 0xFFFFF71D, 0x00000325, 0x00001C7E, 0xFFFFF71D, 0x00000325 }, - { 0x0213F0FE990810E4, 0x00003185, 0xFFFFEAFA, 0x000004E4, 0x00001A12, 0xFFFFF83C, 0x00000303, 0x00001A12, 0xFFFFF83C, 0x00000303 }, - { 0x0213F0FE990A1944, 0x00003032, 0xFFFFEAE6, 0x000004FC, 0x00001B2A, 0xFFFFF73F, 0x0000032B, 0x00001B2A, 0xFFFFF73F, 0x0000032B }, - { 0x0213F0FD42D838C4, 0x00002691, 0xFFFFF22D, 0x000003D6, 0x00001700, 0xFFFFFA6E, 0x000002C0, 0x00001700, 0xFFFFFA6E, 0x000002C0 }, - { 0x0213F0FE990218A4, 0x00002B2F, 0xFFFFEEC4, 0x0000044B, 0x0000215F, 0xFFFFF33F, 0x000003D2, 0x0000215F, 0xFFFFF33F, 0x000003D2 }, - { 0x0213F0FE990A4184, 0x000034AA, 0xFFFFE706, 0x000005B1, 0x00001B28, 0xFFFFF6B5, 0x00000349, 0x00001B28, 0xFFFFF6B5, 0x00000349 }, - { 0x0213F0FD42DA2964, 0x0000307E, 0xFFFFEB38, 0x000004E6, 0x00001A22, 0xFFFFF83F, 0x00000300, 0x00001A22, 0xFFFFF83F, 0x00000300 }, - { 0x0213F0FE990618A4, 0x000038D6, 0xFFFFE6D8, 0x0000057C, 0x00001B24, 0xFFFFF7E4, 0x00000307, 0x00001B24, 0xFFFFF7E4, 0x00000307 }, - { 0x0213F0FE99183044, 0x00002757, 0xFFFFF1E8, 0x000003DD, 0x000017F5, 0xFFFFFA15, 0x000002C8, 0x000017F5, 0xFFFFFA15, 0x000002C8 }, - { 0x0213F0FE99083184, 0x000031FC, 0xFFFFEB3E, 0x000004CE, 0x00001B4C, 0xFFFFF7AD, 0x00000319, 0x00001B4C, 0xFFFFF7AD, 0x00000319 }, - { 0x0213F0FE99301864, 0x00002933, 0xFFFFF073, 0x0000040E, 0x00001C3C, 0xFFFFF701, 0x0000033C, 0x00001C3C, 0xFFFFF701, 0x0000033C }, - { 0x0213F0FD42D218A4, 0x000040BB, 0xFFFFE066, 0x0000069A, 0x0000257F, 0xFFFFF08A, 0x00000435, 0x0000257F, 0xFFFFF08A, 0x00000435 }, - { 0x0213F0FE991010A4, 0x0000305B, 0xFFFFEB9B, 0x000004CB, 0x00001996, 0xFFFFF846, 0x00000308, 0x00001996, 0xFFFFF846, 0x00000308 }, - { 0x0213F0FE99064884, 0x000039C0, 0xFFFFE5D3, 0x000005B0, 0x00001A8D, 0xFFFFF7DA, 0x00000313, 0x00001A8D, 0xFFFFF7DA, 0x00000313 }, - { 0x0213EA94DE0210A4, 0x00002E23, 0xFFFFED3F, 0x0000048F, 0x0000189D, 0xFFFFF94C, 0x000002DE, 0x0000189D, 0xFFFFF94C, 0x000002DE }, - { 0x0213EA94DE021984, 0x0000332B, 0xFFFFE9F1, 0x00000516, 0x000018E6, 0xFFFFF8FE, 0x000002EC, 0x000018E6, 0xFFFFF8FE, 0x000002EC }, - { 0x0213F0FE990838C4, 0x000034A0, 0xFFFFEA44, 0x000004E4, 0x00001ECD, 0xFFFFF5B4, 0x00000364, 0x00001ECD, 0xFFFFF5B4, 0x00000364 }, - { 0x0213F0FD42D24104, 0x0000448C, 0xFFFFDF34, 0x000006A8, 0x0000231C, 0xFFFFF286, 0x000003D9, 0x0000231C, 0xFFFFF286, 0x000003D9 }, - { 0x0213EA94DE062144, 0x00002D8C, 0xFFFFEE65, 0x00000456, 0x000018B1, 0xFFFFF9C8, 0x000002C8, 0x000018B1, 0xFFFFF9C8, 0x000002C8 }, - { 0x0213F0FE99061904, 0x00003527, 0xFFFFE9BF, 0x000004FD, 0x00001D23, 0xFFFFF69F, 0x00000342, 0x00001D23, 0xFFFFF69F, 0x00000342 }, - { 0x0213F0FD42DC38A4, 0x00002C51, 0xFFFFEDC3, 0x00000483, 0x00001BE0, 0xFFFFF720, 0x0000032D, 0x00001BE0, 0xFFFFF720, 0x0000032D }, - { 0x0213F0FE990A3044, 0x00002C6C, 0xFFFFECEB, 0x000004B7, 0x00001C86, 0xFFFFF5E7, 0x00000371, 0x00001C86, 0xFFFFF5E7, 0x00000371 }, - { 0x0213F0FE99045144, 0x000037CF, 0xFFFFE6BE, 0x00000599, 0x000018CD, 0xFFFFF967, 0x000002C7, 0x000018CD, 0xFFFFF967, 0x000002C7 }, - { 0x0213F0FE99103164, 0x00002E6F, 0xFFFFED1D, 0x0000048E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E }, - { 0x0213F0FD42D42984, 0x00003FF3, 0xFFFFDF13, 0x000006F9, 0x000025BF, 0xFFFFEEEE, 0x00000497, 0x000025BF, 0xFFFFEEEE, 0x00000497 }, - { 0x0213F0FD42DC5104, 0x00004135, 0xFFFFDF97, 0x000006CC, 0x00001D52, 0xFFFFF541, 0x00000383, 0x00001D52, 0xFFFFF541, 0x00000383 }, - { 0x0213F0FD42DC20E4, 0x00002EA9, 0xFFFFEDDB, 0x0000045F, 0x0000197C, 0xFFFFF8E1, 0x000002F0, 0x0000197C, 0xFFFFF8E1, 0x000002F0 }, - { 0x0213EA94DE043084, 0x0000345C, 0xFFFFE922, 0x00000532, 0x00001922, 0xFFFFF8C7, 0x000002F1, 0x00001922, 0xFFFFF8C7, 0x000002F1 }, - { 0x0213F0FE99064124, 0x000035C4, 0xFFFFE8FE, 0x00000521, 0x00001C87, 0xFFFFF6F3, 0x00000330, 0x00001C87, 0xFFFFF6F3, 0x00000330 }, - { 0x0213F0FD42D83164, 0x00002888, 0xFFFFF08A, 0x0000041E, 0x0000150F, 0xFFFFFB87, 0x00000291, 0x0000150F, 0xFFFFFB87, 0x00000291 }, - { 0x0213F0FE990A1124, 0x000035E9, 0xFFFFE657, 0x000005CC, 0x00001BD6, 0xFFFFF664, 0x00000355, 0x00001BD6, 0xFFFFF664, 0x00000355 }, - { 0x0213F0FE991648E4, 0x00002F94, 0xFFFFEBD0, 0x000004E5, 0x00001333, 0xFFFFFCA7, 0x00000266, 0x00001333, 0xFFFFFCA7, 0x00000266 }, - { 0x0213F0FE99181964, 0x000029E7, 0xFFFFF009, 0x00000433, 0x0000144A, 0xFFFFFC37, 0x0000027D, 0x0000144A, 0xFFFFFC37, 0x0000027D }, - { 0x0213F0FE992C1944, 0x00003418, 0xFFFFE979, 0x00000521, 0x00001D33, 0xFFFFF66B, 0x0000034A, 0x00001D33, 0xFFFFF66B, 0x0000034A }, - { 0x0213EA94DE0440E4, 0x00003656, 0xFFFFE79D, 0x0000057A, 0x000017C2, 0xFFFFF992, 0x000002D4, 0x000017C2, 0xFFFFF992, 0x000002D4 }, - { 0x0213F0FE990C40C4, 0x00002EB2, 0xFFFFECFE, 0x00000493, 0x00001F2A, 0xFFFFF543, 0x0000037B, 0x00001F2A, 0xFFFFF543, 0x0000037B }, - { 0x0213F0FE99021124, 0x00002FC1, 0xFFFFEB3F, 0x000004E8, 0x00001CD0, 0xFFFFF5F7, 0x00000364, 0x00001CD0, 0xFFFFF5F7, 0x00000364 }, - { 0x0213F0FE990C1124, 0x0000307B, 0xFFFFEB66, 0x000004DE, 0x00001953, 0xFFFFF8ED, 0x000002E4, 0x00001953, 0xFFFFF8ED, 0x000002E4 }, - { 0x0213F0FD42DA1884, 0x00002CAA, 0xFFFFED07, 0x000004AC, 0x0000251C, 0xFFFFF086, 0x0000044D, 0x0000251C, 0xFFFFF086, 0x0000044D }, - { 0x0213EA94DE043944, 0x00002C94, 0xFFFFEE5F, 0x0000045B, 0x000018D7, 0xFFFFF900, 0x000002EB, 0x000018D7, 0xFFFFF900, 0x000002EB }, - { 0x0213F0FE99021864, 0x000031F1, 0xFFFFE9BE, 0x0000052E, 0x00001DDF, 0xFFFFF558, 0x00000380, 0x00001DDF, 0xFFFFF558, 0x00000380 }, - { 0x0213F0FE990E50C4, 0x00002603, 0xFFFFF1E9, 0x000003DA, 0x00001B37, 0xFFFFF75A, 0x0000032F, 0x00001B37, 0xFFFFF75A, 0x0000032F }, - { 0x0213F0FD42DA3044, 0x00003992, 0xFFFFE4F9, 0x000005EB, 0x00001775, 0xFFFFF9B8, 0x000002C2, 0x00001775, 0xFFFFF9B8, 0x000002C2 }, - { 0x0213F0FE99184964, 0x000029DA, 0xFFFFF052, 0x0000041F, 0x000016E2, 0xFFFFFA99, 0x000002BB, 0x000016E2, 0xFFFFFA99, 0x000002BB }, - { 0x0213F0FE99101064, 0x00002FF2, 0xFFFFEB8F, 0x000004DF, 0x00001AF6, 0xFFFFF7A1, 0x00000321, 0x00001AF6, 0xFFFFF7A1, 0x00000321 }, - { 0x0213F0FE991608E4, 0x00002590, 0xFFFFF222, 0x000003EE, 0x0000130B, 0xFFFFFCC9, 0x00000268, 0x0000130B, 0xFFFFFCC9, 0x00000268 }, - { 0x0213F0FE99024064, 0x000038A2, 0xFFFFE65F, 0x000005A2, 0x000018B1, 0xFFFFF917, 0x000002E1, 0x000018B1, 0xFFFFF917, 0x000002E1 }, - { 0x0213F0FD42DC48E4, 0x000035FD, 0xFFFFE73C, 0x0000058D, 0x00001BB3, 0xFFFFF6E1, 0x00000337, 0x00001BB3, 0xFFFFF6E1, 0x00000337 }, - { 0x0213F0FE991038C4, 0x00002AB7, 0xFFFFEF98, 0x00000429, 0x00001F35, 0xFFFFF539, 0x0000037C, 0x00001F35, 0xFFFFF539, 0x0000037C }, - { 0x0213F0FE990A0944, 0x000034BA, 0xFFFFE73D, 0x000005A6, 0x000018A6, 0xFFFFF888, 0x000002FB, 0x000018A6, 0xFFFFF888, 0x000002FB }, - { 0x0213F0FE99063844, 0x000032EA, 0xFFFFEA78, 0x000004F4, 0x00001AB6, 0xFFFFF812, 0x00000308, 0x00001AB6, 0xFFFFF812, 0x00000308 }, - { 0x0213F0FE990C3044, 0x00002BE9, 0xFFFFEE9A, 0x00000457, 0x00001942, 0xFFFFF8D2, 0x000002F2, 0x00001942, 0xFFFFF8D2, 0x000002F2 }, - { 0x0213F0FE99105124, 0x00002FAB, 0xFFFFEB76, 0x000004E1, 0x00001DCA, 0xFFFFF57D, 0x00000378, 0x00001DCA, 0xFFFFF57D, 0x00000378 }, - { 0x0213F0FE992E2844, 0x0000330A, 0xFFFFE9E1, 0x0000051B, 0x00001CC4, 0xFFFFF6DF, 0x00000335, 0x00001CC4, 0xFFFFF6DF, 0x00000335 }, - { 0x0213F0FE991828A4, 0x000027D8, 0xFFFFF276, 0x000003BF, 0x0000178A, 0xFFFFFABF, 0x000002B5, 0x0000178A, 0xFFFFFABF, 0x000002B5 }, - { 0x0213F0FD42DC3864, 0x0000340A, 0xFFFFE86D, 0x00000562, 0x00001B85, 0xFFFFF719, 0x0000032F, 0x00001B85, 0xFFFFF719, 0x0000032F }, - { 0x0213EA94DE063084, 0x00003879, 0xFFFFE73F, 0x00000578, 0x0000161C, 0xFFFFFB6B, 0x00000281, 0x0000161C, 0xFFFFFB6B, 0x00000281 }, - { 0x0213F0FE99184064, 0x00002879, 0xFFFFF0F8, 0x0000040A, 0x00001749, 0xFFFFFA37, 0x000002CC, 0x00001749, 0xFFFFFA37, 0x000002CC }, - { 0x0213F0FE99043964, 0x00002C3A, 0xFFFFEEA0, 0x0000044F, 0x00001D57, 0xFFFFF6C2, 0x00000332, 0x00001D57, 0xFFFFF6C2, 0x00000332 }, - { 0x0213EA94DE021964, 0x000035BB, 0xFFFFE90D, 0x0000052A, 0x000017D9, 0xFFFFF9F5, 0x000002C3, 0x000017D9, 0xFFFFF9F5, 0x000002C3 }, - { 0x0213EA94DE041124, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x00001F10, 0xFFFFF539, 0x0000037D, 0x00001F10, 0xFFFFF539, 0x0000037D }, - { 0x0213F0FE99102824, 0x00002A1A, 0xFFFFEFAD, 0x00000430, 0x00001D47, 0xFFFFF62F, 0x0000035E, 0x00001D47, 0xFFFFF62F, 0x0000035E }, - { 0x0213F0FE99164924, 0x00002AF0, 0xFFFFEEDC, 0x00000465, 0x0000145F, 0xFFFFFBEB, 0x00000281, 0x0000145F, 0xFFFFFBEB, 0x00000281 }, - { 0x0213F0FE99183164, 0x00002657, 0xFFFFF2E0, 0x000003B6, 0x00001664, 0xFFFFFB37, 0x000002A2, 0x00001664, 0xFFFFFB37, 0x000002A2 }, - { 0x0213F0FD42D03864, 0x00003183, 0xFFFFE9F1, 0x0000052B, 0x00002020, 0xFFFFF3CE, 0x000003C1, 0x00002020, 0xFFFFF3CE, 0x000003C1 }, - { 0x0213F0FD42C628E4, 0x00003240, 0xFFFFEB65, 0x000004C7, 0x00002425, 0xFFFFF245, 0x000003F3, 0x00002425, 0xFFFFF245, 0x000003F3 }, - { 0x0213EA94DE321104, 0x000023D0, 0xFFFFF400, 0x00000397, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, - { 0x0213F0FD42CE38A4, 0x00003440, 0xFFFFE872, 0x0000055B, 0x00002247, 0xFFFFF296, 0x000003E8, 0x00002247, 0xFFFFF296, 0x000003E8 }, - { 0x0213F0FD42D04904, 0x00003275, 0xFFFFE970, 0x00000538, 0x00001F94, 0xFFFFF429, 0x000003AD, 0x00001F94, 0xFFFFF429, 0x000003AD }, - { 0x0213F0FD42C640A4, 0x00003918, 0xFFFFE5DA, 0x000005B6, 0x000024FC, 0xFFFFF106, 0x00000426, 0x000024FC, 0xFFFFF106, 0x00000426 }, - { 0x0213EA94DE062044, 0x0000334B, 0xFFFFEA39, 0x000004FD, 0x00001983, 0xFFFFF8F6, 0x000002E2, 0x00001983, 0xFFFFF8F6, 0x000002E2 }, - { 0x0213F0FD42C64984, 0x00003B59, 0xFFFFE4D0, 0x000005DA, 0x00002605, 0xFFFFF090, 0x00000439, 0x00002605, 0xFFFFF090, 0x00000439 }, - { 0x0213F0FD42D03124, 0x00003251, 0xFFFFEA46, 0x00000511, 0x00002781, 0xFFFFEF84, 0x00000470, 0x00002781, 0xFFFFEF84, 0x00000470 }, - { 0x0213F0FD42CA3164, 0x00003304, 0xFFFFE926, 0x00000542, 0x00001EE9, 0xFFFFF4E4, 0x0000038B, 0x00001EE9, 0xFFFFF4E4, 0x0000038B }, - { 0x0213F0FD42CC38C4, 0x00002F4C, 0xFFFFEC0C, 0x000004C4, 0x00001E49, 0xFFFFF578, 0x00000374, 0x00001E49, 0xFFFFF578, 0x00000374 }, - { 0x0213EA94DE1C2164, 0x00002034, 0xFFFFF692, 0x0000034C, 0x000014B8, 0xFFFFFC5B, 0x00000294, 0x000014B8, 0xFFFFFC5B, 0x00000294 }, - { 0x0213F0FD42CE4924, 0x0000385F, 0xFFFFE513, 0x000005F3, 0x000024E7, 0xFFFFF053, 0x00000450, 0x000024E7, 0xFFFFF053, 0x00000450 }, - { 0x0213EA94DE1C40E4, 0x00001D70, 0xFFFFF821, 0x0000030F, 0x00001541, 0xFFFFFBB4, 0x000002B0, 0x00001541, 0xFFFFFBB4, 0x000002B0 }, - { 0x0213F0FD42D02084, 0x000034EB, 0xFFFFE7FF, 0x00000575, 0x000019B4, 0xFFFFF836, 0x00000308, 0x000019B4, 0xFFFFF836, 0x00000308 }, - { 0x0213F0FD42D050E4, 0x000037C9, 0xFFFFE5D4, 0x000005CD, 0x000026A1, 0xFFFFEF0C, 0x00000491, 0x000026A1, 0xFFFFEF0C, 0x00000491 }, - { 0x0213EA94DE121944, 0x00002918, 0xFFFFF148, 0x000003E9, 0x00001A49, 0xFFFFF94C, 0x000002CF, 0x00001A49, 0xFFFFF94C, 0x000002CF }, - { 0x0213F0FD42CA4064, 0x00002F90, 0xFFFFEAB5, 0x00000514, 0x00001707, 0xFFFFF9C7, 0x000002C4, 0x00001707, 0xFFFFF9C7, 0x000002C4 }, - { 0x0213EA94DE062064, 0x0000327E, 0xFFFFEA99, 0x000004F4, 0x0000194F, 0xFFFFF929, 0x000002DC, 0x0000194F, 0xFFFFF929, 0x000002DC }, - { 0x0213F0FD42C64084, 0x0000326F, 0xFFFFE9CF, 0x00000519, 0x00002240, 0xFFFFF299, 0x000003E7, 0x00002240, 0xFFFFF299, 0x000003E7 }, - { 0x0213EA94DE321124, 0x000022FB, 0xFFFFF4C6, 0x00000371, 0x00001506, 0xFFFFFC73, 0x00000265, 0x00001506, 0xFFFFFC73, 0x00000265 }, - { 0x0213F0FD42CA3924, 0x00003AD6, 0xFFFFE470, 0x000005FE, 0x00001F03, 0xFFFFF4F3, 0x00000387, 0x00001F03, 0xFFFFF4F3, 0x00000387 }, - { 0x0213EA94DE201124, 0x00001F11, 0xFFFFF756, 0x00000332, 0x00001666, 0xFFFFFB8A, 0x000002B2, 0x00001666, 0xFFFFFB8A, 0x000002B2 }, - { 0x0213EA94DE0238A4, 0x00002A5F, 0xFFFFEFA7, 0x00000430, 0x00001943, 0xFFFFF8C6, 0x000002F7, 0x00001943, 0xFFFFF8C6, 0x000002F7 }, - { 0x0213EA94DE1650E4, 0x0000235E, 0xFFFFF3B4, 0x000003B3, 0x00001489, 0xFFFFFBCF, 0x0000029B, 0x00001489, 0xFFFFFBCF, 0x0000029B }, - { 0x0213F0FD42CC38A4, 0x00003570, 0xFFFFE780, 0x0000058D, 0x00001B1D, 0xFFFFF767, 0x00000325, 0x00001B1D, 0xFFFFF767, 0x00000325 }, - { 0x0213EA94DE042064, 0x00003678, 0xFFFFE7C3, 0x00000569, 0x00001831, 0xFFFFF98E, 0x000002C8, 0x00001831, 0xFFFFF98E, 0x000002C8 }, - { 0x0213EA94DE201864, 0x000020B9, 0xFFFFF625, 0x0000035A, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, - { 0x0213F0FD42C63184, 0x00003985, 0xFFFFE529, 0x000005DD, 0x00002165, 0xFFFFF351, 0x000003C5, 0x00002165, 0xFFFFF351, 0x000003C5 }, - { 0x0213F0FD42D02064, 0x0000322A, 0xFFFFE99D, 0x00000535, 0x000019A1, 0xFFFFF844, 0x00000305, 0x000019A1, 0xFFFFF844, 0x00000305 }, - { 0x0213F0FD42D05104, 0x000033ED, 0xFFFFE834, 0x00000571, 0x00002094, 0xFFFFF33A, 0x000003DB, 0x00002094, 0xFFFFF33A, 0x000003DB }, - { 0x0213EA94DE2040C4, 0x00001D10, 0xFFFFF84D, 0x0000030B, 0x00001659, 0xFFFFFB0A, 0x000002CB, 0x00001659, 0xFFFFFB0A, 0x000002CB }, - { 0x0213EA94DE1C1124, 0x0000210F, 0xFFFFF644, 0x00000355, 0x00001A4A, 0xFFFFF90F, 0x00000310, 0x00001A4A, 0xFFFFF90F, 0x00000310 }, - { 0x0213EA94DE164164, 0x00001CA8, 0xFFFFF813, 0x00000316, 0x00001440, 0xFFFFFC1C, 0x0000029D, 0x00001440, 0xFFFFFC1C, 0x0000029D }, - { 0x0213EA94DE3210C4, 0x00002864, 0xFFFFF15A, 0x000003FA, 0x0000137F, 0xFFFFFD43, 0x00000248, 0x0000137F, 0xFFFFFD43, 0x00000248 }, - { 0x0213F0FD42D04184, 0x00002CDB, 0xFFFFECFD, 0x000004A7, 0x00002472, 0xFFFFF0E1, 0x00000437, 0x00002472, 0xFFFFF0E1, 0x00000437 }, - { 0x0213F0FD42CC5104, 0x00003348, 0xFFFFE8CA, 0x00000554, 0x00001E91, 0xFFFFF4D4, 0x00000392, 0x00001E91, 0xFFFFF4D4, 0x00000392 }, - { 0x0213F0FD42C64944, 0x00003989, 0xFFFFE4BB, 0x000005F8, 0x00001ACB, 0xFFFFF780, 0x00000319, 0x00001ACB, 0xFFFFF780, 0x00000319 }, - { 0x0213F0FD42CA2104, 0x00003238, 0xFFFFEA09, 0x0000051E, 0x00001F08, 0xFFFFF4F4, 0x0000038C, 0x00001F08, 0xFFFFF4F4, 0x0000038C }, - { 0x0213EA94DE120904, 0x00002453, 0xFFFFF3B0, 0x0000038D, 0x00001AED, 0xFFFFF8A2, 0x000002EA, 0x00001AED, 0xFFFFF8A2, 0x000002EA }, - { 0x0213EA94DE1C3024, 0x00002459, 0xFFFFF409, 0x000003A8, 0x000017B5, 0xFFFFFA53, 0x000002E1, 0x000017B5, 0xFFFFFA53, 0x000002E1 }, - { 0x0213EA94DE021184, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001DC9, 0xFFFFF5D5, 0x00000368, 0x00001DC9, 0xFFFFF5D5, 0x00000368 }, - { 0x0213EA94DE023104, 0x000031BF, 0xFFFFECA3, 0x00000498, 0x00001DC9, 0xFFFFF717, 0x00000336, 0x00001DC9, 0xFFFFF717, 0x00000336 }, - { 0x0213F0FD42CE2104, 0x00003896, 0xFFFFE5DD, 0x000005C5, 0x000023E2, 0xFFFFF1A1, 0x00000416, 0x000023E2, 0xFFFFF1A1, 0x00000416 }, - { 0x0213EA94DE323904, 0x000023CB, 0xFFFFF4C8, 0x00000372, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, - { 0x0213F0FD42D020C4, 0x00002F6B, 0xFFFFEBF0, 0x000004CE, 0x00001C89, 0xFFFFF689, 0x0000034D, 0x00001C89, 0xFFFFF689, 0x0000034D }, - { 0x0213F0FD42CE3904, 0x00003E72, 0xFFFFE211, 0x0000065D, 0x0000218D, 0xFFFFF309, 0x000003DC, 0x0000218D, 0xFFFFF309, 0x000003DC }, - { 0x0213EA94DE022084, 0x00002612, 0xFFFFF2C3, 0x000003AD, 0x000019F7, 0xFFFFF891, 0x000002FE, 0x000019F7, 0xFFFFF891, 0x000002FE }, - { 0x0213EA94DE164184, 0x0000205D, 0xFFFFF59F, 0x00000372, 0x000012E6, 0xFFFFFD0A, 0x00000270, 0x000012E6, 0xFFFFFD0A, 0x00000270 }, - { 0x0213F0FD42CA2124, 0x00002ECB, 0xFFFFEC47, 0x000004BD, 0x00001936, 0xFFFFF8D9, 0x000002E4, 0x00001936, 0xFFFFF8D9, 0x000002E4 }, - { 0x0213EA94DE064904, 0x00002BDB, 0xFFFFEE6D, 0x00000458, 0x00001852, 0xFFFFF943, 0x000002D9, 0x00001852, 0xFFFFF943, 0x000002D9 }, - { 0x0213EA94DE124904, 0x00003387, 0xFFFFE958, 0x00000534, 0x00001932, 0xFFFFF8FA, 0x000002E4, 0x00001932, 0xFFFFF8FA, 0x000002E4 }, - { 0x0213EA94DE0208C4, 0x00002E3C, 0xFFFFED26, 0x00000495, 0x00001858, 0xFFFFF990, 0x000002D1, 0x00001858, 0xFFFFF990, 0x000002D1 }, - { 0x0213EA94DE022964, 0x000033B8, 0xFFFFEA5C, 0x000004F9, 0x00001BD1, 0xFFFFF76A, 0x0000032E, 0x00001BD1, 0xFFFFF76A, 0x0000032E }, - { 0x0213EA94DE062984, 0x00002BCE, 0xFFFFEEE9, 0x00000443, 0x00001982, 0xFFFFF90D, 0x000002DF, 0x00001982, 0xFFFFF90D, 0x000002DF }, - { 0x0213F0FD42D048E4, 0x00003495, 0xFFFFE7D9, 0x0000057B, 0x00001D2A, 0xFFFFF5A5, 0x00000372, 0x00001D2A, 0xFFFFF5A5, 0x00000372 }, - { 0x0213F0FD42CA38E4, 0x000034B1, 0xFFFFE88D, 0x00000556, 0x00002014, 0xFFFFF43A, 0x000003AA, 0x00002014, 0xFFFFF43A, 0x000003AA }, - { 0x0213F0FD42CC3124, 0x00002F96, 0xFFFFEC84, 0x000004AD, 0x000024A2, 0xFFFFF1CE, 0x0000040A, 0x000024A2, 0xFFFFF1CE, 0x0000040A }, - { 0x0213EA94DE161064, 0x0000203B, 0xFFFFF640, 0x00000359, 0x000014EC, 0xFFFFFC14, 0x0000029C, 0x000014EC, 0xFFFFFC14, 0x0000029C }, - { 0x0213F0FD42D02984, 0x000034E2, 0xFFFFE7B8, 0x00000582, 0x00001938, 0xFFFFF872, 0x000002FA, 0x00001938, 0xFFFFF872, 0x000002FA }, - { 0x0213EA94DE063124, 0x00002AC7, 0xFFFFF0C1, 0x000003F5, 0x00002268, 0xFFFFF39C, 0x000003C9, 0x00002268, 0xFFFFF39C, 0x000003C9 }, - { 0x0213F0FD42C63144, 0x000036F6, 0xFFFFE77F, 0x00000571, 0x000027D9, 0xFFFFEF6F, 0x00000461, 0x000027D9, 0xFFFFEF6F, 0x00000461 }, - { 0x0213EA94DE123124, 0x00002BAB, 0xFFFFF018, 0x00000419, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, - { 0x0213EA94DE323924, 0x000028C4, 0xFFFFF161, 0x000003F8, 0x0000180C, 0xFFFFFA4B, 0x000002C8, 0x0000180C, 0xFFFFFA4B, 0x000002C8 }, - { 0x0213F0FD42CA2864, 0x00002F48, 0xFFFFEB62, 0x000004EE, 0x00001912, 0xFFFFF8C8, 0x000002EA, 0x00001912, 0xFFFFF8C8, 0x000002EA }, - { 0x0213F0FD42CE2864, 0x000032DF, 0xFFFFE911, 0x00000545, 0x00001F06, 0xFFFFF485, 0x0000039C, 0x00001F06, 0xFFFFF485, 0x0000039C }, - { 0x0213F0FD42D04144, 0x000035B8, 0xFFFFE74F, 0x00000590, 0x00001FD7, 0xFFFFF410, 0x000003AF, 0x00001FD7, 0xFFFFF410, 0x000003AF }, - { 0x0213F0FD42D050C4, 0x00003608, 0xFFFFE6D7, 0x000005A9, 0x000024A6, 0xFFFFF075, 0x00000450, 0x000024A6, 0xFFFFF075, 0x00000450 }, - { 0x0213F0FD42CA3884, 0x000030AB, 0xFFFFEAED, 0x000004F5, 0x000019EE, 0xFFFFF84E, 0x000002FC, 0x000019EE, 0xFFFFF84E, 0x000002FC }, - { 0x0213EA94DE0620C4, 0x000030C6, 0xFFFFEC92, 0x0000049E, 0x000019BB, 0xFFFFF8F1, 0x000002F3, 0x000019BB, 0xFFFFF8F1, 0x000002F3 }, - { 0x0213F0FD42C630A4, 0x00003B27, 0xFFFFE544, 0x000005C1, 0x00002697, 0xFFFFF072, 0x00000438, 0x00002697, 0xFFFFF072, 0x00000438 }, - { 0x0213EA94DE1248E4, 0x00002F23, 0xFFFFEC48, 0x000004B9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, - { 0x0213EA94DE0629A4, 0x00002BD7, 0xFFFFEEAC, 0x00000450, 0x00001991, 0xFFFFF8F4, 0x000002E2, 0x00001991, 0xFFFFF8F4, 0x000002E2 }, - { 0x0213EA94DE022024, 0x00003210, 0xFFFFEB24, 0x000004DE, 0x00001BDF, 0xFFFFF744, 0x00000333, 0x00001BDF, 0xFFFFF744, 0x00000333 }, - { 0x0213EA94DE244144, 0x00002DDC, 0xFFFFED0D, 0x000004AC, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, - { 0x0213EA94DE203964, 0x000023E6, 0xFFFFF40C, 0x000003A9, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, - { 0x0213F0FD42CA29A4, 0x000030CE, 0xFFFFE9A5, 0x0000053C, 0x00001C45, 0xFFFFF60E, 0x0000035D, 0x00001C45, 0xFFFFF60E, 0x0000035D }, - { 0x0213EA94DE161084, 0x00001E89, 0xFFFFF73A, 0x00000337, 0x0000157C, 0xFFFFFBC0, 0x000002AA, 0x0000157C, 0xFFFFFBC0, 0x000002AA }, - { 0x0213F0FD42D04124, 0x000036C6, 0xFFFFE6CF, 0x000005A1, 0x00002457, 0xFFFFF11D, 0x0000042D, 0x00002457, 0xFFFFF11D, 0x0000042D }, - { 0x0213EA94DE321944, 0x00002815, 0xFFFFF19A, 0x000003F2, 0x000016D2, 0xFFFFFB40, 0x00000299, 0x000016D2, 0xFFFFFB40, 0x00000299 }, - { 0x0213EA94DE1C19A4, 0x00001FE2, 0xFFFFF660, 0x00000354, 0x000015A7, 0xFFFFFB47, 0x000002C1, 0x000015A7, 0xFFFFFB47, 0x000002C1 }, - { 0x0213EA94DE161964, 0x00002114, 0xFFFFF634, 0x00000356, 0x000016C1, 0xFFFFFB43, 0x000002B8, 0x000016C1, 0xFFFFFB43, 0x000002B8 }, - { 0x0213F0FD42CC28C4, 0x000028E3, 0xFFFFF075, 0x00000414, 0x0000203C, 0xFFFFF438, 0x000003B3, 0x0000203C, 0xFFFFF438, 0x000003B3 }, - { 0x0213EA94DE1C3924, 0x00001EEB, 0xFFFFF7BB, 0x0000031A, 0x00001580, 0xFFFFFBD7, 0x000002AD, 0x00001580, 0xFFFFFBD7, 0x000002AD }, - { 0x0213EA94DE2408C4, 0x00002BB2, 0xFFFFEE72, 0x00000470, 0x0000192C, 0xFFFFF91E, 0x000002E7, 0x0000192C, 0xFFFFF91E, 0x000002E7 }, - { 0x0213EA94DE0650E4, 0x00003A3D, 0xFFFFE49D, 0x000005F5, 0x00001A3B, 0xFFFFF7B1, 0x00000320, 0x00001A3B, 0xFFFFF7B1, 0x00000320 }, - { 0x0213F0FD42CE3164, 0x00002E93, 0xFFFFEC5A, 0x000004B4, 0x000025EB, 0xFFFFF03C, 0x0000044A, 0x000025EB, 0xFFFFF03C, 0x0000044A }, - { 0x0213F0FD42CA20C4, 0x0000331F, 0xFFFFE97A, 0x00000531, 0x00001A06, 0xFFFFF850, 0x000002FD, 0x00001A06, 0xFFFFF850, 0x000002FD }, - { 0x0213F0FD42C63964, 0x00003937, 0xFFFFE5A0, 0x000005C7, 0x0000235E, 0xFFFFF234, 0x000003F2, 0x0000235E, 0xFFFFF234, 0x000003F2 }, - { 0x0213EA94DE1E3924, 0x00001DD0, 0xFFFFF80E, 0x00000319, 0x000015C7, 0xFFFFFB91, 0x000002BC, 0x000015C7, 0xFFFFFB91, 0x000002BC }, - { 0x0213F0FD42D03964, 0x00003328, 0xFFFFE905, 0x0000054A, 0x00002054, 0xFFFFF3BF, 0x000003C0, 0x00002054, 0xFFFFF3BF, 0x000003C0 }, - { 0x0213F0FD42CC1104, 0x00002FE5, 0xFFFFEA65, 0x00000520, 0x0000188B, 0xFFFFF8A7, 0x000002F5, 0x0000188B, 0xFFFFF8A7, 0x000002F5 }, - { 0x0213F0FD42CA38A4, 0x00002ED3, 0xFFFFEC51, 0x000004B9, 0x00001888, 0xFFFFF96A, 0x000002CA, 0x00001888, 0xFFFFF96A, 0x000002CA }, - { 0x0213F0FD42D03084, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001F8D, 0xFFFFF436, 0x000003B4, 0x00001F8D, 0xFFFFF436, 0x000003B4 }, - { 0x0213F0FD42CE4084, 0x0000329F, 0xFFFFE8F7, 0x0000054F, 0x000023DB, 0xFFFFF0EE, 0x0000043A, 0x000023DB, 0xFFFFF0EE, 0x0000043A }, - { 0x0213EA94DE0438A4, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001AFD, 0xFFFFF781, 0x00000329, 0x00001AFD, 0xFFFFF781, 0x00000329 }, - { 0x0213EA94DE1E19A4, 0x00001BBF, 0xFFFFF8E2, 0x000002F7, 0x00001722, 0xFFFFFA85, 0x000002DB, 0x00001722, 0xFFFFFA85, 0x000002DB }, - { 0x0213EA94DE022044, 0x000030E4, 0xFFFFEBE6, 0x000004BB, 0x00001C80, 0xFFFFF6E1, 0x0000033E, 0x00001C80, 0xFFFFF6E1, 0x0000033E }, - { 0x0213EA94DE122944, 0x000030E2, 0xFFFFECD0, 0x00000492, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, - { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, - { 0x0213EA94DE1610A4, 0x00002147, 0xFFFFF585, 0x0000037A, 0x000014CC, 0xFFFFFC3B, 0x00000296, 0x000014CC, 0xFFFFFC3B, 0x00000296 }, - { 0x0213EA94DE322124, 0x00002507, 0xFFFFF432, 0x0000038A, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, - { 0x0213EA94DE0638A4, 0x0000339B, 0xFFFFEA7D, 0x000004F0, 0x0000191E, 0xFFFFF944, 0x000002DF, 0x0000191E, 0xFFFFF944, 0x000002DF }, - { 0x0213F0FD42CC28A4, 0x00002842, 0xFFFFF043, 0x00000427, 0x00001988, 0xFFFFF892, 0x000002F7, 0x00001988, 0xFFFFF892, 0x000002F7 }, - { 0x0213F0FD42C618A4, 0x0000389D, 0xFFFFE5D8, 0x000005BF, 0x00001EE1, 0xFFFFF4EF, 0x00000387, 0x00001EE1, 0xFFFFF4EF, 0x00000387 }, - { 0x0213F0FD42CE3184, 0x0000396D, 0xFFFFE4D7, 0x000005F2, 0x000020DA, 0xFFFFF34E, 0x000003CD, 0x000020DA, 0xFFFFF34E, 0x000003CD }, - { 0x0213F0FD42CA3104, 0x0000355F, 0xFFFFE85A, 0x0000055F, 0x0000281F, 0xFFFFEF28, 0x0000047D, 0x0000281F, 0xFFFFEF28, 0x0000047D }, - { 0x0213EA94DE1C50E4, 0x00002284, 0xFFFFF46E, 0x00000399, 0x00001498, 0xFFFFFBE3, 0x0000029C, 0x00001498, 0xFFFFFBE3, 0x0000029C }, - { 0x0213EA94DE023944, 0x000031B6, 0xFFFFEB42, 0x000004D9, 0x00001F54, 0xFFFFF4D2, 0x00000399, 0x00001F54, 0xFFFFF4D2, 0x00000399 }, - { 0x0213F0FD42C63064, 0x000035CE, 0xFFFFE79D, 0x00000578, 0x00001C78, 0xFFFFF68C, 0x00000344, 0x00001C78, 0xFFFFF68C, 0x00000344 }, - { 0x0213EA94DE1E4964, 0x00001C0A, 0xFFFFF81B, 0x00000318, 0x00001492, 0xFFFFFBCC, 0x000002A5, 0x00001492, 0xFFFFFBCC, 0x000002A5 }, - { 0x0213EA94DE022184, 0x00003492, 0xFFFFE95C, 0x00000526, 0x00001A97, 0xFFFFF81B, 0x0000030B, 0x00001A97, 0xFFFFF81B, 0x0000030B }, - { 0x0213EA94DE163164, 0x00001E89, 0xFFFFF7D0, 0x0000031A, 0x000017A5, 0xFFFFFA99, 0x000002D9, 0x000017A5, 0xFFFFFA99, 0x000002D9 }, - { 0x0213F0FD42CA48C4, 0x00002DCC, 0xFFFFEBE0, 0x000004DE, 0x000019BA, 0xFFFFF7F5, 0x0000030D, 0x000019BA, 0xFFFFF7F5, 0x0000030D }, - { 0x0213EA94DE042984, 0x000030EF, 0xFFFFEBC1, 0x000004C0, 0x00001AA9, 0xFFFFF814, 0x0000030A, 0x00001AA9, 0xFFFFF814, 0x0000030A }, - { 0x0213EA94DE245124, 0x00002EA3, 0xFFFFEBF6, 0x000004D8, 0x00001DCF, 0xFFFFF521, 0x00000399, 0x00001DCF, 0xFFFFF521, 0x00000399 }, - { 0x0213EA94DE324164, 0x00002B5F, 0xFFFFEEA1, 0x0000046C, 0x000017EB, 0xFFFFF9C9, 0x000002D4, 0x000017EB, 0xFFFFF9C9, 0x000002D4 }, - { 0x0213EA94DE024104, 0x00002C63, 0xFFFFEE82, 0x00000455, 0x00002268, 0xFFFFF29D, 0x000003F6, 0x00002268, 0xFFFFF29D, 0x000003F6 }, - { 0x0213EA94DE121904, 0x00002B1A, 0xFFFFF016, 0x0000041C, 0x000019AA, 0xFFFFF988, 0x000002D2, 0x000019AA, 0xFFFFF988, 0x000002D2 }, - { 0x0213F0FD42CA2964, 0x0000332F, 0xFFFFE934, 0x0000053B, 0x00001E47, 0xFFFFF566, 0x00000374, 0x00001E47, 0xFFFFF566, 0x00000374 }, - { 0x0213F0FD42CA48E4, 0x00002995, 0xFFFFEEC1, 0x00000465, 0x0000178F, 0xFFFFF995, 0x000002C5, 0x0000178F, 0xFFFFF995, 0x000002C5 }, - { 0x0213EA94DE201884, 0x00001C2E, 0xFFFFF932, 0x000002E9, 0x000015C2, 0xFFFFFBC5, 0x000002AD, 0x000015C2, 0xFFFFFBC5, 0x000002AD }, - { 0x0213F0FD42C640E4, 0x00003B08, 0xFFFFE4E8, 0x000005D8, 0x0000209D, 0xFFFFF444, 0x00000398, 0x0000209D, 0xFFFFF444, 0x00000398 }, - { 0x0213EA94DE0450E4, 0x00002F1F, 0xFFFFEB74, 0x000004EB, 0x00001F4C, 0xFFFFF3D4, 0x000003CE, 0x00001F4C, 0xFFFFF3D4, 0x000003CE }, - { 0x0213EA94DE043884, 0x00003415, 0xFFFFE89F, 0x00000553, 0x0000186B, 0xFFFFF8E1, 0x000002EF, 0x0000186B, 0xFFFFF8E1, 0x000002EF }, - { 0x0213F0FD42CC10C4, 0x00003441, 0xFFFFE779, 0x0000059D, 0x000019EA, 0xFFFFF7B2, 0x0000031F, 0x000019EA, 0xFFFFF7B2, 0x0000031F }, - { 0x0213EA94DE164064, 0x00002174, 0xFFFFF546, 0x00000378, 0x00001456, 0xFFFFFC5F, 0x00000284, 0x00001456, 0xFFFFFC5F, 0x00000284 }, - { 0x0213F0FD42CE40C4, 0x00003788, 0xFFFFE61E, 0x000005BF, 0x00001DF4, 0xFFFFF562, 0x00000374, 0x00001DF4, 0xFFFFF562, 0x00000374 }, - { 0x0213EA94DE1E1844, 0x00001C41, 0xFFFFF8C1, 0x000002FC, 0x0000171E, 0xFFFFFA93, 0x000002DE, 0x0000171E, 0xFFFFFA93, 0x000002DE }, - { 0x0213F0FD42CA3864, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x000017E4, 0xFFFFF934, 0x000002DF, 0x000017E4, 0xFFFFF934, 0x000002DF }, - { 0x0213F0FD42CC3144, 0x0000327A, 0xFFFFEA71, 0x000004FF, 0x00001D96, 0xFFFFF63B, 0x00000351, 0x00001D96, 0xFFFFF63B, 0x00000351 }, - { 0x0213EA94DE1E4064, 0x000023C6, 0xFFFFF3E5, 0x000003B6, 0x000014DE, 0xFFFFFC29, 0x00000294, 0x000014DE, 0xFFFFFC29, 0x00000294 }, - { 0x0213EA94DE164944, 0x00001F96, 0xFFFFF5FA, 0x00000364, 0x00001397, 0xFFFFFC9D, 0x0000027D, 0x00001397, 0xFFFFFC9D, 0x0000027D }, - { 0x0213EA94DE063144, 0x00002B51, 0xFFFFEFB5, 0x00000420, 0x00001ACA, 0xFFFFF824, 0x0000030D, 0x00001ACA, 0xFFFFF824, 0x0000030D }, - { 0x0213EA94DE1E4944, 0x000020DB, 0xFFFFF55B, 0x0000037C, 0x0000153D, 0xFFFFFB5F, 0x000002BA, 0x0000153D, 0xFFFFFB5F, 0x000002BA }, - { 0x0213EA94DE0221A4, 0x000030BB, 0xFFFFEBDA, 0x000004BC, 0x00001B0E, 0xFFFFF7A8, 0x0000031E, 0x00001B0E, 0xFFFFF7A8, 0x0000031E }, - { 0x0213F0FD42C62904, 0x000033C4, 0xFFFFEA41, 0x000004FA, 0x000022C6, 0xFFFFF363, 0x000003BC, 0x000022C6, 0xFFFFF363, 0x000003BC }, - { 0x0213EA94DE240924, 0x00002D47, 0xFFFFEE01, 0x00000477, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, - { 0x0213EA94DE1E31A4, 0x00001E7B, 0xFFFFF733, 0x00000339, 0x00001668, 0xFFFFFB29, 0x000002BF, 0x00001668, 0xFFFFFB29, 0x000002BF }, - { 0x0213F0FD42CA2984, 0x00002F7E, 0xFFFFEAFF, 0x000004FC, 0x000018D4, 0xFFFFF8BE, 0x000002E8, 0x000018D4, 0xFFFFF8BE, 0x000002E8 }, - { 0x0213EA94DE3238A4, 0x00002635, 0xFFFFF2E1, 0x000003BC, 0x000017A4, 0xFFFFFA67, 0x000002C3, 0x000017A4, 0xFFFFFA67, 0x000002C3 }, - { 0x0213EA94DE1230A4, 0x000026CA, 0xFFFFF2C1, 0x000003B2, 0x00001C3E, 0xFFFFF7AE, 0x0000031F, 0x00001C3E, 0xFFFFF7AE, 0x0000031F }, - { 0x0213EA94DE1C1064, 0x00002550, 0xFFFFF380, 0x000003B5, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, - { 0x0213F0FD42CA4904, 0x00002FBC, 0xFFFFEAF8, 0x000004FA, 0x000018CC, 0xFFFFF8C6, 0x000002E8, 0x000018CC, 0xFFFFF8C6, 0x000002E8 }, - { 0x0213F0FD42D018E4, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001EFF, 0xFFFFF4DA, 0x0000038F, 0x00001EFF, 0xFFFFF4DA, 0x0000038F }, - { 0x0213EA94DE164084, 0x000023E6, 0xFFFFF413, 0x000003A1, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, - { 0x0213F0FD42CE3024, 0x00003251, 0xFFFFEAA2, 0x000004F5, 0x000025B0, 0xFFFFF0DF, 0x00000431, 0x000025B0, 0xFFFFF0DF, 0x00000431 }, - { 0x0213F0FD42D03984, 0x00002F6F, 0xFFFFEB67, 0x000004E6, 0x00002275, 0xFFFFF249, 0x000003FB, 0x00002275, 0xFFFFF249, 0x000003FB }, - { 0x0213EA94DE322964, 0x00002597, 0xFFFFF34A, 0x000003B1, 0x00001BCC, 0xFFFFF822, 0x0000031A, 0x00001BCC, 0xFFFFF822, 0x0000031A }, - { 0x0213F0FD42C63864, 0x00003B1D, 0xFFFFE40E, 0x0000060D, 0x00001F61, 0xFFFFF470, 0x0000039F, 0x00001F61, 0xFFFFF470, 0x0000039F }, - { 0x0213F0FD42C64144, 0x0000379F, 0xFFFFE6DB, 0x0000058C, 0x00002460, 0xFFFFF170, 0x00000415, 0x00002460, 0xFFFFF170, 0x00000415 }, - { 0x0213EA94DE165144, 0x00002442, 0xFFFFF2FB, 0x000003D9, 0x00001414, 0xFFFFFBDC, 0x000002A2, 0x00001414, 0xFFFFFBDC, 0x000002A2 }, - { 0x0213EA94DE0240C4, 0x00003270, 0xFFFFEA0D, 0x0000051C, 0x00001AFD, 0xFFFFF783, 0x00000328, 0x00001AFD, 0xFFFFF783, 0x00000328 }, - { 0x0213EA94DE161104, 0x00001B23, 0xFFFFF94B, 0x000002EB, 0x000015F1, 0xFFFFFB82, 0x000002B4, 0x000015F1, 0xFFFFFB82, 0x000002B4 }, - { 0x0213EA94DE323844, 0x000026AE, 0xFFFFF21A, 0x000003DB, 0x00001827, 0xFFFFFA10, 0x000002C8, 0x00001827, 0xFFFFFA10, 0x000002C8 }, - { 0x0213F0FD42CA4884, 0x00002DCF, 0xFFFFEBD8, 0x000004DB, 0x00001A75, 0xFFFFF719, 0x0000033A, 0x00001A75, 0xFFFFF719, 0x0000033A }, - { 0x0213F0FD42CE40E4, 0x00003983, 0xFFFFE500, 0x000005EA, 0x000022A6, 0xFFFFF25F, 0x000003F1, 0x000022A6, 0xFFFFF25F, 0x000003F1 }, - { 0x0213EA94DE1218C4, 0x00002AD5, 0xFFFFF07A, 0x00000406, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, - { 0x0213F0FD42CA39A4, 0x00002A43, 0xFFFFEE43, 0x00000474, 0x00001D65, 0xFFFFF538, 0x00000387, 0x00001D65, 0xFFFFF538, 0x00000387 }, - { 0x0213F0FD42C62084, 0x0000311E, 0xFFFFEAF8, 0x000004E8, 0x00001959, 0xFFFFF8E4, 0x000002DC, 0x00001959, 0xFFFFF8E4, 0x000002DC }, - { 0x0213F0FD42D031A4, 0x0000339A, 0xFFFFE8A7, 0x00000559, 0x00001A04, 0xFFFFF7E5, 0x00000311, 0x00001A04, 0xFFFFF7E5, 0x00000311 }, - { 0x0213EA94DE204144, 0x000021B3, 0xFFFFF50F, 0x00000389, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, - { 0x0213EA94DE021884, 0x00003417, 0xFFFFE9A6, 0x0000051D, 0x000018A4, 0xFFFFF984, 0x000002CF, 0x000018A4, 0xFFFFF984, 0x000002CF }, - { 0x0213EA94DE202984, 0x00001FED, 0xFFFFF6A2, 0x00000347, 0x00001639, 0xFFFFFB59, 0x000002BB, 0x00001639, 0xFFFFFB59, 0x000002BB }, - { 0x0213EA94DE1218A4, 0x000032D2, 0xFFFFEB18, 0x000004DC, 0x00001A01, 0xFFFFF95E, 0x000002CF, 0x00001A01, 0xFFFFF95E, 0x000002CF }, - { 0x0213F0FD42D04084, 0x00003147, 0xFFFFEA3B, 0x00000518, 0x0000241D, 0xFFFFF11C, 0x00000431, 0x0000241D, 0xFFFFF11C, 0x00000431 }, - { 0x0213EA94DE1C0904, 0x00001D44, 0xFFFFF7E7, 0x0000031A, 0x0000153F, 0xFFFFFBBC, 0x000002A9, 0x0000153F, 0xFFFFFBBC, 0x000002A9 }, - { 0x0213F0FD42CC4104, 0x00003690, 0xFFFFE6E3, 0x000005A4, 0x000018DE, 0xFFFFF908, 0x000002DD, 0x000018DE, 0xFFFFF908, 0x000002DD }, - { 0x0213F0FD42CC2184, 0x00003561, 0xFFFFE6F8, 0x000005AB, 0x000018B5, 0xFFFFF8A0, 0x000002F3, 0x000018B5, 0xFFFFF8A0, 0x000002F3 }, - { 0x0213EA94DE323124, 0x000028F4, 0xFFFFF23A, 0x000003CE, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, - { 0x0213F0FD42D03184, 0x000035D7, 0xFFFFE71C, 0x0000059B, 0x00001D49, 0xFFFFF5C8, 0x00000368, 0x00001D49, 0xFFFFF5C8, 0x00000368 }, - { 0x0213F0FD42CE18A4, 0x0000397E, 0xFFFFE4CB, 0x000005F4, 0x00001989, 0xFFFFF844, 0x000002FD, 0x00001989, 0xFFFFF844, 0x000002FD }, - { 0x0213F0FD42C62064, 0x00003BAB, 0xFFFFE332, 0x0000063F, 0x00001A69, 0xFFFFF7B9, 0x00000312, 0x00001A69, 0xFFFFF7B9, 0x00000312 }, - { 0x0213F0FD42D03064, 0x00002F26, 0xFFFFEB82, 0x000004E8, 0x00001D7D, 0xFFFFF590, 0x00000379, 0x00001D7D, 0xFFFFF590, 0x00000379 }, - { 0x0213EA94DE0631A4, 0x00002FDC, 0xFFFFEBE0, 0x000004C3, 0x00001940, 0xFFFFF8CC, 0x000002EE, 0x00001940, 0xFFFFF8CC, 0x000002EE }, - { 0x0213EA94DE1C08E4, 0x000021B2, 0xFFFFF558, 0x00000379, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, - { 0x0213EA94DE321904, 0x00002897, 0xFFFFF181, 0x000003F7, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, - { 0x0213EA94DE1E0924, 0x00001D19, 0xFFFFF829, 0x0000031A, 0x00001558, 0xFFFFFBCA, 0x000002AF, 0x00001558, 0xFFFFFBCA, 0x000002AF }, - { 0x0213EA94DE043144, 0x00003311, 0xFFFFEAD9, 0x000004E1, 0x00001BDC, 0xFFFFF79E, 0x0000031D, 0x00001BDC, 0xFFFFF79E, 0x0000031D }, - { 0x0213EA94DE1E29C4, 0x00001E54, 0xFFFFF740, 0x00000333, 0x000016A1, 0xFFFFFAF0, 0x000002C4, 0x000016A1, 0xFFFFFAF0, 0x000002C4 }, - { 0x0213F0FD42CE3964, 0x00003266, 0xFFFFE9A8, 0x00000527, 0x00002307, 0xFFFFF219, 0x000003FC, 0x00002307, 0xFFFFF219, 0x000003FC }, - { 0x0213EA94DE321144, 0x00001D1F, 0xFFFFF82B, 0x000002F0, 0x000013F0, 0xFFFFFD0B, 0x0000024E, 0x000013F0, 0xFFFFFD0B, 0x0000024E }, - { 0x0213F0FD42C648A4, 0x0000312E, 0xFFFFEA67, 0x00000502, 0x0000222A, 0xFFFFF253, 0x000003F9, 0x0000222A, 0xFFFFF253, 0x000003F9 }, - { 0x0213F0FD42CA4124, 0x000032B2, 0xFFFFE9AD, 0x00000523, 0x00001E97, 0xFFFFF527, 0x0000037F, 0x00001E97, 0xFFFFF527, 0x0000037F }, - { 0x0213EA94DE1640E4, 0x00001F6A, 0xFFFFF6FC, 0x00000338, 0x0000164B, 0xFFFFFB2C, 0x000002C2, 0x0000164B, 0xFFFFFB2C, 0x000002C2 }, - { 0x0213EA94DE0228C4, 0x00002603, 0xFFFFF386, 0x00000392, 0x00001EE0, 0xFFFFF601, 0x00000369, 0x00001EE0, 0xFFFFF601, 0x00000369 }, - { 0x0213EA94DE201164, 0x00001D0C, 0xFFFFF803, 0x00000317, 0x00001345, 0xFFFFFD52, 0x00000260, 0x00001345, 0xFFFFFD52, 0x00000260 }, - { 0x0213F0FD42CC1884, 0x0000327A, 0xFFFFE8E5, 0x0000055C, 0x00001680, 0xFFFFFA2D, 0x000002B2, 0x00001680, 0xFFFFFA2D, 0x000002B2 }, - { 0x0213F0FD42CA3964, 0x000032B8, 0xFFFFE91A, 0x0000054A, 0x00001BAB, 0xFFFFF6EC, 0x00000338, 0x00001BAB, 0xFFFFF6EC, 0x00000338 }, - { 0x0213F0FD42CC3044, 0x00002F79, 0xFFFFEB63, 0x000004EF, 0x000017BB, 0xFFFFF9B1, 0x000002CA, 0x000017BB, 0xFFFFF9B1, 0x000002CA }, - { 0x0213EA94DE0438E4, 0x00002AE5, 0xFFFFEFCB, 0x0000041D, 0x0000214A, 0xFFFFF3A7, 0x000003C7, 0x0000214A, 0xFFFFF3A7, 0x000003C7 }, - { 0x0213EA94DE322064, 0x0000212C, 0xFFFFF5BC, 0x0000034F, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, - { 0x0213EA94DE121124, 0x00002BE7, 0xFFFFEF40, 0x0000043C, 0x00001AE2, 0xFFFFF8CF, 0x000002E3, 0x00001AE2, 0xFFFFF8CF, 0x000002E3 }, - { 0x0213F0FD42D05144, 0x000032DC, 0xFFFFE90F, 0x00000549, 0x00002A2D, 0xFFFFECC9, 0x000004ED, 0x00002A2D, 0xFFFFECC9, 0x000004ED }, - { 0x0213EA94DE1618A4, 0x00001DE3, 0xFFFFF80D, 0x00000319, 0x000016FA, 0xFFFFFB42, 0x000002BC, 0x000016FA, 0xFFFFFB42, 0x000002BC }, - { 0x0213EA94DE1E2844, 0x00001F1B, 0xFFFFF6DE, 0x00000346, 0x00001502, 0xFFFFFC23, 0x00000298, 0x00001502, 0xFFFFFC23, 0x00000298 }, - { 0x0213EA94DE061864, 0x00003203, 0xFFFFEA87, 0x000004FE, 0x0000194E, 0xFFFFF8E3, 0x000002EC, 0x0000194E, 0xFFFFF8E3, 0x000002EC }, - { 0x0213F0FD42D02144, 0x0000337A, 0xFFFFE8DD, 0x00000551, 0x00001E3C, 0xFFFFF534, 0x00000385, 0x00001E3C, 0xFFFFF534, 0x00000385 }, - { 0x0213F0FD42CA4864, 0x000036F6, 0xFFFFE62A, 0x000005C5, 0x000023C0, 0xFFFFF117, 0x00000435, 0x000023C0, 0xFFFFF117, 0x00000435 }, - { 0x0213F0FD42CC2144, 0x00003125, 0xFFFFEA4E, 0x0000051A, 0x00001E6C, 0xFFFFF503, 0x0000038E, 0x00001E6C, 0xFFFFF503, 0x0000038E }, - { 0x0213EA94DE1C08A4, 0x00001CD4, 0xFFFFF82D, 0x0000030E, 0x0000156D, 0xFFFFFB64, 0x000002B8, 0x0000156D, 0xFFFFFB64, 0x000002B8 }, - { 0x0213EA94DE0240A4, 0x00002F14, 0xFFFFEC46, 0x000004B8, 0x000017F1, 0xFFFFF977, 0x000002D2, 0x000017F1, 0xFFFFF977, 0x000002D2 }, - { 0x0213EA94DE0640A4, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x0000184C, 0xFFFFF983, 0x000002D4, 0x0000184C, 0xFFFFF983, 0x000002D4 }, - { 0x0213F0FD42D04984, 0x00002EA9, 0xFFFFEBD7, 0x000004D5, 0x0000288D, 0xFFFFEDDB, 0x000004C0, 0x0000288D, 0xFFFFEDDB, 0x000004C0 }, - { 0x0213F0FD42CA3984, 0x0000335F, 0xFFFFE82C, 0x00000579, 0x00001DBF, 0xFFFFF512, 0x0000038C, 0x00001DBF, 0xFFFFF512, 0x0000038C }, - { 0x0213EA94DE201184, 0x0000224F, 0xFFFFF4B5, 0x00000391, 0x0000138C, 0xFFFFFCC3, 0x0000027A, 0x0000138C, 0xFFFFFCC3, 0x0000027A }, - { 0x0213EA94DE1240A4, 0x0000320D, 0xFFFFEACD, 0x000004F5, 0x00001976, 0xFFFFF913, 0x000002E2, 0x00001976, 0xFFFFF913, 0x000002E2 }, - { 0x0213EA94DE202104, 0x00001BEB, 0xFFFFF99C, 0x000002E4, 0x000016A4, 0xFFFFFB77, 0x000002C3, 0x000016A4, 0xFFFFFB77, 0x000002C3 }, - { 0x0213EA94DE063044, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x000018F4, 0xFFFFF91A, 0x000002E3, 0x000018F4, 0xFFFFF91A, 0x000002E3 }, - { 0x0213EA94DE022864, 0x00003251, 0xFFFFEA8E, 0x000004FA, 0x000018EF, 0xFFFFF910, 0x000002E4, 0x000018EF, 0xFFFFF910, 0x000002E4 }, - { 0x0213EA94DE1C1924, 0x00001DAF, 0xFFFFF857, 0x0000030D, 0x00001915, 0xFFFFF9D8, 0x000002F7, 0x00001915, 0xFFFFF9D8, 0x000002F7 }, - { 0x0213EA94DE2041A4, 0x000025B6, 0xFFFFF26B, 0x000003E5, 0x00001531, 0xFFFFFB68, 0x000002AF, 0x00001531, 0xFFFFFB68, 0x000002AF }, - { 0x0213EA94DE061884, 0x00002B2E, 0xFFFFEF2E, 0x00000440, 0x00001968, 0xFFFFF91A, 0x000002DF, 0x00001968, 0xFFFFF91A, 0x000002DF }, - { 0x0213EA94DE1C2064, 0x00002305, 0xFFFFF528, 0x00000377, 0x000018A4, 0xFFFFF9EB, 0x000002F0, 0x000018A4, 0xFFFFF9EB, 0x000002F0 }, - { 0x0213F0FD42CA40C4, 0x000032A1, 0xFFFFE992, 0x0000052E, 0x00001A55, 0xFFFFF826, 0x000002FE, 0x00001A55, 0xFFFFF826, 0x000002FE }, - { 0x0213EA94DE042184, 0x00002CCD, 0xFFFFEE35, 0x00000462, 0x00001B09, 0xFFFFF7E6, 0x0000030F, 0x00001B09, 0xFFFFF7E6, 0x0000030F }, - { 0x0213EA94DE323084, 0x00002602, 0xFFFFF2CF, 0x000003C5, 0x000016EE, 0xFFFFFAD4, 0x000002B4, 0x000016EE, 0xFFFFFAD4, 0x000002B4 }, - { 0x0213F0FD42D01964, 0x00003370, 0xFFFFE891, 0x00000560, 0x000017F0, 0xFFFFF930, 0x000002DF, 0x000017F0, 0xFFFFF930, 0x000002DF }, - { 0x0213F0FD42CA1884, 0x00002EDC, 0xFFFFEB6D, 0x000004EC, 0x000016E6, 0xFFFFF9ED, 0x000002BC, 0x000016E6, 0xFFFFF9ED, 0x000002BC }, - { 0x0213EA94DE1228C4, 0x00002A05, 0xFFFFF13D, 0x000003F0, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, - { 0x0213F0FD42CE2044, 0x00002F8A, 0xFFFFEB6E, 0x000004E4, 0x00001E3E, 0xFFFFF50E, 0x0000038D, 0x00001E3E, 0xFFFFF50E, 0x0000038D }, - { 0x0213F0FD42CA3044, 0x00002BB5, 0xFFFFED6A, 0x000004A1, 0x000017BF, 0xFFFFF937, 0x000002E5, 0x000017BF, 0xFFFFF937, 0x000002E5 }, - { 0x0213EA94DE201964, 0x0000202C, 0xFFFFF6CE, 0x0000033F, 0x000015EE, 0xFFFFFB83, 0x000002B9, 0x000015EE, 0xFFFFFB83, 0x000002B9 }, - { 0x0213EA94DE022884, 0x00002C0C, 0xFFFFEF10, 0x0000043F, 0x00001A73, 0xFFFFF83E, 0x0000030C, 0x00001A73, 0xFFFFF83E, 0x0000030C }, - { 0x0213EA94DE324104, 0x0000234F, 0xFFFFF460, 0x00000385, 0x000018C3, 0xFFFFF9A5, 0x000002DD, 0x000018C3, 0xFFFFF9A5, 0x000002DD }, - { 0x0213F0FD42CE1904, 0x00003679, 0xFFFFE704, 0x00000595, 0x00002177, 0xFFFFF31A, 0x000003D7, 0x00002177, 0xFFFFF31A, 0x000003D7 }, - { 0x0213F0FD42CA2924, 0x00003008, 0xFFFFEBB8, 0x000004D5, 0x000024FF, 0xFFFFF112, 0x00000430, 0x000024FF, 0xFFFFF112, 0x00000430 }, - { 0x0213F0FD42C641A4, 0x00003848, 0xFFFFE6A3, 0x00000594, 0x00002958, 0xFFFFEE37, 0x000004A0, 0x00002958, 0xFFFFEE37, 0x000004A0 }, - { 0x0213F0FD42CC1924, 0x00002FDF, 0xFFFFEB08, 0x000004FD, 0x00001D77, 0xFFFFF58B, 0x0000037A, 0x00001D77, 0xFFFFF58B, 0x0000037A }, - { 0x0213EA94DE063064, 0x00002EC8, 0xFFFFED41, 0x00000481, 0x00001949, 0xFFFFF91C, 0x000002DF, 0x00001949, 0xFFFFF91C, 0x000002DF }, - { 0x0213F0FD42D041A4, 0x000037C1, 0xFFFFE5BA, 0x000005D7, 0x0000252C, 0xFFFFF023, 0x00000460, 0x0000252C, 0xFFFFF023, 0x00000460 }, - { 0x0213F0FD42CE2944, 0x00003716, 0xFFFFE70C, 0x0000058A, 0x000028CC, 0xFFFFEE57, 0x0000049D, 0x000028CC, 0xFFFFEE57, 0x0000049D }, - { 0x0213F0FD42CA40E4, 0x000033D1, 0xFFFFE8E8, 0x00000547, 0x00001AB1, 0xFFFFF7E5, 0x00000309, 0x00001AB1, 0xFFFFF7E5, 0x00000309 }, - { 0x0213F0FD42CC2944, 0x00002D72, 0xFFFFED65, 0x0000048E, 0x00001E0D, 0xFFFFF5A7, 0x00000370, 0x00001E0D, 0xFFFFF5A7, 0x00000370 }, - { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, - { 0x0213EA94DE243044, 0x000026EE, 0xFFFFF18C, 0x000003F7, 0x000018A7, 0xFFFFF95A, 0x000002E5, 0x000018A7, 0xFFFFF95A, 0x000002E5 }, - { 0x0213EA94DE042164, 0x00002F62, 0xFFFFEC9B, 0x000004A4, 0x0000194E, 0xFFFFF932, 0x000002D9, 0x0000194E, 0xFFFFF932, 0x000002D9 }, - { 0x0213EA94DE1E3984, 0x00001CE8, 0xFFFFF7FA, 0x0000031C, 0x000014CE, 0xFFFFFBD4, 0x000002AB, 0x000014CE, 0xFFFFFBD4, 0x000002AB }, - { 0x0213EA94DE1210E4, 0x00002E5A, 0xFFFFEDAB, 0x0000047C, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, - { 0x0213F0FD42CC30E4, 0x00003057, 0xFFFFEC34, 0x000004B9, 0x00002296, 0xFFFFF342, 0x000003D0, 0x00002296, 0xFFFFF342, 0x000003D0 }, - { 0x0213EA94DE0418A4, 0x00002B0F, 0xFFFFEF58, 0x00000434, 0x00001BFD, 0xFFFFF721, 0x00000330, 0x00001BFD, 0xFFFFF721, 0x00000330 }, - { 0x0213EA94DE2010A4, 0x00001F01, 0xFFFFF751, 0x0000032F, 0x00001502, 0xFFFFFC3E, 0x00000296, 0x00001502, 0xFFFFFC3E, 0x00000296 }, - { 0x0213F0FD42CA3064, 0x00002FF4, 0xFFFFEAE2, 0x00000503, 0x00001B36, 0xFFFFF736, 0x00000330, 0x00001B36, 0xFFFFF736, 0x00000330 }, - { 0x0213F0FD42CE2064, 0x00003762, 0xFFFFE5AB, 0x000005DE, 0x000018CB, 0xFFFFF896, 0x000002F4, 0x000018CB, 0xFFFFF896, 0x000002F4 }, - { 0x0213F0FD42CC2064, 0x00002890, 0xFFFFEF92, 0x00000445, 0x0000191D, 0xFFFFF86F, 0x00000302, 0x0000191D, 0xFFFFF86F, 0x00000302 }, - { 0x0213EA94DE043064, 0x00002F76, 0xFFFFEC0E, 0x000004BF, 0x00001F7D, 0xFFFFF41A, 0x000003C0, 0x00001F7D, 0xFFFFF41A, 0x000003C0 }, - { 0x0213EA94DE1E08A4, 0x00001D55, 0xFFFFF7F8, 0x0000031E, 0x000015DF, 0xFFFFFB79, 0x000002B7, 0x000015DF, 0xFFFFFB79, 0x000002B7 }, - { 0x0213EA94DE204924, 0x00001FE9, 0xFFFFF64A, 0x00000353, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, - { 0x0213EA94DE063964, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001857, 0xFFFFF968, 0x000002D8, 0x00001857, 0xFFFFF968, 0x000002D8 }, - { 0x0213F0FD42CA28C4, 0x00003398, 0xFFFFE9A3, 0x00000524, 0x00001FF9, 0xFFFFF458, 0x000003AD, 0x00001FF9, 0xFFFFF458, 0x000003AD }, - { 0x0213F0FD42CE2964, 0x00003897, 0xFFFFE5BD, 0x000005C8, 0x00002519, 0xFFFFF0BA, 0x00000438, 0x00002519, 0xFFFFF0BA, 0x00000438 }, - { 0x0213F0FD42D04064, 0x00003234, 0xFFFFE9B1, 0x00000530, 0x000022CC, 0xFFFFF20E, 0x00000409, 0x000022CC, 0xFFFFF20E, 0x00000409 }, - { 0x0213EA94DE205104, 0x00001FD2, 0xFFFFF641, 0x00000354, 0x000017C9, 0xFFFFF9C0, 0x000002FB, 0x000017C9, 0xFFFFF9C0, 0x000002FB }, - { 0x0213F0FD42CE48E4, 0x00003234, 0xFFFFE946, 0x0000053D, 0x00002267, 0xFFFFF1F5, 0x0000040D, 0x00002267, 0xFFFFF1F5, 0x0000040D }, - { 0x0213EA94DE2029A4, 0x00002330, 0xFFFFF474, 0x00000399, 0x00001490, 0xFFFFFC67, 0x00000288, 0x00001490, 0xFFFFFC67, 0x00000288 }, - { 0x0213F0FD42D03924, 0x000032A3, 0xFFFFE9EB, 0x0000051B, 0x0000234D, 0xFFFFF23C, 0x000003F7, 0x0000234D, 0xFFFFF23C, 0x000003F7 }, - { 0x0213EA94DE200904, 0x0000217E, 0xFFFFF53A, 0x00000384, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, - { 0x0213F0FD42CE50E4, 0x0000384F, 0xFFFFE562, 0x000005E2, 0x0000295A, 0xFFFFED53, 0x000004D3, 0x0000295A, 0xFFFFED53, 0x000004D3 }, - { 0x0213F0FD42D05124, 0x00003315, 0xFFFFE8D1, 0x00000552, 0x000025D1, 0xFFFFEFAF, 0x00000471, 0x000025D1, 0xFFFFEFAF, 0x00000471 }, - { 0x0213F0FD42C64924, 0x00004183, 0xFFFFDF61, 0x000006DA, 0x0000193C, 0xFFFFF88F, 0x000002EC, 0x0000193C, 0xFFFFF88F, 0x000002EC }, - { 0x0213EA94DE242164, 0x00002DFC, 0xFFFFEDF2, 0x0000047A, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, - { 0x0213F0FD42CA31A4, 0x000033FE, 0xFFFFE774, 0x0000059F, 0x00001E70, 0xFFFFF492, 0x000003A0, 0x00001E70, 0xFFFFF492, 0x000003A0 }, - { 0x0213F0FD42C629A4, 0x000040D7, 0xFFFFDFB8, 0x000006CE, 0x00001AC8, 0xFFFFF773, 0x0000031D, 0x00001AC8, 0xFFFFF773, 0x0000031D }, - { 0x0213EA94DE1E1164, 0x00001D02, 0xFFFFF803, 0x00000322, 0x000015FE, 0xFFFFFB71, 0x000002BB, 0x000015FE, 0xFFFFFB71, 0x000002BB }, - { 0x0213F0FD42D02884, 0x00002EB0, 0xFFFFEC31, 0x000004C4, 0x00001B3C, 0xFFFFF73B, 0x00000330, 0x00001B3C, 0xFFFFF73B, 0x00000330 }, - { 0x0213F0FD42CA4984, 0x00002D9F, 0xFFFFECBF, 0x000004A8, 0x000022B0, 0xFFFFF23C, 0x000003F9, 0x000022B0, 0xFFFFF23C, 0x000003F9 }, - { 0x0213F0FD42CC18E4, 0x00002C6A, 0xFFFFEDAC, 0x00000488, 0x00002419, 0xFFFFF159, 0x00000427, 0x00002419, 0xFFFFF159, 0x00000427 }, - { 0x0213EA94DE1210A4, 0x00002991, 0xFFFFF06C, 0x0000040E, 0x00001AA9, 0xFFFFF8D0, 0x000002E1, 0x00001AA9, 0xFFFFF8D0, 0x000002E1 }, - { 0x0213EA94DE123904, 0x00002F8E, 0xFFFFED1B, 0x00000493, 0x00001DE4, 0xFFFFF69C, 0x00000347, 0x00001DE4, 0xFFFFF69C, 0x00000347 }, - { 0x0213EA94DE204184, 0x00002136, 0xFFFFF540, 0x0000037C, 0x000014FF, 0xFFFFFB83, 0x000002B2, 0x000014FF, 0xFFFFFB83, 0x000002B2 }, - { 0x0213EA94DE0618E4, 0x0000354C, 0xFFFFE97D, 0x0000051A, 0x00001906, 0xFFFFF965, 0x000002DD, 0x00001906, 0xFFFFF965, 0x000002DD }, - { 0x0213F0FD42C620C4, 0x0000348B, 0xFFFFE94D, 0x0000051F, 0x0000285B, 0xFFFFEF1A, 0x00000473, 0x0000285B, 0xFFFFEF1A, 0x00000473 }, - { 0x0213EA94DE3218A4, 0x000026E6, 0xFFFFF24E, 0x000003D6, 0x0000141F, 0xFFFFFCCE, 0x00000260, 0x0000141F, 0xFFFFFCCE, 0x00000260 }, - { 0x0213F0FD42C64164, 0x00003CED, 0xFFFFE2A5, 0x0000064E, 0x00002060, 0xFFFFF3E0, 0x000003B0, 0x00002060, 0xFFFFF3E0, 0x000003B0 }, - { 0x0213EA94DE021084, 0x000029D4, 0xFFFFEFF7, 0x00000426, 0x00001976, 0xFFFFF8E1, 0x000002EE, 0x00001976, 0xFFFFF8E1, 0x000002EE }, - { 0x0213F0FD42CA40A4, 0x00003767, 0xFFFFE601, 0x000005CC, 0x00001D22, 0xFFFFF5F4, 0x00000361, 0x00001D22, 0xFFFFF5F4, 0x00000361 }, - { 0x0213F0FD42C650C4, 0x00003CE8, 0xFFFFE2E8, 0x00000637, 0x0000232C, 0xFFFFF1E7, 0x00000405, 0x0000232C, 0xFFFFF1E7, 0x00000405 }, - { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, - { 0x0213F0FD42CC30A4, 0x00003451, 0xFFFFE8B9, 0x00000551, 0x00001AD7, 0xFFFFF7BF, 0x00000318, 0x00001AD7, 0xFFFFF7BF, 0x00000318 }, - { 0x0213F0FD42CE2984, 0x0000381B, 0xFFFFE5A0, 0x000005D0, 0x00001E0F, 0xFFFFF521, 0x00000382, 0x00001E0F, 0xFFFFF521, 0x00000382 }, - { 0x0213EA94DE2038C4, 0x000023A4, 0xFFFFF4A6, 0x00000394, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, - { 0x0213F0FD42C620A4, 0x00003C2B, 0xFFFFE447, 0x000005F0, 0x0000207F, 0xFFFFF44E, 0x0000039A, 0x0000207F, 0xFFFFF44E, 0x0000039A }, - { 0x0213F0FD42CC3984, 0x00002F07, 0xFFFFEB70, 0x000004E9, 0x00001765, 0xFFFFF9A5, 0x000002C6, 0x00001765, 0xFFFFF9A5, 0x000002C6 }, - { 0x0213F0FD42C62984, 0x00003A01, 0xFFFFE4E0, 0x000005E7, 0x0000227A, 0xFFFFF292, 0x000003E5, 0x0000227A, 0xFFFFF292, 0x000003E5 }, - { 0x0213F0FD42CE20A4, 0x0000376E, 0xFFFFE686, 0x000005A6, 0x00001FCF, 0xFFFFF43B, 0x000003A8, 0x00001FCF, 0xFFFFF43B, 0x000003A8 }, - { 0x0213F0FFEF5A4984, 0x0000485F, 0xFFFFDCC1, 0x00000713, 0x00002CF8, 0xFFFFEC45, 0x000004DA, 0x00002CF8, 0xFFFFEC45, 0x000004DA }, - { 0x0213F0FFEF5C3184, 0x0000331C, 0xFFFFE8FF, 0x00000541, 0x00002366, 0xFFFFF19D, 0x00000411, 0x00002366, 0xFFFFF19D, 0x00000411 }, - { 0x0213F0FFEF643864, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002FB3, 0xFFFFE827, 0x000005B9, 0x00002FB3, 0xFFFFE827, 0x000005B9 }, - { 0x0213EA94DE321104, 0x000023F3, 0xFFFFF3EA, 0x0000039A, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, - { 0x0213F0FFEF5C28A4, 0x000038C0, 0xFFFFE58A, 0x000005CC, 0x000023CA, 0xFFFFF1AA, 0x00000408, 0x000023CA, 0xFFFFF1AA, 0x00000408 }, - { 0x0213F0FFEF662944, 0x00004976, 0xFFFFDD6A, 0x000006D7, 0x000033C6, 0xFFFFE8EB, 0x0000054D, 0x000033C6, 0xFFFFE8EB, 0x0000054D }, - { 0x0213F0FFEF644904, 0x00004049, 0xFFFFDF6D, 0x000006D8, 0x00003129, 0xFFFFE716, 0x000005E9, 0x00003129, 0xFFFFE716, 0x000005E9 }, - { 0x0213F0FFEF661164, 0x000046C2, 0xFFFFDCEB, 0x0000071C, 0x00002E6D, 0xFFFFEA8F, 0x0000052E, 0x00002E6D, 0xFFFFEA8F, 0x0000052E }, - { 0x0213F0FFEF6238A4, 0x00004080, 0xFFFFE1E1, 0x0000063A, 0x0000396D, 0xFFFFE40A, 0x0000062C, 0x0000396D, 0xFFFFE40A, 0x0000062C }, - { 0x0213F0FFEF5E2124, 0x00003DE0, 0xFFFFE358, 0x0000060C, 0x00002AA2, 0xFFFFEDBF, 0x000004A0, 0x00002AA2, 0xFFFFEDBF, 0x000004A0 }, - { 0x0213F0FFEF5E3144, 0x00003FC0, 0xFFFFE2A1, 0x0000061A, 0x000027D8, 0xFFFFEFEC, 0x0000043A, 0x000027D8, 0xFFFFEFEC, 0x0000043A }, - { 0x0213F0FFEF661924, 0x00003FBF, 0xFFFFE2F5, 0x00000603, 0x000032D7, 0xFFFFE900, 0x00000552, 0x000032D7, 0xFFFFE900, 0x00000552 }, - { 0x0213F0FFEF5C10E4, 0x000035EE, 0xFFFFE6CA, 0x000005A2, 0x0000247C, 0xFFFFF088, 0x00000446, 0x0000247C, 0xFFFFF088, 0x00000446 }, - { 0x0213F0FFEF643884, 0x000039C8, 0xFFFFE3AE, 0x0000062A, 0x000028AF, 0xFFFFED24, 0x000004DF, 0x000028AF, 0xFFFFED24, 0x000004DF }, - { 0x0213F0FFEF5C2884, 0x00003BDE, 0xFFFFE33B, 0x00000632, 0x00001B6C, 0xFFFFF720, 0x00000326, 0x00001B6C, 0xFFFFF720, 0x00000326 }, - { 0x0213F0FFEF7210A4, 0x00003818, 0xFFFFE57D, 0x000005D4, 0x000020EF, 0xFFFFF327, 0x000003CE, 0x000020EF, 0xFFFFF327, 0x000003CE }, - { 0x0213F0FFEF5E19A4, 0x000038DA, 0xFFFFE561, 0x000005D3, 0x0000297D, 0xFFFFED6D, 0x000004C5, 0x0000297D, 0xFFFFED6D, 0x000004C5 }, - { 0x0213F0FFEF684884, 0x000027AC, 0xFFFFF0CE, 0x00000417, 0x00001F5F, 0xFFFFF484, 0x000003B2, 0x00001F5F, 0xFFFFF484, 0x000003B2 }, - { 0x0213F0FFEF6648A4, 0x00003F02, 0xFFFFE222, 0x00000643, 0x000026D4, 0xFFFFF000, 0x00000443, 0x000026D4, 0xFFFFF000, 0x00000443 }, - { 0x0213F0FFEF624164, 0x00004303, 0xFFFFDFE3, 0x00000690, 0x0000312C, 0xFFFFE912, 0x00000561, 0x0000312C, 0xFFFFE912, 0x00000561 }, - { 0x0213F0FFEF600904, 0x000039E5, 0xFFFFE31F, 0x00000657, 0x00001D23, 0xFFFFF51F, 0x00000386, 0x00001D23, 0xFFFFF51F, 0x00000386 }, - { 0x0213F0FFEF661144, 0x000041FA, 0xFFFFE01B, 0x00000697, 0x00002767, 0xFFFFEF90, 0x00000455, 0x00002767, 0xFFFFEF90, 0x00000455 }, - { 0x0213F0FFEF6830A4, 0x00002888, 0xFFFFF11C, 0x00000403, 0x00001864, 0xFFFFF9D8, 0x000002D3, 0x00001864, 0xFFFFF9D8, 0x000002D3 }, - { 0x0213EA94DE201864, 0x0000215C, 0xFFFFF5B6, 0x0000036D, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, - { 0x0213F0FFEF683984, 0x00002FAF, 0xFFFFEC27, 0x000004CA, 0x00002184, 0xFFFFF39C, 0x000003CD, 0x00002184, 0xFFFFF39C, 0x000003CD }, - { 0x0213F0FFEF5E10C4, 0x00004ACE, 0xFFFFD9A3, 0x000007BC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC }, - { 0x0213F0FFEF5A3044, 0x00003763, 0xFFFFE797, 0x0000055F, 0x000029B5, 0xFFFFEEA1, 0x00000474, 0x000029B5, 0xFFFFEEA1, 0x00000474 }, - { 0x0213F0FFEF5E3164, 0x00003832, 0xFFFFE6F9, 0x00000575, 0x00002C99, 0xFFFFEC42, 0x000004E3, 0x00002C99, 0xFFFFEC42, 0x000004E3 }, - { 0x0213F0FFEF604164, 0x000041C9, 0xFFFFDE33, 0x0000071E, 0x0000199D, 0xFFFFF808, 0x000002F9, 0x0000199D, 0xFFFFF808, 0x000002F9 }, - { 0x0213F0FFEF641164, 0x0000474A, 0xFFFFD96E, 0x00000802, 0x00002A30, 0xFFFFEB57, 0x0000053F, 0x00002A30, 0xFFFFEB57, 0x0000053F }, - { 0x0213F0FFEF5C31C4, 0x0000312F, 0xFFFFEA6A, 0x00000508, 0x000029D3, 0xFFFFED38, 0x000004D3, 0x000029D3, 0xFFFFED38, 0x000004D3 }, - { 0x0213F0FFEF7210C4, 0x00003BD6, 0xFFFFE2E7, 0x00000644, 0x00002093, 0xFFFFF37B, 0x000003BD, 0x00002093, 0xFFFFF37B, 0x000003BD }, - { 0x0213F0FFEF6840E4, 0x00002F94, 0xFFFFECD4, 0x000004A3, 0x00002196, 0xFFFFF40B, 0x000003B5, 0x00002196, 0xFFFFF40B, 0x000003B5 }, - { 0x0213F0FFEF5E1944, 0x0000369B, 0xFFFFE762, 0x00000571, 0x00002726, 0xFFFFEF99, 0x00000459, 0x00002726, 0xFFFFEF99, 0x00000459 }, - { 0x0213F0FFEF642064, 0x00003F57, 0xFFFFDF47, 0x000006F4, 0x00002E5F, 0xFFFFE8AE, 0x000005AB, 0x00002E5F, 0xFFFFE8AE, 0x000005AB }, - { 0x0213EA94DE0A40C4, 0x00004313, 0xFFFFDD81, 0x0000072D, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, - { 0x0213F0FFEF683044, 0x00002A35, 0xFFFFEFA8, 0x00000441, 0x00001F3F, 0xFFFFF4F3, 0x000003A0, 0x00001F3F, 0xFFFFF4F3, 0x000003A0 }, - { 0x0213F0FFEF6630A4, 0x00003E33, 0xFFFFE4B0, 0x000005AF, 0x00002802, 0xFFFFF092, 0x00000412, 0x00002802, 0xFFFFF092, 0x00000412 }, - { 0x0213EA94DE323904, 0x00002815, 0xFFFFF20E, 0x000003DD, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, - { 0x0213F0FFEF5A2184, 0x00003CC2, 0xFFFFE43E, 0x000005DE, 0x00002C16, 0xFFFFECED, 0x000004BA, 0x00002C16, 0xFFFFECED, 0x000004BA }, - { 0x0213F0FFEF5C4084, 0x00003CFA, 0xFFFFE1EE, 0x00000673, 0x00001F7D, 0xFFFFF402, 0x000003AE, 0x00001F7D, 0xFFFFF402, 0x000003AE }, - { 0x0213F0FFEF622104, 0x0000486E, 0xFFFFDD43, 0x000006EE, 0x000036F0, 0xFFFFE609, 0x000005D5, 0x000036F0, 0xFFFFE609, 0x000005D5 }, - { 0x0213F0FFEF5C4964, 0x000039FE, 0xFFFFE41F, 0x00000613, 0x0000266C, 0xFFFFEF35, 0x0000047D, 0x0000266C, 0xFFFFEF35, 0x0000047D }, - { 0x0213EA94DE123124, 0x00002EA4, 0xFFFFEE3B, 0x00000462, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, - { 0x0213F0FFEF683944, 0x00002D2E, 0xFFFFEE7B, 0x00000462, 0x0000229D, 0xFFFFF363, 0x000003D4, 0x0000229D, 0xFFFFF363, 0x000003D4 }, - { 0x0213F0FFEF5E2844, 0x0000375C, 0xFFFFE695, 0x0000059D, 0x00002319, 0xFFFFF237, 0x000003EE, 0x00002319, 0xFFFFF237, 0x000003EE }, - { 0x0213F0FFEF7250C4, 0x00004522, 0xFFFFDC71, 0x0000075E, 0x0000247E, 0xFFFFF0A0, 0x0000043C, 0x0000247E, 0xFFFFF0A0, 0x0000043C }, - { 0x0213EA94DE1248E4, 0x00002E58, 0xFFFFECB9, 0x000004A9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, - { 0x0213F0FFEF6438E4, 0x00003791, 0xFFFFE5FE, 0x000005B6, 0x000029F5, 0xFFFFED0D, 0x000004CD, 0x000029F5, 0xFFFFED0D, 0x000004CD }, - { 0x0213EA94DE244144, 0x00002E9E, 0xFFFFEC8D, 0x000004C1, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, - { 0x0213EA94DE203964, 0x0000237C, 0xFFFFF435, 0x000003A6, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, - { 0x0213F0FFEF662924, 0x00003FE5, 0xFFFFE4A2, 0x000005A0, 0x00003416, 0xFFFFE995, 0x00000523, 0x00003416, 0xFFFFE995, 0x00000523 }, - { 0x0213F0FFEF5C0924, 0x00002B27, 0xFFFFED51, 0x000004A5, 0x000025D1, 0xFFFFEF18, 0x00000492, 0x000025D1, 0xFFFFEF18, 0x00000492 }, - { 0x0213F0FFEF684904, 0x00002D77, 0xFFFFED79, 0x00000494, 0x00002196, 0xFFFFF352, 0x000003DE, 0x00002196, 0xFFFFF352, 0x000003DE }, - { 0x0213F0FFEF5C20C4, 0x00003750, 0xFFFFE6AC, 0x00000596, 0x00002524, 0xFFFFF0B5, 0x00000431, 0x00002524, 0xFFFFF0B5, 0x00000431 }, - { 0x0213EA94DE122944, 0x00002896, 0xFFFFF1BB, 0x000003D9, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, - { 0x0213F0FFEF641984, 0x00003CA7, 0xFFFFE0F7, 0x000006B1, 0x00002CB8, 0xFFFFE9AB, 0x00000587, 0x00002CB8, 0xFFFFE9AB, 0x00000587 }, - { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, - { 0x0213F0FFEF662164, 0x00003914, 0xFFFFE683, 0x00000586, 0x00003120, 0xFFFFE9A6, 0x00000543, 0x00003120, 0xFFFFE9A6, 0x00000543 }, - { 0x0213F0FFEF643904, 0x000040D0, 0xFFFFE007, 0x000006AC, 0x00002B9E, 0xFFFFEBF5, 0x000004FB, 0x00002B9E, 0xFFFFEBF5, 0x000004FB }, - { 0x0213F0FFEF5A4884, 0x00004412, 0xFFFFDF5F, 0x000006A9, 0x00002A9E, 0xFFFFEDCE, 0x00000498, 0x00002A9E, 0xFFFFEDCE, 0x00000498 }, - { 0x0213F0FFEF624884, 0x000042A6, 0xFFFFDFEF, 0x00000696, 0x00002E65, 0xFFFFEAAE, 0x00000529, 0x00002E65, 0xFFFFEAAE, 0x00000529 }, - { 0x0213EA94DE322124, 0x000022E8, 0xFFFFF565, 0x0000035F, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, - { 0x0213F0FFEF6239A4, 0x00004637, 0xFFFFDDD8, 0x000006E9, 0x0000349D, 0xFFFFE6C8, 0x000005C7, 0x0000349D, 0xFFFFE6C8, 0x000005C7 }, - { 0x0213EA94DE263904, 0x00004686, 0xFFFFDC58, 0x0000073D, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, - { 0x0213F0FFEF6808E4, 0x00002B35, 0xFFFFEE9C, 0x0000046C, 0x00001F5B, 0xFFFFF4A3, 0x000003A9, 0x00001F5B, 0xFFFFF4A3, 0x000003A9 }, - { 0x0213F0FFEF724144, 0x00003AC9, 0xFFFFE3B2, 0x0000061B, 0x000023A1, 0xFFFFF170, 0x0000040F, 0x000023A1, 0xFFFFF170, 0x0000040F }, - { 0x0213F0FFEF5E1884, 0x00003C50, 0xFFFFE37E, 0x00000617, 0x0000218F, 0xFFFFF339, 0x000003C4, 0x0000218F, 0xFFFFF339, 0x000003C4 }, - { 0x0213F0FFEF663044, 0x00003793, 0xFFFFE761, 0x0000055D, 0x000029C7, 0xFFFFEE03, 0x00000496, 0x000029C7, 0xFFFFEE03, 0x00000496 }, - { 0x0213F0FFEF6438A4, 0x000040B5, 0xFFFFDF78, 0x000006DA, 0x00002DED, 0xFFFFEA20, 0x00000551, 0x00002DED, 0xFFFFEA20, 0x00000551 }, - { 0x0213F0FFEF601144, 0x000039D6, 0xFFFFE37D, 0x0000063C, 0x00001AED, 0xFFFFF6E2, 0x00000331, 0x00001AED, 0xFFFFF6E2, 0x00000331 }, - { 0x0213F0FFEF662144, 0x0000431F, 0xFFFFE09B, 0x0000066A, 0x00002BDF, 0xFFFFED93, 0x00000496, 0x00002BDF, 0xFFFFED93, 0x00000496 }, - { 0x0213F0FFEF623864, 0x00004887, 0xFFFFDC65, 0x00000721, 0x00003669, 0xFFFFE5C4, 0x000005E9, 0x00003669, 0xFFFFE5C4, 0x000005E9 }, - { 0x0213F0FFEF640924, 0x00004120, 0xFFFFDDAE, 0x00000748, 0x0000303B, 0xFFFFE70D, 0x000005FC, 0x0000303B, 0xFFFFE70D, 0x000005FC }, - { 0x0213F0FFEF5E28A4, 0x0000415D, 0xFFFFE0BE, 0x0000067B, 0x00002FA7, 0xFFFFEA28, 0x00000538, 0x00002FA7, 0xFFFFEA28, 0x00000538 }, - { 0x0213F0FFEF681904, 0x00002B12, 0xFFFFEFF9, 0x00000428, 0x00001DDA, 0xFFFFF693, 0x00000356, 0x00001DDA, 0xFFFFF693, 0x00000356 }, - { 0x0213F0FFEF5E3184, 0x00003ED3, 0xFFFFE28D, 0x0000062D, 0x00002B00, 0xFFFFED4E, 0x000004B3, 0x00002B00, 0xFFFFED4E, 0x000004B3 }, - { 0x0213F0FFEF6250A4, 0x00004218, 0xFFFFE039, 0x0000068F, 0x00002F84, 0xFFFFEA0C, 0x00000541, 0x00002F84, 0xFFFFEA0C, 0x00000541 }, - { 0x0213F0FFEF5A3844, 0x00003FF5, 0xFFFFE2A3, 0x00000617, 0x00003017, 0xFFFFEA7A, 0x00000520, 0x00003017, 0xFFFFEA7A, 0x00000520 }, - { 0x0213F0FFEF5A08A4, 0x00004304, 0xFFFFDFCC, 0x0000069E, 0x00002E0C, 0xFFFFEB51, 0x00000505, 0x00002E0C, 0xFFFFEB51, 0x00000505 }, - { 0x0213F0FFEF641944, 0x00003D3A, 0xFFFFE17F, 0x00000687, 0x0000284C, 0xFFFFED83, 0x000004CD, 0x0000284C, 0xFFFFED83, 0x000004CD }, - { 0x0213F0FFEF5E40A4, 0x000042F5, 0xFFFFDF76, 0x000006B2, 0x000027B6, 0xFFFFEF72, 0x00000455, 0x000027B6, 0xFFFFEF72, 0x00000455 }, - { 0x0213F0FFEF5C38C4, 0x00004267, 0xFFFFDF29, 0x000006D5, 0x0000298F, 0xFFFFEDBD, 0x000004AC, 0x0000298F, 0xFFFFEDBD, 0x000004AC }, - { 0x0213EA94DE240924, 0x0000303E, 0xFFFFEC00, 0x000004CB, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, - { 0x0213F0FFEF5E28C4, 0x00003127, 0xFFFFEBDB, 0x000004A6, 0x00002E95, 0xFFFFEB78, 0x000004F3, 0x00002E95, 0xFFFFEB78, 0x000004F3 }, - { 0x0213EA94DE1C1064, 0x00002655, 0xFFFFF2D9, 0x000003CF, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, - { 0x0213EA94DE164084, 0x00002372, 0xFFFFF449, 0x0000039B, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, - { 0x0213F0FFEF6628C4, 0x0000348E, 0xFFFFEB20, 0x000004B2, 0x00002BE8, 0xFFFFEE80, 0x00000467, 0x00002BE8, 0xFFFFEE80, 0x00000467 }, - { 0x0213F0FFEF5E1104, 0x00004092, 0xFFFFE073, 0x0000069B, 0x00002061, 0xFFFFF403, 0x000003A0, 0x00002061, 0xFFFFF403, 0x000003A0 }, - { 0x0213F0FFEF7220E4, 0x000039D1, 0xFFFFE55D, 0x000005CC, 0x000025CB, 0xFFFFF0C0, 0x00000428, 0x000025CB, 0xFFFFF0C0, 0x00000428 }, - { 0x0213F0FFEF5E4884, 0x000042AA, 0xFFFFDF68, 0x000006C2, 0x0000290B, 0xFFFFEE78, 0x00000485, 0x0000290B, 0xFFFFEE78, 0x00000485 }, - { 0x0213F0FFEF7218C4, 0x0000356F, 0xFFFFE7AC, 0x0000056E, 0x00001BE8, 0xFFFFF6E3, 0x0000032A, 0x00001BE8, 0xFFFFF6E3, 0x0000032A }, - { 0x0213F0FFEF5E1144, 0x00003525, 0xFFFFE7FF, 0x0000055D, 0x0000242C, 0xFFFFF12E, 0x0000041D, 0x0000242C, 0xFFFFF12E, 0x0000041D }, - { 0x0213F0FFEF5C48C4, 0x00003360, 0xFFFFE895, 0x00000550, 0x00002175, 0xFFFFF29E, 0x000003E9, 0x00002175, 0xFFFFF29E, 0x000003E9 }, - { 0x0213F0FFEF6440A4, 0x00003C94, 0xFFFFE1C4, 0x0000067E, 0x00002E28, 0xFFFFE964, 0x0000057F, 0x00002E28, 0xFFFFE964, 0x0000057F }, - { 0x0213F0FFEF724124, 0x0000431C, 0xFFFFDE4B, 0x000006FF, 0x00002270, 0xFFFFF268, 0x000003E5, 0x00002270, 0xFFFFF268, 0x000003E5 }, - { 0x0213EA94DE1218C4, 0x00002B67, 0xFFFFF01D, 0x00000414, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, - { 0x0213F0FFEF5E3984, 0x0000400B, 0xFFFFE13D, 0x0000066F, 0x000024F3, 0xFFFFF125, 0x00000417, 0x000024F3, 0xFFFFF125, 0x00000417 }, - { 0x0213F0FFEF5A20A4, 0x00004460, 0xFFFFE00E, 0x0000067B, 0x000023DF, 0xFFFFF2E6, 0x000003BB, 0x000023DF, 0xFFFFF2E6, 0x000003BB }, - { 0x0213F0FFEF641864, 0x00003AFB, 0xFFFFE2C5, 0x00000650, 0x00002D46, 0xFFFFE9C4, 0x00000571, 0x00002D46, 0xFFFFE9C4, 0x00000571 }, - { 0x0213F0FFEF622924, 0x00005482, 0xFFFFD5BC, 0x0000081A, 0x00003250, 0xFFFFE961, 0x00000541, 0x00003250, 0xFFFFE961, 0x00000541 }, - { 0x0213F0FFEF5C2944, 0x00003D27, 0xFFFFE2FA, 0x00000632, 0x00002A4D, 0xFFFFED6A, 0x000004BB, 0x00002A4D, 0xFFFFED6A, 0x000004BB }, - { 0x0213F0FFEF6018A4, 0x00003E03, 0xFFFFE142, 0x00000690, 0x00001E08, 0xFFFFF555, 0x0000036C, 0x00001E08, 0xFFFFF555, 0x0000036C }, - { 0x0213F0FFEF5C2064, 0x000031B5, 0xFFFFE97D, 0x00000535, 0x0000232E, 0xFFFFF166, 0x00000422, 0x0000232E, 0xFFFFF166, 0x00000422 }, - { 0x0213F0FFEF5E18E4, 0x00003753, 0xFFFFE724, 0x00000575, 0x0000281A, 0xFFFFEF1A, 0x0000046B, 0x0000281A, 0xFFFFEF1A, 0x0000046B }, - { 0x0213EA94DE204144, 0x00002071, 0xFFFFF5C9, 0x0000036F, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, - { 0x0213F0FFEF683144, 0x00002799, 0xFFFFF223, 0x000003CF, 0x00001CD3, 0xFFFFF74A, 0x00000333, 0x00001CD3, 0xFFFFF74A, 0x00000333 }, - { 0x0213F0FFEF6610C4, 0x000040DF, 0xFFFFE11C, 0x00000664, 0x000031D4, 0xFFFFE8BC, 0x0000056F, 0x000031D4, 0xFFFFE8BC, 0x0000056F }, - { 0x0213F0FFEF6440C4, 0x00003A4D, 0xFFFFE3A6, 0x00000627, 0x00002871, 0xFFFFEDA0, 0x000004C0, 0x00002871, 0xFFFFEDA0, 0x000004C0 }, - { 0x0213F0FFEF681984, 0x00002AF9, 0xFFFFEED7, 0x00000464, 0x0000219B, 0xFFFFF368, 0x000003D6, 0x0000219B, 0xFFFFF368, 0x000003D6 }, - { 0x0213EA94DE323124, 0x000026D5, 0xFFFFF36C, 0x000003A3, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, - { 0x0213F0FFEF5E2044, 0x0000325D, 0xFFFFEA07, 0x0000050B, 0x000026D1, 0xFFFFEFB3, 0x0000045A, 0x000026D1, 0xFFFFEFB3, 0x0000045A }, - { 0x0213F0FFEF682864, 0x00002F75, 0xFFFFEC64, 0x000004BE, 0x00001EEB, 0xFFFFF559, 0x00000386, 0x00001EEB, 0xFFFFF559, 0x00000386 }, - { 0x0213F0FFEF5A38A4, 0x00003C2F, 0xFFFFE541, 0x000005A3, 0x000025B6, 0xFFFFF16F, 0x000003FA, 0x000025B6, 0xFFFFF16F, 0x000003FA }, - { 0x0213F0FFEF684924, 0x00002BC2, 0xFFFFEE89, 0x0000046A, 0x00001D04, 0xFFFFF651, 0x00000361, 0x00001D04, 0xFFFFF651, 0x00000361 }, - { 0x0213F0FFEF6829A4, 0x00002DD0, 0xFFFFED40, 0x0000049F, 0x00001C8C, 0xFFFFF6B3, 0x00000353, 0x00001C8C, 0xFFFFF6B3, 0x00000353 }, - { 0x0213EA94DE1C08E4, 0x000021ED, 0xFFFFF530, 0x00000380, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, - { 0x0213EA94DE321904, 0x000028C7, 0xFFFFF160, 0x000003FD, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, - { 0x0213F0FFEF6610A4, 0x0000431C, 0xFFFFDF9D, 0x000006A3, 0x000034A6, 0xFFFFE6B0, 0x000005C9, 0x000034A6, 0xFFFFE6B0, 0x000005C9 }, - { 0x0213EA94DE2630A4, 0x00004115, 0xFFFFE0D6, 0x00000667, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, - { 0x0213F0FFEF643924, 0x0000424A, 0xFFFFDEEC, 0x000006E1, 0x0000346A, 0xFFFFE5EA, 0x00000602, 0x0000346A, 0xFFFFE5EA, 0x00000602 }, - { 0x0213F0FFEF661984, 0x00004990, 0xFFFFDAFA, 0x00000771, 0x00002A9C, 0xFFFFED37, 0x000004BC, 0x00002A9C, 0xFFFFED37, 0x000004BC }, - { 0x0213F0FFEF6428A4, 0x00003858, 0xFFFFE568, 0x000005D2, 0x00003030, 0xFFFFE8B0, 0x0000058E, 0x00003030, 0xFFFFE8B0, 0x0000058E }, - { 0x0213F0FFEF684164, 0x00001EDC, 0xFFFFF6CD, 0x00000322, 0x00001FCA, 0xFFFFF4BD, 0x0000039E, 0x00001FCA, 0xFFFFF4BD, 0x0000039E }, - { 0x0213F0FFEF662124, 0x00004C88, 0xFFFFDBA3, 0x0000071B, 0x000030C4, 0xFFFFEAFD, 0x000004F7, 0x000030C4, 0xFFFFEAFD, 0x000004F7 }, - { 0x0213F0FFEF680904, 0x00002B9A, 0xFFFFEE41, 0x0000047D, 0x00002131, 0xFFFFF344, 0x000003E5, 0x00002131, 0xFFFFF344, 0x000003E5 }, - { 0x0213F0FFEF623984, 0x00003E4B, 0xFFFFE33C, 0x000005FA, 0x00003877, 0xFFFFE437, 0x0000062E, 0x00003877, 0xFFFFE437, 0x0000062E }, - { 0x0213EA94DE322064, 0x00002376, 0xFFFFF444, 0x0000038A, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, - { 0x0213F0FFEF661084, 0x00004517, 0xFFFFDDF4, 0x000006F2, 0x000030DC, 0xFFFFE8EF, 0x00000571, 0x000030DC, 0xFFFFE8EF, 0x00000571 }, - { 0x0213F0FFEF681944, 0x0000270C, 0xFFFFF1F3, 0x000003DF, 0x0000207B, 0xFFFFF474, 0x000003AD, 0x0000207B, 0xFFFFF474, 0x000003AD }, - { 0x0213F0FFEF645144, 0x00004086, 0xFFFFDF39, 0x000006E3, 0x00002A24, 0xFFFFEC2B, 0x000004FF, 0x00002A24, 0xFFFFEC2B, 0x000004FF }, - { 0x0213F0FFEF5C3124, 0x00003BDE, 0xFFFFE45E, 0x000005EB, 0x00002CD5, 0xFFFFEC45, 0x000004DD, 0x00002CD5, 0xFFFFEC45, 0x000004DD }, - { 0x0213F0FFEF7230E4, 0x00003803, 0xFFFFE714, 0x00000579, 0x0000288A, 0xFFFFEF21, 0x0000046B, 0x0000288A, 0xFFFFEF21, 0x0000046B }, - { 0x0213F0FFEF601104, 0x00003F50, 0xFFFFE002, 0x000006CD, 0x00001AD4, 0xFFFFF72E, 0x0000031F, 0x00001AD4, 0xFFFFF72E, 0x0000031F }, - { 0x0213F0FFEF6820E4, 0x00002968, 0xFFFFF100, 0x00000402, 0x00001FB5, 0xFFFFF57C, 0x0000037F, 0x00001FB5, 0xFFFFF57C, 0x0000037F }, - { 0x0213F0FFEF662104, 0x00004283, 0xFFFFE2A7, 0x000005F5, 0x00003165, 0xFFFFEB0C, 0x000004EC, 0x00003165, 0xFFFFEB0C, 0x000004EC }, - { 0x0213F0FFEF6431A4, 0x00004253, 0xFFFFDDA8, 0x00000732, 0x00002E5C, 0xFFFFE90A, 0x00000593, 0x00002E5C, 0xFFFFE90A, 0x00000593 }, - { 0x0213F0FFEF5C50A4, 0x00003551, 0xFFFFE756, 0x0000058D, 0x000029A7, 0xFFFFED0C, 0x000004DE, 0x000029A7, 0xFFFFED0C, 0x000004DE }, - { 0x0213F0FFEF6428C4, 0x00003728, 0xFFFFE604, 0x000005C4, 0x00002832, 0xFFFFEE64, 0x00000493, 0x00002832, 0xFFFFEE64, 0x00000493 }, - { 0x0213F0FFEF623964, 0x00004796, 0xFFFFDCC8, 0x00000715, 0x000032AB, 0xFFFFE848, 0x0000057C, 0x000032AB, 0xFFFFE848, 0x0000057C }, - { 0x0213F0FFEF6210C4, 0x000049DF, 0xFFFFDB24, 0x0000075F, 0x00003076, 0xFFFFE967, 0x0000055C, 0x00003076, 0xFFFFE967, 0x0000055C }, - { 0x0213F0FFEF721104, 0x00003F13, 0xFFFFE099, 0x000006A8, 0x00002279, 0xFFFFF226, 0x000003F3, 0x00002279, 0xFFFFF226, 0x000003F3 }, - { 0x0213F0FFEF6430A4, 0x00003E03, 0xFFFFE19F, 0x00000674, 0x00002D66, 0xFFFFEAA7, 0x00000537, 0x00002D66, 0xFFFFEAA7, 0x00000537 }, - { 0x0213F0FFEF5C4104, 0x000037DA, 0xFFFFE63F, 0x000005A7, 0x00002543, 0xFFFFF0A0, 0x00000431, 0x00002543, 0xFFFFF0A0, 0x00000431 }, - { 0x0213F0FFEF624944, 0x00003D82, 0xFFFFE3F5, 0x000005D9, 0x0000332F, 0xFFFFE834, 0x00000577, 0x0000332F, 0xFFFFE834, 0x00000577 }, - { 0x0213EA94DE1228C4, 0x00002915, 0xFFFFF1E0, 0x000003D4, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, - { 0x0213F0FFEF5E4904, 0x000036FC, 0xFFFFE72D, 0x00000577, 0x00002811, 0xFFFFEF30, 0x00000464, 0x00002811, 0xFFFFEF30, 0x00000464 }, - { 0x0213F0FFEF623184, 0x00004767, 0xFFFFDD30, 0x000006FD, 0x00003703, 0xFFFFE564, 0x000005F8, 0x00003703, 0xFFFFE564, 0x000005F8 }, - { 0x0213F0FFEF603184, 0x00003094, 0xFFFFEAA9, 0x000004F5, 0x000022E7, 0xFFFFF200, 0x000003FB, 0x000022E7, 0xFFFFF200, 0x000003FB }, - { 0x0213F0FFEF641144, 0x00003EF0, 0xFFFFDF83, 0x000006ED, 0x00002A27, 0xFFFFEB7C, 0x00000537, 0x00002A27, 0xFFFFEB7C, 0x00000537 }, - { 0x0213F0FFEF681124, 0x0000243C, 0xFFFFF358, 0x000003AC, 0x00001DC4, 0xFFFFF5E9, 0x00000372, 0x00001DC4, 0xFFFFF5E9, 0x00000372 }, - { 0x0213F0FFEF722144, 0x0000284B, 0xFFFFF036, 0x0000040F, 0x00001FCD, 0xFFFFF445, 0x00000395, 0x00001FCD, 0xFFFFF445, 0x00000395 }, - { 0x0213F0FFEF6840C4, 0x00002611, 0xFFFFF285, 0x000003C7, 0x00001CFE, 0xFFFFF6A0, 0x00000355, 0x00001CFE, 0xFFFFF6A0, 0x00000355 }, - { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, - { 0x0213F0FFEF5E38A4, 0x000037F3, 0xFFFFE68D, 0x00000590, 0x00002443, 0xFFFFF1AD, 0x000003FA, 0x00002443, 0xFFFFF1AD, 0x000003FA }, - { 0x0213F0FFEF682144, 0x00002C01, 0xFFFFEF3F, 0x00000444, 0x0000210A, 0xFFFFF475, 0x000003A7, 0x0000210A, 0xFFFFF475, 0x000003A7 }, - { 0x0213EA94DE1210E4, 0x00002C0E, 0xFFFFEF0F, 0x00000446, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, - { 0x0213F0FFEF5E20C4, 0x00003FA6, 0xFFFFE20A, 0x0000063F, 0x00002E29, 0xFFFFEB21, 0x00000510, 0x00002E29, 0xFFFFEB21, 0x00000510 }, - { 0x0213F0FFEF5C2164, 0x00003BCD, 0xFFFFE31B, 0x0000063C, 0x000019AF, 0xFFFFF83D, 0x000002F8, 0x000019AF, 0xFFFFF83D, 0x000002F8 }, - { 0x0213F0FFEF664164, 0x000044C8, 0xFFFFDF08, 0x000006B0, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, - { 0x0213F0FFEF5C1884, 0x00003790, 0xFFFFE571, 0x000005E3, 0x00002042, 0xFFFFF35D, 0x000003CF, 0x00002042, 0xFFFFF35D, 0x000003CF }, - { 0x0213F0FFEF6050E4, 0x000038AC, 0xFFFFE46C, 0x00000609, 0x0000215E, 0xFFFFF22D, 0x00000403, 0x0000215E, 0xFFFFF22D, 0x00000403 }, - { 0x0213F0FFEF5E29A4, 0x00003A1E, 0xFFFFE536, 0x000005C9, 0x000024F3, 0xFFFFF11A, 0x0000041B, 0x000024F3, 0xFFFFF11A, 0x0000041B }, - { 0x0213F0FFEF6650E4, 0x0000431A, 0xFFFFDF1B, 0x000006C5, 0x00002F34, 0xFFFFEA02, 0x00000545, 0x00002F34, 0xFFFFEA02, 0x00000545 }, - { 0x0213F0FFEF641904, 0x000042DC, 0xFFFFDE28, 0x0000070C, 0x00003B53, 0xFFFFE0EA, 0x000006E2, 0x00003B53, 0xFFFFE0EA, 0x000006E2 }, - { 0x0213F0FFEF683164, 0x0000264B, 0xFFFFF29A, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4 }, - { 0x0213F0FFEF5A4064, 0x00004225, 0xFFFFE0E8, 0x00000665, 0x00002B53, 0xFFFFED89, 0x0000049F, 0x00002B53, 0xFFFFED89, 0x0000049F }, - { 0x0213EA94DE204924, 0x00001FCC, 0xFFFFF63F, 0x00000358, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, - { 0x0213F0FFEF6240A4, 0x000045E0, 0xFFFFDDD0, 0x000006ED, 0x00003193, 0xFFFFE8BD, 0x00000572, 0x00003193, 0xFFFFE8BD, 0x00000572 }, - { 0x0213F0FFEF683924, 0x000024FC, 0xFFFFF366, 0x000003A6, 0x00001FE8, 0xFFFFF509, 0x00000394, 0x00001FE8, 0xFFFFF509, 0x00000394 }, - { 0x0213F0FFEF5C4884, 0x0000378F, 0xFFFFE54B, 0x000005F1, 0x00001C9B, 0xFFFFF5C7, 0x00000368, 0x00001C9B, 0xFFFFF5C7, 0x00000368 }, - { 0x0213F0FFEF6418A4, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002CDD, 0xFFFFEA44, 0x00000557, 0x00002CDD, 0xFFFFEA44, 0x00000557 }, - { 0x0213EA94DE200904, 0x000021EC, 0xFFFFF4F4, 0x0000038F, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, - { 0x0213F0FFEF6010A4, 0x00003C8A, 0xFFFFE1C1, 0x00000685, 0x000019C7, 0xFFFFF7E2, 0x00000301, 0x000019C7, 0xFFFFF7E2, 0x00000301 }, - { 0x0213F0FFEF5E2064, 0x00003908, 0xFFFFE5C7, 0x000005B3, 0x00002793, 0xFFFFEF46, 0x00000465, 0x00002793, 0xFFFFEF46, 0x00000465 }, - { 0x0213F0FFEF605104, 0x000040A3, 0xFFFFDE61, 0x00000725, 0x00002077, 0xFFFFF2CE, 0x000003E8, 0x00002077, 0xFFFFF2CE, 0x000003E8 }, - { 0x0213F0FFEF664144, 0x00003DCA, 0xFFFFE34D, 0x00000608, 0x00002D66, 0xFFFFEBDF, 0x000004E8, 0x00002D66, 0xFFFFEBDF, 0x000004E8 }, - { 0x0213F0FFEF5E50C4, 0x00003085, 0xFFFFEB70, 0x000004C8, 0x000029B1, 0xFFFFEDD9, 0x000004A5, 0x000029B1, 0xFFFFEDD9, 0x000004A5 }, - { 0x0213EA94DE083884, 0x00004C73, 0xFFFFD676, 0x0000086C, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, - { 0x0213EA94DE242164, 0x00002CE5, 0xFFFFEE8C, 0x00000466, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, - { 0x0213F0FFEF621124, 0x0000489F, 0xFFFFDBF1, 0x0000073E, 0x0000332D, 0xFFFFE786, 0x000005AD, 0x0000332D, 0xFFFFE786, 0x000005AD }, - { 0x0213F0FFEF602864, 0x00003D09, 0xFFFFE193, 0x00000689, 0x00001E82, 0xFFFFF4C0, 0x00000386, 0x00001E82, 0xFFFFF4C0, 0x00000386 }, - { 0x0213F0FFEF644104, 0x00003E4C, 0xFFFFE131, 0x00000689, 0x00002F4E, 0xFFFFE925, 0x0000057B, 0x00002F4E, 0xFFFFE925, 0x0000057B }, - { 0x0213F0FFEF5A4084, 0x00003B31, 0xFFFFE53F, 0x000005B3, 0x0000248A, 0xFFFFF211, 0x000003DF, 0x0000248A, 0xFFFFF211, 0x000003DF }, - { 0x0213F0FFEF644124, 0x000038DD, 0xFFFFE54A, 0x000005C9, 0x00002B6D, 0xFFFFEBDF, 0x00000502, 0x00002B6D, 0xFFFFEBDF, 0x00000502 }, - { 0x0213F0FFEF684064, 0x00002698, 0xFFFFF1A8, 0x000003F2, 0x00002163, 0xFFFFF34B, 0x000003E3, 0x00002163, 0xFFFFF34B, 0x000003E3 }, - { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, - { 0x0213F0FFEF6418C4, 0x00003EAF, 0xFFFFE0C3, 0x000006A0, 0x000030AB, 0xFFFFE829, 0x000005A6, 0x000030AB, 0xFFFFE829, 0x000005A6 }, - { 0x0213F0FFEF684944, 0x00002E89, 0xFFFFECA6, 0x000004B6, 0x00001FA0, 0xFFFFF4A8, 0x000003A3, 0x00001FA0, 0xFFFFF4A8, 0x000003A3 }, - { 0x0213F0FFEF6828A4, 0x000028A4, 0xFFFFF112, 0x00000402, 0x00001F7C, 0xFFFFF545, 0x0000038A, 0x00001F7C, 0xFFFFF545, 0x0000038A }, - { 0x0213F0FFEF6650A4, 0x00004135, 0xFFFFDFA2, 0x000006C5, 0x0000324C, 0xFFFFE7AA, 0x000005AF, 0x0000324C, 0xFFFFE7AA, 0x000005AF }, - { 0x0213EA94DE2038C4, 0x00002012, 0xFFFFF693, 0x00000352, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, - { 0x0213F0FFEF643084, 0x00003D7C, 0xFFFFE1BC, 0x00000671, 0x00002A45, 0xFFFFEC84, 0x000004EC, 0x00002A45, 0xFFFFEC84, 0x000004EC }, - { 0x0213F0FFEF723064, 0x00004172, 0xFFFFDF58, 0x000006DA, 0x00002504, 0xFFFFF0A6, 0x00000431, 0x00002504, 0xFFFFF0A6, 0x00000431 }, - { 0x0213F0FE99281944, 0x000029C7, 0xFFFFF087, 0x00000414, 0x00001DCB, 0xFFFFF675, 0x0000035F, 0x00001DCB, 0xFFFFF675, 0x0000035F }, - { 0x0213F0FE992A29A4, 0x000027F0, 0xFFFFF05A, 0x00000432, 0x00001707, 0xFFFFFA0E, 0x000002D1, 0x00001707, 0xFFFFFA0E, 0x000002D1 }, - { 0x0213F0FE99222144, 0x00003279, 0xFFFFE9F7, 0x00000511, 0x00001B5E, 0xFFFFF787, 0x00000317, 0x00001B5E, 0xFFFFF787, 0x00000317 }, - { 0x0213F0FE99322184, 0x000030A5, 0xFFFFEABC, 0x000004FF, 0x000019D1, 0xFFFFF83C, 0x00000304, 0x000019D1, 0xFFFFF83C, 0x00000304 }, - { 0x0213F0FE99282844, 0x0000283B, 0xFFFFF122, 0x00000402, 0x000019C2, 0xFFFFF8E9, 0x000002FB, 0x000019C2, 0xFFFFF8E9, 0x000002FB }, - { 0x0213F0FE992C2084, 0x00003376, 0xFFFFE9E1, 0x00000510, 0x000021A7, 0xFFFFF39F, 0x000003BF, 0x000021A7, 0xFFFFF39F, 0x000003BF }, - { 0x0213F0FE993218C4, 0x000031D2, 0xFFFFEA9C, 0x000004FC, 0x00001F66, 0xFFFFF4E4, 0x00000390, 0x00001F66, 0xFFFFF4E4, 0x00000390 }, - { 0x0213F0FE991A3864, 0x00003006, 0xFFFFEB18, 0x000004F2, 0x000019B3, 0xFFFFF84E, 0x00000301, 0x000019B3, 0xFFFFF84E, 0x00000301 }, - { 0x0213F0FE993039A4, 0x0000364F, 0xFFFFE81F, 0x00000556, 0x00002AC9, 0xFFFFED87, 0x000004BD, 0x00002AC9, 0xFFFFED87, 0x000004BD }, - { 0x0213F0FE992E3844, 0x00003043, 0xFFFFEBAE, 0x000004CD, 0x00001B0C, 0xFFFFF7ED, 0x0000030C, 0x00001B0C, 0xFFFFF7ED, 0x0000030C }, - { 0x0213F0FE993048A4, 0x000037CE, 0xFFFFE69E, 0x00000596, 0x0000276B, 0xFFFFEF65, 0x0000046E, 0x0000276B, 0xFFFFEF65, 0x0000046E }, - { 0x0213F0FE992C3104, 0x00003063, 0xFFFFED5E, 0x0000046F, 0x000024AE, 0xFFFFF2C4, 0x000003D8, 0x000024AE, 0xFFFFF2C4, 0x000003D8 }, - { 0x0213F0FE992E08A4, 0x00002F5D, 0xFFFFEBDC, 0x000004D3, 0x00001EDB, 0xFFFFF50F, 0x0000038E, 0x00001EDB, 0xFFFFF50F, 0x0000038E }, - { 0x0213F0FE992E48A4, 0x00003148, 0xFFFFEA9A, 0x000004FB, 0x0000192D, 0xFFFFF8E9, 0x000002DF, 0x0000192D, 0xFFFFF8E9, 0x000002DF }, - { 0x0213F0FE992C2064, 0x00003682, 0xFFFFE7E4, 0x0000055C, 0x0000250E, 0xFFFFF150, 0x0000041A, 0x0000250E, 0xFFFFF150, 0x0000041A }, - { 0x0213F0FE992A2084, 0x0000284E, 0xFFFFF15A, 0x000003F8, 0x00001CE2, 0xFFFFF6F9, 0x0000034F, 0x00001CE2, 0xFFFFF6F9, 0x0000034F }, - { 0x0213F0FE993018A4, 0x00003171, 0xFFFFEAE9, 0x000004ED, 0x00001F40, 0xFFFFF513, 0x00000384, 0x00001F40, 0xFFFFF513, 0x00000384 }, - { 0x0213F0FE99323044, 0x000031BD, 0xFFFFEA64, 0x0000050A, 0x00001EFD, 0xFFFFF4F7, 0x00000390, 0x00001EFD, 0xFFFFF4F7, 0x00000390 }, - { 0x0213F0FE992E50E4, 0x00003050, 0xFFFFEB29, 0x000004EA, 0x000019B3, 0xFFFFF878, 0x000002F9, 0x000019B3, 0xFFFFF878, 0x000002F9 }, - { 0x0213F0FE992C1904, 0x00003400, 0xFFFFE9A0, 0x0000051A, 0x00002460, 0xFFFFF1DA, 0x00000409, 0x00002460, 0xFFFFF1DA, 0x00000409 }, - { 0x0213F0FE992C4884, 0x000034A1, 0xFFFFE86F, 0x00000558, 0x0000255D, 0xFFFFF09E, 0x00000443, 0x0000255D, 0xFFFFF09E, 0x00000443 }, - { 0x0213F0FE992E48E4, 0x00003103, 0xFFFFEAD7, 0x000004F0, 0x00001896, 0xFFFFF95A, 0x000002CC, 0x00001896, 0xFFFFF95A, 0x000002CC }, - { 0x0213F0FE993018E4, 0x00003120, 0xFFFFEB9E, 0x000004CB, 0x000021E8, 0xFFFFF3A2, 0x000003C1, 0x000021E8, 0xFFFFF3A2, 0x000003C1 }, - { 0x0213F0FE991C50E4, 0x00003558, 0xFFFFE812, 0x00000565, 0x0000256E, 0xFFFFF097, 0x00000447, 0x0000256E, 0xFFFFF097, 0x00000447 }, - { 0x0213F0FE991A2844, 0x00002DA8, 0xFFFFECA8, 0x000004B7, 0x0000180B, 0xFFFFF96D, 0x000002D8, 0x0000180B, 0xFFFFF96D, 0x000002D8 }, - { 0x0213F0FE992E3064, 0x00003232, 0xFFFFEA66, 0x000004FF, 0x00001DDE, 0xFFFFF5FE, 0x0000035A, 0x00001DDE, 0xFFFFF5FE, 0x0000035A }, - { 0x0213F0FE993050E4, 0x000034D2, 0xFFFFE89F, 0x00000548, 0x0000246C, 0xFFFFF17F, 0x00000418, 0x0000246C, 0xFFFFF17F, 0x00000418 }, - { 0x0213F0FE99304904, 0x000033EC, 0xFFFFE954, 0x0000052A, 0x00002323, 0xFFFFF279, 0x000003EE, 0x00002323, 0xFFFFF279, 0x000003EE }, - { 0x0213F0FE99303884, 0x000033AA, 0xFFFFE955, 0x0000052D, 0x0000229F, 0xFFFFF2B2, 0x000003E7, 0x0000229F, 0xFFFFF2B2, 0x000003E7 }, - { 0x0213F0FE99324964, 0x00003258, 0xFFFFE9AA, 0x0000052A, 0x00001D5F, 0xFFFFF5D1, 0x0000036B, 0x00001D5F, 0xFFFFF5D1, 0x0000036B }, - { 0x0213F0FE993029A4, 0x0000323A, 0xFFFFEA5F, 0x00000504, 0x00002108, 0xFFFFF3D5, 0x000003BA, 0x00002108, 0xFFFFF3D5, 0x000003BA }, - { 0x0213F0FE992C2184, 0x00003216, 0xFFFFEA6B, 0x000004FF, 0x00001D6E, 0xFFFFF640, 0x00000350, 0x00001D6E, 0xFFFFF640, 0x00000350 }, - { 0x0213F0FE993210E4, 0x000030C5, 0xFFFFEAC4, 0x000004FC, 0x00001924, 0xFFFFF8C2, 0x000002EE, 0x00001924, 0xFFFFF8C2, 0x000002EE }, - { 0x0213F0FE99305104, 0x000032BB, 0xFFFFE9F1, 0x00000515, 0x00002211, 0xFFFFF31B, 0x000003D5, 0x00002211, 0xFFFFF31B, 0x000003D5 }, - { 0x0213F0FE993048C4, 0x0000352C, 0xFFFFE85B, 0x00000553, 0x00002410, 0xFFFFF1B4, 0x0000040F, 0x00002410, 0xFFFFF1B4, 0x0000040F }, - { 0x0213F0FE992238C4, 0x000036A0, 0xFFFFE7E8, 0x0000055D, 0x00002901, 0xFFFFEEB8, 0x00000489, 0x00002901, 0xFFFFEEB8, 0x00000489 }, - { 0x0213F0FE992C3044, 0x00003340, 0xFFFFE9D9, 0x00000516, 0x00002332, 0xFFFFF27A, 0x000003F0, 0x00002332, 0xFFFFF27A, 0x000003F0 }, - { 0x0213F0FE991A38A4, 0x00003564, 0xFFFFE86D, 0x0000054E, 0x00002613, 0xFFFFF07C, 0x00000444, 0x00002613, 0xFFFFF07C, 0x00000444 }, - { 0x0213F0FE99280904, 0x00002AD1, 0xFFFFEF0B, 0x0000045C, 0x00001DEA, 0xFFFFF5C8, 0x00000381, 0x00001DEA, 0xFFFFF5C8, 0x00000381 }, - { 0x0213F0FE992220E4, 0x000035B0, 0xFFFFE846, 0x00000555, 0x000027BE, 0xFFFFEF5D, 0x00000474, 0x000027BE, 0xFFFFEF5D, 0x00000474 }, - { 0x0213F0FE992238A4, 0x000032C4, 0xFFFFEA48, 0x00000502, 0x000022C6, 0xFFFFF2DF, 0x000003DE, 0x000022C6, 0xFFFFF2DF, 0x000003DE }, - { 0x0213F0FE993008C4, 0x00003036, 0xFFFFEB0D, 0x000004F9, 0x00001FE8, 0xFFFFF41A, 0x000003BC, 0x00001FE8, 0xFFFFF41A, 0x000003BC }, - { 0x0213F0FE991A0904, 0x000030F8, 0xFFFFEA13, 0x00000524, 0x00001B6A, 0xFFFFF6C9, 0x0000034A, 0x00001B6A, 0xFFFFF6C9, 0x0000034A }, - { 0x0213F0FE993010A4, 0x00002EE2, 0xFFFFEC0C, 0x000004CB, 0x00001A39, 0xFFFFF814, 0x0000030F, 0x00001A39, 0xFFFFF814, 0x0000030F }, - { 0x0213F0FE991C3184, 0x00003457, 0xFFFFE924, 0x0000052A, 0x00001E9D, 0xFFFFF59C, 0x00000363, 0x00001E9D, 0xFFFFF59C, 0x00000363 }, - { 0x0213F0FE99322844, 0x000030BF, 0xFFFFEB18, 0x000004ED, 0x00001D37, 0xFFFFF636, 0x0000035C, 0x00001D37, 0xFFFFF636, 0x0000035C }, - { 0x0213F0FE992E4084, 0x000031AF, 0xFFFFEA75, 0x000004FE, 0x000019F2, 0xFFFFF87A, 0x000002F0, 0x000019F2, 0xFFFFF87A, 0x000002F0 }, - { 0x0213F0FE99302884, 0x00003642, 0xFFFFE85B, 0x00000547, 0x00002975, 0xFFFFEE98, 0x0000048B, 0x00002975, 0xFFFFEE98, 0x0000048B }, - { 0x0213F0FE992E2884, 0x00002E8B, 0xFFFFED1E, 0x0000048E, 0x000019C1, 0xFFFFF917, 0x000002D6, 0x000019C1, 0xFFFFF917, 0x000002D6 }, - { 0x0213F0FE993241A4, 0x000033D9, 0xFFFFE8E1, 0x00000548, 0x0000224B, 0xFFFFF298, 0x000003F4, 0x0000224B, 0xFFFFF298, 0x000003F4 }, - { 0x0213F0FE992E28C4, 0x000032BC, 0xFFFFEB0F, 0x000004D6, 0x00002488, 0xFFFFF240, 0x000003F2, 0x00002488, 0xFFFFF240, 0x000003F2 }, - { 0x0213F0FE99304944, 0x000035FD, 0xFFFFE838, 0x00000553, 0x00002762, 0xFFFFEFBC, 0x00000460, 0x00002762, 0xFFFFEFBC, 0x00000460 }, - { 0x0213F0FE992818A4, 0x0000268B, 0xFFFFF263, 0x000003D1, 0x00001914, 0xFFFFF977, 0x000002E8, 0x00001914, 0xFFFFF977, 0x000002E8 }, - { 0x0213F0FE992C3184, 0x0000330B, 0xFFFFEA1E, 0x00000505, 0x000020B1, 0xFFFFF44D, 0x0000039E, 0x000020B1, 0xFFFFF44D, 0x0000039E }, - { 0x0213F0FE99222084, 0x0000326E, 0xFFFFEA26, 0x00000508, 0x00001C17, 0xFFFFF722, 0x00000328, 0x00001C17, 0xFFFFF722, 0x00000328 }, - { 0x0213F0FE992A31A4, 0x00002A3F, 0xFFFFEEE8, 0x0000046D, 0x00001B2B, 0xFFFFF737, 0x0000034D, 0x00001B2B, 0xFFFFF737, 0x0000034D }, - { 0x0213F0FE992C4064, 0x00003732, 0xFFFFE765, 0x00000574, 0x00002A6D, 0xFFFFEDA8, 0x000004B7, 0x00002A6D, 0xFFFFEDA8, 0x000004B7 }, - { 0x0213F0FE99300924, 0x000034D3, 0xFFFFE827, 0x00000569, 0x000027AA, 0xFFFFEEE7, 0x00000492, 0x000027AA, 0xFFFFEEE7, 0x00000492 }, - { 0x0213F0FE992E40C4, 0x00003306, 0xFFFFEA39, 0x000004FC, 0x00001DCC, 0xFFFFF655, 0x00000344, 0x00001DCC, 0xFFFFF655, 0x00000344 }, - { 0x0213F0FE99282044, 0x00002A48, 0xFFFFEFCA, 0x00000439, 0x00001DED, 0xFFFFF60D, 0x00000375, 0x00001DED, 0xFFFFF60D, 0x00000375 }, - { 0x0213F0FE993038C4, 0x000033A3, 0xFFFFEA36, 0x000004F9, 0x0000247C, 0xFFFFF21F, 0x000003F4, 0x0000247C, 0xFFFFF21F, 0x000003F4 }, - { 0x0213F0FE992C3164, 0x0000311B, 0xFFFFEB76, 0x000004D1, 0x00001EB1, 0xFFFFF5B6, 0x00000366, 0x00001EB1, 0xFFFFF5B6, 0x00000366 }, - { 0x0213F0FE99324164, 0x00003307, 0xFFFFE97F, 0x0000052A, 0x00001E76, 0xFFFFF54D, 0x0000037C, 0x00001E76, 0xFFFFF54D, 0x0000037C }, - { 0x0213F0FE991C2144, 0x0000344B, 0xFFFFE9C5, 0x00000509, 0x000020D6, 0xFFFFF486, 0x0000038F, 0x000020D6, 0xFFFFF486, 0x0000038F }, - { 0x0213F0FE992C3144, 0x000034B9, 0xFFFFEA0B, 0x000004F7, 0x000027B3, 0xFFFFF057, 0x0000043A, 0x000027B3, 0xFFFFF057, 0x0000043A }, - { 0x0213F0FE99301964, 0x00003360, 0xFFFFE984, 0x00000527, 0x00002238, 0xFFFFF2EE, 0x000003E0, 0x00002238, 0xFFFFF2EE, 0x000003E0 }, - { 0x0213F0FE99302124, 0x0000315C, 0xFFFFEC05, 0x000004B1, 0x000023C8, 0xFFFFF2CC, 0x000003DE, 0x000023C8, 0xFFFFF2CC, 0x000003DE }, - { 0x0213F0FE992C2864, 0x0000389B, 0xFFFFE6D5, 0x00000582, 0x00002C6C, 0xFFFFEC92, 0x000004DE, 0x00002C6C, 0xFFFFEC92, 0x000004DE }, - { 0x0213F0FE992E1124, 0x00003058, 0xFFFFEB30, 0x000004E6, 0x000019B5, 0xFFFFF88B, 0x000002F1, 0x000019B5, 0xFFFFF88B, 0x000002F1 }, - { 0x0213F0FE992E0904, 0x00002F69, 0xFFFFEB4A, 0x000004F1, 0x00001B82, 0xFFFFF6EC, 0x00000341, 0x00001B82, 0xFFFFF6EC, 0x00000341 }, - { 0x0213F0FE991A18E4, 0x000031EB, 0xFFFFEA64, 0x00000508, 0x00002059, 0xFFFFF427, 0x000003B0, 0x00002059, 0xFFFFF427, 0x000003B0 }, - { 0x0213F0FE99224124, 0x000033E2, 0xFFFFE94D, 0x0000052A, 0x000020BF, 0xFFFFF40B, 0x000003AB, 0x000020BF, 0xFFFFF40B, 0x000003AB }, - { 0x0213F0FE99283184, 0x00002AF9, 0xFFFFEFE9, 0x00000427, 0x00001F72, 0xFFFFF57A, 0x00000383, 0x00001F72, 0xFFFFF57A, 0x00000383 }, - { 0x0213F0FE992C2824, 0x00003282, 0xFFFFEA88, 0x000004FA, 0x00002561, 0xFFFFF126, 0x0000042B, 0x00002561, 0xFFFFF126, 0x0000042B }, - { 0x0213F0FE993010E4, 0x0000308A, 0xFFFFEB5D, 0x000004E0, 0x00001E83, 0xFFFFF577, 0x00000378, 0x00001E83, 0xFFFFF577, 0x00000378 }, - { 0x0213F0FE99324884, 0x0000336E, 0xFFFFE8C8, 0x00000553, 0x0000217C, 0xFFFFF2E1, 0x000003EB, 0x0000217C, 0xFFFFF2E1, 0x000003EB }, - { 0x0213F0FE991A2164, 0x000034A9, 0xFFFFE838, 0x00000561, 0x000020CE, 0xFFFFF38A, 0x000003C7, 0x000020CE, 0xFFFFF38A, 0x000003C7 }, - { 0x0213F0FE99222184, 0x00003152, 0xFFFFE9EB, 0x00000522, 0x00001755, 0xFFFFF9A9, 0x000002C6, 0x00001755, 0xFFFFF9A9, 0x000002C6 }, - { 0x0213F0FE99281884, 0x0000286E, 0xFFFFF136, 0x000003FD, 0x00001BAB, 0xFFFFF7C3, 0x0000032C, 0x00001BAB, 0xFFFFF7C3, 0x0000032C }, - { 0x0213F0FE99300944, 0x0000316B, 0xFFFFEA02, 0x00000528, 0x00002247, 0xFFFFF24E, 0x00000408, 0x00002247, 0xFFFFF24E, 0x00000408 }, - { 0x0213F0FE992C08E4, 0x000034CF, 0xFFFFE83D, 0x00000562, 0x00002458, 0xFFFFF130, 0x00000430, 0x00002458, 0xFFFFF130, 0x00000430 }, - { 0x0213F0FE992C2984, 0x00003352, 0xFFFFE9D1, 0x00000515, 0x0000212A, 0xFFFFF3DC, 0x000003B4, 0x0000212A, 0xFFFFF3DC, 0x000003B4 }, - { 0x0213F0FE992840A4, 0x00002946, 0xFFFFF09B, 0x00000415, 0x00001DC9, 0xFFFFF650, 0x00000366, 0x00001DC9, 0xFFFFF650, 0x00000366 }, - { 0x0213F0FE99301124, 0x00003080, 0xFFFFEB47, 0x000004E1, 0x00001BD5, 0xFFFFF73B, 0x00000329, 0x00001BD5, 0xFFFFF73B, 0x00000329 }, - { 0x0213F0FE991A1884, 0x00002FBD, 0xFFFFEB7B, 0x000004DD, 0x000017FC, 0xFFFFF99E, 0x000002C7, 0x000017FC, 0xFFFFF99E, 0x000002C7 }, - { 0x0213F0FE99281124, 0x00002A28, 0xFFFFF032, 0x0000041F, 0x00001B19, 0xFFFFF83A, 0x00000312, 0x00001B19, 0xFFFFF83A, 0x00000312 }, - { 0x0213F0FE992240C4, 0x00003420, 0xFFFFE936, 0x00000530, 0x000023C2, 0xFFFFF203, 0x00000406, 0x000023C2, 0xFFFFF203, 0x00000406 }, - { 0x0213F0FE99301144, 0x00002F7C, 0xFFFFEBBA, 0x000004D1, 0x0000185D, 0xFFFFF975, 0x000002CA, 0x0000185D, 0xFFFFF975, 0x000002CA }, - { 0x0213F0FE992E2044, 0x00002C51, 0xFFFFEE3B, 0x0000046F, 0x000019AA, 0xFFFFF8DD, 0x000002ED, 0x000019AA, 0xFFFFF8DD, 0x000002ED }, - { 0x0213F0FE991A4144, 0x000033D6, 0xFFFFE8F2, 0x0000053D, 0x00001D73, 0xFFFFF5FB, 0x0000035B, 0x00001D73, 0xFFFFF5FB, 0x0000035B }, - { 0x0213F0FE99323084, 0x000031D9, 0xFFFFEAF7, 0x000004E4, 0x00001EBD, 0xFFFFF5A6, 0x00000368, 0x00001EBD, 0xFFFFF5A6, 0x00000368 }, - { 0x0213F0FE991A20A4, 0x00003386, 0xFFFFE9CE, 0x00000515, 0x00002422, 0xFFFFF1F3, 0x00000405, 0x00002422, 0xFFFFF1F3, 0x00000405 }, - { 0x0213F0FE992C50E4, 0x000032FB, 0xFFFFE9BC, 0x00000520, 0x00002301, 0xFFFFF267, 0x000003F7, 0x00002301, 0xFFFFF267, 0x000003F7 }, - { 0x0213F0FE99322924, 0x000032C2, 0xFFFFEAC0, 0x000004EA, 0x0000250F, 0xFFFFF1A2, 0x00000413, 0x0000250F, 0xFFFFF1A2, 0x00000413 }, - { 0x0213F0FE991C2944, 0x00003722, 0xFFFFE8A6, 0x00000527, 0x000026E4, 0xFFFFF0F5, 0x0000041C, 0x000026E4, 0xFFFFF0F5, 0x0000041C }, - { 0x0213F0FE992C48C4, 0x000035A4, 0xFFFFE822, 0x00000558, 0x000022F2, 0xFFFFF288, 0x000003E8, 0x000022F2, 0xFFFFF288, 0x000003E8 }, - { 0x0213F0FE99280924, 0x00002CD1, 0xFFFFEDC6, 0x0000048C, 0x00001EAF, 0xFFFFF53D, 0x00000396, 0x00001EAF, 0xFFFFF53D, 0x00000396 }, - { 0x0213F0FE99301164, 0x00003156, 0xFFFFEA60, 0x0000050B, 0x00001BBC, 0xFFFFF704, 0x00000335, 0x00001BBC, 0xFFFFF704, 0x00000335 }, - { 0x0213F0FE992C5104, 0x000034A1, 0xFFFFE8C0, 0x00000544, 0x00002528, 0xFFFFF105, 0x0000042C, 0x00002528, 0xFFFFF105, 0x0000042C }, - { 0x0213F0FE99323064, 0x000032CE, 0xFFFFE9D3, 0x00000520, 0x000021FF, 0xFFFFF2FD, 0x000003E4, 0x000021FF, 0xFFFFF2FD, 0x000003E4 }, - { 0x0213F0FE991A50A4, 0x000034A0, 0xFFFFE823, 0x0000056D, 0x0000256F, 0xFFFFF047, 0x0000045A, 0x0000256F, 0xFFFFF047, 0x0000045A }, - { 0x0213F0FE99303944, 0x00003109, 0xFFFFEBD6, 0x000004BF, 0x000022D4, 0xFFFFF32D, 0x000003D0, 0x000022D4, 0xFFFFF32D, 0x000003D0 }, - { 0x0213F0FE992C1164, 0x000030B7, 0xFFFFEAF0, 0x000004F3, 0x00001AEC, 0xFFFFF7A9, 0x0000031B, 0x00001AEC, 0xFFFFF7A9, 0x0000031B }, - { 0x0213F0FE992C39A4, 0x00003078, 0xFFFFEBA4, 0x000004CF, 0x00001E7A, 0xFFFFF5AF, 0x0000036B, 0x00001E7A, 0xFFFFF5AF, 0x0000036B }, - { 0x0213F0FE99304124, 0x00003442, 0xFFFFE998, 0x00000518, 0x000025EA, 0xFFFFF0F3, 0x0000042B, 0x000025EA, 0xFFFFF0F3, 0x0000042B }, - { 0x0213F0FE993021A4, 0x000031CB, 0xFFFFEA80, 0x00000501, 0x000020A3, 0xFFFFF403, 0x000003B2, 0x000020A3, 0xFFFFF403, 0x000003B2 }, - { 0x0213F0FE992A2984, 0x00002947, 0xFFFFF018, 0x00000433, 0x00001BA5, 0xFFFFF75C, 0x00000340, 0x00001BA5, 0xFFFFF75C, 0x00000340 }, - { 0x0213F0FE992C3984, 0x000033F9, 0xFFFFE99D, 0x00000518, 0x00002231, 0xFFFFF358, 0x000003C5, 0x00002231, 0xFFFFF358, 0x000003C5 }, - { 0x0213F0FE99321124, 0x00003131, 0xFFFFEA45, 0x00000513, 0x00001973, 0xFFFFF85E, 0x00000301, 0x00001973, 0xFFFFF85E, 0x00000301 }, - { 0x0213F0FE991C29A4, 0x00003571, 0xFFFFE8AC, 0x00000539, 0x00002049, 0xFFFFF49C, 0x0000038D, 0x00002049, 0xFFFFF49C, 0x0000038D }, - { 0x0213F0FE992E3864, 0x0000309E, 0xFFFFEB1D, 0x000004E8, 0x000019ED, 0xFFFFF86E, 0x000002F8, 0x000019ED, 0xFFFFF86E, 0x000002F8 }, - { 0x0213F0FE99302984, 0x00003091, 0xFFFFEB9B, 0x000004CC, 0x00001D2C, 0xFFFFF6A2, 0x0000033D, 0x00001D2C, 0xFFFFF6A2, 0x0000033D }, - { 0x0213F0FE993008E4, 0x00003069, 0xFFFFEAFD, 0x000004F8, 0x00001E82, 0xFFFFF51C, 0x0000038D, 0x00001E82, 0xFFFFF51C, 0x0000038D }, - { 0x0213F0FE992210A4, 0x00003459, 0xFFFFE7F2, 0x00000572, 0x00001DA7, 0xFFFFF552, 0x0000037F, 0x00001DA7, 0xFFFFF552, 0x0000037F }, - { 0x0213F0FE99321104, 0x0000304B, 0xFFFFEAFB, 0x000004F4, 0x0000191E, 0xFFFFF8BD, 0x000002EE, 0x0000191E, 0xFFFFF8BD, 0x000002EE }, - { 0x0213F0FE993020C4, 0x0000346E, 0xFFFFEA07, 0x000004FD, 0x00002767, 0xFFFFF058, 0x00000440, 0x00002767, 0xFFFFF058, 0x00000440 }, - { 0x0213F0FE992E3084, 0x000030B5, 0xFFFFEBC1, 0x000004C1, 0x00001B3C, 0xFFFFF818, 0x000002FD, 0x00001B3C, 0xFFFFF818, 0x000002FD }, - { 0x0213F0FE99300904, 0x0000321F, 0xFFFFE9EA, 0x00000524, 0x00002380, 0xFFFFF1C2, 0x0000041A, 0x00002380, 0xFFFFF1C2, 0x0000041A }, - { 0x0213F0FE992E3044, 0x000030DF, 0xFFFFEB37, 0x000004E2, 0x00001E3C, 0xFFFFF5BB, 0x00000369, 0x00001E3C, 0xFFFFF5BB, 0x00000369 }, - { 0x0213F0FE992848A4, 0x000027E0, 0xFFFFF0E2, 0x00000416, 0x00001A6A, 0xFFFFF820, 0x00000321, 0x00001A6A, 0xFFFFF820, 0x00000321 }, - { 0x0213F0FE991A1084, 0x00002FA1, 0xFFFFEB63, 0x000004E7, 0x0000196B, 0xFFFFF880, 0x000002FB, 0x0000196B, 0xFFFFF880, 0x000002FB }, - { 0x0213F0FE991C1084, 0x0000310C, 0xFFFFEAAF, 0x000004FC, 0x000019EF, 0xFFFFF850, 0x000002FD, 0x000019EF, 0xFFFFF850, 0x000002FD }, - { 0x0213F0FE99323904, 0x0000334A, 0xFFFFEA07, 0x0000050B, 0x00002380, 0xFFFFF26F, 0x000003F0, 0x00002380, 0xFFFFF26F, 0x000003F0 }, - { 0x0213F0FE99302944, 0x00002FF9, 0xFFFFECDC, 0x00000492, 0x00002297, 0xFFFFF394, 0x000003BF, 0x00002297, 0xFFFFF394, 0x000003BF }, - { 0x0213F0FE992C2164, 0x0000354B, 0xFFFFE894, 0x00000546, 0x000024C4, 0xFFFFF16C, 0x0000041B, 0x000024C4, 0xFFFFF16C, 0x0000041B }, - { 0x0213F0FE99220924, 0x00003245, 0xFFFFE92F, 0x00000544, 0x00001829, 0xFFFFF8F1, 0x000002EA, 0x00001829, 0xFFFFF8F1, 0x000002EA }, - { 0x0213F0FE992E4884, 0x0000302F, 0xFFFFEB51, 0x000004E3, 0x0000199F, 0xFFFFF894, 0x000002F4, 0x0000199F, 0xFFFFF894, 0x000002F4 }, - { 0x0213F0FE992E18C4, 0x00002F54, 0xFFFFEC86, 0x000004A6, 0x00001A6F, 0xFFFFF891, 0x000002EC, 0x00001A6F, 0xFFFFF891, 0x000002EC }, - { 0x0213F0FE99284164, 0x00002908, 0xFFFFF0D8, 0x0000040A, 0x00001C9B, 0xFFFFF729, 0x00000342, 0x00001C9B, 0xFFFFF729, 0x00000342 }, - { 0x0213F0FE99302964, 0x000031D9, 0xFFFFEB40, 0x000004D7, 0x000023F5, 0xFFFFF259, 0x000003F4, 0x000023F5, 0xFFFFF259, 0x000003F4 }, - { 0x0213F0FE993048E4, 0x000034C8, 0xFFFFE8C6, 0x0000053F, 0x00002313, 0xFFFFF280, 0x000003EC, 0x00002313, 0xFFFFF280, 0x000003EC }, - { 0x0213F0FE993050C4, 0x000037D1, 0xFFFFE6A1, 0x0000059C, 0x00002C6A, 0xFFFFEBFF, 0x00000504, 0x00002C6A, 0xFFFFEBFF, 0x00000504 }, - { 0x0213F0FE99321964, 0x000030E9, 0xFFFFEA6B, 0x0000050F, 0x00001A2D, 0xFFFFF7DF, 0x00000316, 0x00001A2D, 0xFFFFF7DF, 0x00000316 }, - { 0x0213F0FE99302084, 0x0000323D, 0xFFFFEA95, 0x000004F4, 0x00001ED2, 0xFFFFF584, 0x0000036C, 0x00001ED2, 0xFFFFF584, 0x0000036C }, - { 0x0213F0FE992C3024, 0x000033D6, 0xFFFFE9DB, 0x00000510, 0x000027A7, 0xFFFFEFC7, 0x0000045E, 0x000027A7, 0xFFFFEFC7, 0x0000045E }, - { 0x0213F0FE991C3164, 0x00003444, 0xFFFFE98A, 0x00000517, 0x000020FD, 0xFFFFF43F, 0x0000039D, 0x000020FD, 0xFFFFF43F, 0x0000039D }, - { 0x0213F0FE992808E4, 0x00002987, 0xFFFFEFA1, 0x0000044B, 0x00001B06, 0xFFFFF788, 0x0000033C, 0x00001B06, 0xFFFFF788, 0x0000033C }, - { 0x0213F0FE992C28E4, 0x0000311D, 0xFFFFED20, 0x00000474, 0x000025DA, 0xFFFFF223, 0x000003F0, 0x000025DA, 0xFFFFF223, 0x000003F0 }, - { 0x0213F0FE992C1124, 0x000032A2, 0xFFFFEA0A, 0x0000050D, 0x00001D48, 0xFFFFF659, 0x0000034A, 0x00001D48, 0xFFFFF659, 0x0000034A }, - { 0x0213F0FE992208E4, 0x00003110, 0xFFFFE9EA, 0x00000529, 0x00001786, 0xFFFFF958, 0x000002DB, 0x00001786, 0xFFFFF958, 0x000002DB }, - { 0x0213F0FE992821A4, 0x000027F2, 0xFFFFF174, 0x000003F7, 0x00001C7A, 0xFFFFF72A, 0x00000348, 0x00001C7A, 0xFFFFF72A, 0x00000348 }, - { 0x0213F0FE991C10E4, 0x000031DB, 0xFFFFEA7D, 0x000004FB, 0x000019C4, 0xFFFFF8B1, 0x000002E6, 0x000019C4, 0xFFFFF8B1, 0x000002E6 }, - { 0x0213F0FE992C1104, 0x00003158, 0xFFFFEAAC, 0x000004FA, 0x00001BC1, 0xFFFFF737, 0x0000032B, 0x00001BC1, 0xFFFFF737, 0x0000032B }, - { 0x0213F0FE993010C4, 0x00002F36, 0xFFFFEBF9, 0x000004CA, 0x00001A2A, 0xFFFFF83F, 0x00000303, 0x00001A2A, 0xFFFFF83F, 0x00000303 }, - { 0x0213F0FE993238A4, 0x000032B4, 0xFFFFEA72, 0x000004FA, 0x000021FF, 0xFFFFF378, 0x000003C5, 0x000021FF, 0xFFFFF378, 0x000003C5 }, - { 0x0213F0FE99303164, 0x00003262, 0xFFFFEAFA, 0x000004DF, 0x00002441, 0xFFFFF237, 0x000003F6, 0x00002441, 0xFFFFF237, 0x000003F6 }, - { 0x0213F0FE99303924, 0x0000336A, 0xFFFFEAFB, 0x000004D1, 0x00002746, 0xFFFFF0B8, 0x0000042B, 0x00002746, 0xFFFFF0B8, 0x0000042B }, - { 0x0213F0FE991A4084, 0x000032E5, 0xFFFFE923, 0x00000541, 0x00001DF0, 0xFFFFF552, 0x00000380, 0x00001DF0, 0xFFFFF552, 0x00000380 }, - { 0x0213F0FE99304064, 0x000035D1, 0xFFFFE80B, 0x0000055F, 0x00002780, 0xFFFFEF74, 0x0000046F, 0x00002780, 0xFFFFEF74, 0x0000046F }, - { 0x0213F0FE993028A4, 0x000033EC, 0xFFFFEA48, 0x000004F4, 0x0000269F, 0xFFFFF0D8, 0x0000042A, 0x0000269F, 0xFFFFF0D8, 0x0000042A }, - { 0x0213F0FE99323884, 0x000030C4, 0xFFFFEB39, 0x000004E2, 0x00001B44, 0xFFFFF7AA, 0x00000318, 0x00001B44, 0xFFFFF7AA, 0x00000318 }, - { 0x0213F0FE99281144, 0x00002926, 0xFFFFF0AF, 0x0000040E, 0x0000194E, 0xFFFFF959, 0x000002E2, 0x0000194E, 0xFFFFF959, 0x000002E2 }, - { 0x0213F0FE992C10C4, 0x00003141, 0xFFFFEAAF, 0x000004F6, 0x00001864, 0xFFFFF97C, 0x000002C6, 0x00001864, 0xFFFFF97C, 0x000002C6 }, - { 0x0213F0FE99301064, 0x000030B2, 0xFFFFEB7C, 0x000004DB, 0x000022CE, 0xFFFFF2B5, 0x000003F0, 0x000022CE, 0xFFFFF2B5, 0x000003F0 }, - { 0x0213F0FE99301944, 0x0000318C, 0xFFFFEAC7, 0x000004F6, 0x00002113, 0xFFFFF3CA, 0x000003BD, 0x00002113, 0xFFFFF3CA, 0x000003BD }, - { 0x0213F0FE992E1104, 0x00002FD2, 0xFFFFEB8F, 0x000004D9, 0x00001996, 0xFFFFF89F, 0x000002F1, 0x00001996, 0xFFFFF89F, 0x000002F1 }, - { 0x0213F0FE991A28A4, 0x0000310D, 0xFFFFEB25, 0x000004E7, 0x00001F67, 0xFFFFF4EF, 0x0000038E, 0x00001F67, 0xFFFFF4EF, 0x0000038E }, - { 0x0213F0FE992A4964, 0x00002BBC, 0xFFFFEE68, 0x00000477, 0x00002050, 0xFFFFF41D, 0x000003C8, 0x00002050, 0xFFFFF41D, 0x000003C8 }, - { 0x0213F0FE99302104, 0x00003096, 0xFFFFECED, 0x00000486, 0x000024C9, 0xFFFFF278, 0x000003E7, 0x000024C9, 0xFFFFF278, 0x000003E7 }, - { 0x0213F0FE992C10A4, 0x00003401, 0xFFFFE8F1, 0x0000053C, 0x00001E75, 0xFFFFF55C, 0x00000376, 0x00001E75, 0xFFFFF55C, 0x00000376 }, - { 0x0213F0FE99302844, 0x0000319E, 0xFFFFEAB1, 0x000004F8, 0x00001EA3, 0xFFFFF567, 0x00000378, 0x00001EA3, 0xFFFFF567, 0x00000378 }, - { 0x0213F0FE99322964, 0x000030FD, 0xFFFFEB4C, 0x000004DB, 0x00001CA6, 0xFFFFF6E8, 0x00000335, 0x00001CA6, 0xFFFFF6E8, 0x00000335 }, - { 0x0213F0FE992E40A4, 0x000030D6, 0xFFFFEB1A, 0x000004E4, 0x00001A0D, 0xFFFFF87D, 0x000002EF, 0x00001A0D, 0xFFFFF87D, 0x000002EF }, - { 0x0213F0FE992C2124, 0x0000324B, 0xFFFFEB17, 0x000004D9, 0x00002225, 0xFFFFF3A8, 0x000003BA, 0x00002225, 0xFFFFF3A8, 0x000003BA }, - { 0x0213F0FE99284084, 0x00002A00, 0xFFFFF02E, 0x00000424, 0x00001E21, 0xFFFFF61D, 0x0000036C, 0x00001E21, 0xFFFFF61D, 0x0000036C }, - { 0x0213F0FE992A48A4, 0x000029CF, 0xFFFFEF53, 0x00000457, 0x00001B11, 0xFFFFF772, 0x0000033D, 0x00001B11, 0xFFFFF772, 0x0000033D }, - { 0x0213F0FE991A30A4, 0x000032A1, 0xFFFFEA63, 0x000004FB, 0x00001F83, 0xFFFFF516, 0x0000037E, 0x00001F83, 0xFFFFF516, 0x0000037E }, - { 0x0213F0FE992E20C4, 0x0000305C, 0xFFFFEC14, 0x000004B5, 0x00001D0B, 0xFFFFF6ED, 0x00000332, 0x00001D0B, 0xFFFFF6ED, 0x00000332 }, - { 0x0213F0FE992C1064, 0x00003467, 0xFFFFE8D5, 0x00000543, 0x0000243F, 0xFFFFF190, 0x00000418, 0x0000243F, 0xFFFFF190, 0x00000418 }, - { 0x0213F0FE992A2064, 0x00002796, 0xFFFFF133, 0x00000409, 0x00001903, 0xFFFFF91C, 0x000002FC, 0x00001903, 0xFFFFF91C, 0x000002FC }, - { 0x0213F0FE99302164, 0x000031F6, 0xFFFFEAB7, 0x000004F5, 0x000022B9, 0xFFFFF2D0, 0x000003E6, 0x000022B9, 0xFFFFF2D0, 0x000003E6 }, - { 0x0213F0FE992E5104, 0x00003196, 0xFFFFEA76, 0x00000503, 0x00001CC5, 0xFFFFF67D, 0x0000034A, 0x00001CC5, 0xFFFFF67D, 0x0000034A }, - { 0x0213F0FE99321144, 0x00002F9E, 0xFFFFEAD9, 0x00000505, 0x000017C1, 0xFFFFF93D, 0x000002DF, 0x000017C1, 0xFFFFF93D, 0x000002DF }, - { 0x0213F0FE992E2124, 0x00002FBC, 0xFFFFEC75, 0x000004A8, 0x00001D6D, 0xFFFFF6AC, 0x0000033D, 0x00001D6D, 0xFFFFF6AC, 0x0000033D }, - { 0x0213F0FE992C38A4, 0x00003541, 0xFFFFE921, 0x00000524, 0x00002662, 0xFFFFF0CB, 0x0000042B, 0x00002662, 0xFFFFF0CB, 0x0000042B }, - { 0x0213F0FE992A21A4, 0x00002953, 0xFFFFEF76, 0x00000459, 0x00001C05, 0xFFFFF6A0, 0x00000368, 0x00001C05, 0xFFFFF6A0, 0x00000368 }, - { 0x0213F0FE992C4924, 0x000034BC, 0xFFFFE8DD, 0x00000536, 0x0000210E, 0xFFFFF3F4, 0x000003A8, 0x0000210E, 0xFFFFF3F4, 0x000003A8 }, - { 0x0213F0FE992C29A4, 0x000034BE, 0xFFFFE916, 0x0000052F, 0x000024A1, 0xFFFFF1A6, 0x00000410, 0x000024A1, 0xFFFFF1A6, 0x00000410 }, - { 0x0213F0FE99304964, 0x000037B5, 0xFFFFE7A9, 0x0000055B, 0x000028A1, 0xFFFFEF51, 0x00000467, 0x000028A1, 0xFFFFEF51, 0x00000467 }, - { 0x0213F0FE99301104, 0x00002FC5, 0xFFFFEBBE, 0x000004D1, 0x00001BA5, 0xFFFFF757, 0x00000328, 0x00001BA5, 0xFFFFF757, 0x00000328 }, - { 0x0213F0FE993040A4, 0x000033CB, 0xFFFFE944, 0x0000052B, 0x00001FBE, 0xFFFFF4B1, 0x0000038C, 0x00001FBE, 0xFFFFF4B1, 0x0000038C }, - { 0x0213F0FE99301844, 0x000030AE, 0xFFFFEBA0, 0x000004D3, 0x00002268, 0xFFFFF316, 0x000003DD, 0x00002268, 0xFFFFF316, 0x000003DD }, - { 0x0213F0FE992C20A4, 0x00002F90, 0xFFFFEC5A, 0x000004B0, 0x00001C3A, 0xFFFFF752, 0x00000323, 0x00001C3A, 0xFFFFF752, 0x00000323 }, - { 0x0213F0FE992E38E4, 0x00003113, 0xFFFFEB91, 0x000004C8, 0x00001E3C, 0xFFFFF623, 0x0000034E, 0x00001E3C, 0xFFFFF623, 0x0000034E }, - { 0x0213F0FE99323984, 0x0000330B, 0xFFFFE94B, 0x00000539, 0x000020E7, 0xFFFFF37E, 0x000003CD, 0x000020E7, 0xFFFFF37E, 0x000003CD }, - { 0x0213F0FE992E2864, 0x000031D1, 0xFFFFEACB, 0x000004ED, 0x00001E82, 0xFFFFF5B2, 0x00000365, 0x00001E82, 0xFFFFF5B2, 0x00000365 }, - { 0x0213F0FE992A3984, 0x00002CD5, 0xFFFFEDC1, 0x0000048D, 0x000020F8, 0xFFFFF3C1, 0x000003D1, 0x000020F8, 0xFFFFF3C1, 0x000003D1 }, - { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } -}; - -int pp_override_get_default_fuse_value(uint64_t key, - struct phm_fuses_default *result) -{ - const struct phm_fuses_default *list = vega10_fuses_default; - uint32_t i; - - for (i = 0; list[i].key != 0; i++) { - if (key == list[i].key) { - result->key = list[i].key; - result->VFT2_m1 = list[i].VFT2_m1; - result->VFT2_m2 = list[i].VFT2_m2; - result->VFT2_b = list[i].VFT2_b; - result->VFT1_m1 = list[i].VFT1_m1; - result->VFT1_m2 = list[i].VFT1_m2; - result->VFT1_b = list[i].VFT1_b; - result->VFT0_m1 = list[i].VFT0_m1; - result->VFT0_m2 = list[i].VFT0_m2; - result->VFT0_b = list[i].VFT0_b; - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h deleted file mode 100644 index 4112a9398163..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 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 _PP_OVERDRIVER_H_ -#define _PP_OVERDRIVER_H_ - -#include -#include - -struct phm_fuses_default { - uint64_t key; - uint32_t VFT2_m1; - uint32_t VFT2_m2; - uint32_t VFT2_b; - uint32_t VFT1_m1; - uint32_t VFT1_m2; - uint32_t VFT1_b; - uint32_t VFT0_m1; - uint32_t VFT0_m2; - uint32_t VFT0_b; -}; - -extern int pp_override_get_default_fuse_value(uint64_t key, - struct phm_fuses_default *result); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c deleted file mode 100644 index 31a32a79cfc2..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include -#include -#include -#include "pp_psm.h" - -int psm_init_power_state_table(struct pp_hwmgr *hwmgr) -{ - int result; - unsigned int i; - unsigned int table_entries; - struct pp_power_state *state; - int size; - - if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) - return 0; - - if (hwmgr->hwmgr_func->get_power_state_size == NULL) - return 0; - - hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); - - hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + - sizeof(struct pp_power_state); - - if (table_entries == 0 || size == 0) { - pr_warn("Please check whether power state management is supported on this asic\n"); - return 0; - } - - hwmgr->ps = kcalloc(table_entries, size, GFP_KERNEL); - if (hwmgr->ps == NULL) - return -ENOMEM; - - hwmgr->request_ps = kzalloc(size, GFP_KERNEL); - if (hwmgr->request_ps == NULL) { - kfree(hwmgr->ps); - hwmgr->ps = NULL; - return -ENOMEM; - } - - hwmgr->current_ps = kzalloc(size, GFP_KERNEL); - if (hwmgr->current_ps == NULL) { - kfree(hwmgr->request_ps); - kfree(hwmgr->ps); - hwmgr->request_ps = NULL; - hwmgr->ps = NULL; - return -ENOMEM; - } - - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); - - if (state->classification.flags & PP_StateClassificationFlag_Boot) { - hwmgr->boot_ps = state; - memcpy(hwmgr->current_ps, state, size); - memcpy(hwmgr->request_ps, state, size); - } - - state->id = i + 1; /* assigned unique num for every power state id */ - - if (state->classification.flags & PP_StateClassificationFlag_Uvd) - hwmgr->uvd_ps = state; - state = (struct pp_power_state *)((unsigned long)state + size); - } - - return 0; -} - -int psm_fini_power_state_table(struct pp_hwmgr *hwmgr) -{ - if (hwmgr == NULL) - return -EINVAL; - - if (!hwmgr->ps) - return 0; - - kfree(hwmgr->current_ps); - kfree(hwmgr->request_ps); - kfree(hwmgr->ps); - hwmgr->request_ps = NULL; - hwmgr->ps = NULL; - hwmgr->current_ps = NULL; - return 0; -} - -static int psm_get_ui_state(struct pp_hwmgr *hwmgr, - enum PP_StateUILabel ui_label, - unsigned long *state_id) -{ - struct pp_power_state *state; - int table_entries; - int i; - - table_entries = hwmgr->num_ps; - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->classification.ui_label & ui_label) { - *state_id = state->id; - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -EINVAL; -} - -static int psm_get_state_by_classification(struct pp_hwmgr *hwmgr, - enum PP_StateClassificationFlag flag, - unsigned long *state_id) -{ - struct pp_power_state *state; - int table_entries; - int i; - - table_entries = hwmgr->num_ps; - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->classification.flags & flag) { - *state_id = state->id; - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -EINVAL; -} - -static int psm_set_states(struct pp_hwmgr *hwmgr, unsigned long state_id) -{ - struct pp_power_state *state; - int table_entries; - int i; - - table_entries = hwmgr->num_ps; - - state = hwmgr->ps; - - for (i = 0; i < table_entries; i++) { - if (state->id == state_id) { - memcpy(hwmgr->request_ps, state, hwmgr->ps_size); - return 0; - } - state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); - } - return -EINVAL; -} - -int psm_set_boot_states(struct pp_hwmgr *hwmgr) -{ - unsigned long state_id; - int ret = -EINVAL; - - if (!hwmgr->ps) - return 0; - - if (!psm_get_state_by_classification(hwmgr, PP_StateClassificationFlag_Boot, - &state_id)) - ret = psm_set_states(hwmgr, state_id); - - return ret; -} - -int psm_set_performance_states(struct pp_hwmgr *hwmgr) -{ - unsigned long state_id; - int ret = -EINVAL; - - if (!hwmgr->ps) - return 0; - - if (!psm_get_ui_state(hwmgr, PP_StateUILabel_Performance, - &state_id)) - ret = psm_set_states(hwmgr, state_id); - - return ret; -} - -int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, - enum PP_StateUILabel label_id, - struct pp_power_state **state) -{ - int table_entries; - int i; - - if (!hwmgr->ps) - return 0; - - table_entries = hwmgr->num_ps; - *state = hwmgr->ps; - -restart_search: - for (i = 0; i < table_entries; i++) { - if ((*state)->classification.ui_label & label_id) - return 0; - *state = (struct pp_power_state *)((uintptr_t)*state + hwmgr->ps_size); - } - - switch (label_id) { - case PP_StateUILabel_Battery: - case PP_StateUILabel_Balanced: - label_id = PP_StateUILabel_Performance; - goto restart_search; - default: - break; - } - return -EINVAL; -} - -static void power_state_management(struct pp_hwmgr *hwmgr, - struct pp_power_state *new_ps) -{ - struct pp_power_state *pcurrent; - struct pp_power_state *requested; - bool equal; - - if (new_ps != NULL) - requested = new_ps; - else - requested = hwmgr->request_ps; - - pcurrent = hwmgr->current_ps; - - phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); - if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, - &pcurrent->hardware, &requested->hardware, &equal))) - equal = false; - - if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { - phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); - memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); - } -} - -int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip_display_settings, - struct pp_power_state *new_ps) -{ - uint32_t index; - long workload; - - if (hwmgr->not_vf) { - if (!skip_display_settings) - phm_display_configuration_changed(hwmgr); - - if (hwmgr->ps) - power_state_management(hwmgr, new_ps); - else - /* - * for vega12/vega20 which does not support power state manager - * DAL clock limits should also be honoured - */ - phm_apply_clock_adjust_rules(hwmgr); - - if (!skip_display_settings) - phm_notify_smc_display_config_after_ps_adjustment(hwmgr); - } - - if (!phm_force_dpm_levels(hwmgr, hwmgr->request_dpm_level)) - hwmgr->dpm_level = hwmgr->request_dpm_level; - - if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { - index = fls(hwmgr->workload_mask); - index = index > 0 && index <= Workload_Policy_Max ? index - 1 : 0; - workload = hwmgr->workload_setting[index]; - - if (hwmgr->power_profile_mode != workload && hwmgr->hwmgr_func->set_power_profile_mode) - hwmgr->hwmgr_func->set_power_profile_mode(hwmgr, &workload, 0); - } - - return 0; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h deleted file mode 100644 index b62d55f1f289..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef PP_PSM_H -#define PP_PSM_H - -#include "hwmgr.h" - -int psm_init_power_state_table(struct pp_hwmgr *hwmgr); -int psm_fini_power_state_table(struct pp_hwmgr *hwmgr); -int psm_set_boot_states(struct pp_hwmgr *hwmgr); -int psm_set_performance_states(struct pp_hwmgr *hwmgr); -int psm_set_user_performance_state(struct pp_hwmgr *hwmgr, - enum PP_StateUILabel label_id, - struct pp_power_state **state); -int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, - bool skip_display_settings, - struct pp_power_state *new_ps); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c deleted file mode 100644 index 01dc46dc9c8a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c +++ /dev/null @@ -1,1562 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include "atom.h" -#include "ppatomctrl.h" -#include "atombios.h" -#include "cgs_common.h" -#include "ppevvmath.h" - -#define MEM_ID_MASK 0xff000000 -#define MEM_ID_SHIFT 24 -#define CLOCK_RANGE_MASK 0x00ffffff -#define CLOCK_RANGE_SHIFT 0 -#define LOW_NIBBLE_MASK 0xf -#define DATA_EQU_PREV 0 -#define DATA_FROM_TABLE 4 - -union voltage_object_info { - struct _ATOM_VOLTAGE_OBJECT_INFO v1; - struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; - struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3; -}; - -static int atomctrl_retrieve_ac_timing( - uint8_t index, - ATOM_INIT_REG_BLOCK *reg_block, - pp_atomctrl_mc_reg_table *table) -{ - uint32_t i, j; - uint8_t tmem_id; - ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) - ((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize)); - - uint8_t num_ranges = 0; - - while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK && - num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) { - tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT); - - if (index == tmem_id) { - table->mc_reg_table_entry[num_ranges].mclk_max = - (uint32_t)((*(uint32_t *)reg_data & CLOCK_RANGE_MASK) >> - CLOCK_RANGE_SHIFT); - - for (i = 0, j = 1; i < table->last; i++) { - if ((table->mc_reg_address[i].uc_pre_reg_data & - LOW_NIBBLE_MASK) == DATA_FROM_TABLE) { - table->mc_reg_table_entry[num_ranges].mc_data[i] = - (uint32_t)*((uint32_t *)reg_data + j); - j++; - } else if ((table->mc_reg_address[i].uc_pre_reg_data & - LOW_NIBBLE_MASK) == DATA_EQU_PREV) { - table->mc_reg_table_entry[num_ranges].mc_data[i] = - table->mc_reg_table_entry[num_ranges].mc_data[i-1]; - } - } - num_ranges++; - } - - reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) - ((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ; - } - - PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK), - "Invalid VramInfo table.", return -1); - table->num_entries = num_ranges; - - return 0; -} - -/** - * Get memory clock AC timing registers index from VBIOS table - * VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 1 - * @param reg_block the address ATOM_INIT_REG_BLOCK - * @param table the address of MCRegTable - * @return 0 - */ -static int atomctrl_set_mc_reg_address_table( - ATOM_INIT_REG_BLOCK *reg_block, - pp_atomctrl_mc_reg_table *table) -{ - uint8_t i = 0; - uint8_t num_entries = (uint8_t)((le16_to_cpu(reg_block->usRegIndexTblSize)) - / sizeof(ATOM_INIT_REG_INDEX_FORMAT)); - ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0]; - - num_entries--; /* subtract 1 data end mark entry */ - - PP_ASSERT_WITH_CODE((num_entries <= VBIOS_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -1); - - /* ucPreRegDataLength bit6 = 1 is the end of memory clock AC timing registers */ - while ((!(format->ucPreRegDataLength & ACCESS_PLACEHOLDER)) && - (i < num_entries)) { - table->mc_reg_address[i].s1 = - (uint16_t)(le16_to_cpu(format->usRegIndex)); - table->mc_reg_address[i].uc_pre_reg_data = - format->ucPreRegDataLength; - - i++; - format = (ATOM_INIT_REG_INDEX_FORMAT *) - ((uint8_t *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT)); - } - - table->last = i; - return 0; -} - -int atomctrl_initialize_mc_reg_table( - struct pp_hwmgr *hwmgr, - uint8_t module_index, - pp_atomctrl_mc_reg_table *table) -{ - ATOM_VRAM_INFO_HEADER_V2_1 *vram_info; - ATOM_INIT_REG_BLOCK *reg_block; - int result = 0; - u8 frev, crev; - u16 size; - - vram_info = (ATOM_VRAM_INFO_HEADER_V2_1 *) - smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev); - - if (module_index >= vram_info->ucNumOfVRAMModule) { - pr_err("Invalid VramInfo table."); - result = -1; - } else if (vram_info->sHeader.ucTableFormatRevision < 2) { - pr_err("Invalid VramInfo table."); - result = -1; - } - - if (0 == result) { - reg_block = (ATOM_INIT_REG_BLOCK *) - ((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset)); - result = atomctrl_set_mc_reg_address_table(reg_block, table); - } - - if (0 == result) { - result = atomctrl_retrieve_ac_timing(module_index, - reg_block, table); - } - - return result; -} - -/** - * Set DRAM timings based on engine clock and memory clock. - */ -int atomctrl_set_engine_dram_timings_rv770( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock) -{ - struct amdgpu_device *adev = hwmgr->adev; - - SET_ENGINE_CLOCK_PS_ALLOCATION engine_clock_parameters; - - /* They are both in 10KHz Units. */ - engine_clock_parameters.ulTargetEngineClock = - cpu_to_le32((engine_clock & SET_CLOCK_FREQ_MASK) | - ((COMPUTE_ENGINE_PLL_PARAM << 24))); - - /* in 10 khz units.*/ - engine_clock_parameters.sReserved.ulClock = - cpu_to_le32(memory_clock & SET_CLOCK_FREQ_MASK); - - return amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings), - (uint32_t *)&engine_clock_parameters); -} - -/** - * Private Function to get the PowerPlay Table Address. - * WARNING: The tabled returned by this function is in - * dynamically allocated memory. - * The caller has to release if by calling kfree. - */ -static ATOM_VOLTAGE_OBJECT_INFO *get_voltage_info_table(void *device) -{ - int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); - u8 frev, crev; - u16 size; - union voltage_object_info *voltage_info; - - voltage_info = (union voltage_object_info *) - smu_atom_get_data_table(device, index, - &size, &frev, &crev); - - if (voltage_info != NULL) - return (ATOM_VOLTAGE_OBJECT_INFO *) &(voltage_info->v3); - else - return NULL; -} - -static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3( - const ATOM_VOLTAGE_OBJECT_INFO_V3_1 * voltage_object_info_table, - uint8_t voltage_type, uint8_t voltage_mode) -{ - unsigned int size = le16_to_cpu(voltage_object_info_table->sHeader.usStructureSize); - unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]); - uint8_t *start = (uint8_t *)voltage_object_info_table; - - while (offset < size) { - const ATOM_VOLTAGE_OBJECT_V3 *voltage_object = - (const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset); - - if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType && - voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode) - return voltage_object; - - offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize); - } - - return NULL; -} - -/** atomctrl_get_memory_pll_dividers_si(). - * - * @param hwmgr input parameter: pointer to HwMgr - * @param clock_value input parameter: memory clock - * @param dividers output parameter: memory PLL dividers - * @param strobe_mode input parameter: 1 for strobe mode, 0 for performance mode - */ -int atomctrl_get_memory_pll_dividers_si( - struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_memory_clock_param *mpll_param, - bool strobe_mode) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 mpll_parameters; - int result; - - mpll_parameters.ulClock = cpu_to_le32(clock_value); - mpll_parameters.ucInputFlag = (uint8_t)((strobe_mode) ? 1 : 0); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), - (uint32_t *)&mpll_parameters); - - if (0 == result) { - mpll_param->mpll_fb_divider.clk_frac = - le16_to_cpu(mpll_parameters.ulFbDiv.usFbDivFrac); - mpll_param->mpll_fb_divider.cl_kf = - le16_to_cpu(mpll_parameters.ulFbDiv.usFbDiv); - mpll_param->mpll_post_divider = - (uint32_t)mpll_parameters.ucPostDiv; - mpll_param->vco_mode = - (uint32_t)(mpll_parameters.ucPllCntlFlag & - MPLL_CNTL_FLAG_VCO_MODE_MASK); - mpll_param->yclk_sel = - (uint32_t)((mpll_parameters.ucPllCntlFlag & - MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0); - mpll_param->qdr = - (uint32_t)((mpll_parameters.ucPllCntlFlag & - MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0); - mpll_param->half_rate = - (uint32_t)((mpll_parameters.ucPllCntlFlag & - MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0); - mpll_param->dll_speed = - (uint32_t)(mpll_parameters.ucDllSpeed); - mpll_param->bw_ctrl = - (uint32_t)(mpll_parameters.ucBWCntl); - } - - return result; -} - -/** atomctrl_get_memory_pll_dividers_vi(). - * - * @param hwmgr input parameter: pointer to HwMgr - * @param clock_value input parameter: memory clock - * @param dividers output parameter: memory PLL dividers - */ -int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, - uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 mpll_parameters; - int result; - - mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), - (uint32_t *)&mpll_parameters); - - if (!result) - mpll_param->mpll_post_divider = - (uint32_t)mpll_parameters.ulClock.ucPostDiv; - - return result; -} - -int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_memory_clock_param_ai *mpll_param) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_3 mpll_parameters = {{0}, 0, 0}; - int result; - - mpll_parameters.ulClock.ulClock = cpu_to_le32(clock_value); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), - (uint32_t *)&mpll_parameters); - - /* VEGAM's mpll takes sometime to finish computing */ - udelay(10); - - if (!result) { - mpll_param->ulMclk_fcw_int = - le16_to_cpu(mpll_parameters.usMclk_fcw_int); - mpll_param->ulMclk_fcw_frac = - le16_to_cpu(mpll_parameters.usMclk_fcw_frac); - mpll_param->ulClock = - le32_to_cpu(mpll_parameters.ulClock.ulClock); - mpll_param->ulPostDiv = mpll_parameters.ulClock.ucPostDiv; - } - - return result; -} - -int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_clock_dividers_kong *dividers) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 pll_parameters; - int result; - - pll_parameters.ulClock = cpu_to_le32(clock_value); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), - (uint32_t *)&pll_parameters); - - if (0 == result) { - dividers->pll_post_divider = pll_parameters.ucPostDiv; - dividers->real_clock = le32_to_cpu(pll_parameters.ulClock); - } - - return result; -} - -int atomctrl_get_engine_pll_dividers_vi( - struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_clock_dividers_vi *dividers) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; - int result; - - pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); - pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), - (uint32_t *)&pll_patameters); - - if (0 == result) { - dividers->pll_post_divider = - pll_patameters.ulClock.ucPostDiv; - dividers->real_clock = - le32_to_cpu(pll_patameters.ulClock.ulClock); - - dividers->ul_fb_div.ul_fb_div_frac = - le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac); - dividers->ul_fb_div.ul_fb_div = - le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv); - - dividers->uc_pll_ref_div = - pll_patameters.ucPllRefDiv; - dividers->uc_pll_post_div = - pll_patameters.ucPllPostDiv; - dividers->uc_pll_cntl_flag = - pll_patameters.ucPllCntlFlag; - } - - return result; -} - -int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_clock_dividers_ai *dividers) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_7 pll_patameters; - int result; - - pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); - pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), - (uint32_t *)&pll_patameters); - - if (0 == result) { - dividers->usSclk_fcw_frac = le16_to_cpu(pll_patameters.usSclk_fcw_frac); - dividers->usSclk_fcw_int = le16_to_cpu(pll_patameters.usSclk_fcw_int); - dividers->ucSclkPostDiv = pll_patameters.ucSclkPostDiv; - dividers->ucSclkVcoMode = pll_patameters.ucSclkVcoMode; - dividers->ucSclkPllRange = pll_patameters.ucSclkPllRange; - dividers->ucSscEnable = pll_patameters.ucSscEnable; - dividers->usSsc_fcw1_frac = le16_to_cpu(pll_patameters.usSsc_fcw1_frac); - dividers->usSsc_fcw1_int = le16_to_cpu(pll_patameters.usSsc_fcw1_int); - dividers->usPcc_fcw_int = le16_to_cpu(pll_patameters.usPcc_fcw_int); - dividers->usSsc_fcw_slew_frac = le16_to_cpu(pll_patameters.usSsc_fcw_slew_frac); - dividers->usPcc_fcw_slew_frac = le16_to_cpu(pll_patameters.usPcc_fcw_slew_frac); - } - return result; -} - -int atomctrl_get_dfs_pll_dividers_vi( - struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_clock_dividers_vi *dividers) -{ - struct amdgpu_device *adev = hwmgr->adev; - COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; - int result; - - pll_patameters.ulClock.ulClock = cpu_to_le32(clock_value); - pll_patameters.ulClock.ucPostDiv = - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), - (uint32_t *)&pll_patameters); - - if (0 == result) { - dividers->pll_post_divider = - pll_patameters.ulClock.ucPostDiv; - dividers->real_clock = - le32_to_cpu(pll_patameters.ulClock.ulClock); - - dividers->ul_fb_div.ul_fb_div_frac = - le16_to_cpu(pll_patameters.ulFbDiv.usFbDivFrac); - dividers->ul_fb_div.ul_fb_div = - le16_to_cpu(pll_patameters.ulFbDiv.usFbDiv); - - dividers->uc_pll_ref_div = - pll_patameters.ucPllRefDiv; - dividers->uc_pll_post_div = - pll_patameters.ucPllPostDiv; - dividers->uc_pll_cntl_flag = - pll_patameters.ucPllCntlFlag; - } - - return result; -} - -/** - * Get the reference clock in 10KHz - */ -uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) -{ - ATOM_FIRMWARE_INFO *fw_info; - u8 frev, crev; - u16 size; - uint32_t clock; - - fw_info = (ATOM_FIRMWARE_INFO *) - smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, FirmwareInfo), - &size, &frev, &crev); - - if (fw_info == NULL) - clock = 2700; - else - clock = (uint32_t)(le16_to_cpu(fw_info->usReferenceClock)); - - return clock; -} - -/** - * Returns true if the given voltage type is controlled by GPIO pins. - * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, - * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. - * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE - */ -bool atomctrl_is_voltage_controlled_by_gpio_v3( - struct pp_hwmgr *hwmgr, - uint8_t voltage_type, - uint8_t voltage_mode) -{ - ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = - (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); - bool ret; - - PP_ASSERT_WITH_CODE((NULL != voltage_info), - "Could not find Voltage Table in BIOS.", return false;); - - ret = (NULL != atomctrl_lookup_voltage_type_v3 - (voltage_info, voltage_type, voltage_mode)) ? true : false; - - return ret; -} - -int atomctrl_get_voltage_table_v3( - struct pp_hwmgr *hwmgr, - uint8_t voltage_type, - uint8_t voltage_mode, - pp_atomctrl_voltage_table *voltage_table) -{ - ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = - (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); - const ATOM_VOLTAGE_OBJECT_V3 *voltage_object; - unsigned int i; - - PP_ASSERT_WITH_CODE((NULL != voltage_info), - "Could not find Voltage Table in BIOS.", return -1;); - - voltage_object = atomctrl_lookup_voltage_type_v3 - (voltage_info, voltage_type, voltage_mode); - - if (voltage_object == NULL) - return -1; - - PP_ASSERT_WITH_CODE( - (voltage_object->asGpioVoltageObj.ucGpioEntryNum <= - PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES), - "Too many voltage entries!", - return -1; - ); - - for (i = 0; i < voltage_object->asGpioVoltageObj.ucGpioEntryNum; i++) { - voltage_table->entries[i].value = - le16_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].usVoltageValue); - voltage_table->entries[i].smio_low = - le32_to_cpu(voltage_object->asGpioVoltageObj.asVolGpioLut[i].ulVoltageId); - } - - voltage_table->mask_low = - le32_to_cpu(voltage_object->asGpioVoltageObj.ulGpioMaskVal); - voltage_table->count = - voltage_object->asGpioVoltageObj.ucGpioEntryNum; - voltage_table->phase_delay = - voltage_object->asGpioVoltageObj.ucPhaseDelay; - - return 0; -} - -static bool atomctrl_lookup_gpio_pin( - ATOM_GPIO_PIN_LUT * gpio_lookup_table, - const uint32_t pinId, - pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - unsigned int size = le16_to_cpu(gpio_lookup_table->sHeader.usStructureSize); - unsigned int offset = offsetof(ATOM_GPIO_PIN_LUT, asGPIO_Pin[0]); - uint8_t *start = (uint8_t *)gpio_lookup_table; - - while (offset < size) { - const ATOM_GPIO_PIN_ASSIGNMENT *pin_assignment = - (const ATOM_GPIO_PIN_ASSIGNMENT *)(start + offset); - - if (pinId == pin_assignment->ucGPIO_ID) { - gpio_pin_assignment->uc_gpio_pin_bit_shift = - pin_assignment->ucGpioPinBitShift; - gpio_pin_assignment->us_gpio_pin_aindex = - le16_to_cpu(pin_assignment->usGpioPin_AIndex); - return true; - } - - offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1; - } - - return false; -} - -/** - * Private Function to get the PowerPlay Table Address. - * WARNING: The tabled returned by this function is in - * dynamically allocated memory. - * The caller has to release if by calling kfree. - */ -static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device) -{ - u8 frev, crev; - u16 size; - void *table_address; - - table_address = (ATOM_GPIO_PIN_LUT *) - smu_atom_get_data_table(device, - GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT), - &size, &frev, &crev); - - PP_ASSERT_WITH_CODE((NULL != table_address), - "Error retrieving BIOS Table Address!", return NULL;); - - return (ATOM_GPIO_PIN_LUT *)table_address; -} - -/** - * Returns 1 if the given pin id find in lookup table. - */ -bool atomctrl_get_pp_assign_pin( - struct pp_hwmgr *hwmgr, - const uint32_t pinId, - pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - bool bRet = false; - ATOM_GPIO_PIN_LUT *gpio_lookup_table = - get_gpio_lookup_table(hwmgr->adev); - - PP_ASSERT_WITH_CODE((NULL != gpio_lookup_table), - "Could not find GPIO lookup Table in BIOS.", return false); - - bRet = atomctrl_lookup_gpio_pin(gpio_lookup_table, pinId, - gpio_pin_assignment); - - return bRet; -} - -int atomctrl_calculate_voltage_evv_on_sclk( - struct pp_hwmgr *hwmgr, - uint8_t voltage_type, - uint32_t sclk, - uint16_t virtual_voltage_Id, - uint16_t *voltage, - uint16_t dpm_level, - bool debug) -{ - ATOM_ASIC_PROFILING_INFO_V3_4 *getASICProfilingInfo; - struct amdgpu_device *adev = hwmgr->adev; - EFUSE_LINEAR_FUNC_PARAM sRO_fuse; - EFUSE_LINEAR_FUNC_PARAM sCACm_fuse; - EFUSE_LINEAR_FUNC_PARAM sCACb_fuse; - EFUSE_LOGISTIC_FUNC_PARAM sKt_Beta_fuse; - EFUSE_LOGISTIC_FUNC_PARAM sKv_m_fuse; - EFUSE_LOGISTIC_FUNC_PARAM sKv_b_fuse; - EFUSE_INPUT_PARAMETER sInput_FuseValues; - READ_EFUSE_VALUE_PARAMETER sOutput_FuseValues; - - uint32_t ul_RO_fused, ul_CACb_fused, ul_CACm_fused, ul_Kt_Beta_fused, ul_Kv_m_fused, ul_Kv_b_fused; - fInt fSM_A0, fSM_A1, fSM_A2, fSM_A3, fSM_A4, fSM_A5, fSM_A6, fSM_A7; - fInt fMargin_RO_a, fMargin_RO_b, fMargin_RO_c, fMargin_fixed, fMargin_FMAX_mean, fMargin_Plat_mean, fMargin_FMAX_sigma, fMargin_Plat_sigma, fMargin_DC_sigma; - fInt fLkg_FT, repeat; - fInt fMicro_FMAX, fMicro_CR, fSigma_FMAX, fSigma_CR, fSigma_DC, fDC_SCLK, fSquared_Sigma_DC, fSquared_Sigma_CR, fSquared_Sigma_FMAX; - fInt fRLL_LoadLine, fPowerDPMx, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin; - fInt fRO_fused, fCACm_fused, fCACb_fused, fKv_m_fused, fKv_b_fused, fKt_Beta_fused, fFT_Lkg_V0NORM; - fInt fSclk_margin, fSclk, fEVV_V; - fInt fV_min, fV_max, fT_prod, fLKG_Factor, fT_FT, fV_FT, fV_x, fTDP_Power, fTDP_Power_right, fTDP_Power_left, fTDP_Current, fV_NL; - uint32_t ul_FT_Lkg_V0NORM; - fInt fLn_MaxDivMin, fMin, fAverage, fRange; - fInt fRoots[2]; - fInt fStepSize = GetScaledFraction(625, 100000); - - int result; - - getASICProfilingInfo = (ATOM_ASIC_PROFILING_INFO_V3_4 *) - smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), - NULL, NULL, NULL); - - if (!getASICProfilingInfo) - return -1; - - if (getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 || - (getASICProfilingInfo->asHeader.ucTableFormatRevision == 3 && - getASICProfilingInfo->asHeader.ucTableContentRevision < 4)) - return -1; - - /*----------------------------------------------------------- - *GETTING MULTI-STEP PARAMETERS RELATED TO CURRENT DPM LEVEL - *----------------------------------------------------------- - */ - fRLL_LoadLine = Divide(getASICProfilingInfo->ulLoadLineSlop, 1000); - - switch (dpm_level) { - case 1: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm1)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM1), 1000); - break; - case 2: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm2)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM2), 1000); - break; - case 3: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm3)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM3), 1000); - break; - case 4: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm4)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM4), 1000); - break; - case 5: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm5)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM5), 1000); - break; - case 6: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm6)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM6), 1000); - break; - case 7: - fPowerDPMx = Convert_ULONG_ToFraction(le16_to_cpu(getASICProfilingInfo->usPowerDpm7)); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM7), 1000); - break; - default: - pr_err("DPM Level not supported\n"); - fPowerDPMx = Convert_ULONG_ToFraction(1); - fDerateTDP = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulTdpDerateDPM0), 1000); - } - - /*------------------------- - * DECODING FUSE VALUES - * ------------------------ - */ - /*Decode RO_Fused*/ - sRO_fuse = getASICProfilingInfo->sRoFuse; - - sInput_FuseValues.usEfuseIndex = sRO_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sRO_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sRO_fuse.ucEfuseLength; - - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - /* Finally, the actual fuse value */ - ul_RO_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fMin = GetScaledFraction(le32_to_cpu(sRO_fuse.ulEfuseMin), 1); - fRange = GetScaledFraction(le32_to_cpu(sRO_fuse.ulEfuseEncodeRange), 1); - fRO_fused = fDecodeLinearFuse(ul_RO_fused, fMin, fRange, sRO_fuse.ucEfuseLength); - - sCACm_fuse = getASICProfilingInfo->sCACm; - - sInput_FuseValues.usEfuseIndex = sCACm_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sCACm_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sCACm_fuse.ucEfuseLength; - - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - ul_CACm_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fMin = GetScaledFraction(le32_to_cpu(sCACm_fuse.ulEfuseMin), 1000); - fRange = GetScaledFraction(le32_to_cpu(sCACm_fuse.ulEfuseEncodeRange), 1000); - - fCACm_fused = fDecodeLinearFuse(ul_CACm_fused, fMin, fRange, sCACm_fuse.ucEfuseLength); - - sCACb_fuse = getASICProfilingInfo->sCACb; - - sInput_FuseValues.usEfuseIndex = sCACb_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sCACb_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sCACb_fuse.ucEfuseLength; - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - ul_CACb_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fMin = GetScaledFraction(le32_to_cpu(sCACb_fuse.ulEfuseMin), 1000); - fRange = GetScaledFraction(le32_to_cpu(sCACb_fuse.ulEfuseEncodeRange), 1000); - - fCACb_fused = fDecodeLinearFuse(ul_CACb_fused, fMin, fRange, sCACb_fuse.ucEfuseLength); - - sKt_Beta_fuse = getASICProfilingInfo->sKt_b; - - sInput_FuseValues.usEfuseIndex = sKt_Beta_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sKt_Beta_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sKt_Beta_fuse.ucEfuseLength; - - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - ul_Kt_Beta_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fAverage = GetScaledFraction(le32_to_cpu(sKt_Beta_fuse.ulEfuseEncodeAverage), 1000); - fRange = GetScaledFraction(le32_to_cpu(sKt_Beta_fuse.ulEfuseEncodeRange), 1000); - - fKt_Beta_fused = fDecodeLogisticFuse(ul_Kt_Beta_fused, - fAverage, fRange, sKt_Beta_fuse.ucEfuseLength); - - sKv_m_fuse = getASICProfilingInfo->sKv_m; - - sInput_FuseValues.usEfuseIndex = sKv_m_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sKv_m_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sKv_m_fuse.ucEfuseLength; - - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - if (result) - return result; - - ul_Kv_m_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fAverage = GetScaledFraction(le32_to_cpu(sKv_m_fuse.ulEfuseEncodeAverage), 1000); - fRange = GetScaledFraction((le32_to_cpu(sKv_m_fuse.ulEfuseEncodeRange) & 0x7fffffff), 1000); - fRange = fMultiply(fRange, ConvertToFraction(-1)); - - fKv_m_fused = fDecodeLogisticFuse(ul_Kv_m_fused, - fAverage, fRange, sKv_m_fuse.ucEfuseLength); - - sKv_b_fuse = getASICProfilingInfo->sKv_b; - - sInput_FuseValues.usEfuseIndex = sKv_b_fuse.usEfuseIndex; - sInput_FuseValues.ucBitShift = sKv_b_fuse.ucEfuseBitLSB; - sInput_FuseValues.ucBitLength = sKv_b_fuse.ucEfuseLength; - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - ul_Kv_b_fused = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fAverage = GetScaledFraction(le32_to_cpu(sKv_b_fuse.ulEfuseEncodeAverage), 1000); - fRange = GetScaledFraction(le32_to_cpu(sKv_b_fuse.ulEfuseEncodeRange), 1000); - - fKv_b_fused = fDecodeLogisticFuse(ul_Kv_b_fused, - fAverage, fRange, sKv_b_fuse.ucEfuseLength); - - /* Decoding the Leakage - No special struct container */ - /* - * usLkgEuseIndex=56 - * ucLkgEfuseBitLSB=6 - * ucLkgEfuseLength=10 - * ulLkgEncodeLn_MaxDivMin=69077 - * ulLkgEncodeMax=1000000 - * ulLkgEncodeMin=1000 - * ulEfuseLogisticAlpha=13 - */ - - sInput_FuseValues.usEfuseIndex = getASICProfilingInfo->usLkgEuseIndex; - sInput_FuseValues.ucBitShift = getASICProfilingInfo->ucLkgEfuseBitLSB; - sInput_FuseValues.ucBitLength = getASICProfilingInfo->ucLkgEfuseLength; - - sOutput_FuseValues.sEfuse = sInput_FuseValues; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&sOutput_FuseValues); - - if (result) - return result; - - ul_FT_Lkg_V0NORM = le32_to_cpu(sOutput_FuseValues.ulEfuseValue); - fLn_MaxDivMin = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLkgEncodeLn_MaxDivMin), 10000); - fMin = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLkgEncodeMin), 10000); - - fFT_Lkg_V0NORM = fDecodeLeakageID(ul_FT_Lkg_V0NORM, - fLn_MaxDivMin, fMin, getASICProfilingInfo->ucLkgEfuseLength); - fLkg_FT = fFT_Lkg_V0NORM; - - /*------------------------------------------- - * PART 2 - Grabbing all required values - *------------------------------------------- - */ - fSM_A0 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A0), 1000000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A0_sign))); - fSM_A1 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A1), 1000000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A1_sign))); - fSM_A2 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A2), 100000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A2_sign))); - fSM_A3 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A3), 1000000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A3_sign))); - fSM_A4 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A4), 1000000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A4_sign))); - fSM_A5 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A5), 1000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A5_sign))); - fSM_A6 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A6), 1000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A6_sign))); - fSM_A7 = fMultiply(GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulSM_A7), 1000), - ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A7_sign))); - - fMargin_RO_a = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_a)); - fMargin_RO_b = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_b)); - fMargin_RO_c = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_RO_c)); - - fMargin_fixed = ConvertToFraction(le32_to_cpu(getASICProfilingInfo->ulMargin_fixed)); - - fMargin_FMAX_mean = GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMargin_Fmax_mean), 10000); - fMargin_Plat_mean = GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMargin_plat_mean), 10000); - fMargin_FMAX_sigma = GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMargin_Fmax_sigma), 10000); - fMargin_Plat_sigma = GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMargin_plat_sigma), 10000); - - fMargin_DC_sigma = GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMargin_DC_sigma), 100); - fMargin_DC_sigma = fDivide(fMargin_DC_sigma, ConvertToFraction(1000)); - - fCACm_fused = fDivide(fCACm_fused, ConvertToFraction(100)); - fCACb_fused = fDivide(fCACb_fused, ConvertToFraction(100)); - fKt_Beta_fused = fDivide(fKt_Beta_fused, ConvertToFraction(100)); - fKv_m_fused = fNegate(fDivide(fKv_m_fused, ConvertToFraction(100))); - fKv_b_fused = fDivide(fKv_b_fused, ConvertToFraction(10)); - - fSclk = GetScaledFraction(sclk, 100); - - fV_max = fDivide(GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMaxVddc), 1000), ConvertToFraction(4)); - fT_prod = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulBoardCoreTemp), 10); - fLKG_Factor = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulEvvLkgFactor), 100); - fT_FT = GetScaledFraction(le32_to_cpu(getASICProfilingInfo->ulLeakageTemp), 10); - fV_FT = fDivide(GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulLeakageVoltage), 1000), ConvertToFraction(4)); - fV_min = fDivide(GetScaledFraction( - le32_to_cpu(getASICProfilingInfo->ulMinVddc), 1000), ConvertToFraction(4)); - - /*----------------------- - * PART 3 - *----------------------- - */ - - fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4, fSclk), fSM_A5)); - fB_Term = fAdd(fAdd(fMultiply(fSM_A2, fSclk), fSM_A6), fMargin_RO_b); - fC_Term = fAdd(fMargin_RO_c, - fAdd(fMultiply(fSM_A0, fLkg_FT), - fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT, fSclk)), - fAdd(fMultiply(fSM_A3, fSclk), - fSubtract(fSM_A7, fRO_fused))))); - - fVDDC_base = fSubtract(fRO_fused, - fSubtract(fMargin_RO_c, - fSubtract(fSM_A3, fMultiply(fSM_A1, fSclk)))); - fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0, fSclk), fSM_A2)); - - repeat = fSubtract(fVDDC_base, - fDivide(fMargin_DC_sigma, ConvertToFraction(1000))); - - fRO_DC_margin = fAdd(fMultiply(fMargin_RO_a, - fGetSquare(repeat)), - fAdd(fMultiply(fMargin_RO_b, repeat), - fMargin_RO_c)); - - fDC_SCLK = fSubtract(fRO_fused, - fSubtract(fRO_DC_margin, - fSubtract(fSM_A3, - fMultiply(fSM_A2, repeat)))); - fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0, repeat), fSM_A1)); - - fSigma_DC = fSubtract(fSclk, fDC_SCLK); - - fMicro_FMAX = fMultiply(fSclk, fMargin_FMAX_mean); - fMicro_CR = fMultiply(fSclk, fMargin_Plat_mean); - fSigma_FMAX = fMultiply(fSclk, fMargin_FMAX_sigma); - fSigma_CR = fMultiply(fSclk, fMargin_Plat_sigma); - - fSquared_Sigma_DC = fGetSquare(fSigma_DC); - fSquared_Sigma_CR = fGetSquare(fSigma_CR); - fSquared_Sigma_FMAX = fGetSquare(fSigma_FMAX); - - fSclk_margin = fAdd(fMicro_FMAX, - fAdd(fMicro_CR, - fAdd(fMargin_fixed, - fSqrt(fAdd(fSquared_Sigma_FMAX, - fAdd(fSquared_Sigma_DC, fSquared_Sigma_CR)))))); - /* - fA_Term = fSM_A4 * (fSclk + fSclk_margin) + fSM_A5; - fB_Term = fSM_A2 * (fSclk + fSclk_margin) + fSM_A6; - fC_Term = fRO_DC_margin + fSM_A0 * fLkg_FT + fSM_A1 * fLkg_FT * (fSclk + fSclk_margin) + fSM_A3 * (fSclk + fSclk_margin) + fSM_A7 - fRO_fused; - */ - - fA_Term = fAdd(fMultiply(fSM_A4, fAdd(fSclk, fSclk_margin)), fSM_A5); - fB_Term = fAdd(fMultiply(fSM_A2, fAdd(fSclk, fSclk_margin)), fSM_A6); - fC_Term = fAdd(fRO_DC_margin, - fAdd(fMultiply(fSM_A0, fLkg_FT), - fAdd(fMultiply(fMultiply(fSM_A1, fLkg_FT), - fAdd(fSclk, fSclk_margin)), - fAdd(fMultiply(fSM_A3, - fAdd(fSclk, fSclk_margin)), - fSubtract(fSM_A7, fRO_fused))))); - - SolveQuadracticEqn(fA_Term, fB_Term, fC_Term, fRoots); - - if (GreaterThan(fRoots[0], fRoots[1])) - fEVV_V = fRoots[1]; - else - fEVV_V = fRoots[0]; - - if (GreaterThan(fV_min, fEVV_V)) - fEVV_V = fV_min; - else if (GreaterThan(fEVV_V, fV_max)) - fEVV_V = fSubtract(fV_max, fStepSize); - - fEVV_V = fRoundUpByStepSize(fEVV_V, fStepSize, 0); - - /*----------------- - * PART 4 - *----------------- - */ - - fV_x = fV_min; - - while (GreaterThan(fAdd(fV_max, fStepSize), fV_x)) { - fTDP_Power_left = fMultiply(fMultiply(fMultiply(fAdd( - fMultiply(fCACm_fused, fV_x), fCACb_fused), fSclk), - fGetSquare(fV_x)), fDerateTDP); - - fTDP_Power_right = fMultiply(fFT_Lkg_V0NORM, fMultiply(fLKG_Factor, - fMultiply(fExponential(fMultiply(fAdd(fMultiply(fKv_m_fused, - fT_prod), fKv_b_fused), fV_x)), fV_x))); - fTDP_Power_right = fMultiply(fTDP_Power_right, fExponential(fMultiply( - fKt_Beta_fused, fT_prod))); - fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( - fAdd(fMultiply(fKv_m_fused, fT_prod), fKv_b_fused), fV_FT))); - fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( - fKt_Beta_fused, fT_FT))); - - fTDP_Power = fAdd(fTDP_Power_left, fTDP_Power_right); - - fTDP_Current = fDivide(fTDP_Power, fV_x); - - fV_NL = fAdd(fV_x, fDivide(fMultiply(fTDP_Current, fRLL_LoadLine), - ConvertToFraction(10))); - - fV_NL = fRoundUpByStepSize(fV_NL, fStepSize, 0); - - if (GreaterThan(fV_max, fV_NL) && - (GreaterThan(fV_NL, fEVV_V) || - Equal(fV_NL, fEVV_V))) { - fV_NL = fMultiply(fV_NL, ConvertToFraction(1000)); - - *voltage = (uint16_t)fV_NL.partial.real; - break; - } else - fV_x = fAdd(fV_x, fStepSize); - } - - return result; -} - -/** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table. - * @param hwmgr input: pointer to hwManager - * @param voltage_type input: type of EVV voltage VDDC or VDDGFX - * @param sclk input: in 10Khz unit. DPM state SCLK frequency - * which is define in PPTable SCLK/VDDC dependence - * table associated with this virtual_voltage_Id - * @param virtual_voltage_Id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 - * @param voltage output: real voltage level in unit of mv - */ -int atomctrl_get_voltage_evv_on_sclk( - struct pp_hwmgr *hwmgr, - uint8_t voltage_type, - uint32_t sclk, uint16_t virtual_voltage_Id, - uint16_t *voltage) -{ - struct amdgpu_device *adev = hwmgr->adev; - GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space; - int result; - - get_voltage_info_param_space.ucVoltageType = - voltage_type; - get_voltage_info_param_space.ucVoltageMode = - ATOM_GET_VOLTAGE_EVV_VOLTAGE; - get_voltage_info_param_space.usVoltageLevel = - cpu_to_le16(virtual_voltage_Id); - get_voltage_info_param_space.ulSCLKFreq = - cpu_to_le32(sclk); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), - (uint32_t *)&get_voltage_info_param_space); - - *voltage = result ? 0 : - le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *) - (&get_voltage_info_param_space))->usVoltageLevel); - - return result; -} - -/** - * atomctrl_get_voltage_evv gets voltage via call to ATOM COMMAND table. - * @param hwmgr input: pointer to hwManager - * @param virtual_voltage_id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 - * @param voltage output: real voltage level in unit of mv - */ -int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, - uint16_t virtual_voltage_id, - uint16_t *voltage) -{ - struct amdgpu_device *adev = hwmgr->adev; - GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space; - int result; - int entry_id; - - /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ - for (entry_id = 0; entry_id < hwmgr->dyn_state.vddc_dependency_on_sclk->count; entry_id++) { - if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].v == virtual_voltage_id) { - /* found */ - break; - } - } - - if (entry_id >= hwmgr->dyn_state.vddc_dependency_on_sclk->count) { - pr_debug("Can't find requested voltage id in vddc_dependency_on_sclk table!\n"); - return -EINVAL; - } - - get_voltage_info_param_space.ucVoltageType = VOLTAGE_TYPE_VDDC; - get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; - get_voltage_info_param_space.usVoltageLevel = virtual_voltage_id; - get_voltage_info_param_space.ulSCLKFreq = - cpu_to_le32(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[entry_id].clk); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), - (uint32_t *)&get_voltage_info_param_space); - - if (0 != result) - return result; - - *voltage = le16_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *) - (&get_voltage_info_param_space))->usVoltageLevel); - - return result; -} - -/** - * Get the mpll reference clock in 10KHz - */ -uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr) -{ - ATOM_COMMON_TABLE_HEADER *fw_info; - uint32_t clock; - u8 frev, crev; - u16 size; - - fw_info = (ATOM_COMMON_TABLE_HEADER *) - smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, FirmwareInfo), - &size, &frev, &crev); - - if (fw_info == NULL) - clock = 2700; - else { - if ((fw_info->ucTableFormatRevision == 2) && - (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) { - ATOM_FIRMWARE_INFO_V2_1 *fwInfo_2_1 = - (ATOM_FIRMWARE_INFO_V2_1 *)fw_info; - clock = (uint32_t)(le16_to_cpu(fwInfo_2_1->usMemoryReferenceClock)); - } else { - ATOM_FIRMWARE_INFO *fwInfo_0_0 = - (ATOM_FIRMWARE_INFO *)fw_info; - clock = (uint32_t)(le16_to_cpu(fwInfo_0_0->usReferenceClock)); - } - } - - return clock; -} - -/** - * Get the asic internal spread spectrum table - */ -static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device) -{ - ATOM_ASIC_INTERNAL_SS_INFO *table = NULL; - u8 frev, crev; - u16 size; - - table = (ATOM_ASIC_INTERNAL_SS_INFO *) - smu_atom_get_data_table(device, - GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info), - &size, &frev, &crev); - - return table; -} - -/** - * Get the asic internal spread spectrum assignment - */ -static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr, - const uint8_t clockSource, - const uint32_t clockSpeed, - pp_atomctrl_internal_ss_info *ssEntry) -{ - ATOM_ASIC_INTERNAL_SS_INFO *table; - ATOM_ASIC_SS_ASSIGNMENT *ssInfo; - int entry_found = 0; - - memset(ssEntry, 0x00, sizeof(pp_atomctrl_internal_ss_info)); - - table = asic_internal_ss_get_ss_table(hwmgr->adev); - - if (NULL == table) - return -1; - - ssInfo = &table->asSpreadSpectrum[0]; - - while (((uint8_t *)ssInfo - (uint8_t *)table) < - le16_to_cpu(table->sHeader.usStructureSize)) { - if ((clockSource == ssInfo->ucClockIndication) && - ((uint32_t)clockSpeed <= le32_to_cpu(ssInfo->ulTargetClockRange))) { - entry_found = 1; - break; - } - - ssInfo = (ATOM_ASIC_SS_ASSIGNMENT *)((uint8_t *)ssInfo + - sizeof(ATOM_ASIC_SS_ASSIGNMENT)); - } - - if (entry_found) { - ssEntry->speed_spectrum_percentage = - le16_to_cpu(ssInfo->usSpreadSpectrumPercentage); - ssEntry->speed_spectrum_rate = le16_to_cpu(ssInfo->usSpreadRateInKhz); - - if (((GET_DATA_TABLE_MAJOR_REVISION(table) == 2) && - (GET_DATA_TABLE_MINOR_REVISION(table) >= 2)) || - (GET_DATA_TABLE_MAJOR_REVISION(table) == 3)) { - ssEntry->speed_spectrum_rate /= 100; - } - - switch (ssInfo->ucSpreadSpectrumMode) { - case 0: - ssEntry->speed_spectrum_mode = - pp_atomctrl_spread_spectrum_mode_down; - break; - case 1: - ssEntry->speed_spectrum_mode = - pp_atomctrl_spread_spectrum_mode_center; - break; - default: - ssEntry->speed_spectrum_mode = - pp_atomctrl_spread_spectrum_mode_down; - break; - } - } - - return entry_found ? 0 : 1; -} - -/** - * Get the memory clock spread spectrum info - */ -int atomctrl_get_memory_clock_spread_spectrum( - struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - pp_atomctrl_internal_ss_info *ssInfo) -{ - return asic_internal_ss_get_ss_asignment(hwmgr, - ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo); -} -/** - * Get the engine clock spread spectrum info - */ -int atomctrl_get_engine_clock_spread_spectrum( - struct pp_hwmgr *hwmgr, - const uint32_t engine_clock, - pp_atomctrl_internal_ss_info *ssInfo) -{ - return asic_internal_ss_get_ss_asignment(hwmgr, - ASIC_INTERNAL_ENGINE_SS, engine_clock, ssInfo); -} - -int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, - uint16_t end_index, uint32_t mask, uint32_t *efuse) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - READ_EFUSE_VALUE_PARAMETER efuse_param; - - efuse_param.sEfuse.usEfuseIndex = cpu_to_le16((start_index / 32) * 4); - efuse_param.sEfuse.ucBitShift = (uint8_t) - (start_index - ((start_index / 32) * 32)); - efuse_param.sEfuse.ucBitLength = (uint8_t) - ((end_index - start_index) + 1); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), - (uint32_t *)&efuse_param); - *efuse = result ? 0 : le32_to_cpu(efuse_param.ulEfuseValue) & mask; - - return result; -} - -int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock, - uint8_t level) -{ - struct amdgpu_device *adev = hwmgr->adev; - DYNAMICE_MEMORY_SETTINGS_PARAMETER_V2_1 memory_clock_parameters; - int result; - - memory_clock_parameters.asDPMMCReg.ulClock.ulClockFreq = - memory_clock & SET_CLOCK_FREQ_MASK; - memory_clock_parameters.asDPMMCReg.ulClock.ulComputeClockFlag = - ADJUST_MC_SETTING_PARAM; - memory_clock_parameters.asDPMMCReg.ucMclkDPMState = level; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings), - (uint32_t *)&memory_clock_parameters); - - return result; -} - -int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_3 get_voltage_info_param_space; - - get_voltage_info_param_space.ucVoltageType = voltage_type; - get_voltage_info_param_space.ucVoltageMode = ATOM_GET_VOLTAGE_EVV_VOLTAGE; - get_voltage_info_param_space.usVoltageLevel = cpu_to_le16(virtual_voltage_Id); - get_voltage_info_param_space.ulSCLKFreq = cpu_to_le32(sclk); - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), - (uint32_t *)&get_voltage_info_param_space); - - *voltage = result ? 0 : - le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel); - - return result; -} - -int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table) -{ - - int i; - u8 frev, crev; - u16 size; - - ATOM_SMU_INFO_V2_1 *psmu_info = - (ATOM_SMU_INFO_V2_1 *)smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, SMU_Info), - &size, &frev, &crev); - - - for (i = 0; i < psmu_info->ucSclkEntryNum; i++) { - table->entry[i].ucVco_setting = psmu_info->asSclkFcwRangeEntry[i].ucVco_setting; - table->entry[i].ucPostdiv = psmu_info->asSclkFcwRangeEntry[i].ucPostdiv; - table->entry[i].usFcw_pcc = - le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_pcc); - table->entry[i].usFcw_trans_upper = - le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucFcw_trans_upper); - table->entry[i].usRcw_trans_lower = - le16_to_cpu(psmu_info->asSclkFcwRangeEntry[i].ucRcw_trans_lower); - } - - return 0; -} - -int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, - struct pp_atom_ctrl__avfs_parameters *param) -{ - ATOM_ASIC_PROFILING_INFO_V3_6 *profile = NULL; - - if (param == NULL) - return -EINVAL; - - profile = (ATOM_ASIC_PROFILING_INFO_V3_6 *) - smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), - NULL, NULL, NULL); - if (!profile) - return -1; - - param->ulAVFS_meanNsigma_Acontant0 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant0); - param->ulAVFS_meanNsigma_Acontant1 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant1); - param->ulAVFS_meanNsigma_Acontant2 = le32_to_cpu(profile->ulAVFS_meanNsigma_Acontant2); - param->usAVFS_meanNsigma_DC_tol_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_DC_tol_sigma); - param->usAVFS_meanNsigma_Platform_mean = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_mean); - param->usAVFS_meanNsigma_Platform_sigma = le16_to_cpu(profile->usAVFS_meanNsigma_Platform_sigma); - param->ulGB_VDROOP_TABLE_CKSOFF_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a0); - param->ulGB_VDROOP_TABLE_CKSOFF_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a1); - param->ulGB_VDROOP_TABLE_CKSOFF_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSOFF_a2); - param->ulGB_VDROOP_TABLE_CKSON_a0 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a0); - param->ulGB_VDROOP_TABLE_CKSON_a1 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a1); - param->ulGB_VDROOP_TABLE_CKSON_a2 = le32_to_cpu(profile->ulGB_VDROOP_TABLE_CKSON_a2); - param->ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_m1); - param->usAVFSGB_FUSE_TABLE_CKSOFF_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSOFF_m2); - param->ulAVFSGB_FUSE_TABLE_CKSOFF_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSOFF_b); - param->ulAVFSGB_FUSE_TABLE_CKSON_m1 = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_m1); - param->usAVFSGB_FUSE_TABLE_CKSON_m2 = le16_to_cpu(profile->usAVFSGB_FUSE_TABLE_CKSON_m2); - param->ulAVFSGB_FUSE_TABLE_CKSON_b = le32_to_cpu(profile->ulAVFSGB_FUSE_TABLE_CKSON_b); - param->usMaxVoltage_0_25mv = le16_to_cpu(profile->usMaxVoltage_0_25mv); - param->ucEnableGB_VDROOP_TABLE_CKSOFF = profile->ucEnableGB_VDROOP_TABLE_CKSOFF; - param->ucEnableGB_VDROOP_TABLE_CKSON = profile->ucEnableGB_VDROOP_TABLE_CKSON; - param->ucEnableGB_FUSE_TABLE_CKSOFF = profile->ucEnableGB_FUSE_TABLE_CKSOFF; - param->ucEnableGB_FUSE_TABLE_CKSON = profile->ucEnableGB_FUSE_TABLE_CKSON; - param->usPSM_Age_ComFactor = le16_to_cpu(profile->usPSM_Age_ComFactor); - param->ucEnableApplyAVFS_CKS_OFF_Voltage = profile->ucEnableApplyAVFS_CKS_OFF_Voltage; - - return 0; -} - -int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint8_t *svd_gpio_id, uint8_t *svc_gpio_id, - uint16_t *load_line) -{ - ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = - (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->adev); - - const ATOM_VOLTAGE_OBJECT_V3 *voltage_object; - - PP_ASSERT_WITH_CODE((NULL != voltage_info), - "Could not find Voltage Table in BIOS.", return -EINVAL); - - voltage_object = atomctrl_lookup_voltage_type_v3 - (voltage_info, voltage_type, VOLTAGE_OBJ_SVID2); - - *svd_gpio_id = voltage_object->asSVID2Obj.ucSVDGpioId; - *svc_gpio_id = voltage_object->asSVID2Obj.ucSVCGpioId; - *load_line = voltage_object->asSVID2Obj.usLoadLine_PSI; - - return 0; -} - -int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id) -{ - struct amdgpu_device *adev = hwmgr->adev; - SET_VOLTAGE_PS_ALLOCATION allocation; - SET_VOLTAGE_PARAMETERS_V1_3 *voltage_parameters = - (SET_VOLTAGE_PARAMETERS_V1_3 *)&allocation.sASICSetVoltage; - int result; - - voltage_parameters->ucVoltageMode = ATOM_GET_LEAKAGE_ID; - - result = amdgpu_atom_execute_table(adev->mode_info.atom_context, - GetIndexIntoMasterTable(COMMAND, SetVoltage), - (uint32_t *)voltage_parameters); - - *virtual_voltage_id = voltage_parameters->usVoltageLevel; - - return result; -} - -int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, - uint16_t *vddc, uint16_t *vddci, - uint16_t virtual_voltage_id, - uint16_t efuse_voltage_id) -{ - int i, j; - int ix; - u16 *leakage_bin, *vddc_id_buf, *vddc_buf, *vddci_id_buf, *vddci_buf; - ATOM_ASIC_PROFILING_INFO_V2_1 *profile; - - *vddc = 0; - *vddci = 0; - - ix = GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo); - - profile = (ATOM_ASIC_PROFILING_INFO_V2_1 *) - smu_atom_get_data_table(hwmgr->adev, - ix, - NULL, NULL, NULL); - if (!profile) - return -EINVAL; - - if ((profile->asHeader.ucTableFormatRevision >= 2) && - (profile->asHeader.ucTableContentRevision >= 1) && - (profile->asHeader.usStructureSize >= sizeof(ATOM_ASIC_PROFILING_INFO_V2_1))) { - leakage_bin = (u16 *)((char *)profile + profile->usLeakageBinArrayOffset); - vddc_id_buf = (u16 *)((char *)profile + profile->usElbVDDC_IdArrayOffset); - vddc_buf = (u16 *)((char *)profile + profile->usElbVDDC_LevelArrayOffset); - if (profile->ucElbVDDC_Num > 0) { - for (i = 0; i < profile->ucElbVDDC_Num; i++) { - if (vddc_id_buf[i] == virtual_voltage_id) { - for (j = 0; j < profile->ucLeakageBinNum; j++) { - if (efuse_voltage_id <= leakage_bin[j]) { - *vddc = vddc_buf[j * profile->ucElbVDDC_Num + i]; - break; - } - } - break; - } - } - } - - vddci_id_buf = (u16 *)((char *)profile + profile->usElbVDDCI_IdArrayOffset); - vddci_buf = (u16 *)((char *)profile + profile->usElbVDDCI_LevelArrayOffset); - if (profile->ucElbVDDCI_Num > 0) { - for (i = 0; i < profile->ucElbVDDCI_Num; i++) { - if (vddci_id_buf[i] == virtual_voltage_id) { - for (j = 0; j < profile->ucLeakageBinNum; j++) { - if (efuse_voltage_id <= leakage_bin[j]) { - *vddci = vddci_buf[j * profile->ucElbVDDCI_Num + i]; - break; - } - } - break; - } - } - } - } - - return 0; -} - -void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, - uint32_t *min_vddc) -{ - void *profile; - - profile = smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), - NULL, NULL, NULL); - - if (profile) { - switch (hwmgr->chip_id) { - case CHIP_TONGA: - case CHIP_FIJI: - *max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMaxVddc) / 4; - *min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_3 *)profile)->ulMinVddc) / 4; - return; - case CHIP_POLARIS11: - case CHIP_POLARIS10: - case CHIP_POLARIS12: - *max_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMaxVddc) / 100; - *min_vddc = le32_to_cpu(((ATOM_ASIC_PROFILING_INFO_V3_6 *)profile)->ulMinVddc) / 100; - return; - default: - break; - } - } - *max_vddc = 0; - *min_vddc = 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h deleted file mode 100644 index 76ed2e413594..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright 2015 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 PP_ATOMVOLTAGECTRL_H -#define PP_ATOMVOLTAGECTRL_H - -#include "hwmgr.h" - -/* As returned from PowerConnectorDetectionTable. */ -#define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80 -#define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40 -#define PP_ATOM_POWER_BUDGET_SHOW_WAIVER 0x20 -#define PP_ATOM_POWER_POWER_BUDGET_BEHAVIOUR 0x0F - -/* New functions for Evergreen and beyond. */ -#define PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES 32 - -struct pp_atomctrl_clock_dividers { - uint32_t pll_post_divider; - uint32_t pll_feedback_divider; - uint32_t pll_ref_divider; - bool enable_post_divider; -}; - -typedef struct pp_atomctrl_clock_dividers pp_atomctrl_clock_dividers; - -union pp_atomctrl_tcipll_fb_divider { - struct { - uint32_t ul_fb_div_frac : 14; - uint32_t ul_fb_div : 12; - uint32_t un_used : 6; - }; - uint32_t ul_fb_divider; -}; - -typedef union pp_atomctrl_tcipll_fb_divider pp_atomctrl_tcipll_fb_divider; - -struct pp_atomctrl_clock_dividers_rv730 { - uint32_t pll_post_divider; - pp_atomctrl_tcipll_fb_divider mpll_feedback_divider; - uint32_t pll_ref_divider; - bool enable_post_divider; - bool enable_dithen; - uint32_t vco_mode; -}; -typedef struct pp_atomctrl_clock_dividers_rv730 pp_atomctrl_clock_dividers_rv730; - - -struct pp_atomctrl_clock_dividers_kong { - uint32_t pll_post_divider; - uint32_t real_clock; -}; -typedef struct pp_atomctrl_clock_dividers_kong pp_atomctrl_clock_dividers_kong; - -struct pp_atomctrl_clock_dividers_ci { - uint32_t pll_post_divider; /* post divider value */ - uint32_t real_clock; - pp_atomctrl_tcipll_fb_divider ul_fb_div; /* Output Parameter: PLL FB divider */ - uint8_t uc_pll_ref_div; /* Output Parameter: PLL ref divider */ - uint8_t uc_pll_post_div; /* Output Parameter: PLL post divider */ - uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ -}; -typedef struct pp_atomctrl_clock_dividers_ci pp_atomctrl_clock_dividers_ci; - -struct pp_atomctrl_clock_dividers_vi { - uint32_t pll_post_divider; /* post divider value */ - uint32_t real_clock; - pp_atomctrl_tcipll_fb_divider ul_fb_div; /*Output Parameter: PLL FB divider */ - uint8_t uc_pll_ref_div; /*Output Parameter: PLL ref divider */ - uint8_t uc_pll_post_div; /*Output Parameter: PLL post divider */ - uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ -}; -typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi; - -struct pp_atomctrl_clock_dividers_ai { - u16 usSclk_fcw_frac; - u16 usSclk_fcw_int; - u8 ucSclkPostDiv; - u8 ucSclkVcoMode; - u8 ucSclkPllRange; - u8 ucSscEnable; - u16 usSsc_fcw1_frac; - u16 usSsc_fcw1_int; - u16 usReserved; - u16 usPcc_fcw_int; - u16 usSsc_fcw_slew_frac; - u16 usPcc_fcw_slew_frac; -}; -typedef struct pp_atomctrl_clock_dividers_ai pp_atomctrl_clock_dividers_ai; - - -union pp_atomctrl_s_mpll_fb_divider { - struct { - uint32_t cl_kf : 12; - uint32_t clk_frac : 12; - uint32_t un_used : 8; - }; - uint32_t ul_fb_divider; -}; -typedef union pp_atomctrl_s_mpll_fb_divider pp_atomctrl_s_mpll_fb_divider; - -enum pp_atomctrl_spread_spectrum_mode { - pp_atomctrl_spread_spectrum_mode_down = 0, - pp_atomctrl_spread_spectrum_mode_center -}; -typedef enum pp_atomctrl_spread_spectrum_mode pp_atomctrl_spread_spectrum_mode; - -struct pp_atomctrl_memory_clock_param { - pp_atomctrl_s_mpll_fb_divider mpll_fb_divider; - uint32_t mpll_post_divider; - uint32_t bw_ctrl; - uint32_t dll_speed; - uint32_t vco_mode; - uint32_t yclk_sel; - uint32_t qdr; - uint32_t half_rate; -}; -typedef struct pp_atomctrl_memory_clock_param pp_atomctrl_memory_clock_param; - -struct pp_atomctrl_memory_clock_param_ai { - uint32_t ulClock; - uint32_t ulPostDiv; - uint16_t ulMclk_fcw_frac; - uint16_t ulMclk_fcw_int; -}; -typedef struct pp_atomctrl_memory_clock_param_ai pp_atomctrl_memory_clock_param_ai; - -struct pp_atomctrl_internal_ss_info { - uint32_t speed_spectrum_percentage; /* in 1/100 percentage */ - uint32_t speed_spectrum_rate; /* in KHz */ - pp_atomctrl_spread_spectrum_mode speed_spectrum_mode; -}; -typedef struct pp_atomctrl_internal_ss_info pp_atomctrl_internal_ss_info; - -#ifndef NUMBER_OF_M3ARB_PARAMS -#define NUMBER_OF_M3ARB_PARAMS 3 -#endif - -#ifndef NUMBER_OF_M3ARB_PARAM_SETS -#define NUMBER_OF_M3ARB_PARAM_SETS 10 -#endif - -struct pp_atomctrl_kong_system_info { - uint32_t ul_bootup_uma_clock; /* in 10kHz unit */ - uint16_t us_max_nb_voltage; /* high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ - uint16_t us_min_nb_voltage; /* low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ - uint16_t us_bootup_nb_voltage; /* boot up NB voltage */ - uint8_t uc_htc_tmp_lmt; /* bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD */ - uint8_t uc_tj_offset; /* bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD */ - /* 0: default 1: uvd 2: fs-3d */ - uint32_t ul_csr_m3_srb_cntl[NUMBER_OF_M3ARB_PARAM_SETS][NUMBER_OF_M3ARB_PARAMS];/* arrays with values for CSR M3 arbiter for default */ -}; -typedef struct pp_atomctrl_kong_system_info pp_atomctrl_kong_system_info; - -struct pp_atomctrl_memory_info { - uint8_t memory_vendor; - uint8_t memory_type; -}; -typedef struct pp_atomctrl_memory_info pp_atomctrl_memory_info; - -#define MAX_AC_TIMING_ENTRIES 16 - -struct pp_atomctrl_memory_clock_range_table { - uint8_t num_entries; - uint8_t rsv[3]; - - uint32_t mclk[MAX_AC_TIMING_ENTRIES]; -}; -typedef struct pp_atomctrl_memory_clock_range_table pp_atomctrl_memory_clock_range_table; - -struct pp_atomctrl_voltage_table_entry { - uint16_t value; - uint32_t smio_low; -}; - -typedef struct pp_atomctrl_voltage_table_entry pp_atomctrl_voltage_table_entry; - -struct pp_atomctrl_voltage_table { - uint32_t count; - uint32_t mask_low; - uint32_t phase_delay; /* Used for ATOM_GPIO_VOLTAGE_OBJECT_V3 and later */ - pp_atomctrl_voltage_table_entry entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES]; -}; - -typedef struct pp_atomctrl_voltage_table pp_atomctrl_voltage_table; - -#define VBIOS_MC_REGISTER_ARRAY_SIZE 32 -#define VBIOS_MAX_AC_TIMING_ENTRIES 20 - -struct pp_atomctrl_mc_reg_entry { - uint32_t mclk_max; - uint32_t mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE]; -}; -typedef struct pp_atomctrl_mc_reg_entry pp_atomctrl_mc_reg_entry; - -struct pp_atomctrl_mc_register_address { - uint16_t s1; - uint8_t uc_pre_reg_data; -}; - -typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address; - -#define MAX_SCLK_RANGE 8 - -struct pp_atom_ctrl_sclk_range_table_entry{ - uint8_t ucVco_setting; - uint8_t ucPostdiv; - uint16_t usFcw_pcc; - uint16_t usFcw_trans_upper; - uint16_t usRcw_trans_lower; -}; - - -struct pp_atom_ctrl_sclk_range_table{ - struct pp_atom_ctrl_sclk_range_table_entry entry[MAX_SCLK_RANGE]; -}; - -struct pp_atomctrl_mc_reg_table { - uint8_t last; /* number of registers */ - uint8_t num_entries; /* number of AC timing entries */ - pp_atomctrl_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES]; - pp_atomctrl_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE]; -}; -typedef struct pp_atomctrl_mc_reg_table pp_atomctrl_mc_reg_table; - -struct pp_atomctrl_gpio_pin_assignment { - uint16_t us_gpio_pin_aindex; - uint8_t uc_gpio_pin_bit_shift; -}; -typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment; - -struct pp_atom_ctrl__avfs_parameters { - uint32_t ulAVFS_meanNsigma_Acontant0; - uint32_t ulAVFS_meanNsigma_Acontant1; - uint32_t ulAVFS_meanNsigma_Acontant2; - uint16_t usAVFS_meanNsigma_DC_tol_sigma; - uint16_t usAVFS_meanNsigma_Platform_mean; - uint16_t usAVFS_meanNsigma_Platform_sigma; - uint32_t ulGB_VDROOP_TABLE_CKSOFF_a0; - uint32_t ulGB_VDROOP_TABLE_CKSOFF_a1; - uint32_t ulGB_VDROOP_TABLE_CKSOFF_a2; - uint32_t ulGB_VDROOP_TABLE_CKSON_a0; - uint32_t ulGB_VDROOP_TABLE_CKSON_a1; - uint32_t ulGB_VDROOP_TABLE_CKSON_a2; - uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_m1; - uint16_t usAVFSGB_FUSE_TABLE_CKSOFF_m2; - uint32_t ulAVFSGB_FUSE_TABLE_CKSOFF_b; - uint32_t ulAVFSGB_FUSE_TABLE_CKSON_m1; - uint16_t usAVFSGB_FUSE_TABLE_CKSON_m2; - uint32_t ulAVFSGB_FUSE_TABLE_CKSON_b; - uint16_t usMaxVoltage_0_25mv; - uint8_t ucEnableGB_VDROOP_TABLE_CKSOFF; - uint8_t ucEnableGB_VDROOP_TABLE_CKSON; - uint8_t ucEnableGB_FUSE_TABLE_CKSOFF; - uint8_t ucEnableGB_FUSE_TABLE_CKSON; - uint16_t usPSM_Age_ComFactor; - uint8_t ucEnableApplyAVFS_CKS_OFF_Voltage; - uint8_t ucReserved; -}; - -extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); -extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); -extern int atomctrl_get_voltage_evv(struct pp_hwmgr *hwmgr, uint16_t virtual_voltage_id, uint16_t *voltage); -extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr); -extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo); -extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo); -extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table); -extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock); -extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr); -extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode); -extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); -extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); -extern bool atomctrl_is_voltage_controlled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode); -extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table); -extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, - uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param); -extern int atomctrl_get_memory_pll_dividers_ai(struct pp_hwmgr *hwmgr, - uint32_t clock_value, pp_atomctrl_memory_clock_param_ai *mpll_param); -extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, - uint32_t clock_value, - pp_atomctrl_clock_dividers_kong *dividers); -extern int atomctrl_read_efuse(struct pp_hwmgr *hwmgr, uint16_t start_index, - uint16_t end_index, uint32_t mask, uint32_t *efuse); -extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug); -extern int atomctrl_get_engine_pll_dividers_ai(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_ai *dividers); -extern int atomctrl_set_ac_timing_ai(struct pp_hwmgr *hwmgr, uint32_t memory_clock, - uint8_t level); -extern int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint32_t sclk, uint16_t virtual_voltage_Id, uint32_t *voltage); -extern int atomctrl_get_smc_sclk_range_table(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl_sclk_range_table *table); - -extern int atomctrl_get_avfs_information(struct pp_hwmgr *hwmgr, struct pp_atom_ctrl__avfs_parameters *param); - -extern int atomctrl_get_svi2_info(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint8_t *svd_gpio_id, uint8_t *svc_gpio_id, - uint16_t *load_line); - -extern int atomctrl_get_leakage_vddc_base_on_leakage(struct pp_hwmgr *hwmgr, - uint16_t *vddc, uint16_t *vddci, - uint16_t virtual_voltage_id, - uint16_t efuse_voltage_id); -extern int atomctrl_get_leakage_id_from_efuse(struct pp_hwmgr *hwmgr, uint16_t *virtual_voltage_id); - -extern void atomctrl_get_voltage_range(struct pp_hwmgr *hwmgr, uint32_t *max_vddc, - uint32_t *min_vddc); -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c deleted file mode 100644 index 615cf2c09e54..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Copyright 2016 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 "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "atom.h" -#include "pp_debug.h" - -static const union atom_voltage_object_v4 *pp_atomfwctrl_lookup_voltage_type_v4( - const struct atom_voltage_objects_info_v4_1 *voltage_object_info_table, - uint8_t voltage_type, uint8_t voltage_mode) -{ - unsigned int size = le16_to_cpu( - voltage_object_info_table->table_header.structuresize); - unsigned int offset = - offsetof(struct atom_voltage_objects_info_v4_1, voltage_object[0]); - unsigned long start = (unsigned long)voltage_object_info_table; - - while (offset < size) { - const union atom_voltage_object_v4 *voltage_object = - (const union atom_voltage_object_v4 *)(start + offset); - - if (voltage_type == voltage_object->gpio_voltage_obj.header.voltage_type && - voltage_mode == voltage_object->gpio_voltage_obj.header.voltage_mode) - return voltage_object; - - offset += le16_to_cpu(voltage_object->gpio_voltage_obj.header.object_size); - - } - - return NULL; -} - -static struct atom_voltage_objects_info_v4_1 *pp_atomfwctrl_get_voltage_info_table( - struct pp_hwmgr *hwmgr) -{ - const void *table_address; - uint16_t idx; - - idx = GetIndexIntoMasterDataTable(voltageobject_info); - table_address = smu_atom_get_data_table(hwmgr->adev, - idx, NULL, NULL, NULL); - - PP_ASSERT_WITH_CODE(table_address, - "Error retrieving BIOS Table Address!", - return NULL); - - return (struct atom_voltage_objects_info_v4_1 *)table_address; -} - -/** -* Returns TRUE if the given voltage type is controlled by GPIO pins. -* voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. -* voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE -*/ -bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, - uint8_t voltage_type, uint8_t voltage_mode) -{ - struct atom_voltage_objects_info_v4_1 *voltage_info = - (struct atom_voltage_objects_info_v4_1 *) - pp_atomfwctrl_get_voltage_info_table(hwmgr); - bool ret; - - /* If we cannot find the table do NOT try to control this voltage. */ - PP_ASSERT_WITH_CODE(voltage_info, - "Could not find Voltage Table in BIOS.", - return false); - - ret = (pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, - voltage_type, voltage_mode)) ? true : false; - - return ret; -} - -int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, - uint8_t voltage_type, uint8_t voltage_mode, - struct pp_atomfwctrl_voltage_table *voltage_table) -{ - struct atom_voltage_objects_info_v4_1 *voltage_info = - (struct atom_voltage_objects_info_v4_1 *) - pp_atomfwctrl_get_voltage_info_table(hwmgr); - const union atom_voltage_object_v4 *voltage_object; - unsigned int i; - int result = 0; - - PP_ASSERT_WITH_CODE(voltage_info, - "Could not find Voltage Table in BIOS.", - return -1); - - voltage_object = pp_atomfwctrl_lookup_voltage_type_v4(voltage_info, - voltage_type, voltage_mode); - - if (!voltage_object) - return -1; - - voltage_table->count = 0; - if (voltage_mode == VOLTAGE_OBJ_GPIO_LUT) { - PP_ASSERT_WITH_CODE( - (voltage_object->gpio_voltage_obj.gpio_entry_num <= - PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES), - "Too many voltage entries!", - result = -1); - - if (!result) { - for (i = 0; i < voltage_object->gpio_voltage_obj. - gpio_entry_num; i++) { - voltage_table->entries[i].value = - le16_to_cpu(voltage_object->gpio_voltage_obj. - voltage_gpio_lut[i].voltage_level_mv); - voltage_table->entries[i].smio_low = - le32_to_cpu(voltage_object->gpio_voltage_obj. - voltage_gpio_lut[i].voltage_gpio_reg_val); - } - voltage_table->count = - voltage_object->gpio_voltage_obj.gpio_entry_num; - voltage_table->mask_low = - le32_to_cpu( - voltage_object->gpio_voltage_obj.gpio_mask_val); - voltage_table->phase_delay = - voltage_object->gpio_voltage_obj.phase_delay_us; - } - } else if (voltage_mode == VOLTAGE_OBJ_SVID2) { - voltage_table->psi1_enable = - (voltage_object->svid2_voltage_obj.loadline_psi1 & 0x20) >> 5; - voltage_table->psi0_enable = - voltage_object->svid2_voltage_obj.psi0_enable & 0x1; - voltage_table->max_vid_step = - voltage_object->svid2_voltage_obj.maxvstep; - voltage_table->telemetry_offset = - voltage_object->svid2_voltage_obj.telemetry_offset; - voltage_table->telemetry_slope = - voltage_object->svid2_voltage_obj.telemetry_gain; - } else - PP_ASSERT_WITH_CODE(false, - "Unsupported Voltage Object Mode!", - result = -1); - - return result; -} - - -static struct atom_gpio_pin_lut_v2_1 *pp_atomfwctrl_get_gpio_lookup_table( - struct pp_hwmgr *hwmgr) -{ - const void *table_address; - uint16_t idx; - - idx = GetIndexIntoMasterDataTable(gpio_pin_lut); - table_address = smu_atom_get_data_table(hwmgr->adev, - idx, NULL, NULL, NULL); - PP_ASSERT_WITH_CODE(table_address, - "Error retrieving BIOS Table Address!", - return NULL); - - return (struct atom_gpio_pin_lut_v2_1 *)table_address; -} - -static bool pp_atomfwctrl_lookup_gpio_pin( - struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table, - const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - unsigned int size = le16_to_cpu( - gpio_lookup_table->table_header.structuresize); - unsigned int offset = - offsetof(struct atom_gpio_pin_lut_v2_1, gpio_pin[0]); - unsigned long start = (unsigned long)gpio_lookup_table; - - while (offset < size) { - const struct atom_gpio_pin_assignment *pin_assignment = - (const struct atom_gpio_pin_assignment *)(start + offset); - - if (pin_id == pin_assignment->gpio_id) { - gpio_pin_assignment->uc_gpio_pin_bit_shift = - pin_assignment->gpio_bitshift; - gpio_pin_assignment->us_gpio_pin_aindex = - le16_to_cpu(pin_assignment->data_a_reg_index); - return true; - } - offset += offsetof(struct atom_gpio_pin_assignment, gpio_id) + 1; - } - return false; -} - -/** -* Returns TRUE if the given pin id find in lookup table. -*/ -bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, - const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment) -{ - bool ret = false; - struct atom_gpio_pin_lut_v2_1 *gpio_lookup_table = - pp_atomfwctrl_get_gpio_lookup_table(hwmgr); - - /* If we cannot find the table do NOT try to control this voltage. */ - PP_ASSERT_WITH_CODE(gpio_lookup_table, - "Could not find GPIO lookup Table in BIOS.", - return false); - - ret = pp_atomfwctrl_lookup_gpio_pin(gpio_lookup_table, - pin_id, gpio_pin_assignment); - - return ret; -} - -/** -* Enter to SelfRefresh mode. -* @param hwmgr -*/ -int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr) -{ - /* 0 - no action - * 1 - leave power to video memory always on - */ - return 0; -} - -/** pp_atomfwctrl_get_gpu_pll_dividers_vega10(). - * - * @param hwmgr input parameter: pointer to HwMgr - * @param clock_type input parameter: Clock type: 1 - GFXCLK, 2 - UCLK, 0 - All other clocks - * @param clock_value input parameter: Clock - * @param dividers output parameter:Clock dividers - */ -int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, - uint32_t clock_type, uint32_t clock_value, - struct pp_atomfwctrl_clock_dividers_soc15 *dividers) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct compute_gpu_clock_input_parameter_v1_8 pll_parameters; - struct compute_gpu_clock_output_parameter_v1_8 *pll_output; - uint32_t idx; - - pll_parameters.gpuclock_10khz = (uint32_t)clock_value; - pll_parameters.gpu_clock_type = clock_type; - - idx = GetIndexIntoMasterCmdTable(computegpuclockparam); - - if (amdgpu_atom_execute_table( - adev->mode_info.atom_context, idx, (uint32_t *)&pll_parameters)) - return -EINVAL; - - pll_output = (struct compute_gpu_clock_output_parameter_v1_8 *) - &pll_parameters; - dividers->ulClock = le32_to_cpu(pll_output->gpuclock_10khz); - dividers->ulDid = le32_to_cpu(pll_output->dfs_did); - dividers->ulPll_fb_mult = le32_to_cpu(pll_output->pll_fb_mult); - dividers->ulPll_ss_fbsmult = le32_to_cpu(pll_output->pll_ss_fbsmult); - dividers->usPll_ss_slew_frac = le16_to_cpu(pll_output->pll_ss_slew_frac); - dividers->ucPll_ss_enable = pll_output->pll_ss_enable; - - return 0; -} - -int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_avfs_parameters *param) -{ - uint16_t idx; - uint8_t format_revision, content_revision; - - struct atom_asic_profiling_info_v4_1 *profile; - struct atom_asic_profiling_info_v4_2 *profile_v4_2; - - idx = GetIndexIntoMasterDataTable(asic_profiling_info); - profile = (struct atom_asic_profiling_info_v4_1 *) - smu_atom_get_data_table(hwmgr->adev, - idx, NULL, NULL, NULL); - - if (!profile) - return -1; - - format_revision = ((struct atom_common_table_header *)profile)->format_revision; - content_revision = ((struct atom_common_table_header *)profile)->content_revision; - - if (format_revision == 4 && content_revision == 1) { - param->ulMaxVddc = le32_to_cpu(profile->maxvddc); - param->ulMinVddc = le32_to_cpu(profile->minvddc); - param->ulMeanNsigmaAcontant0 = - le32_to_cpu(profile->avfs_meannsigma_acontant0); - param->ulMeanNsigmaAcontant1 = - le32_to_cpu(profile->avfs_meannsigma_acontant1); - param->ulMeanNsigmaAcontant2 = - le32_to_cpu(profile->avfs_meannsigma_acontant2); - param->usMeanNsigmaDcTolSigma = - le16_to_cpu(profile->avfs_meannsigma_dc_tol_sigma); - param->usMeanNsigmaPlatformMean = - le16_to_cpu(profile->avfs_meannsigma_platform_mean); - param->usMeanNsigmaPlatformSigma = - le16_to_cpu(profile->avfs_meannsigma_platform_sigma); - param->ulGbVdroopTableCksoffA0 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a0); - param->ulGbVdroopTableCksoffA1 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a1); - param->ulGbVdroopTableCksoffA2 = - le32_to_cpu(profile->gb_vdroop_table_cksoff_a2); - param->ulGbVdroopTableCksonA0 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a0); - param->ulGbVdroopTableCksonA1 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a1); - param->ulGbVdroopTableCksonA2 = - le32_to_cpu(profile->gb_vdroop_table_ckson_a2); - param->ulGbFuseTableCksoffM1 = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1); - param->ulGbFuseTableCksoffM2 = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m2); - param->ulGbFuseTableCksoffB = - le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b); - param->ulGbFuseTableCksonM1 = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1); - param->ulGbFuseTableCksonM2 = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_m2); - param->ulGbFuseTableCksonB = - le32_to_cpu(profile->avfsgb_fuse_table_ckson_b); - - param->ucEnableGbVdroopTableCkson = - profile->enable_gb_vdroop_table_ckson; - param->ucEnableGbFuseTableCkson = - profile->enable_gb_fuse_table_ckson; - param->usPsmAgeComfactor = - le16_to_cpu(profile->psm_age_comfactor); - - param->ulDispclk2GfxclkM1 = - le32_to_cpu(profile->dispclk2gfxclk_a); - param->ulDispclk2GfxclkM2 = - le32_to_cpu(profile->dispclk2gfxclk_b); - param->ulDispclk2GfxclkB = - le32_to_cpu(profile->dispclk2gfxclk_c); - param->ulDcefclk2GfxclkM1 = - le32_to_cpu(profile->dcefclk2gfxclk_a); - param->ulDcefclk2GfxclkM2 = - le32_to_cpu(profile->dcefclk2gfxclk_b); - param->ulDcefclk2GfxclkB = - le32_to_cpu(profile->dcefclk2gfxclk_c); - param->ulPixelclk2GfxclkM1 = - le32_to_cpu(profile->pixclk2gfxclk_a); - param->ulPixelclk2GfxclkM2 = - le32_to_cpu(profile->pixclk2gfxclk_b); - param->ulPixelclk2GfxclkB = - le32_to_cpu(profile->pixclk2gfxclk_c); - param->ulPhyclk2GfxclkM1 = - le32_to_cpu(profile->phyclk2gfxclk_a); - param->ulPhyclk2GfxclkM2 = - le32_to_cpu(profile->phyclk2gfxclk_b); - param->ulPhyclk2GfxclkB = - le32_to_cpu(profile->phyclk2gfxclk_c); - param->ulAcgGbVdroopTableA0 = 0; - param->ulAcgGbVdroopTableA1 = 0; - param->ulAcgGbVdroopTableA2 = 0; - param->ulAcgGbFuseTableM1 = 0; - param->ulAcgGbFuseTableM2 = 0; - param->ulAcgGbFuseTableB = 0; - param->ucAcgEnableGbVdroopTable = 0; - param->ucAcgEnableGbFuseTable = 0; - } else if (format_revision == 4 && content_revision == 2) { - profile_v4_2 = (struct atom_asic_profiling_info_v4_2 *)profile; - param->ulMaxVddc = le32_to_cpu(profile_v4_2->maxvddc); - param->ulMinVddc = le32_to_cpu(profile_v4_2->minvddc); - param->ulMeanNsigmaAcontant0 = - le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant0); - param->ulMeanNsigmaAcontant1 = - le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant1); - param->ulMeanNsigmaAcontant2 = - le32_to_cpu(profile_v4_2->avfs_meannsigma_acontant2); - param->usMeanNsigmaDcTolSigma = - le16_to_cpu(profile_v4_2->avfs_meannsigma_dc_tol_sigma); - param->usMeanNsigmaPlatformMean = - le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_mean); - param->usMeanNsigmaPlatformSigma = - le16_to_cpu(profile_v4_2->avfs_meannsigma_platform_sigma); - param->ulGbVdroopTableCksoffA0 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a0); - param->ulGbVdroopTableCksoffA1 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a1); - param->ulGbVdroopTableCksoffA2 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_cksoff_a2); - param->ulGbVdroopTableCksonA0 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a0); - param->ulGbVdroopTableCksonA1 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a1); - param->ulGbVdroopTableCksonA2 = - le32_to_cpu(profile_v4_2->gb_vdroop_table_ckson_a2); - param->ulGbFuseTableCksoffM1 = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m1); - param->ulGbFuseTableCksoffM2 = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_m2); - param->ulGbFuseTableCksoffB = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_cksoff_b); - param->ulGbFuseTableCksonM1 = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m1); - param->ulGbFuseTableCksonM2 = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_m2); - param->ulGbFuseTableCksonB = - le32_to_cpu(profile_v4_2->avfsgb_fuse_table_ckson_b); - - param->ucEnableGbVdroopTableCkson = - profile_v4_2->enable_gb_vdroop_table_ckson; - param->ucEnableGbFuseTableCkson = - profile_v4_2->enable_gb_fuse_table_ckson; - param->usPsmAgeComfactor = - le16_to_cpu(profile_v4_2->psm_age_comfactor); - - param->ulDispclk2GfxclkM1 = - le32_to_cpu(profile_v4_2->dispclk2gfxclk_a); - param->ulDispclk2GfxclkM2 = - le32_to_cpu(profile_v4_2->dispclk2gfxclk_b); - param->ulDispclk2GfxclkB = - le32_to_cpu(profile_v4_2->dispclk2gfxclk_c); - param->ulDcefclk2GfxclkM1 = - le32_to_cpu(profile_v4_2->dcefclk2gfxclk_a); - param->ulDcefclk2GfxclkM2 = - le32_to_cpu(profile_v4_2->dcefclk2gfxclk_b); - param->ulDcefclk2GfxclkB = - le32_to_cpu(profile_v4_2->dcefclk2gfxclk_c); - param->ulPixelclk2GfxclkM1 = - le32_to_cpu(profile_v4_2->pixclk2gfxclk_a); - param->ulPixelclk2GfxclkM2 = - le32_to_cpu(profile_v4_2->pixclk2gfxclk_b); - param->ulPixelclk2GfxclkB = - le32_to_cpu(profile_v4_2->pixclk2gfxclk_c); - param->ulPhyclk2GfxclkM1 = - le32_to_cpu(profile->phyclk2gfxclk_a); - param->ulPhyclk2GfxclkM2 = - le32_to_cpu(profile_v4_2->phyclk2gfxclk_b); - param->ulPhyclk2GfxclkB = - le32_to_cpu(profile_v4_2->phyclk2gfxclk_c); - param->ulAcgGbVdroopTableA0 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a0); - param->ulAcgGbVdroopTableA1 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a1); - param->ulAcgGbVdroopTableA2 = le32_to_cpu(profile_v4_2->acg_gb_vdroop_table_a2); - param->ulAcgGbFuseTableM1 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m1); - param->ulAcgGbFuseTableM2 = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_m2); - param->ulAcgGbFuseTableB = le32_to_cpu(profile_v4_2->acg_avfsgb_fuse_table_b); - param->ucAcgEnableGbVdroopTable = le32_to_cpu(profile_v4_2->enable_acg_gb_vdroop_table); - param->ucAcgEnableGbFuseTable = le32_to_cpu(profile_v4_2->enable_acg_gb_fuse_table); - } else { - pr_info("Invalid VBIOS AVFS ProfilingInfo Revision!\n"); - return -EINVAL; - } - - return 0; -} - -int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_gpio_parameters *param) -{ - struct atom_smu_info_v3_1 *info; - uint16_t idx; - - idx = GetIndexIntoMasterDataTable(smu_info); - info = (struct atom_smu_info_v3_1 *) - smu_atom_get_data_table(hwmgr->adev, - idx, NULL, NULL, NULL); - - if (!info) { - pr_info("Error retrieving BIOS smu_info Table Address!"); - return -1; - } - - param->ucAcDcGpio = info->ac_dc_gpio_bit; - param->ucAcDcPolarity = info->ac_dc_polarity; - param->ucVR0HotGpio = info->vr0hot_gpio_bit; - param->ucVR0HotPolarity = info->vr0hot_polarity; - param->ucVR1HotGpio = info->vr1hot_gpio_bit; - param->ucVR1HotPolarity = info->vr1hot_polarity; - param->ucFwCtfGpio = info->fw_ctf_gpio_bit; - param->ucFwCtfPolarity = info->fw_ctf_polarity; - - return 0; -} - -int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, - uint8_t clk_id, uint8_t syspll_id, - uint32_t *frequency) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct atom_get_smu_clock_info_parameters_v3_1 parameters; - struct atom_get_smu_clock_info_output_parameters_v3_1 *output; - uint32_t ix; - - parameters.clk_id = clk_id; - parameters.syspll_id = syspll_id; - parameters.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ; - parameters.dfsdid = 0; - - ix = GetIndexIntoMasterCmdTable(getsmuclockinfo); - - if (amdgpu_atom_execute_table( - adev->mode_info.atom_context, ix, (uint32_t *)¶meters)) - return -EINVAL; - - output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)¶meters; - *frequency = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000; - - return 0; -} - -static void pp_atomfwctrl_copy_vbios_bootup_values_3_2(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_bios_boot_up_values *boot_values, - struct atom_firmware_info_v3_2 *fw_info) -{ - uint32_t frequency = 0; - - boot_values->ulRevision = fw_info->firmware_revision; - boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz; - boot_values->ulUClk = fw_info->bootup_mclk_in10khz; - boot_values->usVddc = fw_info->bootup_vddc_mv; - boot_values->usVddci = fw_info->bootup_vddci_mv; - boot_values->usMvddc = fw_info->bootup_mvddc_mv; - boot_values->usVddGfx = fw_info->bootup_vddgfx_mv; - boot_values->ucCoolingID = fw_info->coolingsolution_id; - boot_values->ulSocClk = 0; - boot_values->ulDCEFClk = 0; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_SOCCLK_ID, SMU11_SYSPLL0_ID, &frequency)) - boot_values->ulSocClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCEFCLK_ID, SMU11_SYSPLL0_ID, &frequency)) - boot_values->ulDCEFClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_ECLK_ID, SMU11_SYSPLL0_ID, &frequency)) - boot_values->ulEClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_VCLK_ID, SMU11_SYSPLL0_ID, &frequency)) - boot_values->ulVClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL0_DCLK_ID, SMU11_SYSPLL0_ID, &frequency)) - boot_values->ulDClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU11_SYSPLL1_0_FCLK_ID, SMU11_SYSPLL1_2_ID, &frequency)) - boot_values->ulFClk = frequency; -} - -static void pp_atomfwctrl_copy_vbios_bootup_values_3_1(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_bios_boot_up_values *boot_values, - struct atom_firmware_info_v3_1 *fw_info) -{ - uint32_t frequency = 0; - - boot_values->ulRevision = fw_info->firmware_revision; - boot_values->ulGfxClk = fw_info->bootup_sclk_in10khz; - boot_values->ulUClk = fw_info->bootup_mclk_in10khz; - boot_values->usVddc = fw_info->bootup_vddc_mv; - boot_values->usVddci = fw_info->bootup_vddci_mv; - boot_values->usMvddc = fw_info->bootup_mvddc_mv; - boot_values->usVddGfx = fw_info->bootup_vddgfx_mv; - boot_values->ucCoolingID = fw_info->coolingsolution_id; - boot_values->ulSocClk = 0; - boot_values->ulDCEFClk = 0; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_SOCCLK_ID, 0, &frequency)) - boot_values->ulSocClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCEFCLK_ID, 0, &frequency)) - boot_values->ulDCEFClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_ECLK_ID, 0, &frequency)) - boot_values->ulEClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_VCLK_ID, 0, &frequency)) - boot_values->ulVClk = frequency; - - if (!pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, SMU9_SYSPLL0_DCLK_ID, 0, &frequency)) - boot_values->ulDClk = frequency; -} - -int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_bios_boot_up_values *boot_values) -{ - struct atom_firmware_info_v3_2 *fwinfo_3_2; - struct atom_firmware_info_v3_1 *fwinfo_3_1; - struct atom_common_table_header *info = NULL; - uint16_t ix; - - ix = GetIndexIntoMasterDataTable(firmwareinfo); - info = (struct atom_common_table_header *) - smu_atom_get_data_table(hwmgr->adev, - ix, NULL, NULL, NULL); - - if (!info) { - pr_info("Error retrieving BIOS firmwareinfo!"); - return -EINVAL; - } - - if ((info->format_revision == 3) && (info->content_revision == 2)) { - fwinfo_3_2 = (struct atom_firmware_info_v3_2 *)info; - pp_atomfwctrl_copy_vbios_bootup_values_3_2(hwmgr, - boot_values, fwinfo_3_2); - } else if ((info->format_revision == 3) && (info->content_revision == 1)) { - fwinfo_3_1 = (struct atom_firmware_info_v3_1 *)info; - pp_atomfwctrl_copy_vbios_bootup_values_3_1(hwmgr, - boot_values, fwinfo_3_1); - } else { - pr_info("Fw info table revision does not match!"); - return -EINVAL; - } - - return 0; -} - -int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_smc_dpm_parameters *param) -{ - struct atom_smc_dpm_info_v4_1 *info; - uint16_t ix; - - ix = GetIndexIntoMasterDataTable(smc_dpm_info); - info = (struct atom_smc_dpm_info_v4_1 *) - smu_atom_get_data_table(hwmgr->adev, - ix, NULL, NULL, NULL); - if (!info) { - pr_info("Error retrieving BIOS Table Address!"); - return -EINVAL; - } - - param->liquid1_i2c_address = info->liquid1_i2c_address; - param->liquid2_i2c_address = info->liquid2_i2c_address; - param->vr_i2c_address = info->vr_i2c_address; - param->plx_i2c_address = info->plx_i2c_address; - - param->liquid_i2c_linescl = info->liquid_i2c_linescl; - param->liquid_i2c_linesda = info->liquid_i2c_linesda; - param->vr_i2c_linescl = info->vr_i2c_linescl; - param->vr_i2c_linesda = info->vr_i2c_linesda; - - param->plx_i2c_linescl = info->plx_i2c_linescl; - param->plx_i2c_linesda = info->plx_i2c_linesda; - param->vrsensorpresent = info->vrsensorpresent; - param->liquidsensorpresent = info->liquidsensorpresent; - - param->maxvoltagestepgfx = info->maxvoltagestepgfx; - param->maxvoltagestepsoc = info->maxvoltagestepsoc; - - param->vddgfxvrmapping = info->vddgfxvrmapping; - param->vddsocvrmapping = info->vddsocvrmapping; - param->vddmem0vrmapping = info->vddmem0vrmapping; - param->vddmem1vrmapping = info->vddmem1vrmapping; - - param->gfxulvphasesheddingmask = info->gfxulvphasesheddingmask; - param->soculvphasesheddingmask = info->soculvphasesheddingmask; - - param->gfxmaxcurrent = info->gfxmaxcurrent; - param->gfxoffset = info->gfxoffset; - param->padding_telemetrygfx = info->padding_telemetrygfx; - - param->socmaxcurrent = info->socmaxcurrent; - param->socoffset = info->socoffset; - param->padding_telemetrysoc = info->padding_telemetrysoc; - - param->mem0maxcurrent = info->mem0maxcurrent; - param->mem0offset = info->mem0offset; - param->padding_telemetrymem0 = info->padding_telemetrymem0; - - param->mem1maxcurrent = info->mem1maxcurrent; - param->mem1offset = info->mem1offset; - param->padding_telemetrymem1 = info->padding_telemetrymem1; - - param->acdcgpio = info->acdcgpio; - param->acdcpolarity = info->acdcpolarity; - param->vr0hotgpio = info->vr0hotgpio; - param->vr0hotpolarity = info->vr0hotpolarity; - - param->vr1hotgpio = info->vr1hotgpio; - param->vr1hotpolarity = info->vr1hotpolarity; - param->padding1 = info->padding1; - param->padding2 = info->padding2; - - param->ledpin0 = info->ledpin0; - param->ledpin1 = info->ledpin1; - param->ledpin2 = info->ledpin2; - - param->pllgfxclkspreadenabled = info->pllgfxclkspreadenabled; - param->pllgfxclkspreadpercent = info->pllgfxclkspreadpercent; - param->pllgfxclkspreadfreq = info->pllgfxclkspreadfreq; - - param->uclkspreadenabled = info->uclkspreadenabled; - param->uclkspreadpercent = info->uclkspreadpercent; - param->uclkspreadfreq = info->uclkspreadfreq; - - param->socclkspreadenabled = info->socclkspreadenabled; - param->socclkspreadpercent = info->socclkspreadpercent; - param->socclkspreadfreq = info->socclkspreadfreq; - - param->acggfxclkspreadenabled = info->acggfxclkspreadenabled; - param->acggfxclkspreadpercent = info->acggfxclkspreadpercent; - param->acggfxclkspreadfreq = info->acggfxclkspreadfreq; - - param->Vr2_I2C_address = info->Vr2_I2C_address; - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h deleted file mode 100644 index b7e2651b570b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2016 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 PP_ATOMFWCTRL_H -#define PP_ATOMFWCTRL_H - -#include "hwmgr.h" - -typedef enum atom_smu9_syspll0_clock_id BIOS_CLKID; - -#define GetIndexIntoMasterCmdTable(FieldName) \ - (((char*)(&((struct atom_master_list_of_command_functions_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t)) -#define GetIndexIntoMasterDataTable(FieldName) \ - (((char*)(&((struct atom_master_list_of_data_tables_v2_1*)0)->FieldName)-(char*)0)/sizeof(uint16_t)) - -#define PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES 32 - -struct pp_atomfwctrl_voltage_table_entry { - uint16_t value; - uint32_t smio_low; -}; - -struct pp_atomfwctrl_voltage_table { - uint32_t count; - uint32_t mask_low; - uint32_t phase_delay; - uint8_t psi0_enable; - uint8_t psi1_enable; - uint8_t max_vid_step; - uint8_t telemetry_offset; - uint8_t telemetry_slope; - struct pp_atomfwctrl_voltage_table_entry entries[PP_ATOMFWCTRL_MAX_VOLTAGE_ENTRIES]; -}; - -struct pp_atomfwctrl_gpio_pin_assignment { - uint16_t us_gpio_pin_aindex; - uint8_t uc_gpio_pin_bit_shift; -}; - -struct pp_atomfwctrl_clock_dividers_soc15 { - uint32_t ulClock; /* the actual clock */ - uint32_t ulDid; /* DFS divider */ - uint32_t ulPll_fb_mult; /* Feedback Multiplier: bit 8:0 int, bit 15:12 post_div, bit 31:16 frac */ - uint32_t ulPll_ss_fbsmult; /* Spread FB Multiplier: bit 8:0 int, bit 31:16 frac */ - uint16_t usPll_ss_slew_frac; - uint8_t ucPll_ss_enable; - uint8_t ucReserve; - uint32_t ulReserve[2]; -}; - -struct pp_atomfwctrl_avfs_parameters { - uint32_t ulMaxVddc; - uint32_t ulMinVddc; - - uint32_t ulMeanNsigmaAcontant0; - uint32_t ulMeanNsigmaAcontant1; - uint32_t ulMeanNsigmaAcontant2; - uint16_t usMeanNsigmaDcTolSigma; - uint16_t usMeanNsigmaPlatformMean; - uint16_t usMeanNsigmaPlatformSigma; - uint32_t ulGbVdroopTableCksoffA0; - uint32_t ulGbVdroopTableCksoffA1; - uint32_t ulGbVdroopTableCksoffA2; - uint32_t ulGbVdroopTableCksonA0; - uint32_t ulGbVdroopTableCksonA1; - uint32_t ulGbVdroopTableCksonA2; - - uint32_t ulGbFuseTableCksoffM1; - uint32_t ulGbFuseTableCksoffM2; - uint32_t ulGbFuseTableCksoffB; - - uint32_t ulGbFuseTableCksonM1; - uint32_t ulGbFuseTableCksonM2; - uint32_t ulGbFuseTableCksonB; - - uint8_t ucEnableGbVdroopTableCkson; - uint8_t ucEnableGbFuseTableCkson; - uint16_t usPsmAgeComfactor; - - uint32_t ulDispclk2GfxclkM1; - uint32_t ulDispclk2GfxclkM2; - uint32_t ulDispclk2GfxclkB; - uint32_t ulDcefclk2GfxclkM1; - uint32_t ulDcefclk2GfxclkM2; - uint32_t ulDcefclk2GfxclkB; - uint32_t ulPixelclk2GfxclkM1; - uint32_t ulPixelclk2GfxclkM2; - uint32_t ulPixelclk2GfxclkB; - uint32_t ulPhyclk2GfxclkM1; - uint32_t ulPhyclk2GfxclkM2; - uint32_t ulPhyclk2GfxclkB; - uint32_t ulAcgGbVdroopTableA0; - uint32_t ulAcgGbVdroopTableA1; - uint32_t ulAcgGbVdroopTableA2; - uint32_t ulAcgGbFuseTableM1; - uint32_t ulAcgGbFuseTableM2; - uint32_t ulAcgGbFuseTableB; - uint32_t ucAcgEnableGbVdroopTable; - uint32_t ucAcgEnableGbFuseTable; -}; - -struct pp_atomfwctrl_gpio_parameters { - uint8_t ucAcDcGpio; - uint8_t ucAcDcPolarity; - uint8_t ucVR0HotGpio; - uint8_t ucVR0HotPolarity; - uint8_t ucVR1HotGpio; - uint8_t ucVR1HotPolarity; - uint8_t ucFwCtfGpio; - uint8_t ucFwCtfPolarity; -}; - -struct pp_atomfwctrl_bios_boot_up_values { - uint32_t ulRevision; - uint32_t ulGfxClk; - uint32_t ulUClk; - uint32_t ulSocClk; - uint32_t ulDCEFClk; - uint32_t ulEClk; - uint32_t ulVClk; - uint32_t ulDClk; - uint32_t ulFClk; - uint16_t usVddc; - uint16_t usVddci; - uint16_t usMvddc; - uint16_t usVddGfx; - uint8_t ucCoolingID; -}; - -struct pp_atomfwctrl_smc_dpm_parameters -{ - uint8_t liquid1_i2c_address; - uint8_t liquid2_i2c_address; - uint8_t vr_i2c_address; - uint8_t plx_i2c_address; - uint8_t liquid_i2c_linescl; - uint8_t liquid_i2c_linesda; - uint8_t vr_i2c_linescl; - uint8_t vr_i2c_linesda; - uint8_t plx_i2c_linescl; - uint8_t plx_i2c_linesda; - uint8_t vrsensorpresent; - uint8_t liquidsensorpresent; - uint16_t maxvoltagestepgfx; - uint16_t maxvoltagestepsoc; - uint8_t vddgfxvrmapping; - uint8_t vddsocvrmapping; - uint8_t vddmem0vrmapping; - uint8_t vddmem1vrmapping; - uint8_t gfxulvphasesheddingmask; - uint8_t soculvphasesheddingmask; - - uint16_t gfxmaxcurrent; - uint8_t gfxoffset; - uint8_t padding_telemetrygfx; - uint16_t socmaxcurrent; - uint8_t socoffset; - uint8_t padding_telemetrysoc; - uint16_t mem0maxcurrent; - uint8_t mem0offset; - uint8_t padding_telemetrymem0; - uint16_t mem1maxcurrent; - uint8_t mem1offset; - uint8_t padding_telemetrymem1; - - uint8_t acdcgpio; - uint8_t acdcpolarity; - uint8_t vr0hotgpio; - uint8_t vr0hotpolarity; - uint8_t vr1hotgpio; - uint8_t vr1hotpolarity; - uint8_t padding1; - uint8_t padding2; - - uint8_t ledpin0; - uint8_t ledpin1; - uint8_t ledpin2; - - uint8_t pllgfxclkspreadenabled; - uint8_t pllgfxclkspreadpercent; - uint16_t pllgfxclkspreadfreq; - - uint8_t uclkspreadenabled; - uint8_t uclkspreadpercent; - uint16_t uclkspreadfreq; - - uint8_t socclkspreadenabled; - uint8_t socclkspreadpercent; - uint16_t socclkspreadfreq; - - uint8_t acggfxclkspreadenabled; - uint8_t acggfxclkspreadpercent; - uint16_t acggfxclkspreadfreq; - - uint8_t Vr2_I2C_address; -}; - -int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr, - uint32_t clock_type, uint32_t clock_value, - struct pp_atomfwctrl_clock_dividers_soc15 *dividers); -int pp_atomfwctrl_enter_self_refresh(struct pp_hwmgr *hwmgr); -bool pp_atomfwctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pin_id, - struct pp_atomfwctrl_gpio_pin_assignment *gpio_pin_assignment); - -int pp_atomfwctrl_get_voltage_table_v4(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint8_t voltage_mode, struct pp_atomfwctrl_voltage_table *voltage_table); -bool pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(struct pp_hwmgr *hwmgr, - uint8_t voltage_type, uint8_t voltage_mode); - -int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_avfs_parameters *param); -int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_gpio_parameters *param); - -int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_bios_boot_up_values *boot_values); -int pp_atomfwctrl_get_smc_dpm_information(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_smc_dpm_parameters *param); -int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, - uint8_t clk_id, uint8_t syspll_id, - uint32_t *frequency); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h deleted file mode 100644 index 8f50a038396c..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright 2015 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 - -#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ - -#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */ - -#define SHIFTED_2 (2 << SHIFT_AMOUNT) -#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */ - -/* ------------------------------------------------------------------------------- - * NEW TYPE - fINT - * ------------------------------------------------------------------------------- - * A variable of type fInt can be accessed in 3 ways using the dot (.) operator - * fInt A; - * A.full => The full number as it is. Generally not easy to read - * A.partial.real => Only the integer portion - * A.partial.decimal => Only the fractional portion - */ -typedef union _fInt { - int full; - struct _partial { - unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/ - int real: 32 - SHIFT_AMOUNT; - } partial; -} fInt; - -/* ------------------------------------------------------------------------------- - * Function Declarations - * ------------------------------------------------------------------------------- - */ -static fInt ConvertToFraction(int); /* Use this to convert an INT to a FINT */ -static fInt Convert_ULONG_ToFraction(uint32_t); /* Use this to convert an uint32_t to a FINT */ -static fInt GetScaledFraction(int, int); /* Use this to convert an INT to a FINT after scaling it by a factor */ -static int ConvertBackToInteger(fInt); /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */ - -static fInt fNegate(fInt); /* Returns -1 * input fInt value */ -static fInt fAdd (fInt, fInt); /* Returns the sum of two fInt numbers */ -static fInt fSubtract (fInt A, fInt B); /* Returns A-B - Sometimes easier than Adding negative numbers */ -static fInt fMultiply (fInt, fInt); /* Returns the product of two fInt numbers */ -static fInt fDivide (fInt A, fInt B); /* Returns A/B */ -static fInt fGetSquare(fInt); /* Returns the square of a fInt number */ -static fInt fSqrt(fInt); /* Returns the Square Root of a fInt number */ - -static int uAbs(int); /* Returns the Absolute value of the Int */ -static int uPow(int base, int exponent); /* Returns base^exponent an INT */ - -static void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */ -static bool Equal(fInt, fInt); /* Returns true if two fInts are equal to each other */ -static bool GreaterThan(fInt A, fInt B); /* Returns true if A > B */ - -static fInt fExponential(fInt exponent); /* Can be used to calculate e^exponent */ -static fInt fNaturalLog(fInt value); /* Can be used to calculate ln(value) */ - -/* Fuse decoding functions - * ------------------------------------------------------------------------------------- - */ -static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength); -static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength); -static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength); - -/* Internal Support Functions - Use these ONLY for testing or adding to internal functions - * ------------------------------------------------------------------------------------- - * Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons. - */ -static fInt Divide (int, int); /* Divide two INTs and return result as FINT */ -static fInt fNegate(fInt); - -static int uGetScaledDecimal (fInt); /* Internal function */ -static int GetReal (fInt A); /* Internal function */ - -/* ------------------------------------------------------------------------------------- - * TROUBLESHOOTING INFORMATION - * ------------------------------------------------------------------------------------- - * 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767) - * 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767) - * 3) fMultiply - OutputOutOfRangeException: - * 4) fGetSquare - OutputOutOfRangeException: - * 5) fDivide - DivideByZeroException - * 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number - */ - -/* ------------------------------------------------------------------------------------- - * START OF CODE - * ------------------------------------------------------------------------------------- - */ -static fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/ -{ - uint32_t i; - bool bNegated = false; - - fInt fPositiveOne = ConvertToFraction(1); - fInt fZERO = ConvertToFraction(0); - - fInt lower_bound = Divide(78, 10000); - fInt solution = fPositiveOne; /*Starting off with baseline of 1 */ - fInt error_term; - - static const uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; - static const uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; - - if (GreaterThan(fZERO, exponent)) { - exponent = fNegate(exponent); - bNegated = true; - } - - while (GreaterThan(exponent, lower_bound)) { - for (i = 0; i < 11; i++) { - if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) { - exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000)); - solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000)); - } - } - } - - error_term = fAdd(fPositiveOne, exponent); - - solution = fMultiply(solution, error_term); - - if (bNegated) - solution = fDivide(fPositiveOne, solution); - - return solution; -} - -static fInt fNaturalLog(fInt value) -{ - uint32_t i; - fInt upper_bound = Divide(8, 1000); - fInt fNegativeOne = ConvertToFraction(-1); - fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */ - fInt error_term; - - static const uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; - static const uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; - - while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) { - for (i = 0; i < 10; i++) { - if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) { - value = fDivide(value, GetScaledFraction(k_array[i], 10000)); - solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000)); - } - } - } - - error_term = fAdd(fNegativeOne, value); - - return (fAdd(solution, error_term)); -} - -static fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength) -{ - fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); - fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); - - fInt f_decoded_value; - - f_decoded_value = fDivide(f_fuse_value, f_bit_max_value); - f_decoded_value = fMultiply(f_decoded_value, f_range); - f_decoded_value = fAdd(f_decoded_value, f_min); - - return f_decoded_value; -} - - -static fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength) -{ - fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); - fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); - - fInt f_CONSTANT_NEG13 = ConvertToFraction(-13); - fInt f_CONSTANT1 = ConvertToFraction(1); - - fInt f_decoded_value; - - f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1); - f_decoded_value = fNaturalLog(f_decoded_value); - f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13)); - f_decoded_value = fAdd(f_decoded_value, f_average); - - return f_decoded_value; -} - -static fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength) -{ - fInt fLeakage; - fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); - - fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse)); - fLeakage = fDivide(fLeakage, f_bit_max_value); - fLeakage = fExponential(fLeakage); - fLeakage = fMultiply(fLeakage, f_min); - - return fLeakage; -} - -static fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */ -{ - fInt temp; - - if (X <= MAX) - temp.full = (X << SHIFT_AMOUNT); - else - temp.full = 0; - - return temp; -} - -static fInt fNegate(fInt X) -{ - fInt CONSTANT_NEGONE = ConvertToFraction(-1); - return (fMultiply(X, CONSTANT_NEGONE)); -} - -static fInt Convert_ULONG_ToFraction(uint32_t X) -{ - fInt temp; - - if (X <= MAX) - temp.full = (X << SHIFT_AMOUNT); - else - temp.full = 0; - - return temp; -} - -static fInt GetScaledFraction(int X, int factor) -{ - int times_shifted, factor_shifted; - bool bNEGATED; - fInt fValue; - - times_shifted = 0; - factor_shifted = 0; - bNEGATED = false; - - if (X < 0) { - X = -1*X; - bNEGATED = true; - } - - if (factor < 0) { - factor = -1*factor; - bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */ - } - - if ((X > MAX) || factor > MAX) { - if ((X/factor) <= MAX) { - while (X > MAX) { - X = X >> 1; - times_shifted++; - } - - while (factor > MAX) { - factor = factor >> 1; - factor_shifted++; - } - } else { - fValue.full = 0; - return fValue; - } - } - - if (factor == 1) - return ConvertToFraction(X); - - fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor)); - - fValue.full = fValue.full << times_shifted; - fValue.full = fValue.full >> factor_shifted; - - return fValue; -} - -/* Addition using two fInts */ -static fInt fAdd (fInt X, fInt Y) -{ - fInt Sum; - - Sum.full = X.full + Y.full; - - return Sum; -} - -/* Addition using two fInts */ -static fInt fSubtract (fInt X, fInt Y) -{ - fInt Difference; - - Difference.full = X.full - Y.full; - - return Difference; -} - -static bool Equal(fInt A, fInt B) -{ - if (A.full == B.full) - return true; - else - return false; -} - -static bool GreaterThan(fInt A, fInt B) -{ - if (A.full > B.full) - return true; - else - return false; -} - -static fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */ -{ - fInt Product; - int64_t tempProduct; - bool X_LessThanOne, Y_LessThanOne; - - X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0); - Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0); - - /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ - /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION - - if (X_LessThanOne && Y_LessThanOne) { - Product.full = X.full * Y.full; - return Product - }*/ - - tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */ - tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */ - Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */ - - return Product; -} - -static fInt fDivide (fInt X, fInt Y) -{ - fInt fZERO, fQuotient; - int64_t longlongX, longlongY; - - fZERO = ConvertToFraction(0); - - if (Equal(Y, fZERO)) - return fZERO; - - longlongX = (int64_t)X.full; - longlongY = (int64_t)Y.full; - - longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */ - - div64_s64(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */ - - fQuotient.full = (int)longlongX; - return fQuotient; -} - -static int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/ -{ - fInt fullNumber, scaledDecimal, scaledReal; - - scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */ - - scaledDecimal.full = uGetScaledDecimal(A); - - fullNumber = fAdd(scaledDecimal,scaledReal); - - return fullNumber.full; -} - -static fInt fGetSquare(fInt A) -{ - return fMultiply(A,A); -} - -/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */ -static fInt fSqrt(fInt num) -{ - fInt F_divide_Fprime, Fprime; - fInt test; - fInt twoShifted; - int seed, counter, error; - fInt x_new, x_old, C, y; - - fInt fZERO = ConvertToFraction(0); - - /* (0 > num) is the same as (num < 0), i.e., num is negative */ - - if (GreaterThan(fZERO, num) || Equal(fZERO, num)) - return fZERO; - - C = num; - - if (num.partial.real > 3000) - seed = 60; - else if (num.partial.real > 1000) - seed = 30; - else if (num.partial.real > 100) - seed = 10; - else - seed = 2; - - counter = 0; - - if (Equal(num, fZERO)) /*Square Root of Zero is zero */ - return fZERO; - - twoShifted = ConvertToFraction(2); - x_new = ConvertToFraction(seed); - - do { - counter++; - - x_old.full = x_new.full; - - test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */ - y = fSubtract(test, C); /*y = f(x) = x^2 - C; */ - - Fprime = fMultiply(twoShifted, x_old); - F_divide_Fprime = fDivide(y, Fprime); - - x_new = fSubtract(x_old, F_divide_Fprime); - - error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old); - - if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/ - return x_new; - - } while (uAbs(error) > 0); - - return (x_new); -} - -static void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[]) -{ - fInt *pRoots = &Roots[0]; - fInt temp, root_first, root_second; - fInt f_CONSTANT10, f_CONSTANT100; - - f_CONSTANT100 = ConvertToFraction(100); - f_CONSTANT10 = ConvertToFraction(10); - - while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) { - A = fDivide(A, f_CONSTANT10); - B = fDivide(B, f_CONSTANT10); - C = fDivide(C, f_CONSTANT10); - } - - temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */ - temp = fMultiply(temp, C); /* root = 4*A*C */ - temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */ - temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */ - - root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */ - root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */ - - root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ - root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ - - root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ - root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ - - *(pRoots + 0) = root_first; - *(pRoots + 1) = root_second; -} - -/* ----------------------------------------------------------------------------- - * SUPPORT FUNCTIONS - * ----------------------------------------------------------------------------- - */ - -/* Conversion Functions */ -static int GetReal (fInt A) -{ - return (A.full >> SHIFT_AMOUNT); -} - -static fInt Divide (int X, int Y) -{ - fInt A, B, Quotient; - - A.full = X << SHIFT_AMOUNT; - B.full = Y << SHIFT_AMOUNT; - - Quotient = fDivide(A, B); - - return Quotient; -} - -static int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */ -{ - int dec[PRECISION]; - int i, scaledDecimal = 0, tmp = A.partial.decimal; - - for (i = 0; i < PRECISION; i++) { - dec[i] = tmp / (1 << SHIFT_AMOUNT); - tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]); - tmp *= 10; - scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i); - } - - return scaledDecimal; -} - -static int uPow(int base, int power) -{ - if (power == 0) - return 1; - else - return (base)*uPow(base, power - 1); -} - -static int uAbs(int X) -{ - if (X < 0) - return (X * -1); - else - return X; -} - -static fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term) -{ - fInt solution; - - solution = fDivide(A, fStepSize); - solution.partial.decimal = 0; /*All fractional digits changes to 0 */ - - if (error_term) - solution.partial.real += 1; /*Error term of 1 added */ - - solution = fMultiply(solution, fStepSize); - solution = fAdd(solution, fStepSize); - - return solution; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c deleted file mode 100644 index 186496a34cbe..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2015 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 -#include "atom-types.h" -#include "atombios.h" -#include "pppcielanes.h" - -/** \file - * Functions related to PCIe lane changes. - */ - -/* For converting from number of lanes to lane bits. */ -static const unsigned char pp_r600_encode_lanes[] = { - 0, /* 0 Not Supported */ - 1, /* 1 Lane */ - 2, /* 2 Lanes */ - 0, /* 3 Not Supported */ - 3, /* 4 Lanes */ - 0, /* 5 Not Supported */ - 0, /* 6 Not Supported */ - 0, /* 7 Not Supported */ - 4, /* 8 Lanes */ - 0, /* 9 Not Supported */ - 0, /* 10 Not Supported */ - 0, /* 11 Not Supported */ - 5, /* 12 Lanes (Not actually supported) */ - 0, /* 13 Not Supported */ - 0, /* 14 Not Supported */ - 0, /* 15 Not Supported */ - 6 /* 16 Lanes */ -}; - -static const unsigned char pp_r600_decoded_lanes[8] = { 16, 1, 2, 4, 8, 12, 16, }; - -uint8_t encode_pcie_lane_width(uint32_t num_lanes) -{ - return pp_r600_encode_lanes[num_lanes]; -} - -uint8_t decode_pcie_lane_width(uint32_t num_lanes) -{ - return pp_r600_decoded_lanes[num_lanes]; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h deleted file mode 100644 index 70b163b35570..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2015 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 PP_PCIELANES_H -#define PP_PCIELANES_H - -extern uint8_t encode_pcie_lane_width(uint32_t num_lanes); -extern uint8_t decode_pcie_lane_width(uint32_t num_lanes); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h deleted file mode 100644 index 1e870f58dd12..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pptable_v1_0.h +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright 2015 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 TONGA_PPTABLE_H -#define TONGA_PPTABLE_H - -/** \file - * This is a PowerPlay table header file - */ -#pragma pack(push, 1) - -#include "hwmgr.h" - -#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f -#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */ - -#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17 -#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21 -#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22 - -/* - * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. - * We probably should reserve the bit 0x80 for this use. - * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). - * The driver can pick the correct internal controller based on the ASIC. - */ - -#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */ -#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */ - -/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */ -#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */ -#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */ -#define ____RETIRE16____ 0x10 -#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */ -#define ____RETIRE64____ 0x40 -#define ____RETIRE128____ 0x80 -#define ____RETIRE256____ 0x100 -#define ____RETIRE512____ 0x200 -#define ____RETIRE1024____ 0x400 -#define ____RETIRE2048____ 0x800 -#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */ -#define ____RETIRE2000____ 0x2000 -#define ____RETIRE4000____ 0x4000 -#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */ -#define ____RETIRE10000____ 0x10000 -#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */ - -#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */ -#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */ -#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000 - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ -#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 -#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 -#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 -#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 -/* 2, 4, 6, 7 are reserved */ - -#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 -#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 -#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 -#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 -#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 -#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ -#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 - -#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000 -#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000 - -#define ATOM_Tonga_TABLE_REVISION_TONGA 7 - -typedef struct _ATOM_Tonga_POWERPLAYTABLE { - ATOM_COMMON_TABLE_HEADER sHeader; - - UCHAR ucTableRevision; - USHORT usTableSize; /*the size of header structure */ - - ULONG ulGoldenPPID; - ULONG ulGoldenRevision; - USHORT usFormatID; - - USHORT usVoltageTime; /*in microseconds */ - ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */ - - ULONG ulMaxODEngineClock; /*For Overdrive. */ - ULONG ulMaxODMemoryClock; /*For Overdrive. */ - - USHORT usPowerControlLimit; - USHORT usUlvVoltageOffset; /*in mv units */ - - USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */ - USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */ - USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */ - USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */ - - USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */ - USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */ - USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ - USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ - - USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */ - - USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */ - - USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */ - USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */ - - USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */ - - USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */ - - USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */ - - USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */ -} ATOM_Tonga_POWERPLAYTABLE; - -typedef struct _ATOM_Tonga_State { - UCHAR ucEngineClockIndexHigh; - UCHAR ucEngineClockIndexLow; - - UCHAR ucMemoryClockIndexHigh; - UCHAR ucMemoryClockIndexLow; - - UCHAR ucPCIEGenLow; - UCHAR ucPCIEGenHigh; - - UCHAR ucPCIELaneLow; - UCHAR ucPCIELaneHigh; - - USHORT usClassification; - ULONG ulCapsAndSettings; - USHORT usClassification2; - UCHAR ucUnused[4]; -} ATOM_Tonga_State; - -typedef struct _ATOM_Tonga_State_Array { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_State entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_State_Array; - -typedef struct _ATOM_Tonga_MCLK_Dependency_Record { - UCHAR ucVddcInd; /* Vddc voltage */ - USHORT usVddci; - USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */ - USHORT usMvdd; - ULONG ulMclk; - USHORT usReserved; -} ATOM_Tonga_MCLK_Dependency_Record; - -typedef struct _ATOM_Tonga_MCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_MCLK_Dependency_Table; - -typedef struct _ATOM_Tonga_SCLK_Dependency_Record { - UCHAR ucVddInd; /* Base voltage */ - USHORT usVddcOffset; /* Offset relative to base voltage */ - ULONG ulSclk; - USHORT usEdcCurrent; - UCHAR ucReliabilityTemperature; - UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ -} ATOM_Tonga_SCLK_Dependency_Record; - -typedef struct _ATOM_Tonga_SCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_SCLK_Dependency_Table; - -typedef struct _ATOM_Polaris_SCLK_Dependency_Record { - UCHAR ucVddInd; /* Base voltage */ - USHORT usVddcOffset; /* Offset relative to base voltage */ - ULONG ulSclk; - USHORT usEdcCurrent; - UCHAR ucReliabilityTemperature; - UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ - ULONG ulSclkOffset; -} ATOM_Polaris_SCLK_Dependency_Record; - -typedef struct _ATOM_Polaris_SCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Polaris_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Polaris_SCLK_Dependency_Table; - -typedef struct _ATOM_Tonga_PCIE_Record { - UCHAR ucPCIEGenSpeed; - UCHAR usPCIELaneWidth; - UCHAR ucReserved[2]; -} ATOM_Tonga_PCIE_Record; - -typedef struct _ATOM_Tonga_PCIE_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_PCIE_Table; - -typedef struct _ATOM_Polaris10_PCIE_Record { - UCHAR ucPCIEGenSpeed; - UCHAR usPCIELaneWidth; - UCHAR ucReserved[2]; - ULONG ulPCIE_Sclk; -} ATOM_Polaris10_PCIE_Record; - -typedef struct _ATOM_Polaris10_PCIE_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Polaris10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Polaris10_PCIE_Table; - - -typedef struct _ATOM_Tonga_MM_Dependency_Record { - UCHAR ucVddcInd; /* VDDC voltage */ - USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ - ULONG ulDClk; /* UVD D-clock */ - ULONG ulVClk; /* UVD V-clock */ - ULONG ulEClk; /* VCE clock */ - ULONG ulAClk; /* ACP clock */ - ULONG ulSAMUClk; /* SAMU clock */ -} ATOM_Tonga_MM_Dependency_Record; - -typedef struct _ATOM_Tonga_MM_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_MM_Dependency_Table; - -typedef struct _ATOM_Tonga_Voltage_Lookup_Record { - USHORT usVdd; /* Base voltage */ - USHORT usCACLow; - USHORT usCACMid; - USHORT usCACHigh; -} ATOM_Tonga_Voltage_Lookup_Record; - -typedef struct _ATOM_Tonga_Voltage_Lookup_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Tonga_Voltage_Lookup_Table; - -typedef struct _ATOM_Tonga_Fan_Table { - UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ - UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ - USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ - USHORT usTMed; /* The middle temperature where we change slopes. */ - USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ - USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ - USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ - USHORT usPWMHigh; /* The PWM value at THigh. */ - USHORT usTMax; /* The max temperature */ - UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ - USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ - USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ - USHORT usFanRPMMax; /* The default value in RPM */ - ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ - UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ - UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ - USHORT usReserved; -} ATOM_Tonga_Fan_Table; - -typedef struct _ATOM_Fiji_Fan_Table { - UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ - UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ - USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ - USHORT usTMed; /* The middle temperature where we change slopes. */ - USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ - USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ - USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ - USHORT usPWMHigh; /* The PWM value at THigh. */ - USHORT usTMax; /* The max temperature */ - UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ - USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ - USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ - USHORT usFanRPMMax; /* The default value in RPM */ - ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ - UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ - UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ - USHORT usFanGainEdge; - USHORT usFanGainHotspot; - USHORT usFanGainLiquid; - USHORT usFanGainVrVddc; - USHORT usFanGainVrMvdd; - USHORT usFanGainPlx; - USHORT usFanGainHbm; - USHORT usReserved; -} ATOM_Fiji_Fan_Table; - -typedef struct _ATOM_Tonga_Thermal_Controller { - UCHAR ucRevId; - UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ - UCHAR ucI2cLine; /* as interpreted by DAL I2C */ - UCHAR ucI2cAddress; - UCHAR ucFanParameters; /* Fan Control Parameters. */ - UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */ - UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */ - UCHAR ucReserved; - UCHAR ucFlags; /* to be defined */ -} ATOM_Tonga_Thermal_Controller; - -typedef struct _ATOM_Tonga_VCE_State_Record { - UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */ - UCHAR ucFlag; /* 2 bits indicates memory p-states */ - UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */ - UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */ -} ATOM_Tonga_VCE_State_Record; - -typedef struct _ATOM_Tonga_VCE_State_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Tonga_VCE_State_Record entries[1]; -} ATOM_Tonga_VCE_State_Table; - -typedef struct _ATOM_Tonga_PowerTune_Table { - UCHAR ucRevId; - USHORT usTDP; - USHORT usConfigurableTDP; - USHORT usTDC; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usLowCACLeakage; - USHORT usHighCACLeakage; - USHORT usMaximumPowerDeliveryLimit; - USHORT usTjMax; - USHORT usPowerTuneDataSetID; - USHORT usEDCLimit; - USHORT usSoftwareShutdownTemp; - USHORT usClockStretchAmount; - USHORT usReserve[2]; -} ATOM_Tonga_PowerTune_Table; - -typedef struct _ATOM_Fiji_PowerTune_Table { - UCHAR ucRevId; - USHORT usTDP; - USHORT usConfigurableTDP; - USHORT usTDC; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usLowCACLeakage; - USHORT usHighCACLeakage; - USHORT usMaximumPowerDeliveryLimit; - USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */ - USHORT usPowerTuneDataSetID; - USHORT usEDCLimit; - USHORT usSoftwareShutdownTemp; - USHORT usClockStretchAmount; - USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */ - USHORT usTemperatureLimitLiquid1; - USHORT usTemperatureLimitLiquid2; - USHORT usTemperatureLimitVrVddc; - USHORT usTemperatureLimitVrMvdd; - USHORT usTemperatureLimitPlx; - UCHAR ucLiquid1_I2C_address; /*Liquid */ - UCHAR ucLiquid2_I2C_address; - UCHAR ucLiquid_I2C_Line; - UCHAR ucVr_I2C_address; /*VR */ - UCHAR ucVr_I2C_Line; - UCHAR ucPlx_I2C_address; /*PLX */ - UCHAR ucPlx_I2C_Line; - USHORT usReserved; -} ATOM_Fiji_PowerTune_Table; - -#define ATOM_PPM_A_A 1 -#define ATOM_PPM_A_I 2 -typedef struct _ATOM_Tonga_PPM_Table { - UCHAR ucRevId; - UCHAR ucPpmDesign; /*A+I or A+A */ - USHORT usCpuCoreNumber; - ULONG ulPlatformTDP; - ULONG ulSmallACPlatformTDP; - ULONG ulPlatformTDC; - ULONG ulSmallACPlatformTDC; - ULONG ulApuTDP; - ULONG ulDGpuTDP; - ULONG ulDGpuUlvPower; - ULONG ulTjmax; -} ATOM_Tonga_PPM_Table; - -typedef struct _ATOM_Tonga_Hard_Limit_Record { - ULONG ulSCLKLimit; - ULONG ulMCLKLimit; - USHORT usVddcLimit; - USHORT usVddciLimit; - USHORT usVddgfxLimit; -} ATOM_Tonga_Hard_Limit_Record; - -typedef struct _ATOM_Tonga_Hard_Limit_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Tonga_Hard_Limit_Record entries[1]; -} ATOM_Tonga_Hard_Limit_Table; - -typedef struct _ATOM_Tonga_GPIO_Table { - UCHAR ucRevId; - UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */ - UCHAR ucReserve[5]; -} ATOM_Tonga_GPIO_Table; - -typedef struct _PPTable_Generic_SubTable_Header { - UCHAR ucRevId; -} PPTable_Generic_SubTable_Header; - - -#pragma pack(pop) - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c deleted file mode 100644 index b760f95e7fa7..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c +++ /dev/null @@ -1,1337 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include - -#include "process_pptables_v1_0.h" -#include "ppatomctrl.h" -#include "atombios.h" -#include "hwmgr.h" -#include "cgs_common.h" -#include "pptable_v1_0.h" - -/** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). - * @param cap Which capability to set/reset. - */ -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) -{ - if (setIt) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - - -/** - * Private Function used during initialization. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_caps the bit array (from BIOS) of capability bits. - * @exception the current implementation always returns 1. - */ -static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) -{ - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), - "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), - "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), - "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), - "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); - PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), - "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), - PHM_PlatformCaps_AutomaticDCTransition - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), - PHM_PlatformCaps_EnableMVDDControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), - PHM_PlatformCaps_ControlVDDCI - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), - PHM_PlatformCaps_ControlVDDGFX - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), - PHM_PlatformCaps_DisableVoltageIsland - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), - PHM_PlatformCaps_CombinePCCWithThermalSignal - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), - PHM_PlatformCaps_LoadPostProductionFirmware - ); - - return 0; -} - -/** - * Private Function to get the PowerPlay Table Address. - */ -static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) -{ - int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); - - u16 size; - u8 frev, crev; - void *table_address = (void *)hwmgr->soft_pp_table; - - if (!table_address) { - table_address = (ATOM_Tonga_POWERPLAYTABLE *) - smu_atom_get_data_table(hwmgr->adev, - index, &size, &frev, &crev); - hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ - hwmgr->soft_pp_table_size = size; - } - - return table_address; -} - -static int get_vddc_lookup_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table **lookup_table, - const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, - uint32_t max_levels - ) -{ - uint32_t table_size, i; - phm_ppt_v1_voltage_lookup_table *table; - phm_ppt_v1_voltage_lookup_record *record; - ATOM_Tonga_Voltage_Lookup_Record *atom_record; - - PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), - "Invalid CAC Leakage PowerPlay Table!", return 1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - table->count = vddc_lookup_pp_tables->ucNumEntries; - - for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { - record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_voltage_lookup_record, - entries, table, i); - atom_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_Voltage_Lookup_Record, - entries, vddc_lookup_pp_tables, i); - record->us_calculated = 0; - record->us_vdd = le16_to_cpu(atom_record->usVdd); - record->us_cac_low = le16_to_cpu(atom_record->usCACLow); - record->us_cac_mid = le16_to_cpu(atom_record->usCACMid); - record->us_cac_high = le16_to_cpu(atom_record->usCACHigh); - } - - *lookup_table = table; - - return 0; -} - -/** - * Private Function used during initialization. - * Initialize Platform Power Management Parameter table - * @param hwmgr Pointer to the hardware manager. - * @param atom_ppm_table Pointer to PPM table in VBIOS - */ -static int get_platform_power_management_table( - struct pp_hwmgr *hwmgr, - ATOM_Tonga_PPM_Table *atom_ppm_table) -{ - struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (NULL == ptr) - return -ENOMEM; - - ptr->ppm_design - = atom_ppm_table->ucPpmDesign; - ptr->cpu_core_number - = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); - ptr->platform_tdp - = le32_to_cpu(atom_ppm_table->ulPlatformTDP); - ptr->small_ac_platform_tdp - = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); - ptr->platform_tdc - = le32_to_cpu(atom_ppm_table->ulPlatformTDC); - ptr->small_ac_platform_tdc - = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); - ptr->apu_tdp - = le32_to_cpu(atom_ppm_table->ulApuTDP); - ptr->dgpu_tdp - = le32_to_cpu(atom_ppm_table->ulDGpuTDP); - ptr->dgpu_ulv_power - = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); - ptr->tj_max - = le32_to_cpu(atom_ppm_table->ulTjmax); - - pp_table_information->ppm_parameter_table = ptr; - - return 0; -} - -/** - * Private Function used during initialization. - * Initialize TDP limits for DPM2 - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - */ -static int init_dpm_2_parameters( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - int result = 0; - struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); - ATOM_Tonga_PPM_Table *atom_ppm_table; - uint32_t disable_ppm = 0; - uint32_t disable_power_control = 0; - - pp_table_information->us_ulv_voltage_offset = - le16_to_cpu(powerplay_table->usUlvVoltageOffset); - - pp_table_information->ppm_parameter_table = NULL; - pp_table_information->vddc_lookup_table = NULL; - pp_table_information->vddgfx_lookup_table = NULL; - /* TDP limits */ - hwmgr->platform_descriptor.TDPODLimit = - le16_to_cpu(powerplay_table->usPowerControlLimit); - hwmgr->platform_descriptor.TDPAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; - hwmgr->platform_descriptor.VidMinLimit = 0; - hwmgr->platform_descriptor.VidMaxLimit = 1500000; - hwmgr->platform_descriptor.VidStep = 6250; - - disable_power_control = 0; - if (0 == disable_power_control) { - /* enable TDP overdrive (PowerControl) feature as well if supported */ - if (hwmgr->platform_descriptor.TDPODLimit != 0) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); - } - - if (0 != powerplay_table->usVddcLookupTableOffset) { - const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = - (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); - - result = get_vddc_lookup_table(hwmgr, - &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); - } - - if (0 != powerplay_table->usVddgfxLookupTableOffset) { - const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = - (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); - - result = get_vddc_lookup_table(hwmgr, - &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); - } - - disable_ppm = 0; - if (0 == disable_ppm) { - atom_ppm_table = (ATOM_Tonga_PPM_Table *) - (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); - - if (0 != powerplay_table->usPPMTableOffset) { - if (get_platform_power_management_table(hwmgr, atom_ppm_table) == 0) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnablePlatformPowerManagement); - } - } - } - - return result; -} - -static int get_valid_clk( - struct pp_hwmgr *hwmgr, - struct phm_clock_array **clk_table, - phm_ppt_v1_clock_voltage_dependency_table const *clk_volt_pp_table - ) -{ - uint32_t table_size, i; - struct phm_clock_array *table; - phm_ppt_v1_clock_voltage_dependency_record *dep_record; - - PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(uint32_t) * clk_volt_pp_table->count; - - table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - table->count = (uint32_t)clk_volt_pp_table->count; - - for (i = 0; i < table->count; i++) { - dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, clk_volt_pp_table, i); - table->values[i] = (uint32_t)dep_record->clk; - } - *clk_table = table; - - return 0; -} - -static int get_hard_limits( - struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *limits, - ATOM_Tonga_Hard_Limit_Table const *limitable - ) -{ - PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); - - /* currently we always take entries[0] parameters */ - limits->sclk = le32_to_cpu(limitable->entries[0].ulSCLKLimit); - limits->mclk = le32_to_cpu(limitable->entries[0].ulMCLKLimit); - limits->vddc = le16_to_cpu(limitable->entries[0].usVddcLimit); - limits->vddci = le16_to_cpu(limitable->entries[0].usVddciLimit); - limits->vddgfx = le16_to_cpu(limitable->entries[0].usVddgfxLimit); - - return 0; -} - -static int get_mclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, - ATOM_Tonga_MCLK_Dependency_Table const *mclk_dep_table - ) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *mclk_table; - phm_ppt_v1_clock_voltage_dependency_record *mclk_table_record; - ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * mclk_dep_table->ucNumEntries; - - mclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mclk_table) - return -ENOMEM; - - mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; - - for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { - mclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, mclk_table, i); - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, i); - mclk_table_record->vddInd = mclk_dep_record->ucVddcInd; - mclk_table_record->vdd_offset = le16_to_cpu(mclk_dep_record->usVddgfxOffset); - mclk_table_record->vddci = le16_to_cpu(mclk_dep_record->usVddci); - mclk_table_record->mvdd = le16_to_cpu(mclk_dep_record->usMvdd); - mclk_table_record->clk = le32_to_cpu(mclk_dep_record->ulMclk); - } - - *pp_tonga_mclk_dep_table = mclk_table; - - return 0; -} - -static int get_sclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, - PPTable_Generic_SubTable_Header const *sclk_dep_table - ) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *sclk_table; - phm_ppt_v1_clock_voltage_dependency_record *sclk_table_record; - - if (sclk_dep_table->ucRevId < 1) { - const ATOM_Tonga_SCLK_Dependency_Table *tonga_table = - (ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table; - ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != tonga_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * tonga_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) - return -ENOMEM; - - sclk_table->count = (uint32_t)tonga_table->ucNumEntries; - - for (i = 0; i < tonga_table->ucNumEntries; i++) { - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_SCLK_Dependency_Record, - entries, tonga_table, i); - sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, sclk_table, i); - sclk_table_record->vddInd = sclk_dep_record->ucVddInd; - sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset); - sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk); - sclk_table_record->cks_enable = - (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); - } - } else { - const ATOM_Polaris_SCLK_Dependency_Table *polaris_table = - (ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table; - ATOM_Polaris_SCLK_Dependency_Record *sclk_dep_record; - - PP_ASSERT_WITH_CODE((0 != polaris_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) - * polaris_table->ucNumEntries; - - sclk_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == sclk_table) - return -ENOMEM; - - sclk_table->count = (uint32_t)polaris_table->ucNumEntries; - - for (i = 0; i < polaris_table->ucNumEntries; i++) { - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Polaris_SCLK_Dependency_Record, - entries, polaris_table, i); - sclk_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_clock_voltage_dependency_record, - entries, sclk_table, i); - sclk_table_record->vddInd = sclk_dep_record->ucVddInd; - sclk_table_record->vdd_offset = le16_to_cpu(sclk_dep_record->usVddcOffset); - sclk_table_record->clk = le32_to_cpu(sclk_dep_record->ulSclk); - sclk_table_record->cks_enable = - (((sclk_dep_record->ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; - sclk_table_record->cks_voffset = (sclk_dep_record->ucCKSVOffsetandDisable & 0x7F); - sclk_table_record->sclk_offset = le32_to_cpu(sclk_dep_record->ulSclkOffset); - } - } - *pp_tonga_sclk_dep_table = sclk_table; - - return 0; -} - -static int get_pcie_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_pcie_table **pp_tonga_pcie_table, - PPTable_Generic_SubTable_Header const *ptable - ) -{ - uint32_t table_size, i, pcie_count; - phm_ppt_v1_pcie_table *pcie_table; - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_pcie_record *pcie_record; - - if (ptable->ucRevId < 1) { - const ATOM_Tonga_PCIE_Table *atom_pcie_table = (ATOM_Tonga_PCIE_Table *)ptable; - ATOM_Tonga_PCIE_Record *atom_pcie_record; - - PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) - return -ENOMEM; - - /* - * Make sure the number of pcie entries are less than or equal to sclk dpm levels. - * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. - */ - pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; - if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) - pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; - else - pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); - - pcie_table->count = pcie_count; - for (i = 0; i < pcie_count; i++) { - pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_pcie_record, - entries, pcie_table, i); - atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_PCIE_Record, - entries, atom_pcie_table, i); - pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; - pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth); - } - - *pp_tonga_pcie_table = pcie_table; - } else { - /* Polaris10/Polaris11 and newer. */ - const ATOM_Polaris10_PCIE_Table *atom_pcie_table = (ATOM_Polaris10_PCIE_Table *)ptable; - ATOM_Polaris10_PCIE_Record *atom_pcie_record; - - PP_ASSERT_WITH_CODE((atom_pcie_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (pcie_table == NULL) - return -ENOMEM; - - /* - * Make sure the number of pcie entries are less than or equal to sclk dpm levels. - * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. - */ - pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; - if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) - pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; - else - pr_err("Number of Pcie Entries exceed the number of SCLK Dpm Levels! Disregarding the excess entries...\n"); - - pcie_table->count = pcie_count; - - for (i = 0; i < pcie_count; i++) { - pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_pcie_record, - entries, pcie_table, i); - atom_pcie_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Polaris10_PCIE_Record, - entries, atom_pcie_table, i); - pcie_record->gen_speed = atom_pcie_record->ucPCIEGenSpeed; - pcie_record->lane_width = le16_to_cpu(atom_pcie_record->usPCIELaneWidth); - pcie_record->pcie_sclk = le32_to_cpu(atom_pcie_record->ulPCIE_Sclk); - } - - *pp_tonga_pcie_table = pcie_table; - } - - return 0; -} - -static int get_cac_tdp_table( - struct pp_hwmgr *hwmgr, - struct phm_cac_tdp_table **cac_tdp_table, - const PPTable_Generic_SubTable_Header * table - ) -{ - uint32_t table_size; - struct phm_cac_tdp_table *tdp_table; - - table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); - tdp_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == tdp_table) - return -ENOMEM; - - hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == hwmgr->dyn_state.cac_dtp_table) { - kfree(tdp_table); - return -ENOMEM; - } - - if (table->ucRevId < 3) { - const ATOM_Tonga_PowerTune_Table *tonga_table = - (ATOM_Tonga_PowerTune_Table *)table; - tdp_table->usTDP = le16_to_cpu(tonga_table->usTDP); - tdp_table->usConfigurableTDP = - le16_to_cpu(tonga_table->usConfigurableTDP); - tdp_table->usTDC = le16_to_cpu(tonga_table->usTDC); - tdp_table->usBatteryPowerLimit = - le16_to_cpu(tonga_table->usBatteryPowerLimit); - tdp_table->usSmallPowerLimit = - le16_to_cpu(tonga_table->usSmallPowerLimit); - tdp_table->usLowCACLeakage = - le16_to_cpu(tonga_table->usLowCACLeakage); - tdp_table->usHighCACLeakage = - le16_to_cpu(tonga_table->usHighCACLeakage); - tdp_table->usMaximumPowerDeliveryLimit = - le16_to_cpu(tonga_table->usMaximumPowerDeliveryLimit); - tdp_table->usDefaultTargetOperatingTemp = - le16_to_cpu(tonga_table->usTjMax); - tdp_table->usTargetOperatingTemp = - le16_to_cpu(tonga_table->usTjMax); /*Set the initial temp to the same as default */ - tdp_table->usPowerTuneDataSetID = - le16_to_cpu(tonga_table->usPowerTuneDataSetID); - tdp_table->usSoftwareShutdownTemp = - le16_to_cpu(tonga_table->usSoftwareShutdownTemp); - tdp_table->usClockStretchAmount = - le16_to_cpu(tonga_table->usClockStretchAmount); - } else { /* Fiji and newer */ - const ATOM_Fiji_PowerTune_Table *fijitable = - (ATOM_Fiji_PowerTune_Table *)table; - tdp_table->usTDP = le16_to_cpu(fijitable->usTDP); - tdp_table->usConfigurableTDP = le16_to_cpu(fijitable->usConfigurableTDP); - tdp_table->usTDC = le16_to_cpu(fijitable->usTDC); - tdp_table->usBatteryPowerLimit = le16_to_cpu(fijitable->usBatteryPowerLimit); - tdp_table->usSmallPowerLimit = le16_to_cpu(fijitable->usSmallPowerLimit); - tdp_table->usLowCACLeakage = le16_to_cpu(fijitable->usLowCACLeakage); - tdp_table->usHighCACLeakage = le16_to_cpu(fijitable->usHighCACLeakage); - tdp_table->usMaximumPowerDeliveryLimit = - le16_to_cpu(fijitable->usMaximumPowerDeliveryLimit); - tdp_table->usDefaultTargetOperatingTemp = - le16_to_cpu(fijitable->usTjMax); - tdp_table->usTargetOperatingTemp = - le16_to_cpu(fijitable->usTjMax); /*Set the initial temp to the same as default */ - tdp_table->usPowerTuneDataSetID = - le16_to_cpu(fijitable->usPowerTuneDataSetID); - tdp_table->usSoftwareShutdownTemp = - le16_to_cpu(fijitable->usSoftwareShutdownTemp); - tdp_table->usClockStretchAmount = - le16_to_cpu(fijitable->usClockStretchAmount); - tdp_table->usTemperatureLimitHotspot = - le16_to_cpu(fijitable->usTemperatureLimitHotspot); - tdp_table->usTemperatureLimitLiquid1 = - le16_to_cpu(fijitable->usTemperatureLimitLiquid1); - tdp_table->usTemperatureLimitLiquid2 = - le16_to_cpu(fijitable->usTemperatureLimitLiquid2); - tdp_table->usTemperatureLimitVrVddc = - le16_to_cpu(fijitable->usTemperatureLimitVrVddc); - tdp_table->usTemperatureLimitVrMvdd = - le16_to_cpu(fijitable->usTemperatureLimitVrMvdd); - tdp_table->usTemperatureLimitPlx = - le16_to_cpu(fijitable->usTemperatureLimitPlx); - tdp_table->ucLiquid1_I2C_address = - fijitable->ucLiquid1_I2C_address; - tdp_table->ucLiquid2_I2C_address = - fijitable->ucLiquid2_I2C_address; - tdp_table->ucLiquid_I2C_Line = - fijitable->ucLiquid_I2C_Line; - tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; - tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; - tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; - tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; - } - - *cac_tdp_table = tdp_table; - - return 0; -} - -static int get_mm_clock_voltage_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, - const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table - ) -{ - uint32_t table_size, i; - const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; - phm_ppt_v1_mm_clock_voltage_dependency_record *mm_table_record; - - PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) - * mm_dependency_table->ucNumEntries; - mm_table = kzalloc(table_size, GFP_KERNEL); - - if (NULL == mm_table) - return -ENOMEM; - - mm_table->count = mm_dependency_table->ucNumEntries; - - for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { - mm_dependency_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MM_Dependency_Record, - entries, mm_dependency_table, i); - mm_table_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - phm_ppt_v1_mm_clock_voltage_dependency_record, - entries, mm_table, i); - mm_table_record->vddcInd = mm_dependency_record->ucVddcInd; - mm_table_record->vddgfx_offset = le16_to_cpu(mm_dependency_record->usVddgfxOffset); - mm_table_record->aclk = le32_to_cpu(mm_dependency_record->ulAClk); - mm_table_record->samclock = le32_to_cpu(mm_dependency_record->ulSAMUClk); - mm_table_record->eclk = le32_to_cpu(mm_dependency_record->ulEClk); - mm_table_record->vclk = le32_to_cpu(mm_dependency_record->ulVClk); - mm_table_record->dclk = le32_to_cpu(mm_dependency_record->ulDClk); - } - - *tonga_mm_table = mm_table; - - return 0; -} - -static int get_gpio_table(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_gpio_table **pp_tonga_gpio_table, - const ATOM_Tonga_GPIO_Table *atom_gpio_table) -{ - uint32_t table_size; - struct phm_ppt_v1_gpio_table *pp_gpio_table; - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - table_size = sizeof(struct phm_ppt_v1_gpio_table); - pp_gpio_table = kzalloc(table_size, GFP_KERNEL); - if (!pp_gpio_table) - return -ENOMEM; - - if (pp_table_information->vdd_dep_on_sclk->count < - atom_gpio_table->ucVRHotTriggeredSclkDpmIndex) - PP_ASSERT_WITH_CODE(false, - "SCLK DPM index for VRHot cannot exceed the total sclk level count!",); - else - pp_gpio_table->vrhot_triggered_sclk_dpm_index = - atom_gpio_table->ucVRHotTriggeredSclkDpmIndex; - - *pp_tonga_gpio_table = pp_gpio_table; - - return 0; -} -/** - * Private Function used during initialization. - * Initialize clock voltage dependency - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - */ -static int init_clock_voltage_dependency( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - int result = 0; - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = - (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); - const PPTable_Generic_SubTable_Header *pPowerTuneTable = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); - const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = - (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); - const PPTable_Generic_SubTable_Header *sclk_dep_table = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); - const ATOM_Tonga_Hard_Limit_Table *pHardLimits = - (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usHardLimitTableOffset)); - const PPTable_Generic_SubTable_Header *pcie_table = - (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPCIETableOffset)); - const ATOM_Tonga_GPIO_Table *gpio_table = - (const ATOM_Tonga_GPIO_Table *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usGPIOTableOffset)); - - pp_table_information->vdd_dep_on_sclk = NULL; - pp_table_information->vdd_dep_on_mclk = NULL; - pp_table_information->mm_dep_table = NULL; - pp_table_information->pcie_table = NULL; - pp_table_information->gpio_table = NULL; - - if (powerplay_table->usMMDependencyTableOffset != 0) - result = get_mm_clock_voltage_table(hwmgr, - &pp_table_information->mm_dep_table, mm_dependency_table); - - if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) - result = get_cac_tdp_table(hwmgr, - &pp_table_information->cac_dtp_table, pPowerTuneTable); - - if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) - result = get_sclk_voltage_dependency_table(hwmgr, - &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); - - if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) - result = get_mclk_voltage_dependency_table(hwmgr, - &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); - - if (result == 0 && powerplay_table->usPCIETableOffset != 0) - result = get_pcie_table(hwmgr, - &pp_table_information->pcie_table, pcie_table); - - if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) - result = get_hard_limits(hwmgr, - &pp_table_information->max_clock_voltage_on_dc, pHardLimits); - - hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = - pp_table_information->max_clock_voltage_on_dc.sclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = - pp_table_information->max_clock_voltage_on_dc.mclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = - pp_table_information->max_clock_voltage_on_dc.vddc; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = - pp_table_information->max_clock_voltage_on_dc.vddci; - - if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) - && (0 != pp_table_information->vdd_dep_on_mclk->count)) - result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, - pp_table_information->vdd_dep_on_mclk); - - if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) - && (0 != pp_table_information->vdd_dep_on_sclk->count)) - result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, - pp_table_information->vdd_dep_on_sclk); - - if (!result && gpio_table) - result = get_gpio_table(hwmgr, &pp_table_information->gpio_table, - gpio_table); - - return result; -} - -/** Retrieves the (signed) Overdrive limits from VBIOS. - * The max engine clock, memory clock and max temperature come from the firmware info table. - * - * The information is placed into the platform descriptor. - * - * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. - * @param powerplay_table the address of the PowerPlay table. - * - * @return 1 as long as the firmware info table was present and of a supported version. - */ -static int init_over_drive_limits( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) -{ - hwmgr->platform_descriptor.overdriveLimit.engineClock = - le32_to_cpu(powerplay_table->ulMaxODEngineClock); - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - le32_to_cpu(powerplay_table->ulMaxODMemoryClock); - - hwmgr->platform_descriptor.minOverdriveVDDC = 0; - hwmgr->platform_descriptor.maxOverdriveVDDC = 0; - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - - return 0; -} - -/** - * Private Function used during initialization. - * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception This implementation always returns 1. - */ -static int init_thermal_controller( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - const PPTable_Generic_SubTable_Header *fan_table; - ATOM_Tonga_Thermal_Controller *thermal_controller; - - thermal_controller = (ATOM_Tonga_Thermal_Controller *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usThermalControllerOffset)); - PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), - "Thermal controller table not set!", return -1); - - hwmgr->thermal_controller.ucType = thermal_controller->ucType; - hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; - hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; - - hwmgr->thermal_controller.fanInfo.bNoFan = - (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - thermal_controller->ucFanParameters & - ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - - hwmgr->thermal_controller.fanInfo.ulMinRPM - = thermal_controller->ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM - = thermal_controller->ucFanMaxRPM * 100UL; - - set_hw_cap( - hwmgr, - ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController - ); - - if (0 == powerplay_table->usFanTableOffset) { - hwmgr->thermal_controller.use_hw_fan_control = 1; - return 0; - } - - fan_table = (const PPTable_Generic_SubTable_Header *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usFanTableOffset)); - - PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), - "Fan table not set!", return -1); - PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), - "Unsupported fan table format!", return -1); - - hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay - = 100000; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - if (fan_table->ucRevId < 8) { - const ATOM_Tonga_Fan_Table *tonga_fan_table = - (ATOM_Tonga_Fan_Table *)fan_table; - hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst - = tonga_fan_table->ucTHyst; - hwmgr->thermal_controller.advanceFanControlParameters.usTMin - = le16_to_cpu(tonga_fan_table->usTMin); - hwmgr->thermal_controller.advanceFanControlParameters.usTMed - = le16_to_cpu(tonga_fan_table->usTMed); - hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - = le16_to_cpu(tonga_fan_table->usTHigh); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin - = le16_to_cpu(tonga_fan_table->usPWMMin); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - = le16_to_cpu(tonga_fan_table->usPWMMed); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - = le16_to_cpu(tonga_fan_table->usPWMHigh); - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = 10900; /* hard coded */ - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = le16_to_cpu(tonga_fan_table->usTMax); - hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode - = tonga_fan_table->ucFanControlMode; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM - = le16_to_cpu(tonga_fan_table->usFanPWMMax); - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity - = 4836; - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity - = le16_to_cpu(tonga_fan_table->usFanOutputSensitivity); - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM - = le16_to_cpu(tonga_fan_table->usFanRPMMax); - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit - = (le32_to_cpu(tonga_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ - hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature - = tonga_fan_table->ucTargetTemperature; - hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit - = tonga_fan_table->ucMinimumPWMLimit; - } else { - const ATOM_Fiji_Fan_Table *fiji_fan_table = - (ATOM_Fiji_Fan_Table *)fan_table; - hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst - = fiji_fan_table->ucTHyst; - hwmgr->thermal_controller.advanceFanControlParameters.usTMin - = le16_to_cpu(fiji_fan_table->usTMin); - hwmgr->thermal_controller.advanceFanControlParameters.usTMed - = le16_to_cpu(fiji_fan_table->usTMed); - hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - = le16_to_cpu(fiji_fan_table->usTHigh); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin - = le16_to_cpu(fiji_fan_table->usPWMMin); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - = le16_to_cpu(fiji_fan_table->usPWMMed); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - = le16_to_cpu(fiji_fan_table->usPWMHigh); - hwmgr->thermal_controller.advanceFanControlParameters.usTMax - = le16_to_cpu(fiji_fan_table->usTMax); - hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode - = fiji_fan_table->ucFanControlMode; - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM - = le16_to_cpu(fiji_fan_table->usFanPWMMax); - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity - = 4836; - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity - = le16_to_cpu(fiji_fan_table->usFanOutputSensitivity); - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM - = le16_to_cpu(fiji_fan_table->usFanRPMMax); - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit - = (le32_to_cpu(fiji_fan_table->ulMinFanSCLKAcousticLimit) / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ - hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature - = fiji_fan_table->ucTargetTemperature; - hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit - = fiji_fan_table->ucMinimumPWMLimit; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge - = le16_to_cpu(fiji_fan_table->usFanGainEdge); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot - = le16_to_cpu(fiji_fan_table->usFanGainHotspot); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid - = le16_to_cpu(fiji_fan_table->usFanGainLiquid); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc - = le16_to_cpu(fiji_fan_table->usFanGainVrVddc); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd - = le16_to_cpu(fiji_fan_table->usFanGainVrMvdd); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx - = le16_to_cpu(fiji_fan_table->usFanGainPlx); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm - = le16_to_cpu(fiji_fan_table->usFanGainHbm); - } - - return 0; -} - -/** - * Private Function used during initialization. - * Inspect the PowerPlay table for obvious signs of corruption. - * @param hwmgr Pointer to the hardware manager. - * @param powerplay_table Pointer to the PowerPlay Table. - * @exception 2 if the powerplay table is incorrect. - */ -static int check_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table - ) -{ - const ATOM_Tonga_State_Array *state_arrays; - - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= - powerplay_table->sHeader.ucTableFormatRevision), - "Unsupported PPTable format!", return -1); - PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), - "State table is not set!", return -1); - PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), - "Invalid PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), - "Invalid PowerPlay Table!", return -1); - - return 0; -} - -static int pp_tables_v1_0_initialize(struct pp_hwmgr *hwmgr) -{ - int result = 0; - const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; - - hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); - - PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), - "Failed to allocate hwmgr->pptable!", return -ENOMEM); - - powerplay_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((NULL != powerplay_table), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_thermal_controller(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_thermal_controller failed", return result); - - result = init_over_drive_limits(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_over_drive_limits failed", return result); - - result = init_clock_voltage_dependency(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_clock_voltage_dependency failed", return result); - - result = init_dpm_2_parameters(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_dpm_2_parameters failed", return result); - - return result; -} - -static int pp_tables_v1_0_uninitialize(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *pp_table_information = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - kfree(pp_table_information->vdd_dep_on_sclk); - pp_table_information->vdd_dep_on_sclk = NULL; - - kfree(pp_table_information->vdd_dep_on_mclk); - pp_table_information->vdd_dep_on_mclk = NULL; - - kfree(pp_table_information->valid_mclk_values); - pp_table_information->valid_mclk_values = NULL; - - kfree(pp_table_information->valid_sclk_values); - pp_table_information->valid_sclk_values = NULL; - - kfree(pp_table_information->vddc_lookup_table); - pp_table_information->vddc_lookup_table = NULL; - - kfree(pp_table_information->vddgfx_lookup_table); - pp_table_information->vddgfx_lookup_table = NULL; - - kfree(pp_table_information->mm_dep_table); - pp_table_information->mm_dep_table = NULL; - - kfree(pp_table_information->cac_dtp_table); - pp_table_information->cac_dtp_table = NULL; - - kfree(hwmgr->dyn_state.cac_dtp_table); - hwmgr->dyn_state.cac_dtp_table = NULL; - - kfree(pp_table_information->ppm_parameter_table); - pp_table_information->ppm_parameter_table = NULL; - - kfree(pp_table_information->pcie_table); - pp_table_information->pcie_table = NULL; - - kfree(pp_table_information->gpio_table); - pp_table_information->gpio_table = NULL; - - kfree(hwmgr->pptable); - hwmgr->pptable = NULL; - - return 0; -} - -const struct pp_table_func pptable_v1_0_funcs = { - .pptable_init = pp_tables_v1_0_initialize, - .pptable_fini = pp_tables_v1_0_uninitialize, -}; - -int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr) -{ - ATOM_Tonga_State_Array const *state_arrays; - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((NULL != pp_table), - "Missing PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= - ATOM_Tonga_TABLE_REVISION_TONGA), - "Incorrect PowerPlay table revision!", return -1); - - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - return (uint32_t)(state_arrays->ucNumEntries); -} - -/** -* Private function to convert flags stored in the BIOS to software flags in PowerPlay. -*/ -static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, - uint16_t classification, uint16_t classification2) -{ - uint32_t result = 0; - - if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) - result |= PP_StateClassificationFlag_Boot; - - if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) - result |= PP_StateClassificationFlag_Thermal; - - if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - result |= PP_StateClassificationFlag_LimitedPowerSource; - - if (classification & ATOM_PPLIB_CLASSIFICATION_REST) - result |= PP_StateClassificationFlag_Rest; - - if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) - result |= PP_StateClassificationFlag_Forced; - - if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) - result |= PP_StateClassificationFlag_ACPI; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - result |= PP_StateClassificationFlag_LimitedPowerSource_2; - - return result; -} - -static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr) -{ - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - const ATOM_Tonga_VCE_State_Table *vce_state_table; - - - if (pp_table == NULL) - return 0; - - vce_state_table = (void *)pp_table + - le16_to_cpu(pp_table->usVCEStateTableOffset); - - return vce_state_table->ucNumEntries; -} - -static int ppt_get_vce_state_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t i, - struct amd_vce_state *vce_state, void **clock_info, uint32_t *flag) -{ - const ATOM_Tonga_VCE_State_Record *vce_state_record; - ATOM_Tonga_SCLK_Dependency_Record *sclk_dep_record; - ATOM_Tonga_MCLK_Dependency_Record *mclk_dep_record; - ATOM_Tonga_MM_Dependency_Record *mm_dep_record; - const ATOM_Tonga_POWERPLAYTABLE *pptable = get_powerplay_table(hwmgr); - const ATOM_Tonga_VCE_State_Table *vce_state_table = (ATOM_Tonga_VCE_State_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usVCEStateTableOffset)); - const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = (ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usSclkDependencyTableOffset)); - const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = (ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usMclkDependencyTableOffset)); - const ATOM_Tonga_MM_Dependency_Table *mm_dep_table = (ATOM_Tonga_MM_Dependency_Table *)(((unsigned long)pptable) - + le16_to_cpu(pptable->usMMDependencyTableOffset)); - - PP_ASSERT_WITH_CODE((i < vce_state_table->ucNumEntries), - "Requested state entry ID is out of range!", - return -EINVAL); - - vce_state_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_VCE_State_Record, - entries, vce_state_table, i); - sclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_SCLK_Dependency_Record, - entries, sclk_dep_table, - vce_state_record->ucSCLKIndex); - mm_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MM_Dependency_Record, - entries, mm_dep_table, - vce_state_record->ucVCEClockIndex); - *flag = vce_state_record->ucFlag; - - vce_state->evclk = le32_to_cpu(mm_dep_record->ulEClk); - vce_state->ecclk = le32_to_cpu(mm_dep_record->ulEClk); - vce_state->sclk = le32_to_cpu(sclk_dep_record->ulSclk); - - if (vce_state_record->ucMCLKIndex >= mclk_dep_table->ucNumEntries) - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, - mclk_dep_table->ucNumEntries - 1); - else - mclk_dep_record = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_MCLK_Dependency_Record, - entries, mclk_dep_table, - vce_state_record->ucMCLKIndex); - - vce_state->mclk = le32_to_cpu(mclk_dep_record->ulMclk); - return 0; -} - -/** -* Create a Power State out of an entry in the PowerPlay table. -* This function is called by the hardware back-end. -* @param hwmgr Pointer to the hardware manager. -* @param entry_index The index of the entry to be extracted from the table. -* @param power_state The address of the PowerState instance being created. -* @return -1 if the entry cannot be retrieved. -*/ -int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, - uint32_t entry_index, struct pp_power_state *power_state, - int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)) -{ - int result = 0; - const ATOM_Tonga_State_Array *state_arrays; - const ATOM_Tonga_State *state_entry; - const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - int i, j; - uint32_t flags = 0; - - PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); - power_state->classification.bios_index = entry_index; - - if (pp_table->sHeader.ucTableFormatRevision >= - ATOM_Tonga_TABLE_REVISION_TONGA) { - state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), - "Invalid PowerPlay Table State Array Offset.", return -1); - PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array.", return -1); - PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array Entry.", return -1); - - state_entry = GET_FLEXIBLE_ARRAY_MEMBER_ADDR( - ATOM_Tonga_State, entries, - state_arrays, entry_index); - - result = call_back_func(hwmgr, (void *)state_entry, power_state, - (void *)pp_table, - make_classification_flags(hwmgr, - le16_to_cpu(state_entry->usClassification), - le16_to_cpu(state_entry->usClassification2))); - } - - if (!result && (power_state->classification.flags & - PP_StateClassificationFlag_Boot)) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); - - hwmgr->num_vce_state_tables = i = ppt_get_num_of_vce_state_table_entries_v1_0(hwmgr); - - if ((i != 0) && (i <= AMD_MAX_VCE_LEVELS)) { - for (j = 0; j < i; j++) - ppt_get_vce_state_table_entry_v1_0(hwmgr, j, &(hwmgr->vce_states[j]), NULL, &flags); - } - - return result; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h deleted file mode 100644 index b9710abdff01..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 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 _PROCESSPPTABLES_V1_0_H -#define _PROCESSPPTABLES_V1_0_H - -#include "hwmgr.h" - -extern const struct pp_table_func pptable_v1_0_funcs; -extern int get_number_of_powerplay_table_entries_v1_0(struct pp_hwmgr *hwmgr); -extern int get_powerplay_table_entry_v1_0(struct pp_hwmgr *hwmgr, uint32_t entry_index, - struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c deleted file mode 100644 index 719597c5d27d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ /dev/null @@ -1,1732 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include -#include "processpptables.h" -#include -#include -#include "pptable.h" -#include "power_state.h" -#include "hwmgr.h" -#include "hardwaremanager.h" - - -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 -#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 - -#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 - -static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t vce_table_offset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *extended_header = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(extended_header->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) - vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset); - } - } - - return vce_table_offset; -} - -static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) - return table_offset + 1; - - return 0; -} - -static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, - powerplay_table); - uint16_t table_size = 0; - - if (table_offset > 0) { - const VCEClockInfoArray *p = (const VCEClockInfoArray *) - (((unsigned long) powerplay_table) + table_offset); - table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo); - } - - return table_size; -} - -static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) - return table_offset + get_vce_clock_info_array_size(hwmgr, - powerplay_table); - - return 0; -} - -static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); - uint16_t table_size = 0; - - if (table_offset > 0) { - const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable = - (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset); - - table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record); - } - return table_size; -} - -static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); - - if (table_offset > 0) - return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table); - - return 0; -} - -static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table); - - if (table_offset > 0) - return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset); - - return NULL; -} - -static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t uvd_table_offset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *extended_header = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(extended_header->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) - uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset); - } - } - return uvd_table_offset; -} - -static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_uvd_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) - return table_offset + 1; - return 0; -} - -static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, - powerplay_table); - uint16_t table_size = 0; - - if (table_offset > 0) { - const UVDClockInfoArray *p = (const UVDClockInfoArray *) - (((unsigned long) powerplay_table) - + table_offset); - table_size = sizeof(UCHAR) + - p->ucNumEntries * sizeof(UVDClockInfo); - } - - return table_size; -} - -static uint16_t get_uvd_clock_voltage_limit_table_offset( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) - return table_offset + - get_uvd_clock_info_array_size(hwmgr, powerplay_table); - - return 0; -} - -static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t samu_table_offset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *extended_header = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(extended_header->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) - samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset); - } - } - - return samu_table_offset; -} - -static uint16_t get_samu_clock_voltage_limit_table_offset( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t table_offset = get_samu_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) - return table_offset + 1; - - return 0; -} - -static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t acp_table_offset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(pExtendedHeader->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) - acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset); - } - } - - return acp_table_offset; -} - -static uint16_t get_acp_clock_voltage_limit_table_offset( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table); - - if (tableOffset > 0) - return tableOffset + 1; - - return 0; -} - -static uint16_t get_cacp_tdp_table_offset( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t cacTdpTableOffset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(pExtendedHeader->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) - cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset); - } - } - - return cacTdpTableOffset; -} - -static int get_cac_tdp_table(struct pp_hwmgr *hwmgr, - struct phm_cac_tdp_table **ptable, - const ATOM_PowerTune_Table *table, - uint16_t us_maximum_power_delivery_limit) -{ - unsigned long table_size; - struct phm_cac_tdp_table *tdp_table; - - table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table); - - tdp_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == tdp_table) - return -ENOMEM; - - tdp_table->usTDP = le16_to_cpu(table->usTDP); - tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP); - tdp_table->usTDC = le16_to_cpu(table->usTDC); - tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit); - tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit); - tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage); - tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage); - tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit; - - *ptable = tdp_table; - - return 0; -} - -static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t sclk_vdd_gfx_table_offset = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - if (powerplay_table3->usExtendendedHeaderOffset > 0) { - const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = - (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table3) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - if (le16_to_cpu(pExtendedHeader->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) - sclk_vdd_gfx_table_offset = - le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset); - } - } - - return sclk_vdd_gfx_table_offset; -} - -static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table); - - if (tableOffset > 0) - return tableOffset; - - return 0; -} - - -static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table **ptable, - const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) -{ - - unsigned long table_size, i; - struct phm_clock_voltage_dependency_table *dep_table; - - table_size = sizeof(unsigned long) + - sizeof(struct phm_clock_voltage_dependency_table) - * table->ucNumEntries; - - dep_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == dep_table) - return -ENOMEM; - - dep_table->count = (unsigned long)table->ucNumEntries; - - for (i = 0; i < dep_table->count; i++) { - dep_table->entries[i].clk = - ((unsigned long)table->entries[i].ucClockHigh << 16) | - le16_to_cpu(table->entries[i].usClockLow); - dep_table->entries[i].v = - (unsigned long)le16_to_cpu(table->entries[i].usVoltage); - } - - *ptable = dep_table; - - return 0; -} - -static int get_valid_clk(struct pp_hwmgr *hwmgr, - struct phm_clock_array **ptable, - const struct phm_clock_voltage_dependency_table *table) -{ - unsigned long table_size, i; - struct phm_clock_array *clock_table; - - table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count; - clock_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == clock_table) - return -ENOMEM; - - clock_table->count = (unsigned long)table->count; - - for (i = 0; i < clock_table->count; i++) - clock_table->values[i] = (unsigned long)table->entries[i].clk; - - *ptable = clock_table; - - return 0; -} - -static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *limits, - const ATOM_PPLIB_Clock_Voltage_Limit_Table *table) -{ - limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) | - le16_to_cpu(table->entries[0].usSclkLow); - limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) | - le16_to_cpu(table->entries[0].usMclkLow); - limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc); - limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci); - - return 0; -} - - -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, - enum phm_platform_caps cap) -{ - if (enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - -static int set_platform_caps(struct pp_hwmgr *hwmgr, - unsigned long powerplay_caps) -{ - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s), - PHM_PlatformCaps_EnableASPML0s - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1), - PHM_PlatformCaps_EnableASPML1 - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS), - PHM_PlatformCaps_EnableBackbias - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC), - PHM_PlatformCaps_AutomaticDCTransition - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY), - PHM_PlatformCaps_GeminiPrimary - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC), - PHM_PlatformCaps_StepVddc - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL), - PHM_PlatformCaps_EnableVoltageControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL), - PHM_PlatformCaps_EnableSideportControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1), - PHM_PlatformCaps_TurnOffPll_ASPML1 - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL), - PHM_PlatformCaps_EnableHTLinkControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL), - PHM_PlatformCaps_EnableMVDDControl - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL), - PHM_PlatformCaps_ControlVDDCI - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT), - PHM_PlatformCaps_RegulatorHot - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT), - PHM_PlatformCaps_BootStateOnAlert - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT), - PHM_PlatformCaps_DontWaitForVBlankOnAlert - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE), - PHM_PlatformCaps_NewCACVoltage - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY), - PHM_PlatformCaps_RevertGPIO5Polarity - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17), - PHM_PlatformCaps_Thermal2GPIO17 - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE), - PHM_PlatformCaps_VRHotGPIOConfigurable - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION), - PHM_PlatformCaps_TempInversion - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV), - PHM_PlatformCaps_EVV - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), - PHM_PlatformCaps_CombinePCCWithThermalSignal - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), - PHM_PlatformCaps_LoadPostProductionFirmware - ); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC), - PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc - ); - - return 0; -} - -static PP_StateClassificationFlags make_classification_flags( - struct pp_hwmgr *hwmgr, - USHORT classification, - USHORT classification2) -{ - PP_StateClassificationFlags result = 0; - - if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) - result |= PP_StateClassificationFlag_Boot; - - if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) - result |= PP_StateClassificationFlag_Thermal; - - if (classification & - ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - result |= PP_StateClassificationFlag_LimitedPowerSource; - - if (classification & ATOM_PPLIB_CLASSIFICATION_REST) - result |= PP_StateClassificationFlag_Rest; - - if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) - result |= PP_StateClassificationFlag_Forced; - - if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) - result |= PP_StateClassificationFlag_3DPerformance; - - - if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) - result |= PP_StateClassificationFlag_ACOverdriveTemplate; - - if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) - result |= PP_StateClassificationFlag_Uvd; - - if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE) - result |= PP_StateClassificationFlag_UvdHD; - - if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE) - result |= PP_StateClassificationFlag_UvdSD; - - if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE) - result |= PP_StateClassificationFlag_HD2; - - if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) - result |= PP_StateClassificationFlag_ACPI; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - result |= PP_StateClassificationFlag_LimitedPowerSource_2; - - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV) - result |= PP_StateClassificationFlag_ULV; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) - result |= PP_StateClassificationFlag_UvdMVC; - - return result; -} - -static int init_non_clock_fields(struct pp_hwmgr *hwmgr, - struct pp_power_state *ps, - uint8_t version, - const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) { - unsigned long rrr_index; - unsigned long tmp; - - ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) & - ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; - ps->classification.flags = make_classification_flags(hwmgr, - le16_to_cpu(pnon_clock_info->usClassification), - le16_to_cpu(pnon_clock_info->usClassification2)); - - ps->classification.temporary_state = false; - ps->classification.to_be_deleted = false; - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_SINGLE_DISPLAY_ONLY; - - ps->validation.singleDisplayOnly = (0 != tmp); - - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_DISALLOW_ON_DC; - - ps->validation.disallowOnDC = (0 != tmp); - - ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> - ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; - - ps->pcie.lanes = 0; - - ps->display.disableFrameModulation = false; - - rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >> - ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT; - - if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) { - static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \ - { 0, 50, 0 }; - - ps->display.refreshrateSource = PP_RefreshrateSource_Explicit; - ps->display.explicitRefreshrate = look_up[rrr_index]; - ps->display.limitRefreshrate = true; - - if (ps->display.explicitRefreshrate == 0) - ps->display.limitRefreshrate = false; - } else - ps->display.limitRefreshrate = false; - - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_ENABLE_VARIBRIGHT; - - ps->display.enableVariBright = (0 != tmp); - - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF; - - ps->memory.dllOff = (0 != tmp); - - ps->memory.m3arb = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; - - ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * - pnon_clock_info->ucMinTemperature; - - ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * - pnon_clock_info->ucMaxTemperature; - - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING; - - ps->software.disableLoadBalancing = tmp; - - tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & - ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS; - - ps->software.enableSleepForTimestamps = (0 != tmp); - - ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower; - - if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) { - ps->uvd_clocks.VCLK = le32_to_cpu(pnon_clock_info->ulVCLK); - ps->uvd_clocks.DCLK = le32_to_cpu(pnon_clock_info->ulDCLK); - } else { - ps->uvd_clocks.VCLK = 0; - ps->uvd_clocks.DCLK = 0; - } - - return 0; -} - -static ULONG size_of_entry_v2(ULONG num_dpm_levels) -{ - return (sizeof(UCHAR) + sizeof(UCHAR) + - (num_dpm_levels * sizeof(UCHAR))); -} - -static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( - const StateArray * pstate_arrays, - ULONG entry_index) -{ - ULONG i; - const ATOM_PPLIB_STATE_V2 *pstate; - - pstate = pstate_arrays->states; - if (entry_index <= pstate_arrays->ucNumEntries) { - for (i = 0; i < entry_index; i++) - pstate = (ATOM_PPLIB_STATE_V2 *)( - (unsigned long)pstate + - size_of_entry_v2(pstate->ucNumDPMLevels)); - } - return pstate; -} - -static const unsigned char soft_dummy_pp_table[] = { - 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x18, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe1, 0x00, 0x43, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x8e, 0x01, 0x00, 0x00, 0xb8, 0x01, 0x00, 0x00, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, - 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x70, 0x00, 0x91, 0xf4, 0x00, - 0x64, 0x00, 0x40, 0x19, 0x01, 0x5a, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, - 0x00, 0x00, 0x09, 0x30, 0x75, 0x00, 0x30, 0x75, 0x00, 0x40, 0x9c, 0x00, 0x40, 0x9c, 0x00, 0x59, - 0xd8, 0x00, 0x59, 0xd8, 0x00, 0x91, 0xf4, 0x00, 0x91, 0xf4, 0x00, 0x0e, 0x28, 0x01, 0x0e, 0x28, - 0x01, 0x90, 0x5f, 0x01, 0x90, 0x5f, 0x01, 0x00, 0x77, 0x01, 0x00, 0x77, 0x01, 0xca, 0x91, 0x01, - 0xca, 0x91, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, - 0x7c, 0x00, 0x02, 0x70, 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, - 0x00, 0x07, 0x08, 0x08, 0x00, 0x08, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x04, 0x02, 0x00, 0x08, 0x40, 0x9c, 0x00, 0x30, 0x75, 0x00, 0x74, 0xb5, 0x00, 0xa0, 0x8c, - 0x00, 0x60, 0xea, 0x00, 0x74, 0xb5, 0x00, 0x0e, 0x28, 0x01, 0x60, 0xea, 0x00, 0x90, 0x5f, 0x01, - 0x40, 0x19, 0x01, 0xb2, 0xb0, 0x01, 0x90, 0x5f, 0x01, 0xc0, 0xd4, 0x01, 0x00, 0x77, 0x01, 0x5e, - 0xff, 0x01, 0xca, 0x91, 0x01, 0x08, 0x80, 0x00, 0x00, 0x7e, 0x00, 0x01, 0x7c, 0x00, 0x02, 0x70, - 0x00, 0x03, 0x64, 0x00, 0x04, 0x5a, 0x00, 0x05, 0x52, 0x00, 0x06, 0x4a, 0x00, 0x07, 0x00, 0x08, - 0x80, 0x00, 0x30, 0x75, 0x00, 0x7e, 0x00, 0x40, 0x9c, 0x00, 0x7c, 0x00, 0x59, 0xd8, 0x00, 0x70, - 0x00, 0xdc, 0x0b, 0x01, 0x64, 0x00, 0x80, 0x38, 0x01, 0x5a, 0x00, 0x80, 0x38, 0x01, 0x52, 0x00, - 0x80, 0x38, 0x01, 0x4a, 0x00, 0x80, 0x38, 0x01, 0x08, 0x30, 0x75, 0x00, 0x80, 0x00, 0xa0, 0x8c, - 0x00, 0x7e, 0x00, 0x71, 0xa5, 0x00, 0x7c, 0x00, 0xe5, 0xc8, 0x00, 0x74, 0x00, 0x91, 0xf4, 0x00, - 0x66, 0x00, 0x40, 0x19, 0x01, 0x58, 0x00, 0x0e, 0x28, 0x01, 0x52, 0x00, 0x80, 0x38, 0x01, 0x4a, - 0x00 -}; - -static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( - struct pp_hwmgr *hwmgr) -{ - const void *table_addr = hwmgr->soft_pp_table; - uint8_t frev, crev; - uint16_t size; - - if (!table_addr) { - if (hwmgr->chip_id == CHIP_RAVEN) { - table_addr = &soft_dummy_pp_table[0]; - hwmgr->soft_pp_table = &soft_dummy_pp_table[0]; - hwmgr->soft_pp_table_size = sizeof(soft_dummy_pp_table); - } else { - table_addr = smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, PowerPlayInfo), - &size, &frev, &crev); - hwmgr->soft_pp_table = table_addr; - hwmgr->soft_pp_table_size = size; - } - } - - return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; -} - -int pp_tables_get_response_times(struct pp_hwmgr *hwmgr, - uint32_t *vol_rep_time, uint32_t *bb_rep_time) -{ - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_tab = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE(NULL != powerplay_tab, - "Missing PowerPlay Table!", return -EINVAL); - - *vol_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usVoltageTime); - *bb_rep_time = (uint32_t)le16_to_cpu(powerplay_tab->usBackbiasTime); - - return 0; -} - -int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, - unsigned long *num_of_entries) -{ - const StateArray *pstate_arrays; - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); - - if (powerplay_table == NULL) - return -1; - - if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { - pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usStateArrayOffset)); - - *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries); - } else - *num_of_entries = (unsigned long)(powerplay_table->ucNumStates); - - return 0; -} - -int pp_tables_get_entry(struct pp_hwmgr *hwmgr, - unsigned long entry_index, - struct pp_power_state *ps, - pp_tables_hw_clock_info_callback func) -{ - int i; - const StateArray *pstate_arrays; - const ATOM_PPLIB_STATE_V2 *pstate_entry_v2; - const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info; - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); - int result = 0; - int res = 0; - - const ClockInfoArray *pclock_arrays; - - const NonClockInfoArray *pnon_clock_arrays; - - const ATOM_PPLIB_STATE *pstate_entry; - - if (powerplay_table == NULL) - return -1; - - ps->classification.bios_index = entry_index; - - if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { - pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usStateArrayOffset)); - - if (entry_index > pstate_arrays->ucNumEntries) - return -1; - - pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index); - pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); - - pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset)); - - pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) + - (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize)); - - result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info); - - for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) { - const void *pclock_info = (const void *)( - (unsigned long)(pclock_arrays->clockInfo) + - (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize)); - res = func(hwmgr, &ps->hardware, i, pclock_info); - if ((0 == result) && (0 != res)) - result = res; - } - } else { - if (entry_index > powerplay_table->ucNumStates) - return -1; - - pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + - le16_to_cpu(powerplay_table->usStateArrayOffset) + - entry_index * powerplay_table->ucStateEntrySize); - - pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table + - le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) + - pstate_entry->ucNonClockStateIndex * - powerplay_table->ucNonClockSize); - - result = init_non_clock_fields(hwmgr, ps, - powerplay_table->ucNonClockSize, - pnon_clock_info); - - for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) { - const void *pclock_info = (const void *)((unsigned long)powerplay_table + - le16_to_cpu(powerplay_table->usClockInfoArrayOffset) + - pstate_entry->ucClockStateIndices[i] * - powerplay_table->ucClockInfoSize); - - int res = func(hwmgr, &ps->hardware, i, pclock_info); - - if ((0 == result) && (0 != res)) - result = res; - } - } - - if ((0 == result) && (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) { - if (hwmgr->chip_family < AMDGPU_FAMILY_RV) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); - } - - return result; -} - -static int init_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table -) -{ - return 0; -} - - -static int init_thermal_controller( - struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - hwmgr->thermal_controller.ucType = - powerplay_table->sThermalController.ucType; - hwmgr->thermal_controller.ucI2cLine = - powerplay_table->sThermalController.ucI2cLine; - hwmgr->thermal_controller.ucI2cAddress = - powerplay_table->sThermalController.ucI2cAddress; - - hwmgr->thermal_controller.fanInfo.bNoFan = - (0 != (powerplay_table->sThermalController.ucFanParameters & - ATOM_PP_FANPARAMETERS_NOFAN)); - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - powerplay_table->sThermalController.ucFanParameters & - ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - - hwmgr->thermal_controller.fanInfo.ulMinRPM - = powerplay_table->sThermalController.ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM - = powerplay_table->sThermalController.ucFanMaxRPM * 100UL; - - set_hw_cap(hwmgr, - ATOM_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController); - - hwmgr->thermal_controller.use_hw_fan_control = 1; - - return 0; -} - -static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, - const ATOM_FIRMWARE_INFO_V1_4 *fw_info) -{ - hwmgr->platform_descriptor.overdriveLimit.engineClock = - le32_to_cpu(fw_info->ulASICMaxEngineClock); - - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - le32_to_cpu(fw_info->ulASICMaxMemoryClock); - - hwmgr->platform_descriptor.maxOverdriveVDDC = - le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF; - - hwmgr->platform_descriptor.minOverdriveVDDC = - le16_to_cpu(fw_info->usBootUpVDDCVoltage); - - hwmgr->platform_descriptor.maxOverdriveVDDC = - le16_to_cpu(fw_info->usBootUpVDDCVoltage); - - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - return 0; -} - -static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, - const ATOM_FIRMWARE_INFO_V2_1 *fw_info) -{ - const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3; - const ATOM_PPLIB_EXTENDEDHEADER *header; - - if (le16_to_cpu(powerplay_table->usTableSize) < - sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) - return 0; - - powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; - - if (0 == powerplay_table3->usExtendendedHeaderOffset) - return 0; - - header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); - - hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock); - hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock); - - - hwmgr->platform_descriptor.minOverdriveVDDC = 0; - hwmgr->platform_descriptor.maxOverdriveVDDC = 0; - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - - return 0; -} - -static int init_overdrive_limits(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - int result = 0; - uint8_t frev, crev; - uint16_t size; - - const ATOM_COMMON_TABLE_HEADER *fw_info = NULL; - - hwmgr->platform_descriptor.overdriveLimit.engineClock = 0; - hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0; - hwmgr->platform_descriptor.minOverdriveVDDC = 0; - hwmgr->platform_descriptor.maxOverdriveVDDC = 0; - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - - if (hwmgr->chip_id == CHIP_RAVEN) - return 0; - - /* We assume here that fw_info is unchanged if this call fails.*/ - fw_info = smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, FirmwareInfo), - &size, &frev, &crev); - - if ((fw_info->ucTableFormatRevision == 1) - && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) - result = init_overdrive_limits_V1_4(hwmgr, - powerplay_table, - (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info); - - else if ((fw_info->ucTableFormatRevision == 2) - && (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) - result = init_overdrive_limits_V2_1(hwmgr, - powerplay_table, - (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info); - - return result; -} - -static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, - struct phm_uvd_clock_voltage_dependency_table **ptable, - const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, - const UVDClockInfoArray *array) -{ - unsigned long table_size, i; - struct phm_uvd_clock_voltage_dependency_table *uvd_table; - - table_size = sizeof(unsigned long) + - sizeof(struct phm_uvd_clock_voltage_dependency_table) * - table->numEntries; - - uvd_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == uvd_table) - return -ENOMEM; - - uvd_table->count = table->numEntries; - - for (i = 0; i < table->numEntries; i++) { - const UVDClockInfo *entry = - &array->entries[table->entries[i].ucUVDClockInfoIndex]; - uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); - uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16) - | le16_to_cpu(entry->usVClkLow); - uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16) - | le16_to_cpu(entry->usDClkLow); - } - - *ptable = uvd_table; - - return 0; -} - -static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, - struct phm_vce_clock_voltage_dependency_table **ptable, - const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, - const VCEClockInfoArray *array) -{ - unsigned long table_size, i; - struct phm_vce_clock_voltage_dependency_table *vce_table = NULL; - - table_size = sizeof(unsigned long) + - sizeof(struct phm_vce_clock_voltage_dependency_table) - * table->numEntries; - - vce_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == vce_table) - return -ENOMEM; - - vce_table->count = table->numEntries; - for (i = 0; i < table->numEntries; i++) { - const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex]; - - vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); - vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16) - | le16_to_cpu(entry->usEVClkLow); - vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16) - | le16_to_cpu(entry->usECClkLow); - } - - *ptable = vce_table; - - return 0; -} - -static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, - struct phm_samu_clock_voltage_dependency_table **ptable, - const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) -{ - unsigned long table_size, i; - struct phm_samu_clock_voltage_dependency_table *samu_table; - - table_size = sizeof(unsigned long) + - sizeof(struct phm_samu_clock_voltage_dependency_table) * - table->numEntries; - - samu_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == samu_table) - return -ENOMEM; - - samu_table->count = table->numEntries; - - for (i = 0; i < table->numEntries; i++) { - samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); - samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16) - | le16_to_cpu(table->entries[i].usSAMClockLow); - } - - *ptable = samu_table; - - return 0; -} - -static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, - struct phm_acp_clock_voltage_dependency_table **ptable, - const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) -{ - unsigned table_size, i; - struct phm_acp_clock_voltage_dependency_table *acp_table; - - table_size = sizeof(unsigned long) + - sizeof(struct phm_acp_clock_voltage_dependency_table) * - table->numEntries; - - acp_table = kzalloc(table_size, GFP_KERNEL); - if (NULL == acp_table) - return -ENOMEM; - - acp_table->count = (unsigned long)table->numEntries; - - for (i = 0; i < table->numEntries; i++) { - acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); - acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16) - | le16_to_cpu(table->entries[i].usACPClockLow); - } - - *ptable = acp_table; - - return 0; -} - -static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - ATOM_PPLIB_Clock_Voltage_Dependency_Table *table; - ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table; - int result = 0; - - uint16_t vce_clock_info_array_offset; - uint16_t uvd_clock_info_array_offset; - uint16_t table_offset; - - hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; - hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; - hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; - hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; - hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; - hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; - hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; - hwmgr->dyn_state.ppm_parameter_table = NULL; - hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; - - vce_clock_info_array_offset = get_vce_clock_info_array_offset( - hwmgr, powerplay_table); - table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, - powerplay_table); - if (vce_clock_info_array_offset > 0 && table_offset > 0) { - const VCEClockInfoArray *array = (const VCEClockInfoArray *) - (((unsigned long) powerplay_table) + - vce_clock_info_array_offset); - const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = - (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_vce_clock_voltage_limit_table(hwmgr, - &hwmgr->dyn_state.vce_clock_voltage_dependency_table, - table, array); - } - - uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); - table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); - - if (uvd_clock_info_array_offset > 0 && table_offset > 0) { - const UVDClockInfoArray *array = (const UVDClockInfoArray *) - (((unsigned long) powerplay_table) + - uvd_clock_info_array_offset); - const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = - (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_uvd_clock_voltage_limit_table(hwmgr, - &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array); - } - - table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) { - const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = - (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_samu_clock_voltage_limit_table(hwmgr, - &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); - } - - table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) { - const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = - (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_acp_clock_voltage_limit_table(hwmgr, - &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); - } - - table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); - if (table_offset > 0) { - UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); - - if (rev_id > 0) { - const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = - (const ATOM_PPLIB_POWERTUNE_Table_V1 *) - (((unsigned long) powerplay_table) + table_offset); - result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, - &tune_table->power_tune_table, - le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); - hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = - le16_to_cpu(tune_table->usTjMax); - } else { - const ATOM_PPLIB_POWERTUNE_Table *tune_table = - (const ATOM_PPLIB_POWERTUNE_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_cac_tdp_table(hwmgr, - &hwmgr->dyn_state.cac_dtp_table, - &tune_table->power_tune_table, 255); - } - } - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { - const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = - (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; - if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { - table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (((unsigned long) powerplay_table4) + - le16_to_cpu(powerplay_table4->usVddcDependencyOnSCLKOffset)); - result = get_clock_voltage_dependency_table(hwmgr, - &hwmgr->dyn_state.vddc_dependency_on_sclk, table); - } - - if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { - table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (((unsigned long) powerplay_table4) + - le16_to_cpu(powerplay_table4->usVddciDependencyOnMCLKOffset)); - result = get_clock_voltage_dependency_table(hwmgr, - &hwmgr->dyn_state.vddci_dependency_on_mclk, table); - } - - if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { - table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (((unsigned long) powerplay_table4) + - le16_to_cpu(powerplay_table4->usVddcDependencyOnMCLKOffset)); - result = get_clock_voltage_dependency_table(hwmgr, - &hwmgr->dyn_state.vddc_dependency_on_mclk, table); - } - - if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { - limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) - (((unsigned long) powerplay_table4) + - le16_to_cpu(powerplay_table4->usMaxClockVoltageOnDCOffset)); - result = get_clock_voltage_limit(hwmgr, - &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); - } - - if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && - (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) - result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, - hwmgr->dyn_state.vddc_dependency_on_mclk); - - if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && - (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) - result = get_valid_clk(hwmgr, - &hwmgr->dyn_state.valid_sclk_values, - hwmgr->dyn_state.vddc_dependency_on_sclk); - - if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { - table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (((unsigned long) powerplay_table4) + - le16_to_cpu(powerplay_table4->usMvddDependencyOnMCLKOffset)); - result = get_clock_voltage_dependency_table(hwmgr, - &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); - } - } - - table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, - powerplay_table); - - if (table_offset > 0) { - table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) - (((unsigned long) powerplay_table) + table_offset); - result = get_clock_voltage_dependency_table(hwmgr, - &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); - } - - return result; -} - -static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, - struct phm_cac_leakage_table **ptable, - const ATOM_PPLIB_CAC_Leakage_Table *table) -{ - struct phm_cac_leakage_table *cac_leakage_table; - unsigned long table_size, i; - - if (hwmgr == NULL || table == NULL || ptable == NULL) - return -EINVAL; - - table_size = sizeof(ULONG) + - (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); - - cac_leakage_table = kzalloc(table_size, GFP_KERNEL); - - if (cac_leakage_table == NULL) - return -ENOMEM; - - cac_leakage_table->count = (ULONG)table->ucNumEntries; - - for (i = 0; i < cac_leakage_table->count; i++) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV)) { - cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); - cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); - cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); - } else { - cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); - cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); - } - } - - *ptable = cac_leakage_table; - - return 0; -} - -static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, - ATOM_PPLIB_PPM_Table *atom_ppm_table) -{ - struct phm_ppm_table *ptr = kzalloc(sizeof(struct phm_ppm_table), GFP_KERNEL); - - if (NULL == ptr) - return -ENOMEM; - - ptr->ppm_design = atom_ppm_table->ucPpmDesign; - ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); - ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); - ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); - ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); - ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); - ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); - ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); - ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); - ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); - hwmgr->dyn_state.ppm_parameter_table = ptr; - - return 0; -} - -static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - int result = 0; - - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { - const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = - (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; - const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = - (const ATOM_PPLIB_POWERPLAYTABLE4 *) - (&ptable5->basicTable4); - const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = - (const ATOM_PPLIB_POWERPLAYTABLE3 *) - (&ptable4->basicTable3); - const ATOM_PPLIB_EXTENDEDHEADER *extended_header; - uint16_t table_offset; - ATOM_PPLIB_PPM_Table *atom_ppm_table; - - hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); - hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); - - hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); - hwmgr->platform_descriptor.TDPAdjustment = 0; - - hwmgr->platform_descriptor.VidAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; - hwmgr->platform_descriptor.VidMinLimit = 0; - hwmgr->platform_descriptor.VidMaxLimit = 1500000; - hwmgr->platform_descriptor.VidStep = 6250; - - hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); - - if (hwmgr->platform_descriptor.TDPODLimit != 0) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); - - hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); - - hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); - - hwmgr->dyn_state.cac_leakage_table = NULL; - - if (0 != ptable5->usCACLeakageTableOffset) { - const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = - (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + - le16_to_cpu(ptable5->usCACLeakageTableOffset)); - result = get_cac_leakage_table(hwmgr, - &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); - } - - hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); - - hwmgr->dyn_state.ppm_parameter_table = NULL; - - if (0 != ptable3->usExtendendedHeaderOffset) { - extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) - (((unsigned long)powerplay_table) + - le16_to_cpu(ptable3->usExtendendedHeaderOffset)); - if ((extended_header->usPPMTableOffset > 0) && - le16_to_cpu(extended_header->usSize) >= - SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { - table_offset = le16_to_cpu(extended_header->usPPMTableOffset); - atom_ppm_table = (ATOM_PPLIB_PPM_Table *) - (((unsigned long)powerplay_table) + table_offset); - if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnablePlatformPowerManagement); - } - } - } - return result; -} - -static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) -{ - if (le16_to_cpu(powerplay_table->usTableSize) >= - sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { - const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = - (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; - - if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { - const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = - (ATOM_PPLIB_PhaseSheddingLimits_Table *) - (((unsigned long)powerplay_table4) + - le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); - struct phm_phase_shedding_limits_table *table; - unsigned long size, i; - - - size = sizeof(unsigned long) + - (sizeof(struct phm_phase_shedding_limits_table) * - ptable->ucNumEntries); - - table = kzalloc(size, GFP_KERNEL); - - if (table == NULL) - return -ENOMEM; - - table->count = (unsigned long)ptable->ucNumEntries; - - for (i = 0; i < table->count; i++) { - table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); - table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) - | le16_to_cpu(ptable->entries[i].usSclkLow); - table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) - | le16_to_cpu(ptable->entries[i].usMclkLow); - } - hwmgr->dyn_state.vddc_phase_shed_limits_table = table; - } - } - - return 0; -} - -static int get_number_of_vce_state_table_entries( - struct pp_hwmgr *hwmgr) -{ - const ATOM_PPLIB_POWERPLAYTABLE *table = - get_powerplay_table(hwmgr); - const ATOM_PPLIB_VCE_State_Table *vce_table = - get_vce_state_table(hwmgr, table); - - if (vce_table) - return vce_table->numEntries; - - return 0; -} - -static int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, - unsigned long i, - struct amd_vce_state *vce_state, - void **clock_info, - unsigned long *flag) -{ - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); - - const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); - - unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); - - const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); - - const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); - - const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; - - const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; - - unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; - - *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); - - vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | le16_to_cpu(vce_clock_info->usEVClkLow); - vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | le16_to_cpu(vce_clock_info->usECClkLow); - - *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); - - return 0; -} - - -static int pp_tables_initialize(struct pp_hwmgr *hwmgr) -{ - int result; - const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; - - if (hwmgr->chip_id == CHIP_RAVEN) - return 0; - - hwmgr->need_pp_table_upload = true; - - powerplay_table = get_powerplay_table(hwmgr); - - result = init_powerplay_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_thermal_controller(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_thermal_controller failed", return result); - - result = init_overdrive_limits(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_overdrive_limits failed", return result); - - result = init_clock_voltage_dependency(hwmgr, - powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_clock_voltage_dependency failed", return result); - - result = init_dpm2_parameters(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_dpm2_parameters failed", return result); - - result = init_phase_shedding_table(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_phase_shedding_table failed", return result); - - return result; -} - -static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->chip_id == CHIP_RAVEN) - return 0; - - kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); - hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; - - kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); - hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; - - kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); - hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; - - kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); - hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; - - kfree(hwmgr->dyn_state.valid_mclk_values); - hwmgr->dyn_state.valid_mclk_values = NULL; - - kfree(hwmgr->dyn_state.valid_sclk_values); - hwmgr->dyn_state.valid_sclk_values = NULL; - - kfree(hwmgr->dyn_state.cac_leakage_table); - hwmgr->dyn_state.cac_leakage_table = NULL; - - kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); - hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; - - kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); - hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; - - kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); - hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; - - kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); - hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; - - kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); - hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; - - kfree(hwmgr->dyn_state.cac_dtp_table); - hwmgr->dyn_state.cac_dtp_table = NULL; - - kfree(hwmgr->dyn_state.ppm_parameter_table); - hwmgr->dyn_state.ppm_parameter_table = NULL; - - kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); - hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; - - return 0; -} - -const struct pp_table_func pptable_funcs = { - .pptable_init = pp_tables_initialize, - .pptable_fini = pp_tables_uninitialize, - .pptable_get_number_of_vce_state_table_entries = - get_number_of_vce_state_table_entries, - .pptable_get_vce_state_table_entry = - get_vce_state_table_entry, -}; - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h deleted file mode 100644 index baddaa75693b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2015 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. - * Interface Functions related to the BIOS PowerPlay Tables. - * - */ - -#ifndef PROCESSPPTABLES_H -#define PROCESSPPTABLES_H - -struct pp_hwmgr; -struct pp_power_state; -struct pp_hw_power_state; - -extern const struct pp_table_func pptable_funcs; - -typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps, - unsigned int index, - const void *clock_info); - -int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, - unsigned long *num_of_entries); - -int pp_tables_get_entry(struct pp_hwmgr *hwmgr, - unsigned long entry_index, - struct pp_power_state *ps, - pp_tables_hw_clock_info_callback func); - -int pp_tables_get_response_times(struct pp_hwmgr *hwmgr, - uint32_t *vol_rep_time, uint32_t *bb_rep_time); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c deleted file mode 100644 index c9cfe90a2947..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c +++ /dev/null @@ -1,1404 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include "atom-types.h" -#include "atombios.h" -#include "processpptables.h" -#include "cgs_common.h" -#include "smumgr.h" -#include "hwmgr.h" -#include "hardwaremanager.h" -#include "rv_ppsmc.h" -#include "smu10_hwmgr.h" -#include "power_state.h" -#include "soc15_common.h" -#include "smu10.h" -#include "asic_reg/pwr/pwr_10_0_offset.h" -#include "asic_reg/pwr/pwr_10_0_sh_mask.h" - -#define SMU10_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define SMU10_MINIMUM_ENGINE_CLOCK 800 /* 8Mhz, the low boundary of engine clock allowed on this chip */ -#define SCLK_MIN_DIV_INTV_SHIFT 12 -#define SMU10_DISPCLK_BYPASS_THRESHOLD 10000 /* 100Mhz */ -#define SMC_RAM_END 0x40000 - -static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic; - - -static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock_req) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - enum amd_pp_clock_type clk_type = clock_req->clock_type; - uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; - PPSMC_Msg msg; - - switch (clk_type) { - case amd_pp_dcf_clock: - if (clk_freq == smu10_data->dcf_actual_hard_min_freq) - return 0; - msg = PPSMC_MSG_SetHardMinDcefclkByFreq; - smu10_data->dcf_actual_hard_min_freq = clk_freq; - break; - case amd_pp_soc_clock: - msg = PPSMC_MSG_SetHardMinSocclkByFreq; - break; - case amd_pp_f_clock: - if (clk_freq == smu10_data->f_actual_hard_min_freq) - return 0; - smu10_data->f_actual_hard_min_freq = clk_freq; - msg = PPSMC_MSG_SetHardMinFclkByFreq; - break; - default: - pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); - return -EINVAL; - } - smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq, NULL); - - return 0; -} - -static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps) -{ - if (SMU10_Magic != hw_ps->magic) - return NULL; - - return (struct smu10_power_state *)hw_ps; -} - -static const struct smu10_power_state *cast_const_smu10_ps( - const struct pp_hw_power_state *hw_ps) -{ - if (SMU10_Magic != hw_ps->magic) - return NULL; - - return (struct smu10_power_state *)hw_ps; -} - -static int smu10_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - smu10_data->dce_slow_sclk_threshold = 30000; - smu10_data->thermal_auto_throttling_treshold = 0; - smu10_data->is_nb_dpm_enabled = 1; - smu10_data->dpm_flags = 1; - smu10_data->need_min_deep_sleep_dcefclk = true; - smu10_data->num_active_display = 0; - smu10_data->deep_sleep_dcefclk = 0; - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerPlaySupport); - return 0; -} - -static int smu10_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *table) -{ - return 0; -} - -static int smu10_init_dynamic_state_adjustment_rule_settings( - struct pp_hwmgr *hwmgr) -{ - struct phm_clock_voltage_dependency_table *table_clk_vlt; - - table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), - GFP_KERNEL); - - if (NULL == table_clk_vlt) { - pr_err("Can not allocate memory!\n"); - return -ENOMEM; - } - - table_clk_vlt->count = 8; - table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; - table_clk_vlt->entries[0].v = 0; - table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; - table_clk_vlt->entries[1].v = 1; - table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; - table_clk_vlt->entries[2].v = 2; - table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; - table_clk_vlt->entries[3].v = 3; - table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; - table_clk_vlt->entries[4].v = 4; - table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; - table_clk_vlt->entries[5].v = 5; - table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; - table_clk_vlt->entries[6].v = 6; - table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; - table_clk_vlt->entries[7].v = 7; - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; - - return 0; -} - -static int smu10_get_system_info_data(struct pp_hwmgr *hwmgr) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)hwmgr->backend; - - smu10_data->sys_info.htc_hyst_lmt = 5; - smu10_data->sys_info.htc_tmp_lmt = 203; - - if (smu10_data->thermal_auto_throttling_treshold == 0) - smu10_data->thermal_auto_throttling_treshold = 203; - - smu10_construct_max_power_limits_table (hwmgr, - &hwmgr->dyn_state.max_clock_voltage_on_ac); - - smu10_init_dynamic_state_adjustment_rule_settings(hwmgr); - - return 0; -} - -static int smu10_construct_boot_state(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int smu10_set_clock_limit(struct pp_hwmgr *hwmgr, const void *input) -{ - struct PP_Clocks clocks = {0}; - struct pp_display_clock_request clock_req; - - clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; - clock_req.clock_type = amd_pp_dcf_clock; - clock_req.clock_freq_in_khz = clocks.dcefClock * 10; - - PP_ASSERT_WITH_CODE(!smu10_display_clock_voltage_request(hwmgr, &clock_req), - "Attempt to set DCF Clock Failed!", return -EINVAL); - - return 0; -} - -static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (smu10_data->need_min_deep_sleep_dcefclk && - smu10_data->deep_sleep_dcefclk != clock) { - smu10_data->deep_sleep_dcefclk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinDeepSleepDcefclk, - smu10_data->deep_sleep_dcefclk, - NULL); - } - return 0; -} - -static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (smu10_data->dcf_actual_hard_min_freq && - smu10_data->dcf_actual_hard_min_freq != clock) { - smu10_data->dcf_actual_hard_min_freq = clock; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinDcefclkByFreq, - smu10_data->dcf_actual_hard_min_freq, - NULL); - } - return 0; -} - -static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t clock) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (smu10_data->f_actual_hard_min_freq && - smu10_data->f_actual_hard_min_freq != clock) { - smu10_data->f_actual_hard_min_freq = clock; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - smu10_data->f_actual_hard_min_freq, - NULL); - } - return 0; -} - -static int smu10_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (smu10_data->num_active_display != count) { - smu10_data->num_active_display = count; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDisplayCount, - smu10_data->num_active_display, - NULL); - } - - return 0; -} - -static int smu10_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) -{ - return smu10_set_clock_limit(hwmgr, input); -} - -static int smu10_init_power_gate_state(struct pp_hwmgr *hwmgr) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - - smu10_data->vcn_power_gated = true; - smu10_data->isp_tileA_power_gated = true; - smu10_data->isp_tileB_power_gated = true; - - if (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetGfxCGPG, - true, - NULL); - else - return 0; -} - - -static int smu10_setup_asic_task(struct pp_hwmgr *hwmgr) -{ - return smu10_init_power_gate_state(hwmgr); -} - -static int smu10_reset_cc6_data(struct pp_hwmgr *hwmgr) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - smu10_data->separation_time = 0; - smu10_data->cc6_disable = false; - smu10_data->pstate_disable = false; - smu10_data->cc6_setting_changed = false; - - return 0; -} - -static int smu10_power_off_asic(struct pp_hwmgr *hwmgr) -{ - return smu10_reset_cc6_data(hwmgr); -} - -static bool smu10_is_gfx_on(struct pp_hwmgr *hwmgr) -{ - uint32_t reg; - struct amdgpu_device *adev = hwmgr->adev; - - reg = RREG32_SOC15(PWR, 0, mmPWR_MISC_CNTL_STATUS); - if ((reg & PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS_MASK) == - (0x2 << PWR_MISC_CNTL_STATUS__PWR_GFXOFF_STATUS__SHIFT)) - return true; - - return false; -} - -static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (adev->pm.pp_feature & PP_GFXOFF_MASK) { - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableGfxOff, NULL); - - /* confirm gfx is back to "on" state */ - while (!smu10_is_gfx_on(hwmgr)) - msleep(1); - } - - return 0; -} - -static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (adev->pm.pp_feature & PP_GFXOFF_MASK) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableGfxOff, NULL); - - return 0; -} - -static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) -{ - if (enable) - return smu10_enable_gfx_off(hwmgr); - else - return smu10_disable_gfx_off(hwmgr); -} - -static int smu10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *prequest_ps, - const struct pp_power_state *pcurrent_ps) -{ - return 0; -} - -/* temporary hardcoded clock voltage breakdown tables */ -static const DpmClock_t VddDcfClk[]= { - { 300, 2600}, - { 600, 3200}, - { 600, 3600}, -}; - -static const DpmClock_t VddSocClk[]= { - { 478, 2600}, - { 722, 3200}, - { 722, 3600}, -}; - -static const DpmClock_t VddFClk[]= { - { 400, 2600}, - {1200, 3200}, - {1200, 3600}, -}; - -static const DpmClock_t VddDispClk[]= { - { 435, 2600}, - { 661, 3200}, - {1086, 3600}, -}; - -static const DpmClock_t VddDppClk[]= { - { 435, 2600}, - { 661, 3200}, - { 661, 3600}, -}; - -static const DpmClock_t VddPhyClk[]= { - { 540, 2600}, - { 810, 3200}, - { 810, 3600}, -}; - -static int smu10_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, - struct smu10_voltage_dependency_table **pptable, - uint32_t num_entry, const DpmClock_t *pclk_dependency_table) -{ - uint32_t i; - struct smu10_voltage_dependency_table *ptable; - - ptable = kzalloc(struct_size(ptable, entries, num_entry), GFP_KERNEL); - if (NULL == ptable) - return -ENOMEM; - - ptable->count = num_entry; - - for (i = 0; i < ptable->count; i++) { - ptable->entries[i].clk = pclk_dependency_table->Freq * 100; - ptable->entries[i].vol = pclk_dependency_table->Vol; - pclk_dependency_table++; - } - - *pptable = ptable; - - return 0; -} - - -static int smu10_populate_clock_table(struct pp_hwmgr *hwmgr) -{ - uint32_t result; - - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - DpmClocks_t *table = &(smu10_data->clock_table); - struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); - - result = smum_smc_table_manager(hwmgr, (uint8_t *)table, SMU10_CLOCKTABLE, true); - - PP_ASSERT_WITH_CODE((0 == result), - "Attempt to copy clock table from smc failed", - return result); - - if (0 == result && table->DcefClocks[0].Freq != 0) { - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, - NUM_DCEFCLK_DPM_LEVELS, - &smu10_data->clock_table.DcefClocks[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, - NUM_SOCCLK_DPM_LEVELS, - &smu10_data->clock_table.SocClocks[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, - NUM_FCLK_DPM_LEVELS, - &smu10_data->clock_table.FClocks[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_mclk, - NUM_MEMCLK_DPM_LEVELS, - &smu10_data->clock_table.MemClocks[0]); - } else { - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dcefclk, - ARRAY_SIZE(VddDcfClk), - &VddDcfClk[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_socclk, - ARRAY_SIZE(VddSocClk), - &VddSocClk[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_fclk, - ARRAY_SIZE(VddFClk), - &VddFClk[0]); - } - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dispclk, - ARRAY_SIZE(VddDispClk), - &VddDispClk[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_dppclk, - ARRAY_SIZE(VddDppClk), &VddDppClk[0]); - smu10_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk, - ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMinGfxclkFrequency, &result); - smu10_data->gfx_min_freq_limit = result / 10 * 1000; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxGfxclkFrequency, &result); - smu10_data->gfx_max_freq_limit = result / 10 * 1000; - - return 0; -} - -static int smu10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct smu10_hwmgr *data; - - data = kzalloc(sizeof(struct smu10_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - - result = smu10_initialize_dpm_defaults(hwmgr); - if (result != 0) { - pr_err("smu10_initialize_dpm_defaults failed\n"); - return result; - } - - smu10_populate_clock_table(hwmgr); - - result = smu10_get_system_info_data(hwmgr); - if (result != 0) { - pr_err("smu10_get_system_info_data failed\n"); - return result; - } - - smu10_construct_boot_state(hwmgr); - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = - SMU10_MAX_HARDWARE_POWERLEVELS; - - hwmgr->platform_descriptor.hardwarePerformanceLevels = - SMU10_MAX_HARDWARE_POWERLEVELS; - - hwmgr->platform_descriptor.vbiosInterruptId = 0; - - hwmgr->platform_descriptor.clockStep.engineClock = 500; - - hwmgr->platform_descriptor.clockStep.memoryClock = 500; - - hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - - hwmgr->pstate_sclk = SMU10_UMD_PSTATE_GFXCLK * 100; - hwmgr->pstate_mclk = SMU10_UMD_PSTATE_FCLK * 100; - - return result; -} - -static int smu10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); - - kfree(pinfo->vdd_dep_on_dcefclk); - pinfo->vdd_dep_on_dcefclk = NULL; - kfree(pinfo->vdd_dep_on_socclk); - pinfo->vdd_dep_on_socclk = NULL; - kfree(pinfo->vdd_dep_on_fclk); - pinfo->vdd_dep_on_fclk = NULL; - kfree(pinfo->vdd_dep_on_dispclk); - pinfo->vdd_dep_on_dispclk = NULL; - kfree(pinfo->vdd_dep_on_dppclk); - pinfo->vdd_dep_on_dppclk = NULL; - kfree(pinfo->vdd_dep_on_phyclk); - pinfo->vdd_dep_on_phyclk = NULL; - - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - - kfree(hwmgr->backend); - hwmgr->backend = NULL; - - return 0; -} - -static int smu10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - struct smu10_hwmgr *data = hwmgr->backend; - uint32_t min_sclk = hwmgr->display_config->min_core_set_clock; - uint32_t min_mclk = hwmgr->display_config->min_mem_set_clock/100; - - if (hwmgr->smu_version < 0x1E3700) { - pr_info("smu firmware version too old, can not set dpm level\n"); - return 0; - } - - if (min_sclk < data->gfx_min_freq_limit) - min_sclk = data->gfx_min_freq_limit; - - min_sclk /= 100; /* transfer 10KHz to MHz */ - if (min_mclk < data->clock_table.FClocks[0].Freq) - min_mclk = data->clock_table.FClocks[0].Freq; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - data->gfx_max_freq_limit/100, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - SMU10_UMD_PSTATE_PEAK_FCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinSocclkByFreq, - SMU10_UMD_PSTATE_PEAK_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinVcn, - SMU10_UMD_PSTATE_VCE, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - data->gfx_max_freq_limit/100, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - SMU10_UMD_PSTATE_PEAK_FCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxSocclkByFreq, - SMU10_UMD_PSTATE_PEAK_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxVcn, - SMU10_UMD_PSTATE_VCE, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - min_sclk, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - min_sclk, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - min_mclk, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - min_mclk, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - SMU10_UMD_PSTATE_GFXCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - SMU10_UMD_PSTATE_FCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinSocclkByFreq, - SMU10_UMD_PSTATE_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinVcn, - SMU10_UMD_PSTATE_VCE, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - SMU10_UMD_PSTATE_GFXCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - SMU10_UMD_PSTATE_FCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxSocclkByFreq, - SMU10_UMD_PSTATE_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxVcn, - SMU10_UMD_PSTATE_VCE, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - min_sclk, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - hwmgr->display_config->num_display > 3 ? - SMU10_UMD_PSTATE_PEAK_FCLK : - min_mclk, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinSocclkByFreq, - SMU10_UMD_PSTATE_MIN_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinVcn, - SMU10_UMD_PSTATE_MIN_VCE, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - data->gfx_max_freq_limit/100, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - SMU10_UMD_PSTATE_PEAK_FCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxSocclkByFreq, - SMU10_UMD_PSTATE_PEAK_SOCCLK, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxVcn, - SMU10_UMD_PSTATE_VCE, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - data->gfx_min_freq_limit/100, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - data->gfx_min_freq_limit/100, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - min_mclk, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - min_mclk, - NULL); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - return 0; -} - -static uint32_t smu10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct smu10_hwmgr *data; - - if (hwmgr == NULL) - return -EINVAL; - - data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (low) - return data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; - else - return data->clock_vol_info.vdd_dep_on_fclk->entries[ - data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; -} - -static uint32_t smu10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct smu10_hwmgr *data; - - if (hwmgr == NULL) - return -EINVAL; - - data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (low) - return data->gfx_min_freq_limit; - else - return data->gfx_max_freq_limit; -} - -static int smu10_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps) -{ - return 0; -} - -static int smu10_dpm_get_pp_table_entry_callback( - struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps, - unsigned int index, - const void *clock_info) -{ - struct smu10_power_state *smu10_ps = cast_smu10_ps(hw_ps); - - smu10_ps->levels[index].engine_clock = 0; - - smu10_ps->levels[index].vddc_index = 0; - smu10_ps->level = index + 1; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { - smu10_ps->levels[index].ds_divider_index = 5; - smu10_ps->levels[index].ss_divider_index = 5; - } - - return 0; -} - -static int smu10_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) -{ - int result; - unsigned long ret = 0; - - result = pp_tables_get_num_of_entries(hwmgr, &ret); - - return result ? 0 : ret; -} - -static int smu10_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, - unsigned long entry, struct pp_power_state *ps) -{ - int result; - struct smu10_power_state *smu10_ps; - - ps->hardware.magic = SMU10_Magic; - - smu10_ps = cast_smu10_ps(&(ps->hardware)); - - result = pp_tables_get_entry(hwmgr, entry, ps, - smu10_dpm_get_pp_table_entry_callback); - - smu10_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; - smu10_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; - - return result; -} - -static int smu10_get_power_state_size(struct pp_hwmgr *hwmgr) -{ - return sizeof(struct smu10_power_state); -} - -static int smu10_set_cpu_power_state(struct pp_hwmgr *hwmgr) -{ - return 0; -} - - -static int smu10_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, - bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) -{ - struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (separation_time != data->separation_time || - cc6_disable != data->cc6_disable || - pstate_disable != data->pstate_disable) { - data->separation_time = separation_time; - data->cc6_disable = cc6_disable; - data->pstate_disable = pstate_disable; - data->cc6_setting_changed = true; - } - return 0; -} - -static int smu10_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ - return -EINVAL; -} - -static int smu10_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - struct smu10_hwmgr *data = hwmgr->backend; - struct smu10_voltage_dependency_table *mclk_table = - data->clock_vol_info.vdd_dep_on_fclk; - uint32_t low, high; - - low = mask ? (ffs(mask) - 1) : 0; - high = mask ? (fls(mask) - 1) : 0; - - switch (type) { - case PP_SCLK: - if (low > 2 || high > 2) { - pr_info("Currently sclk only support 3 levels on RV\n"); - return -EINVAL; - } - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinGfxClk, - low == 2 ? data->gfx_max_freq_limit/100 : - low == 1 ? SMU10_UMD_PSTATE_GFXCLK : - data->gfx_min_freq_limit/100, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxClk, - high == 0 ? data->gfx_min_freq_limit/100 : - high == 1 ? SMU10_UMD_PSTATE_GFXCLK : - data->gfx_max_freq_limit/100, - NULL); - break; - - case PP_MCLK: - if (low > mclk_table->count - 1 || high > mclk_table->count - 1) - return -EINVAL; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinFclkByFreq, - mclk_table->entries[low].clk/100, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxFclkByFreq, - mclk_table->entries[high].clk/100, - NULL); - break; - - case PP_PCIE: - default: - break; - } - return 0; -} - -static int smu10_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - struct smu10_hwmgr *data = (struct smu10_hwmgr *)(hwmgr->backend); - struct smu10_voltage_dependency_table *mclk_table = - data->clock_vol_info.vdd_dep_on_fclk; - uint32_t i, now, size = 0; - - switch (type) { - case PP_SCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &now); - - /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ - if (now == data->gfx_max_freq_limit/100) - i = 2; - else if (now == data->gfx_min_freq_limit/100) - i = 0; - else - i = 1; - - size += sprintf(buf + size, "0: %uMhz %s\n", - data->gfx_min_freq_limit/100, - i == 0 ? "*" : ""); - size += sprintf(buf + size, "1: %uMhz %s\n", - i == 1 ? now : SMU10_UMD_PSTATE_GFXCLK, - i == 1 ? "*" : ""); - size += sprintf(buf + size, "2: %uMhz %s\n", - data->gfx_max_freq_limit/100, - i == 2 ? "*" : ""); - break; - case PP_MCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &now); - - for (i = 0; i < mclk_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, - mclk_table->entries[i].clk / 100, - ((mclk_table->entries[i].clk / 100) - == now) ? "*" : ""); - break; - default: - break; - } - - return size; -} - -static int smu10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - struct smu10_hwmgr *data; - - if (level == NULL || hwmgr == NULL || state == NULL) - return -EINVAL; - - data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (index == 0) { - level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; - level->coreClock = data->gfx_min_freq_limit; - } else { - level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[ - data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; - level->coreClock = data->gfx_max_freq_limit; - } - - level->nonLocalMemoryFreq = 0; - level->nonLocalMemoryWidth = 0; - - return 0; -} - -static int smu10_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) -{ - const struct smu10_power_state *ps = cast_const_smu10_ps(state); - - clock_info->min_eng_clk = ps->levels[0].engine_clock / (1 << (ps->levels[0].ss_divider_index)); - clock_info->max_eng_clk = ps->levels[ps->level - 1].engine_clock / (1 << (ps->levels[ps->level - 1].ss_divider_index)); - - return 0; -} - -#define MEM_FREQ_LOW_LATENCY 25000 -#define MEM_FREQ_HIGH_LATENCY 80000 -#define MEM_LATENCY_HIGH 245 -#define MEM_LATENCY_LOW 35 -#define MEM_LATENCY_ERR 0xFFFF - - -static uint32_t smu10_get_mem_latency(struct pp_hwmgr *hwmgr, - uint32_t clock) -{ - if (clock >= MEM_FREQ_LOW_LATENCY && - clock < MEM_FREQ_HIGH_LATENCY) - return MEM_LATENCY_HIGH; - else if (clock >= MEM_FREQ_HIGH_LATENCY) - return MEM_LATENCY_LOW; - else - return MEM_LATENCY_ERR; -} - -static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - uint32_t i; - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); - struct smu10_voltage_dependency_table *pclk_vol_table; - bool latency_required = false; - - if (pinfo == NULL) - return -EINVAL; - - switch (type) { - case amd_pp_mem_clock: - pclk_vol_table = pinfo->vdd_dep_on_mclk; - latency_required = true; - break; - case amd_pp_f_clock: - pclk_vol_table = pinfo->vdd_dep_on_fclk; - latency_required = true; - break; - case amd_pp_dcf_clock: - pclk_vol_table = pinfo->vdd_dep_on_dcefclk; - break; - case amd_pp_disp_clock: - pclk_vol_table = pinfo->vdd_dep_on_dispclk; - break; - case amd_pp_phy_clock: - pclk_vol_table = pinfo->vdd_dep_on_phyclk; - break; - case amd_pp_dpp_clock: - pclk_vol_table = pinfo->vdd_dep_on_dppclk; - break; - default: - return -EINVAL; - } - - if (pclk_vol_table == NULL || pclk_vol_table->count == 0) - return -EINVAL; - - clocks->num_levels = 0; - for (i = 0; i < pclk_vol_table->count; i++) { - if (pclk_vol_table->entries[i].clk) { - clocks->data[clocks->num_levels].clocks_in_khz = - pclk_vol_table->entries[i].clk * 10; - clocks->data[clocks->num_levels].latency_in_us = latency_required ? - smu10_get_mem_latency(hwmgr, - pclk_vol_table->entries[i].clk) : - 0; - clocks->num_levels++; - } - } - - return 0; -} - -static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - uint32_t i; - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - struct smu10_clock_voltage_information *pinfo = &(smu10_data->clock_vol_info); - struct smu10_voltage_dependency_table *pclk_vol_table = NULL; - - if (pinfo == NULL) - return -EINVAL; - - switch (type) { - case amd_pp_mem_clock: - pclk_vol_table = pinfo->vdd_dep_on_mclk; - break; - case amd_pp_f_clock: - pclk_vol_table = pinfo->vdd_dep_on_fclk; - break; - case amd_pp_dcf_clock: - pclk_vol_table = pinfo->vdd_dep_on_dcefclk; - break; - case amd_pp_soc_clock: - pclk_vol_table = pinfo->vdd_dep_on_socclk; - break; - case amd_pp_disp_clock: - pclk_vol_table = pinfo->vdd_dep_on_dispclk; - break; - case amd_pp_phy_clock: - pclk_vol_table = pinfo->vdd_dep_on_phyclk; - break; - default: - return -EINVAL; - } - - if (pclk_vol_table == NULL || pclk_vol_table->count == 0) - return -EINVAL; - - clocks->num_levels = 0; - for (i = 0; i < pclk_vol_table->count; i++) { - if (pclk_vol_table->entries[i].clk) { - clocks->data[clocks->num_levels].clocks_in_khz = pclk_vol_table->entries[i].clk * 10; - clocks->data[clocks->num_levels].voltage_in_mv = pclk_vol_table->entries[i].vol; - clocks->num_levels++; - } - } - - return 0; -} - - - -static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) -{ - clocks->engine_max_clock = 80000; /* driver can't get engine clock, temp hard code to 800MHz */ - return 0; -} - -static int smu10_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t reg_value = RREG32_SOC15(THM, 0, mmTHM_TCON_CUR_TMP); - int cur_temp = - (reg_value & THM_TCON_CUR_TMP__CUR_TEMP_MASK) >> THM_TCON_CUR_TMP__CUR_TEMP__SHIFT; - - if (cur_temp & THM_TCON_CUR_TMP__CUR_TEMP_RANGE_SEL_MASK) - cur_temp = ((cur_temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - else - cur_temp = (cur_temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return cur_temp; -} - -static int smu10_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - uint32_t sclk, mclk; - int ret = 0; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency, &sclk); - /* in units of 10KHZ */ - *((uint32_t *)value) = sclk * 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency, &mclk); - /* in units of 10KHZ */ - *((uint32_t *)value) = mclk * 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = smu10_thermal_get_temperature(hwmgr); - break; - case AMDGPU_PP_SENSOR_VCN_POWER_STATE: - *(uint32_t *)value = smu10_data->vcn_power_gated ? 0 : 1; - *size = 4; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static int smu10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_ranges) -{ - struct smu10_hwmgr *data = hwmgr->backend; - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; - Watermarks_t *table = &(data->water_marks_table); - - smu_set_watermarks_for_clocks_ranges(table,wm_with_clock_ranges); - smum_smc_table_manager(hwmgr, (uint8_t *)table, (uint16_t)SMU10_WMTABLE, false); - data->water_marks_exist = true; - return 0; -} - -static int smu10_smus_notify_pwe(struct pp_hwmgr *hwmgr) -{ - - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SetRccPfcPmeRestoreRegister, NULL); -} - -static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr) -{ - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub, NULL); -} - -static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate) -{ - if (gate) - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma, NULL); - else - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma, NULL); -} - -static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - - if (bgate) { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_GATE); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PowerDownVcn, 0, NULL); - smu10_data->vcn_power_gated = true; - } else { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PowerUpVcn, 0, NULL); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCN, - AMD_PG_STATE_UNGATE); - smu10_data->vcn_power_gated = false; - } -} - -static int conv_power_profile_to_pplib_workload(int power_profile) -{ - int pplib_workload = 0; - - switch (power_profile) { - case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: - pplib_workload = WORKLOAD_DEFAULT_BIT; - break; - case PP_SMC_POWER_PROFILE_FULLSCREEN3D: - pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; - break; - case PP_SMC_POWER_PROFILE_POWERSAVING: - pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; - break; - case PP_SMC_POWER_PROFILE_VIDEO: - pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; - break; - case PP_SMC_POWER_PROFILE_VR: - pplib_workload = WORKLOAD_PPLIB_VR_BIT; - break; - case PP_SMC_POWER_PROFILE_COMPUTE: - pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; - break; - } - - return pplib_workload; -} - -static int smu10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) -{ - uint32_t i, size = 0; - static const uint8_t - profile_mode_setting[6][4] = {{70, 60, 0, 0,}, - {70, 60, 1, 3,}, - {90, 60, 0, 0,}, - {70, 60, 0, 0,}, - {70, 90, 0, 0,}, - {30, 60, 0, 6,}, - }; - static const char *profile_name[6] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE"}; - static const char *title[6] = {"NUM", - "MODE_NAME", - "BUSY_SET_POINT", - "FPS", - "USE_RLC_BUSY", - "MIN_ACTIVE_LEVEL"}; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], - title[1], title[2], title[3], title[4], title[5]); - - for (i = 0; i <= PP_SMC_POWER_PROFILE_COMPUTE; i++) - size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", - i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", - profile_mode_setting[i][0], profile_mode_setting[i][1], - profile_mode_setting[i][2], profile_mode_setting[i][3]); - - return size; -} - -static bool smu10_is_raven1_refresh(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - if ((adev->apu_flags & AMD_APU_IS_RAVEN) && - (hwmgr->smu_version >= 0x41e2b)) - return true; - else - return false; -} - -static int smu10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) -{ - int workload_type = 0; - int result = 0; - - if (input[size] > PP_SMC_POWER_PROFILE_COMPUTE) { - pr_err("Invalid power profile mode %ld\n", input[size]); - return -EINVAL; - } - if (hwmgr->power_profile_mode == input[size]) - return 0; - - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = - conv_power_profile_to_pplib_workload(input[size]); - if (workload_type && - smu10_is_raven1_refresh(hwmgr) && - !hwmgr->gfxoff_state_changed_by_workload) { - smu10_gfx_off_control(hwmgr, false); - hwmgr->gfxoff_state_changed_by_workload = true; - } - result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ActiveProcessNotify, - 1 << workload_type, - NULL); - if (!result) - hwmgr->power_profile_mode = input[size]; - if (workload_type && hwmgr->gfxoff_state_changed_by_workload) { - smu10_gfx_off_control(hwmgr, true); - hwmgr->gfxoff_state_changed_by_workload = false; - } - - return 0; -} - -static int smu10_asic_reset(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode) -{ - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DeviceDriverReset, - mode, - NULL); -} - -static const struct pp_hwmgr_func smu10_hwmgr_funcs = { - .backend_init = smu10_hwmgr_backend_init, - .backend_fini = smu10_hwmgr_backend_fini, - .apply_state_adjust_rules = smu10_apply_state_adjust_rules, - .force_dpm_level = smu10_dpm_force_dpm_level, - .get_power_state_size = smu10_get_power_state_size, - .powerdown_uvd = NULL, - .powergate_uvd = smu10_powergate_vcn, - .powergate_vce = NULL, - .get_mclk = smu10_dpm_get_mclk, - .get_sclk = smu10_dpm_get_sclk, - .patch_boot_state = smu10_dpm_patch_boot_state, - .get_pp_table_entry = smu10_dpm_get_pp_table_entry, - .get_num_of_pp_table_entries = smu10_dpm_get_num_of_pp_table_entries, - .set_cpu_power_state = smu10_set_cpu_power_state, - .store_cc6_data = smu10_store_cc6_data, - .force_clock_level = smu10_force_clock_level, - .print_clock_levels = smu10_print_clock_levels, - .get_dal_power_level = smu10_get_dal_power_level, - .get_performance_level = smu10_get_performance_level, - .get_current_shallow_sleep_clocks = smu10_get_current_shallow_sleep_clocks, - .get_clock_by_type_with_latency = smu10_get_clock_by_type_with_latency, - .get_clock_by_type_with_voltage = smu10_get_clock_by_type_with_voltage, - .set_watermarks_for_clocks_ranges = smu10_set_watermarks_for_clocks_ranges, - .get_max_high_clocks = smu10_get_max_high_clocks, - .read_sensor = smu10_read_sensor, - .set_active_display_count = smu10_set_active_display_count, - .set_min_deep_sleep_dcefclk = smu10_set_min_deep_sleep_dcefclk, - .dynamic_state_management_enable = smu10_enable_dpm_tasks, - .power_off_asic = smu10_power_off_asic, - .asic_setup = smu10_setup_asic_task, - .power_state_set = smu10_set_power_state_tasks, - .dynamic_state_management_disable = smu10_disable_dpm_tasks, - .powergate_mmhub = smu10_powergate_mmhub, - .smus_notify_pwe = smu10_smus_notify_pwe, - .display_clock_voltage_request = smu10_display_clock_voltage_request, - .powergate_gfx = smu10_gfx_off_control, - .powergate_sdma = smu10_powergate_sdma, - .set_hard_min_dcefclk_by_freq = smu10_set_hard_min_dcefclk_by_freq, - .set_hard_min_fclk_by_freq = smu10_set_hard_min_fclk_by_freq, - .get_power_profile_mode = smu10_get_power_profile_mode, - .set_power_profile_mode = smu10_set_power_profile_mode, - .asic_reset = smu10_asic_reset, -}; - -int smu10_init_function_pointers(struct pp_hwmgr *hwmgr) -{ - hwmgr->hwmgr_func = &smu10_hwmgr_funcs; - hwmgr->pptable_func = &pptable_funcs; - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h deleted file mode 100644 index 0f969de10fab..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SMU10_HWMGR_H -#define SMU10_HWMGR_H - -#include "hwmgr.h" -#include "smu10_inc.h" -#include "smu10_driver_if.h" -#include "rv_ppsmc.h" - - -#define SMU10_MAX_HARDWARE_POWERLEVELS 8 -#define SMU10_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15 - -#define DPMFlags_SCLK_Enabled 0x00000001 -#define DPMFlags_UVD_Enabled 0x00000002 -#define DPMFlags_VCE_Enabled 0x00000004 -#define DPMFlags_ACP_Enabled 0x00000008 -#define DPMFlags_ForceHighestValid 0x40000000 - -/* Do not change the following, it is also defined in SMU8.h */ -#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001 -#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000 -#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x01000000 -#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x02000000 - -#define SMU_PHYID_SHIFT 8 - -#define SMU10_PCIE_POWERGATING_TARGET_GFX 0 -#define SMU10_PCIE_POWERGATING_TARGET_DDI 1 -#define SMU10_PCIE_POWERGATING_TARGET_PLLCASCADE 2 -#define SMU10_PCIE_POWERGATING_TARGET_PHY 3 - -enum VQ_TYPE { - CLOCK_TYPE_DCLK = 0L, - CLOCK_TYPE_ECLK, - CLOCK_TYPE_SCLK, - CLOCK_TYPE_CCLK, - VQ_GFX_CU -}; - -#define SUSTAINABLE_SCLK_MASK 0x00ffffff -#define SUSTAINABLE_SCLK_SHIFT 0 -#define SUSTAINABLE_CU_MASK 0xff000000 -#define SUSTAINABLE_CU_SHIFT 24 - -struct smu10_dpm_entry { - uint32_t soft_min_clk; - uint32_t hard_min_clk; - uint32_t soft_max_clk; - uint32_t hard_max_clk; -}; - -struct smu10_power_level { - uint32_t engine_clock; - uint8_t vddc_index; - uint8_t ds_divider_index; - uint8_t ss_divider_index; - uint8_t allow_gnb_slow; - uint8_t force_nbp_state; - uint8_t display_wm; - uint8_t vce_wm; - uint8_t num_simd_to_powerdown; - uint8_t hysteresis_up; - uint8_t rsv[3]; -}; - -/*used for the nbpsFlags field in smu10_power state*/ -#define SMU10_POWERSTATE_FLAGS_NBPS_FORCEHIGH (1<<0) -#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOHIGH (1<<1) -#define SMU10_POWERSTATE_FLAGS_NBPS_LOCKTOLOW (1<<2) - -#define SMU10_POWERSTATE_FLAGS_BAPM_DISABLE (1<<0) - -struct smu10_uvd_clocks { - uint32_t vclk; - uint32_t dclk; - uint32_t vclk_low_divider; - uint32_t vclk_high_divider; - uint32_t dclk_low_divider; - uint32_t dclk_high_divider; -}; - -struct pp_disable_nbpslo_flags { - union { - struct { - uint32_t entry : 1; - uint32_t display : 1; - uint32_t driver: 1; - uint32_t vce : 1; - uint32_t uvd : 1; - uint32_t acp : 1; - uint32_t reserved: 26; - } bits; - uint32_t u32All; - }; -}; - - -enum smu10_pstate_previous_action { - DO_NOTHING = 1, - FORCE_HIGH, - CANCEL_FORCE_HIGH -}; - -struct smu10_power_state { - unsigned int magic; - uint32_t level; - struct smu10_uvd_clocks uvd_clocks; - uint32_t evclk; - uint32_t ecclk; - uint32_t samclk; - uint32_t acpclk; - bool need_dfs_bypass; - - uint32_t nbps_flags; - uint32_t bapm_flags; - uint8_t dpm0_pg_nbps_low; - uint8_t dpm0_pg_nbps_high; - uint8_t dpm_x_nbps_low; - uint8_t dpm_x_nbps_high; - - enum smu10_pstate_previous_action action; - - struct smu10_power_level levels[SMU10_MAX_HARDWARE_POWERLEVELS]; - struct pp_disable_nbpslo_flags nbpslo_flags; -}; - -#define SMU10_NUM_NBPSTATES 4 -#define SMU10_NUM_NBPMEMORYCLOCK 2 - - -struct smu10_display_phy_info_entry { - uint8_t phy_present; - uint8_t active_lane_mapping; - uint8_t display_config_type; - uint8_t active_num_of_lanes; -}; - -#define SMU10_MAX_DISPLAYPHY_IDS 10 - -struct smu10_display_phy_info { - bool display_phy_access_initialized; - struct smu10_display_phy_info_entry entries[SMU10_MAX_DISPLAYPHY_IDS]; -}; - -#define MAX_DISPLAY_CLOCK_LEVEL 8 - -struct smu10_system_info{ - uint8_t htc_tmp_lmt; - uint8_t htc_hyst_lmt; -}; - -#define MAX_REGULAR_DPM_NUMBER 8 - -struct smu10_mclk_latency_entries { - uint32_t frequency; - uint32_t latency; -}; - -struct smu10_mclk_latency_table { - uint32_t count; - struct smu10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct smu10_clock_voltage_dependency_record { - uint32_t clk; - uint32_t vol; -}; - - -struct smu10_voltage_dependency_table { - uint32_t count; - struct smu10_clock_voltage_dependency_record entries[]; -}; - -struct smu10_clock_voltage_information { - struct smu10_voltage_dependency_table *vdd_dep_on_dcefclk; - struct smu10_voltage_dependency_table *vdd_dep_on_socclk; - struct smu10_voltage_dependency_table *vdd_dep_on_fclk; - struct smu10_voltage_dependency_table *vdd_dep_on_mclk; - struct smu10_voltage_dependency_table *vdd_dep_on_dispclk; - struct smu10_voltage_dependency_table *vdd_dep_on_dppclk; - struct smu10_voltage_dependency_table *vdd_dep_on_phyclk; -}; - -struct smu10_hwmgr { - uint32_t disable_driver_thermal_policy; - uint32_t thermal_auto_throttling_treshold; - struct smu10_system_info sys_info; - struct smu10_mclk_latency_table mclk_latency_table; - - uint32_t ddi_power_gating_disabled; - - struct smu10_display_phy_info_entry display_phy_info; - uint32_t dce_slow_sclk_threshold; - - bool disp_clk_bypass; - bool disp_clk_bypass_pending; - uint32_t bapm_enabled; - - bool video_start; - bool battery_state; - - uint32_t is_nb_dpm_enabled; - uint32_t is_voltage_island_enabled; - uint32_t disable_smu_acp_s3_handshake; - uint32_t disable_notify_smu_vpu_recovery; - bool in_vpu_recovery; - bool pg_acp_init; - uint8_t disp_config; - - /* PowerTune */ - uint32_t power_containment_features; - bool cac_enabled; - bool disable_uvd_power_tune_feature; - bool enable_bapm_feature; - bool enable_tdc_limit_feature; - - - /* SMC SRAM Address of firmware header tables */ - uint32_t sram_end; - uint32_t dpm_table_start; - uint32_t soft_regs_start; - - /* start of SMU7_Fusion_DpmTable */ - - uint8_t uvd_level_count; - uint8_t vce_level_count; - uint8_t acp_level_count; - uint8_t samu_level_count; - - uint32_t fps_high_threshold; - uint32_t fps_low_threshold; - - uint32_t dpm_flags; - struct smu10_dpm_entry sclk_dpm; - struct smu10_dpm_entry uvd_dpm; - struct smu10_dpm_entry vce_dpm; - struct smu10_dpm_entry acp_dpm; - bool acp_power_up_no_dsp; - - uint32_t max_sclk_level; - uint32_t num_of_clk_entries; - - /* CPU Power State */ - uint32_t separation_time; - bool cc6_disable; - bool pstate_disable; - bool cc6_setting_changed; - - uint32_t ulTotalActiveCUs; - - bool isp_tileA_power_gated; - bool isp_tileB_power_gated; - uint32_t isp_actual_hard_min_freq; - uint32_t soc_actual_hard_min_freq; - uint32_t dcf_actual_hard_min_freq; - - uint32_t f_actual_hard_min_freq; - uint32_t fabric_actual_soft_min_freq; - uint32_t vclk_soft_min; - uint32_t dclk_soft_min; - uint32_t gfx_actual_soft_min_freq; - uint32_t gfx_min_freq_limit; - uint32_t gfx_max_freq_limit; - - bool vcn_power_gated; - bool vcn_dpg_mode; - - bool gfx_off_controled_by_driver; - bool water_marks_exist; - Watermarks_t water_marks_table; - struct smu10_clock_voltage_information clock_vol_info; - DpmClocks_t clock_table; - - uint32_t active_process_mask; - bool need_min_deep_sleep_dcefclk; - uint32_t deep_sleep_dcefclk; - uint32_t num_active_display; -}; - -struct pp_hwmgr; - -int smu10_init_function_pointers(struct pp_hwmgr *hwmgr); - -/* UMD PState SMU10 Msg Parameters in MHz */ -#define SMU10_UMD_PSTATE_GFXCLK 700 -#define SMU10_UMD_PSTATE_SOCCLK 626 -#define SMU10_UMD_PSTATE_FCLK 933 -#define SMU10_UMD_PSTATE_VCE 0x03C00320 - -#define SMU10_UMD_PSTATE_PEAK_SOCCLK 757 -#define SMU10_UMD_PSTATE_PEAK_FCLK 1200 - -#define SMU10_UMD_PSTATE_MIN_FCLK 400 -#define SMU10_UMD_PSTATE_MIN_SOCCLK 200 -#define SMU10_UMD_PSTATE_MIN_VCE 0x0190012C - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h deleted file mode 100644 index edb68e302f6f..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_inc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016 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 SMU10_INC_H -#define SMU10_INC_H - - -#include "asic_reg/mp/mp_10_0_default.h" -#include "asic_reg/mp/mp_10_0_offset.h" -#include "asic_reg/mp/mp_10_0_sh_mask.h" - -#include "asic_reg/nbio/nbio_7_0_default.h" -#include "asic_reg/nbio/nbio_7_0_offset.h" -#include "asic_reg/nbio/nbio_7_0_sh_mask.h" - -#include "asic_reg/thm/thm_10_0_default.h" -#include "asic_reg/thm/thm_10_0_offset.h" -#include "asic_reg/thm/thm_10_0_sh_mask.h" - - -#define ixDDI_PHY_GEN_STATUS 0x3FCE8 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c deleted file mode 100644 index 044cda005aed..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "smu7_baco.h" -#include "tonga_baco.h" -#include "fiji_baco.h" -#include "polaris_baco.h" -#include "ci_baco.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "smu/smu_7_1_2_d.h" -#include "smu/smu_7_1_2_sh_mask.h" - -int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - uint32_t reg; - - *cap = false; - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return 0; - - reg = RREG32(mmCC_BIF_BX_FUSESTRAP0); - - if (reg & CC_BIF_BX_FUSESTRAP0__STRAP_BIF_PX_CAPABLE_MASK) - *cap = true; - - return 0; -} - -int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - uint32_t reg; - - reg = RREG32(mmBACO_CNTL); - - if (reg & BACO_CNTL__BACO_MODE_MASK) - /* gfx has already entered BACO state */ - *state = BACO_STATE_IN; - else - *state = BACO_STATE_OUT; - return 0; -} - -int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - - switch (adev->asic_type) { - case CHIP_TOPAZ: - case CHIP_TONGA: - return tonga_baco_set_state(hwmgr, state); - case CHIP_FIJI: - return fiji_baco_set_state(hwmgr, state); - case CHIP_POLARIS10: - case CHIP_POLARIS11: - case CHIP_POLARIS12: - case CHIP_VEGAM: - return polaris_baco_set_state(hwmgr, state); -#ifdef CONFIG_DRM_AMDGPU_CIK - case CHIP_BONAIRE: - case CHIP_HAWAII: - return ci_baco_set_state(hwmgr, state); -#endif - default: - return -EINVAL; - } -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h deleted file mode 100644 index be0d98abb536..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_baco.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __SMU7_BACO_H__ -#define __SMU7_BACO_H__ -#include "hwmgr.h" -#include "common_baco.h" - -extern int smu7_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); -extern int smu7_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); -extern int smu7_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c deleted file mode 100644 index f2bda3bcbbde..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright 2016 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 "smu7_hwmgr.h" -#include "smu7_clockpowergating.h" -#include "smu7_common.h" - -static int smu7_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - return smum_send_msg_to_smc(hwmgr, enable ? - PPSMC_MSG_UVDDPM_Enable : - PPSMC_MSG_UVDDPM_Disable, - NULL); -} - -static int smu7_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - return smum_send_msg_to_smc(hwmgr, enable ? - PPSMC_MSG_VCEDPM_Enable : - PPSMC_MSG_VCEDPM_Disable, - NULL); -} - -static int smu7_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) -{ - if (!bgate) - smum_update_smc_table(hwmgr, SMU_UVD_TABLE); - return smu7_enable_disable_uvd_dpm(hwmgr, !bgate); -} - -static int smu7_update_vce_dpm(struct pp_hwmgr *hwmgr, bool bgate) -{ - if (!bgate) - smum_update_smc_table(hwmgr, SMU_VCE_TABLE); - return smu7_enable_disable_vce_dpm(hwmgr, !bgate); -} - -int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr) -{ - if (phm_cf_want_uvd_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_UVDPowerOFF, - NULL); - return 0; -} - -static int smu7_powerup_uvd(struct pp_hwmgr *hwmgr) -{ - if (phm_cf_want_uvd_power_gating(hwmgr)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDynamicPowerGating)) { - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDPowerON, 1, NULL); - } else { - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDPowerON, 0, NULL); - } - } - - return 0; -} - -static int smu7_powerdown_vce(struct pp_hwmgr *hwmgr) -{ - if (phm_cf_want_vce_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_VCEPowerOFF, - NULL); - return 0; -} - -static int smu7_powerup_vce(struct pp_hwmgr *hwmgr) -{ - if (phm_cf_want_vce_power_gating(hwmgr)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_VCEPowerON, - NULL); - return 0; -} - -int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->uvd_power_gated = false; - data->vce_power_gated = false; - - smu7_powerup_uvd(hwmgr); - smu7_powerup_vce(hwmgr); - - return 0; -} - -void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->uvd_power_gated = bgate; - - if (bgate) { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_GATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_GATE); - smu7_update_uvd_dpm(hwmgr, true); - smu7_powerdown_uvd(hwmgr); - } else { - smu7_powerup_uvd(hwmgr); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_UNGATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_UNGATE); - smu7_update_uvd_dpm(hwmgr, false); - } - -} - -void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->vce_power_gated = bgate; - - if (bgate) { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_GATE); - smu7_update_vce_dpm(hwmgr, true); - smu7_powerdown_vce(hwmgr); - } else { - smu7_powerup_vce(hwmgr); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_UNGATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); - smu7_update_vce_dpm(hwmgr, false); - } -} - -int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, - const uint32_t *msg_id) -{ - PPSMC_Msg msg; - uint32_t value; - - if (!(hwmgr->feature_mask & PP_ENABLE_GFX_CG_THRU_SMU)) - return 0; - - switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) { - case PP_GROUP_GFX: - switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { - case PP_BLOCK_GFX_CG: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_CGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS - ? PPSMC_MSG_EnableClockGatingFeature - : PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_CGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_GFX_3D: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_3DCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_3DLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_GFX_RLC: - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_RLC_LS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_GFX_CP: - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_GFX_CP_LS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_GFX_MG: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = (CG_CPF_MGCG_MASK | CG_RLC_MGCG_MASK | - CG_GFX_OTHERS_MGCG_MASK); - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - default: - return -EINVAL; - } - break; - - case PP_GROUP_SYS: - switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { - case PP_BLOCK_SYS_BIF: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_BIF_MGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_BIF_MGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_SYS_MC: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_MC_MGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_MC_MGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_SYS_DRM: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_CG ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_DRM_MGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_DRM_MGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_SYS_HDP: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_HDP_MGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_HDP_MGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_SYS_SDMA: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_SDMA_MGCG_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - - if (PP_STATE_SUPPORT_LS & *msg_id) { - msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_SDMA_MGLS_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - case PP_BLOCK_SYS_ROM: - if (PP_STATE_SUPPORT_CG & *msg_id) { - msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) ? - PPSMC_MSG_EnableClockGatingFeature : - PPSMC_MSG_DisableClockGatingFeature; - value = CG_SYS_ROM_MASK; - - if (smum_send_msg_to_smc_with_parameter( - hwmgr, msg, value, NULL)) - return -EINVAL; - } - break; - - default: - return -EINVAL; - - } - break; - - default: - return -EINVAL; - - } - - return 0; -} - -/* This function is for Polaris11 only for now, - * Powerplay will only control the static per CU Power Gating. - * Dynamic per CU Power Gating will be done in gfx. - */ -int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (enable) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GFX_CU_PG_ENABLE, - adev->gfx.cu_info.number, - NULL); - else - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GFX_CU_PG_DISABLE, - NULL); -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h deleted file mode 100644 index fc8f8a6acc72..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_clockpowergating.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2016 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 _SMU7_CLOCK_POWER_GATING_H_ -#define _SMU7_CLOCK_POWER_GATING_H_ - -#include "smu7_hwmgr.h" - -void smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); -void smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); -int smu7_powerdown_uvd(struct pp_hwmgr *hwmgr); -int smu7_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); -int smu7_disable_clock_power_gating(struct pp_hwmgr *hwmgr); -int smu7_update_clock_gatings(struct pp_hwmgr *hwmgr, - const uint32_t *msg_id); -int smu7_powergate_gfx(struct pp_hwmgr *hwmgr, bool enable); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h deleted file mode 100644 index 3477d4dfff70..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_dyn_defaults.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 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 _SMU7_DYN_DEFAULTS_H -#define _SMU7_DYN_DEFAULTS_H - - -/* We need to fill in the default values */ - - -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT1 0x000400 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT2 0xC00080 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT3 0xC00200 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT4 0xC01680 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT5 0xC00033 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT6 0xC00033 -#define SMU7_VOTINGRIGHTSCLIENTS_DFLT7 0x3FFFC000 - - -#define SMU7_THERMALPROTECTCOUNTER_DFLT 0x200 -#define SMU7_STATICSCREENTHRESHOLDUNIT_DFLT 0 -#define SMU7_STATICSCREENTHRESHOLD_DFLT 0x00C8 -#define SMU7_GFXIDLECLOCKSTOPTHRESHOLD_DFLT 0x200 -#define SMU7_REFERENCEDIVIDER_DFLT 4 - -#define SMU7_ULVVOLTAGECHANGEDELAY_DFLT 1687 - -#define SMU7_CGULVPARAMETER_DFLT 0x00040035 -#define SMU7_CGULVCONTROL_DFLT 0x00007450 -#define SMU7_TARGETACTIVITY_DFLT 50 -#define SMU7_MCLK_TARGETACTIVITY_DFLT 10 -#define SMU7_SCLK_TARGETACTIVITY_DFLT 30 -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c deleted file mode 100644 index ffe05b7cc1f0..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ /dev/null @@ -1,5215 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include -#include -#include -#include -#include "ppatomctrl.h" -#include "atombios.h" -#include "pptable_v1_0.h" -#include "pppcielanes.h" -#include "amd_pcie_helpers.h" -#include "hardwaremanager.h" -#include "process_pptables_v1_0.h" -#include "cgs_common.h" - -#include "smu7_common.h" - -#include "hwmgr.h" -#include "smu7_hwmgr.h" -#include "smu_ucode_xfer_vi.h" -#include "smu7_powertune.h" -#include "smu7_dyn_defaults.h" -#include "smu7_thermal.h" -#include "smu7_clockpowergating.h" -#include "processpptables.h" -#include "pp_thermal.h" -#include "smu7_baco.h" - -#include "ivsrcid/ivsrcid_vislands30.h" - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -#define MC_CG_SEQ_DRAMCONF_S0 0x05 -#define MC_CG_SEQ_DRAMCONF_S1 0x06 -#define MC_CG_SEQ_YCLK_SUSPEND 0x04 -#define MC_CG_SEQ_YCLK_RESUME 0x0a - -#define SMC_CG_IND_START 0xc0030000 -#define SMC_CG_IND_END 0xc0040000 - -#define MEM_FREQ_LOW_LATENCY 25000 -#define MEM_FREQ_HIGH_LATENCY 80000 - -#define MEM_LATENCY_HIGH 45 -#define MEM_LATENCY_LOW 35 -#define MEM_LATENCY_ERR 0xFFFF - -#define MC_SEQ_MISC0_GDDR5_SHIFT 28 -#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 -#define MC_SEQ_MISC0_GDDR5_VALUE 5 - -#define PCIE_BUS_CLK 10000 -#define TCLK (PCIE_BUS_CLK / 10) - -static struct profile_mode_setting smu7_profiling[7] = - {{0, 0, 0, 0, 0, 0, 0, 0}, - {1, 0, 100, 30, 1, 0, 100, 10}, - {1, 10, 0, 30, 0, 0, 0, 0}, - {0, 0, 0, 0, 1, 10, 16, 31}, - {1, 0, 11, 50, 1, 0, 100, 10}, - {1, 0, 5, 30, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 0, 0}, - }; - -#define PPSMC_MSG_SetVBITimeout_VEGAM ((uint16_t) 0x310) - -#define ixPWR_SVI2_PLANE1_LOAD 0xC0200280 -#define PWR_SVI2_PLANE1_LOAD__PSI1_MASK 0x00000020L -#define PWR_SVI2_PLANE1_LOAD__PSI0_EN_MASK 0x00000040L -#define PWR_SVI2_PLANE1_LOAD__PSI1__SHIFT 0x00000005 -#define PWR_SVI2_PLANE1_LOAD__PSI0_EN__SHIFT 0x00000006 - -/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ -enum DPM_EVENT_SRC { - DPM_EVENT_SRC_ANALOG = 0, - DPM_EVENT_SRC_EXTERNAL = 1, - DPM_EVENT_SRC_DIGITAL = 2, - DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, - DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 -}; - -static const unsigned long PhwVIslands_Magic = (unsigned long)(PHM_VIslands_Magic); -static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask); - -static struct smu7_power_state *cast_phw_smu7_power_state( - struct pp_hw_power_state *hw_ps) -{ - PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), - "Invalid Powerstate Type!", - return NULL); - - return (struct smu7_power_state *)hw_ps; -} - -static const struct smu7_power_state *cast_const_phw_smu7_power_state( - const struct pp_hw_power_state *hw_ps) -{ - PP_ASSERT_WITH_CODE((PhwVIslands_Magic == hw_ps->magic), - "Invalid Powerstate Type!", - return NULL); - - return (const struct smu7_power_state *)hw_ps; -} - -/** - * Find the MC microcode version and store it in the HwMgr struct - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -static int smu7_get_mc_microcode_version(struct pp_hwmgr *hwmgr) -{ - cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); - - hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); - - return 0; -} - -static uint16_t smu7_get_current_pcie_speed(struct pp_hwmgr *hwmgr) -{ - uint32_t speedCntl = 0; - - /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ - speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE, - ixPCIE_LC_SPEED_CNTL); - return((uint16_t)PHM_GET_FIELD(speedCntl, - PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); -} - -static int smu7_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) -{ - uint32_t link_width; - - /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ - link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, - PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD); - - PP_ASSERT_WITH_CODE((7 >= link_width), - "Invalid PCIe lane width!", return 0); - - return decode_pcie_lane_width(link_width); -} - -/** -* Enable voltage control -* -* @param pHwMgr the address of the powerplay hardware manager. -* @return always PP_Result_OK -*/ -static int smu7_enable_smc_voltage_controller(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->chip_id == CHIP_VEGAM) { - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI1, 0); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, PWR_SVI2_PLANE1_LOAD, PSI0_EN, 0); - } - - if (hwmgr->feature_mask & PP_SMC_VOLTAGE_CONTROL_MASK) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Enable, NULL); - - return 0; -} - -/** -* Checks if we want to support voltage control -* -* @param hwmgr the address of the powerplay hardware manager. -*/ -static bool smu7_voltage_control(const struct pp_hwmgr *hwmgr) -{ - const struct smu7_hwmgr *data = - (const struct smu7_hwmgr *)(hwmgr->backend); - - return (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control); -} - -/** -* Enable voltage control -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_enable_voltage_control(struct pp_hwmgr *hwmgr) -{ - /* enable voltage control */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1); - - return 0; -} - -static int phm_get_svi2_voltage_table_v0(pp_atomctrl_voltage_table *voltage_table, - struct phm_clock_voltage_dependency_table *voltage_dependency_table - ) -{ - uint32_t i; - - PP_ASSERT_WITH_CODE((NULL != voltage_table), - "Voltage Dependency Table empty.", return -EINVAL;); - - voltage_table->mask_low = 0; - voltage_table->phase_delay = 0; - voltage_table->count = voltage_dependency_table->count; - - for (i = 0; i < voltage_dependency_table->count; i++) { - voltage_table->entries[i].value = - voltage_dependency_table->entries[i].v; - voltage_table->entries[i].smio_low = 0; - } - - return 0; -} - - -/** -* Create Voltage Tables. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_construct_voltage_tables(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - int result = 0; - uint32_t tmp; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - result = atomctrl_get_voltage_table_v3(hwmgr, - VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, - &(data->mvdd_voltage_table)); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve MVDD table.", - return result); - } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - if (hwmgr->pp_table_version == PP_TABLE_V1) - result = phm_get_svi2_mvdd_voltage_table(&(data->mvdd_voltage_table), - table_info->vdd_dep_on_mclk); - else if (hwmgr->pp_table_version == PP_TABLE_V0) - result = phm_get_svi2_voltage_table_v0(&(data->mvdd_voltage_table), - hwmgr->dyn_state.mvdd_dependency_on_mclk); - - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve SVI2 MVDD table from dependency table.", - return result;); - } - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - result = atomctrl_get_voltage_table_v3(hwmgr, - VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, - &(data->vddci_voltage_table)); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve VDDCI table.", - return result); - } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - if (hwmgr->pp_table_version == PP_TABLE_V1) - result = phm_get_svi2_vddci_voltage_table(&(data->vddci_voltage_table), - table_info->vdd_dep_on_mclk); - else if (hwmgr->pp_table_version == PP_TABLE_V0) - result = phm_get_svi2_voltage_table_v0(&(data->vddci_voltage_table), - hwmgr->dyn_state.vddci_dependency_on_mclk); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve SVI2 VDDCI table from dependency table.", - return result); - } - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { - /* VDDGFX has only SVI2 voltage control */ - result = phm_get_svi2_vdd_voltage_table(&(data->vddgfx_voltage_table), - table_info->vddgfx_lookup_table); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;); - } - - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { - result = atomctrl_get_voltage_table_v3(hwmgr, - VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT, - &data->vddc_voltage_table); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve VDDC table.", return result;); - } else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - - if (hwmgr->pp_table_version == PP_TABLE_V0) - result = phm_get_svi2_voltage_table_v0(&data->vddc_voltage_table, - hwmgr->dyn_state.vddc_dependency_on_mclk); - else if (hwmgr->pp_table_version == PP_TABLE_V1) - result = phm_get_svi2_vdd_voltage_table(&(data->vddc_voltage_table), - table_info->vddc_lookup_table); - - PP_ASSERT_WITH_CODE((0 == result), - "Failed to retrieve SVI2 VDDC table from dependency table.", return result;); - } - - tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDC); - PP_ASSERT_WITH_CODE( - (data->vddc_voltage_table.count <= tmp), - "Too many voltage values for VDDC. Trimming to fit state table.", - phm_trim_voltage_table_to_fit_state_table(tmp, - &(data->vddc_voltage_table))); - - tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); - PP_ASSERT_WITH_CODE( - (data->vddgfx_voltage_table.count <= tmp), - "Too many voltage values for VDDC. Trimming to fit state table.", - phm_trim_voltage_table_to_fit_state_table(tmp, - &(data->vddgfx_voltage_table))); - - tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDCI); - PP_ASSERT_WITH_CODE( - (data->vddci_voltage_table.count <= tmp), - "Too many voltage values for VDDCI. Trimming to fit state table.", - phm_trim_voltage_table_to_fit_state_table(tmp, - &(data->vddci_voltage_table))); - - tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_MVDD); - PP_ASSERT_WITH_CODE( - (data->mvdd_voltage_table.count <= tmp), - "Too many voltage values for MVDD. Trimming to fit state table.", - phm_trim_voltage_table_to_fit_state_table(tmp, - &(data->mvdd_voltage_table))); - - return 0; -} - -/** -* Programs static screed detection parameters -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_program_static_screen_threshold_parameters( - struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /* Set static screen threshold unit */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT, - data->static_screen_threshold_unit); - /* Set static screen threshold */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, - data->static_screen_threshold); - - return 0; -} - -/** -* Setup display gap for glitch free memory clock switching. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_enable_display_gap(struct pp_hwmgr *hwmgr) -{ - uint32_t display_gap = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_DISPLAY_GAP_CNTL); - - display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, - DISP_GAP, DISPLAY_GAP_IGNORE); - - display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, - DISP_GAP_MCHG, DISPLAY_GAP_VBLANK); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_DISPLAY_GAP_CNTL, display_gap); - - return 0; -} - -/** -* Programs activity state transition voting clients -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_program_voting_clients(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int i; - - /* Clear reset for voting clients before enabling DPM */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); - - for (i = 0; i < 8; i++) - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0 + i * 4, - data->voting_rights_clients[i]); - return 0; -} - -static int smu7_clear_voting_clients(struct pp_hwmgr *hwmgr) -{ - int i; - - /* Reset voting clients before disabling DPM */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 1); - - for (i = 0; i < 8; i++) - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0 + i * 4, 0); - - return 0; -} - -/* Copy one arb setting to another and then switch the active set. - * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants. - */ -static int smu7_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, - uint32_t arb_src, uint32_t arb_dest) -{ - uint32_t mc_arb_dram_timing; - uint32_t mc_arb_dram_timing2; - uint32_t burst_time; - uint32_t mc_cg_config; - - switch (arb_src) { - case MC_CG_ARB_FREQ_F0: - mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - break; - case MC_CG_ARB_FREQ_F1: - mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1); - mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1); - burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1); - break; - default: - return -EINVAL; - } - - switch (arb_dest) { - case MC_CG_ARB_FREQ_F0: - cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); - cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); - PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time); - break; - case MC_CG_ARB_FREQ_F1: - cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); - cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); - PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time); - break; - default: - return -EINVAL; - } - - mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); - mc_cg_config |= 0x0000000F; - cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); - PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest); - - return 0; -} - -static int smu7_reset_to_default(struct pp_hwmgr *hwmgr) -{ - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ResetToDefaults, NULL); -} - -/** -* Initial switch from ARB F0->F1 -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -* This function is to be called from the SetPowerState table. -*/ -static int smu7_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) -{ - return smu7_copy_and_switch_arb_sets(hwmgr, - MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); -} - -static int smu7_force_switch_to_arbf0(struct pp_hwmgr *hwmgr) -{ - uint32_t tmp; - - tmp = (cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, ixSMC_SCRATCH9) & - 0x0000ff00) >> 8; - - if (tmp == MC_CG_ARB_FREQ_F0) - return 0; - - return smu7_copy_and_switch_arb_sets(hwmgr, - tmp, MC_CG_ARB_FREQ_F0); -} - -static int smu7_setup_default_pcie_table(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = NULL; - - uint32_t i, max_entry; - uint32_t tmp; - - PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels || - data->use_pcie_power_saving_levels), "No pcie performance levels!", - return -EINVAL); - - if (table_info != NULL) - pcie_table = table_info->pcie_table; - - if (data->use_pcie_performance_levels && - !data->use_pcie_power_saving_levels) { - data->pcie_gen_power_saving = data->pcie_gen_performance; - data->pcie_lane_power_saving = data->pcie_lane_performance; - } else if (!data->use_pcie_performance_levels && - data->use_pcie_power_saving_levels) { - data->pcie_gen_performance = data->pcie_gen_power_saving; - data->pcie_lane_performance = data->pcie_lane_power_saving; - } - tmp = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_LINK); - phm_reset_single_dpm_table(&data->dpm_table.pcie_speed_table, - tmp, - MAX_REGULAR_DPM_NUMBER); - - if (pcie_table != NULL) { - /* max_entry is used to make sure we reserve one PCIE level - * for boot level (fix for A+A PSPP issue). - * If PCIE table from PPTable have ULV entry + 8 entries, - * then ignore the last entry.*/ - max_entry = (tmp < pcie_table->count) ? tmp : pcie_table->count; - for (i = 1; i < max_entry; i++) { - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1, - get_pcie_gen_support(data->pcie_gen_cap, - pcie_table->entries[i].gen_speed), - get_pcie_lane_support(data->pcie_lane_cap, - pcie_table->entries[i].lane_width)); - } - data->dpm_table.pcie_speed_table.count = max_entry - 1; - smum_update_smc_table(hwmgr, SMU_BIF_TABLE); - } else { - /* Hardcode Pcie Table */ - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Min_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Min_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Max_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Max_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Max_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Max_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - - data->dpm_table.pcie_speed_table.count = 6; - } - /* Populate last level for boot PCIE level, but do not increment count. */ - if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { - for (i = 0; i <= data->dpm_table.pcie_speed_table.count; i++) - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Max_PCIEGen), - data->vbios_boot_state.pcie_lane_bootup_value); - } else { - phm_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, - data->dpm_table.pcie_speed_table.count, - get_pcie_gen_support(data->pcie_gen_cap, - PP_Min_PCIEGen), - get_pcie_lane_support(data->pcie_lane_cap, - PP_Max_PCIELane)); - } - return 0; -} - -static int smu7_reset_dpm_tables(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table)); - - phm_reset_single_dpm_table( - &data->dpm_table.sclk_table, - smum_get_mac_definition(hwmgr, - SMU_MAX_LEVELS_GRAPHICS), - MAX_REGULAR_DPM_NUMBER); - phm_reset_single_dpm_table( - &data->dpm_table.mclk_table, - smum_get_mac_definition(hwmgr, - SMU_MAX_LEVELS_MEMORY), MAX_REGULAR_DPM_NUMBER); - - phm_reset_single_dpm_table( - &data->dpm_table.vddc_table, - smum_get_mac_definition(hwmgr, - SMU_MAX_LEVELS_VDDC), - MAX_REGULAR_DPM_NUMBER); - phm_reset_single_dpm_table( - &data->dpm_table.vddci_table, - smum_get_mac_definition(hwmgr, - SMU_MAX_LEVELS_VDDCI), MAX_REGULAR_DPM_NUMBER); - - phm_reset_single_dpm_table( - &data->dpm_table.mvdd_table, - smum_get_mac_definition(hwmgr, - SMU_MAX_LEVELS_MVDD), - MAX_REGULAR_DPM_NUMBER); - return 0; -} -/* - * This function is to initialize all DPM state tables - * for SMU7 based on the dependency table. - * Dynamic state patching function will then trim these - * state tables to the allowed range based - * on the power policy or external client requests, - * such as UVD request, etc. - */ - -static int smu7_setup_dpm_tables_v0(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_clock_voltage_dependency_table *allowed_vdd_sclk_table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - struct phm_clock_voltage_dependency_table *allowed_vdd_mclk_table = - hwmgr->dyn_state.vddc_dependency_on_mclk; - struct phm_cac_leakage_table *std_voltage_table = - hwmgr->dyn_state.cac_leakage_table; - uint32_t i; - - PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL, - "SCLK dependency table is missing. This table is mandatory", return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1, - "SCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); - - PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, - "MCLK dependency table is missing. This table is mandatory", return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1, - "VMCLK dependency table has to have is missing. This table is mandatory", return -EINVAL); - - - /* Initialize Sclk DPM table based on allow Sclk values*/ - data->dpm_table.sclk_table.count = 0; - - for (i = 0; i < allowed_vdd_sclk_table->count; i++) { - if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value != - allowed_vdd_sclk_table->entries[i].clk) { - data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = - allowed_vdd_sclk_table->entries[i].clk; - data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = (i == 0) ? 1 : 0; - data->dpm_table.sclk_table.count++; - } - } - - PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, - "MCLK dependency table is missing. This table is mandatory", return -EINVAL); - /* Initialize Mclk DPM table based on allow Mclk values */ - data->dpm_table.mclk_table.count = 0; - for (i = 0; i < allowed_vdd_mclk_table->count; i++) { - if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value != - allowed_vdd_mclk_table->entries[i].clk) { - data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = - allowed_vdd_mclk_table->entries[i].clk; - data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = (i == 0) ? 1 : 0; - data->dpm_table.mclk_table.count++; - } - } - - /* Initialize Vddc DPM table based on allow Vddc values. And populate corresponding std values. */ - for (i = 0; i < allowed_vdd_sclk_table->count; i++) { - data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; - data->dpm_table.vddc_table.dpm_levels[i].param1 = std_voltage_table->entries[i].Leakage; - /* param1 is for corresponding std voltage */ - data->dpm_table.vddc_table.dpm_levels[i].enabled = true; - } - - data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count; - allowed_vdd_mclk_table = hwmgr->dyn_state.vddci_dependency_on_mclk; - - if (NULL != allowed_vdd_mclk_table) { - /* Initialize Vddci DPM table based on allow Mclk values */ - for (i = 0; i < allowed_vdd_mclk_table->count; i++) { - data->dpm_table.vddci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; - data->dpm_table.vddci_table.dpm_levels[i].enabled = true; - } - data->dpm_table.vddci_table.count = allowed_vdd_mclk_table->count; - } - - allowed_vdd_mclk_table = hwmgr->dyn_state.mvdd_dependency_on_mclk; - - if (NULL != allowed_vdd_mclk_table) { - /* - * Initialize MVDD DPM table based on allow Mclk - * values - */ - for (i = 0; i < allowed_vdd_mclk_table->count; i++) { - data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].v; - data->dpm_table.mvdd_table.dpm_levels[i].enabled = true; - } - data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count; - } - - return 0; -} - -static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i; - - struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; - - if (table_info == NULL) - return -EINVAL; - - dep_sclk_table = table_info->vdd_dep_on_sclk; - dep_mclk_table = table_info->vdd_dep_on_mclk; - - PP_ASSERT_WITH_CODE(dep_sclk_table != NULL, - "SCLK dependency table is missing.", - return -EINVAL); - PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1, - "SCLK dependency table count is 0.", - return -EINVAL); - - PP_ASSERT_WITH_CODE(dep_mclk_table != NULL, - "MCLK dependency table is missing.", - return -EINVAL); - PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, - "MCLK dependency table count is 0", - return -EINVAL); - - /* Initialize Sclk DPM table based on allow Sclk values */ - data->dpm_table.sclk_table.count = 0; - for (i = 0; i < dep_sclk_table->count; i++) { - if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count - 1].value != - dep_sclk_table->entries[i].clk) { - - data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = - dep_sclk_table->entries[i].clk; - - data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = - (i == 0) ? true : false; - data->dpm_table.sclk_table.count++; - } - } - if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) - hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk; - /* Initialize Mclk DPM table based on allow Mclk values */ - data->dpm_table.mclk_table.count = 0; - for (i = 0; i < dep_mclk_table->count; i++) { - if (i == 0 || data->dpm_table.mclk_table.dpm_levels - [data->dpm_table.mclk_table.count - 1].value != - dep_mclk_table->entries[i].clk) { - data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = - dep_mclk_table->entries[i].clk; - data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = - (i == 0) ? true : false; - data->dpm_table.mclk_table.count++; - } - } - - if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) - hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk; - return 0; -} - -static int smu7_odn_initial_default_setting(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i; - - struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; - struct phm_odn_performance_level *entries; - - if (table_info == NULL) - return -EINVAL; - - dep_sclk_table = table_info->vdd_dep_on_sclk; - dep_mclk_table = table_info->vdd_dep_on_mclk; - - odn_table->odn_core_clock_dpm_levels.num_of_pl = - data->golden_dpm_table.sclk_table.count; - entries = odn_table->odn_core_clock_dpm_levels.entries; - for (i=0; igolden_dpm_table.sclk_table.count; i++) { - entries[i].clock = data->golden_dpm_table.sclk_table.dpm_levels[i].value; - entries[i].enabled = true; - entries[i].vddc = dep_sclk_table->entries[i].vddc; - } - - smu_get_voltage_dependency_table_ppt_v1(dep_sclk_table, - (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk)); - - odn_table->odn_memory_clock_dpm_levels.num_of_pl = - data->golden_dpm_table.mclk_table.count; - entries = odn_table->odn_memory_clock_dpm_levels.entries; - for (i=0; igolden_dpm_table.mclk_table.count; i++) { - entries[i].clock = data->golden_dpm_table.mclk_table.dpm_levels[i].value; - entries[i].enabled = true; - entries[i].vddc = dep_mclk_table->entries[i].vddc; - } - - smu_get_voltage_dependency_table_ppt_v1(dep_mclk_table, - (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk)); - - return 0; -} - -static void smu7_setup_voltage_range_from_vbios(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t min_vddc = 0; - uint32_t max_vddc = 0; - - if (!table_info) - return; - - dep_sclk_table = table_info->vdd_dep_on_sclk; - - atomctrl_get_voltage_range(hwmgr, &max_vddc, &min_vddc); - - if (min_vddc == 0 || min_vddc > 2000 - || min_vddc > dep_sclk_table->entries[0].vddc) - min_vddc = dep_sclk_table->entries[0].vddc; - - if (max_vddc == 0 || max_vddc > 2000 - || max_vddc < dep_sclk_table->entries[dep_sclk_table->count-1].vddc) - max_vddc = dep_sclk_table->entries[dep_sclk_table->count-1].vddc; - - data->odn_dpm_table.min_vddc = min_vddc; - data->odn_dpm_table.max_vddc = max_vddc; -} - -static void smu7_check_dpm_table_updated(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i; - - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; - struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; - - if (table_info == NULL) - return; - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - if (odn_table->odn_core_clock_dpm_levels.entries[i].clock != - data->dpm_table.sclk_table.dpm_levels[i].value) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; - break; - } - } - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - if (odn_table->odn_memory_clock_dpm_levels.entries[i].clock != - data->dpm_table.mclk_table.dpm_levels[i].value) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; - break; - } - } - - dep_table = table_info->vdd_dep_on_mclk; - odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_mclk); - - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; - return; - } - } - - dep_table = table_info->vdd_dep_on_sclk; - odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dependency_on_sclk); - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; - return; - } - } - if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { - data->need_update_smu7_dpm_table &= ~DPMTABLE_OD_UPDATE_VDDC; - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; - } -} - -static int smu7_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - smu7_reset_dpm_tables(hwmgr); - - if (hwmgr->pp_table_version == PP_TABLE_V1) - smu7_setup_dpm_tables_v1(hwmgr); - else if (hwmgr->pp_table_version == PP_TABLE_V0) - smu7_setup_dpm_tables_v0(hwmgr); - - smu7_setup_default_pcie_table(hwmgr); - - /* save a copy of the default DPM table */ - memcpy(&(data->golden_dpm_table), &(data->dpm_table), - sizeof(struct smu7_dpm_table)); - - /* initialize ODN table */ - if (hwmgr->od_enabled) { - if (data->odn_dpm_table.max_vddc) { - smu7_check_dpm_table_updated(hwmgr); - } else { - smu7_setup_voltage_range_from_vbios(hwmgr); - smu7_odn_initial_default_setting(hwmgr); - } - } - return 0; -} - -static int smu7_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr) -{ - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_EnableVRHotGPIOInterrupt, - NULL); - - return 0; -} - -static int smu7_enable_sclk_control(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, - SCLK_PWRMGT_OFF, 0); - return 0; -} - -static int smu7_enable_ulv(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->ulv_supported) - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableULV, NULL); - - return 0; -} - -static int smu7_disable_ulv(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->ulv_supported) - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableULV, NULL); - - return 0; -} - -static int smu7_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) -{ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) { - if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MASTER_DeepSleep_ON, NULL)) - PP_ASSERT_WITH_CODE(false, - "Attempt to enable Master Deep Sleep switch failed!", - return -EINVAL); - } else { - if (smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_MASTER_DeepSleep_OFF, - NULL)) { - PP_ASSERT_WITH_CODE(false, - "Attempt to disable Master Deep Sleep switch failed!", - return -EINVAL); - } - } - - return 0; -} - -static int smu7_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) -{ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) { - if (smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_MASTER_DeepSleep_OFF, - NULL)) { - PP_ASSERT_WITH_CODE(false, - "Attempt to disable Master Deep Sleep switch failed!", - return -EINVAL); - } - } - - return 0; -} - -static int smu7_disable_sclk_vce_handshake(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t soft_register_value = 0; - uint32_t handshake_disables_offset = data->soft_regs_start - + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, HandshakeDisables); - - soft_register_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, handshake_disables_offset); - soft_register_value |= SMU7_VCE_SCLK_HANDSHAKE_DISABLE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - handshake_disables_offset, soft_register_value); - return 0; -} - -static int smu7_disable_handshake_uvd(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t soft_register_value = 0; - uint32_t handshake_disables_offset = data->soft_regs_start - + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, HandshakeDisables); - - soft_register_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, handshake_disables_offset); - soft_register_value |= smum_get_mac_definition(hwmgr, - SMU_UVD_MCLK_HANDSHAKE_DISABLE); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - handshake_disables_offset, soft_register_value); - return 0; -} - -static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /* enable SCLK dpm */ - if (!data->sclk_dpm_key_disabled) { - if (hwmgr->chip_id == CHIP_VEGAM) - smu7_disable_sclk_vce_handshake(hwmgr); - - PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Enable, NULL)), - "Failed to enable SCLK DPM during DPM Start Function!", - return -EINVAL); - } - - /* enable MCLK dpm */ - if (0 == data->mclk_dpm_key_disabled) { - if (!(hwmgr->feature_mask & PP_UVD_HANDSHAKE_MASK)) - smu7_disable_handshake_uvd(hwmgr); - - PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_MCLKDPM_Enable, - NULL)), - "Failed to enable MCLK DPM during DPM Start Function!", - return -EINVAL); - - if (hwmgr->chip_family != CHIP_VEGAM) - PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); - - - if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x100005); - udelay(10); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d30, 0x400005); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d3c, 0x400005); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, 0xc0400d80, 0x500005); - } else { - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x5); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x100005); - udelay(10); - if (hwmgr->chip_id == CHIP_VEGAM) { - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400009); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400009); - } else { - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC0_CNTL, 0x400005); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_MC1_CNTL, 0x400005); - } - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixLCAC_CPL_CNTL, 0x500005); - } - } - - return 0; -} - -static int smu7_start_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /*enable general power management */ - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, - GLOBAL_PWRMGT_EN, 1); - - /* enable sclk deep sleep */ - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, - DYNAMIC_PM_EN, 1); - - /* prepare for PCIE DPM */ - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, SMU_SoftRegisters, - VoltageChangeTimeout), 0x1000); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, - SWRST_COMMAND_1, RESETLC, 0x0); - - if (hwmgr->chip_family == AMDGPU_FAMILY_CI) - cgs_write_register(hwmgr->device, 0x1488, - (cgs_read_register(hwmgr->device, 0x1488) & ~0x1)); - - if (smu7_enable_sclk_mclk_dpm(hwmgr)) { - pr_err("Failed to enable Sclk DPM and Mclk DPM!"); - return -EINVAL; - } - - /* enable PCIE dpm */ - if (0 == data->pcie_dpm_key_disabled) { - PP_ASSERT_WITH_CODE( - (0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_PCIeDPM_Enable, - NULL)), - "Failed to enable pcie DPM during DPM Start Function!", - return -EINVAL); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition)) { - PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_EnableACDCGPIOInterrupt, - NULL)), - "Failed to enable AC DC GPIO Interrupt!", - ); - } - - return 0; -} - -static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /* disable SCLK dpm */ - if (!data->sclk_dpm_key_disabled) { - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to disable SCLK DPM when DPM is disabled", - return 0); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DPM_Disable, NULL); - } - - /* disable MCLK dpm */ - if (!data->mclk_dpm_key_disabled) { - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to disable MCLK DPM when DPM is disabled", - return 0); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_Disable, NULL); - } - - return 0; -} - -static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /* disable general power management */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, - GLOBAL_PWRMGT_EN, 0); - /* disable sclk deep sleep */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, - DYNAMIC_PM_EN, 0); - - /* disable PCIE dpm */ - if (!data->pcie_dpm_key_disabled) { - PP_ASSERT_WITH_CODE( - (smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_PCIeDPM_Disable, - NULL) == 0), - "Failed to disable pcie DPM during DPM Stop Function!", - return -EINVAL); - } - - smu7_disable_sclk_mclk_dpm(hwmgr); - - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to disable voltage DPM when DPM is disabled", - return 0); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Voltage_Cntl_Disable, NULL); - - return 0; -} - -static void smu7_set_dpm_event_sources(struct pp_hwmgr *hwmgr, uint32_t sources) -{ - bool protection; - enum DPM_EVENT_SRC src; - - switch (sources) { - default: - pr_err("Unknown throttling event sources."); - fallthrough; - case 0: - protection = false; - /* src is unused */ - break; - case (1 << PHM_AutoThrottleSource_Thermal): - protection = true; - src = DPM_EVENT_SRC_DIGITAL; - break; - case (1 << PHM_AutoThrottleSource_External): - protection = true; - src = DPM_EVENT_SRC_EXTERNAL; - break; - case (1 << PHM_AutoThrottleSource_External) | - (1 << PHM_AutoThrottleSource_Thermal): - protection = true; - src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL; - break; - } - /* Order matters - don't enable thermal protection for the wrong source. */ - if (protection) { - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, - DPM_EVENT_SRC, src); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, - THERMAL_PROTECTION_DIS, - !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController)); - } else - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, - THERMAL_PROTECTION_DIS, 1); -} - -static int smu7_enable_auto_throttle_source(struct pp_hwmgr *hwmgr, - PHM_AutoThrottleSource source) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (!(data->active_auto_throttle_sources & (1 << source))) { - data->active_auto_throttle_sources |= 1 << source; - smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); - } - return 0; -} - -static int smu7_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) -{ - return smu7_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); -} - -static int smu7_disable_auto_throttle_source(struct pp_hwmgr *hwmgr, - PHM_AutoThrottleSource source) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->active_auto_throttle_sources & (1 << source)) { - data->active_auto_throttle_sources &= ~(1 << source); - smu7_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); - } - return 0; -} - -static int smu7_disable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) -{ - return smu7_disable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); -} - -static int smu7_pcie_performance_request(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - data->pcie_performance_request = true; - - return 0; -} - -static int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int tmp_result = 0; - int result = 0; - - if (smu7_voltage_control(hwmgr)) { - tmp_result = smu7_enable_voltage_control(hwmgr); - PP_ASSERT_WITH_CODE(tmp_result == 0, - "Failed to enable voltage control!", - result = tmp_result); - - tmp_result = smu7_construct_voltage_tables(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to construct voltage tables!", - result = tmp_result); - } - smum_initialize_mc_reg_table(hwmgr); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController)) - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0); - - tmp_result = smu7_program_static_screen_threshold_parameters(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to program static screen threshold parameters!", - result = tmp_result); - - tmp_result = smu7_enable_display_gap(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable display gap!", result = tmp_result); - - tmp_result = smu7_program_voting_clients(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to program voting clients!", result = tmp_result); - - tmp_result = smum_process_firmware_header(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to process firmware header!", result = tmp_result); - - if (hwmgr->chip_id != CHIP_VEGAM) { - tmp_result = smu7_initial_switch_from_arbf0_to_f1(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to initialize switch from ArbF0 to F1!", - result = tmp_result); - } - - result = smu7_setup_default_dpm_tables(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to setup default DPM tables!", return result); - - tmp_result = smum_init_smc_table(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to initialize SMC table!", result = tmp_result); - - tmp_result = smu7_enable_vrhot_gpio_interrupt(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable VR hot GPIO interrupt!", result = tmp_result); - - smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_NoDisplay, NULL); - - tmp_result = smu7_enable_sclk_control(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable SCLK control!", result = tmp_result); - - tmp_result = smu7_enable_smc_voltage_controller(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable voltage control!", result = tmp_result); - - tmp_result = smu7_enable_ulv(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable ULV!", result = tmp_result); - - tmp_result = smu7_enable_deep_sleep_master_switch(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable deep sleep master switch!", result = tmp_result); - - tmp_result = smu7_enable_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to enable deep sleep master switch!", result = tmp_result); - - tmp_result = smu7_start_dpm(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to start DPM!", result = tmp_result); - - tmp_result = smu7_enable_smc_cac(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable SMC CAC!", result = tmp_result); - - tmp_result = smu7_enable_power_containment(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable power containment!", result = tmp_result); - - tmp_result = smu7_power_control_set_level(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to power control set level!", result = tmp_result); - - tmp_result = smu7_enable_thermal_auto_throttle(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable thermal auto throttle!", result = tmp_result); - - tmp_result = smu7_pcie_performance_request(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "pcie performance request failed!", result = tmp_result); - - return 0; -} - -static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) -{ - if (!hwmgr->avfs_supported) - return 0; - - if (enable) { - if (!PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( - hwmgr, PPSMC_MSG_EnableAvfs, NULL), - "Failed to enable AVFS!", - return -EINVAL); - } - } else if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc( - hwmgr, PPSMC_MSG_DisableAvfs, NULL), - "Failed to disable AVFS!", - return -EINVAL); - } - - return 0; -} - -static int smu7_update_avfs(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (!hwmgr->avfs_supported) - return 0; - - if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { - smu7_avfs_control(hwmgr, false); - } else if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { - smu7_avfs_control(hwmgr, false); - smu7_avfs_control(hwmgr, true); - } else { - smu7_avfs_control(hwmgr, true); - } - - return 0; -} - -static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int tmp_result, result = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalController)) - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 1); - - tmp_result = smu7_disable_power_containment(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable power containment!", result = tmp_result); - - tmp_result = smu7_disable_smc_cac(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable SMC CAC!", result = tmp_result); - - tmp_result = smu7_disable_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable DIDT!", result = tmp_result); - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_SPLL_SPREAD_SPECTRUM, SSEN, 0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 0); - - tmp_result = smu7_disable_thermal_auto_throttle(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable thermal auto throttle!", result = tmp_result); - - tmp_result = smu7_avfs_control(hwmgr, false); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable AVFS!", result = tmp_result); - - tmp_result = smu7_stop_dpm(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to stop DPM!", result = tmp_result); - - tmp_result = smu7_disable_deep_sleep_master_switch(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable deep sleep master switch!", result = tmp_result); - - tmp_result = smu7_disable_ulv(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable ULV!", result = tmp_result); - - tmp_result = smu7_clear_voting_clients(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to clear voting clients!", result = tmp_result); - - tmp_result = smu7_reset_to_default(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to reset to default!", result = tmp_result); - - tmp_result = smu7_force_switch_to_arbf0(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to force to switch arbf0!", result = tmp_result); - - return result; -} - -static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct amdgpu_device *adev = hwmgr->adev; - - data->dll_default_on = false; - data->mclk_dpm0_activity_target = 0xa; - data->vddc_vddgfx_delta = 300; - data->static_screen_threshold = SMU7_STATICSCREENTHRESHOLD_DFLT; - data->static_screen_threshold_unit = SMU7_STATICSCREENTHRESHOLDUNIT_DFLT; - data->voting_rights_clients[0] = SMU7_VOTINGRIGHTSCLIENTS_DFLT0; - data->voting_rights_clients[1]= SMU7_VOTINGRIGHTSCLIENTS_DFLT1; - data->voting_rights_clients[2] = SMU7_VOTINGRIGHTSCLIENTS_DFLT2; - data->voting_rights_clients[3]= SMU7_VOTINGRIGHTSCLIENTS_DFLT3; - data->voting_rights_clients[4]= SMU7_VOTINGRIGHTSCLIENTS_DFLT4; - data->voting_rights_clients[5]= SMU7_VOTINGRIGHTSCLIENTS_DFLT5; - data->voting_rights_clients[6]= SMU7_VOTINGRIGHTSCLIENTS_DFLT6; - data->voting_rights_clients[7]= SMU7_VOTINGRIGHTSCLIENTS_DFLT7; - - data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; - data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; - data->pcie_dpm_key_disabled = hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; - /* need to set voltage control types before EVV patching */ - data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE; - data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE; - data->mvdd_control = SMU7_VOLTAGE_CONTROL_NONE; - data->enable_tdc_limit_feature = true; - data->enable_pkg_pwr_tracking_feature = true; - data->force_pcie_gen = PP_PCIEGenInvalid; - data->ulv_supported = hwmgr->feature_mask & PP_ULV_MASK ? true : false; - data->current_profile_setting.bupdate_sclk = 1; - data->current_profile_setting.sclk_up_hyst = 0; - data->current_profile_setting.sclk_down_hyst = 100; - data->current_profile_setting.sclk_activity = SMU7_SCLK_TARGETACTIVITY_DFLT; - data->current_profile_setting.bupdate_mclk = 1; - data->current_profile_setting.mclk_up_hyst = 0; - data->current_profile_setting.mclk_down_hyst = 100; - data->current_profile_setting.mclk_activity = SMU7_MCLK_TARGETACTIVITY_DFLT; - hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D]; - hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D; - - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) { - uint8_t tmp1, tmp2; - uint16_t tmp3 = 0; - atomctrl_get_svi2_info(hwmgr, VOLTAGE_TYPE_VDDC, &tmp1, &tmp2, - &tmp3); - tmp3 = (tmp3 >> 5) & 0x3; - data->vddc_phase_shed_control = ((tmp3 << 1) | (tmp3 >> 1)) & 0x3; - } else if (hwmgr->chip_family == AMDGPU_FAMILY_CI) { - data->vddc_phase_shed_control = 1; - } else { - data->vddc_phase_shed_control = 0; - } - - if (hwmgr->chip_id == CHIP_HAWAII) { - data->thermal_temp_setting.temperature_low = 94500; - data->thermal_temp_setting.temperature_high = 95000; - data->thermal_temp_setting.temperature_shutdown = 104000; - } else { - data->thermal_temp_setting.temperature_low = 99500; - data->thermal_temp_setting.temperature_high = 100000; - data->thermal_temp_setting.temperature_shutdown = 104000; - } - - data->fast_watermark_threshold = 100; - if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) - data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; - else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_GPIO_LUT)) - data->voltage_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDGFX)) { - if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) { - data->vdd_gfx_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; - } - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableMVDDControl)) { - if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) - data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; - else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) - data->mvdd_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDGFX); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI)) { - if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) - data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_GPIO; - else if (atomctrl_is_voltage_controlled_by_gpio_v3(hwmgr, - VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) - data->vddci_control = SMU7_VOLTAGE_CONTROL_BY_SVID2; - } - - if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableMVDDControl); - - if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI); - - if ((hwmgr->pp_table_version != PP_TABLE_V0) && (hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK) - && (table_info->cac_dtp_table->usClockStretchAmount != 0)) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - - data->pcie_gen_performance.max = PP_PCIEGen1; - data->pcie_gen_performance.min = PP_PCIEGen3; - data->pcie_gen_power_saving.max = PP_PCIEGen1; - data->pcie_gen_power_saving.min = PP_PCIEGen3; - data->pcie_lane_performance.max = 0; - data->pcie_lane_performance.min = 16; - data->pcie_lane_power_saving.max = 0; - data->pcie_lane_power_saving.min = 16; - - - if (adev->pg_flags & AMD_PG_SUPPORT_UVD) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - if (adev->pg_flags & AMD_PG_SUPPORT_VCE) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); -} - -/** -* Get Leakage VDDC based on leakage ID. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t vv_id; - uint16_t vddc = 0; - uint16_t vddgfx = 0; - uint16_t i, j; - uint32_t sclk = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; - - - for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { - vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - if ((hwmgr->pp_table_version == PP_TABLE_V1) - && !phm_get_sclk_for_voltage_evv(hwmgr, - table_info->vddgfx_lookup_table, vv_id, &sclk)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - sclk_table = table_info->vdd_dep_on_sclk; - - for (j = 1; j < sclk_table->count; j++) { - if (sclk_table->entries[j].clk == sclk && - sclk_table->entries[j].cks_enable == 0) { - sclk += 5000; - break; - } - } - } - if (0 == atomctrl_get_voltage_evv_on_sclk - (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk, - vv_id, &vddgfx)) { - /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */ - PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -EINVAL); - - /* the voltage should not be zero nor equal to leakage ID */ - if (vddgfx != 0 && vddgfx != vv_id) { - data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx; - data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = vv_id; - data->vddcgfx_leakage.count++; - } - } else { - pr_info("Error retrieving EVV voltage value!\n"); - } - } - } else { - if ((hwmgr->pp_table_version == PP_TABLE_V0) - || !phm_get_sclk_for_voltage_evv(hwmgr, - table_info->vddc_lookup_table, vv_id, &sclk)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - if (table_info == NULL) - return -EINVAL; - sclk_table = table_info->vdd_dep_on_sclk; - - for (j = 1; j < sclk_table->count; j++) { - if (sclk_table->entries[j].clk == sclk && - sclk_table->entries[j].cks_enable == 0) { - sclk += 5000; - break; - } - } - } - - if (phm_get_voltage_evv_on_sclk(hwmgr, - VOLTAGE_TYPE_VDDC, - sclk, vv_id, &vddc) == 0) { - if (vddc >= 2000 || vddc == 0) - return -EINVAL; - } else { - pr_debug("failed to retrieving EVV voltage!\n"); - continue; - } - - /* the voltage should not be zero nor equal to leakage ID */ - if (vddc != 0 && vddc != vv_id) { - data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc); - data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; - data->vddc_leakage.count++; - } - } - } - } - - return 0; -} - -/** - * Change virtual leakage voltage to actual value. - * - * @param hwmgr the address of the powerplay hardware manager. - * @param pointer to changing voltage - * @param pointer to leakage table - */ -static void smu7_patch_ppt_v1_with_vdd_leakage(struct pp_hwmgr *hwmgr, - uint16_t *voltage, struct smu7_leakage_voltage *leakage_table) -{ - uint32_t index; - - /* search for leakage voltage ID 0xff01 ~ 0xff08 */ - for (index = 0; index < leakage_table->count; index++) { - /* if this voltage matches a leakage voltage ID */ - /* patch with actual leakage voltage */ - if (leakage_table->leakage_id[index] == *voltage) { - *voltage = leakage_table->actual_voltage[index]; - break; - } - } - - if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) - pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); -} - -/** -* Patch voltage lookup table by EVV leakages. -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pointer to voltage lookup table -* @param pointer to leakage table -* @return always 0 -*/ -static int smu7_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table *lookup_table, - struct smu7_leakage_voltage *leakage_table) -{ - uint32_t i; - - for (i = 0; i < lookup_table->count; i++) - smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, - &lookup_table->entries[i].us_vdd, leakage_table); - - return 0; -} - -static int smu7_patch_clock_voltage_limits_with_vddc_leakage( - struct pp_hwmgr *hwmgr, struct smu7_leakage_voltage *leakage_table, - uint16_t *vddc) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = - table_info->max_clock_voltage_on_dc.vddc; - return 0; -} - -static int smu7_patch_voltage_dependency_tables_with_lookup_table( - struct pp_hwmgr *hwmgr) -{ - uint8_t entry_id; - uint8_t voltage_id; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = - table_info->vdd_dep_on_mclk; - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { - voltage_id = sclk_table->entries[entry_id].vddInd; - sclk_table->entries[entry_id].vddgfx = - table_info->vddgfx_lookup_table->entries[voltage_id].us_vdd; - } - } else { - for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { - voltage_id = sclk_table->entries[entry_id].vddInd; - sclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - } - - for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { - voltage_id = mclk_table->entries[entry_id].vddInd; - mclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { - voltage_id = mm_table->entries[entry_id].vddcInd; - mm_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - return 0; - -} - -static int phm_add_voltage(struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table *look_up_table, - phm_ppt_v1_voltage_lookup_record *record) -{ - uint32_t i; - - PP_ASSERT_WITH_CODE((NULL != look_up_table), - "Lookup Table empty.", return -EINVAL); - PP_ASSERT_WITH_CODE((0 != look_up_table->count), - "Lookup Table empty.", return -EINVAL); - - i = smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_VDDGFX); - PP_ASSERT_WITH_CODE((i >= look_up_table->count), - "Lookup Table is full.", return -EINVAL); - - /* This is to avoid entering duplicate calculated records. */ - for (i = 0; i < look_up_table->count; i++) { - if (look_up_table->entries[i].us_vdd == record->us_vdd) { - if (look_up_table->entries[i].us_calculated == 1) - return 0; - break; - } - } - - look_up_table->entries[i].us_calculated = 1; - look_up_table->entries[i].us_vdd = record->us_vdd; - look_up_table->entries[i].us_cac_low = record->us_cac_low; - look_up_table->entries[i].us_cac_mid = record->us_cac_mid; - look_up_table->entries[i].us_cac_high = record->us_cac_high; - /* Only increment the count when we're appending, not replacing duplicate entry. */ - if (i == look_up_table->count) - look_up_table->count++; - - return 0; -} - - -static int smu7_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr) -{ - uint8_t entry_id; - struct phm_ppt_v1_voltage_lookup_record v_record; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - - phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; - phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk; - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - for (entry_id = 0; entry_id < sclk_table->count; ++entry_id) { - if (sclk_table->entries[entry_id].vdd_offset & (1 << 15)) - v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + - sclk_table->entries[entry_id].vdd_offset - 0xFFFF; - else - v_record.us_vdd = sclk_table->entries[entry_id].vddgfx + - sclk_table->entries[entry_id].vdd_offset; - - sclk_table->entries[entry_id].vddc = - v_record.us_cac_low = v_record.us_cac_mid = - v_record.us_cac_high = v_record.us_vdd; - - phm_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record); - } - - for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { - if (mclk_table->entries[entry_id].vdd_offset & (1 << 15)) - v_record.us_vdd = mclk_table->entries[entry_id].vddc + - mclk_table->entries[entry_id].vdd_offset - 0xFFFF; - else - v_record.us_vdd = mclk_table->entries[entry_id].vddc + - mclk_table->entries[entry_id].vdd_offset; - - mclk_table->entries[entry_id].vddgfx = v_record.us_cac_low = - v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; - phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); - } - } - return 0; -} - -static int smu7_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr) -{ - uint8_t entry_id; - struct phm_ppt_v1_voltage_lookup_record v_record; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - for (entry_id = 0; entry_id < mm_table->count; entry_id++) { - if (mm_table->entries[entry_id].vddgfx_offset & (1 << 15)) - v_record.us_vdd = mm_table->entries[entry_id].vddc + - mm_table->entries[entry_id].vddgfx_offset - 0xFFFF; - else - v_record.us_vdd = mm_table->entries[entry_id].vddc + - mm_table->entries[entry_id].vddgfx_offset; - - /* Add the calculated VDDGFX to the VDDGFX lookup table */ - mm_table->entries[entry_id].vddgfx = v_record.us_cac_low = - v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; - phm_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); - } - } - return 0; -} - -static int smu7_sort_lookup_table(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_voltage_lookup_table *lookup_table) -{ - uint32_t table_size, i, j; - table_size = lookup_table->count; - - PP_ASSERT_WITH_CODE(0 != lookup_table->count, - "Lookup table is empty", return -EINVAL); - - /* Sorting voltages */ - for (i = 0; i < table_size - 1; i++) { - for (j = i + 1; j > 0; j--) { - if (lookup_table->entries[j].us_vdd < - lookup_table->entries[j - 1].us_vdd) { - swap(lookup_table->entries[j - 1], - lookup_table->entries[j]); - } - } - } - - return 0; -} - -static int smu7_complete_dependency_tables(struct pp_hwmgr *hwmgr) -{ - int result = 0; - int tmp_result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, - table_info->vddgfx_lookup_table, &(data->vddcgfx_leakage)); - if (tmp_result != 0) - result = tmp_result; - - smu7_patch_ppt_v1_with_vdd_leakage(hwmgr, - &table_info->max_clock_voltage_on_dc.vddgfx, &(data->vddcgfx_leakage)); - } else { - - tmp_result = smu7_patch_lookup_table_with_leakage(hwmgr, - table_info->vddc_lookup_table, &(data->vddc_leakage)); - if (tmp_result) - result = tmp_result; - - tmp_result = smu7_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, - &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); - if (tmp_result) - result = tmp_result; - } - - tmp_result = smu7_patch_voltage_dependency_tables_with_lookup_table(hwmgr); - if (tmp_result) - result = tmp_result; - - tmp_result = smu7_calc_voltage_dependency_tables(hwmgr); - if (tmp_result) - result = tmp_result; - - tmp_result = smu7_calc_mm_voltage_dependency_table(hwmgr); - if (tmp_result) - result = tmp_result; - - tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddgfx_lookup_table); - if (tmp_result) - result = tmp_result; - - tmp_result = smu7_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); - if (tmp_result) - result = tmp_result; - - return result; -} - -static int smu7_set_private_data_based_on_pptable_v1(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = - table_info->vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = - table_info->vdd_dep_on_mclk; - - PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL, - "VDD dependency on SCLK table is missing.", - return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, - "VDD dependency on SCLK table has to have is missing.", - return -EINVAL); - - PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL, - "VDD dependency on MCLK table is missing", - return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, - "VDD dependency on MCLK table has to have is missing.", - return -EINVAL); - - table_info->max_clock_voltage_on_ac.sclk = - allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; - table_info->max_clock_voltage_on_ac.mclk = - allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; - table_info->max_clock_voltage_on_ac.vddc = - allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; - table_info->max_clock_voltage_on_ac.vddci = - allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; - - hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = table_info->max_clock_voltage_on_ac.sclk; - hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = table_info->max_clock_voltage_on_ac.mclk; - hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = table_info->max_clock_voltage_on_ac.vddc; - hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = table_info->max_clock_voltage_on_ac.vddci; - - return 0; -} - -static int smu7_patch_voltage_workaround(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; - struct phm_ppt_v1_voltage_lookup_table *lookup_table; - uint32_t i; - uint32_t hw_revision, sub_vendor_id, sub_sys_id; - struct amdgpu_device *adev = hwmgr->adev; - - if (table_info != NULL) { - dep_mclk_table = table_info->vdd_dep_on_mclk; - lookup_table = table_info->vddc_lookup_table; - } else - return 0; - - hw_revision = adev->pdev->revision; - sub_sys_id = adev->pdev->subsystem_device; - sub_vendor_id = adev->pdev->subsystem_vendor; - - if (hwmgr->chip_id == CHIP_POLARIS10 && hw_revision == 0xC7 && - ((sub_sys_id == 0xb37 && sub_vendor_id == 0x1002) || - (sub_sys_id == 0x4a8 && sub_vendor_id == 0x1043) || - (sub_sys_id == 0x9480 && sub_vendor_id == 0x1682))) { - if (lookup_table->entries[dep_mclk_table->entries[dep_mclk_table->count-1].vddInd].us_vdd >= 1000) - return 0; - - for (i = 0; i < lookup_table->count; i++) { - if (lookup_table->entries[i].us_vdd < 0xff01 && lookup_table->entries[i].us_vdd >= 1000) { - dep_mclk_table->entries[dep_mclk_table->count-1].vddInd = (uint8_t) i; - return 0; - } - } - } - return 0; -} - -static int smu7_thermal_parameter_init(struct pp_hwmgr *hwmgr) -{ - struct pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; - uint32_t temp_reg; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { - temp_reg = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL); - switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) { - case 0: - temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1); - break; - case 1: - temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2); - break; - case 2: - temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, GNB_SLOW, 0x1); - break; - case 3: - temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1); - break; - case 4: - temp_reg = PHM_SET_FIELD(temp_reg, CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1); - break; - default: - break; - } - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL, temp_reg); - } - - if (table_info == NULL) - return 0; - - if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp != 0 && - hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode) { - hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit = - (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMaxLimit = - (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMStep = 1; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = 100; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMinLimit = - (uint16_t)hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit; - - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMStep = 1; - - table_info->cac_dtp_table->usDefaultTargetOperatingTemp = (table_info->cac_dtp_table->usDefaultTargetOperatingTemp >= 50) ? - (table_info->cac_dtp_table->usDefaultTargetOperatingTemp - 50) : 0; - - table_info->cac_dtp_table->usOperatingTempMaxLimit = table_info->cac_dtp_table->usDefaultTargetOperatingTemp; - table_info->cac_dtp_table->usOperatingTempStep = 1; - table_info->cac_dtp_table->usOperatingTempHyst = 1; - - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; - - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM; - - hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit = - table_info->cac_dtp_table->usOperatingTempMinLimit; - - hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit = - table_info->cac_dtp_table->usOperatingTempMaxLimit; - - hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = - table_info->cac_dtp_table->usDefaultTargetOperatingTemp; - - hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep = - table_info->cac_dtp_table->usOperatingTempStep; - - hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp = - table_info->cac_dtp_table->usTargetOperatingTemp; - if (hwmgr->feature_mask & PP_OD_FUZZY_FAN_CONTROL_MASK) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODFuzzyFanControlSupport); - } - - return 0; -} - -/** - * Change virtual leakage voltage to actual value. - * - * @param hwmgr the address of the powerplay hardware manager. - * @param pointer to changing voltage - * @param pointer to leakage table - */ -static void smu7_patch_ppt_v0_with_vdd_leakage(struct pp_hwmgr *hwmgr, - uint32_t *voltage, struct smu7_leakage_voltage *leakage_table) -{ - uint32_t index; - - /* search for leakage voltage ID 0xff01 ~ 0xff08 */ - for (index = 0; index < leakage_table->count; index++) { - /* if this voltage matches a leakage voltage ID */ - /* patch with actual leakage voltage */ - if (leakage_table->leakage_id[index] == *voltage) { - *voltage = leakage_table->actual_voltage[index]; - break; - } - } - - if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) - pr_err("Voltage value looks like a Leakage ID but it's not patched \n"); -} - - -static int smu7_patch_vddc(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddc_leakage); - - return 0; -} - -static int smu7_patch_vddci(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddci_leakage); - - return 0; -} - -static int smu7_patch_vce_vddc(struct pp_hwmgr *hwmgr, - struct phm_vce_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddc_leakage); - - return 0; -} - - -static int smu7_patch_uvd_vddc(struct pp_hwmgr *hwmgr, - struct phm_uvd_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddc_leakage); - - return 0; -} - -static int smu7_patch_vddc_shed_limit(struct pp_hwmgr *hwmgr, - struct phm_phase_shedding_limits_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].Voltage, - &data->vddc_leakage); - - return 0; -} - -static int smu7_patch_samu_vddc(struct pp_hwmgr *hwmgr, - struct phm_samu_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddc_leakage); - - return 0; -} - -static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr, - struct phm_acp_clock_voltage_dependency_table *tab) -{ - uint16_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) - for (i = 0; i < tab->count; i++) - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &tab->entries[i].v, - &data->vddc_leakage); - - return 0; -} - -static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *tab) -{ - uint32_t vddc, vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) { - vddc = tab->vddc; - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, - &data->vddc_leakage); - tab->vddc = vddc; - vddci = tab->vddci; - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci, - &data->vddci_leakage); - tab->vddci = vddci; - } - - return 0; -} - -static int smu7_patch_cac_vddc(struct pp_hwmgr *hwmgr, struct phm_cac_leakage_table *tab) -{ - uint32_t i; - uint32_t vddc; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (tab) { - for (i = 0; i < tab->count; i++) { - vddc = (uint32_t)(tab->entries[i].Vddc); - smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, &data->vddc_leakage); - tab->entries[i].Vddc = (uint16_t)vddc; - } - } - - return 0; -} - -static int smu7_patch_dependency_tables_with_leakage(struct pp_hwmgr *hwmgr) -{ - int tmp; - - tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_sclk); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dependency_on_mclk); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_vddc(hwmgr, hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_vddci(hwmgr, hwmgr->dyn_state.vddci_dependency_on_mclk); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_vce_vddc(hwmgr, hwmgr->dyn_state.vce_clock_voltage_dependency_table); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_uvd_vddc(hwmgr, hwmgr->dyn_state.uvd_clock_voltage_dependency_table); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_samu_vddc(hwmgr, hwmgr->dyn_state.samu_clock_voltage_dependency_table); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_acp_vddc(hwmgr, hwmgr->dyn_state.acp_clock_voltage_dependency_table); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_vddc_shed_limit(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_ac); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_limits_vddc(hwmgr, &hwmgr->dyn_state.max_clock_voltage_on_dc); - if (tmp) - return -EINVAL; - - tmp = smu7_patch_cac_vddc(hwmgr, hwmgr->dyn_state.cac_leakage_table); - if (tmp) - return -EINVAL; - - return 0; -} - - -static int smu7_set_private_data_based_on_pptable_v0(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - struct phm_clock_voltage_dependency_table *allowed_sclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_sclk; - struct phm_clock_voltage_dependency_table *allowed_mclk_vddc_table = hwmgr->dyn_state.vddc_dependency_on_mclk; - struct phm_clock_voltage_dependency_table *allowed_mclk_vddci_table = hwmgr->dyn_state.vddci_dependency_on_mclk; - - PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table != NULL, - "VDDC dependency on SCLK table is missing. This table is mandatory", - return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_sclk_vddc_table->count >= 1, - "VDDC dependency on SCLK table has to have is missing. This table is mandatory", - return -EINVAL); - - PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table != NULL, - "VDDC dependency on MCLK table is missing. This table is mandatory", - return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_mclk_vddc_table->count >= 1, - "VDD dependency on MCLK table has to have is missing. This table is mandatory", - return -EINVAL); - - data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[0].v; - data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; - - hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = - allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].clk; - hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = - allowed_mclk_vddc_table->entries[allowed_mclk_vddc_table->count - 1].clk; - hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = - allowed_sclk_vddc_table->entries[allowed_sclk_vddc_table->count - 1].v; - - if (allowed_mclk_vddci_table != NULL && allowed_mclk_vddci_table->count >= 1) { - data->min_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[0].v; - data->max_vddci_in_pptable = (uint16_t)allowed_mclk_vddci_table->entries[allowed_mclk_vddci_table->count - 1].v; - } - - if (hwmgr->dyn_state.vddci_dependency_on_mclk != NULL && hwmgr->dyn_state.vddci_dependency_on_mclk->count >= 1) - hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = hwmgr->dyn_state.vddci_dependency_on_mclk->entries[hwmgr->dyn_state.vddci_dependency_on_mclk->count - 1].v; - - return 0; -} - -static int smu7_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - kfree(hwmgr->backend); - hwmgr->backend = NULL; - - return 0; -} - -static int smu7_get_elb_voltages(struct pp_hwmgr *hwmgr) -{ - uint16_t virtual_voltage_id, vddc, vddci, efuse_voltage_id; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int i; - - if (atomctrl_get_leakage_id_from_efuse(hwmgr, &efuse_voltage_id) == 0) { - for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { - virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; - if (atomctrl_get_leakage_vddc_base_on_leakage(hwmgr, &vddc, &vddci, - virtual_voltage_id, - efuse_voltage_id) == 0) { - if (vddc != 0 && vddc != virtual_voltage_id) { - data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc; - data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id; - data->vddc_leakage.count++; - } - if (vddci != 0 && vddci != virtual_voltage_id) { - data->vddci_leakage.actual_voltage[data->vddci_leakage.count] = vddci; - data->vddci_leakage.leakage_id[data->vddci_leakage.count] = virtual_voltage_id; - data->vddci_leakage.count++; - } - } - } - } - return 0; -} - -static int smu7_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data; - int result = 0; - - data = kzalloc(sizeof(struct smu7_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - smu7_patch_voltage_workaround(hwmgr); - smu7_init_dpm_defaults(hwmgr); - - /* Get leakage voltage based on leakage ID. */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EVV)) { - result = smu7_get_evv_voltages(hwmgr); - if (result) { - pr_info("Get EVV Voltage Failed. Abort Driver loading!\n"); - return -EINVAL; - } - } else { - smu7_get_elb_voltages(hwmgr); - } - - if (hwmgr->pp_table_version == PP_TABLE_V1) { - smu7_complete_dependency_tables(hwmgr); - smu7_set_private_data_based_on_pptable_v1(hwmgr); - } else if (hwmgr->pp_table_version == PP_TABLE_V0) { - smu7_patch_dependency_tables_with_leakage(hwmgr); - smu7_set_private_data_based_on_pptable_v0(hwmgr); - } - - /* Initalize Dynamic State Adjustment Rule Settings */ - result = phm_initializa_dynamic_state_adjustment_rule_settings(hwmgr); - - if (0 == result) { - struct amdgpu_device *adev = hwmgr->adev; - - data->is_tlu_enabled = false; - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = - SMU7_MAX_HARDWARE_POWERLEVELS; - hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; - hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - - data->pcie_gen_cap = adev->pm.pcie_gen_mask; - if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) - data->pcie_spc_cap = 20; - data->pcie_lane_cap = adev->pm.pcie_mlw_mask; - - hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ -/* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ - hwmgr->platform_descriptor.clockStep.engineClock = 500; - hwmgr->platform_descriptor.clockStep.memoryClock = 500; - smu7_thermal_parameter_init(hwmgr); - } else { - /* Ignore return value in here, we are cleaning up a mess. */ - smu7_hwmgr_backend_fini(hwmgr); - } - - return 0; -} - -static int smu7_force_dpm_highest(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t level, tmp; - - if (!data->pcie_dpm_key_disabled) { - if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { - level = 0; - tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask; - while (tmp >>= 1) - level++; - - if (level) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PCIeDPM_ForceLevel, level, - NULL); - } - } - - if (!data->sclk_dpm_key_disabled) { - if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { - level = 0; - tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; - while (tmp >>= 1) - level++; - - if (level) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - (1 << level), - NULL); - } - } - - if (!data->mclk_dpm_key_disabled) { - if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { - level = 0; - tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask; - while (tmp >>= 1) - level++; - - if (level) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_MCLKDPM_SetEnabledMask, - (1 << level), - NULL); - } - } - - return 0; -} - -static int smu7_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (hwmgr->pp_table_version == PP_TABLE_V1) - phm_apply_dal_min_voltage_request(hwmgr); -/* TO DO for v0 iceland and Ci*/ - - if (!data->sclk_dpm_key_disabled) { - if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - data->dpm_level_enable_mask.sclk_dpm_enable_mask, - NULL); - } - - if (!data->mclk_dpm_key_disabled) { - if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_MCLKDPM_SetEnabledMask, - data->dpm_level_enable_mask.mclk_dpm_enable_mask, - NULL); - } - - return 0; -} - -static int smu7_unforce_dpm_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (!smum_is_dpm_running(hwmgr)) - return -EINVAL; - - if (!data->pcie_dpm_key_disabled) { - smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_PCIeDPM_UnForceLevel, - NULL); - } - - return smu7_upload_dpm_level_enable_mask(hwmgr); -} - -static int smu7_force_dpm_lowest(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = - (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t level; - - if (!data->sclk_dpm_key_disabled) - if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { - level = phm_get_lowest_enabled_level(hwmgr, - data->dpm_level_enable_mask.sclk_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - (1 << level), - NULL); - - } - - if (!data->mclk_dpm_key_disabled) { - if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { - level = phm_get_lowest_enabled_level(hwmgr, - data->dpm_level_enable_mask.mclk_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_MCLKDPM_SetEnabledMask, - (1 << level), - NULL); - } - } - - if (!data->pcie_dpm_key_disabled) { - if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { - level = phm_get_lowest_enabled_level(hwmgr, - data->dpm_level_enable_mask.pcie_dpm_enable_mask); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PCIeDPM_ForceLevel, - (level), - NULL); - } - } - - return 0; -} - -static int smu7_get_profiling_clk(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, - uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *pcie_mask) -{ - uint32_t percentage; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *golden_dpm_table = &data->golden_dpm_table; - int32_t tmp_mclk; - int32_t tmp_sclk; - int32_t count; - - if (golden_dpm_table->mclk_table.count < 1) - return -EINVAL; - - percentage = 100 * golden_dpm_table->sclk_table.dpm_levels[golden_dpm_table->sclk_table.count - 1].value / - golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; - - if (golden_dpm_table->mclk_table.count == 1) { - percentage = 70; - tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 1].value; - *mclk_mask = golden_dpm_table->mclk_table.count - 1; - } else { - tmp_mclk = golden_dpm_table->mclk_table.dpm_levels[golden_dpm_table->mclk_table.count - 2].value; - *mclk_mask = golden_dpm_table->mclk_table.count - 2; - } - - tmp_sclk = tmp_mclk * percentage / 100; - - if (hwmgr->pp_table_version == PP_TABLE_V0) { - for (count = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; - count >= 0; count--) { - if (tmp_sclk >= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk) { - tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[count].clk; - *sclk_mask = count; - break; - } - } - if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - tmp_sclk = hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].clk; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - *sclk_mask = hwmgr->dyn_state.vddc_dependency_on_sclk->count-1; - } else if (hwmgr->pp_table_version == PP_TABLE_V1) { - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - for (count = table_info->vdd_dep_on_sclk->count-1; count >= 0; count--) { - if (tmp_sclk >= table_info->vdd_dep_on_sclk->entries[count].clk) { - tmp_sclk = table_info->vdd_dep_on_sclk->entries[count].clk; - *sclk_mask = count; - break; - } - } - if (count < 0 || level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - tmp_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) - *mclk_mask = 0; - else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - *mclk_mask = golden_dpm_table->mclk_table.count - 1; - - *pcie_mask = data->dpm_table.pcie_speed_table.count - 1; - hwmgr->pstate_sclk = tmp_sclk; - hwmgr->pstate_mclk = tmp_mclk; - - return 0; -} - -static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask = 0; - uint32_t mclk_mask = 0; - uint32_t pcie_mask = 0; - - if (hwmgr->pstate_sclk == 0) - smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = smu7_force_dpm_highest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = smu7_force_dpm_lowest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = smu7_unforce_dpm_levels(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = smu7_get_profiling_clk(hwmgr, level, &sclk_mask, &mclk_mask, &pcie_mask); - if (ret) - return ret; - smu7_force_clock_level(hwmgr, PP_SCLK, 1<dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); - } - return ret; -} - -static int smu7_get_power_state_size(struct pp_hwmgr *hwmgr) -{ - return sizeof(struct smu7_power_state); -} - -static int smu7_vblank_too_short(struct pp_hwmgr *hwmgr, - uint32_t vblank_time_us) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t switch_limit_us; - - switch (hwmgr->chip_id) { - case CHIP_POLARIS10: - case CHIP_POLARIS11: - case CHIP_POLARIS12: - if (hwmgr->is_kicker) - switch_limit_us = data->is_memory_gddr5 ? 450 : 150; - else - switch_limit_us = data->is_memory_gddr5 ? 190 : 150; - break; - case CHIP_VEGAM: - switch_limit_us = 30; - break; - default: - switch_limit_us = data->is_memory_gddr5 ? 450 : 150; - break; - } - - if (vblank_time_us < switch_limit_us) - return true; - else - return false; -} - -static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *request_ps, - const struct pp_power_state *current_ps) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct smu7_power_state *smu7_ps = - cast_phw_smu7_power_state(&request_ps->hardware); - uint32_t sclk; - uint32_t mclk; - struct PP_Clocks minimum_clocks = {0}; - bool disable_mclk_switching; - bool disable_mclk_switching_for_frame_lock; - const struct phm_clock_and_voltage_limits *max_limits; - uint32_t i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int32_t count; - int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; - - data->battery_state = (PP_StateUILabel_Battery == - request_ps->classification.ui_label); - - PP_ASSERT_WITH_CODE(smu7_ps->performance_level_count == 2, - "VI should always have 2 performance levels", - ); - - max_limits = adev->pm.ac_power ? - &(hwmgr->dyn_state.max_clock_voltage_on_ac) : - &(hwmgr->dyn_state.max_clock_voltage_on_dc); - - /* Cap clock DPM tables at DC MAX if it is in DC. */ - if (!adev->pm.ac_power) { - for (i = 0; i < smu7_ps->performance_level_count; i++) { - if (smu7_ps->performance_levels[i].memory_clock > max_limits->mclk) - smu7_ps->performance_levels[i].memory_clock = max_limits->mclk; - if (smu7_ps->performance_levels[i].engine_clock > max_limits->sclk) - smu7_ps->performance_levels[i].engine_clock = max_limits->sclk; - } - } - - minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; - minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { - max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); - stable_pstate_sclk = (max_limits->sclk * 75) / 100; - - for (count = table_info->vdd_dep_on_sclk->count - 1; - count >= 0; count--) { - if (stable_pstate_sclk >= - table_info->vdd_dep_on_sclk->entries[count].clk) { - stable_pstate_sclk = - table_info->vdd_dep_on_sclk->entries[count].clk; - break; - } - } - - if (count < 0) - stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; - - stable_pstate_mclk = max_limits->mclk; - - minimum_clocks.engineClock = stable_pstate_sclk; - minimum_clocks.memoryClock = stable_pstate_mclk; - } - - disable_mclk_switching_for_frame_lock = phm_cap_enabled( - hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); - - - if (hwmgr->display_config->num_display == 0) - disable_mclk_switching = false; - else - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && - !hwmgr->display_config->multi_monitor_in_sync) || - disable_mclk_switching_for_frame_lock || - smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); - - sclk = smu7_ps->performance_levels[0].engine_clock; - mclk = smu7_ps->performance_levels[0].memory_clock; - - if (disable_mclk_switching) - mclk = smu7_ps->performance_levels - [smu7_ps->performance_level_count - 1].memory_clock; - - if (sclk < minimum_clocks.engineClock) - sclk = (minimum_clocks.engineClock > max_limits->sclk) ? - max_limits->sclk : minimum_clocks.engineClock; - - if (mclk < minimum_clocks.memoryClock) - mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? - max_limits->mclk : minimum_clocks.memoryClock; - - smu7_ps->performance_levels[0].engine_clock = sclk; - smu7_ps->performance_levels[0].memory_clock = mclk; - - smu7_ps->performance_levels[1].engine_clock = - (smu7_ps->performance_levels[1].engine_clock >= - smu7_ps->performance_levels[0].engine_clock) ? - smu7_ps->performance_levels[1].engine_clock : - smu7_ps->performance_levels[0].engine_clock; - - if (disable_mclk_switching) { - if (mclk < smu7_ps->performance_levels[1].memory_clock) - mclk = smu7_ps->performance_levels[1].memory_clock; - - smu7_ps->performance_levels[0].memory_clock = mclk; - smu7_ps->performance_levels[1].memory_clock = mclk; - } else { - if (smu7_ps->performance_levels[1].memory_clock < - smu7_ps->performance_levels[0].memory_clock) - smu7_ps->performance_levels[1].memory_clock = - smu7_ps->performance_levels[0].memory_clock; - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { - for (i = 0; i < smu7_ps->performance_level_count; i++) { - smu7_ps->performance_levels[i].engine_clock = stable_pstate_sclk; - smu7_ps->performance_levels[i].memory_clock = stable_pstate_mclk; - smu7_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max; - smu7_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max; - } - } - return 0; -} - - -static uint32_t smu7_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct pp_power_state *ps; - struct smu7_power_state *smu7_ps; - - if (hwmgr == NULL) - return -EINVAL; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - smu7_ps = cast_phw_smu7_power_state(&ps->hardware); - - if (low) - return smu7_ps->performance_levels[0].memory_clock; - else - return smu7_ps->performance_levels - [smu7_ps->performance_level_count-1].memory_clock; -} - -static uint32_t smu7_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct pp_power_state *ps; - struct smu7_power_state *smu7_ps; - - if (hwmgr == NULL) - return -EINVAL; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - smu7_ps = cast_phw_smu7_power_state(&ps->hardware); - - if (low) - return smu7_ps->performance_levels[0].engine_clock; - else - return smu7_ps->performance_levels - [smu7_ps->performance_level_count-1].engine_clock; -} - -static int smu7_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_power_state *ps = (struct smu7_power_state *)hw_ps; - ATOM_FIRMWARE_INFO_V2_2 *fw_info; - uint16_t size; - uint8_t frev, crev; - int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); - - /* First retrieve the Boot clocks and VDDC from the firmware info table. - * We assume here that fw_info is unchanged if this call fails. - */ - fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)smu_atom_get_data_table(hwmgr->adev, index, - &size, &frev, &crev); - if (!fw_info) - /* During a test, there is no firmware info table. */ - return 0; - - /* Patch the state. */ - data->vbios_boot_state.sclk_bootup_value = - le32_to_cpu(fw_info->ulDefaultEngineClock); - data->vbios_boot_state.mclk_bootup_value = - le32_to_cpu(fw_info->ulDefaultMemoryClock); - data->vbios_boot_state.mvdd_bootup_value = - le16_to_cpu(fw_info->usBootUpMVDDCVoltage); - data->vbios_boot_state.vddc_bootup_value = - le16_to_cpu(fw_info->usBootUpVDDCVoltage); - data->vbios_boot_state.vddci_bootup_value = - le16_to_cpu(fw_info->usBootUpVDDCIVoltage); - data->vbios_boot_state.pcie_gen_bootup_value = - smu7_get_current_pcie_speed(hwmgr); - - data->vbios_boot_state.pcie_lane_bootup_value = - (uint16_t)smu7_get_current_pcie_lane_number(hwmgr); - - /* set boot power state */ - ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value; - ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value; - ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value; - ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value; - - return 0; -} - -static int smu7_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) -{ - int result; - unsigned long ret = 0; - - if (hwmgr->pp_table_version == PP_TABLE_V0) { - result = pp_tables_get_num_of_entries(hwmgr, &ret); - return result ? 0 : ret; - } else if (hwmgr->pp_table_version == PP_TABLE_V1) { - result = get_number_of_powerplay_table_entries_v1_0(hwmgr); - return result; - } - return 0; -} - -static int smu7_get_pp_table_entry_callback_func_v1(struct pp_hwmgr *hwmgr, - void *state, struct pp_power_state *power_state, - void *pp_table, uint32_t classification_flag) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_power_state *smu7_power_state = - (struct smu7_power_state *)(&(power_state->hardware)); - struct smu7_performance_level *performance_level; - ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state; - ATOM_Tonga_POWERPLAYTABLE *powerplay_table = - (ATOM_Tonga_POWERPLAYTABLE *)pp_table; - PPTable_Generic_SubTable_Header *sclk_dep_table = - (PPTable_Generic_SubTable_Header *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); - - ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = - (ATOM_Tonga_MCLK_Dependency_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); - - /* The following fields are not initialized here: id orderedList allStatesList */ - power_state->classification.ui_label = - (le16_to_cpu(state_entry->usClassification) & - ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> - ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; - power_state->classification.flags = classification_flag; - /* NOTE: There is a classification2 flag in BIOS that is not being used right now */ - - power_state->classification.temporary_state = false; - power_state->classification.to_be_deleted = false; - - power_state->validation.disallowOnDC = - (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & - ATOM_Tonga_DISALLOW_ON_DC)); - - power_state->pcie.lanes = 0; - - power_state->display.disableFrameModulation = false; - power_state->display.limitRefreshrate = false; - power_state->display.enableVariBright = - (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & - ATOM_Tonga_ENABLE_VARIBRIGHT)); - - power_state->validation.supportedPowerLevels = 0; - power_state->uvd_clocks.VCLK = 0; - power_state->uvd_clocks.DCLK = 0; - power_state->temperatures.min = 0; - power_state->temperatures.max = 0; - - performance_level = &(smu7_power_state->performance_levels - [smu7_power_state->performance_level_count++]); - - PP_ASSERT_WITH_CODE( - (smu7_power_state->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), - "Performance levels exceeds SMC limit!", - return -EINVAL); - - PP_ASSERT_WITH_CODE( - (smu7_power_state->performance_level_count <= - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), - "Performance levels exceeds Driver limit!", - return -EINVAL); - - /* Performance levels are arranged from low to high. */ - performance_level->memory_clock = mclk_dep_table->entries - [state_entry->ucMemoryClockIndexLow].ulMclk; - if (sclk_dep_table->ucRevId == 0) - performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries - [state_entry->ucEngineClockIndexLow].ulSclk; - else if (sclk_dep_table->ucRevId == 1) - performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries - [state_entry->ucEngineClockIndexLow].ulSclk; - performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, - state_entry->ucPCIEGenLow); - performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, - state_entry->ucPCIELaneLow); - - performance_level = &(smu7_power_state->performance_levels - [smu7_power_state->performance_level_count++]); - performance_level->memory_clock = mclk_dep_table->entries - [state_entry->ucMemoryClockIndexHigh].ulMclk; - - if (sclk_dep_table->ucRevId == 0) - performance_level->engine_clock = ((ATOM_Tonga_SCLK_Dependency_Table *)sclk_dep_table)->entries - [state_entry->ucEngineClockIndexHigh].ulSclk; - else if (sclk_dep_table->ucRevId == 1) - performance_level->engine_clock = ((ATOM_Polaris_SCLK_Dependency_Table *)sclk_dep_table)->entries - [state_entry->ucEngineClockIndexHigh].ulSclk; - - performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, - state_entry->ucPCIEGenHigh); - performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, - state_entry->ucPCIELaneHigh); - - return 0; -} - -static int smu7_get_pp_table_entry_v1(struct pp_hwmgr *hwmgr, - unsigned long entry_index, struct pp_power_state *state) -{ - int result; - struct smu7_power_state *ps; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = - table_info->vdd_dep_on_mclk; - - state->hardware.magic = PHM_VIslands_Magic; - - ps = (struct smu7_power_state *)(&state->hardware); - - result = get_powerplay_table_entry_v1_0(hwmgr, entry_index, state, - smu7_get_pp_table_entry_callback_func_v1); - - /* This is the earliest time we have all the dependency table and the VBIOS boot state - * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state - * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state - */ - if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { - if (dep_mclk_table->entries[0].clk != - data->vbios_boot_state.mclk_bootup_value) - pr_debug("Single MCLK entry VDDCI/MCLK dependency table " - "does not match VBIOS boot MCLK level"); - if (dep_mclk_table->entries[0].vddci != - data->vbios_boot_state.vddci_bootup_value) - pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " - "does not match VBIOS boot VDDCI level"); - } - - /* set DC compatible flag if this state supports DC */ - if (!state->validation.disallowOnDC) - ps->dc_compatible = true; - - if (state->classification.flags & PP_StateClassificationFlag_ACPI) - data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; - - ps->uvd_clks.vclk = state->uvd_clocks.VCLK; - ps->uvd_clks.dclk = state->uvd_clocks.DCLK; - - if (!result) { - uint32_t i; - - switch (state->classification.ui_label) { - case PP_StateUILabel_Performance: - data->use_pcie_performance_levels = true; - for (i = 0; i < ps->performance_level_count; i++) { - if (data->pcie_gen_performance.max < - ps->performance_levels[i].pcie_gen) - data->pcie_gen_performance.max = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_gen_performance.min > - ps->performance_levels[i].pcie_gen) - data->pcie_gen_performance.min = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_lane_performance.max < - ps->performance_levels[i].pcie_lane) - data->pcie_lane_performance.max = - ps->performance_levels[i].pcie_lane; - if (data->pcie_lane_performance.min > - ps->performance_levels[i].pcie_lane) - data->pcie_lane_performance.min = - ps->performance_levels[i].pcie_lane; - } - break; - case PP_StateUILabel_Battery: - data->use_pcie_power_saving_levels = true; - - for (i = 0; i < ps->performance_level_count; i++) { - if (data->pcie_gen_power_saving.max < - ps->performance_levels[i].pcie_gen) - data->pcie_gen_power_saving.max = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_gen_power_saving.min > - ps->performance_levels[i].pcie_gen) - data->pcie_gen_power_saving.min = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_lane_power_saving.max < - ps->performance_levels[i].pcie_lane) - data->pcie_lane_power_saving.max = - ps->performance_levels[i].pcie_lane; - - if (data->pcie_lane_power_saving.min > - ps->performance_levels[i].pcie_lane) - data->pcie_lane_power_saving.min = - ps->performance_levels[i].pcie_lane; - } - break; - default: - break; - } - } - return 0; -} - -static int smu7_get_pp_table_entry_callback_func_v0(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *power_state, - unsigned int index, const void *clock_info) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_power_state *ps = cast_phw_smu7_power_state(power_state); - const ATOM_PPLIB_CI_CLOCK_INFO *visland_clk_info = clock_info; - struct smu7_performance_level *performance_level; - uint32_t engine_clock, memory_clock; - uint16_t pcie_gen_from_bios; - - engine_clock = visland_clk_info->ucEngineClockHigh << 16 | visland_clk_info->usEngineClockLow; - memory_clock = visland_clk_info->ucMemoryClockHigh << 16 | visland_clk_info->usMemoryClockLow; - - if (!(data->mc_micro_code_feature & DISABLE_MC_LOADMICROCODE) && memory_clock > data->highest_mclk) - data->highest_mclk = memory_clock; - - PP_ASSERT_WITH_CODE( - (ps->performance_level_count < smum_get_mac_definition(hwmgr, SMU_MAX_LEVELS_GRAPHICS)), - "Performance levels exceeds SMC limit!", - return -EINVAL); - - PP_ASSERT_WITH_CODE( - (ps->performance_level_count < - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), - "Performance levels exceeds Driver limit, Skip!", - return 0); - - performance_level = &(ps->performance_levels - [ps->performance_level_count++]); - - /* Performance levels are arranged from low to high. */ - performance_level->memory_clock = memory_clock; - performance_level->engine_clock = engine_clock; - - pcie_gen_from_bios = visland_clk_info->ucPCIEGen; - - performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, pcie_gen_from_bios); - performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, visland_clk_info->usPCIELane); - - return 0; -} - -static int smu7_get_pp_table_entry_v0(struct pp_hwmgr *hwmgr, - unsigned long entry_index, struct pp_power_state *state) -{ - int result; - struct smu7_power_state *ps; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_clock_voltage_dependency_table *dep_mclk_table = - hwmgr->dyn_state.vddci_dependency_on_mclk; - - memset(&state->hardware, 0x00, sizeof(struct pp_hw_power_state)); - - state->hardware.magic = PHM_VIslands_Magic; - - ps = (struct smu7_power_state *)(&state->hardware); - - result = pp_tables_get_entry(hwmgr, entry_index, state, - smu7_get_pp_table_entry_callback_func_v0); - - /* - * This is the earliest time we have all the dependency table - * and the VBIOS boot state as - * PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot - * state if there is only one VDDCI/MCLK level, check if it's - * the same as VBIOS boot state - */ - if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { - if (dep_mclk_table->entries[0].clk != - data->vbios_boot_state.mclk_bootup_value) - pr_debug("Single MCLK entry VDDCI/MCLK dependency table " - "does not match VBIOS boot MCLK level"); - if (dep_mclk_table->entries[0].v != - data->vbios_boot_state.vddci_bootup_value) - pr_debug("Single VDDCI entry VDDCI/MCLK dependency table " - "does not match VBIOS boot VDDCI level"); - } - - /* set DC compatible flag if this state supports DC */ - if (!state->validation.disallowOnDC) - ps->dc_compatible = true; - - if (state->classification.flags & PP_StateClassificationFlag_ACPI) - data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; - - ps->uvd_clks.vclk = state->uvd_clocks.VCLK; - ps->uvd_clks.dclk = state->uvd_clocks.DCLK; - - if (!result) { - uint32_t i; - - switch (state->classification.ui_label) { - case PP_StateUILabel_Performance: - data->use_pcie_performance_levels = true; - - for (i = 0; i < ps->performance_level_count; i++) { - if (data->pcie_gen_performance.max < - ps->performance_levels[i].pcie_gen) - data->pcie_gen_performance.max = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_gen_performance.min > - ps->performance_levels[i].pcie_gen) - data->pcie_gen_performance.min = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_lane_performance.max < - ps->performance_levels[i].pcie_lane) - data->pcie_lane_performance.max = - ps->performance_levels[i].pcie_lane; - - if (data->pcie_lane_performance.min > - ps->performance_levels[i].pcie_lane) - data->pcie_lane_performance.min = - ps->performance_levels[i].pcie_lane; - } - break; - case PP_StateUILabel_Battery: - data->use_pcie_power_saving_levels = true; - - for (i = 0; i < ps->performance_level_count; i++) { - if (data->pcie_gen_power_saving.max < - ps->performance_levels[i].pcie_gen) - data->pcie_gen_power_saving.max = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_gen_power_saving.min > - ps->performance_levels[i].pcie_gen) - data->pcie_gen_power_saving.min = - ps->performance_levels[i].pcie_gen; - - if (data->pcie_lane_power_saving.max < - ps->performance_levels[i].pcie_lane) - data->pcie_lane_power_saving.max = - ps->performance_levels[i].pcie_lane; - - if (data->pcie_lane_power_saving.min > - ps->performance_levels[i].pcie_lane) - data->pcie_lane_power_saving.min = - ps->performance_levels[i].pcie_lane; - } - break; - default: - break; - } - } - return 0; -} - -static int smu7_get_pp_table_entry(struct pp_hwmgr *hwmgr, - unsigned long entry_index, struct pp_power_state *state) -{ - if (hwmgr->pp_table_version == PP_TABLE_V0) - return smu7_get_pp_table_entry_v0(hwmgr, entry_index, state); - else if (hwmgr->pp_table_version == PP_TABLE_V1) - return smu7_get_pp_table_entry_v1(hwmgr, entry_index, state); - - return 0; -} - -static int smu7_get_gpu_power(struct pp_hwmgr *hwmgr, u32 *query) -{ - struct amdgpu_device *adev = hwmgr->adev; - int i; - u32 tmp = 0; - - if (!query) - return -EINVAL; - - /* - * PPSMC_MSG_GetCurrPkgPwr is not supported on: - * - Hawaii - * - Bonaire - * - Fiji - * - Tonga - */ - if ((adev->asic_type != CHIP_HAWAII) && - (adev->asic_type != CHIP_BONAIRE) && - (adev->asic_type != CHIP_FIJI) && - (adev->asic_type != CHIP_TONGA)) { - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetCurrPkgPwr, 0, &tmp); - *query = tmp; - - if (tmp != 0) - return 0; - } - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogStart, NULL); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_PM_STATUS_95, 0); - - for (i = 0; i < 10; i++) { - msleep(500); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PmStatusLogSample, NULL); - tmp = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - ixSMU_PM_STATUS_95); - if (tmp != 0) - break; - } - *query = tmp; - - return 0; -} - -static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - uint32_t sclk, mclk, activity_percent; - uint32_t offset, val_vid; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - /* size must be at least 4 bytes for all sensors */ - if (*size < 4) - return -EINVAL; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &sclk); - *((uint32_t *)value) = sclk; - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_GFX_MCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &mclk); - *((uint32_t *)value) = mclk; - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_GPU_LOAD: - case AMDGPU_PP_SENSOR_MEM_LOAD: - offset = data->soft_regs_start + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, - (idx == AMDGPU_PP_SENSOR_GPU_LOAD) ? - AverageGraphicsActivity: - AverageMemoryActivity); - - activity_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); - activity_percent += 0x80; - activity_percent >>= 8; - *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = smu7_thermal_get_temperature(hwmgr); - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_UVD_POWER: - *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_VCE_POWER: - *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; - *size = 4; - return 0; - case AMDGPU_PP_SENSOR_GPU_POWER: - return smu7_get_gpu_power(hwmgr, (uint32_t *)value); - case AMDGPU_PP_SENSOR_VDDGFX: - if ((data->vr_config & 0xff) == 0x2) - val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); - else - val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE1_VID); - - *((uint32_t *)value) = (uint32_t)convert_to_vddc(val_vid); - return 0; - default: - return -EINVAL; - } -} - -static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) -{ - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - const struct smu7_power_state *smu7_ps = - cast_const_phw_smu7_power_state(states->pnew_state); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); - uint32_t sclk = smu7_ps->performance_levels - [smu7_ps->performance_level_count - 1].engine_clock; - struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); - uint32_t mclk = smu7_ps->performance_levels - [smu7_ps->performance_level_count - 1].memory_clock; - struct PP_Clocks min_clocks = {0}; - uint32_t i; - - for (i = 0; i < sclk_table->count; i++) { - if (sclk == sclk_table->dpm_levels[i].value) - break; - } - - if (i >= sclk_table->count) { - if (sclk > sclk_table->dpm_levels[i-1].value) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; - sclk_table->dpm_levels[i-1].value = sclk; - } - } else { - /* TODO: Check SCLK in DAL's minimum clocks - * in case DeepSleep divider update is required. - */ - if (data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR && - (min_clocks.engineClockInSR >= SMU7_MINIMUM_ENGINE_CLOCK || - data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) - data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK; - } - - for (i = 0; i < mclk_table->count; i++) { - if (mclk == mclk_table->dpm_levels[i].value) - break; - } - - if (i >= mclk_table->count) { - if (mclk > mclk_table->dpm_levels[i-1].value) { - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; - mclk_table->dpm_levels[i-1].value = mclk; - } - } - - if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) - data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; - - return 0; -} - -static uint16_t smu7_get_maximum_link_speed(struct pp_hwmgr *hwmgr, - const struct smu7_power_state *smu7_ps) -{ - uint32_t i; - uint32_t sclk, max_sclk = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - - for (i = 0; i < smu7_ps->performance_level_count; i++) { - sclk = smu7_ps->performance_levels[i].engine_clock; - if (max_sclk < sclk) - max_sclk = sclk; - } - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk) - return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ? - dpm_table->pcie_speed_table.dpm_levels - [dpm_table->pcie_speed_table.count - 1].value : - dpm_table->pcie_speed_table.dpm_levels[i].value); - } - - return 0; -} - -static int smu7_request_link_speed_change_before_state_change( - struct pp_hwmgr *hwmgr, const void *input) -{ - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - const struct smu7_power_state *smu7_nps = - cast_const_phw_smu7_power_state(states->pnew_state); - const struct smu7_power_state *polaris10_cps = - cast_const_phw_smu7_power_state(states->pcurrent_state); - - uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_nps); - uint16_t current_link_speed; - - if (data->force_pcie_gen == PP_PCIEGenInvalid) - current_link_speed = smu7_get_maximum_link_speed(hwmgr, polaris10_cps); - else - current_link_speed = data->force_pcie_gen; - - data->force_pcie_gen = PP_PCIEGenInvalid; - data->pspp_notify_required = false; - - if (target_link_speed > current_link_speed) { - switch (target_link_speed) { -#ifdef CONFIG_ACPI - case PP_PCIEGen3: - if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN3, false)) - break; - data->force_pcie_gen = PP_PCIEGen2; - if (current_link_speed == PP_PCIEGen2) - break; - fallthrough; - case PP_PCIEGen2: - if (0 == amdgpu_acpi_pcie_performance_request(hwmgr->adev, PCIE_PERF_REQ_GEN2, false)) - break; - fallthrough; -#endif - default: - data->force_pcie_gen = smu7_get_current_pcie_speed(hwmgr); - break; - } - } else { - if (target_link_speed < current_link_speed) - data->pspp_notify_required = true; - } - - return 0; -} - -static int smu7_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (0 == data->need_update_smu7_dpm_table) - return 0; - - if ((0 == data->sclk_dpm_key_disabled) && - (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to freeze SCLK DPM when DPM is disabled", - ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_SCLKDPM_FreezeLevel, - NULL), - "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", - return -EINVAL); - } - - if ((0 == data->mclk_dpm_key_disabled) && - (data->need_update_smu7_dpm_table & - DPMTABLE_OD_UPDATE_MCLK)) { - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to freeze MCLK DPM when DPM is disabled", - ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_MCLKDPM_FreezeLevel, - NULL), - "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", - return -EINVAL); - } - - return 0; -} - -static int smu7_populate_and_upload_sclk_mclk_dpm_levels( - struct pp_hwmgr *hwmgr, const void *input) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - uint32_t count; - struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); - struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); - - if (0 == data->need_update_smu7_dpm_table) - return 0; - - if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { - for (count = 0; count < dpm_table->sclk_table.count; count++) { - dpm_table->sclk_table.dpm_levels[count].enabled = odn_sclk_table->entries[count].enabled; - dpm_table->sclk_table.dpm_levels[count].value = odn_sclk_table->entries[count].clock; - } - } - - if (hwmgr->od_enabled && data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { - for (count = 0; count < dpm_table->mclk_table.count; count++) { - dpm_table->mclk_table.dpm_levels[count].enabled = odn_mclk_table->entries[count].enabled; - dpm_table->mclk_table.dpm_levels[count].value = odn_mclk_table->entries[count].clock; - } - } - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) { - result = smum_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", - return result); - } - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { - /*populate MCLK dpm table to SMU7 */ - result = smum_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", - return result); - } - - return result; -} - -static int smu7_trim_single_dpm_states(struct pp_hwmgr *hwmgr, - struct smu7_single_dpm_table *dpm_table, - uint32_t low_limit, uint32_t high_limit) -{ - uint32_t i; - - /* force the trim if mclk_switching is disabled to prevent flicker */ - bool force_trim = (low_limit == high_limit); - for (i = 0; i < dpm_table->count; i++) { - /*skip the trim if od is enabled*/ - if ((!hwmgr->od_enabled || force_trim) - && (dpm_table->dpm_levels[i].value < low_limit - || dpm_table->dpm_levels[i].value > high_limit)) - dpm_table->dpm_levels[i].enabled = false; - else - dpm_table->dpm_levels[i].enabled = true; - } - - return 0; -} - -static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr, - const struct smu7_power_state *smu7_ps) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t high_limit_count; - - PP_ASSERT_WITH_CODE((smu7_ps->performance_level_count >= 1), - "power state did not have any performance level", - return -EINVAL); - - high_limit_count = (1 == smu7_ps->performance_level_count) ? 0 : 1; - - smu7_trim_single_dpm_states(hwmgr, - &(data->dpm_table.sclk_table), - smu7_ps->performance_levels[0].engine_clock, - smu7_ps->performance_levels[high_limit_count].engine_clock); - - smu7_trim_single_dpm_states(hwmgr, - &(data->dpm_table.mclk_table), - smu7_ps->performance_levels[0].memory_clock, - smu7_ps->performance_levels[high_limit_count].memory_clock); - - return 0; -} - -static int smu7_generate_dpm_level_enable_mask( - struct pp_hwmgr *hwmgr, const void *input) -{ - int result = 0; - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - const struct smu7_power_state *smu7_ps = - cast_const_phw_smu7_power_state(states->pnew_state); - - - result = smu7_trim_dpm_states(hwmgr, smu7_ps); - if (result) - return result; - - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table); - data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table); - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table); - - return 0; -} - -static int smu7_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (0 == data->need_update_smu7_dpm_table) - return 0; - - if ((0 == data->sclk_dpm_key_disabled) && - (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { - - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to Unfreeze SCLK DPM when DPM is disabled", - ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_SCLKDPM_UnfreezeLevel, - NULL), - "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", - return -EINVAL); - } - - if ((0 == data->mclk_dpm_key_disabled) && - (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { - - PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), - "Trying to Unfreeze MCLK DPM when DPM is disabled", - ); - PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_MCLKDPM_UnfreezeLevel, - NULL), - "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", - return -EINVAL); - } - - data->need_update_smu7_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; - - return 0; -} - -static int smu7_notify_link_speed_change_after_state_change( - struct pp_hwmgr *hwmgr, const void *input) -{ - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - const struct smu7_power_state *smu7_ps = - cast_const_phw_smu7_power_state(states->pnew_state); - uint16_t target_link_speed = smu7_get_maximum_link_speed(hwmgr, smu7_ps); - uint8_t request; - - if (data->pspp_notify_required) { - if (target_link_speed == PP_PCIEGen3) - request = PCIE_PERF_REQ_GEN3; - else if (target_link_speed == PP_PCIEGen2) - request = PCIE_PERF_REQ_GEN2; - else - request = PCIE_PERF_REQ_GEN1; - - if (request == PCIE_PERF_REQ_GEN1 && - smu7_get_current_pcie_speed(hwmgr) > 0) - return 0; - -#ifdef CONFIG_ACPI - if (amdgpu_acpi_pcie_performance_request(hwmgr->adev, request, false)) { - if (PP_PCIEGen2 == target_link_speed) - pr_info("PSPP request to switch to Gen2 from Gen3 Failed!"); - else - pr_info("PSPP request to switch to Gen1 from Gen2 Failed!"); - } -#endif - } - - return 0; -} - -static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { - if (hwmgr->chip_id == CHIP_VEGAM) - smum_send_msg_to_smc_with_parameter(hwmgr, - (PPSMC_Msg)PPSMC_MSG_SetVBITimeout_VEGAM, data->frame_time_x2, - NULL); - else - smum_send_msg_to_smc_with_parameter(hwmgr, - (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2, - NULL); - } - return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay, NULL) == 0) ? 0 : -EINVAL; -} - -static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) -{ - int tmp_result, result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - tmp_result = smu7_find_dpm_states_clocks_in_dpm_table(hwmgr, input); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to find DPM states clocks in DPM table!", - result = tmp_result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PCIEPerformanceRequest)) { - tmp_result = - smu7_request_link_speed_change_before_state_change(hwmgr, input); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to request link speed change before state change!", - result = tmp_result); - } - - tmp_result = smu7_freeze_sclk_mclk_dpm(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to freeze SCLK MCLK DPM!", result = tmp_result); - - tmp_result = smu7_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to populate and upload SCLK MCLK DPM levels!", - result = tmp_result); - - /* - * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. - * That effectively disables AVFS feature. - */ - if (hwmgr->hardcode_pp_table != NULL) - data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; - - tmp_result = smu7_update_avfs(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to update avfs voltages!", - result = tmp_result); - - tmp_result = smu7_generate_dpm_level_enable_mask(hwmgr, input); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to generate DPM level enabled mask!", - result = tmp_result); - - tmp_result = smum_update_sclk_threshold(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to update SCLK threshold!", - result = tmp_result); - - tmp_result = smu7_notify_smc_display(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to notify smc display settings!", - result = tmp_result); - - tmp_result = smu7_unfreeze_sclk_mclk_dpm(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to unfreeze SCLK MCLK DPM!", - result = tmp_result); - - tmp_result = smu7_upload_dpm_level_enable_mask(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to upload DPM level enabled mask!", - result = tmp_result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PCIEPerformanceRequest)) { - tmp_result = - smu7_notify_link_speed_change_after_state_change(hwmgr, input); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to notify link speed change after state change!", - result = tmp_result); - } - data->apply_optimized_settings = false; - return result; -} - -static int smu7_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm) -{ - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm, - NULL); -} - -static int -smu7_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) -{ - PPSMC_Msg msg = has_display ? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; - - return (smum_send_msg_to_smc(hwmgr, msg, NULL) == 0) ? 0 : -1; -} - -static int -smu7_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->display_config->num_display > 1 && - !hwmgr->display_config->multi_monitor_in_sync) - smu7_notify_smc_display_change(hwmgr, false); - - return 0; -} - -/** -* Programs the display gap -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always OK -*/ -static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); - uint32_t display_gap2; - uint32_t pre_vbi_time_in_us; - uint32_t frame_time_in_us; - uint32_t ref_clock, refresh_rate; - - display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (hwmgr->display_config->num_display > 0) ? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap); - - ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - refresh_rate = hwmgr->display_config->vrefresh; - - if (0 == refresh_rate) - refresh_rate = 60; - - frame_time_in_us = 1000000 / refresh_rate; - - pre_vbi_time_in_us = frame_time_in_us - 200 - hwmgr->display_config->min_vblank_time; - - data->frame_time_x2 = frame_time_in_us * 2 / 100; - - if (data->frame_time_x2 < 280) { - pr_debug("%s: enforce minimal VBITimeout: %d -> 280\n", __func__, data->frame_time_x2); - data->frame_time_x2 = 280; - } - - display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, - PreVBlankGap), 0x64); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, - VBlankTimeout), - (frame_time_in_us - pre_vbi_time_in_us)); - - return 0; -} - -static int smu7_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - return smu7_program_display_gap(hwmgr); -} - -/** -* Set maximum target operating fan output RPM -* -* @param hwmgr: the address of the powerplay hardware manager. -* @param usMaxFanRpm: max operating fan RPM value. -* @return The response that came from the SMC. -*/ -static int smu7_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_rpm) -{ - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm; - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm, - NULL); -} - -static const struct amdgpu_irq_src_funcs smu7_irq_funcs = { - .process = phm_irq_process, -}; - -static int smu7_register_irq_handlers(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_irq_src *source = - kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL); - - if (!source) - return -ENOMEM; - - source->funcs = &smu7_irq_funcs; - - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - AMDGPU_IRQ_CLIENTID_LEGACY, - VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH, - source); - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - AMDGPU_IRQ_CLIENTID_LEGACY, - VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW, - source); - - /* Register CTF(GPIO_19) interrupt */ - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - AMDGPU_IRQ_CLIENTID_LEGACY, - VISLANDS30_IV_SRCID_GPIO_19, - source); - - return 0; -} - -static bool -smu7_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - bool is_update_required = false; - - if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) - is_update_required = true; - - if (data->display_timing.vrefresh != hwmgr->display_config->vrefresh) - is_update_required = true; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { - if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr && - (data->display_timing.min_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK || - hwmgr->display_config->min_core_set_clock_in_sr >= SMU7_MINIMUM_ENGINE_CLOCK)) - is_update_required = true; - } - return is_update_required; -} - -static inline bool smu7_are_power_levels_equal(const struct smu7_performance_level *pl1, - const struct smu7_performance_level *pl2) -{ - return ((pl1->memory_clock == pl2->memory_clock) && - (pl1->engine_clock == pl2->engine_clock) && - (pl1->pcie_gen == pl2->pcie_gen) && - (pl1->pcie_lane == pl2->pcie_lane)); -} - -static int smu7_check_states_equal(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pstate1, - const struct pp_hw_power_state *pstate2, bool *equal) -{ - const struct smu7_power_state *psa; - const struct smu7_power_state *psb; - int i; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (pstate1 == NULL || pstate2 == NULL || equal == NULL) - return -EINVAL; - - psa = cast_const_phw_smu7_power_state(pstate1); - psb = cast_const_phw_smu7_power_state(pstate2); - /* If the two states don't even have the same number of performance levels they cannot be the same state. */ - if (psa->performance_level_count != psb->performance_level_count) { - *equal = false; - return 0; - } - - for (i = 0; i < psa->performance_level_count; i++) { - if (!smu7_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { - /* If we have found even one performance level pair that is different the states are different. */ - *equal = false; - return 0; - } - } - - /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ - *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); - *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); - *equal &= (psa->sclk_threshold == psb->sclk_threshold); - /* For OD call, set value based on flag */ - *equal &= !(data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK | - DPMTABLE_OD_UPDATE_MCLK | - DPMTABLE_OD_UPDATE_VDDC)); - - return 0; -} - -static int smu7_check_mc_firmware(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t tmp; - - /* Read MC indirect register offset 0x9F bits [3:0] to see - * if VBIOS has already loaded a full version of MC ucode - * or not. - */ - - smu7_get_mc_microcode_version(hwmgr); - - data->need_long_memory_training = false; - - cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, - ixMC_IO_DEBUG_UP_13); - tmp = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); - - if (tmp & (1 << 23)) { - data->mem_latency_high = MEM_LATENCY_HIGH; - data->mem_latency_low = MEM_LATENCY_LOW; - if ((hwmgr->chip_id == CHIP_POLARIS10) || - (hwmgr->chip_id == CHIP_POLARIS11) || - (hwmgr->chip_id == CHIP_POLARIS12)) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableFFC, NULL); - } else { - data->mem_latency_high = 330; - data->mem_latency_low = 330; - if ((hwmgr->chip_id == CHIP_POLARIS10) || - (hwmgr->chip_id == CHIP_POLARIS11) || - (hwmgr->chip_id == CHIP_POLARIS12)) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableFFC, NULL); - } - - return 0; -} - -static int smu7_read_clock_registers(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->clock_registers.vCG_SPLL_FUNC_CNTL = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL); - data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2); - data->clock_registers.vCG_SPLL_FUNC_CNTL_3 = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3); - data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4); - data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM); - data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 = - cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2); - data->clock_registers.vDLL_CNTL = - cgs_read_register(hwmgr->device, mmDLL_CNTL); - data->clock_registers.vMCLK_PWRMGT_CNTL = - cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL); - data->clock_registers.vMPLL_AD_FUNC_CNTL = - cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL); - data->clock_registers.vMPLL_DQ_FUNC_CNTL = - cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL); - data->clock_registers.vMPLL_FUNC_CNTL = - cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL); - data->clock_registers.vMPLL_FUNC_CNTL_1 = - cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1); - data->clock_registers.vMPLL_FUNC_CNTL_2 = - cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2); - data->clock_registers.vMPLL_SS1 = - cgs_read_register(hwmgr->device, mmMPLL_SS1); - data->clock_registers.vMPLL_SS2 = - cgs_read_register(hwmgr->device, mmMPLL_SS2); - return 0; - -} - -/** - * Find out if memory is GDDR5. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -static int smu7_get_memory_type(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - - data->is_memory_gddr5 = (adev->gmc.vram_type == AMDGPU_VRAM_TYPE_GDDR5); - - return 0; -} - -/** - * Enables Dynamic Power Management by SMC - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -static int smu7_enable_acpi_power_management(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - GENERAL_PWRMGT, STATIC_PM_EN, 1); - - return 0; -} - -/** - * Initialize PowerGating States for different engines - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -static int smu7_init_power_gate_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->uvd_power_gated = false; - data->vce_power_gated = false; - - return 0; -} - -static int smu7_init_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - data->low_sclk_interrupt_threshold = 0; - return 0; -} - -static int smu7_setup_asic_task(struct pp_hwmgr *hwmgr) -{ - int tmp_result, result = 0; - - smu7_check_mc_firmware(hwmgr); - - tmp_result = smu7_read_clock_registers(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to read clock registers!", result = tmp_result); - - tmp_result = smu7_get_memory_type(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to get memory type!", result = tmp_result); - - tmp_result = smu7_enable_acpi_power_management(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to enable ACPI power management!", result = tmp_result); - - tmp_result = smu7_init_power_gate_state(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to init power gate state!", result = tmp_result); - - tmp_result = smu7_get_mc_microcode_version(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to get MC microcode version!", result = tmp_result); - - tmp_result = smu7_init_sclk_threshold(hwmgr); - PP_ASSERT_WITH_CODE((0 == tmp_result), - "Failed to init sclk threshold!", result = tmp_result); - - return result; -} - -static int smu7_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (mask == 0) - return -EINVAL; - - switch (type) { - case PP_SCLK: - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SCLKDPM_SetEnabledMask, - data->dpm_level_enable_mask.sclk_dpm_enable_mask & mask, - NULL); - break; - case PP_MCLK: - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_MCLKDPM_SetEnabledMask, - data->dpm_level_enable_mask.mclk_dpm_enable_mask & mask, - NULL); - break; - case PP_PCIE: - { - uint32_t tmp = mask & data->dpm_level_enable_mask.pcie_dpm_enable_mask; - - if (!data->pcie_dpm_key_disabled) { - if (fls(tmp) != ffs(tmp)) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PCIeDPM_UnForceLevel, - NULL); - else - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PCIeDPM_ForceLevel, - fls(tmp) - 1, - NULL); - } - break; - } - default: - break; - } - - return 0; -} - -static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); - struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); - struct smu7_single_dpm_table *pcie_table = &(data->dpm_table.pcie_speed_table); - struct smu7_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct phm_odn_clock_levels *odn_sclk_table = &(odn_table->odn_core_clock_dpm_levels); - struct phm_odn_clock_levels *odn_mclk_table = &(odn_table->odn_memory_clock_dpm_levels); - int i, now, size = 0; - uint32_t clock, pcie_speed; - - switch (type) { - case PP_SCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetSclkFrequency, &clock); - - for (i = 0; i < sclk_table->count; i++) { - if (clock > sclk_table->dpm_levels[i].value) - continue; - break; - } - now = i; - - for (i = 0; i < sclk_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; - case PP_MCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_API_GetMclkFrequency, &clock); - - for (i = 0; i < mclk_table->count; i++) { - if (clock > mclk_table->dpm_levels[i].value) - continue; - break; - } - now = i; - - for (i = 0; i < mclk_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, mclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; - case PP_PCIE: - pcie_speed = smu7_get_current_pcie_speed(hwmgr); - for (i = 0; i < pcie_table->count; i++) { - if (pcie_speed != pcie_table->dpm_levels[i].value) - continue; - break; - } - now = i; - - for (i = 0; i < pcie_table->count; i++) - size += sprintf(buf + size, "%d: %s %s\n", i, - (pcie_table->dpm_levels[i].value == 0) ? "2.5GT/s, x8" : - (pcie_table->dpm_levels[i].value == 1) ? "5.0GT/s, x16" : - (pcie_table->dpm_levels[i].value == 2) ? "8.0GT/s, x16" : "", - (i == now) ? "*" : ""); - break; - case OD_SCLK: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_SCLK"); - for (i = 0; i < odn_sclk_table->num_of_pl; i++) - size += sprintf(buf + size, "%d: %10uMHz %10umV\n", - i, odn_sclk_table->entries[i].clock/100, - odn_sclk_table->entries[i].vddc); - } - break; - case OD_MCLK: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_MCLK"); - for (i = 0; i < odn_mclk_table->num_of_pl; i++) - size += sprintf(buf + size, "%d: %10uMHz %10umV\n", - i, odn_mclk_table->entries[i].clock/100, - odn_mclk_table->entries[i].vddc); - } - break; - case OD_RANGE: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_RANGE"); - size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); - size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); - size += sprintf(buf + size, "VDDC: %7umV %11umV\n", - data->odn_dpm_table.min_vddc, - data->odn_dpm_table.max_vddc); - } - break; - default: - break; - } - return size; -} - -static void smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - switch (mode) { - case AMD_FAN_CTRL_NONE: - smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - break; - case AMD_FAN_CTRL_MANUAL: - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - smu7_fan_ctrl_stop_smc_fan_control(hwmgr); - break; - case AMD_FAN_CTRL_AUTO: - if (!smu7_fan_ctrl_set_static_mode(hwmgr, mode)) - smu7_fan_ctrl_start_smc_fan_control(hwmgr); - break; - default: - break; - } -} - -static uint32_t smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr) -{ - return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL; -} - -static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); - struct smu7_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.sclk_table); - int value = sclk_table->dpm_levels[sclk_table->count - 1].value; - int golden_value = golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int smu7_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.sclk_table); - struct pp_power_state *ps; - struct smu7_power_state *smu7_ps; - - if (value > 20) - value = 20; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - smu7_ps = cast_phw_smu7_power_state(&ps->hardware); - - smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].engine_clock = - golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * - value / 100 + - golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; - - return 0; -} - -static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); - struct smu7_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mclk_table); - int value = mclk_table->dpm_levels[mclk_table->count - 1].value; - int golden_value = golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int smu7_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mclk_table); - struct pp_power_state *ps; - struct smu7_power_state *smu7_ps; - - if (value > 20) - value = 20; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - smu7_ps = cast_phw_smu7_power_state(&ps->hardware); - - smu7_ps->performance_levels[smu7_ps->performance_level_count - 1].memory_clock = - golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * - value / 100 + - golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; - - return 0; -} - - -static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = NULL; - struct phm_clock_voltage_dependency_table *sclk_table; - int i; - - if (hwmgr->pp_table_version == PP_TABLE_V1) { - if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL) - return -EINVAL; - dep_sclk_table = table_info->vdd_dep_on_sclk; - for (i = 0; i < dep_sclk_table->count; i++) - clocks->clock[i] = dep_sclk_table->entries[i].clk * 10; - clocks->count = dep_sclk_table->count; - } else if (hwmgr->pp_table_version == PP_TABLE_V0) { - sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk; - for (i = 0; i < sclk_table->count; i++) - clocks->clock[i] = sclk_table->entries[i].clk * 10; - clocks->count = sclk_table->count; - } - - return 0; -} - -static uint32_t smu7_get_mem_latency(struct pp_hwmgr *hwmgr, uint32_t clk) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (clk >= MEM_FREQ_LOW_LATENCY && clk < MEM_FREQ_HIGH_LATENCY) - return data->mem_latency_high; - else if (clk >= MEM_FREQ_HIGH_LATENCY) - return data->mem_latency_low; - else - return MEM_LATENCY_ERR; -} - -static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table; - int i; - struct phm_clock_voltage_dependency_table *mclk_table; - - if (hwmgr->pp_table_version == PP_TABLE_V1) { - if (table_info == NULL) - return -EINVAL; - dep_mclk_table = table_info->vdd_dep_on_mclk; - for (i = 0; i < dep_mclk_table->count; i++) { - clocks->clock[i] = dep_mclk_table->entries[i].clk * 10; - clocks->latency[i] = smu7_get_mem_latency(hwmgr, - dep_mclk_table->entries[i].clk); - } - clocks->count = dep_mclk_table->count; - } else if (hwmgr->pp_table_version == PP_TABLE_V0) { - mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk; - for (i = 0; i < mclk_table->count; i++) - clocks->clock[i] = mclk_table->entries[i].clk * 10; - clocks->count = mclk_table->count; - } - return 0; -} - -static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, - struct amd_pp_clocks *clocks) -{ - switch (type) { - case amd_pp_sys_clock: - smu7_get_sclks(hwmgr, clocks); - break; - case amd_pp_mem_clock: - smu7_get_mclks(hwmgr, clocks); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, - SMU_SoftRegisters, DRAM_LOG_ADDR_H), - mc_addr_hi); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, - SMU_SoftRegisters, DRAM_LOG_ADDR_L), - mc_addr_low); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, - SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H), - virtual_addr_hi); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, - SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L), - virtual_addr_low); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - data->soft_regs_start + - smum_get_offsetof(hwmgr, - SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE), - size); - return 0; -} - -static int smu7_get_max_high_clocks(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *clocks) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); - struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); - - if (clocks == NULL) - return -EINVAL; - - clocks->memory_max_clock = mclk_table->count > 1 ? - mclk_table->dpm_levels[mclk_table->count-1].value : - mclk_table->dpm_levels[0].value; - clocks->engine_max_clock = sclk_table->count > 1 ? - sclk_table->dpm_levels[sclk_table->count-1].value : - sclk_table->dpm_levels[0].value; - return 0; -} - -static int smu7_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *thermal_data) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - - memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); - - if (hwmgr->pp_table_version == PP_TABLE_V1) - thermal_data->max = table_info->cac_dtp_table->usSoftwareShutdownTemp * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - else if (hwmgr->pp_table_version == PP_TABLE_V0) - thermal_data->max = data->thermal_temp_setting.temperature_shutdown * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static bool smu7_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - uint32_t clk, - uint32_t voltage) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (voltage < data->odn_dpm_table.min_vddc || voltage > data->odn_dpm_table.max_vddc) { - pr_info("OD voltage is out of range [%d - %d] mV\n", - data->odn_dpm_table.min_vddc, - data->odn_dpm_table.max_vddc); - return false; - } - - if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { - if (data->golden_dpm_table.sclk_table.dpm_levels[0].value > clk || - hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { - pr_info("OD engine clock is out of range [%d - %d] MHz\n", - data->golden_dpm_table.sclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); - return false; - } - } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { - if (data->golden_dpm_table.mclk_table.dpm_levels[0].value > clk || - hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { - pr_info("OD memory clock is out of range [%d - %d] MHz\n", - data->golden_dpm_table.mclk_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); - return false; - } - } else { - return false; - } - - return true; -} - -static int smu7_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size) -{ - uint32_t i; - struct phm_odn_clock_levels *podn_dpm_table_in_backend = NULL; - struct smu7_odn_clock_voltage_dependency_table *podn_vdd_dep_in_backend = NULL; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t input_clk; - uint32_t input_vol; - uint32_t input_level; - - PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", - return -EINVAL); - - if (!hwmgr->od_enabled) { - pr_info("OverDrive feature not enabled\n"); - return -EINVAL; - } - - if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { - podn_dpm_table_in_backend = &data->odn_dpm_table.odn_core_clock_dpm_levels; - podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_sclk; - PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), - "Failed to get ODN SCLK and Voltage tables", - return -EINVAL); - } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { - podn_dpm_table_in_backend = &data->odn_dpm_table.odn_memory_clock_dpm_levels; - podn_vdd_dep_in_backend = &data->odn_dpm_table.vdd_dependency_on_mclk; - - PP_ASSERT_WITH_CODE((podn_dpm_table_in_backend && podn_vdd_dep_in_backend), - "Failed to get ODN MCLK and Voltage tables", - return -EINVAL); - } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { - smu7_odn_initial_default_setting(hwmgr); - return 0; - } else if (PP_OD_COMMIT_DPM_TABLE == type) { - smu7_check_dpm_table_updated(hwmgr); - return 0; - } else { - return -EINVAL; - } - - for (i = 0; i < size; i += 3) { - if (i + 3 > size || input[i] >= podn_dpm_table_in_backend->num_of_pl) { - pr_info("invalid clock voltage input \n"); - return 0; - } - input_level = input[i]; - input_clk = input[i+1] * 100; - input_vol = input[i+2]; - - if (smu7_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { - podn_dpm_table_in_backend->entries[input_level].clock = input_clk; - podn_vdd_dep_in_backend->entries[input_level].clk = input_clk; - podn_dpm_table_in_backend->entries[input_level].vddc = input_vol; - podn_vdd_dep_in_backend->entries[input_level].vddc = input_vol; - podn_vdd_dep_in_backend->entries[input_level].vddgfx = input_vol; - } else { - return -EINVAL; - } - } - - return 0; -} - -static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t i, size = 0; - uint32_t len; - - static const char *profile_name[7] = {"BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - - static const char *title[8] = {"NUM", - "MODE_NAME", - "SCLK_UP_HYST", - "SCLK_DOWN_HYST", - "SCLK_ACTIVE_LEVEL", - "MCLK_UP_HYST", - "MCLK_DOWN_HYST", - "MCLK_ACTIVE_LEVEL"}; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%s %16s %16s %16s %16s %16s %16s %16s\n", - title[0], title[1], title[2], title[3], - title[4], title[5], title[6], title[7]); - - len = ARRAY_SIZE(smu7_profiling); - - for (i = 0; i < len; i++) { - if (i == hwmgr->power_profile_mode) { - size += sprintf(buf + size, "%3d %14s %s: %8d %16d %16d %16d %16d %16d\n", - i, profile_name[i], "*", - data->current_profile_setting.sclk_up_hyst, - data->current_profile_setting.sclk_down_hyst, - data->current_profile_setting.sclk_activity, - data->current_profile_setting.mclk_up_hyst, - data->current_profile_setting.mclk_down_hyst, - data->current_profile_setting.mclk_activity); - continue; - } - if (smu7_profiling[i].bupdate_sclk) - size += sprintf(buf + size, "%3d %16s: %8d %16d %16d ", - i, profile_name[i], smu7_profiling[i].sclk_up_hyst, - smu7_profiling[i].sclk_down_hyst, - smu7_profiling[i].sclk_activity); - else - size += sprintf(buf + size, "%3d %16s: %8s %16s %16s ", - i, profile_name[i], "-", "-", "-"); - - if (smu7_profiling[i].bupdate_mclk) - size += sprintf(buf + size, "%16d %16d %16d\n", - smu7_profiling[i].mclk_up_hyst, - smu7_profiling[i].mclk_down_hyst, - smu7_profiling[i].mclk_activity); - else - size += sprintf(buf + size, "%16s %16s %16s\n", - "-", "-", "-"); - } - - return size; -} - -static void smu7_patch_compute_profile_mode(struct pp_hwmgr *hwmgr, - enum PP_SMC_POWER_PROFILE requst) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t tmp, level; - - if (requst == PP_SMC_POWER_PROFILE_COMPUTE) { - if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { - level = 0; - tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; - while (tmp >>= 1) - level++; - if (level > 0) - smu7_force_clock_level(hwmgr, PP_SCLK, 3 << (level-1)); - } - } else if (hwmgr->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE) { - smu7_force_clock_level(hwmgr, PP_SCLK, data->dpm_level_enable_mask.sclk_dpm_enable_mask); - } -} - -static int smu7_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct profile_mode_setting tmp; - enum PP_SMC_POWER_PROFILE mode; - - if (input == NULL) - return -EINVAL; - - mode = input[size]; - switch (mode) { - case PP_SMC_POWER_PROFILE_CUSTOM: - if (size < 8 && size != 0) - return -EINVAL; - /* If only CUSTOM is passed in, use the saved values. Check - * that we actually have a CUSTOM profile by ensuring that - * the "use sclk" or the "use mclk" bits are set - */ - tmp = smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM]; - if (size == 0) { - if (tmp.bupdate_sclk == 0 && tmp.bupdate_mclk == 0) - return -EINVAL; - } else { - tmp.bupdate_sclk = input[0]; - tmp.sclk_up_hyst = input[1]; - tmp.sclk_down_hyst = input[2]; - tmp.sclk_activity = input[3]; - tmp.bupdate_mclk = input[4]; - tmp.mclk_up_hyst = input[5]; - tmp.mclk_down_hyst = input[6]; - tmp.mclk_activity = input[7]; - smu7_profiling[PP_SMC_POWER_PROFILE_CUSTOM] = tmp; - } - if (!smum_update_dpm_settings(hwmgr, &tmp)) { - memcpy(&data->current_profile_setting, &tmp, sizeof(struct profile_mode_setting)); - hwmgr->power_profile_mode = mode; - } - break; - case PP_SMC_POWER_PROFILE_FULLSCREEN3D: - case PP_SMC_POWER_PROFILE_POWERSAVING: - case PP_SMC_POWER_PROFILE_VIDEO: - case PP_SMC_POWER_PROFILE_VR: - case PP_SMC_POWER_PROFILE_COMPUTE: - if (mode == hwmgr->power_profile_mode) - return 0; - - memcpy(&tmp, &smu7_profiling[mode], sizeof(struct profile_mode_setting)); - if (!smum_update_dpm_settings(hwmgr, &tmp)) { - if (tmp.bupdate_sclk) { - data->current_profile_setting.bupdate_sclk = tmp.bupdate_sclk; - data->current_profile_setting.sclk_up_hyst = tmp.sclk_up_hyst; - data->current_profile_setting.sclk_down_hyst = tmp.sclk_down_hyst; - data->current_profile_setting.sclk_activity = tmp.sclk_activity; - } - if (tmp.bupdate_mclk) { - data->current_profile_setting.bupdate_mclk = tmp.bupdate_mclk; - data->current_profile_setting.mclk_up_hyst = tmp.mclk_up_hyst; - data->current_profile_setting.mclk_down_hyst = tmp.mclk_down_hyst; - data->current_profile_setting.mclk_activity = tmp.mclk_activity; - } - smu7_patch_compute_profile_mode(hwmgr, mode); - hwmgr->power_profile_mode = mode; - } - break; - default: - return -EINVAL; - } - - return 0; -} - -static int smu7_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - const struct smu7_power_state *ps; - uint32_t i; - - if (level == NULL || hwmgr == NULL || state == NULL) - return -EINVAL; - - ps = cast_const_phw_smu7_power_state(state); - - i = index > ps->performance_level_count - 1 ? - ps->performance_level_count - 1 : index; - - level->coreClock = ps->performance_levels[i].engine_clock; - level->memory_clock = ps->performance_levels[i].memory_clock; - - return 0; -} - -static int smu7_power_off_asic(struct pp_hwmgr *hwmgr) -{ - int result; - - result = smu7_disable_dpm_tasks(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "[disable_dpm_tasks] Failed to disable DPM!", - ); - - return result; -} - -static const struct pp_hwmgr_func smu7_hwmgr_funcs = { - .backend_init = &smu7_hwmgr_backend_init, - .backend_fini = &smu7_hwmgr_backend_fini, - .asic_setup = &smu7_setup_asic_task, - .dynamic_state_management_enable = &smu7_enable_dpm_tasks, - .apply_state_adjust_rules = smu7_apply_state_adjust_rules, - .force_dpm_level = &smu7_force_dpm_level, - .power_state_set = smu7_set_power_state_tasks, - .get_power_state_size = smu7_get_power_state_size, - .get_mclk = smu7_dpm_get_mclk, - .get_sclk = smu7_dpm_get_sclk, - .patch_boot_state = smu7_dpm_patch_boot_state, - .get_pp_table_entry = smu7_get_pp_table_entry, - .get_num_of_pp_table_entries = smu7_get_number_of_powerplay_table_entries, - .powerdown_uvd = smu7_powerdown_uvd, - .powergate_uvd = smu7_powergate_uvd, - .powergate_vce = smu7_powergate_vce, - .disable_clock_power_gating = smu7_disable_clock_power_gating, - .update_clock_gatings = smu7_update_clock_gatings, - .notify_smc_display_config_after_ps_adjustment = smu7_notify_smc_display_config_after_ps_adjustment, - .display_config_changed = smu7_display_configuration_changed_task, - .set_max_fan_pwm_output = smu7_set_max_fan_pwm_output, - .set_max_fan_rpm_output = smu7_set_max_fan_rpm_output, - .stop_thermal_controller = smu7_thermal_stop_thermal_controller, - .get_fan_speed_info = smu7_fan_ctrl_get_fan_speed_info, - .get_fan_speed_percent = smu7_fan_ctrl_get_fan_speed_percent, - .set_fan_speed_percent = smu7_fan_ctrl_set_fan_speed_percent, - .reset_fan_speed_to_default = smu7_fan_ctrl_reset_fan_speed_to_default, - .get_fan_speed_rpm = smu7_fan_ctrl_get_fan_speed_rpm, - .set_fan_speed_rpm = smu7_fan_ctrl_set_fan_speed_rpm, - .uninitialize_thermal_controller = smu7_thermal_ctrl_uninitialize_thermal_controller, - .register_irq_handlers = smu7_register_irq_handlers, - .check_smc_update_required_for_display_configuration = smu7_check_smc_update_required_for_display_configuration, - .check_states_equal = smu7_check_states_equal, - .set_fan_control_mode = smu7_set_fan_control_mode, - .get_fan_control_mode = smu7_get_fan_control_mode, - .force_clock_level = smu7_force_clock_level, - .print_clock_levels = smu7_print_clock_levels, - .powergate_gfx = smu7_powergate_gfx, - .get_sclk_od = smu7_get_sclk_od, - .set_sclk_od = smu7_set_sclk_od, - .get_mclk_od = smu7_get_mclk_od, - .set_mclk_od = smu7_set_mclk_od, - .get_clock_by_type = smu7_get_clock_by_type, - .read_sensor = smu7_read_sensor, - .dynamic_state_management_disable = smu7_disable_dpm_tasks, - .avfs_control = smu7_avfs_control, - .disable_smc_firmware_ctf = smu7_thermal_disable_alert, - .start_thermal_controller = smu7_start_thermal_controller, - .notify_cac_buffer_info = smu7_notify_cac_buffer_info, - .get_max_high_clocks = smu7_get_max_high_clocks, - .get_thermal_temperature_range = smu7_get_thermal_temperature_range, - .odn_edit_dpm_table = smu7_odn_edit_dpm_table, - .set_power_limit = smu7_set_power_limit, - .get_power_profile_mode = smu7_get_power_profile_mode, - .set_power_profile_mode = smu7_set_power_profile_mode, - .get_performance_level = smu7_get_performance_level, - .get_asic_baco_capability = smu7_baco_get_capability, - .get_asic_baco_state = smu7_baco_get_state, - .set_asic_baco_state = smu7_baco_set_state, - .power_off_asic = smu7_power_off_asic, -}; - -uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, - uint32_t clock_insr) -{ - uint8_t i; - uint32_t temp; - uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK); - - PP_ASSERT_WITH_CODE((clock >= min), "Engine clock can't satisfy stutter requirement!", return 0); - for (i = SMU7_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { - temp = clock >> i; - - if (temp >= min || i == 0) - break; - } - return i; -} - -int smu7_init_function_pointers(struct pp_hwmgr *hwmgr) -{ - hwmgr->hwmgr_func = &smu7_hwmgr_funcs; - if (hwmgr->pp_table_version == PP_TABLE_V0) - hwmgr->pptable_func = &pptable_funcs; - else if (hwmgr->pp_table_version == PP_TABLE_V1) - hwmgr->pptable_func = &pptable_v1_0_funcs; - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h deleted file mode 100644 index 69d361f8dfca..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2015 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 _SMU7_HWMGR_H -#define _SMU7_HWMGR_H - -#include "hwmgr.h" -#include "ppatomctrl.h" - -#define SMU7_MAX_HARDWARE_POWERLEVELS 2 - -#define SMU7_VOLTAGE_CONTROL_NONE 0x0 -#define SMU7_VOLTAGE_CONTROL_BY_GPIO 0x1 -#define SMU7_VOLTAGE_CONTROL_BY_SVID2 0x2 -#define SMU7_VOLTAGE_CONTROL_MERGED 0x3 - -enum gpu_pt_config_reg_type { - GPU_CONFIGREG_MMR = 0, - GPU_CONFIGREG_SMC_IND, - GPU_CONFIGREG_DIDT_IND, - GPU_CONFIGREG_GC_CAC_IND, - GPU_CONFIGREG_CACHE, - GPU_CONFIGREG_MAX -}; - -struct gpu_pt_config_reg { - uint32_t offset; - uint32_t mask; - uint32_t shift; - uint32_t value; - enum gpu_pt_config_reg_type type; -}; - -struct smu7_performance_level { - uint32_t memory_clock; - uint32_t engine_clock; - uint16_t pcie_gen; - uint16_t pcie_lane; -}; - -struct smu7_thermal_temperature_setting { - long temperature_low; - long temperature_high; - long temperature_shutdown; -}; - -struct smu7_uvd_clocks { - uint32_t vclk; - uint32_t dclk; -}; - -struct smu7_vce_clocks { - uint32_t evclk; - uint32_t ecclk; -}; - -struct smu7_power_state { - uint32_t magic; - struct smu7_uvd_clocks uvd_clks; - struct smu7_vce_clocks vce_clks; - uint32_t sam_clk; - uint16_t performance_level_count; - bool dc_compatible; - uint32_t sclk_threshold; - struct smu7_performance_level performance_levels[SMU7_MAX_HARDWARE_POWERLEVELS]; -}; - -struct smu7_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -#define SMU7_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define MAX_REGULAR_DPM_NUMBER 8 -#define SMU7_MINIMUM_ENGINE_CLOCK 2500 - -struct smu7_single_dpm_table { - uint32_t count; - struct smu7_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; -}; - -struct smu7_dpm_table { - struct smu7_single_dpm_table sclk_table; - struct smu7_single_dpm_table mclk_table; - struct smu7_single_dpm_table pcie_speed_table; - struct smu7_single_dpm_table vddc_table; - struct smu7_single_dpm_table vddci_table; - struct smu7_single_dpm_table mvdd_table; -}; - -struct smu7_clock_registers { - uint32_t vCG_SPLL_FUNC_CNTL; - uint32_t vCG_SPLL_FUNC_CNTL_2; - uint32_t vCG_SPLL_FUNC_CNTL_3; - uint32_t vCG_SPLL_FUNC_CNTL_4; - uint32_t vCG_SPLL_SPREAD_SPECTRUM; - uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t vDLL_CNTL; - uint32_t vMCLK_PWRMGT_CNTL; - uint32_t vMPLL_AD_FUNC_CNTL; - uint32_t vMPLL_DQ_FUNC_CNTL; - uint32_t vMPLL_FUNC_CNTL; - uint32_t vMPLL_FUNC_CNTL_1; - uint32_t vMPLL_FUNC_CNTL_2; - uint32_t vMPLL_SS1; - uint32_t vMPLL_SS2; -}; - -#define DISABLE_MC_LOADMICROCODE 1 -#define DISABLE_MC_CFGPROGRAMMING 2 - -struct smu7_voltage_smio_registers { - uint32_t vS0_VID_LOWER_SMIO_CNTL; -}; - -#define SMU7_MAX_LEAKAGE_COUNT 8 - -struct smu7_leakage_voltage { - uint16_t count; - uint16_t leakage_id[SMU7_MAX_LEAKAGE_COUNT]; - uint16_t actual_voltage[SMU7_MAX_LEAKAGE_COUNT]; -}; - -struct smu7_vbios_boot_state { - uint16_t mvdd_bootup_value; - uint16_t vddc_bootup_value; - uint16_t vddci_bootup_value; - uint16_t vddgfx_bootup_value; - uint32_t sclk_bootup_value; - uint32_t mclk_bootup_value; - uint16_t pcie_gen_bootup_value; - uint16_t pcie_lane_bootup_value; -}; - -struct smu7_display_timing { - uint32_t min_clock_in_sr; - uint32_t num_existing_displays; - uint32_t vrefresh; -}; - -struct smu7_dpmlevel_enable_mask { - uint32_t uvd_dpm_enable_mask; - uint32_t vce_dpm_enable_mask; - uint32_t acp_dpm_enable_mask; - uint32_t samu_dpm_enable_mask; - uint32_t sclk_dpm_enable_mask; - uint32_t mclk_dpm_enable_mask; - uint32_t pcie_dpm_enable_mask; -}; - -struct smu7_pcie_perf_range { - uint16_t max; - uint16_t min; -}; - -struct smu7_odn_clock_voltage_dependency_table { - uint32_t count; - phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct smu7_odn_dpm_table { - struct phm_odn_clock_levels odn_core_clock_dpm_levels; - struct phm_odn_clock_levels odn_memory_clock_dpm_levels; - struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; - struct smu7_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; - uint32_t odn_mclk_min_limit; - uint32_t min_vddc; - uint32_t max_vddc; -}; - -struct profile_mode_setting { - uint8_t bupdate_sclk; - uint8_t sclk_up_hyst; - uint8_t sclk_down_hyst; - uint16_t sclk_activity; - uint8_t bupdate_mclk; - uint8_t mclk_up_hyst; - uint8_t mclk_down_hyst; - uint16_t mclk_activity; -}; - -struct smu7_hwmgr { - struct smu7_dpm_table dpm_table; - struct smu7_dpm_table golden_dpm_table; - struct smu7_odn_dpm_table odn_dpm_table; - - uint32_t voting_rights_clients[8]; - uint32_t static_screen_threshold_unit; - uint32_t static_screen_threshold; - uint32_t voltage_control; - uint32_t vdd_gfx_control; - uint32_t vddc_vddgfx_delta; - uint32_t active_auto_throttle_sources; - - struct smu7_clock_registers clock_registers; - - bool is_memory_gddr5; - uint16_t acpi_vddc; - bool pspp_notify_required; - uint16_t force_pcie_gen; - uint16_t acpi_pcie_gen; - uint32_t pcie_gen_cap; - uint32_t pcie_lane_cap; - uint32_t pcie_spc_cap; - struct smu7_leakage_voltage vddc_leakage; - struct smu7_leakage_voltage vddci_leakage; - struct smu7_leakage_voltage vddcgfx_leakage; - - uint32_t mvdd_control; - uint32_t vddc_mask_low; - uint32_t mvdd_mask_low; - uint16_t max_vddc_in_pptable; - uint16_t min_vddc_in_pptable; - uint16_t max_vddci_in_pptable; - uint16_t min_vddci_in_pptable; - bool is_uvd_enabled; - struct smu7_vbios_boot_state vbios_boot_state; - - bool pcie_performance_request; - bool battery_state; - bool is_tlu_enabled; - bool disable_handshake; - bool smc_voltage_control_enabled; - bool vbi_time_out_support; - - uint32_t soft_regs_start; - /* ---- Stuff originally coming from Evergreen ---- */ - uint32_t vddci_control; - struct pp_atomctrl_voltage_table vddc_voltage_table; - struct pp_atomctrl_voltage_table vddci_voltage_table; - struct pp_atomctrl_voltage_table mvdd_voltage_table; - struct pp_atomctrl_voltage_table vddgfx_voltage_table; - - uint32_t mgcg_cgtt_local2; - uint32_t mgcg_cgtt_local3; - uint32_t gpio_debug; - uint32_t mc_micro_code_feature; - uint32_t highest_mclk; - uint16_t acpi_vddci; - uint8_t mvdd_high_index; - uint8_t mvdd_low_index; - bool dll_default_on; - bool performance_request_registered; - - /* ---- Low Power Features ---- */ - bool ulv_supported; - - /* ---- CAC Stuff ---- */ - uint32_t cac_table_start; - bool cac_configuration_required; - bool driver_calculate_cac_leakage; - bool cac_enabled; - - /* ---- DPM2 Parameters ---- */ - uint32_t power_containment_features; - bool enable_dte_feature; - bool enable_tdc_limit_feature; - bool enable_pkg_pwr_tracking_feature; - bool disable_uvd_power_tune_feature; - - - uint32_t dte_tj_offset; - uint32_t fast_watermark_threshold; - - /* ---- Phase Shedding ---- */ - uint8_t vddc_phase_shed_control; - - /* ---- DI/DT ---- */ - struct smu7_display_timing display_timing; - - /* ---- Thermal Temperature Setting ---- */ - struct smu7_thermal_temperature_setting thermal_temp_setting; - struct smu7_dpmlevel_enable_mask dpm_level_enable_mask; - uint32_t need_update_smu7_dpm_table; - uint32_t sclk_dpm_key_disabled; - uint32_t mclk_dpm_key_disabled; - uint32_t pcie_dpm_key_disabled; - uint32_t min_engine_clocks; - struct smu7_pcie_perf_range pcie_gen_performance; - struct smu7_pcie_perf_range pcie_lane_performance; - struct smu7_pcie_perf_range pcie_gen_power_saving; - struct smu7_pcie_perf_range pcie_lane_power_saving; - bool use_pcie_performance_levels; - bool use_pcie_power_saving_levels; - uint32_t mclk_dpm0_activity_target; - uint32_t low_sclk_interrupt_threshold; - uint32_t last_mclk_dpm_enable_mask; - bool uvd_enabled; - - /* ---- Power Gating States ---- */ - bool uvd_power_gated; - bool vce_power_gated; - bool need_long_memory_training; - - /* Application power optimization parameters */ - bool update_up_hyst; - bool update_down_hyst; - uint32_t down_hyst; - uint32_t up_hyst; - uint32_t disable_dpm_mask; - bool apply_optimized_settings; - - uint32_t avfs_vdroop_override_setting; - bool apply_avfs_cks_off_voltage; - uint32_t frame_time_x2; - uint16_t mem_latency_high; - uint16_t mem_latency_low; - uint32_t vr_config; - struct profile_mode_setting current_profile_setting; -}; - -/* To convert to Q8.8 format for firmware */ -#define SMU7_Q88_FORMAT_CONVERSION_UNIT 256 - -enum SMU7_I2CLineID { - SMU7_I2CLineID_DDC1 = 0x90, - SMU7_I2CLineID_DDC2 = 0x91, - SMU7_I2CLineID_DDC3 = 0x92, - SMU7_I2CLineID_DDC4 = 0x93, - SMU7_I2CLineID_DDC5 = 0x94, - SMU7_I2CLineID_DDC6 = 0x95, - SMU7_I2CLineID_SCLSDA = 0x96, - SMU7_I2CLineID_DDCVGA = 0x97 -}; - -#define SMU7_I2C_DDC1DATA 0 -#define SMU7_I2C_DDC1CLK 1 -#define SMU7_I2C_DDC2DATA 2 -#define SMU7_I2C_DDC2CLK 3 -#define SMU7_I2C_DDC3DATA 4 -#define SMU7_I2C_DDC3CLK 5 -#define SMU7_I2C_SDA 40 -#define SMU7_I2C_SCL 41 -#define SMU7_I2C_DDC4DATA 65 -#define SMU7_I2C_DDC4CLK 66 -#define SMU7_I2C_DDC5DATA 0x48 -#define SMU7_I2C_DDC5CLK 0x49 -#define SMU7_I2C_DDC6DATA 0x4a -#define SMU7_I2C_DDC6CLK 0x4b -#define SMU7_I2C_DDCVGADATA 0x4c -#define SMU7_I2C_DDCVGACLK 0x4d - -#define SMU7_UNUSED_GPIO_PIN 0x7F -uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, - uint32_t clock_insr); -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c deleted file mode 100644 index 5d4971576111..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include "hwmgr.h" -#include "smumgr.h" -#include "smu7_hwmgr.h" -#include "smu7_powertune.h" -#include "smu7_common.h" - -#define VOLTAGE_SCALE 4 - -static uint32_t DIDTBlock_Info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; - -static uint32_t Polaris11_DIDTBlock_Info = SQ_PCC_MASK | TCP_IR_MASK | TD_PCC_MASK; - -static const struct gpu_pt_config_reg GCCACConfig_Polaris10[] = { -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060013, GPU_CONFIGREG_GC_CAC_IND }, - - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0013, GPU_CONFIGREG_GC_CAC_IND }, - - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900013, GPU_CONFIGREG_GC_CAC_IND }, - - { 0xFFFFFFFF } -}; - -static const struct gpu_pt_config_reg GCCACConfig_Polaris11[] = { -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060011, GPU_CONFIGREG_GC_CAC_IND }, - - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0011, GPU_CONFIGREG_GC_CAC_IND }, - - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100011, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900011, GPU_CONFIGREG_GC_CAC_IND }, - - { 0xFFFFFFFF } -}; - -static const struct gpu_pt_config_reg DIDTConfig_Polaris10[] = { -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { 0xFFFFFFFF } -}; - -static const struct gpu_pt_config_reg DIDTConfig_Polaris11[] = { -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { 0xFFFFFFFF } -}; - -static const struct gpu_pt_config_reg DIDTConfig_Polaris12[] = { -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { 0xFFFFFFFF } -}; - -static const struct gpu_pt_config_reg DIDTConfig_Polaris11_Kicker[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value Type - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x004c, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00d0, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0069, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x0048, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x005f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x007a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x001f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x002d, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x0088, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - /* DIDT_TD */ - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0008, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - /* DIDT_TCP */ - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT,0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct gpu_pt_config_reg GCCACConfig_VegaM[] = -{ -// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -// Offset Mask Shift Value Type -// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // DIDT_SQ - // - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060013, GPU_CONFIGREG_GC_CAC_IND }, - - // DIDT_TD - // - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0013, GPU_CONFIGREG_GC_CAC_IND }, - - // DIDT_TCP - // - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x00900013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x01900013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02100013, GPU_CONFIGREG_GC_CAC_IND }, - { ixGC_CAC_CNTL, 0xFFFFFFFF, 0, 0x02900013, GPU_CONFIGREG_GC_CAC_IND }, - - { 0xFFFFFFFF } // End of list -}; - -static const struct gpu_pt_config_reg DIDTConfig_VegaM[] = -{ -// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -// Offset Mask Shift Value Type -// --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // DIDT_SQ - // - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT0_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT0__SHIFT, 0x0073, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT1_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT1__SHIFT, 0x00ab, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT2_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT2__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT0_3, DIDT_SQ_WEIGHT0_3__WEIGHT3_MASK, DIDT_SQ_WEIGHT0_3__WEIGHT3__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT4_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT4__SHIFT, 0x0067, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT5_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT5__SHIFT, 0x0084, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT6_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT6__SHIFT, 0x0027, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT4_7, DIDT_SQ_WEIGHT4_7__WEIGHT7_MASK, DIDT_SQ_WEIGHT4_7__WEIGHT7__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT8_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT8__SHIFT, 0x00aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT9_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT9__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT10_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT10__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_WEIGHT8_11, DIDT_SQ_WEIGHT8_11__WEIGHT11_MASK, DIDT_SQ_WEIGHT8_11__WEIGHT11__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__UNUSED_0_MASK, DIDT_SQ_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL_OCP, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_SQ_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_0_MASK, DIDT_SQ_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x005a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_1_MASK, DIDT_SQ_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__UNUSED_2_MASK, DIDT_SQ_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x0ebb, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__UNUSED_0_MASK, DIDT_SQ_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_SQ_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK, DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__USE_REF_CLOCK_MASK, DIDT_SQ_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__UNUSED_0_MASK, DIDT_SQ_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - // DIDT_TD - // - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT0_MASK, DIDT_TD_WEIGHT0_3__WEIGHT0__SHIFT, 0x000a, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT1_MASK, DIDT_TD_WEIGHT0_3__WEIGHT1__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT2_MASK, DIDT_TD_WEIGHT0_3__WEIGHT2__SHIFT, 0x0017, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT0_3, DIDT_TD_WEIGHT0_3__WEIGHT3_MASK, DIDT_TD_WEIGHT0_3__WEIGHT3__SHIFT, 0x002f, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT4_MASK, DIDT_TD_WEIGHT4_7__WEIGHT4__SHIFT, 0x0046, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT5_MASK, DIDT_TD_WEIGHT4_7__WEIGHT5__SHIFT, 0x005d, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT6_MASK, DIDT_TD_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_WEIGHT4_7, DIDT_TD_WEIGHT4_7__WEIGHT7_MASK, DIDT_TD_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__UNUSED_0_MASK, DIDT_TD_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL_OCP, DIDT_TD_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TD_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_0_MASK, DIDT_TD_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x000f, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_1_MASK, DIDT_TD_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__UNUSED_2_MASK, DIDT_TD_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT, 0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__UNUSED_0_MASK, DIDT_TD_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TD_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__UNUSED_0_MASK, DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__USE_REF_CLOCK_MASK, DIDT_TD_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0009, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__UNUSED_0_MASK, DIDT_TD_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - // DIDT_TCP - // - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT0_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT0__SHIFT, 0x0004, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT1_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT1__SHIFT, 0x0037, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT2_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT2__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT0_3, DIDT_TCP_WEIGHT0_3__WEIGHT3_MASK, DIDT_TCP_WEIGHT0_3__WEIGHT3__SHIFT, 0x00ff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT4_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT4__SHIFT, 0x0054, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT5_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT5__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT6_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT6__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_WEIGHT4_7, DIDT_TCP_WEIGHT4_7__WEIGHT7_MASK, DIDT_TCP_WEIGHT4_7__WEIGHT7__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__UNUSED_0_MASK, DIDT_TCP_CTRL_OCP__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL_OCP, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER_MASK, DIDT_TCP_CTRL_OCP__OCP_MAX_POWER__SHIFT, 0xffff, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_0_MASK, DIDT_TCP_CTRL2__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x0032, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_1_MASK, DIDT_TCP_CTRL2__UNUSED_1__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__UNUSED_2_MASK, DIDT_TCP_CTRL2__UNUSED_2__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_CTRL_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_STALL_CTRL__DIDT_HI_POWER_THRESHOLD__SHIFT,0x01aa, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__UNUSED_0_MASK, DIDT_TCP_STALL_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE_MASK, DIDT_TCP_TUNING_CTRL__DIDT_TUNING_ENABLE__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK, DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0001, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__USE_REF_CLOCK_MASK, DIDT_TCP_CTRL0__USE_REF_CLOCK__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_CTRL0__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x0010, GPU_CONFIGREG_DIDT_IND }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__UNUSED_0_MASK, DIDT_TCP_CTRL0__UNUSED_0__SHIFT, 0x0000, GPU_CONFIGREG_DIDT_IND }, - - { 0xFFFFFFFF } // End of list -}; -static int smu7_enable_didt(struct pp_hwmgr *hwmgr, const bool enable) -{ - uint32_t en = enable ? 1 : 0; - uint32_t block_en = 0; - int32_t result = 0; - uint32_t didt_block; - - if (hwmgr->chip_id == CHIP_POLARIS11) - didt_block = Polaris11_DIDTBlock_Info; - else - didt_block = DIDTBlock_Info; - - block_en = PP_CAP(PHM_PlatformCaps_SQRamping) ? en : 0; - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_SQ_CTRL0, DIDT_CTRL_EN, block_en); - didt_block &= ~SQ_Enable_MASK; - didt_block |= block_en << SQ_Enable_SHIFT; - - block_en = PP_CAP(PHM_PlatformCaps_DBRamping) ? en : 0; - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_DB_CTRL0, DIDT_CTRL_EN, block_en); - didt_block &= ~DB_Enable_MASK; - didt_block |= block_en << DB_Enable_SHIFT; - - block_en = PP_CAP(PHM_PlatformCaps_TDRamping) ? en : 0; - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_TD_CTRL0, DIDT_CTRL_EN, block_en); - didt_block &= ~TD_Enable_MASK; - didt_block |= block_en << TD_Enable_SHIFT; - - block_en = PP_CAP(PHM_PlatformCaps_TCPRamping) ? en : 0; - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_TCP_CTRL0, DIDT_CTRL_EN, block_en); - didt_block &= ~TCP_Enable_MASK; - didt_block |= block_en << TCP_Enable_SHIFT; - - if (enable) - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_Didt_Block_Function, - didt_block, - NULL); - - return result; -} - -static int smu7_program_pt_config_registers(struct pp_hwmgr *hwmgr, - const struct gpu_pt_config_reg *cac_config_regs) -{ - const struct gpu_pt_config_reg *config_regs = cac_config_regs; - uint32_t cache = 0; - uint32_t data = 0; - - PP_ASSERT_WITH_CODE((config_regs != NULL), "Invalid config register table.", return -EINVAL); - - while (config_regs->offset != 0xFFFFFFFF) { - if (config_regs->type == GPU_CONFIGREG_CACHE) - cache |= ((config_regs->value << config_regs->shift) & config_regs->mask); - else { - switch (config_regs->type) { - case GPU_CONFIGREG_SMC_IND: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, config_regs->offset); - break; - - case GPU_CONFIGREG_DIDT_IND: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset); - break; - - case GPU_CONFIGREG_GC_CAC_IND: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset); - break; - - default: - data = cgs_read_register(hwmgr->device, config_regs->offset); - break; - } - - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - data |= cache; - - switch (config_regs->type) { - case GPU_CONFIGREG_SMC_IND: - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, config_regs->offset, data); - break; - - case GPU_CONFIGREG_DIDT_IND: - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset, data); - break; - - case GPU_CONFIGREG_GC_CAC_IND: - cgs_write_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset, data); - break; - - default: - cgs_write_register(hwmgr->device, config_regs->offset, data); - break; - } - cache = 0; - } - - config_regs++; - } - - return 0; -} - -int smu7_enable_didt_config(struct pp_hwmgr *hwmgr) -{ - int result; - uint32_t num_se = 0; - uint32_t count, value, value2; - struct amdgpu_device *adev = hwmgr->adev; - - num_se = adev->gfx.config.max_shader_engines; - - if (PP_CAP(PHM_PlatformCaps_SQRamping) || - PP_CAP(PHM_PlatformCaps_DBRamping) || - PP_CAP(PHM_PlatformCaps_TDRamping) || - PP_CAP(PHM_PlatformCaps_TCPRamping)) { - - amdgpu_gfx_rlc_enter_safe_mode(adev); - mutex_lock(&adev->grbm_idx_mutex); - value = 0; - value2 = cgs_read_register(hwmgr->device, mmGRBM_GFX_INDEX); - for (count = 0; count < num_se; count++) { - value = SYS_GRBM_GFX_INDEX_DATA__INSTANCE_BROADCAST_WRITES_MASK - | SYS_GRBM_GFX_INDEX_DATA__SH_BROADCAST_WRITES_MASK - | (count << SYS_GRBM_GFX_INDEX_DATA__SE_INDEX__SHIFT); - cgs_write_register(hwmgr->device, mmGRBM_GFX_INDEX, value); - - if (hwmgr->chip_id == CHIP_POLARIS10) { - result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris10); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris10); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - } else if (hwmgr->chip_id == CHIP_POLARIS11) { - result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - if (hwmgr->is_kicker) - result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11_Kicker); - else - result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris11); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - } else if (hwmgr->chip_id == CHIP_POLARIS12) { - result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_Polaris11); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_Polaris12); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - } else if (hwmgr->chip_id == CHIP_VEGAM) { - result = smu7_program_pt_config_registers(hwmgr, GCCACConfig_VegaM); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - result = smu7_program_pt_config_registers(hwmgr, DIDTConfig_VegaM); - PP_ASSERT_WITH_CODE((result == 0), "DIDT Config failed.", goto error); - } - } - cgs_write_register(hwmgr->device, mmGRBM_GFX_INDEX, value2); - - result = smu7_enable_didt(hwmgr, true); - PP_ASSERT_WITH_CODE((result == 0), "EnableDiDt failed.", goto error); - - if (hwmgr->chip_id == CHIP_POLARIS11) { - result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_EnableDpmDidt), - NULL); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to enable DPM DIDT.", goto error); - } - mutex_unlock(&adev->grbm_idx_mutex); - amdgpu_gfx_rlc_exit_safe_mode(adev); - } - - return 0; -error: - mutex_unlock(&adev->grbm_idx_mutex); - amdgpu_gfx_rlc_exit_safe_mode(adev); - return result; -} - -int smu7_disable_didt_config(struct pp_hwmgr *hwmgr) -{ - int result; - struct amdgpu_device *adev = hwmgr->adev; - - if (PP_CAP(PHM_PlatformCaps_SQRamping) || - PP_CAP(PHM_PlatformCaps_DBRamping) || - PP_CAP(PHM_PlatformCaps_TDRamping) || - PP_CAP(PHM_PlatformCaps_TCPRamping)) { - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - result = smu7_enable_didt(hwmgr, false); - PP_ASSERT_WITH_CODE((result == 0), - "Post DIDT enable clock gating failed.", - goto error); - if (hwmgr->chip_id == CHIP_POLARIS11) { - result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_DisableDpmDidt), - NULL); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to disable DPM DIDT.", goto error); - } - amdgpu_gfx_rlc_exit_safe_mode(adev); - } - - return 0; -error: - amdgpu_gfx_rlc_exit_safe_mode(adev); - return result; -} - -int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - - if (PP_CAP(PHM_PlatformCaps_CAC)) { - int smc_result; - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_EnableCac), - NULL); - PP_ASSERT_WITH_CODE((0 == smc_result), - "Failed to enable CAC in SMC.", result = -1); - - data->cac_enabled = (0 == smc_result) ? true : false; - } - return result; -} - -int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - - if (PP_CAP(PHM_PlatformCaps_CAC) && data->cac_enabled) { - int smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_DisableCac), - NULL); - PP_ASSERT_WITH_CODE((smc_result == 0), - "Failed to disable CAC in SMC.", result = -1); - - data->cac_enabled = false; - } - return result; -} - -int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->power_containment_features & - POWERCONTAINMENT_FEATURE_PkgPwrLimit) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PkgPwrSetLimit, - n<<8, - NULL); - return 0; -} - -static int smu7_set_overdriver_target_tdp(struct pp_hwmgr *hwmgr, - uint32_t target_tdp) -{ - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_OverDriveSetTargetTdp, - target_tdp, - NULL); -} - -int smu7_enable_power_containment(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int smc_result; - int result = 0; - struct phm_cac_tdp_table *cac_table; - - data->power_containment_features = 0; - if (hwmgr->pp_table_version == PP_TABLE_V1) - cac_table = table_info->cac_dtp_table; - else - cac_table = hwmgr->dyn_state.cac_dtp_table; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - if (data->enable_tdc_limit_feature) { - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_TDCLimitEnable), - NULL); - PP_ASSERT_WITH_CODE((0 == smc_result), - "Failed to enable TDCLimit in SMC.", result = -1;); - if (0 == smc_result) - data->power_containment_features |= - POWERCONTAINMENT_FEATURE_TDCLimit; - } - - if (data->enable_pkg_pwr_tracking_feature) { - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable), - NULL); - PP_ASSERT_WITH_CODE((0 == smc_result), - "Failed to enable PkgPwrTracking in SMC.", result = -1;); - if (0 == smc_result) { - hwmgr->default_power_limit = hwmgr->power_limit = - cac_table->usMaximumPowerDeliveryLimit; - data->power_containment_features |= - POWERCONTAINMENT_FEATURE_PkgPwrLimit; - - if (smu7_set_power_limit(hwmgr, hwmgr->power_limit)) - pr_err("Failed to set Default Power Limit in SMC!"); - } - } - } - return result; -} - -int smu7_disable_power_containment(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment) && - data->power_containment_features) { - int smc_result; - - if (data->power_containment_features & - POWERCONTAINMENT_FEATURE_TDCLimit) { - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_TDCLimitDisable), - NULL); - PP_ASSERT_WITH_CODE((smc_result == 0), - "Failed to disable TDCLimit in SMC.", - result = smc_result); - } - - if (data->power_containment_features & - POWERCONTAINMENT_FEATURE_DTE) { - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_DisableDTE), - NULL); - PP_ASSERT_WITH_CODE((smc_result == 0), - "Failed to disable DTE in SMC.", - result = smc_result); - } - - if (data->power_containment_features & - POWERCONTAINMENT_FEATURE_PkgPwrLimit) { - smc_result = smum_send_msg_to_smc(hwmgr, - (uint16_t)(PPSMC_MSG_PkgPwrLimitDisable), - NULL); - PP_ASSERT_WITH_CODE((smc_result == 0), - "Failed to disable PkgPwrTracking in SMC.", - result = smc_result); - } - data->power_containment_features = 0; - } - - return result; -} - -int smu7_power_control_set_level(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_table; - - int adjust_percent, target_tdp; - int result = 0; - - if (hwmgr->pp_table_version == PP_TABLE_V1) - cac_table = table_info->cac_dtp_table; - else - cac_table = hwmgr->dyn_state.cac_dtp_table; - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - /* adjustment percentage has already been validated */ - adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? - hwmgr->platform_descriptor.TDPAdjustment : - (-1 * hwmgr->platform_descriptor.TDPAdjustment); - - if (hwmgr->chip_id > CHIP_TONGA) - target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; - else - target_tdp = ((100 + adjust_percent) * (int)(cac_table->usConfigurableTDP * 256)) / 100; - - result = smu7_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); - } - - return result; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h deleted file mode 100644 index 22f86b6bf1be..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_powertune.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2015 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 _SMU7_POWERTUNE_H -#define _SMU7_POWERTUNE_H - -#define DIDT_SQ_CTRL0__UNUSED_0_MASK 0xfffc0000 -#define DIDT_SQ_CTRL0__UNUSED_0__SHIFT 0x12 -#define DIDT_TD_CTRL0__UNUSED_0_MASK 0xfffc0000 -#define DIDT_TD_CTRL0__UNUSED_0__SHIFT 0x12 -#define DIDT_TCP_CTRL0__UNUSED_0_MASK 0xfffc0000 -#define DIDT_TCP_CTRL0__UNUSED_0__SHIFT 0x12 -#define DIDT_SQ_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 -#define DIDT_SQ_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e -#define DIDT_TD_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 -#define DIDT_TD_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e -#define DIDT_TCP_TUNING_CTRL__UNUSED_0_MASK 0xc0000000 -#define DIDT_TCP_TUNING_CTRL__UNUSED_0__SHIFT 0x0000001e - -/* PowerContainment Features */ -#define POWERCONTAINMENT_FEATURE_DTE 0x00000001 -#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 -#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 - -#define ixGC_CAC_CNTL 0x0000 -#define ixDIDT_SQ_STALL_CTRL 0x0004 -#define ixDIDT_SQ_TUNING_CTRL 0x0005 -#define ixDIDT_TD_STALL_CTRL 0x0044 -#define ixDIDT_TD_TUNING_CTRL 0x0045 -#define ixDIDT_TCP_STALL_CTRL 0x0064 -#define ixDIDT_TCP_TUNING_CTRL 0x0065 - - -int smu7_enable_smc_cac(struct pp_hwmgr *hwmgr); -int smu7_disable_smc_cac(struct pp_hwmgr *hwmgr); -int smu7_enable_power_containment(struct pp_hwmgr *hwmgr); -int smu7_disable_power_containment(struct pp_hwmgr *hwmgr); -int smu7_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); -int smu7_power_control_set_level(struct pp_hwmgr *hwmgr); -int smu7_enable_didt_config(struct pp_hwmgr *hwmgr); -int smu7_disable_didt_config(struct pp_hwmgr *hwmgr); -#endif /* DGPU_POWERTUNE_H */ - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c deleted file mode 100644 index 0b30f73649a8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2016 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 -#include "smu7_thermal.h" -#include "smu7_hwmgr.h" -#include "smu7_common.h" - -int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info) -{ - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return -ENODEV; - - fan_speed_info->supports_percent_read = true; - fan_speed_info->supports_percent_write = true; - fan_speed_info->min_percent = 0; - fan_speed_info->max_percent = 100; - - if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { - fan_speed_info->supports_rpm_read = true; - fan_speed_info->supports_rpm_write = true; - fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; - fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM; - } else { - fan_speed_info->min_rpm = 0; - fan_speed_info->max_rpm = 0; - } - - return 0; -} - -int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t *speed) -{ - uint32_t duty100; - uint32_t duty; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return -ENODEV; - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_STATUS, FDO_PWM_DUTY); - - if (duty100 == 0) - return -EINVAL; - - - tmp64 = (uint64_t)duty * 100; - do_div(tmp64, duty100); - *speed = (uint32_t)tmp64; - - if (*speed > 100) - *speed = 100; - - return 0; -} - -int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) -{ - uint32_t tach_period; - uint32_t crystal_clock_freq; - - if (hwmgr->thermal_controller.fanInfo.bNoFan || - !hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) - return -ENODEV; - - tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_TACH_STATUS, TACH_PERIOD); - - if (tach_period == 0) - return -EINVAL; - - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - *speed = 60 * crystal_clock_freq * 10000 / tach_period; - - return 0; -} - -/** -* Set Fan Speed Control to static mode, so that the user can decide what speed to use. -* @param hwmgr the address of the powerplay hardware manager. -* mode the fan control mode, 0 default, 1 by percent, 5, by RPM -* @exception Should always succeed. -*/ -int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - if (hwmgr->fan_ctrl_is_in_default_mode) { - hwmgr->fan_ctrl_default_mode = - PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, FDO_PWM_MODE); - hwmgr->tmin = - PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, TMIN); - hwmgr->fan_ctrl_is_in_default_mode = false; - } - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, TMIN, 0); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, FDO_PWM_MODE, mode); - - return 0; -} - -/** -* Reset Fan Speed Control to default mode. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Should always succeed. -*/ -int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->fan_ctrl_is_in_default_mode) { - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, TMIN, hwmgr->tmin); - hwmgr->fan_ctrl_is_in_default_mode = true; - } - - return 0; -} - -int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - int result; - - if (PP_CAP(PHM_PlatformCaps_ODFuzzyFanControlSupport)) { - result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl, - FAN_CONTROL_FUZZY, NULL); - - if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM)) - hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr, - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM); - else - hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr, - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanPWM); - - } else { - result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_StartFanControl, - FAN_CONTROL_TABLE, NULL); - } - - if (!result && hwmgr->thermal_controller. - advanceFanControlParameters.ucTargetTemperature) - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanTemperatureTarget, - hwmgr->thermal_controller. - advanceFanControlParameters.ucTargetTemperature, - NULL); - hwmgr->fan_ctrl_enabled = true; - - return result; -} - - -int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - hwmgr->fan_ctrl_enabled = false; - return smum_send_msg_to_smc(hwmgr, PPSMC_StopFanControl, NULL); -} - -/** -* Set Fan Speed in percent. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (0% - 100%) to be set. -* @exception Fails is the 100% setting appears to be 0. -*/ -int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t speed) -{ - uint32_t duty100; - uint32_t duty; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - if (speed > 100) - speed = 100; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - smu7_fan_ctrl_stop_smc_fan_control(hwmgr); - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); - - return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); -} - -/** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. -*/ -int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) -{ - int result; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { - result = smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); - if (!result) - result = smu7_fan_ctrl_start_smc_fan_control(hwmgr); - } else - result = smu7_fan_ctrl_set_default_mode(hwmgr); - - return result; -} - -/** -* Set Fan Speed in RPM. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (min - max) to be set. -* @exception Fails is the speed not lie between min and max. -*/ -int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) -{ - uint32_t tach_period; - uint32_t crystal_clock_freq; - - if (hwmgr->thermal_controller.fanInfo.bNoFan || - (hwmgr->thermal_controller.fanInfo. - ucTachometerPulsesPerRevolution == 0) || - speed == 0 || - (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || - (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return 0; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - smu7_fan_ctrl_stop_smc_fan_control(hwmgr); - - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_TACH_CTRL, TARGET_PERIOD, tach_period); - - return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); -} - -/** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - int temp; - - temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_MULT_THERMAL_STATUS, CTF_TEMP); - - /* Bit 9 means the reading is lower than the lowest usable value. */ - if (temp & 0x200) - temp = SMU7_THERMAL_MAXIMUM_TEMP_READING; - else - temp = temp & 0x1ff; - - temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return temp; -} - -/** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ -static int smu7_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - int low_temp, int high_temp) -{ - int low = SMU7_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = SMU7_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - if (low < low_temp) - low = low_temp; - if (high > high_temp) - high = high_temp; - - if (low > high) - return -EINVAL; - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, DIG_THERM_INTH, - (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, DIG_THERM_INTL, - (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_CTRL, DIG_THERM_DPM, - (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - - return 0; -} - -/** -* Programs thermal controller one-time setting registers -* -* @param hwmgr The address of the hardware manager. -*/ -static int smu7_thermal_initialize(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_TACH_CTRL, EDGE_PER_REV, - hwmgr->thermal_controller.fanInfo. - ucTachometerPulsesPerRevolution - 1); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); - - return 0; -} - -/** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -static void smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr) -{ - uint32_t alert; - - alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, THERM_INT_MASK); - alert &= ~(SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, THERM_INT_MASK, alert); - - /* send message to SMU to enable internal thermal interrupts */ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Enable, NULL); -} - -/** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ -int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr) -{ - uint32_t alert; - - alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, THERM_INT_MASK); - alert |= (SMU7_THERMAL_HIGH_ALERT_MASK | SMU7_THERMAL_LOW_ALERT_MASK); - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_THERMAL_INT, THERM_INT_MASK, alert); - - /* send message to SMU to disable internal thermal interrupts */ - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_Thermal_Cntl_Disable, NULL); -} - -/** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ -int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) -{ - int result = smu7_thermal_disable_alert(hwmgr); - - if (!hwmgr->thermal_controller.fanInfo.bNoFan) - smu7_fan_ctrl_set_default_mode(hwmgr); - - return result; -} - -/** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int smu7_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ -/* If the fantable setup has failed we could have disabled - * PHM_PlatformCaps_MicrocodeFanControl even after - * this function was included in the table. - * Make sure that we still think controlling the fan is OK. -*/ - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { - smu7_fan_ctrl_start_smc_fan_control(hwmgr); - smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); - } - - return 0; -} - -int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - int ret = 0; - - if (range == NULL) - return -EINVAL; - - smu7_thermal_initialize(hwmgr); - ret = smu7_thermal_set_temperature_range(hwmgr, range->min, range->max); - if (ret) - return -EINVAL; - smu7_thermal_enable_alert(hwmgr); - ret = smum_thermal_avfs_enable(hwmgr); - if (ret) - return -EINVAL; - -/* We should restrict performance levels to low before we halt the SMC. - * On the other hand we are still in boot state when we do this - * so it would be pointless. - * If this assumption changes we have to revisit this table. - */ - smum_thermal_setup_fan_table(hwmgr); - smu7_thermal_start_smc_fan_control(hwmgr); - return 0; -} - - - -int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->thermal_controller.fanInfo.bNoFan) - smu7_fan_ctrl_set_default_mode(hwmgr); - return 0; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h deleted file mode 100644 index 42c1ba0fad78..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2016 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 _SMU7_THERMAL_H_ -#define _SMU7_THERMAL_H_ - -#include "hwmgr.h" - -#define SMU7_THERMAL_HIGH_ALERT_MASK 0x1 -#define SMU7_THERMAL_LOW_ALERT_MASK 0x2 - -#define SMU7_THERMAL_MINIMUM_TEMP_READING -256 -#define SMU7_THERMAL_MAXIMUM_TEMP_READING 255 - -#define SMU7_THERMAL_MINIMUM_ALERT_TEMP 0 -#define SMU7_THERMAL_MAXIMUM_ALERT_TEMP 255 - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -extern int smu7_thermal_get_temperature(struct pp_hwmgr *hwmgr); -extern int smu7_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); -extern int smu7_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); -extern int smu7_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed); -extern int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); -extern int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode); -extern int smu7_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); -extern int smu7_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); -extern int smu7_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr); -extern int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed); -extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); -extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr); -extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int smu7_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *temperature_range); -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c deleted file mode 100644 index 35ed47ebaf09..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c +++ /dev/null @@ -1,2049 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include "atom-types.h" -#include "atombios.h" -#include "processpptables.h" -#include "cgs_common.h" -#include "smu/smu_8_0_d.h" -#include "smu8_fusion.h" -#include "smu/smu_8_0_sh_mask.h" -#include "smumgr.h" -#include "hwmgr.h" -#include "hardwaremanager.h" -#include "cz_ppsmc.h" -#include "smu8_hwmgr.h" -#include "power_state.h" -#include "pp_thermal.h" - -#define ixSMUSVI_NB_CURRENTVID 0xD8230044 -#define CURRENT_NB_VID_MASK 0xff000000 -#define CURRENT_NB_VID__SHIFT 24 -#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 -#define CURRENT_GFX_VID_MASK 0xff000000 -#define CURRENT_GFX_VID__SHIFT 24 - -static const unsigned long smu8_magic = (unsigned long) PHM_Cz_Magic; - -static struct smu8_power_state *cast_smu8_power_state(struct pp_hw_power_state *hw_ps) -{ - if (smu8_magic != hw_ps->magic) - return NULL; - - return (struct smu8_power_state *)hw_ps; -} - -static const struct smu8_power_state *cast_const_smu8_power_state( - const struct pp_hw_power_state *hw_ps) -{ - if (smu8_magic != hw_ps->magic) - return NULL; - - return (struct smu8_power_state *)hw_ps; -} - -static uint32_t smu8_get_eclk_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint32_t msg) -{ - int i = 0; - struct phm_vce_clock_voltage_dependency_table *ptable = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - switch (msg) { - case PPSMC_MSG_SetEclkSoftMin: - case PPSMC_MSG_SetEclkHardMin: - for (i = 0; i < (int)ptable->count; i++) { - if (clock <= ptable->entries[i].ecclk) - break; - } - break; - - case PPSMC_MSG_SetEclkSoftMax: - case PPSMC_MSG_SetEclkHardMax: - for (i = ptable->count - 1; i >= 0; i--) { - if (clock >= ptable->entries[i].ecclk) - break; - } - break; - - default: - break; - } - - return i; -} - -static uint32_t smu8_get_sclk_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint32_t msg) -{ - int i = 0; - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - - switch (msg) { - case PPSMC_MSG_SetSclkSoftMin: - case PPSMC_MSG_SetSclkHardMin: - for (i = 0; i < (int)table->count; i++) { - if (clock <= table->entries[i].clk) - break; - } - break; - - case PPSMC_MSG_SetSclkSoftMax: - case PPSMC_MSG_SetSclkHardMax: - for (i = table->count - 1; i >= 0; i--) { - if (clock >= table->entries[i].clk) - break; - } - break; - - default: - break; - } - return i; -} - -static uint32_t smu8_get_uvd_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint32_t msg) -{ - int i = 0; - struct phm_uvd_clock_voltage_dependency_table *ptable = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - - switch (msg) { - case PPSMC_MSG_SetUvdSoftMin: - case PPSMC_MSG_SetUvdHardMin: - for (i = 0; i < (int)ptable->count; i++) { - if (clock <= ptable->entries[i].vclk) - break; - } - break; - - case PPSMC_MSG_SetUvdSoftMax: - case PPSMC_MSG_SetUvdHardMax: - for (i = ptable->count - 1; i >= 0; i--) { - if (clock >= ptable->entries[i].vclk) - break; - } - break; - - default: - break; - } - - return i; -} - -static uint32_t smu8_get_max_sclk_level(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - if (data->max_sclk_level == 0) { - smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetMaxSclkLevel, - &data->max_sclk_level); - data->max_sclk_level += 1; - } - - return data->max_sclk_level; -} - -static int smu8_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct amdgpu_device *adev = hwmgr->adev; - - data->gfx_ramp_step = 256*25/100; - data->gfx_ramp_delay = 1; /* by default, we delay 1us */ - - data->mgcg_cgtt_local0 = 0x00000000; - data->mgcg_cgtt_local1 = 0x00000000; - data->clock_slow_down_freq = 25000; - data->skip_clock_slow_down = 1; - data->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */ - data->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */ - data->voting_rights_clients = 0x00C00033; - data->static_screen_threshold = 8; - data->ddi_power_gating_disabled = 0; - data->bapm_enabled = 1; - data->voltage_drop_threshold = 0; - data->gfx_power_gating_threshold = 500; - data->vce_slow_sclk_threshold = 20000; - data->dce_slow_sclk_threshold = 30000; - data->disable_driver_thermal_policy = 1; - data->disable_nb_ps3_in_battery = 0; - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ABM); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_NonABMSupportInPPLib); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicM3Arbiter); - - data->override_dynamic_mgpg = 1; - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPatchPowerState); - - data->thermal_auto_throttling_treshold = 0; - data->tdr_clock = 0; - data->disable_gfx_power_gating_in_uvd = 0; - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicUVDState); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEDPM); - - data->cc6_settings.cpu_cc6_disable = false; - data->cc6_settings.cpu_pstate_disable = false; - data->cc6_settings.nb_pstate_switch_disable = false; - data->cc6_settings.cpu_pstate_separation_time = 0; - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DisableVoltageIsland); - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - if (adev->pg_flags & AMD_PG_SUPPORT_UVD) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - if (adev->pg_flags & AMD_PG_SUPPORT_VCE) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - - return 0; -} - -/* convert form 8bit vid to real voltage in mV*4 */ -static uint32_t smu8_convert_8Bit_index_to_voltage( - struct pp_hwmgr *hwmgr, uint16_t voltage) -{ - return 6200 - (voltage * 25); -} - -static int smu8_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *table) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct smu8_sys_info *sys_info = &data->sys_info; - struct phm_clock_voltage_dependency_table *dep_table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - - if (dep_table->count > 0) { - table->sclk = dep_table->entries[dep_table->count-1].clk; - table->vddc = smu8_convert_8Bit_index_to_voltage(hwmgr, - (uint16_t)dep_table->entries[dep_table->count-1].v); - } - table->mclk = sys_info->nbp_memory_clock[0]; - return 0; -} - -static int smu8_init_dynamic_state_adjustment_rule_settings( - struct pp_hwmgr *hwmgr, - ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table) -{ - struct phm_clock_voltage_dependency_table *table_clk_vlt; - - table_clk_vlt = kzalloc(struct_size(table_clk_vlt, entries, 7), - GFP_KERNEL); - - if (NULL == table_clk_vlt) { - pr_err("Can not allocate memory!\n"); - return -ENOMEM; - } - - table_clk_vlt->count = 8; - table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; - table_clk_vlt->entries[0].v = 0; - table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; - table_clk_vlt->entries[1].v = 1; - table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; - table_clk_vlt->entries[2].v = 2; - table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; - table_clk_vlt->entries[3].v = 3; - table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; - table_clk_vlt->entries[4].v = 4; - table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; - table_clk_vlt->entries[5].v = 5; - table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; - table_clk_vlt->entries[6].v = 6; - table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; - table_clk_vlt->entries[7].v = 7; - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; - - return 0; -} - -static int smu8_get_system_info_data(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL; - uint32_t i; - int result = 0; - uint8_t frev, crev; - uint16_t size; - - info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *)smu_atom_get_data_table(hwmgr->adev, - GetIndexIntoMasterTable(DATA, IntegratedSystemInfo), - &size, &frev, &crev); - - if (info == NULL) { - pr_err("Could not retrieve the Integrated System Info Table!\n"); - return -EINVAL; - } - - if (crev != 9) { - pr_err("Unsupported IGP table: %d %d\n", frev, crev); - return -EINVAL; - } - - data->sys_info.bootup_uma_clock = - le32_to_cpu(info->ulBootUpUMAClock); - - data->sys_info.bootup_engine_clock = - le32_to_cpu(info->ulBootUpEngineClock); - - data->sys_info.dentist_vco_freq = - le32_to_cpu(info->ulDentistVCOFreq); - - data->sys_info.system_config = - le32_to_cpu(info->ulSystemConfig); - - data->sys_info.bootup_nb_voltage_index = - le16_to_cpu(info->usBootUpNBVoltage); - - data->sys_info.htc_hyst_lmt = - (info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt; - - data->sys_info.htc_tmp_lmt = - (info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt; - - if (data->sys_info.htc_tmp_lmt <= - data->sys_info.htc_hyst_lmt) { - pr_err("The htcTmpLmt should be larger than htcHystLmt.\n"); - return -EINVAL; - } - - data->sys_info.nb_dpm_enable = - data->enable_nb_ps_policy && - (le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1); - - for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { - if (i < SMU8_NUM_NBPMEMORYCLOCK) { - data->sys_info.nbp_memory_clock[i] = - le32_to_cpu(info->ulNbpStateMemclkFreq[i]); - } - data->sys_info.nbp_n_clock[i] = - le32_to_cpu(info->ulNbpStateNClkFreq[i]); - } - - for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) { - data->sys_info.display_clock[i] = - le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK); - } - - /* Here use 4 levels, make sure not exceed */ - for (i = 0; i < SMU8_NUM_NBPSTATES; i++) { - data->sys_info.nbp_voltage_index[i] = - le16_to_cpu(info->usNBPStateVoltage[i]); - } - - if (!data->sys_info.nb_dpm_enable) { - for (i = 1; i < SMU8_NUM_NBPSTATES; i++) { - if (i < SMU8_NUM_NBPMEMORYCLOCK) { - data->sys_info.nbp_memory_clock[i] = - data->sys_info.nbp_memory_clock[0]; - } - data->sys_info.nbp_n_clock[i] = - data->sys_info.nbp_n_clock[0]; - data->sys_info.nbp_voltage_index[i] = - data->sys_info.nbp_voltage_index[0]; - } - } - - if (le32_to_cpu(info->ulGPUCapInfo) & - SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableDFSBypass); - } - - data->sys_info.uma_channel_number = info->ucUMAChannelNumber; - - smu8_construct_max_power_limits_table (hwmgr, - &hwmgr->dyn_state.max_clock_voltage_on_ac); - - smu8_init_dynamic_state_adjustment_rule_settings(hwmgr, - &info->sDISPCLK_Voltage[0]); - - return result; -} - -static int smu8_construct_boot_state(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->boot_power_level.engineClock = - data->sys_info.bootup_engine_clock; - - data->boot_power_level.vddcIndex = - (uint8_t)data->sys_info.bootup_nb_voltage_index; - - data->boot_power_level.dsDividerIndex = 0; - data->boot_power_level.ssDividerIndex = 0; - data->boot_power_level.allowGnbSlow = 1; - data->boot_power_level.forceNBPstate = 0; - data->boot_power_level.hysteresis_up = 0; - data->boot_power_level.numSIMDToPowerDown = 0; - data->boot_power_level.display_wm = 0; - data->boot_power_level.vce_wm = 0; - - return 0; -} - -static int smu8_upload_pptable_to_smu(struct pp_hwmgr *hwmgr) -{ - struct SMU8_Fusion_ClkTable *clock_table; - int ret; - uint32_t i; - void *table = NULL; - pp_atomctrl_clock_dividers_kong dividers; - - struct phm_clock_voltage_dependency_table *vddc_table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - struct phm_clock_voltage_dependency_table *vdd_gfx_table = - hwmgr->dyn_state.vdd_gfx_dependency_on_sclk; - struct phm_acp_clock_voltage_dependency_table *acp_table = - hwmgr->dyn_state.acp_clock_voltage_dependency_table; - struct phm_uvd_clock_voltage_dependency_table *uvd_table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - struct phm_vce_clock_voltage_dependency_table *vce_table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - if (!hwmgr->need_pp_table_upload) - return 0; - - ret = smum_download_powerplay_table(hwmgr, &table); - - PP_ASSERT_WITH_CODE((0 == ret && NULL != table), - "Fail to get clock table from SMU!", return -EINVAL;); - - clock_table = (struct SMU8_Fusion_ClkTable *)table; - - /* patch clock table */ - PP_ASSERT_WITH_CODE((vddc_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), - "Dependency table entry exceeds max limit!", return -EINVAL;); - PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), - "Dependency table entry exceeds max limit!", return -EINVAL;); - PP_ASSERT_WITH_CODE((acp_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), - "Dependency table entry exceeds max limit!", return -EINVAL;); - PP_ASSERT_WITH_CODE((uvd_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), - "Dependency table entry exceeds max limit!", return -EINVAL;); - PP_ASSERT_WITH_CODE((vce_table->count <= SMU8_MAX_HARDWARE_POWERLEVELS), - "Dependency table entry exceeds max limit!", return -EINVAL;); - - for (i = 0; i < SMU8_MAX_HARDWARE_POWERLEVELS; i++) { - - /* vddc_sclk */ - clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid = - (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0; - clock_table->SclkBreakdownTable.ClkLevel[i].Frequency = - (i < vddc_table->count) ? vddc_table->entries[i].clk : 0; - - atomctrl_get_engine_pll_dividers_kong(hwmgr, - clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, - ÷rs); - - clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid = - (uint8_t)dividers.pll_post_divider; - - /* vddgfx_sclk */ - clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid = - (i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0; - - /* acp breakdown */ - clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid = - (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0; - clock_table->AclkBreakdownTable.ClkLevel[i].Frequency = - (i < acp_table->count) ? acp_table->entries[i].acpclk : 0; - - atomctrl_get_engine_pll_dividers_kong(hwmgr, - clock_table->AclkBreakdownTable.ClkLevel[i].Frequency, - ÷rs); - - clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid = - (uint8_t)dividers.pll_post_divider; - - - /* uvd breakdown */ - clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid = - (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; - clock_table->VclkBreakdownTable.ClkLevel[i].Frequency = - (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0; - - atomctrl_get_engine_pll_dividers_kong(hwmgr, - clock_table->VclkBreakdownTable.ClkLevel[i].Frequency, - ÷rs); - - clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid = - (uint8_t)dividers.pll_post_divider; - - clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid = - (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; - clock_table->DclkBreakdownTable.ClkLevel[i].Frequency = - (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0; - - atomctrl_get_engine_pll_dividers_kong(hwmgr, - clock_table->DclkBreakdownTable.ClkLevel[i].Frequency, - ÷rs); - - clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid = - (uint8_t)dividers.pll_post_divider; - - /* vce breakdown */ - clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid = - (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0; - clock_table->EclkBreakdownTable.ClkLevel[i].Frequency = - (i < vce_table->count) ? vce_table->entries[i].ecclk : 0; - - - atomctrl_get_engine_pll_dividers_kong(hwmgr, - clock_table->EclkBreakdownTable.ClkLevel[i].Frequency, - ÷rs); - - clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid = - (uint8_t)dividers.pll_post_divider; - - } - ret = smum_upload_powerplay_table(hwmgr); - - return ret; -} - -static int smu8_init_sclk_limit(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - unsigned long clock = 0, level; - - if (NULL == table || table->count <= 0) - return -EINVAL; - - data->sclk_dpm.soft_min_clk = table->entries[0].clk; - data->sclk_dpm.hard_min_clk = table->entries[0].clk; - - level = smu8_get_max_sclk_level(hwmgr) - 1; - - if (level < table->count) - clock = table->entries[level].clk; - else - clock = table->entries[table->count - 1].clk; - - data->sclk_dpm.soft_max_clk = clock; - data->sclk_dpm.hard_max_clk = clock; - - return 0; -} - -static int smu8_init_uvd_limit(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_uvd_clock_voltage_dependency_table *table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - unsigned long clock = 0; - uint32_t level; - - if (NULL == table || table->count <= 0) - return -EINVAL; - - data->uvd_dpm.soft_min_clk = 0; - data->uvd_dpm.hard_min_clk = 0; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxUvdLevel, &level); - - if (level < table->count) - clock = table->entries[level].vclk; - else - clock = table->entries[table->count - 1].vclk; - - data->uvd_dpm.soft_max_clk = clock; - data->uvd_dpm.hard_max_clk = clock; - - return 0; -} - -static int smu8_init_vce_limit(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_vce_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - unsigned long clock = 0; - uint32_t level; - - if (NULL == table || table->count <= 0) - return -EINVAL; - - data->vce_dpm.soft_min_clk = 0; - data->vce_dpm.hard_min_clk = 0; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxEclkLevel, &level); - - if (level < table->count) - clock = table->entries[level].ecclk; - else - clock = table->entries[table->count - 1].ecclk; - - data->vce_dpm.soft_max_clk = clock; - data->vce_dpm.hard_max_clk = clock; - - return 0; -} - -static int smu8_init_acp_limit(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_acp_clock_voltage_dependency_table *table = - hwmgr->dyn_state.acp_clock_voltage_dependency_table; - unsigned long clock = 0; - uint32_t level; - - if (NULL == table || table->count <= 0) - return -EINVAL; - - data->acp_dpm.soft_min_clk = 0; - data->acp_dpm.hard_min_clk = 0; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetMaxAclkLevel, &level); - - if (level < table->count) - clock = table->entries[level].acpclk; - else - clock = table->entries[table->count - 1].acpclk; - - data->acp_dpm.soft_max_clk = clock; - data->acp_dpm.hard_max_clk = clock; - return 0; -} - -static void smu8_init_power_gate_state(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->uvd_power_gated = false; - data->vce_power_gated = false; - data->samu_power_gated = false; -#ifdef CONFIG_DRM_AMD_ACP - data->acp_power_gated = false; -#else - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF, NULL); - data->acp_power_gated = true; -#endif - -} - -static void smu8_init_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->low_sclk_interrupt_threshold = 0; -} - -static int smu8_update_sclk_limit(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - - unsigned long clock = 0; - unsigned long level; - unsigned long stable_pstate_sclk; - unsigned long percentage; - - data->sclk_dpm.soft_min_clk = table->entries[0].clk; - level = smu8_get_max_sclk_level(hwmgr) - 1; - - if (level < table->count) - data->sclk_dpm.soft_max_clk = table->entries[level].clk; - else - data->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk; - - clock = hwmgr->display_config->min_core_set_clock; - if (clock == 0) - pr_debug("min_core_set_clock not set\n"); - - if (data->sclk_dpm.hard_min_clk != clock) { - data->sclk_dpm.hard_min_clk = clock; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkHardMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.hard_min_clk, - PPSMC_MSG_SetSclkHardMin), - NULL); - } - - clock = data->sclk_dpm.soft_min_clk; - - /* update minimum clocks for Stable P-State feature */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) { - percentage = 75; - /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */ - stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk * - percentage) / 100; - - if (clock < stable_pstate_sclk) - clock = stable_pstate_sclk; - } - - if (data->sclk_dpm.soft_min_clk != clock) { - data->sclk_dpm.soft_min_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_min_clk, - PPSMC_MSG_SetSclkSoftMin), - NULL); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState) && - data->sclk_dpm.soft_max_clk != clock) { - data->sclk_dpm.soft_max_clk = clock; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_max_clk, - PPSMC_MSG_SetSclkSoftMax), - NULL); - } - - return 0; -} - -static int smu8_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) { - uint32_t clks = hwmgr->display_config->min_core_set_clock_in_sr; - if (clks == 0) - clks = SMU8_MIN_DEEP_SLEEP_SCLK; - - PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinDeepSleepSclk, - clks, - NULL); - } - - return 0; -} - -static int smu8_set_watermark_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = - hwmgr->backend; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetWatermarkFrequency, - data->sclk_dpm.soft_max_clk, - NULL); - - return 0; -} - -static int smu8_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - - if (hw_data->is_nb_dpm_enabled) { - if (enable) { - PP_DBG_LOG("enable Low Memory PState.\n"); - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableLowMemoryPstate, - (lock ? 1 : 0), - NULL); - } else { - PP_DBG_LOG("disable Low Memory PState.\n"); - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableLowMemoryPstate, - (lock ? 1 : 0), - NULL); - } - } - - return 0; -} - -static int smu8_disable_nb_dpm(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - struct smu8_hwmgr *data = hwmgr->backend; - unsigned long dpm_features = 0; - - if (data->is_nb_dpm_enabled) { - smu8_nbdpm_pstate_enable_disable(hwmgr, true, true); - dpm_features |= NB_DPM_MASK; - ret = smum_send_msg_to_smc_with_parameter( - hwmgr, - PPSMC_MSG_DisableAllSmuFeatures, - dpm_features, - NULL); - if (ret == 0) - data->is_nb_dpm_enabled = false; - } - - return ret; -} - -static int smu8_enable_nb_dpm(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - struct smu8_hwmgr *data = hwmgr->backend; - unsigned long dpm_features = 0; - - if (!data->is_nb_dpm_enabled) { - PP_DBG_LOG("enabling ALL SMU features.\n"); - dpm_features |= NB_DPM_MASK; - ret = smum_send_msg_to_smc_with_parameter( - hwmgr, - PPSMC_MSG_EnableAllSmuFeatures, - dpm_features, - NULL); - if (ret == 0) - data->is_nb_dpm_enabled = true; - } - - return ret; -} - -static int smu8_update_low_mem_pstate(struct pp_hwmgr *hwmgr, const void *input) -{ - bool disable_switch; - bool enable_low_mem_state; - struct smu8_hwmgr *hw_data = hwmgr->backend; - const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input; - const struct smu8_power_state *pnew_state = cast_const_smu8_power_state(states->pnew_state); - - if (hw_data->sys_info.nb_dpm_enable) { - disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false; - enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true; - - if (pnew_state->action == FORCE_HIGH) - smu8_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch); - else if (pnew_state->action == CANCEL_FORCE_HIGH) - smu8_nbdpm_pstate_enable_disable(hwmgr, true, disable_switch); - else - smu8_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch); - } - return 0; -} - -static int smu8_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) -{ - int ret = 0; - - smu8_update_sclk_limit(hwmgr); - smu8_set_deep_sleep_sclk_threshold(hwmgr); - smu8_set_watermark_threshold(hwmgr); - ret = smu8_enable_nb_dpm(hwmgr); - if (ret) - return ret; - smu8_update_low_mem_pstate(hwmgr, input); - - return 0; -} - - -static int smu8_setup_asic_task(struct pp_hwmgr *hwmgr) -{ - int ret; - - ret = smu8_upload_pptable_to_smu(hwmgr); - if (ret) - return ret; - ret = smu8_init_sclk_limit(hwmgr); - if (ret) - return ret; - ret = smu8_init_uvd_limit(hwmgr); - if (ret) - return ret; - ret = smu8_init_vce_limit(hwmgr); - if (ret) - return ret; - ret = smu8_init_acp_limit(hwmgr); - if (ret) - return ret; - - smu8_init_power_gate_state(hwmgr); - smu8_init_sclk_threshold(hwmgr); - - return 0; -} - -static void smu8_power_up_display_clock_sys_pll(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - - hw_data->disp_clk_bypass_pending = false; - hw_data->disp_clk_bypass = false; -} - -static void smu8_clear_nb_dpm_flag(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - - hw_data->is_nb_dpm_enabled = false; -} - -static void smu8_reset_cc6_data(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - - hw_data->cc6_settings.cc6_setting_changed = false; - hw_data->cc6_settings.cpu_pstate_separation_time = 0; - hw_data->cc6_settings.cpu_cc6_disable = false; - hw_data->cc6_settings.cpu_pstate_disable = false; -} - -static void smu8_program_voting_clients(struct pp_hwmgr *hwmgr) -{ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0, - SMU8_VOTINGRIGHTSCLIENTS_DFLT0); -} - -static void smu8_clear_voting_clients(struct pp_hwmgr *hwmgr) -{ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_FREQ_TRAN_VOTING_0, 0); -} - -static int smu8_start_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->dpm_flags |= DPMFlags_SCLK_Enabled; - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableAllSmuFeatures, - SCLK_DPM_MASK, - NULL); -} - -static int smu8_stop_dpm(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - struct smu8_hwmgr *data = hwmgr->backend; - unsigned long dpm_features = 0; - - if (data->dpm_flags & DPMFlags_SCLK_Enabled) { - dpm_features |= SCLK_DPM_MASK; - data->dpm_flags &= ~DPMFlags_SCLK_Enabled; - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableAllSmuFeatures, - dpm_features, - NULL); - } - return ret; -} - -static int smu8_program_bootup_state(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->sclk_dpm.soft_min_clk = data->sys_info.bootup_engine_clock; - data->sclk_dpm.soft_max_clk = data->sys_info.bootup_engine_clock; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_min_clk, - PPSMC_MSG_SetSclkSoftMin), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_max_clk, - PPSMC_MSG_SetSclkSoftMax), - NULL); - - return 0; -} - -static void smu8_reset_acp_boot_level(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->acp_boot_level = 0xff; -} - -static int smu8_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - smu8_program_voting_clients(hwmgr); - if (smu8_start_dpm(hwmgr)) - return -EINVAL; - smu8_program_bootup_state(hwmgr); - smu8_reset_acp_boot_level(hwmgr); - - return 0; -} - -static int smu8_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - smu8_disable_nb_dpm(hwmgr); - - smu8_clear_voting_clients(hwmgr); - if (smu8_stop_dpm(hwmgr)) - return -EINVAL; - - return 0; -} - -static int smu8_power_off_asic(struct pp_hwmgr *hwmgr) -{ - smu8_disable_dpm_tasks(hwmgr); - smu8_power_up_display_clock_sys_pll(hwmgr); - smu8_clear_nb_dpm_flag(hwmgr); - smu8_reset_cc6_data(hwmgr); - return 0; -} - -static int smu8_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *prequest_ps, - const struct pp_power_state *pcurrent_ps) -{ - struct smu8_power_state *smu8_ps = - cast_smu8_power_state(&prequest_ps->hardware); - - const struct smu8_power_state *smu8_current_ps = - cast_const_smu8_power_state(&pcurrent_ps->hardware); - - struct smu8_hwmgr *data = hwmgr->backend; - struct PP_Clocks clocks = {0, 0, 0, 0}; - bool force_high; - - smu8_ps->need_dfs_bypass = true; - - data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); - - clocks.memoryClock = hwmgr->display_config->min_mem_set_clock != 0 ? - hwmgr->display_config->min_mem_set_clock : - data->sys_info.nbp_memory_clock[1]; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk; - - force_high = (clocks.memoryClock > data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]) - || (hwmgr->display_config->num_display >= 3); - - smu8_ps->action = smu8_current_ps->action; - - if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - smu8_nbdpm_pstate_enable_disable(hwmgr, false, false); - else if (hwmgr->request_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD) - smu8_nbdpm_pstate_enable_disable(hwmgr, false, true); - else if (!force_high && (smu8_ps->action == FORCE_HIGH)) - smu8_ps->action = CANCEL_FORCE_HIGH; - else if (force_high && (smu8_ps->action != FORCE_HIGH)) - smu8_ps->action = FORCE_HIGH; - else - smu8_ps->action = DO_NOTHING; - - return 0; -} - -static int smu8_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct smu8_hwmgr *data; - - data = kzalloc(sizeof(struct smu8_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - - result = smu8_initialize_dpm_defaults(hwmgr); - if (result != 0) { - pr_err("smu8_initialize_dpm_defaults failed\n"); - return result; - } - - result = smu8_get_system_info_data(hwmgr); - if (result != 0) { - pr_err("smu8_get_system_info_data failed\n"); - return result; - } - - smu8_construct_boot_state(hwmgr); - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = SMU8_MAX_HARDWARE_POWERLEVELS; - - return result; -} - -static int smu8_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - if (hwmgr != NULL) { - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - - kfree(hwmgr->backend); - hwmgr->backend = NULL; - } - return 0; -} - -static int smu8_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_max_clk, - PPSMC_MSG_SetSclkSoftMin), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_max_clk, - PPSMC_MSG_SetSclkSoftMax), - NULL); - - return 0; -} - -static int smu8_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - unsigned long clock = 0, level; - - if (NULL == table || table->count <= 0) - return -EINVAL; - - data->sclk_dpm.soft_min_clk = table->entries[0].clk; - data->sclk_dpm.hard_min_clk = table->entries[0].clk; - hwmgr->pstate_sclk = table->entries[0].clk; - hwmgr->pstate_mclk = 0; - - level = smu8_get_max_sclk_level(hwmgr) - 1; - - if (level < table->count) - clock = table->entries[level].clk; - else - clock = table->entries[table->count - 1].clk; - - data->sclk_dpm.soft_max_clk = clock; - data->sclk_dpm.hard_max_clk = clock; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_min_clk, - PPSMC_MSG_SetSclkSoftMin), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_max_clk, - PPSMC_MSG_SetSclkSoftMax), - NULL); - - return 0; -} - -static int smu8_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_min_clk, - PPSMC_MSG_SetSclkSoftMax), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - smu8_get_sclk_level(hwmgr, - data->sclk_dpm.soft_min_clk, - PPSMC_MSG_SetSclkSoftMin), - NULL); - - return 0; -} - -static int smu8_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - int ret = 0; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = smu8_phm_force_dpm_highest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = smu8_phm_force_dpm_lowest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = smu8_phm_unforce_dpm_levels(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - - return ret; -} - -static int smu8_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) -{ - if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF, NULL); - return 0; -} - -static int smu8_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) -{ - if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { - return smum_send_msg_to_smc_with_parameter( - hwmgr, - PPSMC_MSG_UVDPowerON, - PP_CAP(PHM_PlatformCaps_UVDDynamicPowerGating) ? 1 : 0, - NULL); - } - - return 0; -} - -static int smu8_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_vce_clock_voltage_dependency_table *ptable = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ - if (PP_CAP(PHM_PlatformCaps_StablePState) || - hwmgr->en_umd_pstate) { - data->vce_dpm.hard_min_clk = - ptable->entries[ptable->count - 1].ecclk; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetEclkHardMin, - smu8_get_eclk_level(hwmgr, - data->vce_dpm.hard_min_clk, - PPSMC_MSG_SetEclkHardMin), - NULL); - } else { - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetEclkHardMin, - 0, - NULL); - /* disable ECLK DPM 0. Otherwise VCE could hang if - * switching SCLK from DPM 0 to 6/7 */ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetEclkSoftMin, - 1, - NULL); - } - return 0; -} - -static int smu8_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) -{ - if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_VCEPowerOFF, - NULL); - return 0; -} - -static int smu8_dpm_powerup_vce(struct pp_hwmgr *hwmgr) -{ - if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_VCEPowerON, - NULL); - return 0; -} - -static uint32_t smu8_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - return data->sys_info.bootup_uma_clock; -} - -static uint32_t smu8_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct pp_power_state *ps; - struct smu8_power_state *smu8_ps; - - if (hwmgr == NULL) - return -EINVAL; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - smu8_ps = cast_smu8_power_state(&ps->hardware); - - if (low) - return smu8_ps->levels[0].engineClock; - else - return smu8_ps->levels[smu8_ps->level-1].engineClock; -} - -static int smu8_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); - - smu8_ps->level = 1; - smu8_ps->nbps_flags = 0; - smu8_ps->bapm_flags = 0; - smu8_ps->levels[0] = data->boot_power_level; - - return 0; -} - -static int smu8_dpm_get_pp_table_entry_callback( - struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps, - unsigned int index, - const void *clock_info) -{ - struct smu8_power_state *smu8_ps = cast_smu8_power_state(hw_ps); - - const ATOM_PPLIB_CZ_CLOCK_INFO *smu8_clock_info = clock_info; - - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - uint8_t clock_info_index = smu8_clock_info->index; - - if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1)) - clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1); - - smu8_ps->levels[index].engineClock = table->entries[clock_info_index].clk; - smu8_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v; - - smu8_ps->level = index + 1; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { - smu8_ps->levels[index].dsDividerIndex = 5; - smu8_ps->levels[index].ssDividerIndex = 5; - } - - return 0; -} - -static int smu8_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) -{ - int result; - unsigned long ret = 0; - - result = pp_tables_get_num_of_entries(hwmgr, &ret); - - return result ? 0 : ret; -} - -static int smu8_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, - unsigned long entry, struct pp_power_state *ps) -{ - int result; - struct smu8_power_state *smu8_ps; - - ps->hardware.magic = smu8_magic; - - smu8_ps = cast_smu8_power_state(&(ps->hardware)); - - result = pp_tables_get_entry(hwmgr, entry, ps, - smu8_dpm_get_pp_table_entry_callback); - - smu8_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; - smu8_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; - - return result; -} - -static int smu8_get_power_state_size(struct pp_hwmgr *hwmgr) -{ - return sizeof(struct smu8_power_state); -} - -static void smu8_hw_print_display_cfg( - const struct cc6_settings *cc6_settings) -{ - PP_DBG_LOG("New Display Configuration:\n"); - - PP_DBG_LOG(" cpu_cc6_disable: %d\n", - cc6_settings->cpu_cc6_disable); - PP_DBG_LOG(" cpu_pstate_disable: %d\n", - cc6_settings->cpu_pstate_disable); - PP_DBG_LOG(" nb_pstate_switch_disable: %d\n", - cc6_settings->nb_pstate_switch_disable); - PP_DBG_LOG(" cpu_pstate_separation_time: %d\n\n", - cc6_settings->cpu_pstate_separation_time); -} - - static int smu8_set_cpu_power_state(struct pp_hwmgr *hwmgr) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - uint32_t data = 0; - - if (hw_data->cc6_settings.cc6_setting_changed) { - - hw_data->cc6_settings.cc6_setting_changed = false; - - smu8_hw_print_display_cfg(&hw_data->cc6_settings); - - data |= (hw_data->cc6_settings.cpu_pstate_separation_time - & PWRMGT_SEPARATION_TIME_MASK) - << PWRMGT_SEPARATION_TIME_SHIFT; - - data |= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0) - << PWRMGT_DISABLE_CPU_CSTATES_SHIFT; - - data |= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0) - << PWRMGT_DISABLE_CPU_PSTATES_SHIFT; - - PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n", - data); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDisplaySizePowerParams, - data, - NULL); - } - - return 0; -} - - -static int smu8_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, - bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) -{ - struct smu8_hwmgr *hw_data = hwmgr->backend; - - if (separation_time != - hw_data->cc6_settings.cpu_pstate_separation_time || - cc6_disable != hw_data->cc6_settings.cpu_cc6_disable || - pstate_disable != hw_data->cc6_settings.cpu_pstate_disable || - pstate_switch_disable != hw_data->cc6_settings.nb_pstate_switch_disable) { - - hw_data->cc6_settings.cc6_setting_changed = true; - - hw_data->cc6_settings.cpu_pstate_separation_time = - separation_time; - hw_data->cc6_settings.cpu_cc6_disable = - cc6_disable; - hw_data->cc6_settings.cpu_pstate_disable = - pstate_disable; - hw_data->cc6_settings.nb_pstate_switch_disable = - pstate_switch_disable; - - } - - return 0; -} - -static int smu8_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ - uint32_t i; - const struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dep_on_dal_pwrl; - const struct phm_clock_and_voltage_limits *limits = - &hwmgr->dyn_state.max_clock_voltage_on_ac; - - info->engine_max_clock = limits->sclk; - info->memory_max_clock = limits->mclk; - - for (i = table->count - 1; i > 0; i--) { - if (limits->vddc >= table->entries[i].v) { - info->level = table->entries[i].clk; - return 0; - } - } - return -EINVAL; -} - -static int smu8_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - switch (type) { - case PP_SCLK: - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMin, - mask, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSclkSoftMax, - mask, - NULL); - break; - default: - break; - } - - return 0; -} - -static int smu8_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_clock_voltage_dependency_table *sclk_table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - int i, now, size = 0; - - switch (type) { - case PP_SCLK: - now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - ixTARGET_AND_CURRENT_PROFILE_INDEX), - TARGET_AND_CURRENT_PROFILE_INDEX, - CURR_SCLK_INDEX); - - for (i = 0; i < sclk_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->entries[i].clk / 100, - (i == now) ? "*" : ""); - break; - case PP_MCLK: - now = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - ixTARGET_AND_CURRENT_PROFILE_INDEX), - TARGET_AND_CURRENT_PROFILE_INDEX, - CURR_MCLK_INDEX); - - for (i = SMU8_NUM_NBPMEMORYCLOCK; i > 0; i--) - size += sprintf(buf + size, "%d: %uMhz %s\n", - SMU8_NUM_NBPMEMORYCLOCK-i, data->sys_info.nbp_memory_clock[i-1] / 100, - (SMU8_NUM_NBPMEMORYCLOCK-i == now) ? "*" : ""); - break; - default: - break; - } - return size; -} - -static int smu8_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - const struct smu8_power_state *ps; - struct smu8_hwmgr *data; - uint32_t level_index; - uint32_t i; - - if (level == NULL || hwmgr == NULL || state == NULL) - return -EINVAL; - - data = hwmgr->backend; - ps = cast_const_smu8_power_state(state); - - level_index = index > ps->level - 1 ? ps->level - 1 : index; - level->coreClock = ps->levels[level_index].engineClock; - - if (designation == PHM_PerformanceLevelDesignation_PowerContainment) { - for (i = 1; i < ps->level; i++) { - if (ps->levels[i].engineClock > data->dce_slow_sclk_threshold) { - level->coreClock = ps->levels[i].engineClock; - break; - } - } - } - - if (level_index == 0) - level->memory_clock = data->sys_info.nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK - 1]; - else - level->memory_clock = data->sys_info.nbp_memory_clock[0]; - - level->vddc = (smu8_convert_8Bit_index_to_voltage(hwmgr, ps->levels[level_index].vddcIndex) + 2) / 4; - level->nonLocalMemoryFreq = 0; - level->nonLocalMemoryWidth = 0; - - return 0; -} - -static int smu8_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *state, struct pp_clock_info *clock_info) -{ - const struct smu8_power_state *ps = cast_const_smu8_power_state(state); - - clock_info->min_eng_clk = ps->levels[0].engineClock / (1 << (ps->levels[0].ssDividerIndex)); - clock_info->max_eng_clk = ps->levels[ps->level - 1].engineClock / (1 << (ps->levels[ps->level - 1].ssDividerIndex)); - - return 0; -} - -static int smu8_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, - struct amd_pp_clocks *clocks) -{ - struct smu8_hwmgr *data = hwmgr->backend; - int i; - struct phm_clock_voltage_dependency_table *table; - - clocks->count = smu8_get_max_sclk_level(hwmgr); - switch (type) { - case amd_pp_disp_clock: - for (i = 0; i < clocks->count; i++) - clocks->clock[i] = data->sys_info.display_clock[i] * 10; - break; - case amd_pp_sys_clock: - table = hwmgr->dyn_state.vddc_dependency_on_sclk; - for (i = 0; i < clocks->count; i++) - clocks->clock[i] = table->entries[i].clk * 10; - break; - case amd_pp_mem_clock: - clocks->count = SMU8_NUM_NBPMEMORYCLOCK; - for (i = 0; i < clocks->count; i++) - clocks->clock[i] = data->sys_info.nbp_memory_clock[clocks->count - 1 - i] * 10; - break; - default: - return -1; - } - - return 0; -} - -static int smu8_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks) -{ - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - unsigned long level; - const struct phm_clock_and_voltage_limits *limits = - &hwmgr->dyn_state.max_clock_voltage_on_ac; - - if ((NULL == table) || (table->count <= 0) || (clocks == NULL)) - return -EINVAL; - - level = smu8_get_max_sclk_level(hwmgr) - 1; - - if (level < table->count) - clocks->engine_max_clock = table->entries[level].clk; - else - clocks->engine_max_clock = table->entries[table->count - 1].clk; - - clocks->memory_max_clock = limits->mclk; - - return 0; -} - -static int smu8_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - int actual_temp = 0; - uint32_t val = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP); - uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); - - if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) - actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - else - actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return actual_temp; -} - -static int smu8_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - struct phm_clock_voltage_dependency_table *table = - hwmgr->dyn_state.vddc_dependency_on_sclk; - - struct phm_vce_clock_voltage_dependency_table *vce_table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - struct phm_uvd_clock_voltage_dependency_table *uvd_table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - - uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), - TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); - uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), - TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); - uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), - TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); - - uint32_t sclk, vclk, dclk, ecclk, tmp, activity_percent; - uint16_t vddnb, vddgfx; - int result; - - /* size must be at least 4 bytes for all sensors */ - if (*size < 4) - return -EINVAL; - *size = 4; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - if (sclk_index < NUM_SCLK_LEVELS) { - sclk = table->entries[sclk_index].clk; - *((uint32_t *)value) = sclk; - return 0; - } - return -EINVAL; - case AMDGPU_PP_SENSOR_VDDNB: - tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & - CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; - vddnb = smu8_convert_8Bit_index_to_voltage(hwmgr, tmp) / 4; - *((uint32_t *)value) = vddnb; - return 0; - case AMDGPU_PP_SENSOR_VDDGFX: - tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & - CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; - vddgfx = smu8_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp) / 4; - *((uint32_t *)value) = vddgfx; - return 0; - case AMDGPU_PP_SENSOR_UVD_VCLK: - if (!data->uvd_power_gated) { - if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { - return -EINVAL; - } else { - vclk = uvd_table->entries[uvd_index].vclk; - *((uint32_t *)value) = vclk; - return 0; - } - } - *((uint32_t *)value) = 0; - return 0; - case AMDGPU_PP_SENSOR_UVD_DCLK: - if (!data->uvd_power_gated) { - if (uvd_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { - return -EINVAL; - } else { - dclk = uvd_table->entries[uvd_index].dclk; - *((uint32_t *)value) = dclk; - return 0; - } - } - *((uint32_t *)value) = 0; - return 0; - case AMDGPU_PP_SENSOR_VCE_ECCLK: - if (!data->vce_power_gated) { - if (vce_index >= SMU8_MAX_HARDWARE_POWERLEVELS) { - return -EINVAL; - } else { - ecclk = vce_table->entries[vce_index].ecclk; - *((uint32_t *)value) = ecclk; - return 0; - } - } - *((uint32_t *)value) = 0; - return 0; - case AMDGPU_PP_SENSOR_GPU_LOAD: - result = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetAverageGraphicsActivity, - &activity_percent); - if (0 == result) { - activity_percent = activity_percent > 100 ? 100 : activity_percent; - } else { - activity_percent = 50; - } - *((uint32_t *)value) = activity_percent; - return 0; - case AMDGPU_PP_SENSOR_UVD_POWER: - *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; - return 0; - case AMDGPU_PP_SENSOR_VCE_POWER: - *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; - return 0; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = smu8_thermal_get_temperature(hwmgr); - return 0; - default: - return -EINVAL; - } -} - -static int smu8_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramAddrHiVirtual, - mc_addr_hi, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramAddrLoVirtual, - mc_addr_low, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramAddrHiPhysical, - virtual_addr_hi, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramAddrLoPhysical, - virtual_addr_low, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramBufferSize, - size, - NULL); - return 0; -} - -static int smu8_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *thermal_data) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - memcpy(thermal_data, &SMU7ThermalPolicy[0], sizeof(struct PP_TemperatureRange)); - - thermal_data->max = (data->thermal_auto_throttling_treshold + - data->sys_info.htc_hyst_lmt) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int smu8_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct smu8_hwmgr *data = hwmgr->backend; - uint32_t dpm_features = 0; - - if (enable && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM)) { - data->dpm_flags |= DPMFlags_UVD_Enabled; - dpm_features |= UVD_DPM_MASK; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableAllSmuFeatures, - dpm_features, - NULL); - } else { - dpm_features |= UVD_DPM_MASK; - data->dpm_flags &= ~DPMFlags_UVD_Enabled; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableAllSmuFeatures, - dpm_features, - NULL); - } - return 0; -} - -static int smu8_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu8_hwmgr *data = hwmgr->backend; - struct phm_uvd_clock_voltage_dependency_table *ptable = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - - if (!bgate) { - /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ - if (PP_CAP(PHM_PlatformCaps_StablePState) || - hwmgr->en_umd_pstate) { - data->uvd_dpm.hard_min_clk = - ptable->entries[ptable->count - 1].vclk; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetUvdHardMin, - smu8_get_uvd_level(hwmgr, - data->uvd_dpm.hard_min_clk, - PPSMC_MSG_SetUvdHardMin), - NULL); - - smu8_enable_disable_uvd_dpm(hwmgr, true); - } else { - smu8_enable_disable_uvd_dpm(hwmgr, true); - } - } else { - smu8_enable_disable_uvd_dpm(hwmgr, false); - } - - return 0; -} - -static int smu8_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct smu8_hwmgr *data = hwmgr->backend; - uint32_t dpm_features = 0; - - if (enable && phm_cap_enabled( - hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEDPM)) { - data->dpm_flags |= DPMFlags_VCE_Enabled; - dpm_features |= VCE_DPM_MASK; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableAllSmuFeatures, - dpm_features, - NULL); - } else { - dpm_features |= VCE_DPM_MASK; - data->dpm_flags &= ~DPMFlags_VCE_Enabled; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableAllSmuFeatures, - dpm_features, - NULL); - } - - return 0; -} - - -static void smu8_dpm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - if (data->acp_power_gated == bgate) - return; - - if (bgate) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerOFF, NULL); - else - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ACPPowerON, NULL); -} - -static void smu8_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - data->uvd_power_gated = bgate; - - if (bgate) { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_GATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_GATE); - smu8_dpm_update_uvd_dpm(hwmgr, true); - smu8_dpm_powerdown_uvd(hwmgr); - } else { - smu8_dpm_powerup_uvd(hwmgr); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_CG_STATE_UNGATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_UVD, - AMD_PG_STATE_UNGATE); - smu8_dpm_update_uvd_dpm(hwmgr, false); - } - -} - -static void smu8_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct smu8_hwmgr *data = hwmgr->backend; - - if (bgate) { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_GATE); - smu8_enable_disable_vce_dpm(hwmgr, false); - smu8_dpm_powerdown_vce(hwmgr); - data->vce_power_gated = true; - } else { - smu8_dpm_powerup_vce(hwmgr); - data->vce_power_gated = false; - amdgpu_device_ip_set_clockgating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_CG_STATE_UNGATE); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); - smu8_dpm_update_vce_dpm(hwmgr); - smu8_enable_disable_vce_dpm(hwmgr, true); - } -} - -static const struct pp_hwmgr_func smu8_hwmgr_funcs = { - .backend_init = smu8_hwmgr_backend_init, - .backend_fini = smu8_hwmgr_backend_fini, - .apply_state_adjust_rules = smu8_apply_state_adjust_rules, - .force_dpm_level = smu8_dpm_force_dpm_level, - .get_power_state_size = smu8_get_power_state_size, - .powerdown_uvd = smu8_dpm_powerdown_uvd, - .powergate_uvd = smu8_dpm_powergate_uvd, - .powergate_vce = smu8_dpm_powergate_vce, - .powergate_acp = smu8_dpm_powergate_acp, - .get_mclk = smu8_dpm_get_mclk, - .get_sclk = smu8_dpm_get_sclk, - .patch_boot_state = smu8_dpm_patch_boot_state, - .get_pp_table_entry = smu8_dpm_get_pp_table_entry, - .get_num_of_pp_table_entries = smu8_dpm_get_num_of_pp_table_entries, - .set_cpu_power_state = smu8_set_cpu_power_state, - .store_cc6_data = smu8_store_cc6_data, - .force_clock_level = smu8_force_clock_level, - .print_clock_levels = smu8_print_clock_levels, - .get_dal_power_level = smu8_get_dal_power_level, - .get_performance_level = smu8_get_performance_level, - .get_current_shallow_sleep_clocks = smu8_get_current_shallow_sleep_clocks, - .get_clock_by_type = smu8_get_clock_by_type, - .get_max_high_clocks = smu8_get_max_high_clocks, - .read_sensor = smu8_read_sensor, - .power_off_asic = smu8_power_off_asic, - .asic_setup = smu8_setup_asic_task, - .dynamic_state_management_enable = smu8_enable_dpm_tasks, - .power_state_set = smu8_set_power_state_tasks, - .dynamic_state_management_disable = smu8_disable_dpm_tasks, - .notify_cac_buffer_info = smu8_notify_cac_buffer_info, - .update_nbdpm_pstate = smu8_nbdpm_pstate_enable_disable, - .get_thermal_temperature_range = smu8_get_thermal_temperature_range, -}; - -int smu8_init_function_pointers(struct pp_hwmgr *hwmgr) -{ - hwmgr->hwmgr_func = &smu8_hwmgr_funcs; - hwmgr->pptable_func = &pptable_funcs; - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h deleted file mode 100644 index 05a06083e1b8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.h +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright 2015 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 _SMU8_HWMGR_H_ -#define _SMU8_HWMGR_H_ - -#include "cgs_common.h" -#include "ppatomctrl.h" - -#define SMU8_NUM_NBPSTATES 4 -#define SMU8_NUM_NBPMEMORYCLOCK 2 -#define MAX_DISPLAY_CLOCK_LEVEL 8 -#define SMU8_MAX_HARDWARE_POWERLEVELS 8 -#define SMU8_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 -#define SMU8_MIN_DEEP_SLEEP_SCLK 800 - -/* Carrizo device IDs */ -#define DEVICE_ID_CZ_9870 0x9870 -#define DEVICE_ID_CZ_9874 0x9874 -#define DEVICE_ID_CZ_9875 0x9875 -#define DEVICE_ID_CZ_9876 0x9876 -#define DEVICE_ID_CZ_9877 0x9877 - -struct smu8_dpm_entry { - uint32_t soft_min_clk; - uint32_t hard_min_clk; - uint32_t soft_max_clk; - uint32_t hard_max_clk; -}; - -struct smu8_sys_info { - uint32_t bootup_uma_clock; - uint32_t bootup_engine_clock; - uint32_t dentist_vco_freq; - uint32_t nb_dpm_enable; - uint32_t nbp_memory_clock[SMU8_NUM_NBPMEMORYCLOCK]; - uint32_t nbp_n_clock[SMU8_NUM_NBPSTATES]; - uint16_t nbp_voltage_index[SMU8_NUM_NBPSTATES]; - uint32_t display_clock[MAX_DISPLAY_CLOCK_LEVEL]; - uint16_t bootup_nb_voltage_index; - uint8_t htc_tmp_lmt; - uint8_t htc_hyst_lmt; - uint32_t system_config; - uint32_t uma_channel_number; -}; - -#define MAX_DISPLAYPHY_IDS 0x8 -#define DISPLAYPHY_LANEMASK 0xF -#define UNKNOWN_TRANSMITTER_PHY_ID (-1) - -#define DISPLAYPHY_PHYID_SHIFT 24 -#define DISPLAYPHY_LANESELECT_SHIFT 16 - -#define DISPLAYPHY_RX_SELECT 0x1 -#define DISPLAYPHY_TX_SELECT 0x2 -#define DISPLAYPHY_CORE_SELECT 0x4 - -#define DDI_POWERGATING_ARG(phyID, lanemask, rx, tx, core) \ - (((uint32_t)(phyID))<adev); - uint32_t reg, data; - - *cap = false; - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return 0; - - WREG32(0x12074, 0xFFF0003B); - data = RREG32(0x12075); - - if (data == 0x1) { - reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); - - if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - *cap = true; - } - - return 0; -} - -int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - uint32_t reg; - - reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL); - - if (reg & BACO_CNTL__BACO_MODE_MASK) - /* gfx has already entered BACO state */ - *state = BACO_STATE_IN; - else - *state = BACO_STATE_OUT; - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h deleted file mode 100644 index 84e90f801ac3..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu9_baco.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 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 __SMU9_BACO_H__ -#define __SMU9_BACO_H__ -#include "hwmgr.h" -#include "common_baco.h" - -extern int smu9_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); -extern int smu9_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c deleted file mode 100644 index 60b5ca974356..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright 2018 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 -#include - -#include "hwmgr.h" -#include "pp_debug.h" -#include "ppatomctrl.h" -#include "ppsmc.h" -#include "atom.h" -#include "ivsrcid/thm/irqsrcs_thm_9_0.h" -#include "ivsrcid/smuio/irqsrcs_smuio_9_0.h" -#include "ivsrcid/ivsrcid_vislands30.h" - -uint8_t convert_to_vid(uint16_t vddc) -{ - return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); -} - -uint16_t convert_to_vddc(uint8_t vid) -{ - return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE); -} - -int phm_copy_clock_limits_array( - struct pp_hwmgr *hwmgr, - uint32_t **pptable_info_array, - const uint32_t *pptable_array, - uint32_t power_saving_clock_count) -{ - uint32_t array_size, i; - uint32_t *table; - - array_size = sizeof(uint32_t) * power_saving_clock_count; - table = kzalloc(array_size, GFP_KERNEL); - if (NULL == table) - return -ENOMEM; - - for (i = 0; i < power_saving_clock_count; i++) - table[i] = le32_to_cpu(pptable_array[i]); - - *pptable_info_array = table; - - return 0; -} - -int phm_copy_overdrive_settings_limits_array( - struct pp_hwmgr *hwmgr, - uint32_t **pptable_info_array, - const uint32_t *pptable_array, - uint32_t od_setting_count) -{ - uint32_t array_size, i; - uint32_t *table; - - array_size = sizeof(uint32_t) * od_setting_count; - table = kzalloc(array_size, GFP_KERNEL); - if (NULL == table) - return -ENOMEM; - - for (i = 0; i < od_setting_count; i++) - table[i] = le32_to_cpu(pptable_array[i]); - - *pptable_info_array = table; - - return 0; -} - -uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size) -{ - u32 mask = 0; - u32 shift = 0; - - shift = (offset % 4) << 3; - if (size == sizeof(uint8_t)) - mask = 0xFF << shift; - else if (size == sizeof(uint16_t)) - mask = 0xFFFF << shift; - - original_data &= ~mask; - original_data |= (field << shift); - return original_data; -} - -/** - * Returns once the part of the register indicated by the mask has - * reached the given value. - */ -int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, - uint32_t value, uint32_t mask) -{ - uint32_t i; - uint32_t cur_value; - - if (hwmgr == NULL || hwmgr->device == NULL) { - pr_err("Invalid Hardware Manager!"); - return -EINVAL; - } - - for (i = 0; i < hwmgr->usec_timeout; i++) { - cur_value = cgs_read_register(hwmgr->device, index); - if ((cur_value & mask) == (value & mask)) - break; - udelay(1); - } - - /* timeout means wrong logic*/ - if (i == hwmgr->usec_timeout) - return -1; - return 0; -} - - -/** - * Returns once the part of the register indicated by the mask has - * reached the given value.The indirect space is described by giving - * the memory-mapped index of the indirect index register. - */ -int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, - uint32_t indirect_port, - uint32_t index, - uint32_t value, - uint32_t mask) -{ - if (hwmgr == NULL || hwmgr->device == NULL) { - pr_err("Invalid Hardware Manager!"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, indirect_port, index); - return phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); -} - -int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, - uint32_t index, - uint32_t value, uint32_t mask) -{ - uint32_t i; - uint32_t cur_value; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - for (i = 0; i < hwmgr->usec_timeout; i++) { - cur_value = cgs_read_register(hwmgr->device, - index); - if ((cur_value & mask) != (value & mask)) - break; - udelay(1); - } - - /* timeout means wrong logic */ - if (i == hwmgr->usec_timeout) - return -ETIME; - return 0; -} - -int phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, - uint32_t indirect_port, - uint32_t index, - uint32_t value, - uint32_t mask) -{ - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - cgs_write_register(hwmgr->device, indirect_port, index); - return phm_wait_for_register_unequal(hwmgr, indirect_port + 1, - value, mask); -} - -bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) -{ - return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating); -} - -bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr) -{ - return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); -} - - -int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table) -{ - uint32_t i, j; - uint16_t vvalue; - bool found = false; - struct pp_atomctrl_voltage_table *table; - - PP_ASSERT_WITH_CODE((NULL != vol_table), - "Voltage Table empty.", return -EINVAL); - - table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), - GFP_KERNEL); - - if (NULL == table) - return -EINVAL; - - table->mask_low = vol_table->mask_low; - table->phase_delay = vol_table->phase_delay; - - for (i = 0; i < vol_table->count; i++) { - vvalue = vol_table->entries[i].value; - found = false; - - for (j = 0; j < table->count; j++) { - if (vvalue == table->entries[j].value) { - found = true; - break; - } - } - - if (!found) { - table->entries[table->count].value = vvalue; - table->entries[table->count].smio_low = - vol_table->entries[i].smio_low; - table->count++; - } - } - - memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); - kfree(table); - table = NULL; - return 0; -} - -int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, - phm_ppt_v1_clock_voltage_dependency_table *dep_table) -{ - uint32_t i; - int result; - - PP_ASSERT_WITH_CODE((0 != dep_table->count), - "Voltage Dependency Table empty.", return -EINVAL); - - PP_ASSERT_WITH_CODE((NULL != vol_table), - "vol_table empty.", return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - vol_table->count = dep_table->count; - - for (i = 0; i < dep_table->count; i++) { - vol_table->entries[i].value = dep_table->entries[i].mvdd; - vol_table->entries[i].smio_low = 0; - } - - result = phm_trim_voltage_table(vol_table); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to trim MVDD table.", return result); - - return 0; -} - -int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, - phm_ppt_v1_clock_voltage_dependency_table *dep_table) -{ - uint32_t i; - int result; - - PP_ASSERT_WITH_CODE((0 != dep_table->count), - "Voltage Dependency Table empty.", return -EINVAL); - - PP_ASSERT_WITH_CODE((NULL != vol_table), - "vol_table empty.", return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - vol_table->count = dep_table->count; - - for (i = 0; i < dep_table->count; i++) { - vol_table->entries[i].value = dep_table->entries[i].vddci; - vol_table->entries[i].smio_low = 0; - } - - result = phm_trim_voltage_table(vol_table); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to trim VDDCI table.", return result); - - return 0; -} - -int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, - phm_ppt_v1_voltage_lookup_table *lookup_table) -{ - int i = 0; - - PP_ASSERT_WITH_CODE((0 != lookup_table->count), - "Voltage Lookup Table empty.", return -EINVAL); - - PP_ASSERT_WITH_CODE((NULL != vol_table), - "vol_table empty.", return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - - vol_table->count = lookup_table->count; - - for (i = 0; i < vol_table->count; i++) { - vol_table->entries[i].value = lookup_table->entries[i].us_vdd; - vol_table->entries[i].smio_low = 0; - } - - return 0; -} - -void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, - struct pp_atomctrl_voltage_table *vol_table) -{ - unsigned int i, diff; - - if (vol_table->count <= max_vol_steps) - return; - - diff = vol_table->count - max_vol_steps; - - for (i = 0; i < max_vol_steps; i++) - vol_table->entries[i] = vol_table->entries[i + diff]; - - vol_table->count = max_vol_steps; - - return; -} - -int phm_reset_single_dpm_table(void *table, - uint32_t count, int max) -{ - int i; - - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; - - dpm_table->count = count > max ? max : count; - - for (i = 0; i < dpm_table->count; i++) - dpm_table->dpm_level[i].enabled = false; - - return 0; -} - -void phm_setup_pcie_table_entry( - void *table, - uint32_t index, uint32_t pcie_gen, - uint32_t pcie_lanes) -{ - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; - dpm_table->dpm_level[index].value = pcie_gen; - dpm_table->dpm_level[index].param1 = pcie_lanes; - dpm_table->dpm_level[index].enabled = 1; -} - -int32_t phm_get_dpm_level_enable_mask_value(void *table) -{ - int32_t i; - int32_t mask = 0; - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; - - for (i = dpm_table->count; i > 0; i--) { - mask = mask << 1; - if (dpm_table->dpm_level[i - 1].enabled) - mask |= 0x1; - else - mask &= 0xFFFFFFFE; - } - - return mask; -} - -uint8_t phm_get_voltage_index( - struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) -{ - uint8_t count = (uint8_t) (lookup_table->count); - uint8_t i; - - PP_ASSERT_WITH_CODE((NULL != lookup_table), - "Lookup Table empty.", return 0); - PP_ASSERT_WITH_CODE((0 != count), - "Lookup Table empty.", return 0); - - for (i = 0; i < lookup_table->count; i++) { - /* find first voltage equal or bigger than requested */ - if (lookup_table->entries[i].us_vdd >= voltage) - return i; - } - /* voltage is bigger than max voltage in the table */ - return i - 1; -} - -uint8_t phm_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, - uint32_t voltage) -{ - uint8_t count = (uint8_t) (voltage_table->count); - uint8_t i = 0; - - PP_ASSERT_WITH_CODE((NULL != voltage_table), - "Voltage Table empty.", return 0;); - PP_ASSERT_WITH_CODE((0 != count), - "Voltage Table empty.", return 0;); - - for (i = 0; i < count; i++) { - /* find first voltage bigger than requested */ - if (voltage_table->entries[i].value >= voltage) - return i; - } - - /* voltage is bigger than max voltage in the table */ - return i - 1; -} - -uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) -{ - uint32_t i; - - for (i = 0; i < vddci_table->count; i++) { - if (vddci_table->entries[i].value >= vddci) - return vddci_table->entries[i].value; - } - - pr_debug("vddci is larger than max value in vddci_table\n"); - return vddci_table->entries[i-1].value; -} - -int phm_find_boot_level(void *table, - uint32_t value, uint32_t *boot_level) -{ - int result = -EINVAL; - uint32_t i; - struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; - - for (i = 0; i < dpm_table->count; i++) { - if (value == dpm_table->dpm_level[i].value) { - *boot_level = i; - result = 0; - } - } - - return result; -} - -int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table *lookup_table, - uint16_t virtual_voltage_id, int32_t *sclk) -{ - uint8_t entry_id; - uint8_t voltage_id; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); - - /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ - for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { - voltage_id = table_info->vdd_dep_on_sclk->entries[entry_id].vddInd; - if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) - break; - } - - if (entry_id >= table_info->vdd_dep_on_sclk->count) { - pr_debug("Can't find requested voltage id in vdd_dep_on_sclk table\n"); - return -EINVAL; - } - - *sclk = table_info->vdd_dep_on_sclk->entries[entry_id].clk; - - return 0; -} - -/** - * Initialize Dynamic State Adjustment Rule Settings - * - * @param hwmgr the address of the powerplay hardware manager. - */ -int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) -{ - uint32_t table_size; - struct phm_clock_voltage_dependency_table *table_clk_vlt; - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - - /* initialize vddc_dep_on_dal_pwrl table */ - table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); - table_clk_vlt = kzalloc(table_size, GFP_KERNEL); - - if (NULL == table_clk_vlt) { - pr_err("Can not allocate space for vddc_dep_on_dal_pwrl! \n"); - return -ENOMEM; - } else { - table_clk_vlt->count = 4; - table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; - table_clk_vlt->entries[0].v = 0; - table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; - table_clk_vlt->entries[1].v = 720; - table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; - table_clk_vlt->entries[2].v = 810; - table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; - table_clk_vlt->entries[3].v = 900; - if (pptable_info != NULL) - pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; - } - - return 0; -} - -uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask) -{ - uint32_t level = 0; - - while (0 == (mask & (1 << level))) - level++; - - return level; -} - -void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_clock_voltage_dependency_table *table = - table_info->vddc_dep_on_dal_pwrl; - struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table; - enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level; - uint32_t req_vddc = 0, req_volt, i; - - if (!table || table->count <= 0 - || dal_power_level < PP_DAL_POWERLEVEL_ULTRALOW - || dal_power_level > PP_DAL_POWERLEVEL_PERFORMANCE) - return; - - for (i = 0; i < table->count; i++) { - if (dal_power_level == table->entries[i].clk) { - req_vddc = table->entries[i].v; - break; - } - } - - vddc_table = table_info->vdd_dep_on_sclk; - for (i = 0; i < vddc_table->count; i++) { - if (req_vddc <= vddc_table->entries[i].vddc) { - req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VddC_Request, - req_volt, - NULL); - return; - } - } - pr_err("DAL requested level can not" - " found a available voltage in VDDC DPM Table \n"); -} - -int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint32_t sclk, uint16_t id, uint16_t *voltage) -{ - uint32_t vol; - int ret = 0; - - if (hwmgr->chip_id < CHIP_TONGA) { - ret = atomctrl_get_voltage_evv(hwmgr, id, voltage); - } else if (hwmgr->chip_id < CHIP_POLARIS10) { - ret = atomctrl_get_voltage_evv_on_sclk(hwmgr, voltage_type, sclk, id, voltage); - if (*voltage >= 2000 || *voltage == 0) - *voltage = 1150; - } else { - ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); - *voltage = (uint16_t)(vol/100); - } - return ret; -} - - -int phm_irq_process(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - uint32_t client_id = entry->client_id; - uint32_t src_id = entry->src_id; - - if (client_id == AMDGPU_IRQ_CLIENTID_LEGACY) { - if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_LOW_TO_HIGH) { - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); - } else if (src_id == VISLANDS30_IV_SRCID_CG_TSS_THERMAL_HIGH_TO_LOW) - dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); - else if (src_id == VISLANDS30_IV_SRCID_GPIO_19) { - dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); - /* - * HW CTF just occurred. Shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); - orderly_poweroff(true); - } - } else if (client_id == SOC15_IH_CLIENTID_THM) { - if (src_id == 0) { - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); - } else - dev_emerg(adev->dev, "ERROR: GPU under temperature range detected!\n"); - } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) { - dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); - /* - * HW CTF just occurred. Shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); - orderly_poweroff(true); - } - - return 0; -} - -static const struct amdgpu_irq_src_funcs smu9_irq_funcs = { - .process = phm_irq_process, -}; - -int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_irq_src *source = - kzalloc(sizeof(struct amdgpu_irq_src), GFP_KERNEL); - - if (!source) - return -ENOMEM; - - source->funcs = &smu9_irq_funcs; - - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - SOC15_IH_CLIENTID_THM, - THM_9_0__SRCID__THM_DIG_THERM_L2H, - source); - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - SOC15_IH_CLIENTID_THM, - THM_9_0__SRCID__THM_DIG_THERM_H2L, - source); - - /* Register CTF(GPIO_19) interrupt */ - amdgpu_irq_add_id((struct amdgpu_device *)(hwmgr->adev), - SOC15_IH_CLIENTID_ROM_SMUIO, - SMUIO_9_0__SRCID__SMUIO_GPIO19, - source); - - return 0; -} - -void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, - uint8_t *frev, uint8_t *crev) -{ - struct amdgpu_device *adev = dev; - uint16_t data_start; - - if (amdgpu_atom_parse_data_header( - adev->mode_info.atom_context, table, size, - frev, crev, &data_start)) - return (uint8_t *)adev->mode_info.atom_context->bios + - data_start; - - return NULL; -} - -int smu_get_voltage_dependency_table_ppt_v1( - const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table) -{ - uint8_t i = 0; - PP_ASSERT_WITH_CODE((0 != allowed_dep_table->count), - "Voltage Lookup Table empty", - return -EINVAL); - - dep_table->count = allowed_dep_table->count; - for (i=0; icount; i++) { - dep_table->entries[i].clk = allowed_dep_table->entries[i].clk; - dep_table->entries[i].vddInd = allowed_dep_table->entries[i].vddInd; - dep_table->entries[i].vdd_offset = allowed_dep_table->entries[i].vdd_offset; - dep_table->entries[i].vddc = allowed_dep_table->entries[i].vddc; - dep_table->entries[i].vddgfx = allowed_dep_table->entries[i].vddgfx; - dep_table->entries[i].vddci = allowed_dep_table->entries[i].vddci; - dep_table->entries[i].mvdd = allowed_dep_table->entries[i].mvdd; - dep_table->entries[i].phases = allowed_dep_table->entries[i].phases; - dep_table->entries[i].cks_enable = allowed_dep_table->entries[i].cks_enable; - dep_table->entries[i].cks_voffset = allowed_dep_table->entries[i].cks_voffset; - } - - return 0; -} - -int smu_set_watermarks_for_clocks_ranges(void *wt_table, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges) -{ - uint32_t i; - struct watermarks *table = wt_table; - - if (!table || !wm_with_clock_ranges) - return -EINVAL; - - if (wm_with_clock_ranges->num_wm_dmif_sets > 4 || wm_with_clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; - - for (i = 0; i < wm_with_clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } - - for (i = 0; i < wm_with_clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; - } - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h deleted file mode 100644 index ad33983a8064..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2018 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _SMU_HELPER_H_ -#define _SMU_HELPER_H_ - -struct pp_atomctrl_voltage_table; -struct pp_hwmgr; -struct phm_ppt_v1_voltage_lookup_table; -struct Watermarks_t; -struct pp_wm_sets_with_clock_ranges_soc15; - -uint8_t convert_to_vid(uint16_t vddc); -uint16_t convert_to_vddc(uint8_t vid); - -struct watermark_row_generic_t { - uint16_t MinClock; - uint16_t MaxClock; - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Padding[3]; -}; - -struct watermarks { - struct watermark_row_generic_t WatermarkRow[2][4]; - uint32_t padding[7]; -}; - -int phm_copy_clock_limits_array( - struct pp_hwmgr *hwmgr, - uint32_t **pptable_info_array, - const uint32_t *pptable_array, - uint32_t power_saving_clock_count); - -int phm_copy_overdrive_settings_limits_array( - struct pp_hwmgr *hwmgr, - uint32_t **pptable_info_array, - const uint32_t *pptable_array, - uint32_t od_setting_count); - -extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, - uint32_t index, - uint32_t value, uint32_t mask); -extern int phm_wait_for_indirect_register_unequal( - struct pp_hwmgr *hwmgr, - uint32_t indirect_port, uint32_t index, - uint32_t value, uint32_t mask); - - -extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); -extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr); -extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr); - -extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table); -extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); -extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); -extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table); -extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table); -extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); -extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); -extern int32_t phm_get_dpm_level_enable_mask_value(void *table); -extern uint8_t phm_get_voltage_id(struct pp_atomctrl_voltage_table *voltage_table, - uint32_t voltage); -extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); -extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); -extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); -extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, - uint16_t virtual_voltage_id, int32_t *sclk); -extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); -extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); -extern void phm_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr); - -extern int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, - uint32_t sclk, uint16_t id, uint16_t *voltage); - -extern uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size); - -extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, - uint32_t value, uint32_t mask); - -extern int phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, - uint32_t indirect_port, - uint32_t index, - uint32_t value, - uint32_t mask); - -int phm_irq_process(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry); - -int smu9_register_irq_handlers(struct pp_hwmgr *hwmgr); - -void *smu_atom_get_data_table(void *dev, uint32_t table, uint16_t *size, - uint8_t *frev, uint8_t *crev); - -int smu_get_voltage_dependency_table_ppt_v1( - const struct phm_ppt_v1_clock_voltage_dependency_table *allowed_dep_table, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table); - -int smu_set_watermarks_for_clocks_ranges(void *wt_table, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); - -#define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT -#define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK - -#define PHM_SET_FIELD(origval, reg, field, fieldval) \ - (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ - (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) - -#define PHM_GET_FIELD(value, reg, field) \ - (((value) & PHM_FIELD_MASK(reg, field)) >> \ - PHM_FIELD_SHIFT(reg, field)) - - -/* Operations on named fields. */ - -#define PHM_READ_FIELD(device, reg, field) \ - PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) - -#define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ - PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field) - -#define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ - PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field) - -#define PHM_WRITE_FIELD(device, reg, field, fieldval) \ - cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ - cgs_read_register(device, mm##reg), reg, field, fieldval)) - -#define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ - cgs_write_ind_register(device, port, ix##reg, \ - PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field, fieldval)) - -#define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ - cgs_write_ind_register(device, port, ix##reg, \ - PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ - reg, field, fieldval)) - -#define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ - phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) - - -#define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ - PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) - -#define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ - PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ - << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) - -#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ - phm_wait_for_indirect_register_unequal(hwmgr, \ - mm##port##_INDEX, index, value, mask) - -#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ - PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) - -#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ - PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ - PHM_FIELD_MASK(reg, field) ) - - -#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ - port, index, value, mask) \ - phm_wait_for_indirect_register_unequal(hwmgr, \ - mm##port##_INDEX_11, index, value, mask) - -#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ - PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) - -#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ - PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, \ - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ - PHM_FIELD_MASK(reg, field)) - - -#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, \ - port, index, value, mask) \ - phm_wait_on_indirect_register(hwmgr, \ - mm##port##_INDEX_11, index, value, mask) - -#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ - PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) - -#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ - PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, \ - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ - PHM_FIELD_MASK(reg, field)) - -#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ - index, value, mask) \ - phm_wait_for_register_unequal(hwmgr, \ - index, value, mask) - -#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ - PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, \ - mm##reg, value, mask) - -#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ - PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, \ - (fieldval) << PHM_FIELD_SHIFT(reg, field), \ - PHM_FIELD_MASK(reg, field)) - -#endif /* _SMU_HELPER_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c deleted file mode 100644 index ea743bea8e29..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "tonga_baco.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -#include "smu/smu_7_1_2_d.h" -#include "smu/smu_7_1_2_sh_mask.h" - - -static const struct baco_cmd_entry gpio_tbl[] = -{ - { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff }, - { CMD_WRITE, mmDC_GPIO_DVODATA_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmDC_GPIO_DVODATA_MASK, 0, 0, 0, 0xffffffff }, - { CMD_WRITE, mmDC_GPIO_GENERIC_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_GENERIC_MASK, 0, 0, 0, 0x03333333 }, - { CMD_WRITE, mmDC_GPIO_SYNCA_EN, 0, 0, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmDC_GPIO_SYNCA_MASK, 0, 0, 0, 0x00001111 } -}; - -static const struct baco_cmd_entry enable_fb_req_rej_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0300024 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x1, 0x0, 0, 0x1 }, - { CMD_WRITE, mmBIF_FB_EN, 0, 0, 0, 0x0 } -}; - -static const struct baco_cmd_entry use_bclk_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN_MASK, CG_SPLL_FUNC_CNTL__SPLL_BYPASS_EN__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_BYPASS_CHG__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_STATUS }, - { CMD_WAITFOR, mmGCK_SMC_IND_DATA, CG_SPLL_STATUS__SPLL_CHG_STATUS_MASK, 0, 0xffffffff, 0x2 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG_MASK, CG_SPLL_FUNC_CNTL_2__SPLL_CTLREQ_CHG__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x4000000, 0x1a, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x2 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL_MASK, MPLL_CNTL_MODE__MPLL_SW_DIR_CONTROL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__MPLL_MCLK_SEL_MASK, MPLL_CNTL_MODE__MPLL_MCLK_SEL__SHIFT, 0, 0x0 } -}; - -static const struct baco_cmd_entry turn_off_plls_tbl[] = -{ - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_SPLL_FUNC_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_RESET_MASK, CG_SPLL_FUNC_CNTL__SPLL_RESET__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_SPLL_FUNC_CNTL__SPLL_PWRON_MASK, CG_SPLL_FUNC_CNTL__SPLL_PWRON__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, 0xC0500170 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x2000000, 0x19, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, 0x8000000, 0x1b, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMPLL_CNTL_MODE, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET_MASK, MPLL_CNTL_MODE__GLOBAL_MPLL_RESET__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmMPLL_CONTROL, 0, 0, 0, 0x00000006 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D0, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY0_D1, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D0, 0, 0, 0, 0x00007740 }, - { CMD_WRITE, mmMC_IO_RXCNTL_DPHY1_D1, 0, 0, 0, 0x00007740 }, - { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK0_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK0_PDNB__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMCLK_PWRMGT_CNTL, MCLK_PWRMGT_CNTL__MRDCK1_PDNB_MASK, MCLK_PWRMGT_CNTL__MRDCK1_PDNB__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PU_MASK, MC_SEQ_CNTL_2__DRST_PU__SHIFT, 0, 0x0 }, - { CMD_READMODIFYWRITE, mmMC_SEQ_CNTL_2, MC_SEQ_CNTL_2__DRST_PD_MASK, MC_SEQ_CNTL_2__DRST_PD__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL_2 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN_MASK, CG_CLKPIN_CNTL_2__FORCE_BIF_REFCLK_EN__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMPLL_BYPASSCLK_SEL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL_MASK, MPLL_BYPASSCLK_SEL__MPLL_CLKOUT_SEL__SHIFT, 0, 0x4 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixMISC_CLK_CTRL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL_MASK, MISC_CLK_CTRL__DEEP_SLEEP_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, MISC_CLK_CTRL__ZCLK_SEL_MASK, MISC_CLK_CTRL__ZCLK_SEL__SHIFT, 0, 0x1 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixCG_CLKPIN_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, CG_CLKPIN_CNTL__BCLK_AS_XCLK_MASK, CG_CLKPIN_CNTL__BCLK_AS_XCLK__SHIFT, 0, 0x0 }, - { CMD_WRITE, mmGCK_SMC_IND_INDEX, 0, 0, 0, ixTHM_CLK_CNTL }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__CMON_CLK_SEL_MASK, THM_CLK_CNTL__CMON_CLK_SEL__SHIFT, 0, 0x1 }, - { CMD_READMODIFYWRITE, mmGCK_SMC_IND_DATA, THM_CLK_CNTL__TMON_CLK_SEL_MASK, THM_CLK_CNTL__TMON_CLK_SEL__SHIFT, 0, 0x1 } -}; - -static const struct baco_cmd_entry enter_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, 0, 5, 0x40000 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, 0, 5, 0x02 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, 0, 5, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, 0, 5, 0x08 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x40 } -}; - -#define BACO_CNTL__PWRGOOD_MASK BACO_CNTL__PWRGOOD_GPIO_MASK+BACO_CNTL__PWRGOOD_MEM_MASK+BACO_CNTL__PWRGOOD_DVO_MASK - -static const struct baco_cmd_entry exit_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } -}; - -static const struct baco_cmd_entry clean_baco_tbl[] = -{ - { CMD_WRITE, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, - { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } -}; - -static const struct baco_cmd_entry gpio_tbl_iceland[] = -{ - { CMD_WRITE, mmGPIOPAD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PD_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_PU_EN, 0, 0, 0, 0x0 }, - { CMD_WRITE, mmGPIOPAD_MASK, 0, 0, 0, 0xff77ffff } -}; - -static const struct baco_cmd_entry exit_baco_tbl_iceland[] = -{ - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BCLK_OFF_MASK, BACO_CNTL__BACO_BCLK_OFF__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0x00 }, - { CMD_DELAY_MS, 0, 0, 0, 20, 0 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_BF_MASK, 0, 0xffffffff, 0x200 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ISO_DIS_MASK, BACO_CNTL__BACO_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__PWRGOOD_MASK, 0, 5, 0x1c00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_ANA_ISO_DIS_MASK, BACO_CNTL__BACO_ANA_ISO_DIS__SHIFT, 0, 0x01 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_BIF_SCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_SCLK_SWITCH__SHIFT, 0, 0x00 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_RESET_EN_MASK, BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__RCU_BIF_CONFIG_DONE_MASK, 0, 5, 0x100 }, - { CMD_READMODIFYWRITE, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0x00 }, - { CMD_WAITFOR, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0x00 } -}; - -static const struct baco_cmd_entry clean_baco_tbl_iceland[] = -{ - { CMD_WRITE, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } -}; - -int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu7_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - if (hwmgr->chip_id == CHIP_TOPAZ) - baco_program_registers(hwmgr, gpio_tbl_iceland, ARRAY_SIZE(gpio_tbl_iceland)); - else - baco_program_registers(hwmgr, gpio_tbl, ARRAY_SIZE(gpio_tbl)); - baco_program_registers(hwmgr, enable_fb_req_rej_tbl, - ARRAY_SIZE(enable_fb_req_rej_tbl)); - baco_program_registers(hwmgr, use_bclk_tbl, ARRAY_SIZE(use_bclk_tbl)); - baco_program_registers(hwmgr, turn_off_plls_tbl, - ARRAY_SIZE(turn_off_plls_tbl)); - if (baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (hwmgr->chip_id == CHIP_TOPAZ) { - if (baco_program_registers(hwmgr, exit_baco_tbl_iceland, - ARRAY_SIZE(exit_baco_tbl_iceland))) { - if (baco_program_registers(hwmgr, clean_baco_tbl_iceland, - ARRAY_SIZE(clean_baco_tbl_iceland))) - return 0; - } - } else { - if (baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h deleted file mode 100644 index 5dc16cc8a295..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __TONGA_BACO_H__ -#define __TONGA_BACO_H__ -#include "smu7_baco.h" - -extern int tonga_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c deleted file mode 100644 index 46bb16c29cf6..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2018 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 "amdgpu.h" -#include "soc15.h" -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" -#include "soc15_common.h" -#include "vega10_inc.h" -#include "vega10_ppsmc.h" -#include "vega10_baco.h" - - - -static const struct soc15_baco_cmd_entry pre_baco_tbl[] = -{ - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_DOORBELL_CNTL), BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 1}, - {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIF_FB_EN), 0, 0, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1} -}; - -static const struct soc15_baco_cmd_entry enter_baco_tbl[] = -{ - {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT,0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1}, - {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 5, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0}, - {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100} -}; - -static const struct soc15_baco_cmd_entry exit_baco_tbl[] = -{ - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0}, - {CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10,0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0,0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT,0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0}, - {CMD_WAITFOR, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(THM, 0, mmTHM_BACO_CNTL), THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK ,BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0}, - {CMD_READMODIFYWRITE, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_EN_MASK , BACO_CNTL__BACO_EN__SHIFT, 0,0}, - {CMD_WAITFOR, SOC15_REG_ENTRY(NBIF, 0, mmBACO_CNTL), BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0} - }; - -static const struct soc15_baco_cmd_entry clean_baco_tbl[] = -{ - {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0}, - {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, -}; - -int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu9_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - if (soc15_baco_program_registers(hwmgr, pre_baco_tbl, - ARRAY_SIZE(pre_baco_tbl))) { - if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnterBaco, NULL)) - return -EINVAL; - - if (soc15_baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - } - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (soc15_baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (soc15_baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h deleted file mode 100644 index 96d793f026a5..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2018 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 __VEGA10_BACO_H__ -#define __VEGA10_BACO_H__ -#include "smu9_baco.h" - -extern int vega10_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c deleted file mode 100644 index c378a000c934..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ /dev/null @@ -1,5482 +0,0 @@ -/* - * Copyright 2016 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 -#include -#include -#include -#include - -#include "hwmgr.h" -#include "amd_powerplay.h" -#include "hardwaremanager.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "cgs_common.h" -#include "vega10_powertune.h" -#include "smu9.h" -#include "smu9_driver_if.h" -#include "vega10_inc.h" -#include "soc15_common.h" -#include "pppcielanes.h" -#include "vega10_hwmgr.h" -#include "vega10_smumgr.h" -#include "vega10_processpptables.h" -#include "vega10_pptable.h" -#include "vega10_thermal.h" -#include "pp_debug.h" -#include "amd_pcie_helpers.h" -#include "ppinterrupt.h" -#include "pp_overdriver.h" -#include "pp_thermal.h" -#include "vega10_baco.h" - -#include "smuio/smuio_9_0_offset.h" -#include "smuio/smuio_9_0_sh_mask.h" - -#define HBM_MEMORY_CHANNEL_WIDTH 128 - -static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; - -#define mmDF_CS_AON0_DramBaseAddress0 0x0044 -#define mmDF_CS_AON0_DramBaseAddress0_BASE_IDX 0 - -//DF_CS_AON0_DramBaseAddress0 -#define DF_CS_AON0_DramBaseAddress0__AddrRngVal__SHIFT 0x0 -#define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT 0x1 -#define DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT 0x4 -#define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT 0x8 -#define DF_CS_AON0_DramBaseAddress0__DramBaseAddr__SHIFT 0xc -#define DF_CS_AON0_DramBaseAddress0__AddrRngVal_MASK 0x00000001L -#define DF_CS_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK 0x00000002L -#define DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x000000F0L -#define DF_CS_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000700L -#define DF_CS_AON0_DramBaseAddress0__DramBaseAddr_MASK 0xFFFFF000L - -typedef enum { - CLK_SMNCLK = 0, - CLK_SOCCLK, - CLK_MP0CLK, - CLK_MP1CLK, - CLK_LCLK, - CLK_DCEFCLK, - CLK_VCLK, - CLK_DCLK, - CLK_ECLK, - CLK_UCLK, - CLK_GFXCLK, - CLK_COUNT, -} CLOCK_ID_e; - -static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); - -static struct vega10_power_state *cast_phw_vega10_power_state( - struct pp_hw_power_state *hw_ps) -{ - PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), - "Invalid Powerstate Type!", - return NULL;); - - return (struct vega10_power_state *)hw_ps; -} - -static const struct vega10_power_state *cast_const_phw_vega10_power_state( - const struct pp_hw_power_state *hw_ps) -{ - PP_ASSERT_WITH_CODE((PhwVega10_Magic == hw_ps->magic), - "Invalid Powerstate Type!", - return NULL;); - - return (const struct vega10_power_state *)hw_ps; -} - -static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->registry_data.sclk_dpm_key_disabled = - hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true; - data->registry_data.socclk_dpm_key_disabled = - hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true; - data->registry_data.mclk_dpm_key_disabled = - hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true; - data->registry_data.pcie_dpm_key_disabled = - hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true; - - data->registry_data.dcefclk_dpm_key_disabled = - hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true; - - if (hwmgr->feature_mask & PP_POWER_CONTAINMENT_MASK) { - data->registry_data.power_containment_support = 1; - data->registry_data.enable_pkg_pwr_tracking_feature = 1; - data->registry_data.enable_tdc_limit_feature = 1; - } - - data->registry_data.clock_stretcher_support = - hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? true : false; - - data->registry_data.ulv_support = - hwmgr->feature_mask & PP_ULV_MASK ? true : false; - - data->registry_data.sclk_deep_sleep_support = - hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK ? true : false; - - data->registry_data.disable_water_mark = 0; - - data->registry_data.fan_control_support = 1; - data->registry_data.thermal_support = 1; - data->registry_data.fw_ctf_enabled = 1; - - data->registry_data.avfs_support = - hwmgr->feature_mask & PP_AVFS_MASK ? true : false; - data->registry_data.led_dpm_enabled = 1; - - data->registry_data.vr0hot_enabled = 1; - data->registry_data.vr1hot_enabled = 1; - data->registry_data.regulator_hot_gpio_support = 1; - - data->registry_data.didt_support = 1; - if (data->registry_data.didt_support) { - data->registry_data.didt_mode = 6; - data->registry_data.sq_ramping_support = 1; - data->registry_data.db_ramping_support = 0; - data->registry_data.td_ramping_support = 0; - data->registry_data.tcp_ramping_support = 0; - data->registry_data.dbr_ramping_support = 0; - data->registry_data.edc_didt_support = 1; - data->registry_data.gc_didt_support = 0; - data->registry_data.psm_didt_support = 0; - } - - data->display_voltage_mode = PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT; - data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_a = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_b = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_c = PPREGKEY_VEGA10QUADRATICEQUATION_DFLT; - - data->gfxclk_average_alpha = PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT; - data->socclk_average_alpha = PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT; - data->uclk_average_alpha = PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT; - data->gfx_activity_average_alpha = PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT; -} - -static int vega10_set_features_platform_caps(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct amdgpu_device *adev = hwmgr->adev; - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPatchPowerState); - - if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableSMU7ThermalManagement); - - if (adev->pg_flags & AMD_PG_SUPPORT_UVD) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - - if (adev->pg_flags & AMD_PG_SUPPORT_VCE) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UnTabledHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODFuzzyFanControlSupport); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPowerManagement); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMC); - - /* power tune caps */ - /* assume disabled */ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtSupport); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtEDCEnable); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GCEDC); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PSM); - - if (data->registry_data.didt_support) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); - if (data->registry_data.sq_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); - if (data->registry_data.db_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); - if (data->registry_data.td_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); - if (data->registry_data.tcp_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); - if (data->registry_data.dbr_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); - if (data->registry_data.edc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); - if (data->registry_data.gc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); - if (data->registry_data.psm_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); - } - - if (data->registry_data.power_containment_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CAC); - - if (table_info->tdp_table->usClockStretchAmount && - data->registry_data.clock_stretcher_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEDPM); - - return 0; -} - -static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct vega10_odn_vddc_lookup_table *od_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table[3]; - struct phm_ppt_v1_clock_voltage_dependency_table *od_table[3]; - struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; - uint32_t i; - int result; - - result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); - if (!result) { - data->odn_dpm_table.max_vddc = avfs_params.ulMaxVddc; - data->odn_dpm_table.min_vddc = avfs_params.ulMinVddc; - } - - od_lookup_table = &odn_table->vddc_lookup_table; - vddc_lookup_table = table_info->vddc_lookup_table; - - for (i = 0; i < vddc_lookup_table->count; i++) - od_lookup_table->entries[i].us_vdd = vddc_lookup_table->entries[i].us_vdd; - - od_lookup_table->count = vddc_lookup_table->count; - - dep_table[0] = table_info->vdd_dep_on_sclk; - dep_table[1] = table_info->vdd_dep_on_mclk; - dep_table[2] = table_info->vdd_dep_on_socclk; - od_table[0] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_sclk; - od_table[1] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_mclk; - od_table[2] = (struct phm_ppt_v1_clock_voltage_dependency_table *)&odn_table->vdd_dep_on_socclk; - - for (i = 0; i < 3; i++) - smu_get_voltage_dependency_table_ppt_v1(dep_table[i], od_table[i]); - - if (odn_table->max_vddc == 0 || odn_table->max_vddc > 2000) - odn_table->max_vddc = dep_table[0]->entries[dep_table[0]->count - 1].vddc; - if (odn_table->min_vddc == 0 || odn_table->min_vddc > 2000) - odn_table->min_vddc = dep_table[0]->entries[0].vddc; - - i = od_table[2]->count - 1; - od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ? - hwmgr->platform_descriptor.overdriveLimit.memoryClock : - od_table[2]->entries[i].clk; - od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ? - odn_table->max_vddc : - od_table[2]->entries[i].vddc; - - return 0; -} - -static void vega10_init_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - int i; - uint32_t sub_vendor_id, hw_revision; - uint32_t top32, bottom32; - struct amdgpu_device *adev = hwmgr->adev; - - vega10_initialize_power_tune_defaults(hwmgr); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - data->smu_features[i].smu_feature_id = 0xffff; - data->smu_features[i].smu_feature_bitmap = 1 << i; - data->smu_features[i].enabled = false; - data->smu_features[i].supported = false; - } - - data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = - FEATURE_DPM_PREFETCHER_BIT; - data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = - FEATURE_DPM_GFXCLK_BIT; - data->smu_features[GNLD_DPM_UCLK].smu_feature_id = - FEATURE_DPM_UCLK_BIT; - data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = - FEATURE_DPM_SOCCLK_BIT; - data->smu_features[GNLD_DPM_UVD].smu_feature_id = - FEATURE_DPM_UVD_BIT; - data->smu_features[GNLD_DPM_VCE].smu_feature_id = - FEATURE_DPM_VCE_BIT; - data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = - FEATURE_DPM_MP0CLK_BIT; - data->smu_features[GNLD_DPM_LINK].smu_feature_id = - FEATURE_DPM_LINK_BIT; - data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = - FEATURE_DPM_DCEFCLK_BIT; - data->smu_features[GNLD_ULV].smu_feature_id = - FEATURE_ULV_BIT; - data->smu_features[GNLD_AVFS].smu_feature_id = - FEATURE_AVFS_BIT; - data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = - FEATURE_DS_GFXCLK_BIT; - data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = - FEATURE_DS_SOCCLK_BIT; - data->smu_features[GNLD_DS_LCLK].smu_feature_id = - FEATURE_DS_LCLK_BIT; - data->smu_features[GNLD_PPT].smu_feature_id = - FEATURE_PPT_BIT; - data->smu_features[GNLD_TDC].smu_feature_id = - FEATURE_TDC_BIT; - data->smu_features[GNLD_THERMAL].smu_feature_id = - FEATURE_THERMAL_BIT; - data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = - FEATURE_GFX_PER_CU_CG_BIT; - data->smu_features[GNLD_RM].smu_feature_id = - FEATURE_RM_BIT; - data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = - FEATURE_DS_DCEFCLK_BIT; - data->smu_features[GNLD_ACDC].smu_feature_id = - FEATURE_ACDC_BIT; - data->smu_features[GNLD_VR0HOT].smu_feature_id = - FEATURE_VR0HOT_BIT; - data->smu_features[GNLD_VR1HOT].smu_feature_id = - FEATURE_VR1HOT_BIT; - data->smu_features[GNLD_FW_CTF].smu_feature_id = - FEATURE_FW_CTF_BIT; - data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = - FEATURE_LED_DISPLAY_BIT; - data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = - FEATURE_FAN_CONTROL_BIT; - data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; - data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; - data->smu_features[GNLD_PCC_LIMIT].smu_feature_id = FEATURE_PCC_LIMIT_CONTROL_BIT; - - if (!data->registry_data.prefetcher_dpm_key_disabled) - data->smu_features[GNLD_DPM_PREFETCHER].supported = true; - - if (!data->registry_data.sclk_dpm_key_disabled) - data->smu_features[GNLD_DPM_GFXCLK].supported = true; - - if (!data->registry_data.mclk_dpm_key_disabled) - data->smu_features[GNLD_DPM_UCLK].supported = true; - - if (!data->registry_data.socclk_dpm_key_disabled) - data->smu_features[GNLD_DPM_SOCCLK].supported = true; - - if (PP_CAP(PHM_PlatformCaps_UVDDPM)) - data->smu_features[GNLD_DPM_UVD].supported = true; - - if (PP_CAP(PHM_PlatformCaps_VCEDPM)) - data->smu_features[GNLD_DPM_VCE].supported = true; - - if (!data->registry_data.pcie_dpm_key_disabled) - data->smu_features[GNLD_DPM_LINK].supported = true; - - if (!data->registry_data.dcefclk_dpm_key_disabled) - data->smu_features[GNLD_DPM_DCEFCLK].supported = true; - - if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep) && - data->registry_data.sclk_deep_sleep_support) { - data->smu_features[GNLD_DS_GFXCLK].supported = true; - data->smu_features[GNLD_DS_SOCCLK].supported = true; - data->smu_features[GNLD_DS_LCLK].supported = true; - data->smu_features[GNLD_DS_DCEFCLK].supported = true; - } - - if (data->registry_data.enable_pkg_pwr_tracking_feature) - data->smu_features[GNLD_PPT].supported = true; - - if (data->registry_data.enable_tdc_limit_feature) - data->smu_features[GNLD_TDC].supported = true; - - if (data->registry_data.thermal_support) - data->smu_features[GNLD_THERMAL].supported = true; - - if (data->registry_data.fan_control_support) - data->smu_features[GNLD_FAN_CONTROL].supported = true; - - if (data->registry_data.fw_ctf_enabled) - data->smu_features[GNLD_FW_CTF].supported = true; - - if (data->registry_data.avfs_support) - data->smu_features[GNLD_AVFS].supported = true; - - if (data->registry_data.led_dpm_enabled) - data->smu_features[GNLD_LED_DISPLAY].supported = true; - - if (data->registry_data.vr1hot_enabled) - data->smu_features[GNLD_VR1HOT].supported = true; - - if (data->registry_data.vr0hot_enabled) - data->smu_features[GNLD_VR0HOT].supported = true; - - smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetSmuVersion, - &hwmgr->smu_version); - /* ACG firmware has major version 5 */ - if ((hwmgr->smu_version & 0xff000000) == 0x5000000) - data->smu_features[GNLD_ACG].supported = true; - if (data->registry_data.didt_support) - data->smu_features[GNLD_DIDT].supported = true; - - hw_revision = adev->pdev->revision; - sub_vendor_id = adev->pdev->subsystem_vendor; - - if ((hwmgr->chip_id == 0x6862 || - hwmgr->chip_id == 0x6861 || - hwmgr->chip_id == 0x6868) && - (hw_revision == 0) && - (sub_vendor_id != 0x1002)) - data->smu_features[GNLD_PCC_LIMIT].supported = true; - - /* Get the SN to turn into a Unique ID */ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); - - adev->unique_id = ((uint64_t)bottom32 << 32) | top32; -} - -#ifdef PPLIB_VEGA10_EVV_SUPPORT -static int vega10_get_socclk_for_voltage_evv(struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table *lookup_table, - uint16_t virtual_voltage_id, int32_t *socclk) -{ - uint8_t entry_id; - uint8_t voltage_id; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - PP_ASSERT_WITH_CODE(lookup_table->count != 0, - "Lookup table is empty", - return -EINVAL); - - /* search for leakage voltage ID 0xff01 ~ 0xff08 and sclk */ - for (entry_id = 0; entry_id < table_info->vdd_dep_on_sclk->count; entry_id++) { - voltage_id = table_info->vdd_dep_on_socclk->entries[entry_id].vddInd; - if (lookup_table->entries[voltage_id].us_vdd == virtual_voltage_id) - break; - } - - PP_ASSERT_WITH_CODE(entry_id < table_info->vdd_dep_on_socclk->count, - "Can't find requested voltage id in vdd_dep_on_socclk table!", - return -EINVAL); - - *socclk = table_info->vdd_dep_on_socclk->entries[entry_id].clk; - - return 0; -} - -#define ATOM_VIRTUAL_VOLTAGE_ID0 0xff01 -/** -* Get Leakage VDDC based on leakage ID. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0. -*/ -static int vega10_get_evv_voltages(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint16_t vv_id; - uint32_t vddc = 0; - uint16_t i, j; - uint32_t sclk = 0; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *socclk_table = - table_info->vdd_dep_on_socclk; - int result; - - for (i = 0; i < VEGA10_MAX_LEAKAGE_COUNT; i++) { - vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; - - if (!vega10_get_socclk_for_voltage_evv(hwmgr, - table_info->vddc_lookup_table, vv_id, &sclk)) { - if (PP_CAP(PHM_PlatformCaps_ClockStretcher)) { - for (j = 1; j < socclk_table->count; j++) { - if (socclk_table->entries[j].clk == sclk && - socclk_table->entries[j].cks_enable == 0) { - sclk += 5000; - break; - } - } - } - - PP_ASSERT_WITH_CODE(!atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, - VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc), - "Error retrieving EVV voltage value!", - continue); - - - /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ - PP_ASSERT_WITH_CODE((vddc < 2000 && vddc != 0), - "Invalid VDDC value", result = -EINVAL;); - - /* the voltage should not be zero nor equal to leakage ID */ - if (vddc != 0 && vddc != vv_id) { - data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = (uint16_t)(vddc/100); - data->vddc_leakage.leakage_id[data->vddc_leakage.count] = vv_id; - data->vddc_leakage.count++; - } - } - } - - return 0; -} - -/** - * Change virtual leakage voltage to actual value. - * - * @param hwmgr the address of the powerplay hardware manager. - * @param pointer to changing voltage - * @param pointer to leakage table - */ -static void vega10_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr, - uint16_t *voltage, struct vega10_leakage_voltage *leakage_table) -{ - uint32_t index; - - /* search for leakage voltage ID 0xff01 ~ 0xff08 */ - for (index = 0; index < leakage_table->count; index++) { - /* if this voltage matches a leakage voltage ID */ - /* patch with actual leakage voltage */ - if (leakage_table->leakage_id[index] == *voltage) { - *voltage = leakage_table->actual_voltage[index]; - break; - } - } - - if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) - pr_info("Voltage value looks like a Leakage ID but it's not patched\n"); -} - -/** -* Patch voltage lookup table by EVV leakages. -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pointer to voltage lookup table -* @param pointer to leakage table -* @return always 0 -*/ -static int vega10_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table *lookup_table, - struct vega10_leakage_voltage *leakage_table) -{ - uint32_t i; - - for (i = 0; i < lookup_table->count; i++) - vega10_patch_with_vdd_leakage(hwmgr, - &lookup_table->entries[i].us_vdd, leakage_table); - - return 0; -} - -static int vega10_patch_clock_voltage_limits_with_vddc_leakage( - struct pp_hwmgr *hwmgr, struct vega10_leakage_voltage *leakage_table, - uint16_t *vddc) -{ - vega10_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); - - return 0; -} -#endif - -static int vega10_patch_voltage_dependency_tables_with_lookup_table( - struct pp_hwmgr *hwmgr) -{ - uint8_t entry_id, voltage_id; - unsigned i; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = - table_info->vdd_dep_on_mclk; - - for (i = 0; i < 6; i++) { - struct phm_ppt_v1_clock_voltage_dependency_table *vdt; - switch (i) { - case 0: vdt = table_info->vdd_dep_on_socclk; break; - case 1: vdt = table_info->vdd_dep_on_sclk; break; - case 2: vdt = table_info->vdd_dep_on_dcefclk; break; - case 3: vdt = table_info->vdd_dep_on_pixclk; break; - case 4: vdt = table_info->vdd_dep_on_dispclk; break; - case 5: vdt = table_info->vdd_dep_on_phyclk; break; - } - - for (entry_id = 0; entry_id < vdt->count; entry_id++) { - voltage_id = vdt->entries[entry_id].vddInd; - vdt->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - } - - for (entry_id = 0; entry_id < mm_table->count; ++entry_id) { - voltage_id = mm_table->entries[entry_id].vddcInd; - mm_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - } - - for (entry_id = 0; entry_id < mclk_table->count; ++entry_id) { - voltage_id = mclk_table->entries[entry_id].vddInd; - mclk_table->entries[entry_id].vddc = - table_info->vddc_lookup_table->entries[voltage_id].us_vdd; - voltage_id = mclk_table->entries[entry_id].vddciInd; - mclk_table->entries[entry_id].vddci = - table_info->vddci_lookup_table->entries[voltage_id].us_vdd; - voltage_id = mclk_table->entries[entry_id].mvddInd; - mclk_table->entries[entry_id].mvdd = - table_info->vddmem_lookup_table->entries[voltage_id].us_vdd; - } - - - return 0; - -} - -static int vega10_sort_lookup_table(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_voltage_lookup_table *lookup_table) -{ - uint32_t table_size, i, j; - - PP_ASSERT_WITH_CODE(lookup_table && lookup_table->count, - "Lookup table is empty", return -EINVAL); - - table_size = lookup_table->count; - - /* Sorting voltages */ - for (i = 0; i < table_size - 1; i++) { - for (j = i + 1; j > 0; j--) { - if (lookup_table->entries[j].us_vdd < - lookup_table->entries[j - 1].us_vdd) { - swap(lookup_table->entries[j - 1], - lookup_table->entries[j]); - } - } - } - - return 0; -} - -static int vega10_complete_dependency_tables(struct pp_hwmgr *hwmgr) -{ - int result = 0; - int tmp_result; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); -#ifdef PPLIB_VEGA10_EVV_SUPPORT - struct vega10_hwmgr *data = hwmgr->backend; - - tmp_result = vega10_patch_lookup_table_with_leakage(hwmgr, - table_info->vddc_lookup_table, &(data->vddc_leakage)); - if (tmp_result) - result = tmp_result; - - tmp_result = vega10_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, - &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); - if (tmp_result) - result = tmp_result; -#endif - - tmp_result = vega10_patch_voltage_dependency_tables_with_lookup_table(hwmgr); - if (tmp_result) - result = tmp_result; - - tmp_result = vega10_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); - if (tmp_result) - result = tmp_result; - - return result; -} - -static int vega10_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = - table_info->vdd_dep_on_socclk; - struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = - table_info->vdd_dep_on_mclk; - - PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table, - "VDD dependency on SCLK table is missing. This table is mandatory", return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, - "VDD dependency on SCLK table is empty. This table is mandatory", return -EINVAL); - - PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table, - "VDD dependency on MCLK table is missing. This table is mandatory", return -EINVAL); - PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, - "VDD dependency on MCLK table is empty. This table is mandatory", return -EINVAL); - - table_info->max_clock_voltage_on_ac.sclk = - allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; - table_info->max_clock_voltage_on_ac.mclk = - allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; - table_info->max_clock_voltage_on_ac.vddc = - allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; - table_info->max_clock_voltage_on_ac.vddci = - allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; - - hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = - table_info->max_clock_voltage_on_ac.sclk; - hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = - table_info->max_clock_voltage_on_ac.mclk; - hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = - table_info->max_clock_voltage_on_ac.vddc; - hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = - table_info->max_clock_voltage_on_ac.vddci; - - return 0; -} - -static int vega10_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); - hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; - - kfree(hwmgr->backend); - hwmgr->backend = NULL; - - return 0; -} - -static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct vega10_hwmgr *data; - uint32_t config_telemetry = 0; - struct pp_atomfwctrl_voltage_table vol_table; - struct amdgpu_device *adev = hwmgr->adev; - - data = kzalloc(sizeof(struct vega10_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - - hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; - hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - - vega10_set_default_registry_data(hwmgr); - data->disable_dpm_mask = 0xff; - - /* need to set voltage control types before EVV patching */ - data->vddc_control = VEGA10_VOLTAGE_CONTROL_NONE; - data->mvdd_control = VEGA10_VOLTAGE_CONTROL_NONE; - data->vddci_control = VEGA10_VOLTAGE_CONTROL_NONE; - - /* VDDCR_SOC */ - if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, - VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) { - if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, - VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2, - &vol_table)) { - config_telemetry = ((vol_table.telemetry_slope << 8) & 0xff00) | - (vol_table.telemetry_offset & 0xff); - data->vddc_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; - } - } else { - kfree(hwmgr->backend); - hwmgr->backend = NULL; - PP_ASSERT_WITH_CODE(false, - "VDDCR_SOC is not SVID2!", - return -1); - } - - /* MVDDC */ - if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, - VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2)) { - if (!pp_atomfwctrl_get_voltage_table_v4(hwmgr, - VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_SVID2, - &vol_table)) { - config_telemetry |= - ((vol_table.telemetry_slope << 24) & 0xff000000) | - ((vol_table.telemetry_offset << 16) & 0xff0000); - data->mvdd_control = VEGA10_VOLTAGE_CONTROL_BY_SVID2; - } - } - - /* VDDCI_MEM */ - if (PP_CAP(PHM_PlatformCaps_ControlVDDCI)) { - if (pp_atomfwctrl_is_voltage_controlled_by_gpio_v4(hwmgr, - VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) - data->vddci_control = VEGA10_VOLTAGE_CONTROL_BY_GPIO; - } - - data->config_telemetry = config_telemetry; - - vega10_set_features_platform_caps(hwmgr); - - vega10_init_dpm_defaults(hwmgr); - -#ifdef PPLIB_VEGA10_EVV_SUPPORT - /* Get leakage voltage based on leakage ID. */ - PP_ASSERT_WITH_CODE(!vega10_get_evv_voltages(hwmgr), - "Get EVV Voltage Failed. Abort Driver loading!", - return -1); -#endif - - /* Patch our voltage dependency table with actual leakage voltage - * We need to perform leakage translation before it's used by other functions - */ - vega10_complete_dependency_tables(hwmgr); - - /* Parse pptable data read from VBIOS */ - vega10_set_private_data_based_on_pptable(hwmgr); - - data->is_tlu_enabled = false; - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = - VEGA10_MAX_HARDWARE_POWERLEVELS; - hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; - hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - - hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ - /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ - hwmgr->platform_descriptor.clockStep.engineClock = 500; - hwmgr->platform_descriptor.clockStep.memoryClock = 500; - - data->total_active_cus = adev->gfx.cu_info.number; - if (!hwmgr->not_vf) - return result; - - /* Setup default Overdrive Fan control settings */ - data->odn_fan_table.target_fan_speed = - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM; - data->odn_fan_table.target_temperature = - hwmgr->thermal_controller. - advanceFanControlParameters.ucTargetTemperature; - data->odn_fan_table.min_performance_clock = - hwmgr->thermal_controller.advanceFanControlParameters. - ulMinFanSCLKAcousticLimit; - data->odn_fan_table.min_fan_limit = - hwmgr->thermal_controller. - advanceFanControlParameters.usFanPWMMinLimit * - hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100; - - data->mem_channels = (RREG32_SOC15(DF, 0, mmDF_CS_AON0_DramBaseAddress0) & - DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >> - DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; - PP_ASSERT_WITH_CODE(data->mem_channels < ARRAY_SIZE(channel_number), - "Mem Channel Index Exceeded maximum!", - return -EINVAL); - - return result; -} - -static int vega10_init_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->low_sclk_interrupt_threshold = 0; - - return 0; -} - -static int vega10_setup_dpm_led_config(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - - struct pp_atomfwctrl_voltage_table table; - uint8_t i, j; - uint32_t mask = 0; - uint32_t tmp; - int32_t ret = 0; - - ret = pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_LEDDPM, - VOLTAGE_OBJ_GPIO_LUT, &table); - - if (!ret) { - tmp = table.mask_low; - for (i = 0, j = 0; i < 32; i++) { - if (tmp & 1) { - mask |= (uint32_t)(i << (8 * j)); - if (++j >= 3) - break; - } - tmp >>= 1; - } - } - - pp_table->LedPin0 = (uint8_t)(mask & 0xff); - pp_table->LedPin1 = (uint8_t)((mask >> 8) & 0xff); - pp_table->LedPin2 = (uint8_t)((mask >> 16) & 0xff); - return 0; -} - -static int vega10_setup_asic_task(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->not_vf) - return 0; - - PP_ASSERT_WITH_CODE(!vega10_init_sclk_threshold(hwmgr), - "Failed to init sclk threshold!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(!vega10_setup_dpm_led_config(hwmgr), - "Failed to set up led dpm config!", - return -EINVAL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, - 0, - NULL); - - return 0; -} - -/** -* Remove repeated voltage values and create table with unique values. -* -* @param hwmgr the address of the powerplay hardware manager. -* @param vol_table the pointer to changing voltage table -* @return 0 in success -*/ - -static int vega10_trim_voltage_table(struct pp_hwmgr *hwmgr, - struct pp_atomfwctrl_voltage_table *vol_table) -{ - uint32_t i, j; - uint16_t vvalue; - bool found = false; - struct pp_atomfwctrl_voltage_table *table; - - PP_ASSERT_WITH_CODE(vol_table, - "Voltage Table empty.", return -EINVAL); - table = kzalloc(sizeof(struct pp_atomfwctrl_voltage_table), - GFP_KERNEL); - - if (!table) - return -ENOMEM; - - table->mask_low = vol_table->mask_low; - table->phase_delay = vol_table->phase_delay; - - for (i = 0; i < vol_table->count; i++) { - vvalue = vol_table->entries[i].value; - found = false; - - for (j = 0; j < table->count; j++) { - if (vvalue == table->entries[j].value) { - found = true; - break; - } - } - - if (!found) { - table->entries[table->count].value = vvalue; - table->entries[table->count].smio_low = - vol_table->entries[i].smio_low; - table->count++; - } - } - - memcpy(vol_table, table, sizeof(struct pp_atomfwctrl_voltage_table)); - kfree(table); - - return 0; -} - -static int vega10_get_mvdd_voltage_table(struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table *dep_table, - struct pp_atomfwctrl_voltage_table *vol_table) -{ - int i; - - PP_ASSERT_WITH_CODE(dep_table->count, - "Voltage Dependency Table empty.", - return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - vol_table->count = dep_table->count; - - for (i = 0; i < vol_table->count; i++) { - vol_table->entries[i].value = dep_table->entries[i].mvdd; - vol_table->entries[i].smio_low = 0; - } - - PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, - vol_table), - "Failed to trim MVDD Table!", - return -1); - - return 0; -} - -static int vega10_get_vddci_voltage_table(struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table *dep_table, - struct pp_atomfwctrl_voltage_table *vol_table) -{ - uint32_t i; - - PP_ASSERT_WITH_CODE(dep_table->count, - "Voltage Dependency Table empty.", - return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - vol_table->count = dep_table->count; - - for (i = 0; i < dep_table->count; i++) { - vol_table->entries[i].value = dep_table->entries[i].vddci; - vol_table->entries[i].smio_low = 0; - } - - PP_ASSERT_WITH_CODE(!vega10_trim_voltage_table(hwmgr, vol_table), - "Failed to trim VDDCI table.", - return -1); - - return 0; -} - -static int vega10_get_vdd_voltage_table(struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table *dep_table, - struct pp_atomfwctrl_voltage_table *vol_table) -{ - int i; - - PP_ASSERT_WITH_CODE(dep_table->count, - "Voltage Dependency Table empty.", - return -EINVAL); - - vol_table->mask_low = 0; - vol_table->phase_delay = 0; - vol_table->count = dep_table->count; - - for (i = 0; i < vol_table->count; i++) { - vol_table->entries[i].value = dep_table->entries[i].vddc; - vol_table->entries[i].smio_low = 0; - } - - return 0; -} - -/* ---- Voltage Tables ---- - * If the voltage table would be bigger than - * what will fit into the state table on - * the SMC keep only the higher entries. - */ -static void vega10_trim_voltage_table_to_fit_state_table( - struct pp_hwmgr *hwmgr, - uint32_t max_vol_steps, - struct pp_atomfwctrl_voltage_table *vol_table) -{ - unsigned int i, diff; - - if (vol_table->count <= max_vol_steps) - return; - - diff = vol_table->count - max_vol_steps; - - for (i = 0; i < max_vol_steps; i++) - vol_table->entries[i] = vol_table->entries[i + diff]; - - vol_table->count = max_vol_steps; -} - -/** -* Create Voltage Tables. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int vega10_construct_voltage_tables(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - int result; - - if (data->mvdd_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || - data->mvdd_control == VEGA10_VOLTAGE_CONTROL_NONE) { - result = vega10_get_mvdd_voltage_table(hwmgr, - table_info->vdd_dep_on_mclk, - &(data->mvdd_voltage_table)); - PP_ASSERT_WITH_CODE(!result, - "Failed to retrieve MVDDC table!", - return result); - } - - if (data->vddci_control == VEGA10_VOLTAGE_CONTROL_NONE) { - result = vega10_get_vddci_voltage_table(hwmgr, - table_info->vdd_dep_on_mclk, - &(data->vddci_voltage_table)); - PP_ASSERT_WITH_CODE(!result, - "Failed to retrieve VDDCI_MEM table!", - return result); - } - - if (data->vddc_control == VEGA10_VOLTAGE_CONTROL_BY_SVID2 || - data->vddc_control == VEGA10_VOLTAGE_CONTROL_NONE) { - result = vega10_get_vdd_voltage_table(hwmgr, - table_info->vdd_dep_on_sclk, - &(data->vddc_voltage_table)); - PP_ASSERT_WITH_CODE(!result, - "Failed to retrieve VDDCR_SOC table!", - return result); - } - - PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 16, - "Too many voltage values for VDDC. Trimming to fit state table.", - vega10_trim_voltage_table_to_fit_state_table(hwmgr, - 16, &(data->vddc_voltage_table))); - - PP_ASSERT_WITH_CODE(data->vddci_voltage_table.count <= 16, - "Too many voltage values for VDDCI. Trimming to fit state table.", - vega10_trim_voltage_table_to_fit_state_table(hwmgr, - 16, &(data->vddci_voltage_table))); - - PP_ASSERT_WITH_CODE(data->mvdd_voltage_table.count <= 16, - "Too many voltage values for MVDD. Trimming to fit state table.", - vega10_trim_voltage_table_to_fit_state_table(hwmgr, - 16, &(data->mvdd_voltage_table))); - - - return 0; -} - -/* - * @fn vega10_init_dpm_state - * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. - * - * @param dpm_state - the address of the DPM Table to initiailize. - * @return None. - */ -static void vega10_init_dpm_state(struct vega10_dpm_state *dpm_state) -{ - dpm_state->soft_min_level = 0xff; - dpm_state->soft_max_level = 0xff; - dpm_state->hard_min_level = 0xff; - dpm_state->hard_max_level = 0xff; -} - -static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr, - struct vega10_single_dpm_table *dpm_table, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table) -{ - int i; - - dpm_table->count = 0; - - for (i = 0; i < dep_table->count; i++) { - if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <= - dep_table->entries[i].clk) { - dpm_table->dpm_levels[dpm_table->count].value = - dep_table->entries[i].clk; - dpm_table->dpm_levels[dpm_table->count].enabled = true; - dpm_table->count++; - } - } -} -static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *bios_pcie_table = - table_info->pcie_table; - uint32_t i; - - PP_ASSERT_WITH_CODE(bios_pcie_table->count, - "Incorrect number of PCIE States from VBIOS!", - return -1); - - for (i = 0; i < NUM_LINK_LEVELS; i++) { - if (data->registry_data.pcieSpeedOverride) - pcie_table->pcie_gen[i] = - data->registry_data.pcieSpeedOverride; - else - pcie_table->pcie_gen[i] = - bios_pcie_table->entries[i].gen_speed; - - if (data->registry_data.pcieLaneOverride) - pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( - data->registry_data.pcieLaneOverride); - else - pcie_table->pcie_lane[i] = (uint8_t)encode_pcie_lane_width( - bios_pcie_table->entries[i].lane_width); - if (data->registry_data.pcieClockOverride) - pcie_table->lclk[i] = - data->registry_data.pcieClockOverride; - else - pcie_table->lclk[i] = - bios_pcie_table->entries[i].pcie_sclk; - } - - pcie_table->count = NUM_LINK_LEVELS; - - return 0; -} - -/* - * This function is to initialize all DPM state tables - * for SMU based on the dependency table. - * Dynamic state patching function will then trim these - * state tables to the allowed range based - * on the power policy or external client requests, - * such as UVD request, etc. - */ -static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct vega10_single_dpm_table *dpm_table; - uint32_t i; - - struct phm_ppt_v1_clock_voltage_dependency_table *dep_soc_table = - table_info->vdd_dep_on_socclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_gfx_table = - table_info->vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = - table_info->vdd_dep_on_mclk; - struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_mm_table = - table_info->mm_dep_table; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_dcef_table = - table_info->vdd_dep_on_dcefclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_pix_table = - table_info->vdd_dep_on_pixclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_disp_table = - table_info->vdd_dep_on_dispclk; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_phy_table = - table_info->vdd_dep_on_phyclk; - - PP_ASSERT_WITH_CODE(dep_soc_table, - "SOCCLK dependency table is missing. This table is mandatory", - return -EINVAL); - PP_ASSERT_WITH_CODE(dep_soc_table->count >= 1, - "SOCCLK dependency table is empty. This table is mandatory", - return -EINVAL); - - PP_ASSERT_WITH_CODE(dep_gfx_table, - "GFXCLK dependency table is missing. This table is mandatory", - return -EINVAL); - PP_ASSERT_WITH_CODE(dep_gfx_table->count >= 1, - "GFXCLK dependency table is empty. This table is mandatory", - return -EINVAL); - - PP_ASSERT_WITH_CODE(dep_mclk_table, - "MCLK dependency table is missing. This table is mandatory", - return -EINVAL); - PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, - "MCLK dependency table has to have is missing. This table is mandatory", - return -EINVAL); - - /* Initialize Sclk DPM table based on allow Sclk values */ - dpm_table = &(data->dpm_table.soc_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_soc_table); - - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - dpm_table = &(data->dpm_table.gfx_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_gfx_table); - if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0) - hwmgr->platform_descriptor.overdriveLimit.engineClock = - dpm_table->dpm_levels[dpm_table->count-1].value; - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - /* Initialize Mclk DPM table based on allow Mclk values */ - data->dpm_table.mem_table.count = 0; - dpm_table = &(data->dpm_table.mem_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_mclk_table); - if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - dpm_table->dpm_levels[dpm_table->count-1].value; - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - data->dpm_table.eclk_table.count = 0; - dpm_table = &(data->dpm_table.eclk_table); - for (i = 0; i < dep_mm_table->count; i++) { - if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value <= - dep_mm_table->entries[i].eclk) { - dpm_table->dpm_levels[dpm_table->count].value = - dep_mm_table->entries[i].eclk; - dpm_table->dpm_levels[dpm_table->count].enabled = - (i == 0) ? true : false; - dpm_table->count++; - } - } - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - data->dpm_table.vclk_table.count = 0; - data->dpm_table.dclk_table.count = 0; - dpm_table = &(data->dpm_table.vclk_table); - for (i = 0; i < dep_mm_table->count; i++) { - if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value <= - dep_mm_table->entries[i].vclk) { - dpm_table->dpm_levels[dpm_table->count].value = - dep_mm_table->entries[i].vclk; - dpm_table->dpm_levels[dpm_table->count].enabled = - (i == 0) ? true : false; - dpm_table->count++; - } - } - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - dpm_table = &(data->dpm_table.dclk_table); - for (i = 0; i < dep_mm_table->count; i++) { - if (i == 0 || dpm_table->dpm_levels - [dpm_table->count - 1].value <= - dep_mm_table->entries[i].dclk) { - dpm_table->dpm_levels[dpm_table->count].value = - dep_mm_table->entries[i].dclk; - dpm_table->dpm_levels[dpm_table->count].enabled = - (i == 0) ? true : false; - dpm_table->count++; - } - } - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - /* Assume there is no headless Vega10 for now */ - dpm_table = &(data->dpm_table.dcef_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_dcef_table); - - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - dpm_table = &(data->dpm_table.pixel_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_pix_table); - - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - dpm_table = &(data->dpm_table.display_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_disp_table); - - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - dpm_table = &(data->dpm_table.phy_table); - vega10_setup_default_single_dpm_table(hwmgr, - dpm_table, - dep_phy_table); - - vega10_init_dpm_state(&(dpm_table->dpm_state)); - - vega10_setup_default_pcie_table(hwmgr); - - /* Zero out the saved copy of the CUSTOM profile - * This will be checked when trying to set the profile - * and will require that new values be passed in - */ - data->custom_profile_mode[0] = 0; - data->custom_profile_mode[1] = 0; - data->custom_profile_mode[2] = 0; - data->custom_profile_mode[3] = 0; - - /* save a copy of the default DPM table */ - memcpy(&(data->golden_dpm_table), &(data->dpm_table), - sizeof(struct vega10_dpm_table)); - - return 0; -} - -/* - * @fn vega10_populate_ulv_state - * @brief Function to provide parameters for Utral Low Voltage state to SMC. - * - * @param hwmgr - the address of the hardware manager. - * @return Always 0. - */ -static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - data->smc_state_table.pp_table.UlvOffsetVid = - (uint8_t)table_info->us_ulv_voltage_offset; - - data->smc_state_table.pp_table.UlvSmnclkDid = - (uint8_t)(table_info->us_ulv_smnclk_did); - data->smc_state_table.pp_table.UlvMp1clkDid = - (uint8_t)(table_info->us_ulv_mp1clk_did); - data->smc_state_table.pp_table.UlvGfxclkBypass = - (uint8_t)(table_info->us_ulv_gfxclk_bypass); - data->smc_state_table.pp_table.UlvPhaseSheddingPsi0 = - (uint8_t)(data->vddc_voltage_table.psi0_enable); - data->smc_state_table.pp_table.UlvPhaseSheddingPsi1 = - (uint8_t)(data->vddc_voltage_table.psi1_enable); - - return 0; -} - -static int vega10_populate_single_lclk_level(struct pp_hwmgr *hwmgr, - uint32_t lclock, uint8_t *curr_lclk_did) -{ - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( - hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, - lclock, ÷rs), - "Failed to get LCLK clock settings from VBIOS!", - return -1); - - *curr_lclk_did = dividers.ulDid; - - return 0; -} - -static int vega10_populate_smc_link_levels(struct pp_hwmgr *hwmgr) -{ - int result = -1; - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega10_pcie_table *pcie_table = - &(data->dpm_table.pcie_table); - uint32_t i, j; - - for (i = 0; i < pcie_table->count; i++) { - pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[i]; - pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[i]; - - result = vega10_populate_single_lclk_level(hwmgr, - pcie_table->lclk[i], &(pp_table->LclkDid[i])); - if (result) { - pr_info("Populate LClock Level %d Failed!\n", i); - return result; - } - } - - j = i - 1; - while (i < NUM_LINK_LEVELS) { - pp_table->PcieGenSpeed[i] = pcie_table->pcie_gen[j]; - pp_table->PcieLaneCount[i] = pcie_table->pcie_lane[j]; - - result = vega10_populate_single_lclk_level(hwmgr, - pcie_table->lclk[j], &(pp_table->LclkDid[i])); - if (result) { - pr_info("Populate LClock Level %d Failed!\n", i); - return result; - } - i++; - } - - return result; -} - -/** -* Populates single SMC GFXSCLK structure using the provided engine clock -* -* @param hwmgr the address of the hardware manager -* @param gfx_clock the GFX clock to use to populate the structure. -* @param current_gfxclk_level location in PPTable for the SMC GFXCLK structure. -*/ - -static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr, - uint32_t gfx_clock, PllSetting_t *current_gfxclk_level, - uint32_t *acg_freq) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_sclk; - struct vega10_hwmgr *data = hwmgr->backend; - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - uint32_t gfx_max_clock = - hwmgr->platform_descriptor.overdriveLimit.engineClock; - uint32_t i = 0; - - if (hwmgr->od_enabled) - dep_on_sclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) - &(data->odn_dpm_table.vdd_dep_on_sclk); - else - dep_on_sclk = table_info->vdd_dep_on_sclk; - - PP_ASSERT_WITH_CODE(dep_on_sclk, - "Invalid SOC_VDD-GFX_CLK Dependency Table!", - return -EINVAL); - - if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) - gfx_clock = gfx_clock > gfx_max_clock ? gfx_max_clock : gfx_clock; - else { - for (i = 0; i < dep_on_sclk->count; i++) { - if (dep_on_sclk->entries[i].clk == gfx_clock) - break; - } - PP_ASSERT_WITH_CODE(dep_on_sclk->count > i, - "Cannot find gfx_clk in SOC_VDD-GFX_CLK!", - return -EINVAL); - } - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_GFXCLK, - gfx_clock, ÷rs), - "Failed to get GFX Clock settings from VBIOS!", - return -EINVAL); - - /* Feedback Multiplier: bit 0:8 int, bit 15:12 post_div, bit 31:16 frac */ - current_gfxclk_level->FbMult = - cpu_to_le32(dividers.ulPll_fb_mult); - /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */ - current_gfxclk_level->SsOn = dividers.ucPll_ss_enable; - current_gfxclk_level->SsFbMult = - cpu_to_le32(dividers.ulPll_ss_fbsmult); - current_gfxclk_level->SsSlewFrac = - cpu_to_le16(dividers.usPll_ss_slew_frac); - current_gfxclk_level->Did = (uint8_t)(dividers.ulDid); - - *acg_freq = gfx_clock / 100; /* 100 Khz to Mhz conversion */ - - return 0; -} - -/** - * @brief Populates single SMC SOCCLK structure using the provided clock. - * - * @param hwmgr - the address of the hardware manager. - * @param soc_clock - the SOC clock to use to populate the structure. - * @param current_socclk_level - location in PPTable for the SMC SOCCLK structure. - * @return 0 on success.. - */ -static int vega10_populate_single_soc_level(struct pp_hwmgr *hwmgr, - uint32_t soc_clock, uint8_t *current_soc_did, - uint8_t *current_vol_index) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_soc; - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - uint32_t i; - - if (hwmgr->od_enabled) { - dep_on_soc = (struct phm_ppt_v1_clock_voltage_dependency_table *) - &data->odn_dpm_table.vdd_dep_on_socclk; - for (i = 0; i < dep_on_soc->count; i++) { - if (dep_on_soc->entries[i].clk >= soc_clock) - break; - } - } else { - dep_on_soc = table_info->vdd_dep_on_socclk; - for (i = 0; i < dep_on_soc->count; i++) { - if (dep_on_soc->entries[i].clk == soc_clock) - break; - } - } - - PP_ASSERT_WITH_CODE(dep_on_soc->count > i, - "Cannot find SOC_CLK in SOC_VDD-SOC_CLK Dependency Table", - return -EINVAL); - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, - soc_clock, ÷rs), - "Failed to get SOC Clock settings from VBIOS!", - return -EINVAL); - - *current_soc_did = (uint8_t)dividers.ulDid; - *current_vol_index = (uint8_t)(dep_on_soc->entries[i].vddInd); - return 0; -} - -/** -* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states -* -* @param hwmgr the address of the hardware manager -*/ -static int vega10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); - int result = 0; - uint32_t i, j; - - for (i = 0; i < dpm_table->count; i++) { - result = vega10_populate_single_gfx_level(hwmgr, - dpm_table->dpm_levels[i].value, - &(pp_table->GfxclkLevel[i]), - &(pp_table->AcgFreqTable[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_GFXCLK_DPM_LEVELS) { - result = vega10_populate_single_gfx_level(hwmgr, - dpm_table->dpm_levels[j].value, - &(pp_table->GfxclkLevel[i]), - &(pp_table->AcgFreqTable[i])); - if (result) - return result; - i++; - } - - pp_table->GfxclkSlewRate = - cpu_to_le16(table_info->us_gfxclk_slew_rate); - - dpm_table = &(data->dpm_table.soc_table); - for (i = 0; i < dpm_table->count; i++) { - result = vega10_populate_single_soc_level(hwmgr, - dpm_table->dpm_levels[i].value, - &(pp_table->SocclkDid[i]), - &(pp_table->SocDpmVoltageIndex[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_SOCCLK_DPM_LEVELS) { - result = vega10_populate_single_soc_level(hwmgr, - dpm_table->dpm_levels[j].value, - &(pp_table->SocclkDid[i]), - &(pp_table->SocDpmVoltageIndex[i])); - if (result) - return result; - i++; - } - - return result; -} - -static void vega10_populate_vddc_soc_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct phm_ppt_v2_information *table_info = hwmgr->pptable; - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; - - uint8_t soc_vid = 0; - uint32_t i, max_vddc_level; - - if (hwmgr->od_enabled) - vddc_lookup_table = (struct phm_ppt_v1_voltage_lookup_table *)&data->odn_dpm_table.vddc_lookup_table; - else - vddc_lookup_table = table_info->vddc_lookup_table; - - max_vddc_level = vddc_lookup_table->count; - for (i = 0; i < max_vddc_level; i++) { - soc_vid = (uint8_t)convert_to_vid(vddc_lookup_table->entries[i].us_vdd); - pp_table->SocVid[i] = soc_vid; - } - while (i < MAX_REGULAR_DPM_NUMBER) { - pp_table->SocVid[i] = soc_vid; - i++; - } -} - -/** - * @brief Populates single SMC GFXCLK structure using the provided clock. - * - * @param hwmgr - the address of the hardware manager. - * @param mem_clock - the memory clock to use to populate the structure. - * @return 0 on success.. - */ -static int vega10_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t mem_clock, uint8_t *current_mem_vid, - PllSetting_t *current_memclk_level, uint8_t *current_mem_soc_vind) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_on_mclk; - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - uint32_t mem_max_clock = - hwmgr->platform_descriptor.overdriveLimit.memoryClock; - uint32_t i = 0; - - if (hwmgr->od_enabled) - dep_on_mclk = (struct phm_ppt_v1_clock_voltage_dependency_table *) - &data->odn_dpm_table.vdd_dep_on_mclk; - else - dep_on_mclk = table_info->vdd_dep_on_mclk; - - PP_ASSERT_WITH_CODE(dep_on_mclk, - "Invalid SOC_VDD-UCLK Dependency Table!", - return -EINVAL); - - if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { - mem_clock = mem_clock > mem_max_clock ? mem_max_clock : mem_clock; - } else { - for (i = 0; i < dep_on_mclk->count; i++) { - if (dep_on_mclk->entries[i].clk == mem_clock) - break; - } - PP_ASSERT_WITH_CODE(dep_on_mclk->count > i, - "Cannot find UCLK in SOC_VDD-UCLK Dependency Table!", - return -EINVAL); - } - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10( - hwmgr, COMPUTE_GPUCLK_INPUT_FLAG_UCLK, mem_clock, ÷rs), - "Failed to get UCLK settings from VBIOS!", - return -1); - - *current_mem_vid = - (uint8_t)(convert_to_vid(dep_on_mclk->entries[i].mvdd)); - *current_mem_soc_vind = - (uint8_t)(dep_on_mclk->entries[i].vddInd); - current_memclk_level->FbMult = cpu_to_le32(dividers.ulPll_fb_mult); - current_memclk_level->Did = (uint8_t)(dividers.ulDid); - - PP_ASSERT_WITH_CODE(current_memclk_level->Did >= 1, - "Invalid Divider ID!", - return -EINVAL); - - return 0; -} - -/** - * @brief Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states. - * - * @param pHwMgr - the address of the hardware manager. - * @return PP_Result_OK on success. - */ -static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega10_single_dpm_table *dpm_table = - &(data->dpm_table.mem_table); - int result = 0; - uint32_t i, j; - - for (i = 0; i < dpm_table->count; i++) { - result = vega10_populate_single_memory_level(hwmgr, - dpm_table->dpm_levels[i].value, - &(pp_table->MemVid[i]), - &(pp_table->UclkLevel[i]), - &(pp_table->MemSocVoltageIndex[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_UCLK_DPM_LEVELS) { - result = vega10_populate_single_memory_level(hwmgr, - dpm_table->dpm_levels[j].value, - &(pp_table->MemVid[i]), - &(pp_table->UclkLevel[i]), - &(pp_table->MemSocVoltageIndex[i])); - if (result) - return result; - i++; - } - - pp_table->NumMemoryChannels = (uint16_t)(data->mem_channels); - pp_table->MemoryChannelWidth = - (uint16_t)(HBM_MEMORY_CHANNEL_WIDTH * - channel_number[data->mem_channels]); - - pp_table->LowestUclkReservedForUlv = - (uint8_t)(data->lowest_uclk_reserved_for_ulv); - - return result; -} - -static int vega10_populate_single_display_type(struct pp_hwmgr *hwmgr, - DSPCLK_e disp_clock) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *) - (hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; - uint32_t i; - uint16_t clk = 0, vddc = 0; - uint8_t vid = 0; - - switch (disp_clock) { - case DSPCLK_DCEFCLK: - dep_table = table_info->vdd_dep_on_dcefclk; - break; - case DSPCLK_DISPCLK: - dep_table = table_info->vdd_dep_on_dispclk; - break; - case DSPCLK_PIXCLK: - dep_table = table_info->vdd_dep_on_pixclk; - break; - case DSPCLK_PHYCLK: - dep_table = table_info->vdd_dep_on_phyclk; - break; - default: - return -1; - } - - PP_ASSERT_WITH_CODE(dep_table->count <= NUM_DSPCLK_LEVELS, - "Number Of Entries Exceeded maximum!", - return -1); - - for (i = 0; i < dep_table->count; i++) { - clk = (uint16_t)(dep_table->entries[i].clk / 100); - vddc = table_info->vddc_lookup_table-> - entries[dep_table->entries[i].vddInd].us_vdd; - vid = (uint8_t)convert_to_vid(vddc); - pp_table->DisplayClockTable[disp_clock][i].Freq = - cpu_to_le16(clk); - pp_table->DisplayClockTable[disp_clock][i].Vid = - cpu_to_le16(vid); - } - - while (i < NUM_DSPCLK_LEVELS) { - pp_table->DisplayClockTable[disp_clock][i].Freq = - cpu_to_le16(clk); - pp_table->DisplayClockTable[disp_clock][i].Vid = - cpu_to_le16(vid); - i++; - } - - return 0; -} - -static int vega10_populate_all_display_clock_levels(struct pp_hwmgr *hwmgr) -{ - uint32_t i; - - for (i = 0; i < DSPCLK_COUNT; i++) { - PP_ASSERT_WITH_CODE(!vega10_populate_single_display_type(hwmgr, i), - "Failed to populate Clock in DisplayClockTable!", - return -1); - } - - return 0; -} - -static int vega10_populate_single_eclock_level(struct pp_hwmgr *hwmgr, - uint32_t eclock, uint8_t *current_eclk_did, - uint8_t *current_soc_vol) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = - table_info->mm_dep_table; - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - uint32_t i; - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, - eclock, ÷rs), - "Failed to get ECLK clock settings from VBIOS!", - return -1); - - *current_eclk_did = (uint8_t)dividers.ulDid; - - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].eclk == eclock) - *current_soc_vol = dep_table->entries[i].vddcInd; - } - - return 0; -} - -static int vega10_populate_smc_vce_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega10_single_dpm_table *dpm_table = &(data->dpm_table.eclk_table); - int result = -EINVAL; - uint32_t i, j; - - for (i = 0; i < dpm_table->count; i++) { - result = vega10_populate_single_eclock_level(hwmgr, - dpm_table->dpm_levels[i].value, - &(pp_table->EclkDid[i]), - &(pp_table->VceDpmVoltageIndex[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_VCE_DPM_LEVELS) { - result = vega10_populate_single_eclock_level(hwmgr, - dpm_table->dpm_levels[j].value, - &(pp_table->EclkDid[i]), - &(pp_table->VceDpmVoltageIndex[i])); - if (result) - return result; - i++; - } - - return result; -} - -static int vega10_populate_single_vclock_level(struct pp_hwmgr *hwmgr, - uint32_t vclock, uint8_t *current_vclk_did) -{ - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, - vclock, ÷rs), - "Failed to get VCLK clock settings from VBIOS!", - return -EINVAL); - - *current_vclk_did = (uint8_t)dividers.ulDid; - - return 0; -} - -static int vega10_populate_single_dclock_level(struct pp_hwmgr *hwmgr, - uint32_t dclock, uint8_t *current_dclk_did) -{ - struct pp_atomfwctrl_clock_dividers_soc15 dividers; - - PP_ASSERT_WITH_CODE(!pp_atomfwctrl_get_gpu_pll_dividers_vega10(hwmgr, - COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK, - dclock, ÷rs), - "Failed to get DCLK clock settings from VBIOS!", - return -EINVAL); - - *current_dclk_did = (uint8_t)dividers.ulDid; - - return 0; -} - -static int vega10_populate_smc_uvd_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega10_single_dpm_table *vclk_dpm_table = - &(data->dpm_table.vclk_table); - struct vega10_single_dpm_table *dclk_dpm_table = - &(data->dpm_table.dclk_table); - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *dep_table = - table_info->mm_dep_table; - int result = -EINVAL; - uint32_t i, j; - - for (i = 0; i < vclk_dpm_table->count; i++) { - result = vega10_populate_single_vclock_level(hwmgr, - vclk_dpm_table->dpm_levels[i].value, - &(pp_table->VclkDid[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_UVD_DPM_LEVELS) { - result = vega10_populate_single_vclock_level(hwmgr, - vclk_dpm_table->dpm_levels[j].value, - &(pp_table->VclkDid[i])); - if (result) - return result; - i++; - } - - for (i = 0; i < dclk_dpm_table->count; i++) { - result = vega10_populate_single_dclock_level(hwmgr, - dclk_dpm_table->dpm_levels[i].value, - &(pp_table->DclkDid[i])); - if (result) - return result; - } - - j = i - 1; - while (i < NUM_UVD_DPM_LEVELS) { - result = vega10_populate_single_dclock_level(hwmgr, - dclk_dpm_table->dpm_levels[j].value, - &(pp_table->DclkDid[i])); - if (result) - return result; - i++; - } - - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vclk == - vclk_dpm_table->dpm_levels[i].value && - dep_table->entries[i].dclk == - dclk_dpm_table->dpm_levels[i].value) - pp_table->UvdDpmVoltageIndex[i] = - dep_table->entries[i].vddcInd; - else - return -1; - } - - j = i - 1; - while (i < NUM_UVD_DPM_LEVELS) { - pp_table->UvdDpmVoltageIndex[i] = dep_table->entries[j].vddcInd; - i++; - } - - return 0; -} - -static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_sclk; - uint32_t i; - - for (i = 0; i < dep_table->count; i++) { - pp_table->CksEnable[i] = dep_table->entries[i].cks_enable; - pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset - * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - } - - return 0; -} - -static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_sclk; - struct pp_atomfwctrl_avfs_parameters avfs_params = {0}; - int result = 0; - uint32_t i; - - pp_table->MinVoltageVid = (uint8_t)0xff; - pp_table->MaxVoltageVid = (uint8_t)0; - - if (data->smu_features[GNLD_AVFS].supported) { - result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params); - if (!result) { - pp_table->MinVoltageVid = (uint8_t) - convert_to_vid((uint16_t)(avfs_params.ulMinVddc)); - pp_table->MaxVoltageVid = (uint8_t) - convert_to_vid((uint16_t)(avfs_params.ulMaxVddc)); - - pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0); - pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1); - pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2); - pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); - pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean); - pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma); - pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor); - - pp_table->BtcGbVdroopTableCksOff.a0 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0); - pp_table->BtcGbVdroopTableCksOff.a0_shift = 20; - pp_table->BtcGbVdroopTableCksOff.a1 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1); - pp_table->BtcGbVdroopTableCksOff.a1_shift = 20; - pp_table->BtcGbVdroopTableCksOff.a2 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2); - pp_table->BtcGbVdroopTableCksOff.a2_shift = 20; - - pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson; - pp_table->BtcGbVdroopTableCksOn.a0 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0); - pp_table->BtcGbVdroopTableCksOn.a0_shift = 20; - pp_table->BtcGbVdroopTableCksOn.a1 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1); - pp_table->BtcGbVdroopTableCksOn.a1_shift = 20; - pp_table->BtcGbVdroopTableCksOn.a2 = - cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2); - pp_table->BtcGbVdroopTableCksOn.a2_shift = 20; - - pp_table->AvfsGbCksOn.m1 = - cpu_to_le32(avfs_params.ulGbFuseTableCksonM1); - pp_table->AvfsGbCksOn.m2 = - cpu_to_le32(avfs_params.ulGbFuseTableCksonM2); - pp_table->AvfsGbCksOn.b = - cpu_to_le32(avfs_params.ulGbFuseTableCksonB); - pp_table->AvfsGbCksOn.m1_shift = 24; - pp_table->AvfsGbCksOn.m2_shift = 12; - pp_table->AvfsGbCksOn.b_shift = 0; - - pp_table->OverrideAvfsGbCksOn = - avfs_params.ucEnableGbFuseTableCkson; - pp_table->AvfsGbCksOff.m1 = - cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1); - pp_table->AvfsGbCksOff.m2 = - cpu_to_le32(avfs_params.ulGbFuseTableCksoffM2); - pp_table->AvfsGbCksOff.b = - cpu_to_le32(avfs_params.ulGbFuseTableCksoffB); - pp_table->AvfsGbCksOff.m1_shift = 24; - pp_table->AvfsGbCksOff.m2_shift = 12; - pp_table->AvfsGbCksOff.b_shift = 0; - - for (i = 0; i < dep_table->count; i++) - pp_table->StaticVoltageOffsetVid[i] = - convert_to_vid((uint8_t)(dep_table->entries[i].sclk_offset)); - - if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->disp_clk_quad_eqn_a) && - (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->disp_clk_quad_eqn_b)) { - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = - (int32_t)data->disp_clk_quad_eqn_a; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = - (int32_t)data->disp_clk_quad_eqn_b; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = - (int32_t)data->disp_clk_quad_eqn_c; - } else { - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 = - (int32_t)avfs_params.ulDispclk2GfxclkM1; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 = - (int32_t)avfs_params.ulDispclk2GfxclkM2; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b = - (int32_t)avfs_params.ulDispclk2GfxclkB; - } - - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12; - - if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->dcef_clk_quad_eqn_a) && - (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->dcef_clk_quad_eqn_b)) { - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = - (int32_t)data->dcef_clk_quad_eqn_a; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = - (int32_t)data->dcef_clk_quad_eqn_b; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = - (int32_t)data->dcef_clk_quad_eqn_c; - } else { - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 = - (int32_t)avfs_params.ulDcefclk2GfxclkM1; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 = - (int32_t)avfs_params.ulDcefclk2GfxclkM2; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b = - (int32_t)avfs_params.ulDcefclk2GfxclkB; - } - - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12; - - if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->pixel_clk_quad_eqn_a) && - (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->pixel_clk_quad_eqn_b)) { - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = - (int32_t)data->pixel_clk_quad_eqn_a; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = - (int32_t)data->pixel_clk_quad_eqn_b; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = - (int32_t)data->pixel_clk_quad_eqn_c; - } else { - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 = - (int32_t)avfs_params.ulPixelclk2GfxclkM1; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 = - (int32_t)avfs_params.ulPixelclk2GfxclkM2; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b = - (int32_t)avfs_params.ulPixelclk2GfxclkB; - } - - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12; - if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->phy_clk_quad_eqn_a) && - (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT != - data->phy_clk_quad_eqn_b)) { - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = - (int32_t)data->phy_clk_quad_eqn_a; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = - (int32_t)data->phy_clk_quad_eqn_b; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = - (int32_t)data->phy_clk_quad_eqn_c; - } else { - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 = - (int32_t)avfs_params.ulPhyclk2GfxclkM1; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 = - (int32_t)avfs_params.ulPhyclk2GfxclkM2; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b = - (int32_t)avfs_params.ulPhyclk2GfxclkB; - } - - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12; - pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12; - - pp_table->AcgBtcGbVdroopTable.a0 = avfs_params.ulAcgGbVdroopTableA0; - pp_table->AcgBtcGbVdroopTable.a0_shift = 20; - pp_table->AcgBtcGbVdroopTable.a1 = avfs_params.ulAcgGbVdroopTableA1; - pp_table->AcgBtcGbVdroopTable.a1_shift = 20; - pp_table->AcgBtcGbVdroopTable.a2 = avfs_params.ulAcgGbVdroopTableA2; - pp_table->AcgBtcGbVdroopTable.a2_shift = 20; - - pp_table->AcgAvfsGb.m1 = avfs_params.ulAcgGbFuseTableM1; - pp_table->AcgAvfsGb.m2 = avfs_params.ulAcgGbFuseTableM2; - pp_table->AcgAvfsGb.b = avfs_params.ulAcgGbFuseTableB; - pp_table->AcgAvfsGb.m1_shift = 24; - pp_table->AcgAvfsGb.m2_shift = 12; - pp_table->AcgAvfsGb.b_shift = 0; - - } else { - data->smu_features[GNLD_AVFS].supported = false; - } - } - - return 0; -} - -static int vega10_acg_enable(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t agc_btc_response; - - if (data->smu_features[GNLD_ACG].supported) { - if (0 == vega10_enable_smc_features(hwmgr, true, - data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_bitmap)) - data->smu_features[GNLD_DPM_PREFETCHER].enabled = true; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitializeAcg, NULL); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &agc_btc_response); - - if (1 == agc_btc_response) { - if (1 == data->acg_loop_state) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInClosedLoop, NULL); - else if (2 == data->acg_loop_state) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgInOpenLoop, NULL); - if (0 == vega10_enable_smc_features(hwmgr, true, - data->smu_features[GNLD_ACG].smu_feature_bitmap)) - data->smu_features[GNLD_ACG].enabled = true; - } else { - pr_info("[ACG_Enable] ACG BTC Returned Failed Status!\n"); - data->smu_features[GNLD_ACG].enabled = false; - } - } - - return 0; -} - -static int vega10_acg_disable(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_ACG].supported && - data->smu_features[GNLD_ACG].enabled) - if (!vega10_enable_smc_features(hwmgr, false, - data->smu_features[GNLD_ACG].smu_feature_bitmap)) - data->smu_features[GNLD_ACG].enabled = false; - - return 0; -} - -static int vega10_populate_gpio_parameters(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct pp_atomfwctrl_gpio_parameters gpio_params = {0}; - int result; - - result = pp_atomfwctrl_get_gpio_information(hwmgr, &gpio_params); - if (!result) { - if (PP_CAP(PHM_PlatformCaps_RegulatorHot) && - data->registry_data.regulator_hot_gpio_support) { - pp_table->VR0HotGpio = gpio_params.ucVR0HotGpio; - pp_table->VR0HotPolarity = gpio_params.ucVR0HotPolarity; - pp_table->VR1HotGpio = gpio_params.ucVR1HotGpio; - pp_table->VR1HotPolarity = gpio_params.ucVR1HotPolarity; - } else { - pp_table->VR0HotGpio = 0; - pp_table->VR0HotPolarity = 0; - pp_table->VR1HotGpio = 0; - pp_table->VR1HotPolarity = 0; - } - - if (PP_CAP(PHM_PlatformCaps_AutomaticDCTransition) && - data->registry_data.ac_dc_switch_gpio_support) { - pp_table->AcDcGpio = gpio_params.ucAcDcGpio; - pp_table->AcDcPolarity = gpio_params.ucAcDcPolarity; - } else { - pp_table->AcDcGpio = 0; - pp_table->AcDcPolarity = 0; - } - } - - return result; -} - -static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_AVFS].supported) { - /* Already enabled or disabled */ - if (!(enable ^ data->smu_features[GNLD_AVFS].enabled)) - return 0; - - if (enable) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, - data->smu_features[GNLD_AVFS].smu_feature_bitmap), - "[avfs_control] Attempt to Enable AVFS feature Failed!", - return -1); - data->smu_features[GNLD_AVFS].enabled = true; - } else { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, - data->smu_features[GNLD_AVFS].smu_feature_bitmap), - "[avfs_control] Attempt to Disable AVFS feature Failed!", - return -1); - data->smu_features[GNLD_AVFS].enabled = false; - } - } - - return 0; -} - -static int vega10_update_avfs(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->need_update_dpm_table & DPMTABLE_OD_UPDATE_VDDC) { - vega10_avfs_enable(hwmgr, false); - } else if (data->need_update_dpm_table) { - vega10_avfs_enable(hwmgr, false); - vega10_avfs_enable(hwmgr, true); - } else { - vega10_avfs_enable(hwmgr, true); - } - - return 0; -} - -static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - uint64_t serial_number = 0; - uint32_t top32, bottom32; - struct phm_fuses_default fuse; - - struct vega10_hwmgr *data = hwmgr->backend; - AvfsFuseOverride_t *avfs_fuse_table = &(data->smc_state_table.avfs_fuse_override_table); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); - - serial_number = ((uint64_t)bottom32 << 32) | top32; - - if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) { - avfs_fuse_table->VFT0_b = fuse.VFT0_b; - avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1; - avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2; - avfs_fuse_table->VFT1_b = fuse.VFT1_b; - avfs_fuse_table->VFT1_m1 = fuse.VFT1_m1; - avfs_fuse_table->VFT1_m2 = fuse.VFT1_m2; - avfs_fuse_table->VFT2_b = fuse.VFT2_b; - avfs_fuse_table->VFT2_m1 = fuse.VFT2_m1; - avfs_fuse_table->VFT2_m2 = fuse.VFT2_m2; - result = smum_smc_table_manager(hwmgr, (uint8_t *)avfs_fuse_table, - AVFSFUSETABLE, false); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload FuseOVerride!", - ); - } - - return result; -} - -static void vega10_check_dpm_table_updated(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct phm_ppt_v2_information *table_info = hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; - struct phm_ppt_v1_clock_voltage_dependency_table *odn_dep_table; - uint32_t i; - - dep_table = table_info->vdd_dep_on_mclk; - odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_mclk); - - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_MCLK; - return; - } - } - - dep_table = table_info->vdd_dep_on_sclk; - odn_dep_table = (struct phm_ppt_v1_clock_voltage_dependency_table *)&(odn_table->vdd_dep_on_sclk); - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vddc != odn_dep_table->entries[i].vddc) { - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC | DPMTABLE_OD_UPDATE_SCLK; - return; - } - } -} - -/** -* Initializes the SMC table and uploads it -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data (PowerState) -* @return always 0 -*/ -static int vega10_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct pp_atomfwctrl_voltage_table voltage_table; - struct pp_atomfwctrl_bios_boot_up_values boot_up_values; - struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); - - result = vega10_setup_default_dpm_tables(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to setup default DPM tables!", - return result); - - if (!hwmgr->not_vf) - return 0; - - /* initialize ODN table */ - if (hwmgr->od_enabled) { - if (odn_table->max_vddc) { - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_OD_UPDATE_MCLK; - vega10_check_dpm_table_updated(hwmgr); - } else { - vega10_odn_initial_default_setting(hwmgr); - } - } - - pp_atomfwctrl_get_voltage_table_v4(hwmgr, VOLTAGE_TYPE_VDDC, - VOLTAGE_OBJ_SVID2, &voltage_table); - pp_table->MaxVidStep = voltage_table.max_vid_step; - - pp_table->GfxDpmVoltageMode = - (uint8_t)(table_info->uc_gfx_dpm_voltage_mode); - pp_table->SocDpmVoltageMode = - (uint8_t)(table_info->uc_soc_dpm_voltage_mode); - pp_table->UclkDpmVoltageMode = - (uint8_t)(table_info->uc_uclk_dpm_voltage_mode); - pp_table->UvdDpmVoltageMode = - (uint8_t)(table_info->uc_uvd_dpm_voltage_mode); - pp_table->VceDpmVoltageMode = - (uint8_t)(table_info->uc_vce_dpm_voltage_mode); - pp_table->Mp0DpmVoltageMode = - (uint8_t)(table_info->uc_mp0_dpm_voltage_mode); - - pp_table->DisplayDpmVoltageMode = - (uint8_t)(table_info->uc_dcef_dpm_voltage_mode); - - data->vddc_voltage_table.psi0_enable = voltage_table.psi0_enable; - data->vddc_voltage_table.psi1_enable = voltage_table.psi1_enable; - - if (data->registry_data.ulv_support && - table_info->us_ulv_voltage_offset) { - result = vega10_populate_ulv_state(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ULV state!", - return result); - } - - result = vega10_populate_smc_link_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Link Level!", - return result); - - result = vega10_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Graphics Level!", - return result); - - result = vega10_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Memory Level!", - return result); - - vega10_populate_vddc_soc_levels(hwmgr); - - result = vega10_populate_all_display_clock_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Display Level!", - return result); - - result = vega10_populate_smc_vce_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize VCE Level!", - return result); - - result = vega10_populate_smc_uvd_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize UVD Level!", - return result); - - if (data->registry_data.clock_stretcher_support) { - result = vega10_populate_clock_stretcher_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate Clock Stretcher Table!", - return result); - } - - result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); - if (!result) { - data->vbios_boot_state.vddc = boot_up_values.usVddc; - data->vbios_boot_state.vddci = boot_up_values.usVddci; - data->vbios_boot_state.mvddc = boot_up_values.usMvddc; - data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; - data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; - pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, - SMU9_SYSPLL0_SOCCLK_ID, 0, &boot_up_values.ulSocClk); - - pp_atomfwctrl_get_clk_information_by_clkid(hwmgr, - SMU9_SYSPLL0_DCEFCLK_ID, 0, &boot_up_values.ulDCEFClk); - - data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; - data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; - if (0 != boot_up_values.usVddc) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFloorSocVoltage, - (boot_up_values.usVddc * 4), - NULL); - data->vbios_boot_state.bsoc_vddc_lock = true; - } else { - data->vbios_boot_state.bsoc_vddc_lock = false; - } - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinDeepSleepDcefclk, - (uint32_t)(data->vbios_boot_state.dcef_clock / 100), - NULL); - } - - result = vega10_populate_avfs_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize AVFS Parameters!", - return result); - - result = vega10_populate_gpio_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize GPIO Parameters!", - return result); - - pp_table->GfxclkAverageAlpha = (uint8_t) - (data->gfxclk_average_alpha); - pp_table->SocclkAverageAlpha = (uint8_t) - (data->socclk_average_alpha); - pp_table->UclkAverageAlpha = (uint8_t) - (data->uclk_average_alpha); - pp_table->GfxActivityAverageAlpha = (uint8_t) - (data->gfx_activity_average_alpha); - - vega10_populate_and_upload_avfs_fuse_override(hwmgr); - - result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); - - PP_ASSERT_WITH_CODE(!result, - "Failed to upload PPtable!", return result); - - result = vega10_avfs_enable(hwmgr, true); - PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!", - return result); - vega10_acg_enable(hwmgr); - - return 0; -} - -static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_THERMAL].supported) { - if (data->smu_features[GNLD_THERMAL].enabled) - pr_info("THERMAL Feature Already enabled!"); - - PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr, - true, - data->smu_features[GNLD_THERMAL].smu_feature_bitmap), - "Enable THERMAL Feature Failed!", - return -1); - data->smu_features[GNLD_THERMAL].enabled = true; - } - - return 0; -} - -static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_THERMAL].supported) { - if (!data->smu_features[GNLD_THERMAL].enabled) - pr_info("THERMAL Feature Already disabled!"); - - PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr, - false, - data->smu_features[GNLD_THERMAL].smu_feature_bitmap), - "disable THERMAL Feature Failed!", - return -1); - data->smu_features[GNLD_THERMAL].enabled = false; - } - - return 0; -} - -static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (PP_CAP(PHM_PlatformCaps_RegulatorHot)) { - if (data->smu_features[GNLD_VR0HOT].supported) { - PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr, - true, - data->smu_features[GNLD_VR0HOT].smu_feature_bitmap), - "Attempt to Enable VR0 Hot feature Failed!", - return -1); - data->smu_features[GNLD_VR0HOT].enabled = true; - } else { - if (data->smu_features[GNLD_VR1HOT].supported) { - PP_ASSERT_WITH_CODE( - !vega10_enable_smc_features(hwmgr, - true, - data->smu_features[GNLD_VR1HOT].smu_feature_bitmap), - "Attempt to Enable VR0 Hot feature Failed!", - return -1); - data->smu_features[GNLD_VR1HOT].enabled = true; - } - } - } - return 0; -} - -static int vega10_enable_ulv(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->registry_data.ulv_support) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_ULV].smu_feature_bitmap), - "Enable ULV Feature Failed!", - return -1); - data->smu_features[GNLD_ULV].enabled = true; - } - - return 0; -} - -static int vega10_disable_ulv(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->registry_data.ulv_support) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_ULV].smu_feature_bitmap), - "disable ULV Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_ULV].enabled = false; - } - - return 0; -} - -static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DS_GFXCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), - "Attempt to Enable DS_GFXCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_GFXCLK].enabled = true; - } - - if (data->smu_features[GNLD_DS_SOCCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), - "Attempt to Enable DS_SOCCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_SOCCLK].enabled = true; - } - - if (data->smu_features[GNLD_DS_LCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), - "Attempt to Enable DS_LCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_LCLK].enabled = true; - } - - if (data->smu_features[GNLD_DS_DCEFCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), - "Attempt to Enable DS_DCEFCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_DCEFCLK].enabled = true; - } - - return 0; -} - -static int vega10_disable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DS_GFXCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap), - "Attempt to disable DS_GFXCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_GFXCLK].enabled = false; - } - - if (data->smu_features[GNLD_DS_SOCCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap), - "Attempt to disable DS_ Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_SOCCLK].enabled = false; - } - - if (data->smu_features[GNLD_DS_LCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap), - "Attempt to disable DS_LCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_LCLK].enabled = false; - } - - if (data->smu_features[GNLD_DS_DCEFCLK].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap), - "Attempt to disable DS_DCEFCLK Feature Failed!", - return -EINVAL); - data->smu_features[GNLD_DS_DCEFCLK].enabled = false; - } - - return 0; -} - -static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t i, feature_mask = 0; - - if (!hwmgr->not_vf) - return 0; - - if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), - "Attempt to disable LED DPM feature failed!", return -EINVAL); - data->smu_features[GNLD_LED_DISPLAY].enabled = false; - } - - for (i = 0; i < GNLD_DPM_MAX; i++) { - if (data->smu_features[i].smu_feature_bitmap & bitmap) { - if (data->smu_features[i].supported) { - if (data->smu_features[i].enabled) { - feature_mask |= data->smu_features[i]. - smu_feature_bitmap; - data->smu_features[i].enabled = false; - } - } - } - } - - vega10_enable_smc_features(hwmgr, false, feature_mask); - - return 0; -} - -/** - * @brief Tell SMC to enabled the supported DPMs. - * - * @param hwmgr - the address of the powerplay hardware manager. - * @Param bitmap - bitmap for the features to enabled. - * @return 0 on at least one DPM is successfully enabled. - */ -static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t i, feature_mask = 0; - - for (i = 0; i < GNLD_DPM_MAX; i++) { - if (data->smu_features[i].smu_feature_bitmap & bitmap) { - if (data->smu_features[i].supported) { - if (!data->smu_features[i].enabled) { - feature_mask |= data->smu_features[i]. - smu_feature_bitmap; - data->smu_features[i].enabled = true; - } - } - } - } - - if (vega10_enable_smc_features(hwmgr, - true, feature_mask)) { - for (i = 0; i < GNLD_DPM_MAX; i++) { - if (data->smu_features[i].smu_feature_bitmap & - feature_mask) - data->smu_features[i].enabled = false; - } - } - - if(data->smu_features[GNLD_LED_DISPLAY].supported == true){ - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap), - "Attempt to Enable LED DPM feature Failed!", return -EINVAL); - data->smu_features[GNLD_LED_DISPLAY].enabled = true; - } - - if (data->vbios_boot_state.bsoc_vddc_lock) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFloorSocVoltage, 0, - NULL); - data->vbios_boot_state.bsoc_vddc_lock = false; - } - - if (PP_CAP(PHM_PlatformCaps_Falcon_QuickTransition)) { - if (data->smu_features[GNLD_ACDC].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_ACDC].smu_feature_bitmap), - "Attempt to Enable DS_GFXCLK Feature Failed!", - return -1); - data->smu_features[GNLD_ACDC].enabled = true; - } - } - - return 0; -} - -static int vega10_enable_disable_PCC_limit_feature(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_PCC_LIMIT].supported) { - if (enable == data->smu_features[GNLD_PCC_LIMIT].enabled) - pr_info("GNLD_PCC_LIMIT has been %s \n", enable ? "enabled" : "disabled"); - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - enable, data->smu_features[GNLD_PCC_LIMIT].smu_feature_bitmap), - "Attempt to Enable PCC Limit feature Failed!", - return -EINVAL); - data->smu_features[GNLD_PCC_LIMIT].enabled = enable; - } - - return 0; -} - -static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - int tmp_result, result = 0; - - if (hwmgr->not_vf) { - vega10_enable_disable_PCC_limit_feature(hwmgr, true); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_ConfigureTelemetry, data->config_telemetry, - NULL); - - tmp_result = vega10_construct_voltage_tables(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to construct voltage tables!", - result = tmp_result); - } - - if (hwmgr->not_vf || hwmgr->pp_one_vf) { - tmp_result = vega10_init_smc_table(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to initialize SMC table!", - result = tmp_result); - } - - if (hwmgr->not_vf) { - if (PP_CAP(PHM_PlatformCaps_ThermalController)) { - tmp_result = vega10_enable_thermal_protection(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to enable thermal protection!", - result = tmp_result); - } - - tmp_result = vega10_enable_vrhot_feature(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to enable VR hot feature!", - result = tmp_result); - - tmp_result = vega10_enable_deep_sleep_master_switch(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to enable deep sleep master switch!", - result = tmp_result); - } - - if (hwmgr->not_vf) { - tmp_result = vega10_start_dpm(hwmgr, SMC_DPM_FEATURES); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to start DPM!", result = tmp_result); - } - - if (hwmgr->not_vf) { - /* enable didt, do not abort if failed didt */ - tmp_result = vega10_enable_didt_config(hwmgr); - PP_ASSERT(!tmp_result, - "Failed to enable didt config!"); - } - - tmp_result = vega10_enable_power_containment(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to enable power containment!", - result = tmp_result); - - if (hwmgr->not_vf) { - tmp_result = vega10_power_control_set_level(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to power control set level!", - result = tmp_result); - - tmp_result = vega10_enable_ulv(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to enable ULV!", - result = tmp_result); - } - - return result; -} - -static int vega10_get_power_state_size(struct pp_hwmgr *hwmgr) -{ - return sizeof(struct vega10_power_state); -} - -static int vega10_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr, - void *state, struct pp_power_state *power_state, - void *pp_table, uint32_t classification_flag) -{ - ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_V2; - struct vega10_power_state *vega10_power_state = - cast_phw_vega10_power_state(&(power_state->hardware)); - struct vega10_performance_level *performance_level; - ATOM_Vega10_State *state_entry = (ATOM_Vega10_State *)state; - ATOM_Vega10_POWERPLAYTABLE *powerplay_table = - (ATOM_Vega10_POWERPLAYTABLE *)pp_table; - ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = - (ATOM_Vega10_SOCCLK_Dependency_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); - ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = - (ATOM_Vega10_GFXCLK_Dependency_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); - ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = - (ATOM_Vega10_MCLK_Dependency_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); - - - /* The following fields are not initialized here: - * id orderedList allStatesList - */ - power_state->classification.ui_label = - (le16_to_cpu(state_entry->usClassification) & - ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> - ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; - power_state->classification.flags = classification_flag; - /* NOTE: There is a classification2 flag in BIOS - * that is not being used right now - */ - power_state->classification.temporary_state = false; - power_state->classification.to_be_deleted = false; - - power_state->validation.disallowOnDC = - ((le32_to_cpu(state_entry->ulCapsAndSettings) & - ATOM_Vega10_DISALLOW_ON_DC) != 0); - - power_state->display.disableFrameModulation = false; - power_state->display.limitRefreshrate = false; - power_state->display.enableVariBright = - ((le32_to_cpu(state_entry->ulCapsAndSettings) & - ATOM_Vega10_ENABLE_VARIBRIGHT) != 0); - - power_state->validation.supportedPowerLevels = 0; - power_state->uvd_clocks.VCLK = 0; - power_state->uvd_clocks.DCLK = 0; - power_state->temperatures.min = 0; - power_state->temperatures.max = 0; - - performance_level = &(vega10_power_state->performance_levels - [vega10_power_state->performance_level_count++]); - - PP_ASSERT_WITH_CODE( - (vega10_power_state->performance_level_count < - NUM_GFXCLK_DPM_LEVELS), - "Performance levels exceeds SMC limit!", - return -1); - - PP_ASSERT_WITH_CODE( - (vega10_power_state->performance_level_count <= - hwmgr->platform_descriptor. - hardwareActivityPerformanceLevels), - "Performance levels exceeds Driver limit!", - return -1); - - /* Performance levels are arranged from low to high. */ - performance_level->soc_clock = socclk_dep_table->entries - [state_entry->ucSocClockIndexLow].ulClk; - performance_level->gfx_clock = gfxclk_dep_table->entries - [state_entry->ucGfxClockIndexLow].ulClk; - performance_level->mem_clock = mclk_dep_table->entries - [state_entry->ucMemClockIndexLow].ulMemClk; - - performance_level = &(vega10_power_state->performance_levels - [vega10_power_state->performance_level_count++]); - performance_level->soc_clock = socclk_dep_table->entries - [state_entry->ucSocClockIndexHigh].ulClk; - if (gfxclk_dep_table->ucRevId == 0) { - /* under vega10 pp one vf mode, the gfx clk dpm need be lower - * to level-4 due to the limited 110w-power - */ - if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) - performance_level->gfx_clock = - gfxclk_dep_table->entries[4].ulClk; - else - performance_level->gfx_clock = gfxclk_dep_table->entries - [state_entry->ucGfxClockIndexHigh].ulClk; - } else if (gfxclk_dep_table->ucRevId == 1) { - patom_record_V2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; - if (hwmgr->pp_one_vf && (state_entry->ucGfxClockIndexHigh > 0)) - performance_level->gfx_clock = patom_record_V2[4].ulClk; - else - performance_level->gfx_clock = - patom_record_V2[state_entry->ucGfxClockIndexHigh].ulClk; - } - - performance_level->mem_clock = mclk_dep_table->entries - [state_entry->ucMemClockIndexHigh].ulMemClk; - return 0; -} - -static int vega10_get_pp_table_entry(struct pp_hwmgr *hwmgr, - unsigned long entry_index, struct pp_power_state *state) -{ - int result; - struct vega10_power_state *ps; - - state->hardware.magic = PhwVega10_Magic; - - ps = cast_phw_vega10_power_state(&state->hardware); - - result = vega10_get_powerplay_table_entry(hwmgr, entry_index, state, - vega10_get_pp_table_entry_callback_func); - - /* - * This is the earliest time we have all the dependency table - * and the VBIOS boot state - */ - /* set DC compatible flag if this state supports DC */ - if (!state->validation.disallowOnDC) - ps->dc_compatible = true; - - ps->uvd_clks.vclk = state->uvd_clocks.VCLK; - ps->uvd_clks.dclk = state->uvd_clocks.DCLK; - - return 0; -} - -static int vega10_patch_boot_state(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps) -{ - return 0; -} - -static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *request_ps, - const struct pp_power_state *current_ps) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct vega10_power_state *vega10_ps = - cast_phw_vega10_power_state(&request_ps->hardware); - uint32_t sclk; - uint32_t mclk; - struct PP_Clocks minimum_clocks = {0}; - bool disable_mclk_switching; - bool disable_mclk_switching_for_frame_lock; - bool disable_mclk_switching_for_vr; - bool force_mclk_high; - const struct phm_clock_and_voltage_limits *max_limits; - uint32_t i; - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - int32_t count; - uint32_t stable_pstate_sclk_dpm_percentage; - uint32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; - uint32_t latency; - - data->battery_state = (PP_StateUILabel_Battery == - request_ps->classification.ui_label); - - if (vega10_ps->performance_level_count != 2) - pr_info("VI should always have 2 performance levels"); - - max_limits = adev->pm.ac_power ? - &(hwmgr->dyn_state.max_clock_voltage_on_ac) : - &(hwmgr->dyn_state.max_clock_voltage_on_dc); - - /* Cap clock DPM tables at DC MAX if it is in DC. */ - if (!adev->pm.ac_power) { - for (i = 0; i < vega10_ps->performance_level_count; i++) { - if (vega10_ps->performance_levels[i].mem_clock > - max_limits->mclk) - vega10_ps->performance_levels[i].mem_clock = - max_limits->mclk; - if (vega10_ps->performance_levels[i].gfx_clock > - max_limits->sclk) - vega10_ps->performance_levels[i].gfx_clock = - max_limits->sclk; - } - } - - /* result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ - minimum_clocks.engineClock = hwmgr->display_config->min_core_set_clock; - minimum_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; - - if (PP_CAP(PHM_PlatformCaps_StablePState)) { - stable_pstate_sclk_dpm_percentage = - data->registry_data.stable_pstate_sclk_dpm_percentage; - PP_ASSERT_WITH_CODE( - data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && - data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, - "percent sclk value must range from 1% to 100%, setting default value", - stable_pstate_sclk_dpm_percentage = 75); - - max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); - stable_pstate_sclk = (max_limits->sclk * - stable_pstate_sclk_dpm_percentage) / 100; - - for (count = table_info->vdd_dep_on_sclk->count - 1; - count >= 0; count--) { - if (stable_pstate_sclk >= - table_info->vdd_dep_on_sclk->entries[count].clk) { - stable_pstate_sclk = - table_info->vdd_dep_on_sclk->entries[count].clk; - break; - } - } - - if (count < 0) - stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; - - stable_pstate_mclk = max_limits->mclk; - - minimum_clocks.engineClock = stable_pstate_sclk; - minimum_clocks.memoryClock = stable_pstate_mclk; - } - - disable_mclk_switching_for_frame_lock = - PP_CAP(PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); - disable_mclk_switching_for_vr = - PP_CAP(PHM_PlatformCaps_DisableMclkSwitchForVR); - force_mclk_high = PP_CAP(PHM_PlatformCaps_ForceMclkHigh); - - if (hwmgr->display_config->num_display == 0) - disable_mclk_switching = false; - else - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && - !hwmgr->display_config->multi_monitor_in_sync) || - disable_mclk_switching_for_frame_lock || - disable_mclk_switching_for_vr || - force_mclk_high; - - sclk = vega10_ps->performance_levels[0].gfx_clock; - mclk = vega10_ps->performance_levels[0].mem_clock; - - if (sclk < minimum_clocks.engineClock) - sclk = (minimum_clocks.engineClock > max_limits->sclk) ? - max_limits->sclk : minimum_clocks.engineClock; - - if (mclk < minimum_clocks.memoryClock) - mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? - max_limits->mclk : minimum_clocks.memoryClock; - - vega10_ps->performance_levels[0].gfx_clock = sclk; - vega10_ps->performance_levels[0].mem_clock = mclk; - - if (vega10_ps->performance_levels[1].gfx_clock < - vega10_ps->performance_levels[0].gfx_clock) - vega10_ps->performance_levels[0].gfx_clock = - vega10_ps->performance_levels[1].gfx_clock; - - if (disable_mclk_switching) { - /* Set Mclk the max of level 0 and level 1 */ - if (mclk < vega10_ps->performance_levels[1].mem_clock) - mclk = vega10_ps->performance_levels[1].mem_clock; - - /* Find the lowest MCLK frequency that is within - * the tolerable latency defined in DAL - */ - latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; - for (i = 0; i < data->mclk_latency_table.count; i++) { - if ((data->mclk_latency_table.entries[i].latency <= latency) && - (data->mclk_latency_table.entries[i].frequency >= - vega10_ps->performance_levels[0].mem_clock) && - (data->mclk_latency_table.entries[i].frequency <= - vega10_ps->performance_levels[1].mem_clock)) - mclk = data->mclk_latency_table.entries[i].frequency; - } - vega10_ps->performance_levels[0].mem_clock = mclk; - } else { - if (vega10_ps->performance_levels[1].mem_clock < - vega10_ps->performance_levels[0].mem_clock) - vega10_ps->performance_levels[0].mem_clock = - vega10_ps->performance_levels[1].mem_clock; - } - - if (PP_CAP(PHM_PlatformCaps_StablePState)) { - for (i = 0; i < vega10_ps->performance_level_count; i++) { - vega10_ps->performance_levels[i].gfx_clock = stable_pstate_sclk; - vega10_ps->performance_levels[i].mem_clock = stable_pstate_mclk; - } - } - - return 0; -} - -static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) -{ - struct vega10_hwmgr *data = hwmgr->backend; - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - const struct vega10_power_state *vega10_ps = - cast_const_phw_vega10_power_state(states->pnew_state); - struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); - uint32_t sclk = vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].gfx_clock; - struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); - uint32_t mclk = vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].mem_clock; - uint32_t i; - - for (i = 0; i < sclk_table->count; i++) { - if (sclk == sclk_table->dpm_levels[i].value) - break; - } - - if (i >= sclk_table->count) { - if (sclk > sclk_table->dpm_levels[i-1].value) { - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; - sclk_table->dpm_levels[i-1].value = sclk; - } - } - - for (i = 0; i < mclk_table->count; i++) { - if (mclk == mclk_table->dpm_levels[i].value) - break; - } - - if (i >= mclk_table->count) { - if (mclk > mclk_table->dpm_levels[i-1].value) { - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; - mclk_table->dpm_levels[i-1].value = mclk; - } - } - - if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) - data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; - - return 0; -} - -static int vega10_populate_and_upload_sclk_mclk_dpm_levels( - struct pp_hwmgr *hwmgr, const void *input) -{ - int result = 0; - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_dpm_table *dpm_table = &data->dpm_table; - struct vega10_odn_dpm_table *odn_table = &data->odn_dpm_table; - struct vega10_odn_clock_voltage_dependency_table *odn_clk_table = &odn_table->vdd_dep_on_sclk; - int count; - - if (!data->need_update_dpm_table) - return 0; - - if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { - for (count = 0; count < dpm_table->gfx_table.count; count++) - dpm_table->gfx_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; - } - - odn_clk_table = &odn_table->vdd_dep_on_mclk; - if (hwmgr->od_enabled && data->need_update_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { - for (count = 0; count < dpm_table->mem_table.count; count++) - dpm_table->mem_table.dpm_levels[count].value = odn_clk_table->entries[count].clk; - } - - if (data->need_update_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK | DPMTABLE_UPDATE_SCLK | DPMTABLE_UPDATE_SOCCLK)) { - result = vega10_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", - return result); - } - - if (data->need_update_dpm_table & - (DPMTABLE_OD_UPDATE_MCLK | DPMTABLE_UPDATE_MCLK)) { - result = vega10_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", - return result); - } - - vega10_populate_vddc_soc_levels(hwmgr); - - return result; -} - -static int vega10_trim_single_dpm_states(struct pp_hwmgr *hwmgr, - struct vega10_single_dpm_table *dpm_table, - uint32_t low_limit, uint32_t high_limit) -{ - uint32_t i; - - for (i = 0; i < dpm_table->count; i++) { - if ((dpm_table->dpm_levels[i].value < low_limit) || - (dpm_table->dpm_levels[i].value > high_limit)) - dpm_table->dpm_levels[i].enabled = false; - else - dpm_table->dpm_levels[i].enabled = true; - } - return 0; -} - -static int vega10_trim_single_dpm_states_with_mask(struct pp_hwmgr *hwmgr, - struct vega10_single_dpm_table *dpm_table, - uint32_t low_limit, uint32_t high_limit, - uint32_t disable_dpm_mask) -{ - uint32_t i; - - for (i = 0; i < dpm_table->count; i++) { - if ((dpm_table->dpm_levels[i].value < low_limit) || - (dpm_table->dpm_levels[i].value > high_limit)) - dpm_table->dpm_levels[i].enabled = false; - else if (!((1 << i) & disable_dpm_mask)) - dpm_table->dpm_levels[i].enabled = false; - else - dpm_table->dpm_levels[i].enabled = true; - } - return 0; -} - -static int vega10_trim_dpm_states(struct pp_hwmgr *hwmgr, - const struct vega10_power_state *vega10_ps) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t high_limit_count; - - PP_ASSERT_WITH_CODE((vega10_ps->performance_level_count >= 1), - "power state did not have any performance level", - return -1); - - high_limit_count = (vega10_ps->performance_level_count == 1) ? 0 : 1; - - vega10_trim_single_dpm_states(hwmgr, - &(data->dpm_table.soc_table), - vega10_ps->performance_levels[0].soc_clock, - vega10_ps->performance_levels[high_limit_count].soc_clock); - - vega10_trim_single_dpm_states_with_mask(hwmgr, - &(data->dpm_table.gfx_table), - vega10_ps->performance_levels[0].gfx_clock, - vega10_ps->performance_levels[high_limit_count].gfx_clock, - data->disable_dpm_mask); - - vega10_trim_single_dpm_states(hwmgr, - &(data->dpm_table.mem_table), - vega10_ps->performance_levels[0].mem_clock, - vega10_ps->performance_levels[high_limit_count].mem_clock); - - return 0; -} - -static uint32_t vega10_find_lowest_dpm_level( - struct vega10_single_dpm_table *table) -{ - uint32_t i; - - for (i = 0; i < table->count; i++) { - if (table->dpm_levels[i].enabled) - break; - } - - return i; -} - -static uint32_t vega10_find_highest_dpm_level( - struct vega10_single_dpm_table *table) -{ - uint32_t i = 0; - - if (table->count <= MAX_REGULAR_DPM_NUMBER) { - for (i = table->count; i > 0; i--) { - if (table->dpm_levels[i - 1].enabled) - return i - 1; - } - } else { - pr_info("DPM Table Has Too Many Entries!"); - return MAX_REGULAR_DPM_NUMBER - 1; - } - - return i; -} - -static void vega10_apply_dal_minimum_voltage_request( - struct pp_hwmgr *hwmgr) -{ - return; -} - -static int vega10_get_soc_index_for_max_uclk(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table_on_mclk; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - vdd_dep_table_on_mclk = table_info->vdd_dep_on_mclk; - - return vdd_dep_table_on_mclk->entries[NUM_UCLK_DPM_LEVELS - 1].vddInd + 1; -} - -static int vega10_upload_dpm_bootup_level(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t socclk_idx; - - vega10_apply_dal_minimum_voltage_request(hwmgr); - - if (!data->registry_data.sclk_dpm_key_disabled) { - if (data->smc_state_table.gfx_boot_level != - data->dpm_table.gfx_table.dpm_state.soft_min_level) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMinGfxclkByIndex, - data->smc_state_table.gfx_boot_level, - NULL); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->smc_state_table.gfx_boot_level; - } - } - - if (!data->registry_data.mclk_dpm_key_disabled) { - if (data->smc_state_table.mem_boot_level != - data->dpm_table.mem_table.dpm_state.soft_min_level) { - if ((data->smc_state_table.mem_boot_level == NUM_UCLK_DPM_LEVELS - 1) - && hwmgr->not_vf) { - socclk_idx = vega10_get_soc_index_for_max_uclk(hwmgr); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMinSocclkByIndex, - socclk_idx, - NULL); - } else { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMinUclkByIndex, - data->smc_state_table.mem_boot_level, - NULL); - } - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->smc_state_table.mem_boot_level; - } - } - - if (!hwmgr->not_vf) - return 0; - - if (!data->registry_data.socclk_dpm_key_disabled) { - if (data->smc_state_table.soc_boot_level != - data->dpm_table.soc_table.dpm_state.soft_min_level) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMinSocclkByIndex, - data->smc_state_table.soc_boot_level, - NULL); - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->smc_state_table.soc_boot_level; - } - } - - return 0; -} - -static int vega10_upload_dpm_max_level(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - vega10_apply_dal_minimum_voltage_request(hwmgr); - - if (!data->registry_data.sclk_dpm_key_disabled) { - if (data->smc_state_table.gfx_max_level != - data->dpm_table.gfx_table.dpm_state.soft_max_level) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxGfxclkByIndex, - data->smc_state_table.gfx_max_level, - NULL); - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->smc_state_table.gfx_max_level; - } - } - - if (!data->registry_data.mclk_dpm_key_disabled) { - if (data->smc_state_table.mem_max_level != - data->dpm_table.mem_table.dpm_state.soft_max_level) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxUclkByIndex, - data->smc_state_table.mem_max_level, - NULL); - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->smc_state_table.mem_max_level; - } - } - - if (!hwmgr->not_vf) - return 0; - - if (!data->registry_data.socclk_dpm_key_disabled) { - if (data->smc_state_table.soc_max_level != - data->dpm_table.soc_table.dpm_state.soft_max_level) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMaxSocclkByIndex, - data->smc_state_table.soc_max_level, - NULL); - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->smc_state_table.soc_max_level; - } - } - - return 0; -} - -static int vega10_generate_dpm_level_enable_mask( - struct pp_hwmgr *hwmgr, const void *input) -{ - struct vega10_hwmgr *data = hwmgr->backend; - const struct phm_set_power_state_input *states = - (const struct phm_set_power_state_input *)input; - const struct vega10_power_state *vega10_ps = - cast_const_phw_vega10_power_state(states->pnew_state); - int i; - - PP_ASSERT_WITH_CODE(!vega10_trim_dpm_states(hwmgr, vega10_ps), - "Attempt to Trim DPM States Failed!", - return -1); - - data->smc_state_table.gfx_boot_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.gfx_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.mem_boot_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - data->smc_state_table.mem_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); - data->smc_state_table.soc_boot_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.soc_table)); - data->smc_state_table.soc_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.soc_table)); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Attempt to upload DPM Bootup Levels Failed!", - return -1); - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Attempt to upload DPM Max Levels Failed!", - return -1); - for(i = data->smc_state_table.gfx_boot_level; i < data->smc_state_table.gfx_max_level; i++) - data->dpm_table.gfx_table.dpm_levels[i].enabled = true; - - - for(i = data->smc_state_table.mem_boot_level; i < data->smc_state_table.mem_max_level; i++) - data->dpm_table.mem_table.dpm_levels[i].enabled = true; - - for (i = data->smc_state_table.soc_boot_level; i < data->smc_state_table.soc_max_level; i++) - data->dpm_table.soc_table.dpm_levels[i].enabled = true; - - return 0; -} - -int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DPM_VCE].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), - "Attempt to Enable/Disable DPM VCE Failed!", - return -1); - data->smu_features[GNLD_DPM_VCE].enabled = enable; - } - - return 0; -} - -static int vega10_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t low_sclk_interrupt_threshold = 0; - - if (PP_CAP(PHM_PlatformCaps_SclkThrottleLowNotification) && - (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - data->smc_state_table.pp_table.LowGfxclkInterruptThreshold = - cpu_to_le32(low_sclk_interrupt_threshold); - - /* This message will also enable SmcToHost Interrupt */ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetLowGfxclkInterruptThreshold, - (uint32_t)low_sclk_interrupt_threshold, - NULL); - } - - return 0; -} - -static int vega10_set_power_state_tasks(struct pp_hwmgr *hwmgr, - const void *input) -{ - int tmp_result, result = 0; - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - - tmp_result = vega10_find_dpm_states_clocks_in_dpm_table(hwmgr, input); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to find DPM states clocks in DPM table!", - result = tmp_result); - - tmp_result = vega10_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to populate and upload SCLK MCLK DPM levels!", - result = tmp_result); - - tmp_result = vega10_generate_dpm_level_enable_mask(hwmgr, input); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to generate DPM level enabled mask!", - result = tmp_result); - - tmp_result = vega10_update_sclk_threshold(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to update SCLK threshold!", - result = tmp_result); - - result = smum_smc_table_manager(hwmgr, (uint8_t *)pp_table, PPTABLE, false); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload PPtable!", return result); - - /* - * If a custom pp table is loaded, set DPMTABLE_OD_UPDATE_VDDC flag. - * That effectively disables AVFS feature. - */ - if(hwmgr->hardcode_pp_table != NULL) - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; - - vega10_update_avfs(hwmgr); - - /* - * Clear all OD flags except DPMTABLE_OD_UPDATE_VDDC. - * That will help to keep AVFS disabled. - */ - data->need_update_dpm_table &= DPMTABLE_OD_UPDATE_VDDC; - - return 0; -} - -static uint32_t vega10_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct pp_power_state *ps; - struct vega10_power_state *vega10_ps; - - if (hwmgr == NULL) - return -EINVAL; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - - if (low) - return vega10_ps->performance_levels[0].gfx_clock; - else - return vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].gfx_clock; -} - -static uint32_t vega10_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct pp_power_state *ps; - struct vega10_power_state *vega10_ps; - - if (hwmgr == NULL) - return -EINVAL; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - - if (low) - return vega10_ps->performance_levels[0].mem_clock; - else - return vega10_ps->performance_levels - [vega10_ps->performance_level_count-1].mem_clock; -} - -static int vega10_get_gpu_power(struct pp_hwmgr *hwmgr, - uint32_t *query) -{ - uint32_t value; - - if (!query) - return -EINVAL; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrPkgPwr, &value); - - /* SMC returning actual watts, keep consistent with legacy asics, low 8 bit as 8 fractional bits */ - *query = value << 8; - - return 0; -} - -static int vega10_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t sclk_mhz, mclk_idx, activity_percent = 0; - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_dpm_table *dpm_table = &data->dpm_table; - int ret = 0; - uint32_t val_vid; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetAverageGfxclkActualFrequency, &sclk_mhz); - *((uint32_t *)value) = sclk_mhz * 100; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &mclk_idx); - if (mclk_idx < dpm_table->mem_table.count) { - *((uint32_t *)value) = dpm_table->mem_table.dpm_levels[mclk_idx].value; - *size = 4; - } else { - ret = -EINVAL; - } - break; - case AMDGPU_PP_SENSOR_GPU_LOAD: - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetAverageGfxActivity, 0, - &activity_percent); - *((uint32_t *)value) = activity_percent > 100 ? 100 : activity_percent; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = vega10_thermal_get_temperature(hwmgr); - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHotspot, (uint32_t *)value); - *((uint32_t *)value) = *((uint32_t *)value) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetTemperatureHBM, (uint32_t *)value); - *((uint32_t *)value) = *((uint32_t *)value) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_UVD_POWER: - *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VCE_POWER: - *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - ret = vega10_get_gpu_power(hwmgr, (uint32_t *)value); - break; - case AMDGPU_PP_SENSOR_VDDGFX: - val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_PLANE0_CURRENTVID) & - SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK) >> - SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT; - *((uint32_t *)value) = (uint32_t)convert_to_vddc((uint8_t)val_vid); - return 0; - case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: - ret = vega10_get_enabled_smc_features(hwmgr, (uint64_t *)value); - if (!ret) - *size = 8; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} - -static void vega10_notify_smc_display_change(struct pp_hwmgr *hwmgr, - bool has_disp) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetUclkFastSwitch, - has_disp ? 1 : 0, - NULL); -} - -static int vega10_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock_req) -{ - int result = 0; - enum amd_pp_clock_type clk_type = clock_req->clock_type; - uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; - DSPCLK_e clk_select = 0; - uint32_t clk_request = 0; - - switch (clk_type) { - case amd_pp_dcef_clock: - clk_select = DSPCLK_DCEFCLK; - break; - case amd_pp_disp_clock: - clk_select = DSPCLK_DISPCLK; - break; - case amd_pp_pixel_clock: - clk_select = DSPCLK_PIXCLK; - break; - case amd_pp_phy_clock: - clk_select = DSPCLK_PHYCLK; - break; - default: - pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); - result = -1; - break; - } - - if (!result) { - clk_request = (clk_freq << 16) | clk_select; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_RequestDisplayClockByFreq, - clk_request, - NULL); - } - - return result; -} - -static uint8_t vega10_get_uclk_index(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table, - uint32_t frequency) -{ - uint8_t count; - uint8_t i; - - if (mclk_table == NULL || mclk_table->count == 0) - return 0; - - count = (uint8_t)(mclk_table->count); - - for(i = 0; i < count; i++) { - if(mclk_table->entries[i].clk >= frequency) - return i; - } - - return i-1; -} - -static int vega10_notify_smc_display_config_after_ps_adjustment( - struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *dpm_table = - &data->dpm_table.dcef_table; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = table_info->vdd_dep_on_mclk; - uint32_t idx; - struct PP_Clocks min_clocks = {0}; - uint32_t i; - struct pp_display_clock_request clock_req; - - if ((hwmgr->display_config->num_display > 1) && - !hwmgr->display_config->multi_monitor_in_sync && - !hwmgr->display_config->nb_pstate_switch_disable) - vega10_notify_smc_display_change(hwmgr, false); - else - vega10_notify_smc_display_change(hwmgr, true); - - min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; - min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; - min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; - - for (i = 0; i < dpm_table->count; i++) { - if (dpm_table->dpm_levels[i].value == min_clocks.dcefClock) - break; - } - - if (i < dpm_table->count) { - clock_req.clock_type = amd_pp_dcef_clock; - clock_req.clock_freq_in_khz = dpm_table->dpm_levels[i].value * 10; - if (!vega10_display_clock_voltage_request(hwmgr, &clock_req)) { - smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcefClockInSR / 100, - NULL); - } else { - pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); - } - } else { - pr_debug("Cannot find requested DCEFCLK!"); - } - - if (min_clocks.memoryClock != 0) { - idx = vega10_get_uclk_index(hwmgr, mclk_table, min_clocks.memoryClock); - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetSoftMinUclkByIndex, idx, - NULL); - data->dpm_table.mem_table.dpm_state.soft_min_level= idx; - } - - return 0; -} - -static int vega10_force_dpm_highest(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->smc_state_table.gfx_boot_level = - data->smc_state_table.gfx_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.mem_boot_level = - data->smc_state_table.mem_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload boot level to highest!", - return -1); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -1); - - return 0; -} - -static int vega10_force_dpm_lowest(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->smc_state_table.gfx_boot_level = - data->smc_state_table.gfx_max_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.mem_boot_level = - data->smc_state_table.mem_max_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload boot level to highest!", - return -1); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -1); - - return 0; - -} - -static int vega10_unforce_dpm_levels(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->smc_state_table.gfx_boot_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.gfx_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - data->smc_state_table.mem_boot_level = - vega10_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - data->smc_state_table.mem_max_level = - vega10_find_highest_dpm_level(&(data->dpm_table.mem_table)); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload DPM Bootup Levels!", - return -1); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload DPM Max Levels!", - return -1); - return 0; -} - -static int vega10_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, - uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - if (table_info->vdd_dep_on_sclk->count > VEGA10_UMD_PSTATE_GFXCLK_LEVEL && - table_info->vdd_dep_on_socclk->count > VEGA10_UMD_PSTATE_SOCCLK_LEVEL && - table_info->vdd_dep_on_mclk->count > VEGA10_UMD_PSTATE_MCLK_LEVEL) { - *sclk_mask = VEGA10_UMD_PSTATE_GFXCLK_LEVEL; - *soc_mask = VEGA10_UMD_PSTATE_SOCCLK_LEVEL; - *mclk_mask = VEGA10_UMD_PSTATE_MCLK_LEVEL; - hwmgr->pstate_sclk = table_info->vdd_dep_on_sclk->entries[VEGA10_UMD_PSTATE_GFXCLK_LEVEL].clk; - hwmgr->pstate_mclk = table_info->vdd_dep_on_mclk->entries[VEGA10_UMD_PSTATE_MCLK_LEVEL].clk; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - /* under vega10 pp one vf mode, the gfx clk dpm need be lower - * to level-4 due to the limited power - */ - if (hwmgr->pp_one_vf) - *sclk_mask = 4; - else - *sclk_mask = table_info->vdd_dep_on_sclk->count - 1; - *soc_mask = table_info->vdd_dep_on_socclk->count - 1; - *mclk_mask = table_info->vdd_dep_on_mclk->count - 1; - } - - return 0; -} - -static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - if (!hwmgr->not_vf) - return; - - switch (mode) { - case AMD_FAN_CTRL_NONE: - vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - break; - case AMD_FAN_CTRL_MANUAL: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega10_fan_ctrl_stop_smc_fan_control(hwmgr); - break; - case AMD_FAN_CTRL_AUTO: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega10_fan_ctrl_start_smc_fan_control(hwmgr); - break; - default: - break; - } -} - -static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - switch (type) { - case PP_SCLK: - data->smc_state_table.gfx_boot_level = mask ? (ffs(mask) - 1) : 0; - data->smc_state_table.gfx_max_level = mask ? (fls(mask) - 1) : 0; - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload boot level to lowest!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -EINVAL); - break; - - case PP_MCLK: - data->smc_state_table.mem_boot_level = mask ? (ffs(mask) - 1) : 0; - data->smc_state_table.mem_max_level = mask ? (fls(mask) - 1) : 0; - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload boot level to lowest!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -EINVAL); - - break; - - case PP_SOCCLK: - data->smc_state_table.soc_boot_level = mask ? (ffs(mask) - 1) : 0; - data->smc_state_table.soc_max_level = mask ? (fls(mask) - 1) : 0; - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr), - "Failed to upload boot level to lowest!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -EINVAL); - - break; - - case PP_DCEFCLK: - pr_info("Setting DCEFCLK min/max dpm level is not supported!\n"); - break; - - case PP_PCIE: - default: - break; - } - - return 0; -} - -static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask = 0; - uint32_t mclk_mask = 0; - uint32_t soc_mask = 0; - - if (hwmgr->pstate_sclk == 0) - vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = vega10_force_dpm_highest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = vega10_force_dpm_lowest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = vega10_unforce_dpm_levels(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = vega10_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); - if (ret) - return ret; - vega10_force_clock_level(hwmgr, PP_SCLK, 1<not_vf) - return ret; - - if (!ret) { - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_NONE); - else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) - vega10_set_fan_control_mode(hwmgr, AMD_FAN_CTRL_AUTO); - } - - return ret; -} - -static uint32_t vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) - return AMD_FAN_CTRL_MANUAL; - else - return AMD_FAN_CTRL_AUTO; -} - -static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_clock_and_voltage_limits *max_limits = - &table_info->max_clock_voltage_on_ac; - - info->engine_max_clock = max_limits->sclk; - info->memory_max_clock = max_limits->mclk; - - return 0; -} - -static void vega10_get_sclks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_sclk; - uint32_t i; - - clocks->num_levels = 0; - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].clk) { - clocks->data[clocks->num_levels].clocks_in_khz = - dep_table->entries[i].clk * 10; - clocks->num_levels++; - } - } - -} - -static void vega10_get_memclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_mclk; - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t j = 0; - uint32_t i; - - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].clk) { - - clocks->data[j].clocks_in_khz = - dep_table->entries[i].clk * 10; - data->mclk_latency_table.entries[j].frequency = - dep_table->entries[i].clk; - clocks->data[j].latency_in_us = - data->mclk_latency_table.entries[j].latency = 25; - j++; - } - } - clocks->num_levels = data->mclk_latency_table.count = j; -} - -static void vega10_get_dcefclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_dcefclk; - uint32_t i; - - for (i = 0; i < dep_table->count; i++) { - clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; - clocks->data[i].latency_in_us = 0; - clocks->num_levels++; - } -} - -static void vega10_get_socclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = - table_info->vdd_dep_on_socclk; - uint32_t i; - - for (i = 0; i < dep_table->count; i++) { - clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; - clocks->data[i].latency_in_us = 0; - clocks->num_levels++; - } -} - -static int vega10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - switch (type) { - case amd_pp_sys_clock: - vega10_get_sclks(hwmgr, clocks); - break; - case amd_pp_mem_clock: - vega10_get_memclocks(hwmgr, clocks); - break; - case amd_pp_dcef_clock: - vega10_get_dcefclocks(hwmgr, clocks); - break; - case amd_pp_soc_clock: - vega10_get_socclocks(hwmgr, clocks); - break; - default: - return -1; - } - - return 0; -} - -static int vega10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table; - uint32_t i; - - switch (type) { - case amd_pp_mem_clock: - dep_table = table_info->vdd_dep_on_mclk; - break; - case amd_pp_dcef_clock: - dep_table = table_info->vdd_dep_on_dcefclk; - break; - case amd_pp_disp_clock: - dep_table = table_info->vdd_dep_on_dispclk; - break; - case amd_pp_pixel_clock: - dep_table = table_info->vdd_dep_on_pixclk; - break; - case amd_pp_phy_clock: - dep_table = table_info->vdd_dep_on_phyclk; - break; - default: - return -1; - } - - for (i = 0; i < dep_table->count; i++) { - clocks->data[i].clocks_in_khz = dep_table->entries[i].clk * 10; - clocks->data[i].voltage_in_mv = (uint32_t)(table_info->vddc_lookup_table-> - entries[dep_table->entries[i].vddInd].us_vdd); - clocks->num_levels++; - } - - if (i < dep_table->count) - return -1; - - return 0; -} - -static int vega10_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_range) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_range; - Watermarks_t *table = &(data->smc_state_table.water_marks_table); - - if (!data->registry_data.disable_water_mark) { - smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); - data->water_marks_bitmap = WaterMarksExist; - } - - return 0; -} - -static int vega10_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) -{ - static const char *ppfeature_name[] = { - "DPM_PREFETCHER", - "GFXCLK_DPM", - "UCLK_DPM", - "SOCCLK_DPM", - "UVD_DPM", - "VCE_DPM", - "ULV", - "MP0CLK_DPM", - "LINK_DPM", - "DCEFCLK_DPM", - "AVFS", - "GFXCLK_DS", - "SOCCLK_DS", - "LCLK_DS", - "PPT", - "TDC", - "THERMAL", - "GFX_PER_CU_CG", - "RM", - "DCEFCLK_DS", - "ACDC", - "VR0HOT", - "VR1HOT", - "FW_CTF", - "LED_DISPLAY", - "FAN_CONTROL", - "FAST_PPT", - "DIDT", - "ACG", - "PCC_LIMIT"}; - static const char *output_title[] = { - "FEATURES", - "BITMASK", - "ENABLEMENT"}; - uint64_t features_enabled; - int i; - int ret = 0; - int size = 0; - - ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", - return ret); - - size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); - size += sprintf(buf + size, "%-19s %-22s %s\n", - output_title[0], - output_title[1], - output_title[2]); - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", - ppfeature_name[i], - 1ULL << i, - (features_enabled & (1ULL << i)) ? "Y" : "N"); - } - - return size; -} - -static int vega10_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) -{ - uint64_t features_enabled; - uint64_t features_to_enable; - uint64_t features_to_disable; - int ret = 0; - - if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) - return -EINVAL; - - ret = vega10_get_enabled_smc_features(hwmgr, &features_enabled); - if (ret) - return ret; - - features_to_disable = - features_enabled & ~new_ppfeature_masks; - features_to_enable = - ~features_enabled & new_ppfeature_masks; - - pr_debug("features_to_disable 0x%llx\n", features_to_disable); - pr_debug("features_to_enable 0x%llx\n", features_to_enable); - - if (features_to_disable) { - ret = vega10_enable_smc_features(hwmgr, false, features_to_disable); - if (ret) - return ret; - } - - if (features_to_enable) { - ret = vega10_enable_smc_features(hwmgr, true, features_to_enable); - if (ret) - return ret; - } - - return 0; -} - -static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); - struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); - struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table); - struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table); - struct vega10_pcie_table *pcie_table = &(data->dpm_table.pcie_table); - struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL; - - int i, now, size = 0, count = 0; - - switch (type) { - case PP_SCLK: - if (data->registry_data.sclk_dpm_key_disabled) - break; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now); - - if (hwmgr->pp_one_vf && - (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) - count = 5; - else - count = sclk_table->count; - for (i = 0; i < count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, sclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; - case PP_MCLK: - if (data->registry_data.mclk_dpm_key_disabled) - break; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); - - for (i = 0; i < mclk_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, mclk_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; - case PP_SOCCLK: - if (data->registry_data.socclk_dpm_key_disabled) - break; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); - - for (i = 0; i < soc_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, soc_table->dpm_levels[i].value / 100, - (i == now) ? "*" : ""); - break; - case PP_DCEFCLK: - if (data->registry_data.dcefclk_dpm_key_disabled) - break; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetClockFreqMHz, CLK_DCEFCLK, &now); - - for (i = 0; i < dcef_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, dcef_table->dpm_levels[i].value / 100, - (dcef_table->dpm_levels[i].value / 100 == now) ? - "*" : ""); - break; - case PP_PCIE: - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentLinkIndex, &now); - - for (i = 0; i < pcie_table->count; i++) - size += sprintf(buf + size, "%d: %s %s\n", i, - (pcie_table->pcie_gen[i] == 0) ? "2.5GT/s, x1" : - (pcie_table->pcie_gen[i] == 1) ? "5.0GT/s, x16" : - (pcie_table->pcie_gen[i] == 2) ? "8.0GT/s, x16" : "", - (i == now) ? "*" : ""); - break; - case OD_SCLK: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_SCLK"); - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; - for (i = 0; i < podn_vdd_dep->count; i++) - size += sprintf(buf + size, "%d: %10uMhz %10umV\n", - i, podn_vdd_dep->entries[i].clk / 100, - podn_vdd_dep->entries[i].vddc); - } - break; - case OD_MCLK: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_MCLK"); - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; - for (i = 0; i < podn_vdd_dep->count; i++) - size += sprintf(buf + size, "%d: %10uMhz %10umV\n", - i, podn_vdd_dep->entries[i].clk/100, - podn_vdd_dep->entries[i].vddc); - } - break; - case OD_RANGE: - if (hwmgr->od_enabled) { - size = sprintf(buf, "%s:\n", "OD_RANGE"); - size += sprintf(buf + size, "SCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); - size += sprintf(buf + size, "MCLK: %7uMHz %10uMHz\n", - data->golden_dpm_table.mem_table.dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); - size += sprintf(buf + size, "VDDC: %7umV %11umV\n", - data->odn_dpm_table.min_vddc, - data->odn_dpm_table.max_vddc); - } - break; - default: - break; - } - return size; -} - -static int vega10_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); - int result = 0; - - if ((data->water_marks_bitmap & WaterMarksExist) && - !(data->water_marks_bitmap & WaterMarksLoaded)) { - result = smum_smc_table_manager(hwmgr, (uint8_t *)wm_table, WMTABLE, false); - PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); - data->water_marks_bitmap |= WaterMarksLoaded; - } - - if (data->water_marks_bitmap & WaterMarksLoaded) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, - NULL); - } - - return result; -} - -static int vega10_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DPM_UVD].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), - "Attempt to Enable/Disable DPM UVD Failed!", - return -1); - data->smu_features[GNLD_DPM_UVD].enabled = enable; - } - return 0; -} - -static void vega10_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->vce_power_gated = bgate; - vega10_enable_disable_vce_dpm(hwmgr, !bgate); -} - -static void vega10_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - data->uvd_power_gated = bgate; - vega10_enable_disable_uvd_dpm(hwmgr, !bgate); -} - -static inline bool vega10_are_power_levels_equal( - const struct vega10_performance_level *pl1, - const struct vega10_performance_level *pl2) -{ - return ((pl1->soc_clock == pl2->soc_clock) && - (pl1->gfx_clock == pl2->gfx_clock) && - (pl1->mem_clock == pl2->mem_clock)); -} - -static int vega10_check_states_equal(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pstate1, - const struct pp_hw_power_state *pstate2, bool *equal) -{ - const struct vega10_power_state *psa; - const struct vega10_power_state *psb; - int i; - - if (pstate1 == NULL || pstate2 == NULL || equal == NULL) - return -EINVAL; - - psa = cast_const_phw_vega10_power_state(pstate1); - psb = cast_const_phw_vega10_power_state(pstate2); - /* If the two states don't even have the same number of performance levels they cannot be the same state. */ - if (psa->performance_level_count != psb->performance_level_count) { - *equal = false; - return 0; - } - - for (i = 0; i < psa->performance_level_count; i++) { - if (!vega10_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { - /* If we have found even one performance level pair that is different the states are different. */ - *equal = false; - return 0; - } - } - - /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ - *equal = ((psa->uvd_clks.vclk == psb->uvd_clks.vclk) && (psa->uvd_clks.dclk == psb->uvd_clks.dclk)); - *equal &= ((psa->vce_clks.evclk == psb->vce_clks.evclk) && (psa->vce_clks.ecclk == psb->vce_clks.ecclk)); - *equal &= (psa->sclk_threshold == psb->sclk_threshold); - - return 0; -} - -static bool -vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - bool is_update_required = false; - - if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) - is_update_required = true; - - if (PP_CAP(PHM_PlatformCaps_SclkDeepSleep)) { - if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) - is_update_required = true; - } - - return is_update_required; -} - -static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int tmp_result, result = 0; - - if (!hwmgr->not_vf) - return 0; - - if (PP_CAP(PHM_PlatformCaps_ThermalController)) - vega10_disable_thermal_protection(hwmgr); - - tmp_result = vega10_disable_power_containment(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable power containment!", result = tmp_result); - - tmp_result = vega10_disable_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable didt config!", result = tmp_result); - - tmp_result = vega10_avfs_enable(hwmgr, false); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable AVFS!", result = tmp_result); - - tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to stop DPM!", result = tmp_result); - - tmp_result = vega10_disable_deep_sleep_master_switch(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable deep sleep!", result = tmp_result); - - tmp_result = vega10_disable_ulv(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable ulv!", result = tmp_result); - - tmp_result = vega10_acg_disable(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable acg!", result = tmp_result); - - vega10_enable_disable_PCC_limit_feature(hwmgr, false); - return result; -} - -static int vega10_power_off_asic(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - int result; - - result = vega10_disable_dpm_tasks(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "[disable_dpm_tasks] Failed to disable DPM!", - ); - data->water_marks_bitmap &= ~(WaterMarksLoaded); - - return result; -} - -static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); - struct vega10_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.gfx_table); - int value = sclk_table->dpm_levels[sclk_table->count - 1].value; - int golden_value = golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.gfx_table); - struct pp_power_state *ps; - struct vega10_power_state *vega10_ps; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - - vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].gfx_clock = - golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value * - value / 100 + - golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value; - - if (vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].gfx_clock > - hwmgr->platform_descriptor.overdriveLimit.engineClock) { - vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].gfx_clock = - hwmgr->platform_descriptor.overdriveLimit.engineClock; - pr_warn("max sclk supported by vbios is %d\n", - hwmgr->platform_descriptor.overdriveLimit.engineClock); - } - return 0; -} - -static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); - struct vega10_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mem_table); - int value = mclk_table->dpm_levels[mclk_table->count - 1].value; - int golden_value = golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mem_table); - struct pp_power_state *ps; - struct vega10_power_state *vega10_ps; - - ps = hwmgr->request_ps; - - if (ps == NULL) - return -EINVAL; - - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - - vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].mem_clock = - golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value * - value / 100 + - golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value; - - if (vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].mem_clock > - hwmgr->platform_descriptor.overdriveLimit.memoryClock) { - vega10_ps->performance_levels - [vega10_ps->performance_level_count - 1].mem_clock = - hwmgr->platform_descriptor.overdriveLimit.memoryClock; - pr_warn("max mclk supported by vbios is %d\n", - hwmgr->platform_descriptor.overdriveLimit.memoryClock); - } - - return 0; -} - -static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrHigh, - virtual_addr_hi, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrLow, - virtual_addr_low, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrHigh, - mc_addr_hi, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrLow, - mc_addr_low, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramSize, - size, - NULL); - return 0; -} - -static int vega10_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *thermal_data) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - - memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); - - thermal_data->max = pp_table->TedgeLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_crit_max = pp_table->ThbmLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t i, size = 0; - static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,}, - {70, 60, 1, 3,}, - {90, 60, 0, 0,}, - {70, 60, 0, 0,}, - {70, 90, 0, 0,}, - {30, 60, 0, 6,}, - }; - static const char *profile_name[7] = {"BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - static const char *title[6] = {"NUM", - "MODE_NAME", - "BUSY_SET_POINT", - "FPS", - "USE_RLC_BUSY", - "MIN_ACTIVE_LEVEL"}; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%s %16s %s %s %s %s\n",title[0], - title[1], title[2], title[3], title[4], title[5]); - - for (i = 0; i < PP_SMC_POWER_PROFILE_CUSTOM; i++) - size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", - i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", - profile_mode_setting[i][0], profile_mode_setting[i][1], - profile_mode_setting[i][2], profile_mode_setting[i][3]); - size += sprintf(buf + size, "%3d %14s%s: %14d %3d %10d %14d\n", i, - profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ", - data->custom_profile_mode[0], data->custom_profile_mode[1], - data->custom_profile_mode[2], data->custom_profile_mode[3]); - return size; -} - -static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint8_t busy_set_point; - uint8_t FPS; - uint8_t use_rlc_busy; - uint8_t min_active_level; - uint32_t power_profile_mode = input[size]; - - if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { - if (size != 0 && size != 4) - return -EINVAL; - - /* If size = 0 and the CUSTOM profile has been set already - * then just apply the profile. The copy stored in the hwmgr - * is zeroed out on init - */ - if (size == 0) { - if (data->custom_profile_mode[0] != 0) - goto out; - else - return -EINVAL; - } - - data->custom_profile_mode[0] = busy_set_point = input[0]; - data->custom_profile_mode[1] = FPS = input[1]; - data->custom_profile_mode[2] = use_rlc_busy = input[2]; - data->custom_profile_mode[3] = min_active_level = input[3]; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetCustomGfxDpmParameters, - busy_set_point | FPS<<8 | - use_rlc_busy << 16 | min_active_level<<24, - NULL); - } - -out: - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, - 1 << power_profile_mode, - NULL); - hwmgr->power_profile_mode = power_profile_mode; - - return 0; -} - - -static bool vega10_check_clk_voltage_valid(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - uint32_t clk, - uint32_t voltage) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_odn_dpm_table *odn_table = &(data->odn_dpm_table); - struct vega10_single_dpm_table *golden_table; - - if (voltage < odn_table->min_vddc || voltage > odn_table->max_vddc) { - pr_info("OD voltage is out of range [%d - %d] mV\n", odn_table->min_vddc, odn_table->max_vddc); - return false; - } - - if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { - golden_table = &(data->golden_dpm_table.gfx_table); - if (golden_table->dpm_levels[0].value > clk || - hwmgr->platform_descriptor.overdriveLimit.engineClock < clk) { - pr_info("OD engine clock is out of range [%d - %d] MHz\n", - golden_table->dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.engineClock/100); - return false; - } - } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { - golden_table = &(data->golden_dpm_table.mem_table); - if (golden_table->dpm_levels[0].value > clk || - hwmgr->platform_descriptor.overdriveLimit.memoryClock < clk) { - pr_info("OD memory clock is out of range [%d - %d] MHz\n", - golden_table->dpm_levels[0].value/100, - hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); - return false; - } - } else { - return false; - } - - return true; -} - -static void vega10_odn_update_power_state(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct pp_power_state *ps = hwmgr->request_ps; - struct vega10_power_state *vega10_ps; - struct vega10_single_dpm_table *gfx_dpm_table = - &data->dpm_table.gfx_table; - struct vega10_single_dpm_table *soc_dpm_table = - &data->dpm_table.soc_table; - struct vega10_single_dpm_table *mem_dpm_table = - &data->dpm_table.mem_table; - int max_level; - - if (!ps) - return; - - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - max_level = vega10_ps->performance_level_count - 1; - - if (vega10_ps->performance_levels[max_level].gfx_clock != - gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].gfx_clock = - gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; - - if (vega10_ps->performance_levels[max_level].soc_clock != - soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].soc_clock = - soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; - - if (vega10_ps->performance_levels[max_level].mem_clock != - mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].mem_clock = - mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; - - if (!hwmgr->ps) - return; - - ps = (struct pp_power_state *)((unsigned long)(hwmgr->ps) + hwmgr->ps_size * (hwmgr->num_ps - 1)); - vega10_ps = cast_phw_vega10_power_state(&ps->hardware); - max_level = vega10_ps->performance_level_count - 1; - - if (vega10_ps->performance_levels[max_level].gfx_clock != - gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].gfx_clock = - gfx_dpm_table->dpm_levels[gfx_dpm_table->count - 1].value; - - if (vega10_ps->performance_levels[max_level].soc_clock != - soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].soc_clock = - soc_dpm_table->dpm_levels[soc_dpm_table->count - 1].value; - - if (vega10_ps->performance_levels[max_level].mem_clock != - mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value) - vega10_ps->performance_levels[max_level].mem_clock = - mem_dpm_table->dpm_levels[mem_dpm_table->count - 1].value; -} - -static void vega10_odn_update_soc_table(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table = table_info->vdd_dep_on_socclk; - struct vega10_single_dpm_table *dpm_table = &data->golden_dpm_table.mem_table; - - struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_on_socclk = - &data->odn_dpm_table.vdd_dep_on_socclk; - struct vega10_odn_vddc_lookup_table *od_vddc_lookup_table = &data->odn_dpm_table.vddc_lookup_table; - - struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep; - uint8_t i, j; - - if (type == PP_OD_EDIT_SCLK_VDDC_TABLE) { - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; - for (i = 0; i < podn_vdd_dep->count; i++) - od_vddc_lookup_table->entries[i].us_vdd = podn_vdd_dep->entries[i].vddc; - } else if (type == PP_OD_EDIT_MCLK_VDDC_TABLE) { - podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; - for (i = 0; i < dpm_table->count; i++) { - for (j = 0; j < od_vddc_lookup_table->count; j++) { - if (od_vddc_lookup_table->entries[j].us_vdd > - podn_vdd_dep->entries[i].vddc) - break; - } - if (j == od_vddc_lookup_table->count) { - j = od_vddc_lookup_table->count - 1; - od_vddc_lookup_table->entries[j].us_vdd = - podn_vdd_dep->entries[i].vddc; - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_VDDC; - } - podn_vdd_dep->entries[i].vddInd = j; - } - dpm_table = &data->dpm_table.soc_table; - for (i = 0; i < dep_table->count; i++) { - if (dep_table->entries[i].vddInd == podn_vdd_dep->entries[podn_vdd_dep->count-1].vddInd && - dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count-1].clk) { - data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; - for (; (i < dep_table->count) && - (dep_table->entries[i].clk < podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk); i++) { - podn_vdd_dep_on_socclk->entries[i].clk = podn_vdd_dep->entries[podn_vdd_dep->count-1].clk; - dpm_table->dpm_levels[i].value = podn_vdd_dep_on_socclk->entries[i].clk; - } - break; - } else { - dpm_table->dpm_levels[i].value = dep_table->entries[i].clk; - podn_vdd_dep_on_socclk->entries[i].vddc = dep_table->entries[i].vddc; - podn_vdd_dep_on_socclk->entries[i].vddInd = dep_table->entries[i].vddInd; - podn_vdd_dep_on_socclk->entries[i].clk = dep_table->entries[i].clk; - } - } - if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk < - podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk) { - data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; - podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].clk = - podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; - dpm_table->dpm_levels[podn_vdd_dep_on_socclk->count - 1].value = - podn_vdd_dep->entries[podn_vdd_dep->count - 1].clk; - } - if (podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd < - podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd) { - data->need_update_dpm_table |= DPMTABLE_UPDATE_SOCCLK; - podn_vdd_dep_on_socclk->entries[podn_vdd_dep_on_socclk->count - 1].vddInd = - podn_vdd_dep->entries[podn_vdd_dep->count - 1].vddInd; - } - } - vega10_odn_update_power_state(hwmgr); -} - -static int vega10_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep_table; - struct vega10_single_dpm_table *dpm_table; - - uint32_t input_clk; - uint32_t input_vol; - uint32_t input_level; - uint32_t i; - - PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", - return -EINVAL); - - if (!hwmgr->od_enabled) { - pr_info("OverDrive feature not enabled\n"); - return -EINVAL; - } - - if (PP_OD_EDIT_SCLK_VDDC_TABLE == type) { - dpm_table = &data->dpm_table.gfx_table; - podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_sclk; - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; - } else if (PP_OD_EDIT_MCLK_VDDC_TABLE == type) { - dpm_table = &data->dpm_table.mem_table; - podn_vdd_dep_table = &data->odn_dpm_table.vdd_dep_on_mclk; - data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; - } else if (PP_OD_RESTORE_DEFAULT_TABLE == type) { - memcpy(&(data->dpm_table), &(data->golden_dpm_table), sizeof(struct vega10_dpm_table)); - vega10_odn_initial_default_setting(hwmgr); - vega10_odn_update_power_state(hwmgr); - /* force to update all clock tables */ - data->need_update_dpm_table = DPMTABLE_UPDATE_SCLK | - DPMTABLE_UPDATE_MCLK | - DPMTABLE_UPDATE_SOCCLK; - return 0; - } else if (PP_OD_COMMIT_DPM_TABLE == type) { - vega10_check_dpm_table_updated(hwmgr); - return 0; - } else { - return -EINVAL; - } - - for (i = 0; i < size; i += 3) { - if (i + 3 > size || input[i] >= podn_vdd_dep_table->count) { - pr_info("invalid clock voltage input\n"); - return 0; - } - input_level = input[i]; - input_clk = input[i+1] * 100; - input_vol = input[i+2]; - - if (vega10_check_clk_voltage_valid(hwmgr, type, input_clk, input_vol)) { - dpm_table->dpm_levels[input_level].value = input_clk; - podn_vdd_dep_table->entries[input_level].clk = input_clk; - podn_vdd_dep_table->entries[input_level].vddc = input_vol; - } else { - return -EINVAL; - } - } - vega10_odn_update_soc_table(hwmgr, type); - return 0; -} - -static int vega10_set_mp1_state(struct pp_hwmgr *hwmgr, - enum pp_mp1_state mp1_state) -{ - uint16_t msg; - int ret; - - switch (mp1_state) { - case PP_MP1_STATE_UNLOAD: - msg = PPSMC_MSG_PrepareMp1ForUnload; - break; - case PP_MP1_STATE_SHUTDOWN: - case PP_MP1_STATE_RESET: - case PP_MP1_STATE_NONE: - default: - return 0; - } - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, - "[PrepareMp1] Failed!", - return ret); - - return 0; -} - -static int vega10_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - const struct vega10_power_state *ps; - uint32_t i; - - if (level == NULL || hwmgr == NULL || state == NULL) - return -EINVAL; - - ps = cast_const_phw_vega10_power_state(state); - - i = index > ps->performance_level_count - 1 ? - ps->performance_level_count - 1 : index; - - level->coreClock = ps->performance_levels[i].gfx_clock; - level->memory_clock = ps->performance_levels[i].mem_clock; - - return 0; -} - -static int vega10_disable_power_features_for_compute_performance(struct pp_hwmgr *hwmgr, bool disable) -{ - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t feature_mask = 0; - - if (disable) { - feature_mask |= data->smu_features[GNLD_ULV].enabled ? - data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; - feature_mask |= data->smu_features[GNLD_DS_GFXCLK].enabled ? - data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; - feature_mask |= data->smu_features[GNLD_DS_SOCCLK].enabled ? - data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; - feature_mask |= data->smu_features[GNLD_DS_LCLK].enabled ? - data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; - feature_mask |= data->smu_features[GNLD_DS_DCEFCLK].enabled ? - data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; - } else { - feature_mask |= (!data->smu_features[GNLD_ULV].enabled) ? - data->smu_features[GNLD_ULV].smu_feature_bitmap : 0; - feature_mask |= (!data->smu_features[GNLD_DS_GFXCLK].enabled) ? - data->smu_features[GNLD_DS_GFXCLK].smu_feature_bitmap : 0; - feature_mask |= (!data->smu_features[GNLD_DS_SOCCLK].enabled) ? - data->smu_features[GNLD_DS_SOCCLK].smu_feature_bitmap : 0; - feature_mask |= (!data->smu_features[GNLD_DS_LCLK].enabled) ? - data->smu_features[GNLD_DS_LCLK].smu_feature_bitmap : 0; - feature_mask |= (!data->smu_features[GNLD_DS_DCEFCLK].enabled) ? - data->smu_features[GNLD_DS_DCEFCLK].smu_feature_bitmap : 0; - } - - if (feature_mask) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - !disable, feature_mask), - "enable/disable power features for compute performance Failed!", - return -EINVAL); - - if (disable) { - data->smu_features[GNLD_ULV].enabled = false; - data->smu_features[GNLD_DS_GFXCLK].enabled = false; - data->smu_features[GNLD_DS_SOCCLK].enabled = false; - data->smu_features[GNLD_DS_LCLK].enabled = false; - data->smu_features[GNLD_DS_DCEFCLK].enabled = false; - } else { - data->smu_features[GNLD_ULV].enabled = true; - data->smu_features[GNLD_DS_GFXCLK].enabled = true; - data->smu_features[GNLD_DS_SOCCLK].enabled = true; - data->smu_features[GNLD_DS_LCLK].enabled = true; - data->smu_features[GNLD_DS_DCEFCLK].enabled = true; - } - - return 0; - -} - -static const struct pp_hwmgr_func vega10_hwmgr_funcs = { - .backend_init = vega10_hwmgr_backend_init, - .backend_fini = vega10_hwmgr_backend_fini, - .asic_setup = vega10_setup_asic_task, - .dynamic_state_management_enable = vega10_enable_dpm_tasks, - .dynamic_state_management_disable = vega10_disable_dpm_tasks, - .get_num_of_pp_table_entries = - vega10_get_number_of_powerplay_table_entries, - .get_power_state_size = vega10_get_power_state_size, - .get_pp_table_entry = vega10_get_pp_table_entry, - .patch_boot_state = vega10_patch_boot_state, - .apply_state_adjust_rules = vega10_apply_state_adjust_rules, - .power_state_set = vega10_set_power_state_tasks, - .get_sclk = vega10_dpm_get_sclk, - .get_mclk = vega10_dpm_get_mclk, - .notify_smc_display_config_after_ps_adjustment = - vega10_notify_smc_display_config_after_ps_adjustment, - .force_dpm_level = vega10_dpm_force_dpm_level, - .stop_thermal_controller = vega10_thermal_stop_thermal_controller, - .get_fan_speed_info = vega10_fan_ctrl_get_fan_speed_info, - .get_fan_speed_percent = vega10_fan_ctrl_get_fan_speed_percent, - .set_fan_speed_percent = vega10_fan_ctrl_set_fan_speed_percent, - .reset_fan_speed_to_default = - vega10_fan_ctrl_reset_fan_speed_to_default, - .get_fan_speed_rpm = vega10_fan_ctrl_get_fan_speed_rpm, - .set_fan_speed_rpm = vega10_fan_ctrl_set_fan_speed_rpm, - .uninitialize_thermal_controller = - vega10_thermal_ctrl_uninitialize_thermal_controller, - .set_fan_control_mode = vega10_set_fan_control_mode, - .get_fan_control_mode = vega10_get_fan_control_mode, - .read_sensor = vega10_read_sensor, - .get_dal_power_level = vega10_get_dal_power_level, - .get_clock_by_type_with_latency = vega10_get_clock_by_type_with_latency, - .get_clock_by_type_with_voltage = vega10_get_clock_by_type_with_voltage, - .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges, - .display_clock_voltage_request = vega10_display_clock_voltage_request, - .force_clock_level = vega10_force_clock_level, - .print_clock_levels = vega10_print_clock_levels, - .display_config_changed = vega10_display_configuration_changed_task, - .powergate_uvd = vega10_power_gate_uvd, - .powergate_vce = vega10_power_gate_vce, - .check_states_equal = vega10_check_states_equal, - .check_smc_update_required_for_display_configuration = - vega10_check_smc_update_required_for_display_configuration, - .power_off_asic = vega10_power_off_asic, - .disable_smc_firmware_ctf = vega10_thermal_disable_alert, - .get_sclk_od = vega10_get_sclk_od, - .set_sclk_od = vega10_set_sclk_od, - .get_mclk_od = vega10_get_mclk_od, - .set_mclk_od = vega10_set_mclk_od, - .avfs_control = vega10_avfs_enable, - .notify_cac_buffer_info = vega10_notify_cac_buffer_info, - .get_thermal_temperature_range = vega10_get_thermal_temperature_range, - .register_irq_handlers = smu9_register_irq_handlers, - .start_thermal_controller = vega10_start_thermal_controller, - .get_power_profile_mode = vega10_get_power_profile_mode, - .set_power_profile_mode = vega10_set_power_profile_mode, - .set_power_limit = vega10_set_power_limit, - .odn_edit_dpm_table = vega10_odn_edit_dpm_table, - .get_performance_level = vega10_get_performance_level, - .get_asic_baco_capability = smu9_baco_get_capability, - .get_asic_baco_state = smu9_baco_get_state, - .set_asic_baco_state = vega10_baco_set_state, - .enable_mgpu_fan_boost = vega10_enable_mgpu_fan_boost, - .get_ppfeature_status = vega10_get_ppfeature_status, - .set_ppfeature_status = vega10_set_ppfeature_status, - .set_mp1_state = vega10_set_mp1_state, - .disable_power_features_for_compute_performance = - vega10_disable_power_features_for_compute_performance, -}; - -int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - hwmgr->hwmgr_func = &vega10_hwmgr_funcs; - hwmgr->pptable_func = &vega10_pptable_funcs; - if (amdgpu_passthrough(adev)) - return vega10_baco_set_cap(hwmgr); - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h deleted file mode 100644 index f752b4ad0c8a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright 2016 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 _VEGA10_HWMGR_H_ -#define _VEGA10_HWMGR_H_ - -#include "hwmgr.h" -#include "smu9_driver_if.h" -#include "ppatomctrl.h" -#include "ppatomfwctrl.h" -#include "vega10_ppsmc.h" -#include "vega10_powertune.h" - -#define VEGA10_MAX_HARDWARE_POWERLEVELS 2 - -#define WaterMarksExist 1 -#define WaterMarksLoaded 2 - -enum { - GNLD_DPM_PREFETCHER = 0, - GNLD_DPM_GFXCLK, - GNLD_DPM_UCLK, - GNLD_DPM_SOCCLK, - GNLD_DPM_UVD, - GNLD_DPM_VCE, - GNLD_ULV, - GNLD_DPM_MP0CLK, - GNLD_DPM_LINK, - GNLD_DPM_DCEFCLK, - GNLD_AVFS, - GNLD_DS_GFXCLK, - GNLD_DS_SOCCLK, - GNLD_DS_LCLK, - GNLD_PPT, - GNLD_TDC, - GNLD_THERMAL, - GNLD_GFX_PER_CU_CG, - GNLD_RM, - GNLD_DS_DCEFCLK, - GNLD_ACDC, - GNLD_VR0HOT, - GNLD_VR1HOT, - GNLD_FW_CTF, - GNLD_LED_DISPLAY, - GNLD_FAN_CONTROL, - GNLD_FEATURE_FAST_PPT_BIT, - GNLD_DIDT, - GNLD_ACG, - GNLD_PCC_LIMIT, - GNLD_FEATURES_MAX -}; - -#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) - -#define SMC_DPM_FEATURES 0x30F - -struct smu_features { - bool supported; - bool enabled; - uint32_t smu_feature_id; - uint32_t smu_feature_bitmap; -}; - -struct vega10_performance_level { - uint32_t soc_clock; - uint32_t gfx_clock; - uint32_t mem_clock; -}; - -struct vega10_bacos { - uint32_t baco_flags; - /* struct vega10_performance_level performance_level; */ -}; - -struct vega10_uvd_clocks { - uint32_t vclk; - uint32_t dclk; -}; - -struct vega10_vce_clocks { - uint32_t evclk; - uint32_t ecclk; -}; - -struct vega10_power_state { - uint32_t magic; - struct vega10_uvd_clocks uvd_clks; - struct vega10_vce_clocks vce_clks; - uint16_t performance_level_count; - bool dc_compatible; - uint32_t sclk_threshold; - struct vega10_performance_level performance_levels[VEGA10_MAX_HARDWARE_POWERLEVELS]; -}; - -struct vega10_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -#define VEGA10_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define MAX_REGULAR_DPM_NUMBER 8 -#define MAX_PCIE_CONF 2 -#define VEGA10_MINIMUM_ENGINE_CLOCK 2500 - -struct vega10_dpm_state { - uint32_t soft_min_level; - uint32_t soft_max_level; - uint32_t hard_min_level; - uint32_t hard_max_level; -}; - -struct vega10_single_dpm_table { - uint32_t count; - struct vega10_dpm_state dpm_state; - struct vega10_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega10_pcie_table { - uint16_t count; - uint8_t pcie_gen[MAX_PCIE_CONF]; - uint8_t pcie_lane[MAX_PCIE_CONF]; - uint32_t lclk[MAX_PCIE_CONF]; -}; - -struct vega10_dpm_table { - struct vega10_single_dpm_table soc_table; - struct vega10_single_dpm_table gfx_table; - struct vega10_single_dpm_table mem_table; - struct vega10_single_dpm_table eclk_table; - struct vega10_single_dpm_table vclk_table; - struct vega10_single_dpm_table dclk_table; - struct vega10_single_dpm_table dcef_table; - struct vega10_single_dpm_table pixel_table; - struct vega10_single_dpm_table display_table; - struct vega10_single_dpm_table phy_table; - struct vega10_pcie_table pcie_table; -}; - -#define VEGA10_MAX_LEAKAGE_COUNT 8 -struct vega10_leakage_voltage { - uint16_t count; - uint16_t leakage_id[VEGA10_MAX_LEAKAGE_COUNT]; - uint16_t actual_voltage[VEGA10_MAX_LEAKAGE_COUNT]; -}; - -struct vega10_display_timing { - uint32_t min_clock_in_sr; - uint32_t num_existing_displays; -}; - -struct vega10_dpmlevel_enable_mask { - uint32_t uvd_dpm_enable_mask; - uint32_t vce_dpm_enable_mask; - uint32_t acp_dpm_enable_mask; - uint32_t samu_dpm_enable_mask; - uint32_t sclk_dpm_enable_mask; - uint32_t mclk_dpm_enable_mask; -}; - -struct vega10_vbios_boot_state { - bool bsoc_vddc_lock; - uint16_t vddc; - uint16_t vddci; - uint16_t mvddc; - uint16_t vdd_gfx; - uint32_t gfx_clock; - uint32_t mem_clock; - uint32_t soc_clock; - uint32_t dcef_clock; -}; - -struct vega10_smc_state_table { - uint32_t soc_boot_level; - uint32_t gfx_boot_level; - uint32_t dcef_boot_level; - uint32_t mem_boot_level; - uint32_t uvd_boot_level; - uint32_t vce_boot_level; - uint32_t gfx_max_level; - uint32_t mem_max_level; - uint32_t soc_max_level; - uint8_t vr_hot_gpio; - uint8_t ac_dc_gpio; - uint8_t therm_out_gpio; - uint8_t therm_out_polarity; - uint8_t therm_out_mode; - PPTable_t pp_table; - Watermarks_t water_marks_table; - AvfsTable_t avfs_table; - AvfsFuseOverride_t avfs_fuse_override_table; -}; - -struct vega10_mclk_latency_entries { - uint32_t frequency; - uint32_t latency; -}; - -struct vega10_mclk_latency_table { - uint32_t count; - struct vega10_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega10_registry_data { - uint8_t ac_dc_switch_gpio_support; - uint8_t avfs_support; - uint8_t cac_support; - uint8_t clock_stretcher_support; - uint8_t db_ramping_support; - uint8_t didt_mode; - uint8_t didt_support; - uint8_t edc_didt_support; - uint8_t dynamic_state_patching_support; - uint8_t enable_pkg_pwr_tracking_feature; - uint8_t enable_tdc_limit_feature; - uint32_t fast_watermark_threshold; - uint8_t force_dpm_high; - uint8_t fuzzy_fan_control_support; - uint8_t long_idle_baco_support; - uint8_t mclk_dpm_key_disabled; - uint8_t od_state_in_dc_support; - uint8_t pcieLaneOverride; - uint8_t pcieSpeedOverride; - uint32_t pcieClockOverride; - uint8_t pcie_dpm_key_disabled; - uint8_t dcefclk_dpm_key_disabled; - uint8_t power_containment_support; - uint8_t ppt_support; - uint8_t prefetcher_dpm_key_disabled; - uint8_t quick_transition_support; - uint8_t regulator_hot_gpio_support; - uint8_t sclk_deep_sleep_support; - uint8_t sclk_dpm_key_disabled; - uint8_t sclk_from_vbios; - uint8_t sclk_throttle_low_notification; - uint8_t show_baco_dbg_info; - uint8_t skip_baco_hardware; - uint8_t socclk_dpm_key_disabled; - uint8_t spll_shutdown_support; - uint8_t sq_ramping_support; - uint32_t stable_pstate_sclk_dpm_percentage; - uint8_t tcp_ramping_support; - uint8_t tdc_support; - uint8_t td_ramping_support; - uint8_t dbr_ramping_support; - uint8_t gc_didt_support; - uint8_t psm_didt_support; - uint8_t thermal_out_gpio_support; - uint8_t thermal_support; - uint8_t fw_ctf_enabled; - uint8_t fan_control_support; - uint8_t ulps_support; - uint8_t ulv_support; - uint32_t vddc_vddci_delta; - uint8_t odn_feature_enable; - uint8_t disable_water_mark; - uint8_t zrpm_stop_temp; - uint8_t zrpm_start_temp; - uint8_t led_dpm_enabled; - uint8_t vr0hot_enabled; - uint8_t vr1hot_enabled; -}; - -struct vega10_odn_clock_voltage_dependency_table { - uint32_t count; - struct phm_ppt_v1_clock_voltage_dependency_record entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega10_odn_vddc_lookup_table { - uint32_t count; - struct phm_ppt_v1_voltage_lookup_record entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega10_odn_dpm_table { - struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_sclk; - struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_mclk; - struct vega10_odn_clock_voltage_dependency_table vdd_dep_on_socclk; - struct vega10_odn_vddc_lookup_table vddc_lookup_table; - uint32_t max_vddc; - uint32_t min_vddc; -}; - -struct vega10_odn_fan_table { - uint32_t target_fan_speed; - uint32_t target_temperature; - uint32_t min_performance_clock; - uint32_t min_fan_limit; -}; - -struct vega10_hwmgr { - struct vega10_dpm_table dpm_table; - struct vega10_dpm_table golden_dpm_table; - struct vega10_registry_data registry_data; - struct vega10_vbios_boot_state vbios_boot_state; - struct vega10_mclk_latency_table mclk_latency_table; - - struct vega10_leakage_voltage vddc_leakage; - - uint32_t vddc_control; - struct pp_atomfwctrl_voltage_table vddc_voltage_table; - uint32_t mvdd_control; - struct pp_atomfwctrl_voltage_table mvdd_voltage_table; - uint32_t vddci_control; - struct pp_atomfwctrl_voltage_table vddci_voltage_table; - - uint32_t active_auto_throttle_sources; - uint32_t water_marks_bitmap; - struct vega10_bacos bacos; - - struct vega10_odn_dpm_table odn_dpm_table; - struct vega10_odn_fan_table odn_fan_table; - - /* ---- General data ---- */ - uint8_t need_update_dpm_table; - - bool cac_enabled; - bool battery_state; - bool is_tlu_enabled; - - uint32_t low_sclk_interrupt_threshold; - - uint32_t total_active_cus; - - struct vega10_display_timing display_timing; - - /* ---- Vega10 Dyn Register Settings ---- */ - - uint32_t debug_settings; - uint32_t lowest_uclk_reserved_for_ulv; - uint32_t gfxclk_average_alpha; - uint32_t socclk_average_alpha; - uint32_t uclk_average_alpha; - uint32_t gfx_activity_average_alpha; - uint32_t display_voltage_mode; - uint32_t dcef_clk_quad_eqn_a; - uint32_t dcef_clk_quad_eqn_b; - uint32_t dcef_clk_quad_eqn_c; - uint32_t disp_clk_quad_eqn_a; - uint32_t disp_clk_quad_eqn_b; - uint32_t disp_clk_quad_eqn_c; - uint32_t pixel_clk_quad_eqn_a; - uint32_t pixel_clk_quad_eqn_b; - uint32_t pixel_clk_quad_eqn_c; - uint32_t phy_clk_quad_eqn_a; - uint32_t phy_clk_quad_eqn_b; - uint32_t phy_clk_quad_eqn_c; - - /* ---- Thermal Temperature Setting ---- */ - struct vega10_dpmlevel_enable_mask dpm_level_enable_mask; - - /* ---- Power Gating States ---- */ - bool uvd_power_gated; - bool vce_power_gated; - bool need_long_memory_training; - - /* Internal settings to apply the application power optimization parameters */ - uint32_t disable_dpm_mask; - - /* ---- SMU9 ---- */ - struct smu_features smu_features[GNLD_FEATURES_MAX]; - struct vega10_smc_state_table smc_state_table; - - uint32_t config_telemetry; - uint32_t acg_loop_state; - uint32_t mem_channels; - uint8_t custom_profile_mode[4]; -}; - -#define VEGA10_DPM2_NEAR_TDP_DEC 10 -#define VEGA10_DPM2_ABOVE_SAFE_INC 5 -#define VEGA10_DPM2_BELOW_SAFE_INC 20 - -#define VEGA10_DPM2_LTA_WINDOW_SIZE 7 - -#define VEGA10_DPM2_LTS_TRUNCATE 0 - -#define VEGA10_DPM2_TDP_SAFE_LIMIT_PERCENT 80 - -#define VEGA10_DPM2_MAXPS_PERCENT_M 90 -#define VEGA10_DPM2_MAXPS_PERCENT_H 90 - -#define VEGA10_DPM2_PWREFFICIENCYRATIO_MARGIN 50 - -#define VEGA10_DPM2_SQ_RAMP_MAX_POWER 0x3FFF -#define VEGA10_DPM2_SQ_RAMP_MIN_POWER 0x12 -#define VEGA10_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 -#define VEGA10_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E -#define VEGA10_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF - -#define VEGA10_VOLTAGE_CONTROL_NONE 0x0 -#define VEGA10_VOLTAGE_CONTROL_BY_GPIO 0x1 -#define VEGA10_VOLTAGE_CONTROL_BY_SVID2 0x2 -#define VEGA10_VOLTAGE_CONTROL_MERGED 0x3 -/* To convert to Q8.8 format for firmware */ -#define VEGA10_Q88_FORMAT_CONVERSION_UNIT 256 - -#define VEGA10_UNUSED_GPIO_PIN 0x7F - -#define VEGA10_THERM_OUT_MODE_DISABLE 0x0 -#define VEGA10_THERM_OUT_MODE_THERM_ONLY 0x1 -#define VEGA10_THERM_OUT_MODE_THERM_VRHOT 0x2 - -#define PPVEGA10_VEGA10DISPLAYVOLTAGEMODE_DFLT 0xffffffff -#define PPREGKEY_VEGA10QUADRATICEQUATION_DFLT 0xffffffff - -#define PPVEGA10_VEGA10GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA10_VEGA10SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA10_VEGA10UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA10_VEGA10GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ - -#define VEGA10_UMD_PSTATE_GFXCLK_LEVEL 0x3 -#define VEGA10_UMD_PSTATE_SOCCLK_LEVEL 0x3 -#define VEGA10_UMD_PSTATE_MCLK_LEVEL 0x2 - -extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); -extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); -extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr); -extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); -extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display); -int vega10_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input); -int vega10_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); -int vega10_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate); -int vega10_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate); -int vega10_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); - -#endif /* _VEGA10_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h deleted file mode 100644 index faf7ac044348..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_inc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2016 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 VEGA10_INC_H -#define VEGA10_INC_H - -#include "asic_reg/thm/thm_9_0_default.h" -#include "asic_reg/thm/thm_9_0_offset.h" -#include "asic_reg/thm/thm_9_0_sh_mask.h" - -#include "asic_reg/mp/mp_9_0_offset.h" -#include "asic_reg/mp/mp_9_0_sh_mask.h" - -#include "asic_reg/gc/gc_9_0_default.h" -#include "asic_reg/gc/gc_9_0_offset.h" -#include "asic_reg/gc/gc_9_0_sh_mask.h" - -#include "asic_reg/nbio/nbio_6_1_default.h" -#include "asic_reg/nbio/nbio_6_1_offset.h" -#include "asic_reg/nbio/nbio_6_1_sh_mask.h" - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c deleted file mode 100644 index 9757d47dd6b8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ /dev/null @@ -1,1392 +0,0 @@ -/* - * Copyright 2016 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 "hwmgr.h" -#include "vega10_hwmgr.h" -#include "vega10_smumgr.h" -#include "vega10_powertune.h" -#include "vega10_ppsmc.h" -#include "vega10_inc.h" -#include "pp_debug.h" -#include "soc15_common.h" - -static const struct vega10_didt_config_reg SEDiDtTuningCtrlConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3853 }, - { ixDIDT_SQ_TUNING_CTRL, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_SQ_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3153 }, - - /* DIDT_TD */ - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x0dde }, - { ixDIDT_TD_TUNING_CTRL, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TD_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x0dde }, - - /* DIDT_TCP */ - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, - { ixDIDT_TCP_TUNING_CTRL, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_TCP_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, - - /* DIDT_DB */ - { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_HI__SHIFT, 0x3dde }, - { ixDIDT_DB_TUNING_CTRL, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO_MASK, DIDT_DB_TUNING_CTRL__MAX_POWER_DELTA_LO__SHIFT, 0x3dde }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEDiDtCtrl3Config_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /*DIDT_SQ_CTRL3 */ - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_SQ_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__THROTTLE_POLICY_MASK, DIDT_SQ_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_SQ_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_SQ_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_SQ_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_SEL_MASK, DIDT_SQ_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_SQ_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL3, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_SQ_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, - - /*DIDT_TCP_CTRL3 */ - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TCP_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__THROTTLE_POLICY_MASK, DIDT_TCP_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TCP_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TCP_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TCP_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TCP_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TCP_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TCP_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL3, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TCP_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, - - /*DIDT_TD_CTRL3 */ - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_TD_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__THROTTLE_POLICY_MASK, DIDT_TD_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_TD_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_TD_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_TD_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_SEL_MASK, DIDT_TD_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_TD_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL3, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_TD_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, - - /*DIDT_DB_CTRL3 */ - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_ENABLE_MASK, DIDT_DB_CTRL3__GC_DIDT_ENABLE__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL3__GC_DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__THROTTLE_POLICY_MASK, DIDT_DB_CTRL3__THROTTLE_POLICY__SHIFT, 0x0003 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT_MASK, DIDT_DB_CTRL3__DIDT_POWER_LEVEL_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS_MASK, DIDT_DB_CTRL3__DIDT_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0003 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__GC_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN_MASK, DIDT_DB_CTRL3__SE_DIDT_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__QUALIFY_STALL_EN_MASK, DIDT_DB_CTRL3__QUALIFY_STALL_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_SEL_MASK, DIDT_DB_CTRL3__DIDT_STALL_SEL__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_FORCE_STALL_MASK, DIDT_DB_CTRL3__DIDT_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL3, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN_MASK, DIDT_DB_CTRL3__DIDT_STALL_DELAY_EN__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEDiDtCtrl2Config_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__MAX_POWER_DELTA_MASK, DIDT_SQ_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3853 }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_SQ_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, - { ixDIDT_SQ_CTRL2, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_SQ_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0000 }, - - /* DIDT_TD */ - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TD_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3fff }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TD_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, - { ixDIDT_TD_CTRL2, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TD_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, - - /* DIDT_TCP */ - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__MAX_POWER_DELTA_MASK, DIDT_TCP_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_TCP_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, - { ixDIDT_TCP_CTRL2, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_TCP_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, - - /* DIDT_DB */ - { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__MAX_POWER_DELTA_MASK, DIDT_DB_CTRL2__MAX_POWER_DELTA__SHIFT, 0x3dde }, - { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE_MASK, DIDT_DB_CTRL2__SHORT_TERM_INTERVAL_SIZE__SHIFT, 0x00c0 }, - { ixDIDT_DB_CTRL2, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO_MASK, DIDT_DB_CTRL2__LONG_TERM_INTERVAL_RATIO__SHIFT, 0x0001 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEDiDtCtrl1Config_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MIN_POWER_MASK, DIDT_SQ_CTRL1__MIN_POWER__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL1, DIDT_SQ_CTRL1__MAX_POWER_MASK, DIDT_SQ_CTRL1__MAX_POWER__SHIFT, 0xffff }, - /* DIDT_TD */ - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MIN_POWER_MASK, DIDT_TD_CTRL1__MIN_POWER__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL1, DIDT_TD_CTRL1__MAX_POWER_MASK, DIDT_TD_CTRL1__MAX_POWER__SHIFT, 0xffff }, - /* DIDT_TCP */ - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MIN_POWER_MASK, DIDT_TCP_CTRL1__MIN_POWER__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL1, DIDT_TCP_CTRL1__MAX_POWER_MASK, DIDT_TCP_CTRL1__MAX_POWER__SHIFT, 0xffff }, - /* DIDT_DB */ - { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MIN_POWER_MASK, DIDT_DB_CTRL1__MIN_POWER__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL1, DIDT_DB_CTRL1__MAX_POWER_MASK, DIDT_DB_CTRL1__MAX_POWER__SHIFT, 0xffff }, - - { 0xFFFFFFFF } /* End of list */ -}; - - -static const struct vega10_didt_config_reg SEDiDtWeightConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B363B1A }, - { ixDIDT_SQ_WEIGHT4_7, 0xFFFFFFFF, 0, 0x270B2432 }, - { ixDIDT_SQ_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000018 }, - - /* DIDT_TD */ - { ixDIDT_TD_WEIGHT0_3, 0xFFFFFFFF, 0, 0x2B1D220F }, - { ixDIDT_TD_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00007558 }, - { ixDIDT_TD_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, - - /* DIDT_TCP */ - { ixDIDT_TCP_WEIGHT0_3, 0xFFFFFFFF, 0, 0x5ACE160D }, - { ixDIDT_TCP_WEIGHT4_7, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000000 }, - - /* DIDT_DB */ - { ixDIDT_DB_WEIGHT0_3, 0xFFFFFFFF, 0, 0x0E152A0F }, - { ixDIDT_DB_WEIGHT4_7, 0xFFFFFFFF, 0, 0x09061813 }, - { ixDIDT_DB_WEIGHT8_11, 0xFFFFFFFF, 0, 0x00000013 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEDiDtCtrl0Config_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__PHASE_OFFSET_MASK, DIDT_SQ_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CTRL_RST_MASK, DIDT_SQ_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_SQ_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_SQ_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_SQ_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_SQ_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_CTRL0, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_SQ_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, - /* DIDT_TD */ - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__PHASE_OFFSET_MASK, DIDT_TD_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TD_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TD_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TD_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TD_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TD_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_CTRL0, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TD_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, - /* DIDT_TCP */ - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__PHASE_OFFSET_MASK, DIDT_TCP_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CTRL_RST_MASK, DIDT_TCP_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_TCP_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_TCP_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_TCP_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_TCP_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, - { ixDIDT_TCP_CTRL0, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_TCP_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, - /* DIDT_DB */ - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__PHASE_OFFSET_MASK, DIDT_DB_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CTRL_RST_MASK, DIDT_DB_CTRL0__DIDT_CTRL_RST__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, DIDT_DB_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN_MASK, DIDT_DB_CTRL0__DIDT_TUNING_CTRL_EN__SHIFT, 0x0001 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_AUTO_RELEASE_EN__SHIFT, 0x0001 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD_MASK, DIDT_DB_CTRL0__DIDT_HI_POWER_THRESHOLD__SHIFT, 0xffff }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN_MASK, DIDT_DB_CTRL0__DIDT_AUTO_MPD_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_EN__SHIFT, 0x0000 }, - { ixDIDT_DB_CTRL0, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR_MASK, DIDT_DB_CTRL0__DIDT_STALL_EVENT_COUNTER_CLEAR__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - - -static const struct vega10_didt_config_reg SEDiDtStallCtrlConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ */ - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, - { ixDIDT_SQ_STALL_CTRL, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_SQ_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, - - /* DIDT_TD */ - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, - { ixDIDT_TD_STALL_CTRL, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TD_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, - - /* DIDT_TCP */ - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0001 }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0001 }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, - { ixDIDT_TCP_STALL_CTRL, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_TCP_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, - - /* DIDT_DB */ - { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_HI__SHIFT, 0x0004 }, - { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_STALL_DELAY_LO__SHIFT, 0x0004 }, - { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_HI__SHIFT, 0x000a }, - { ixDIDT_DB_STALL_CTRL, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO_MASK, DIDT_DB_STALL_CTRL__DIDT_MAX_STALLS_ALLOWED_LO__SHIFT, 0x000a }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEDiDtStallPatternConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* DIDT_SQ_STALL_PATTERN_1_2 */ - { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, - { ixDIDT_SQ_STALL_PATTERN_1_2, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_SQ_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, - - /* DIDT_SQ_STALL_PATTERN_3_4 */ - { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, - { ixDIDT_SQ_STALL_PATTERN_3_4, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_SQ_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, - - /* DIDT_SQ_STALL_PATTERN_5_6 */ - { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, - { ixDIDT_SQ_STALL_PATTERN_5_6, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_SQ_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, - - /* DIDT_SQ_STALL_PATTERN_7 */ - { ixDIDT_SQ_STALL_PATTERN_7, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_SQ_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, - - /* DIDT_TCP_STALL_PATTERN_1_2 */ - { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, - { ixDIDT_TCP_STALL_PATTERN_1_2, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TCP_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, - - /* DIDT_TCP_STALL_PATTERN_3_4 */ - { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, - { ixDIDT_TCP_STALL_PATTERN_3_4, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TCP_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, - - /* DIDT_TCP_STALL_PATTERN_5_6 */ - { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, - { ixDIDT_TCP_STALL_PATTERN_5_6, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TCP_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, - - /* DIDT_TCP_STALL_PATTERN_7 */ - { ixDIDT_TCP_STALL_PATTERN_7, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TCP_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, - - /* DIDT_TD_STALL_PATTERN_1_2 */ - { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, - { ixDIDT_TD_STALL_PATTERN_1_2, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_TD_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, - - /* DIDT_TD_STALL_PATTERN_3_4 */ - { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, - { ixDIDT_TD_STALL_PATTERN_3_4, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_TD_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, - - /* DIDT_TD_STALL_PATTERN_5_6 */ - { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, - { ixDIDT_TD_STALL_PATTERN_5_6, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_TD_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, - - /* DIDT_TD_STALL_PATTERN_7 */ - { ixDIDT_TD_STALL_PATTERN_7, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_TD_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, - - /* DIDT_DB_STALL_PATTERN_1_2 */ - { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_1__SHIFT, 0x0001 }, - { ixDIDT_DB_STALL_PATTERN_1_2, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2_MASK, DIDT_DB_STALL_PATTERN_1_2__DIDT_STALL_PATTERN_2__SHIFT, 0x0001 }, - - /* DIDT_DB_STALL_PATTERN_3_4 */ - { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_3__SHIFT, 0x0001 }, - { ixDIDT_DB_STALL_PATTERN_3_4, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4_MASK, DIDT_DB_STALL_PATTERN_3_4__DIDT_STALL_PATTERN_4__SHIFT, 0x0001 }, - - /* DIDT_DB_STALL_PATTERN_5_6 */ - { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_5__SHIFT, 0x0000 }, - { ixDIDT_DB_STALL_PATTERN_5_6, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6_MASK, DIDT_DB_STALL_PATTERN_5_6__DIDT_STALL_PATTERN_6__SHIFT, 0x0000 }, - - /* DIDT_DB_STALL_PATTERN_7 */ - { ixDIDT_DB_STALL_PATTERN_7, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7_MASK, DIDT_DB_STALL_PATTERN_7__DIDT_STALL_PATTERN_7__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SELCacConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00060021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00860021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01060021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01860021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02060021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x02860021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03060021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x03860021 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x04060021 }, - /* TD */ - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x000E0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x008E0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x010E0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x018E0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x020E0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x028E0020 }, - /* TCP */ - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x001c0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x009c0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x011c0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x019c0020 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x021c0020 }, - /* DB */ - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00200008 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x00820008 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01020008 }, - { ixSE_CAC_CNTL, 0xFFFFFFFF, 0, 0x01820008 }, - - { 0xFFFFFFFF } /* End of list */ -}; - - -static const struct vega10_didt_config_reg SEEDCStallPatternConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00030001 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x000F0007 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x003F001F }, - { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x0000007F }, - /* TD */ - { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, - /* TCP */ - { ixDIDT_TCP_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, - /* DB */ - { ixDIDT_DB_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_DB_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_DB_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_DB_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCForceStallPatternConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, - /* TD */ - { ixDIDT_TD_EDC_STALL_PATTERN_1_2, 0xFFFFFFFF, 0, 0x00000015 }, - { ixDIDT_TD_EDC_STALL_PATTERN_3_4, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_PATTERN_5_6, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_PATTERN_7, 0xFFFFFFFF, 0, 0x00000000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCStallDelayConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, - /* TD */ - { ixDIDT_TD_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TD_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, - /* TCP */ - { ixDIDT_TCP_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_DELAY_2, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_DELAY_3, 0xFFFFFFFF, 0, 0x00000000 }, - { ixDIDT_TCP_EDC_STALL_DELAY_4, 0xFFFFFFFF, 0, 0x00000000 }, - /* DB */ - { ixDIDT_DB_EDC_STALL_DELAY_1, 0xFFFFFFFF, 0, 0x00000000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCThresholdConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { ixDIDT_SQ_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0x0000010E }, - { ixDIDT_TD_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, - { ixDIDT_TCP_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, - { ixDIDT_DB_EDC_THRESHOLD, 0xFFFFFFFF, 0, 0xFFFFFFFF }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCCtrlResetConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCCtrlConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0004 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0006 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg SEEDCCtrlForceStallConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ */ - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000C }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, - - /* TD */ - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_EN_MASK, DIDT_TD_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_SW_RST_MASK, DIDT_TD_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_TD_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_TD_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0001 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_TD_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0001 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_TD_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_TD_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_TD_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_TD_EDC_CTRL, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_TD_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg GCDiDtDroopCtrlConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_EN__SHIFT, 0x0000 }, - { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_THRESHOLD__SHIFT, 0x0000 }, - { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_INDEX__SHIFT, 0x0000 }, - { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL_MASK, GC_DIDT_DROOP_CTRL__DIDT_LEVEL_SEL__SHIFT, 0x0000 }, - { mmGC_DIDT_DROOP_CTRL, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW_MASK, GC_DIDT_DROOP_CTRL__DIDT_DROOP_LEVEL_OVERFLOW__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg GCDiDtCtrl0Config_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CTRL_EN_MASK, GC_DIDT_CTRL0__DIDT_CTRL_EN__SHIFT, 0x0000 }, - { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__PHASE_OFFSET_MASK, GC_DIDT_CTRL0__PHASE_OFFSET__SHIFT, 0x0000 }, - { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_SW_RST_MASK, GC_DIDT_CTRL0__DIDT_SW_RST__SHIFT, 0x0000 }, - { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE_MASK, GC_DIDT_CTRL0__DIDT_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { mmGC_DIDT_CTRL0, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT_MASK, GC_DIDT_CTRL0__DIDT_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { 0xFFFFFFFF } /* End of list */ -}; - - -static const struct vega10_didt_config_reg PSMSEEDCStallPatternConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ EDC STALL PATTERNs */ - { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_1__SHIFT, 0x0101 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_1_2, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2_MASK, DIDT_SQ_EDC_STALL_PATTERN_1_2__EDC_STALL_PATTERN_2__SHIFT, 0x0101 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_3__SHIFT, 0x1111 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_3_4, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4_MASK, DIDT_SQ_EDC_STALL_PATTERN_3_4__EDC_STALL_PATTERN_4__SHIFT, 0x1111 }, - - { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_5__SHIFT, 0x1515 }, - { ixDIDT_SQ_EDC_STALL_PATTERN_5_6, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6_MASK, DIDT_SQ_EDC_STALL_PATTERN_5_6__EDC_STALL_PATTERN_6__SHIFT, 0x1515 }, - - { ixDIDT_SQ_EDC_STALL_PATTERN_7, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7_MASK, DIDT_SQ_EDC_STALL_PATTERN_7__EDC_STALL_PATTERN_7__SHIFT, 0x5555 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMSEEDCStallDelayConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ EDC STALL DELAYs */ - { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ0__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ1__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ2__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_1, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3_MASK, DIDT_SQ_EDC_STALL_DELAY_1__EDC_STALL_DELAY_SQ3__SHIFT, 0x0000 }, - - { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ4__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ5__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ6__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_2, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7_MASK, DIDT_SQ_EDC_STALL_DELAY_2__EDC_STALL_DELAY_SQ7__SHIFT, 0x0000 }, - - { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ8__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ9__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ10__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_3, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11_MASK, DIDT_SQ_EDC_STALL_DELAY_3__EDC_STALL_DELAY_SQ11__SHIFT, 0x0000 }, - - { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ12_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ13__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ14__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_STALL_DELAY_4, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15_MASK, DIDT_SQ_EDC_STALL_DELAY_4__EDC_STALL_DELAY_SQ15__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMSEEDCCtrlResetConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ EDC CTRL */ - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMSEEDCCtrlConfig_Vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - /* SQ EDC CTRL */ - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_EN_MASK, DIDT_SQ_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_SW_RST_MASK, DIDT_SQ_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, DIDT_SQ_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL_MASK, DIDT_SQ_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, DIDT_SQ_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS_MASK, DIDT_SQ_EDC_CTRL__EDC_STALL_PATTERN_BIT_NUMS__SHIFT, 0x000E }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, DIDT_SQ_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_STALL_POLICY__SHIFT, 0x0003 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__GC_EDC_LEVEL_COMB_EN__SHIFT, 0x0001 }, - { ixDIDT_SQ_EDC_CTRL, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN_MASK, DIDT_SQ_EDC_CTRL__SE_EDC_LEVEL_COMB_EN__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMGCEDCDroopCtrlConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_EN__SHIFT, 0x0001 }, - { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_THRESHOLD__SHIFT, 0x0384 }, - { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX_MASK, GC_EDC_DROOP_CTRL__EDC_DROOP_LEVEL_INDEX__SHIFT, 0x0001 }, - { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__AVG_PSM_SEL_MASK, GC_EDC_DROOP_CTRL__AVG_PSM_SEL__SHIFT, 0x0001 }, - { mmGC_EDC_DROOP_CTRL, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL_MASK, GC_EDC_DROOP_CTRL__EDC_LEVEL_SEL__SHIFT, 0x0001 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMGCEDCCtrlResetConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0001 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg PSMGCEDCCtrlConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_EN_MASK, GC_EDC_CTRL__EDC_EN__SHIFT, 0x0001 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_SW_RST_MASK, GC_EDC_CTRL__EDC_SW_RST__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE_MASK, GC_EDC_CTRL__EDC_CLK_EN_OVERRIDE__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_FORCE_STALL_MASK, GC_EDC_CTRL__EDC_FORCE_STALL__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT_MASK, GC_EDC_CTRL__EDC_TRIGGER_THROTTLE_LOWBIT__SHIFT, 0x0000 }, - { mmGC_EDC_CTRL, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA_MASK, GC_EDC_CTRL__EDC_ALLOW_WRITE_PWRDELTA__SHIFT, 0x0000 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg AvfsPSMResetConfig_vega10[]= -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { 0x16A02, 0xFFFFFFFF, 0x0, 0x0000005F }, - { 0x16A05, 0xFFFFFFFF, 0x0, 0x00000001 }, - { 0x16A06, 0x00000001, 0x0, 0x02000000 }, - { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static const struct vega10_didt_config_reg AvfsPSMInitConfig_vega10[] = -{ -/* --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - * Offset Mask Shift Value - * --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - */ - { 0x16A05, 0xFFFFFFFF, 0x18, 0x00000001 }, - { 0x16A05, 0xFFFFFFFF, 0x8, 0x00000003 }, - { 0x16A05, 0xFFFFFFFF, 0xa, 0x00000006 }, - { 0x16A05, 0xFFFFFFFF, 0x7, 0x00000000 }, - { 0x16A06, 0xFFFFFFFF, 0x18, 0x00000001 }, - { 0x16A06, 0xFFFFFFFF, 0x19, 0x00000001 }, - { 0x16A01, 0xFFFFFFFF, 0x0, 0x00003027 }, - - { 0xFFFFFFFF } /* End of list */ -}; - -static int vega10_program_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs, enum vega10_didt_config_reg_type reg_type) -{ - uint32_t data; - - PP_ASSERT_WITH_CODE((config_regs != NULL), "[vega10_program_didt_config_registers] Invalid config register table!", return -EINVAL); - - while (config_regs->offset != 0xFFFFFFFF) { - switch (reg_type) { - case VEGA10_CONFIGREG_DIDT: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset); - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, config_regs->offset, data); - break; - case VEGA10_CONFIGREG_GCCAC: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset); - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG_GC_CAC, config_regs->offset, data); - break; - case VEGA10_CONFIGREG_SECAC: - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset); - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG_SE_CAC, config_regs->offset, data); - break; - default: - return -EINVAL; - } - - config_regs++; - } - - return 0; -} - -static int vega10_program_gc_didt_config_registers(struct pp_hwmgr *hwmgr, const struct vega10_didt_config_reg *config_regs) -{ - uint32_t data; - - while (config_regs->offset != 0xFFFFFFFF) { - data = cgs_read_register(hwmgr->device, config_regs->offset); - data &= ~config_regs->mask; - data |= ((config_regs->value << config_regs->shift) & config_regs->mask); - cgs_write_register(hwmgr->device, config_regs->offset, data); - config_regs++; - } - - return 0; -} - -static void vega10_didt_set_mask(struct pp_hwmgr *hwmgr, const bool enable) -{ - uint32_t data; - uint32_t en = (enable ? 1 : 0); - uint32_t didt_block_info = SQ_IR_MASK | TCP_IR_MASK | TD_PCC_MASK; - - if (PP_CAP(PHM_PlatformCaps_SQRamping)) { - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_SQ_CTRL0, DIDT_CTRL_EN, en); - didt_block_info &= ~SQ_Enable_MASK; - didt_block_info |= en << SQ_Enable_SHIFT; - } - - if (PP_CAP(PHM_PlatformCaps_DBRamping)) { - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_DB_CTRL0, DIDT_CTRL_EN, en); - didt_block_info &= ~DB_Enable_MASK; - didt_block_info |= en << DB_Enable_SHIFT; - } - - if (PP_CAP(PHM_PlatformCaps_TDRamping)) { - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_TD_CTRL0, DIDT_CTRL_EN, en); - didt_block_info &= ~TD_Enable_MASK; - didt_block_info |= en << TD_Enable_SHIFT; - } - - if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_TCP_CTRL0, DIDT_CTRL_EN, en); - didt_block_info &= ~TCP_Enable_MASK; - didt_block_info |= en << TCP_Enable_SHIFT; - } - - if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { - CGS_WREG32_FIELD_IND(hwmgr->device, CGS_IND_REG__DIDT, - DIDT_DBR_CTRL0, DIDT_CTRL_EN, en); - } - - if (PP_CAP(PHM_PlatformCaps_DiDtEDCEnable)) { - if (PP_CAP(PHM_PlatformCaps_SQRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL); - data = REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_EN, en); - data = REG_SET_FIELD(data, DIDT_SQ_EDC_CTRL, EDC_SW_RST, ~en); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_SQ_EDC_CTRL, data); - } - - if (PP_CAP(PHM_PlatformCaps_DBRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL); - data = REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_EN, en); - data = REG_SET_FIELD(data, DIDT_DB_EDC_CTRL, EDC_SW_RST, ~en); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DB_EDC_CTRL, data); - } - - if (PP_CAP(PHM_PlatformCaps_TDRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL); - data = REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_EN, en); - data = REG_SET_FIELD(data, DIDT_TD_EDC_CTRL, EDC_SW_RST, ~en); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TD_EDC_CTRL, data); - } - - if (PP_CAP(PHM_PlatformCaps_TCPRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL); - data = REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_EN, en); - data = REG_SET_FIELD(data, DIDT_TCP_EDC_CTRL, EDC_SW_RST, ~en); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_TCP_EDC_CTRL, data); - } - - if (PP_CAP(PHM_PlatformCaps_DBRRamping)) { - data = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL); - data = REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_EN, en); - data = REG_SET_FIELD(data, DIDT_DBR_EDC_CTRL, EDC_SW_RST, ~en); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__DIDT, ixDIDT_DBR_EDC_CTRL, data); - } - } - - /* For Vega10, SMC does not support any mask yet. */ - if (enable) - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ConfigureGfxDidt, didt_block_info, - NULL); - -} - -static int vega10_enable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - uint32_t num_se = 0, count, data; - - num_se = adev->gfx.config.max_shader_engines; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - mutex_lock(&adev->grbm_idx_mutex); - for (count = 0; count < num_se; count++) { - data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); - - result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl1Config_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl2Config_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtTuningCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SELCacConfig_Vega10, VEGA10_CONFIGREG_SECAC); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); - - if (0 != result) - break; - } - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); - mutex_unlock(&adev->grbm_idx_mutex); - - vega10_didt_set_mask(hwmgr, true); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - return 0; -} - -static int vega10_disable_cac_driving_se_didt_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - vega10_didt_set_mask(hwmgr, false); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - return 0; -} - -static int vega10_enable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - uint32_t num_se = 0, count, data; - - num_se = adev->gfx.config.max_shader_engines; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - mutex_lock(&adev->grbm_idx_mutex); - for (count = 0; count < num_se; count++) { - data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); - - result = vega10_program_didt_config_registers(hwmgr, SEDiDtStallCtrlConfig_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtStallPatternConfig_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl3Config_vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEDiDtCtrl0Config_Vega10, VEGA10_CONFIGREG_DIDT); - if (0 != result) - break; - } - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); - mutex_unlock(&adev->grbm_idx_mutex); - - vega10_didt_set_mask(hwmgr, true); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - vega10_program_gc_didt_config_registers(hwmgr, GCDiDtDroopCtrlConfig_vega10); - if (PP_CAP(PHM_PlatformCaps_GCEDC)) - vega10_program_gc_didt_config_registers(hwmgr, GCDiDtCtrl0Config_vega10); - - if (PP_CAP(PHM_PlatformCaps_PSM)) - vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); - - return 0; -} - -static int vega10_disable_psm_gc_didt_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t data; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - vega10_didt_set_mask(hwmgr, false); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - if (PP_CAP(PHM_PlatformCaps_GCEDC)) { - data = 0x00000000; - cgs_write_register(hwmgr->device, mmGC_DIDT_CTRL0, data); - } - - if (PP_CAP(PHM_PlatformCaps_PSM)) - vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); - - return 0; -} - -static int vega10_enable_se_edc_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - uint32_t num_se = 0, count, data; - - num_se = adev->gfx.config.max_shader_engines; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - mutex_lock(&adev->grbm_idx_mutex); - for (count = 0; count < num_se; count++) { - data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); - result = vega10_program_didt_config_registers(hwmgr, SEDiDtWeightConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCThresholdConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); - - if (0 != result) - break; - } - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); - mutex_unlock(&adev->grbm_idx_mutex); - - vega10_didt_set_mask(hwmgr, true); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - return 0; -} - -static int vega10_disable_se_edc_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - vega10_didt_set_mask(hwmgr, false); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - return 0; -} - -static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result = 0; - uint32_t num_se = 0; - uint32_t count, data; - - num_se = adev->gfx.config.max_shader_engines; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); - - mutex_lock(&adev->grbm_idx_mutex); - for (count = 0; count < num_se; count++) { - data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT); - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data); - result = vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT); - - if (0 != result) - break; - } - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); - mutex_unlock(&adev->grbm_idx_mutex); - - vega10_didt_set_mask(hwmgr, true); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCDroopCtrlConfig_vega10); - - if (PP_CAP(PHM_PlatformCaps_GCEDC)) { - vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlResetConfig_vega10); - vega10_program_gc_didt_config_registers(hwmgr, PSMGCEDCCtrlConfig_vega10); - } - - if (PP_CAP(PHM_PlatformCaps_PSM)) - vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMInitConfig_vega10); - - return 0; -} - -static int vega10_disable_psm_gc_edc_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t data; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - vega10_didt_set_mask(hwmgr, false); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - if (PP_CAP(PHM_PlatformCaps_GCEDC)) { - data = 0x00000000; - cgs_write_register(hwmgr->device, mmGC_EDC_CTRL, data); - } - - if (PP_CAP(PHM_PlatformCaps_PSM)) - vega10_program_gc_didt_config_registers(hwmgr, AvfsPSMResetConfig_vega10); - - return 0; -} - -static int vega10_enable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int result; - - amdgpu_gfx_rlc_enter_safe_mode(adev); - - mutex_lock(&adev->grbm_idx_mutex); - WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, 0xE0000000); - mutex_unlock(&adev->grbm_idx_mutex); - - result = vega10_program_didt_config_registers(hwmgr, SEEDCForceStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT); - result |= vega10_program_didt_config_registers(hwmgr, SEEDCCtrlForceStallConfig_Vega10, VEGA10_CONFIGREG_DIDT); - if (0 != result) - return result; - - vega10_didt_set_mask(hwmgr, false); - - amdgpu_gfx_rlc_exit_safe_mode(adev); - - return 0; -} - -static int vega10_disable_se_edc_force_stall_config(struct pp_hwmgr *hwmgr) -{ - int result; - - result = vega10_disable_se_edc_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Pre DIDT disable clock gating failed!", return result); - - return 0; -} - -int vega10_enable_didt_config(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DIDT].supported) { - if (data->smu_features[GNLD_DIDT].enabled) - PP_DBG_LOG("[EnableDiDtConfig] Feature DiDt Already enabled!\n"); - - switch (data->registry_data.didt_mode) { - case 0: - result = vega10_enable_cac_driving_se_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 0 Failed!", return result); - break; - case 2: - result = vega10_enable_psm_gc_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 2 Failed!", return result); - break; - case 3: - result = vega10_enable_se_edc_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 3 Failed!", return result); - break; - case 1: - case 4: - case 5: - result = vega10_enable_psm_gc_edc_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 5 Failed!", return result); - break; - case 6: - result = vega10_enable_se_edc_force_stall_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDt] Attempt to enable DiDt Mode 6 Failed!", return result); - break; - default: - result = -EINVAL; - break; - } - - if (0 == result) { - result = vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap); - PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); - data->smu_features[GNLD_DIDT].enabled = true; - } - } - - return result; -} - -int vega10_disable_didt_config(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_DIDT].supported) { - if (!data->smu_features[GNLD_DIDT].enabled) - PP_DBG_LOG("[DisableDiDtConfig] Feature DiDt Already Disabled!\n"); - - switch (data->registry_data.didt_mode) { - case 0: - result = vega10_disable_cac_driving_se_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 0 Failed!", return result); - break; - case 2: - result = vega10_disable_psm_gc_didt_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 2 Failed!", return result); - break; - case 3: - result = vega10_disable_se_edc_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 3 Failed!", return result); - break; - case 1: - case 4: - case 5: - result = vega10_disable_psm_gc_edc_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 5 Failed!", return result); - break; - case 6: - result = vega10_disable_se_edc_force_stall_config(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDt] Attempt to disable DiDt Mode 6 Failed!", return result); - break; - default: - result = -EINVAL; - break; - } - - if (0 == result) { - result = vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap); - PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); - data->smu_features[GNLD_DIDT].enabled = false; - } - } - - return result; -} - -void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_tdp_table *tdp_table = table_info->tdp_table; - PPTable_t *table = &(data->smc_state_table.pp_table); - - table->SocketPowerLimit = cpu_to_le16( - tdp_table->usMaximumPowerDeliveryLimit); - table->TdcLimit = cpu_to_le16(tdp_table->usTDC); - table->EdcLimit = cpu_to_le16(tdp_table->usEDCLimit); - table->TedgeLimit = cpu_to_le16(tdp_table->usTemperatureLimitTedge); - table->ThotspotLimit = cpu_to_le16(tdp_table->usTemperatureLimitHotspot); - table->ThbmLimit = cpu_to_le16(tdp_table->usTemperatureLimitHBM); - table->Tvr_socLimit = cpu_to_le16(tdp_table->usTemperatureLimitVrVddc); - table->Tvr_memLimit = cpu_to_le16(tdp_table->usTemperatureLimitVrMvdd); - table->Tliquid1Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid1); - table->Tliquid2Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid2); - table->TplxLimit = cpu_to_le16(tdp_table->usTemperatureLimitPlx); - table->LoadLineResistance = - hwmgr->platform_descriptor.LoadLineSlope * 256; - table->FitLimit = 0; /* Not used for Vega10 */ - - table->Liquid1_I2C_address = tdp_table->ucLiquid1_I2C_address; - table->Liquid2_I2C_address = tdp_table->ucLiquid2_I2C_address; - table->Vr_I2C_address = tdp_table->ucVr_I2C_address; - table->Plx_I2C_address = tdp_table->ucPlx_I2C_address; - - table->Liquid_I2C_LineSCL = tdp_table->ucLiquid_I2C_Line; - table->Liquid_I2C_LineSDA = tdp_table->ucLiquid_I2C_LineSDA; - - table->Vr_I2C_LineSCL = tdp_table->ucVr_I2C_Line; - table->Vr_I2C_LineSDA = tdp_table->ucVr_I2C_LineSDA; - - table->Plx_I2C_LineSCL = tdp_table->ucPlx_I2C_Line; - table->Plx_I2C_LineSDA = tdp_table->ucPlx_I2C_LineSDA; -} - -int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->registry_data.enable_pkg_pwr_tracking_feature) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetPptLimit, n, - NULL); - - return 0; -} - -int vega10_enable_power_containment(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - struct phm_tdp_table *tdp_table = table_info->tdp_table; - int result = 0; - - hwmgr->default_power_limit = hwmgr->power_limit = - (uint32_t)(tdp_table->usMaximumPowerDeliveryLimit); - - if (!hwmgr->not_vf) - return 0; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - if (data->smu_features[GNLD_PPT].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_PPT].smu_feature_bitmap), - "Attempt to enable PPT feature Failed!", - data->smu_features[GNLD_PPT].supported = false); - - if (data->smu_features[GNLD_TDC].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, data->smu_features[GNLD_TDC].smu_feature_bitmap), - "Attempt to enable PPT feature Failed!", - data->smu_features[GNLD_TDC].supported = false); - - result = vega10_set_power_limit(hwmgr, hwmgr->power_limit); - PP_ASSERT_WITH_CODE(!result, - "Failed to set Default Power Limit in SMC!", - return result); - } - - return result; -} - -int vega10_disable_power_containment(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - if (data->smu_features[GNLD_PPT].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_PPT].smu_feature_bitmap), - "Attempt to disable PPT feature Failed!", - data->smu_features[GNLD_PPT].supported = false); - - if (data->smu_features[GNLD_TDC].supported) - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, data->smu_features[GNLD_TDC].smu_feature_bitmap), - "Attempt to disable PPT feature Failed!", - data->smu_features[GNLD_TDC].supported = false); - } - - return 0; -} - -static void vega10_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, - uint32_t adjust_percent) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_OverDriveSetPercentage, adjust_percent, - NULL); -} - -int vega10_power_control_set_level(struct pp_hwmgr *hwmgr) -{ - int adjust_percent; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - adjust_percent = - hwmgr->platform_descriptor.TDPAdjustmentPolarity ? - hwmgr->platform_descriptor.TDPAdjustment : - (-1 * hwmgr->platform_descriptor.TDPAdjustment); - vega10_set_overdrive_target_percentage(hwmgr, - (uint32_t)adjust_percent); - } - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h deleted file mode 100644 index b95771ab89cd..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2016 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 _VEGA10_POWERTUNE_H_ -#define _VEGA10_POWERTUNE_H_ - -enum vega10_pt_config_reg_type { - VEGA10_CONFIGREG_MMR = 0, - VEGA10_CONFIGREG_SMC_IND, - VEGA10_CONFIGREG_DIDT_IND, - VEGA10_CONFIGREG_CACHE, - VEGA10_CONFIGREG_MAX -}; - -enum vega10_didt_config_reg_type { - VEGA10_CONFIGREG_DIDT = 0, - VEGA10_CONFIGREG_GCCAC, - VEGA10_CONFIGREG_SECAC -}; - -/* PowerContainment Features */ -#define POWERCONTAINMENT_FEATURE_DTE 0x00000001 -#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 -#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 - -struct vega10_pt_config_reg { - uint32_t offset; - uint32_t mask; - uint32_t shift; - uint32_t value; - enum vega10_pt_config_reg_type type; -}; - -struct vega10_didt_config_reg { - uint32_t offset; - uint32_t mask; - uint32_t shift; - uint32_t value; -}; - -struct vega10_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; -}; - -void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); -int vega10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); -int vega10_populate_pm_fuses(struct pp_hwmgr *hwmgr); -int vega10_enable_smc_cac(struct pp_hwmgr *hwmgr); -int vega10_enable_power_containment(struct pp_hwmgr *hwmgr); -int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); -int vega10_power_control_set_level(struct pp_hwmgr *hwmgr); -int vega10_disable_power_containment(struct pp_hwmgr *hwmgr); - -int vega10_enable_didt_config(struct pp_hwmgr *hwmgr); -int vega10_disable_didt_config(struct pp_hwmgr *hwmgr); - -#endif /* _VEGA10_POWERTUNE_H_ */ - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h deleted file mode 100644 index c934e9612c1b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_pptable.h +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright 2016 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 _VEGA10_PPTABLE_H_ -#define _VEGA10_PPTABLE_H_ - -#pragma pack(push, 1) - -#define ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f -#define ATOM_VEGA10_PP_FANPARAMETERS_NOFAN 0x80 - -#define ATOM_VEGA10_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_VEGA10_PP_THERMALCONTROLLER_LM96163 17 -#define ATOM_VEGA10_PP_THERMALCONTROLLER_VEGA10 24 - -#define ATOM_VEGA10_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 -#define ATOM_VEGA10_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D - -#define ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY 0x1 -#define ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 -#define ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC 0x4 -#define ATOM_VEGA10_PP_PLATFORM_CAP_BACO 0x8 -#define ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x10 - - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ -#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 -#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 -#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 -#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 -#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 -/* 2, 4, 6, 7 are reserved */ - -#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 -#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 -#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 -#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 -#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 -#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 - -/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ -#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 - -#define ATOM_Vega10_DISALLOW_ON_DC 0x00004000 -#define ATOM_Vega10_ENABLE_VARIBRIGHT 0x00008000 - -#define ATOM_Vega10_TABLE_REVISION_VEGA10 8 - -#define ATOM_Vega10_VoltageMode_AVFS_Interpolate 0 -#define ATOM_Vega10_VoltageMode_AVFS_WorstCase 1 -#define ATOM_Vega10_VoltageMode_Static 2 - -typedef struct _ATOM_Vega10_POWERPLAYTABLE { - struct atom_common_table_header sHeader; - UCHAR ucTableRevision; - USHORT usTableSize; /* the size of header structure */ - ULONG ulGoldenPPID; /* PPGen use only */ - ULONG ulGoldenRevision; /* PPGen use only */ - USHORT usFormatID; /* PPGen use only */ - ULONG ulPlatformCaps; /* See ATOM_Vega10_CAPS_* */ - ULONG ulMaxODEngineClock; /* For Overdrive. */ - ULONG ulMaxODMemoryClock; /* For Overdrive. */ - USHORT usPowerControlLimit; - USHORT usUlvVoltageOffset; /* in mv units */ - USHORT usUlvSmnclkDid; - USHORT usUlvMp1clkDid; - USHORT usUlvGfxclkBypass; - USHORT usGfxclkSlewRate; - UCHAR ucGfxVoltageMode; - UCHAR ucSocVoltageMode; - UCHAR ucUclkVoltageMode; - UCHAR ucUvdVoltageMode; - UCHAR ucVceVoltageMode; - UCHAR ucMp0VoltageMode; - UCHAR ucDcefVoltageMode; - USHORT usStateArrayOffset; /* points to ATOM_Vega10_State_Array */ - USHORT usFanTableOffset; /* points to ATOM_Vega10_Fan_Table */ - USHORT usThermalControllerOffset; /* points to ATOM_Vega10_Thermal_Controller */ - USHORT usSocclkDependencyTableOffset; /* points to ATOM_Vega10_SOCCLK_Dependency_Table */ - USHORT usMclkDependencyTableOffset; /* points to ATOM_Vega10_MCLK_Dependency_Table */ - USHORT usGfxclkDependencyTableOffset; /* points to ATOM_Vega10_GFXCLK_Dependency_Table */ - USHORT usDcefclkDependencyTableOffset; /* points to ATOM_Vega10_DCEFCLK_Dependency_Table */ - USHORT usVddcLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ - USHORT usVddmemLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ - USHORT usMMDependencyTableOffset; /* points to ATOM_Vega10_MM_Dependency_Table */ - USHORT usVCEStateTableOffset; /* points to ATOM_Vega10_VCE_State_Table */ - USHORT usReserve; /* No PPM Support for Vega10 */ - USHORT usPowerTuneTableOffset; /* points to ATOM_Vega10_PowerTune_Table */ - USHORT usHardLimitTableOffset; /* points to ATOM_Vega10_Hard_Limit_Table */ - USHORT usVddciLookupTableOffset; /* points to ATOM_Vega10_Voltage_Lookup_Table */ - USHORT usPCIETableOffset; /* points to ATOM_Vega10_PCIE_Table */ - USHORT usPixclkDependencyTableOffset; /* points to ATOM_Vega10_PIXCLK_Dependency_Table */ - USHORT usDispClkDependencyTableOffset; /* points to ATOM_Vega10_DISPCLK_Dependency_Table */ - USHORT usPhyClkDependencyTableOffset; /* points to ATOM_Vega10_PHYCLK_Dependency_Table */ -} ATOM_Vega10_POWERPLAYTABLE; - -typedef struct _ATOM_Vega10_State { - UCHAR ucSocClockIndexHigh; - UCHAR ucSocClockIndexLow; - UCHAR ucGfxClockIndexHigh; - UCHAR ucGfxClockIndexLow; - UCHAR ucMemClockIndexHigh; - UCHAR ucMemClockIndexLow; - USHORT usClassification; - ULONG ulCapsAndSettings; - USHORT usClassification2; -} ATOM_Vega10_State; - -typedef struct _ATOM_Vega10_State_Array { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_State states[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_State_Array; - -typedef struct _ATOM_Vega10_CLK_Dependency_Record { - ULONG ulClk; /* Frequency of Clock */ - UCHAR ucVddInd; /* Base voltage */ -} ATOM_Vega10_CLK_Dependency_Record; - -typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record { - ULONG ulClk; /* Clock Frequency */ - UCHAR ucVddInd; /* SOC_VDD index */ - USHORT usCKSVOffsetandDisable; /* Bits 0~30: Voltage offset for CKS, Bit 31: Disable/enable for the GFXCLK level. */ - USHORT usAVFSOffset; /* AVFS Voltage offset */ -} ATOM_Vega10_GFXCLK_Dependency_Record; - -typedef struct _ATOM_Vega10_GFXCLK_Dependency_Record_V2 { - ULONG ulClk; - UCHAR ucVddInd; - USHORT usCKSVOffsetandDisable; - USHORT usAVFSOffset; - UCHAR ucACGEnable; - UCHAR ucReserved[3]; -} ATOM_Vega10_GFXCLK_Dependency_Record_V2; - -typedef struct _ATOM_Vega10_MCLK_Dependency_Record { - ULONG ulMemClk; /* Clock Frequency */ - UCHAR ucVddInd; /* SOC_VDD index */ - UCHAR ucVddMemInd; /* MEM_VDD - only non zero for MCLK record */ - UCHAR ucVddciInd; /* VDDCI = only non zero for MCLK record */ -} ATOM_Vega10_MCLK_Dependency_Record; - -typedef struct _ATOM_Vega10_GFXCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_GFXCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_GFXCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_MCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_MCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_SOCCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_SOCCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_DCEFCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_DCEFCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_PIXCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_PIXCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_DISPCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries.*/ - ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_DISPCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_PHYCLK_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries. */ - ATOM_Vega10_CLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_PHYCLK_Dependency_Table; - -typedef struct _ATOM_Vega10_MM_Dependency_Record { - UCHAR ucVddcInd; /* SOC_VDD voltage */ - ULONG ulDClk; /* UVD D-clock */ - ULONG ulVClk; /* UVD V-clock */ - ULONG ulEClk; /* VCE clock */ - ULONG ulPSPClk; /* PSP clock */ -} ATOM_Vega10_MM_Dependency_Record; - -typedef struct _ATOM_Vega10_MM_Dependency_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries */ - ATOM_Vega10_MM_Dependency_Record entries[1]; /* Dynamically allocate entries */ -} ATOM_Vega10_MM_Dependency_Table; - -typedef struct _ATOM_Vega10_PCIE_Record { - ULONG ulLCLK; /* LClock */ - UCHAR ucPCIEGenSpeed; /* PCIE Speed */ - UCHAR ucPCIELaneWidth; /* PCIE Lane Width */ -} ATOM_Vega10_PCIE_Record; - -typedef struct _ATOM_Vega10_PCIE_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries */ - ATOM_Vega10_PCIE_Record entries[1]; /* Dynamically allocate entries. */ -} ATOM_Vega10_PCIE_Table; - -typedef struct _ATOM_Vega10_Voltage_Lookup_Record { - USHORT usVdd; /* Base voltage */ -} ATOM_Vega10_Voltage_Lookup_Record; - -typedef struct _ATOM_Vega10_Voltage_Lookup_Table { - UCHAR ucRevId; - UCHAR ucNumEntries; /* Number of entries */ - ATOM_Vega10_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries */ -} ATOM_Vega10_Voltage_Lookup_Table; - -typedef struct _ATOM_Vega10_Fan_Table { - UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ - USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes. */ - USHORT usFanRPMMax; /* The default value in RPM. */ - USHORT usThrottlingRPM; - USHORT usFanAcousticLimit; /* Minimum Fan Controller Frequency Acoustic Limit. */ - USHORT usTargetTemperature; /* The default ideal temperature in Celcius. */ - USHORT usMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. */ - USHORT usTargetGfxClk; /* The ideal Fan Controller GFXCLK Frequency Acoustic Limit. */ - USHORT usFanGainEdge; - USHORT usFanGainHotspot; - USHORT usFanGainLiquid; - USHORT usFanGainVrVddc; - USHORT usFanGainVrMvdd; - USHORT usFanGainPlx; - USHORT usFanGainHbm; - UCHAR ucEnableZeroRPM; - USHORT usFanStopTemperature; - USHORT usFanStartTemperature; -} ATOM_Vega10_Fan_Table; - -typedef struct _ATOM_Vega10_Fan_Table_V2 { - UCHAR ucRevId; - USHORT usFanOutputSensitivity; - USHORT usFanAcousticLimitRpm; - USHORT usThrottlingRPM; - USHORT usTargetTemperature; - USHORT usMinimumPWMLimit; - USHORT usTargetGfxClk; - USHORT usFanGainEdge; - USHORT usFanGainHotspot; - USHORT usFanGainLiquid; - USHORT usFanGainVrVddc; - USHORT usFanGainVrMvdd; - USHORT usFanGainPlx; - USHORT usFanGainHbm; - UCHAR ucEnableZeroRPM; - USHORT usFanStopTemperature; - USHORT usFanStartTemperature; - UCHAR ucFanParameters; - UCHAR ucFanMinRPM; - UCHAR ucFanMaxRPM; -} ATOM_Vega10_Fan_Table_V2; - -typedef struct _ATOM_Vega10_Fan_Table_V3 { - UCHAR ucRevId; - USHORT usFanOutputSensitivity; - USHORT usFanAcousticLimitRpm; - USHORT usThrottlingRPM; - USHORT usTargetTemperature; - USHORT usMinimumPWMLimit; - USHORT usTargetGfxClk; - USHORT usFanGainEdge; - USHORT usFanGainHotspot; - USHORT usFanGainLiquid; - USHORT usFanGainVrVddc; - USHORT usFanGainVrMvdd; - USHORT usFanGainPlx; - USHORT usFanGainHbm; - UCHAR ucEnableZeroRPM; - USHORT usFanStopTemperature; - USHORT usFanStartTemperature; - UCHAR ucFanParameters; - UCHAR ucFanMinRPM; - UCHAR ucFanMaxRPM; - USHORT usMGpuThrottlingRPM; -} ATOM_Vega10_Fan_Table_V3; - -typedef struct _ATOM_Vega10_Thermal_Controller { - UCHAR ucRevId; - UCHAR ucType; /* one of ATOM_VEGA10_PP_THERMALCONTROLLER_*/ - UCHAR ucI2cLine; /* as interpreted by DAL I2C */ - UCHAR ucI2cAddress; - UCHAR ucFanParameters; /* Fan Control Parameters. */ - UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only.*/ - UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only.*/ - UCHAR ucFlags; /* to be defined */ -} ATOM_Vega10_Thermal_Controller; - -typedef struct _ATOM_Vega10_VCE_State_Record -{ - UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Vega10_MM_Dependency_Table' type */ - UCHAR ucFlag; /* 2 bits indicates memory p-states */ - UCHAR ucSCLKIndex; /* index into ATOM_Vega10_SCLK_Dependency_Table */ - UCHAR ucMCLKIndex; /* index into ATOM_Vega10_MCLK_Dependency_Table */ -} ATOM_Vega10_VCE_State_Record; - -typedef struct _ATOM_Vega10_VCE_State_Table -{ - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Vega10_VCE_State_Record entries[1]; -} ATOM_Vega10_VCE_State_Table; - -typedef struct _ATOM_Vega10_PowerTune_Table { - UCHAR ucRevId; - USHORT usSocketPowerLimit; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usTdcLimit; - USHORT usEdcLimit; - USHORT usSoftwareShutdownTemp; - USHORT usTemperatureLimitHotSpot; - USHORT usTemperatureLimitLiquid1; - USHORT usTemperatureLimitLiquid2; - USHORT usTemperatureLimitHBM; - USHORT usTemperatureLimitVrSoc; - USHORT usTemperatureLimitVrMem; - USHORT usTemperatureLimitPlx; - USHORT usLoadLineResistance; - UCHAR ucLiquid1_I2C_address; - UCHAR ucLiquid2_I2C_address; - UCHAR ucVr_I2C_address; - UCHAR ucPlx_I2C_address; - UCHAR ucLiquid_I2C_LineSCL; - UCHAR ucLiquid_I2C_LineSDA; - UCHAR ucVr_I2C_LineSCL; - UCHAR ucVr_I2C_LineSDA; - UCHAR ucPlx_I2C_LineSCL; - UCHAR ucPlx_I2C_LineSDA; - USHORT usTemperatureLimitTedge; -} ATOM_Vega10_PowerTune_Table; - -typedef struct _ATOM_Vega10_PowerTune_Table_V2 -{ - UCHAR ucRevId; - USHORT usSocketPowerLimit; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usTdcLimit; - USHORT usEdcLimit; - USHORT usSoftwareShutdownTemp; - USHORT usTemperatureLimitHotSpot; - USHORT usTemperatureLimitLiquid1; - USHORT usTemperatureLimitLiquid2; - USHORT usTemperatureLimitHBM; - USHORT usTemperatureLimitVrSoc; - USHORT usTemperatureLimitVrMem; - USHORT usTemperatureLimitPlx; - USHORT usLoadLineResistance; - UCHAR ucLiquid1_I2C_address; - UCHAR ucLiquid2_I2C_address; - UCHAR ucLiquid_I2C_Line; - UCHAR ucVr_I2C_address; - UCHAR ucVr_I2C_Line; - UCHAR ucPlx_I2C_address; - UCHAR ucPlx_I2C_Line; - USHORT usTemperatureLimitTedge; -} ATOM_Vega10_PowerTune_Table_V2; - -typedef struct _ATOM_Vega10_PowerTune_Table_V3 -{ - UCHAR ucRevId; - USHORT usSocketPowerLimit; - USHORT usBatteryPowerLimit; - USHORT usSmallPowerLimit; - USHORT usTdcLimit; - USHORT usEdcLimit; - USHORT usSoftwareShutdownTemp; - USHORT usTemperatureLimitHotSpot; - USHORT usTemperatureLimitLiquid1; - USHORT usTemperatureLimitLiquid2; - USHORT usTemperatureLimitHBM; - USHORT usTemperatureLimitVrSoc; - USHORT usTemperatureLimitVrMem; - USHORT usTemperatureLimitPlx; - USHORT usLoadLineResistance; - UCHAR ucLiquid1_I2C_address; - UCHAR ucLiquid2_I2C_address; - UCHAR ucLiquid_I2C_Line; - UCHAR ucVr_I2C_address; - UCHAR ucVr_I2C_Line; - UCHAR ucPlx_I2C_address; - UCHAR ucPlx_I2C_Line; - USHORT usTemperatureLimitTedge; - USHORT usBoostStartTemperature; - USHORT usBoostStopTemperature; - ULONG ulBoostClock; - ULONG Reserved[2]; -} ATOM_Vega10_PowerTune_Table_V3; - -typedef struct _ATOM_Vega10_Hard_Limit_Record { - ULONG ulSOCCLKLimit; - ULONG ulGFXCLKLimit; - ULONG ulMCLKLimit; - USHORT usVddcLimit; - USHORT usVddciLimit; - USHORT usVddMemLimit; -} ATOM_Vega10_Hard_Limit_Record; - -typedef struct _ATOM_Vega10_Hard_Limit_Table -{ - UCHAR ucRevId; - UCHAR ucNumEntries; - ATOM_Vega10_Hard_Limit_Record entries[1]; -} ATOM_Vega10_Hard_Limit_Table; - -typedef struct _Vega10_PPTable_Generic_SubTable_Header -{ - UCHAR ucRevId; -} Vega10_PPTable_Generic_SubTable_Header; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c deleted file mode 100644 index f29af5ca0aa0..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* - * Copyright 2016 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 -#include -#include -#include - -#include "vega10_processpptables.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "pp_debug.h" -#include "cgs_common.h" -#include "vega10_pptable.h" - -#define NUM_DSPCLK_LEVELS 8 -#define VEGA10_ENGINECLOCK_HARDMAX 198000 - -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, - enum phm_platform_caps cap) -{ - if (enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - -static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) -{ - int index = GetIndexIntoMasterDataTable(powerplayinfo); - - u16 size; - u8 frev, crev; - const void *table_address = hwmgr->soft_pp_table; - - if (!table_address) { - table_address = (ATOM_Vega10_POWERPLAYTABLE *) - smu_atom_get_data_table(hwmgr->adev, index, - &size, &frev, &crev); - - hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ - hwmgr->soft_pp_table_size = size; - } - - return table_address; -} - -static int check_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) -{ - const ATOM_Vega10_State_Array *state_arrays; - - state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= - ATOM_Vega10_TABLE_REVISION_VEGA10), - "Unsupported PPTable format!", return -1); - PP_ASSERT_WITH_CODE(powerplay_table->usStateArrayOffset, - "State table is not set!", return -1); - PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, - "Invalid PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, - "Invalid PowerPlay Table!", return -1); - - return 0; -} - -static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) -{ - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_HARDWAREDC), - PHM_PlatformCaps_AutomaticDCTransition); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA10_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), - PHM_PlatformCaps_CombinePCCWithThermalSignal); - - return 0; -} - -static int init_thermal_controller( - struct pp_hwmgr *hwmgr, - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) -{ - const ATOM_Vega10_Thermal_Controller *thermal_controller; - const Vega10_PPTable_Generic_SubTable_Header *header; - const ATOM_Vega10_Fan_Table *fan_table_v1; - const ATOM_Vega10_Fan_Table_V2 *fan_table_v2; - const ATOM_Vega10_Fan_Table_V3 *fan_table_v3; - - thermal_controller = (ATOM_Vega10_Thermal_Controller *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usThermalControllerOffset)); - - PP_ASSERT_WITH_CODE((powerplay_table->usThermalControllerOffset != 0), - "Thermal controller table not set!", return -EINVAL); - - hwmgr->thermal_controller.ucType = thermal_controller->ucType; - hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; - hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; - - hwmgr->thermal_controller.fanInfo.bNoFan = - (0 != (thermal_controller->ucFanParameters & - ATOM_VEGA10_PP_FANPARAMETERS_NOFAN)); - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - thermal_controller->ucFanParameters & - ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - - hwmgr->thermal_controller.fanInfo.ulMinRPM = - thermal_controller->ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM = - thermal_controller->ucFanMaxRPM * 100UL; - - hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay - = 100000; - - set_hw_cap( - hwmgr, - ATOM_VEGA10_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController); - - if (!powerplay_table->usFanTableOffset) - return 0; - - header = (const Vega10_PPTable_Generic_SubTable_Header *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usFanTableOffset)); - - if (header->ucRevId == 10) { - fan_table_v1 = (ATOM_Vega10_Fan_Table *)header; - - PP_ASSERT_WITH_CODE((fan_table_v1->ucRevId >= 8), - "Invalid Input Fan Table!", return -EINVAL); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - le16_to_cpu(fan_table_v1->usFanOutputSensitivity); - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = - le16_to_cpu(fan_table_v1->usFanRPMMax); - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = - le16_to_cpu(fan_table_v1->usThrottlingRPM); - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = - le16_to_cpu(fan_table_v1->usFanAcousticLimit); - hwmgr->thermal_controller.advanceFanControlParameters.usTMax = - le16_to_cpu(fan_table_v1->usTargetTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = - le16_to_cpu(fan_table_v1->usMinimumPWMLimit); - hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = - le16_to_cpu(fan_table_v1->usTargetGfxClk); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = - le16_to_cpu(fan_table_v1->usFanGainEdge); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = - le16_to_cpu(fan_table_v1->usFanGainHotspot); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = - le16_to_cpu(fan_table_v1->usFanGainLiquid); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = - le16_to_cpu(fan_table_v1->usFanGainVrVddc); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = - le16_to_cpu(fan_table_v1->usFanGainVrMvdd); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = - le16_to_cpu(fan_table_v1->usFanGainPlx); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = - le16_to_cpu(fan_table_v1->usFanGainHbm); - - hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = - fan_table_v1->ucEnableZeroRPM; - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = - le16_to_cpu(fan_table_v1->usFanStopTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = - le16_to_cpu(fan_table_v1->usFanStartTemperature); - } else if (header->ucRevId == 0xb) { - fan_table_v2 = (ATOM_Vega10_Fan_Table_V2 *)header; - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - fan_table_v2->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v2->ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v2->ucFanMaxRPM * 100UL; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - le16_to_cpu(fan_table_v2->usFanOutputSensitivity); - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = - fan_table_v2->ucFanMaxRPM * 100UL; - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = - le16_to_cpu(fan_table_v2->usThrottlingRPM); - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = - le16_to_cpu(fan_table_v2->usFanAcousticLimitRpm); - hwmgr->thermal_controller.advanceFanControlParameters.usTMax = - le16_to_cpu(fan_table_v2->usTargetTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = - le16_to_cpu(fan_table_v2->usMinimumPWMLimit); - hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = - le16_to_cpu(fan_table_v2->usTargetGfxClk); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = - le16_to_cpu(fan_table_v2->usFanGainEdge); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = - le16_to_cpu(fan_table_v2->usFanGainHotspot); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = - le16_to_cpu(fan_table_v2->usFanGainLiquid); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = - le16_to_cpu(fan_table_v2->usFanGainVrVddc); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = - le16_to_cpu(fan_table_v2->usFanGainVrMvdd); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = - le16_to_cpu(fan_table_v2->usFanGainPlx); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = - le16_to_cpu(fan_table_v2->usFanGainHbm); - - hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = - fan_table_v2->ucEnableZeroRPM; - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = - le16_to_cpu(fan_table_v2->usFanStopTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = - le16_to_cpu(fan_table_v2->usFanStartTemperature); - } else if (header->ucRevId > 0xb) { - fan_table_v3 = (ATOM_Vega10_Fan_Table_V3 *)header; - - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = - fan_table_v3->ucFanParameters & ATOM_VEGA10_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; - hwmgr->thermal_controller.fanInfo.ulMinRPM = fan_table_v3->ucFanMinRPM * 100UL; - hwmgr->thermal_controller.fanInfo.ulMaxRPM = fan_table_v3->ucFanMaxRPM * 100UL; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - le16_to_cpu(fan_table_v3->usFanOutputSensitivity); - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = - fan_table_v3->ucFanMaxRPM * 100UL; - hwmgr->thermal_controller.advanceFanControlParameters.usFanRPMMaxLimit = - le16_to_cpu(fan_table_v3->usThrottlingRPM); - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit = - le16_to_cpu(fan_table_v3->usFanAcousticLimitRpm); - hwmgr->thermal_controller.advanceFanControlParameters.usTMax = - le16_to_cpu(fan_table_v3->usTargetTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin = - le16_to_cpu(fan_table_v3->usMinimumPWMLimit); - hwmgr->thermal_controller.advanceFanControlParameters.ulTargetGfxClk = - le16_to_cpu(fan_table_v3->usTargetGfxClk); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge = - le16_to_cpu(fan_table_v3->usFanGainEdge); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot = - le16_to_cpu(fan_table_v3->usFanGainHotspot); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid = - le16_to_cpu(fan_table_v3->usFanGainLiquid); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc = - le16_to_cpu(fan_table_v3->usFanGainVrVddc); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd = - le16_to_cpu(fan_table_v3->usFanGainVrMvdd); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx = - le16_to_cpu(fan_table_v3->usFanGainPlx); - hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm = - le16_to_cpu(fan_table_v3->usFanGainHbm); - - hwmgr->thermal_controller.advanceFanControlParameters.ucEnableZeroRPM = - fan_table_v3->ucEnableZeroRPM; - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStopTemperature = - le16_to_cpu(fan_table_v3->usFanStopTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usZeroRPMStartTemperature = - le16_to_cpu(fan_table_v3->usFanStartTemperature); - hwmgr->thermal_controller.advanceFanControlParameters.usMGpuThrottlingRPMLimit = - le16_to_cpu(fan_table_v3->usMGpuThrottlingRPM); - } - - return 0; -} - -static int init_over_drive_limits( - struct pp_hwmgr *hwmgr, - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) -{ - const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = - (const ATOM_Vega10_GFXCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); - bool is_acg_enabled = false; - ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; - - if (gfxclk_dep_table->ucRevId == 1) { - patom_record_v2 = - (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries; - is_acg_enabled = - (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable; - } - - if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX && - !is_acg_enabled) - hwmgr->platform_descriptor.overdriveLimit.engineClock = - VEGA10_ENGINECLOCK_HARDMAX; - else - hwmgr->platform_descriptor.overdriveLimit.engineClock = - le32_to_cpu(powerplay_table->ulMaxODEngineClock); - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - le32_to_cpu(powerplay_table->ulMaxODMemoryClock); - - hwmgr->platform_descriptor.minOverdriveVDDC = 0; - hwmgr->platform_descriptor.maxOverdriveVDDC = 0; - hwmgr->platform_descriptor.overdriveVDDCStep = 0; - - return 0; -} - -static int get_mm_clock_voltage_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_mm_clock_voltage_dependency_table **vega10_mm_table, - const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table) -{ - uint32_t table_size, i; - const ATOM_Vega10_MM_Dependency_Record *mm_dependency_record; - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; - - PP_ASSERT_WITH_CODE((mm_dependency_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) * - mm_dependency_table->ucNumEntries; - mm_table = kzalloc(table_size, GFP_KERNEL); - - if (!mm_table) - return -ENOMEM; - - mm_table->count = mm_dependency_table->ucNumEntries; - - for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { - mm_dependency_record = &mm_dependency_table->entries[i]; - mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd; - mm_table->entries[i].samclock = - le32_to_cpu(mm_dependency_record->ulPSPClk); - mm_table->entries[i].eclk = le32_to_cpu(mm_dependency_record->ulEClk); - mm_table->entries[i].vclk = le32_to_cpu(mm_dependency_record->ulVClk); - mm_table->entries[i].dclk = le32_to_cpu(mm_dependency_record->ulDClk); - } - - *vega10_mm_table = mm_table; - - return 0; -} - -static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) -{ - switch(line){ - case Vega10_I2CLineID_DDC1: - *scl = Vega10_I2C_DDC1CLK; - *sda = Vega10_I2C_DDC1DATA; - break; - case Vega10_I2CLineID_DDC2: - *scl = Vega10_I2C_DDC2CLK; - *sda = Vega10_I2C_DDC2DATA; - break; - case Vega10_I2CLineID_DDC3: - *scl = Vega10_I2C_DDC3CLK; - *sda = Vega10_I2C_DDC3DATA; - break; - case Vega10_I2CLineID_DDC4: - *scl = Vega10_I2C_DDC4CLK; - *sda = Vega10_I2C_DDC4DATA; - break; - case Vega10_I2CLineID_DDC5: - *scl = Vega10_I2C_DDC5CLK; - *sda = Vega10_I2C_DDC5DATA; - break; - case Vega10_I2CLineID_DDC6: - *scl = Vega10_I2C_DDC6CLK; - *sda = Vega10_I2C_DDC6DATA; - break; - case Vega10_I2CLineID_SCLSDA: - *scl = Vega10_I2C_SCL; - *sda = Vega10_I2C_SDA; - break; - case Vega10_I2CLineID_DDCVGA: - *scl = Vega10_I2C_DDCVGACLK; - *sda = Vega10_I2C_DDCVGADATA; - break; - default: - *scl = 0; - *sda = 0; - break; - } -} - -static int get_tdp_table( - struct pp_hwmgr *hwmgr, - struct phm_tdp_table **info_tdp_table, - const Vega10_PPTable_Generic_SubTable_Header *table) -{ - uint32_t table_size; - struct phm_tdp_table *tdp_table; - uint8_t scl; - uint8_t sda; - const ATOM_Vega10_PowerTune_Table *power_tune_table; - const ATOM_Vega10_PowerTune_Table_V2 *power_tune_table_v2; - const ATOM_Vega10_PowerTune_Table_V3 *power_tune_table_v3; - - table_size = sizeof(uint32_t) + sizeof(struct phm_tdp_table); - - tdp_table = kzalloc(table_size, GFP_KERNEL); - - if (!tdp_table) - return -ENOMEM; - - if (table->ucRevId == 5) { - power_tune_table = (ATOM_Vega10_PowerTune_Table *)table; - tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table->usSocketPowerLimit); - tdp_table->usTDC = le16_to_cpu(power_tune_table->usTdcLimit); - tdp_table->usEDCLimit = le16_to_cpu(power_tune_table->usEdcLimit); - tdp_table->usSoftwareShutdownTemp = - le16_to_cpu(power_tune_table->usSoftwareShutdownTemp); - tdp_table->usTemperatureLimitTedge = - le16_to_cpu(power_tune_table->usTemperatureLimitTedge); - tdp_table->usTemperatureLimitHotspot = - le16_to_cpu(power_tune_table->usTemperatureLimitHotSpot); - tdp_table->usTemperatureLimitLiquid1 = - le16_to_cpu(power_tune_table->usTemperatureLimitLiquid1); - tdp_table->usTemperatureLimitLiquid2 = - le16_to_cpu(power_tune_table->usTemperatureLimitLiquid2); - tdp_table->usTemperatureLimitHBM = - le16_to_cpu(power_tune_table->usTemperatureLimitHBM); - tdp_table->usTemperatureLimitVrVddc = - le16_to_cpu(power_tune_table->usTemperatureLimitVrSoc); - tdp_table->usTemperatureLimitVrMvdd = - le16_to_cpu(power_tune_table->usTemperatureLimitVrMem); - tdp_table->usTemperatureLimitPlx = - le16_to_cpu(power_tune_table->usTemperatureLimitPlx); - tdp_table->ucLiquid1_I2C_address = power_tune_table->ucLiquid1_I2C_address; - tdp_table->ucLiquid2_I2C_address = power_tune_table->ucLiquid2_I2C_address; - tdp_table->ucLiquid_I2C_Line = power_tune_table->ucLiquid_I2C_LineSCL; - tdp_table->ucLiquid_I2C_LineSDA = power_tune_table->ucLiquid_I2C_LineSDA; - tdp_table->ucVr_I2C_address = power_tune_table->ucVr_I2C_address; - tdp_table->ucVr_I2C_Line = power_tune_table->ucVr_I2C_LineSCL; - tdp_table->ucVr_I2C_LineSDA = power_tune_table->ucVr_I2C_LineSDA; - tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address; - tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL; - tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA; - hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(power_tune_table->usLoadLineResistance); - } else if (table->ucRevId == 6) { - power_tune_table_v2 = (ATOM_Vega10_PowerTune_Table_V2 *)table; - tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit); - tdp_table->usTDC = le16_to_cpu(power_tune_table_v2->usTdcLimit); - tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v2->usEdcLimit); - tdp_table->usSoftwareShutdownTemp = - le16_to_cpu(power_tune_table_v2->usSoftwareShutdownTemp); - tdp_table->usTemperatureLimitTedge = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitTedge); - tdp_table->usTemperatureLimitHotspot = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitHotSpot); - tdp_table->usTemperatureLimitLiquid1 = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid1); - tdp_table->usTemperatureLimitLiquid2 = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitLiquid2); - tdp_table->usTemperatureLimitHBM = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitHBM); - tdp_table->usTemperatureLimitVrVddc = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrSoc); - tdp_table->usTemperatureLimitVrMvdd = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitVrMem); - tdp_table->usTemperatureLimitPlx = - le16_to_cpu(power_tune_table_v2->usTemperatureLimitPlx); - tdp_table->ucLiquid1_I2C_address = power_tune_table_v2->ucLiquid1_I2C_address; - tdp_table->ucLiquid2_I2C_address = power_tune_table_v2->ucLiquid2_I2C_address; - - get_scl_sda_value(power_tune_table_v2->ucLiquid_I2C_Line, &scl, &sda); - - tdp_table->ucLiquid_I2C_Line = scl; - tdp_table->ucLiquid_I2C_LineSDA = sda; - - tdp_table->ucVr_I2C_address = power_tune_table_v2->ucVr_I2C_address; - - get_scl_sda_value(power_tune_table_v2->ucVr_I2C_Line, &scl, &sda); - - tdp_table->ucVr_I2C_Line = scl; - tdp_table->ucVr_I2C_LineSDA = sda; - tdp_table->ucPlx_I2C_address = power_tune_table_v2->ucPlx_I2C_address; - - get_scl_sda_value(power_tune_table_v2->ucPlx_I2C_Line, &scl, &sda); - - tdp_table->ucPlx_I2C_Line = scl; - tdp_table->ucPlx_I2C_LineSDA = sda; - - hwmgr->platform_descriptor.LoadLineSlope = - le16_to_cpu(power_tune_table_v2->usLoadLineResistance); - } else { - power_tune_table_v3 = (ATOM_Vega10_PowerTune_Table_V3 *)table; - tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v3->usSocketPowerLimit); - tdp_table->usTDC = le16_to_cpu(power_tune_table_v3->usTdcLimit); - tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v3->usEdcLimit); - tdp_table->usSoftwareShutdownTemp = le16_to_cpu(power_tune_table_v3->usSoftwareShutdownTemp); - tdp_table->usTemperatureLimitTedge = le16_to_cpu(power_tune_table_v3->usTemperatureLimitTedge); - tdp_table->usTemperatureLimitHotspot = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHotSpot); - tdp_table->usTemperatureLimitLiquid1 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid1); - tdp_table->usTemperatureLimitLiquid2 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid2); - tdp_table->usTemperatureLimitHBM = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHBM); - tdp_table->usTemperatureLimitVrVddc = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrSoc); - tdp_table->usTemperatureLimitVrMvdd = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrMem); - tdp_table->usTemperatureLimitPlx = le16_to_cpu(power_tune_table_v3->usTemperatureLimitPlx); - tdp_table->ucLiquid1_I2C_address = power_tune_table_v3->ucLiquid1_I2C_address; - tdp_table->ucLiquid2_I2C_address = power_tune_table_v3->ucLiquid2_I2C_address; - tdp_table->usBoostStartTemperature = le16_to_cpu(power_tune_table_v3->usBoostStartTemperature); - tdp_table->usBoostStopTemperature = le16_to_cpu(power_tune_table_v3->usBoostStopTemperature); - tdp_table->ulBoostClock = le32_to_cpu(power_tune_table_v3->ulBoostClock); - - get_scl_sda_value(power_tune_table_v3->ucLiquid_I2C_Line, &scl, &sda); - - tdp_table->ucLiquid_I2C_Line = scl; - tdp_table->ucLiquid_I2C_LineSDA = sda; - - tdp_table->ucVr_I2C_address = power_tune_table_v3->ucVr_I2C_address; - - get_scl_sda_value(power_tune_table_v3->ucVr_I2C_Line, &scl, &sda); - - tdp_table->ucVr_I2C_Line = scl; - tdp_table->ucVr_I2C_LineSDA = sda; - - tdp_table->ucPlx_I2C_address = power_tune_table_v3->ucPlx_I2C_address; - - get_scl_sda_value(power_tune_table_v3->ucPlx_I2C_Line, &scl, &sda); - - tdp_table->ucPlx_I2C_Line = scl; - tdp_table->ucPlx_I2C_LineSDA = sda; - - hwmgr->platform_descriptor.LoadLineSlope = - le16_to_cpu(power_tune_table_v3->usLoadLineResistance); - } - - *info_tdp_table = tdp_table; - - return 0; -} - -static int get_socclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_clk_dep_table, - const ATOM_Vega10_SOCCLK_Dependency_Table *clk_dep_table) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *clk_table; - - PP_ASSERT_WITH_CODE(clk_dep_table->ucNumEntries, - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - - if (!clk_table) - return -ENOMEM; - - clk_table->count = (uint32_t)clk_dep_table->ucNumEntries; - - for (i = 0; i < clk_dep_table->ucNumEntries; i++) { - clk_table->entries[i].vddInd = - clk_dep_table->entries[i].ucVddInd; - clk_table->entries[i].clk = - le32_to_cpu(clk_dep_table->entries[i].ulClk); - } - - *pp_vega10_clk_dep_table = clk_table; - - return 0; -} - -static int get_mclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table **pp_vega10_mclk_dep_table, - const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table) -{ - uint32_t table_size, i; - phm_ppt_v1_clock_voltage_dependency_table *mclk_table; - - PP_ASSERT_WITH_CODE(mclk_dep_table->ucNumEntries, - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - mclk_dep_table->ucNumEntries; - - mclk_table = kzalloc(table_size, GFP_KERNEL); - - if (!mclk_table) - return -ENOMEM; - - mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; - - for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { - mclk_table->entries[i].vddInd = - mclk_dep_table->entries[i].ucVddInd; - mclk_table->entries[i].vddciInd = - mclk_dep_table->entries[i].ucVddciInd; - mclk_table->entries[i].mvddInd = - mclk_dep_table->entries[i].ucVddMemInd; - mclk_table->entries[i].clk = - le32_to_cpu(mclk_dep_table->entries[i].ulMemClk); - } - - *pp_vega10_mclk_dep_table = mclk_table; - - return 0; -} - -static int get_gfxclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table - **pp_vega10_clk_dep_table, - const ATOM_Vega10_GFXCLK_Dependency_Table *clk_dep_table) -{ - uint32_t table_size, i; - struct phm_ppt_v1_clock_voltage_dependency_table - *clk_table; - ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2; - - PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - - if (!clk_table) - return -ENOMEM; - - clk_table->count = clk_dep_table->ucNumEntries; - - if (clk_dep_table->ucRevId == 0) { - for (i = 0; i < clk_table->count; i++) { - clk_table->entries[i].vddInd = - clk_dep_table->entries[i].ucVddInd; - clk_table->entries[i].clk = - le32_to_cpu(clk_dep_table->entries[i].ulClk); - clk_table->entries[i].cks_enable = - (((le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x8000) - >> 15) == 0) ? 1 : 0; - clk_table->entries[i].cks_voffset = - le16_to_cpu(clk_dep_table->entries[i].usCKSVOffsetandDisable) & 0x7F; - clk_table->entries[i].sclk_offset = - le16_to_cpu(clk_dep_table->entries[i].usAVFSOffset); - } - } else if (clk_dep_table->ucRevId == 1) { - patom_record_v2 = (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)clk_dep_table->entries; - for (i = 0; i < clk_table->count; i++) { - clk_table->entries[i].vddInd = - patom_record_v2->ucVddInd; - clk_table->entries[i].clk = - le32_to_cpu(patom_record_v2->ulClk); - clk_table->entries[i].cks_enable = - (((le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x8000) - >> 15) == 0) ? 1 : 0; - clk_table->entries[i].cks_voffset = - le16_to_cpu(patom_record_v2->usCKSVOffsetandDisable) & 0x7F; - clk_table->entries[i].sclk_offset = - le16_to_cpu(patom_record_v2->usAVFSOffset); - patom_record_v2++; - } - } else { - kfree(clk_table); - PP_ASSERT_WITH_CODE(false, - "Unsupported GFXClockDependencyTable Revision!", - return -EINVAL); - } - - *pp_vega10_clk_dep_table = clk_table; - - return 0; -} - -static int get_pix_clk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table - **pp_vega10_clk_dep_table, - const ATOM_Vega10_PIXCLK_Dependency_Table *clk_dep_table) -{ - uint32_t table_size, i; - struct phm_ppt_v1_clock_voltage_dependency_table - *clk_table; - - PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - clk_dep_table->ucNumEntries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - - if (!clk_table) - return -ENOMEM; - - clk_table->count = clk_dep_table->ucNumEntries; - - for (i = 0; i < clk_table->count; i++) { - clk_table->entries[i].vddInd = - clk_dep_table->entries[i].ucVddInd; - clk_table->entries[i].clk = - le32_to_cpu(clk_dep_table->entries[i].ulClk); - } - - *pp_vega10_clk_dep_table = clk_table; - - return 0; -} - -static int get_dcefclk_voltage_dependency_table( - struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table - **pp_vega10_clk_dep_table, - const ATOM_Vega10_DCEFCLK_Dependency_Table *clk_dep_table) -{ - uint32_t table_size, i; - uint8_t num_entries; - struct phm_ppt_v1_clock_voltage_dependency_table - *clk_table; - uint32_t dev_id; - uint32_t rev_id; - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE((clk_dep_table->ucNumEntries != 0), - "Invalid PowerPlay Table!", return -1); - -/* - * workaround needed to add another DPM level for pioneer cards - * as VBIOS is locked down. - * This DPM level was added to support 3DPM monitors @ 4K120Hz - * - */ - dev_id = adev->pdev->device; - rev_id = adev->pdev->revision; - - if (dev_id == 0x6863 && rev_id == 0 && - clk_dep_table->entries[clk_dep_table->ucNumEntries - 1].ulClk < 90000) - num_entries = clk_dep_table->ucNumEntries + 1 > NUM_DSPCLK_LEVELS ? - NUM_DSPCLK_LEVELS : clk_dep_table->ucNumEntries + 1; - else - num_entries = clk_dep_table->ucNumEntries; - - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_clock_voltage_dependency_record) * - num_entries; - - clk_table = kzalloc(table_size, GFP_KERNEL); - - if (!clk_table) - return -ENOMEM; - - clk_table->count = (uint32_t)num_entries; - - for (i = 0; i < clk_dep_table->ucNumEntries; i++) { - clk_table->entries[i].vddInd = - clk_dep_table->entries[i].ucVddInd; - clk_table->entries[i].clk = - le32_to_cpu(clk_dep_table->entries[i].ulClk); - } - - if (i < num_entries) { - clk_table->entries[i].vddInd = clk_dep_table->entries[i-1].ucVddInd; - clk_table->entries[i].clk = 90000; - } - - *pp_vega10_clk_dep_table = clk_table; - - return 0; -} - -static int get_pcie_table(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_pcie_table **vega10_pcie_table, - const Vega10_PPTable_Generic_SubTable_Header *table) -{ - uint32_t table_size, i, pcie_count; - struct phm_ppt_v1_pcie_table *pcie_table; - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - const ATOM_Vega10_PCIE_Table *atom_pcie_table = - (ATOM_Vega10_PCIE_Table *)table; - - PP_ASSERT_WITH_CODE(atom_pcie_table->ucNumEntries, - "Invalid PowerPlay Table!", - return 0); - - table_size = sizeof(uint32_t) + - sizeof(struct phm_ppt_v1_pcie_record) * - atom_pcie_table->ucNumEntries; - - pcie_table = kzalloc(table_size, GFP_KERNEL); - - if (!pcie_table) - return -ENOMEM; - - pcie_count = table_info->vdd_dep_on_sclk->count; - if (atom_pcie_table->ucNumEntries <= pcie_count) - pcie_count = atom_pcie_table->ucNumEntries; - else - pr_info("Number of Pcie Entries exceed the number of" - " GFXCLK Dpm Levels!" - " Disregarding the excess entries...\n"); - - pcie_table->count = pcie_count; - - for (i = 0; i < pcie_count; i++) { - pcie_table->entries[i].gen_speed = - atom_pcie_table->entries[i].ucPCIEGenSpeed; - pcie_table->entries[i].lane_width = - atom_pcie_table->entries[i].ucPCIELaneWidth; - pcie_table->entries[i].pcie_sclk = - atom_pcie_table->entries[i].ulLCLK; - } - - *vega10_pcie_table = pcie_table; - - return 0; -} - -static int get_hard_limits( - struct pp_hwmgr *hwmgr, - struct phm_clock_and_voltage_limits *limits, - const ATOM_Vega10_Hard_Limit_Table *limit_table) -{ - PP_ASSERT_WITH_CODE(limit_table->ucNumEntries, - "Invalid PowerPlay Table!", return -1); - - /* currently we always take entries[0] parameters */ - limits->sclk = le32_to_cpu(limit_table->entries[0].ulSOCCLKLimit); - limits->mclk = le32_to_cpu(limit_table->entries[0].ulMCLKLimit); - limits->gfxclk = le32_to_cpu(limit_table->entries[0].ulGFXCLKLimit); - limits->vddc = le16_to_cpu(limit_table->entries[0].usVddcLimit); - limits->vddci = le16_to_cpu(limit_table->entries[0].usVddciLimit); - limits->vddmem = le16_to_cpu(limit_table->entries[0].usVddMemLimit); - - return 0; -} - -static int get_valid_clk( - struct pp_hwmgr *hwmgr, - struct phm_clock_array **clk_table, - const phm_ppt_v1_clock_voltage_dependency_table *clk_volt_pp_table) -{ - uint32_t table_size, i; - struct phm_clock_array *table; - - PP_ASSERT_WITH_CODE(clk_volt_pp_table->count, - "Invalid PowerPlay Table!", return -1); - - table_size = sizeof(uint32_t) + - sizeof(uint32_t) * clk_volt_pp_table->count; - - table = kzalloc(table_size, GFP_KERNEL); - - if (!table) - return -ENOMEM; - - table->count = (uint32_t)clk_volt_pp_table->count; - - for (i = 0; i < table->count; i++) - table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; - - *clk_table = table; - - return 0; -} - -static int init_powerplay_extended_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) -{ - int result = 0; - struct phm_ppt_v2_information *pp_table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - const ATOM_Vega10_MM_Dependency_Table *mm_dependency_table = - (const ATOM_Vega10_MM_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); - const Vega10_PPTable_Generic_SubTable_Header *power_tune_table = - (const Vega10_PPTable_Generic_SubTable_Header *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); - const ATOM_Vega10_SOCCLK_Dependency_Table *socclk_dep_table = - (const ATOM_Vega10_SOCCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usSocclkDependencyTableOffset)); - const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table = - (const ATOM_Vega10_GFXCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset)); - const ATOM_Vega10_DCEFCLK_Dependency_Table *dcefclk_dep_table = - (const ATOM_Vega10_DCEFCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usDcefclkDependencyTableOffset)); - const ATOM_Vega10_MCLK_Dependency_Table *mclk_dep_table = - (const ATOM_Vega10_MCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); - const ATOM_Vega10_Hard_Limit_Table *hard_limits = - (const ATOM_Vega10_Hard_Limit_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usHardLimitTableOffset)); - const Vega10_PPTable_Generic_SubTable_Header *pcie_table = - (const Vega10_PPTable_Generic_SubTable_Header *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPCIETableOffset)); - const ATOM_Vega10_PIXCLK_Dependency_Table *pixclk_dep_table = - (const ATOM_Vega10_PIXCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPixclkDependencyTableOffset)); - const ATOM_Vega10_PHYCLK_Dependency_Table *phyclk_dep_table = - (const ATOM_Vega10_PHYCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usPhyClkDependencyTableOffset)); - const ATOM_Vega10_DISPCLK_Dependency_Table *dispclk_dep_table = - (const ATOM_Vega10_DISPCLK_Dependency_Table *) - (((unsigned long) powerplay_table) + - le16_to_cpu(powerplay_table->usDispClkDependencyTableOffset)); - - pp_table_info->vdd_dep_on_socclk = NULL; - pp_table_info->vdd_dep_on_sclk = NULL; - pp_table_info->vdd_dep_on_mclk = NULL; - pp_table_info->vdd_dep_on_dcefclk = NULL; - pp_table_info->mm_dep_table = NULL; - pp_table_info->tdp_table = NULL; - pp_table_info->vdd_dep_on_pixclk = NULL; - pp_table_info->vdd_dep_on_phyclk = NULL; - pp_table_info->vdd_dep_on_dispclk = NULL; - - if (powerplay_table->usMMDependencyTableOffset) - result = get_mm_clock_voltage_table(hwmgr, - &pp_table_info->mm_dep_table, - mm_dependency_table); - - if (!result && powerplay_table->usPowerTuneTableOffset) - result = get_tdp_table(hwmgr, - &pp_table_info->tdp_table, - power_tune_table); - - if (!result && powerplay_table->usSocclkDependencyTableOffset) - result = get_socclk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_socclk, - socclk_dep_table); - - if (!result && powerplay_table->usGfxclkDependencyTableOffset) - result = get_gfxclk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_sclk, - gfxclk_dep_table); - - if (!result && powerplay_table->usPixclkDependencyTableOffset) - result = get_pix_clk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_pixclk, - (const ATOM_Vega10_PIXCLK_Dependency_Table*) - pixclk_dep_table); - - if (!result && powerplay_table->usPhyClkDependencyTableOffset) - result = get_pix_clk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_phyclk, - (const ATOM_Vega10_PIXCLK_Dependency_Table *) - phyclk_dep_table); - - if (!result && powerplay_table->usDispClkDependencyTableOffset) - result = get_pix_clk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_dispclk, - (const ATOM_Vega10_PIXCLK_Dependency_Table *) - dispclk_dep_table); - - if (!result && powerplay_table->usDcefclkDependencyTableOffset) - result = get_dcefclk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_dcefclk, - dcefclk_dep_table); - - if (!result && powerplay_table->usMclkDependencyTableOffset) - result = get_mclk_voltage_dependency_table(hwmgr, - &pp_table_info->vdd_dep_on_mclk, - mclk_dep_table); - - if (!result && powerplay_table->usPCIETableOffset) - result = get_pcie_table(hwmgr, - &pp_table_info->pcie_table, - pcie_table); - - if (!result && powerplay_table->usHardLimitTableOffset) - result = get_hard_limits(hwmgr, - &pp_table_info->max_clock_voltage_on_dc, - hard_limits); - - hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = - pp_table_info->max_clock_voltage_on_dc.sclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = - pp_table_info->max_clock_voltage_on_dc.mclk; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = - pp_table_info->max_clock_voltage_on_dc.vddc; - hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = - pp_table_info->max_clock_voltage_on_dc.vddci; - - if (!result && - pp_table_info->vdd_dep_on_socclk && - pp_table_info->vdd_dep_on_socclk->count) - result = get_valid_clk(hwmgr, - &pp_table_info->valid_socclk_values, - pp_table_info->vdd_dep_on_socclk); - - if (!result && - pp_table_info->vdd_dep_on_sclk && - pp_table_info->vdd_dep_on_sclk->count) - result = get_valid_clk(hwmgr, - &pp_table_info->valid_sclk_values, - pp_table_info->vdd_dep_on_sclk); - - if (!result && - pp_table_info->vdd_dep_on_dcefclk && - pp_table_info->vdd_dep_on_dcefclk->count) - result = get_valid_clk(hwmgr, - &pp_table_info->valid_dcefclk_values, - pp_table_info->vdd_dep_on_dcefclk); - - if (!result && - pp_table_info->vdd_dep_on_mclk && - pp_table_info->vdd_dep_on_mclk->count) - result = get_valid_clk(hwmgr, - &pp_table_info->valid_mclk_values, - pp_table_info->vdd_dep_on_mclk); - - return result; -} - -static int get_vddc_lookup_table( - struct pp_hwmgr *hwmgr, - phm_ppt_v1_voltage_lookup_table **lookup_table, - const ATOM_Vega10_Voltage_Lookup_Table *vddc_lookup_pp_tables, - uint32_t max_levels) -{ - uint32_t table_size, i; - phm_ppt_v1_voltage_lookup_table *table; - - PP_ASSERT_WITH_CODE((vddc_lookup_pp_tables->ucNumEntries != 0), - "Invalid SOC_VDDD Lookup Table!", return 1); - - table_size = sizeof(uint32_t) + - sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - - table = kzalloc(table_size, GFP_KERNEL); - - if (table == NULL) - return -ENOMEM; - - table->count = vddc_lookup_pp_tables->ucNumEntries; - - for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) - table->entries[i].us_vdd = - le16_to_cpu(vddc_lookup_pp_tables->entries[i].usVdd); - - *lookup_table = table; - - return 0; -} - -static int init_dpm_2_parameters( - struct pp_hwmgr *hwmgr, - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table) -{ - int result = 0; - struct phm_ppt_v2_information *pp_table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - uint32_t disable_power_control = 0; - - pp_table_info->us_ulv_voltage_offset = - le16_to_cpu(powerplay_table->usUlvVoltageOffset); - - pp_table_info->us_ulv_smnclk_did = - le16_to_cpu(powerplay_table->usUlvSmnclkDid); - pp_table_info->us_ulv_mp1clk_did = - le16_to_cpu(powerplay_table->usUlvMp1clkDid); - pp_table_info->us_ulv_gfxclk_bypass = - le16_to_cpu(powerplay_table->usUlvGfxclkBypass); - pp_table_info->us_gfxclk_slew_rate = - le16_to_cpu(powerplay_table->usGfxclkSlewRate); - pp_table_info->uc_gfx_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucGfxVoltageMode); - pp_table_info->uc_soc_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucSocVoltageMode); - pp_table_info->uc_uclk_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucUclkVoltageMode); - pp_table_info->uc_uvd_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucUvdVoltageMode); - pp_table_info->uc_vce_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucVceVoltageMode); - pp_table_info->uc_mp0_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucMp0VoltageMode); - pp_table_info->uc_dcef_dpm_voltage_mode = - le16_to_cpu(powerplay_table->ucDcefVoltageMode); - - pp_table_info->ppm_parameter_table = NULL; - pp_table_info->vddc_lookup_table = NULL; - pp_table_info->vddmem_lookup_table = NULL; - pp_table_info->vddci_lookup_table = NULL; - - /* TDP limits */ - hwmgr->platform_descriptor.TDPODLimit = - le16_to_cpu(powerplay_table->usPowerControlLimit); - hwmgr->platform_descriptor.TDPAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustment = 0; - hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; - hwmgr->platform_descriptor.VidMinLimit = 0; - hwmgr->platform_descriptor.VidMaxLimit = 1500000; - hwmgr->platform_descriptor.VidStep = 6250; - - disable_power_control = 0; - if (!disable_power_control) { - /* enable TDP overdrive (PowerControl) feature as well if supported */ - if (hwmgr->platform_descriptor.TDPODLimit) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); - } - - if (powerplay_table->usVddcLookupTableOffset) { - const ATOM_Vega10_Voltage_Lookup_Table *vddc_table = - (ATOM_Vega10_Voltage_Lookup_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); - result = get_vddc_lookup_table(hwmgr, - &pp_table_info->vddc_lookup_table, vddc_table, 8); - } - - if (powerplay_table->usVddmemLookupTableOffset) { - const ATOM_Vega10_Voltage_Lookup_Table *vdd_mem_table = - (ATOM_Vega10_Voltage_Lookup_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddmemLookupTableOffset)); - result = get_vddc_lookup_table(hwmgr, - &pp_table_info->vddmem_lookup_table, vdd_mem_table, 4); - } - - if (powerplay_table->usVddciLookupTableOffset) { - const ATOM_Vega10_Voltage_Lookup_Table *vddci_table = - (ATOM_Vega10_Voltage_Lookup_Table *) - (((unsigned long)powerplay_table) + - le16_to_cpu(powerplay_table->usVddciLookupTableOffset)); - result = get_vddc_lookup_table(hwmgr, - &pp_table_info->vddci_lookup_table, vddci_table, 4); - } - - return result; -} - -int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) -{ - int result = 0; - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; - - hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); - - PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), - "Failed to allocate hwmgr->pptable!", return -ENOMEM); - - powerplay_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((powerplay_table != NULL), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_thermal_controller(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_thermal_controller failed", return result); - - result = init_over_drive_limits(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_over_drive_limits failed", return result); - - result = init_powerplay_extended_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_powerplay_extended_tables failed", return result); - - result = init_dpm_2_parameters(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "init_dpm_2_parameters failed", return result); - - return result; -} - -static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v2_information *pp_table_info = - (struct phm_ppt_v2_information *)(hwmgr->pptable); - - kfree(pp_table_info->vdd_dep_on_sclk); - pp_table_info->vdd_dep_on_sclk = NULL; - - kfree(pp_table_info->vdd_dep_on_mclk); - pp_table_info->vdd_dep_on_mclk = NULL; - - kfree(pp_table_info->valid_mclk_values); - pp_table_info->valid_mclk_values = NULL; - - kfree(pp_table_info->valid_sclk_values); - pp_table_info->valid_sclk_values = NULL; - - kfree(pp_table_info->vddc_lookup_table); - pp_table_info->vddc_lookup_table = NULL; - - kfree(pp_table_info->vddmem_lookup_table); - pp_table_info->vddmem_lookup_table = NULL; - - kfree(pp_table_info->vddci_lookup_table); - pp_table_info->vddci_lookup_table = NULL; - - kfree(pp_table_info->ppm_parameter_table); - pp_table_info->ppm_parameter_table = NULL; - - kfree(pp_table_info->mm_dep_table); - pp_table_info->mm_dep_table = NULL; - - kfree(pp_table_info->cac_dtp_table); - pp_table_info->cac_dtp_table = NULL; - - kfree(hwmgr->dyn_state.cac_dtp_table); - hwmgr->dyn_state.cac_dtp_table = NULL; - - kfree(pp_table_info->tdp_table); - pp_table_info->tdp_table = NULL; - - kfree(hwmgr->pptable); - hwmgr->pptable = NULL; - - return 0; -} - -const struct pp_table_func vega10_pptable_funcs = { - .pptable_init = vega10_pp_tables_initialize, - .pptable_fini = vega10_pp_tables_uninitialize, -}; - -int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) -{ - const ATOM_Vega10_State_Array *state_arrays; - const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((pp_table != NULL), - "Missing PowerPlay Table!", return -1); - PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= - ATOM_Vega10_TABLE_REVISION_VEGA10), - "Incorrect PowerPlay table revision!", return -1); - - state_arrays = (ATOM_Vega10_State_Array *)(((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - return (uint32_t)(state_arrays->ucNumEntries); -} - -static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, - uint16_t classification, uint16_t classification2) -{ - uint32_t result = 0; - - if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) - result |= PP_StateClassificationFlag_Boot; - - if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) - result |= PP_StateClassificationFlag_Thermal; - - if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - result |= PP_StateClassificationFlag_LimitedPowerSource; - - if (classification & ATOM_PPLIB_CLASSIFICATION_REST) - result |= PP_StateClassificationFlag_Rest; - - if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) - result |= PP_StateClassificationFlag_Forced; - - if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) - result |= PP_StateClassificationFlag_ACPI; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - result |= PP_StateClassificationFlag_LimitedPowerSource_2; - - return result; -} - -int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, - uint32_t entry_index, struct pp_power_state *power_state, - int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)) -{ - int result = 0; - const ATOM_Vega10_State_Array *state_arrays; - const ATOM_Vega10_State *state_entry; - const ATOM_Vega10_POWERPLAYTABLE *pp_table = - get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", - return -1;); - power_state->classification.bios_index = entry_index; - - if (pp_table->sHeader.format_revision >= - ATOM_Vega10_TABLE_REVISION_VEGA10) { - state_arrays = (ATOM_Vega10_State_Array *) - (((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, - "Invalid PowerPlay Table State Array Offset.", - return -1); - PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, - "Invalid PowerPlay Table State Array.", - return -1); - PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array Entry.", - return -1); - - state_entry = &(state_arrays->states[entry_index]); - - result = call_back_func(hwmgr, (void *)state_entry, power_state, - (void *)pp_table, - make_classification_flags(hwmgr, - le16_to_cpu(state_entry->usClassification), - le16_to_cpu(state_entry->usClassification2))); - } - - if (!result && (power_state->classification.flags & - PP_StateClassificationFlag_Boot)) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); - - return result; -} - -int vega10_baco_set_cap(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - const ATOM_Vega10_POWERPLAYTABLE *powerplay_table; - - powerplay_table = get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE((powerplay_table != NULL), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - set_hw_cap( - hwmgr, - 0 != (le32_to_cpu(powerplay_table->ulPlatformCaps) & ATOM_VEGA10_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO); - return result; -} - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h deleted file mode 100644 index da5fbec9b0cd..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2016 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 VEGA10_PROCESSPPTABLES_H -#define VEGA10_PROCESSPPTABLES_H - -#include "hwmgr.h" - -enum Vega10_I2CLineID { - Vega10_I2CLineID_DDC1 = 0x90, - Vega10_I2CLineID_DDC2 = 0x91, - Vega10_I2CLineID_DDC3 = 0x92, - Vega10_I2CLineID_DDC4 = 0x93, - Vega10_I2CLineID_DDC5 = 0x94, - Vega10_I2CLineID_DDC6 = 0x95, - Vega10_I2CLineID_SCLSDA = 0x96, - Vega10_I2CLineID_DDCVGA = 0x97 -}; - -#define Vega10_I2C_DDC1DATA 0 -#define Vega10_I2C_DDC1CLK 1 -#define Vega10_I2C_DDC2DATA 2 -#define Vega10_I2C_DDC2CLK 3 -#define Vega10_I2C_DDC3DATA 4 -#define Vega10_I2C_DDC3CLK 5 -#define Vega10_I2C_SDA 40 -#define Vega10_I2C_SCL 41 -#define Vega10_I2C_DDC4DATA 65 -#define Vega10_I2C_DDC4CLK 66 -#define Vega10_I2C_DDC5DATA 0x48 -#define Vega10_I2C_DDC5CLK 0x49 -#define Vega10_I2C_DDC6DATA 0x4a -#define Vega10_I2C_DDC6CLK 0x4b -#define Vega10_I2C_DDCVGADATA 0x4c -#define Vega10_I2C_DDCVGACLK 0x4d - -extern const struct pp_table_func vega10_pptable_funcs; -extern int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr); -extern int vega10_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index, - struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)); -extern int vega10_baco_set_cap(struct pp_hwmgr *hwmgr); -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c deleted file mode 100644 index 468bdd6f6697..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright 2016 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 "vega10_thermal.h" -#include "vega10_hwmgr.h" -#include "vega10_smumgr.h" -#include "vega10_ppsmc.h" -#include "vega10_inc.h" -#include "soc15_common.h" -#include "pp_debug.h" - -static int vega10_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) -{ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentRpm, current_rpm); - return 0; -} - -int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info) -{ - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - fan_speed_info->supports_percent_read = true; - fan_speed_info->supports_percent_write = true; - fan_speed_info->min_percent = 0; - fan_speed_info->max_percent = 100; - - if (PP_CAP(PHM_PlatformCaps_FanSpeedInTableIsRPM) && - hwmgr->thermal_controller.fanInfo. - ucTachometerPulsesPerRevolution) { - fan_speed_info->supports_rpm_read = true; - fan_speed_info->supports_rpm_write = true; - fan_speed_info->min_rpm = - hwmgr->thermal_controller.fanInfo.ulMinRPM; - fan_speed_info->max_rpm = - hwmgr->thermal_controller.fanInfo.ulMaxRPM; - } else { - fan_speed_info->min_rpm = 0; - fan_speed_info->max_rpm = 0; - } - - return 0; -} - -int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t *speed) -{ - uint32_t current_rpm; - uint32_t percent = 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - if (vega10_get_current_rpm(hwmgr, ¤t_rpm)) - return -1; - - if (hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM != 0) - percent = current_rpm * 100 / - hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM; - - *speed = percent > 100 ? 100 : percent; - - return 0; -} - -int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t tach_period; - uint32_t crystal_clock_freq; - int result = 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return -1; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - result = vega10_get_current_rpm(hwmgr, speed); - } else { - tach_period = - REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_STATUS), - CG_TACH_STATUS, - TACH_PERIOD); - - if (tach_period == 0) - return -EINVAL; - - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - *speed = 60 * crystal_clock_freq * 10000 / tach_period; - } - - return result; -} - -/** -* Set Fan Speed Control to static mode, -* so that the user can decide what speed to use. -* @param hwmgr the address of the powerplay hardware manager. -* mode the fan control mode, 0 default, 1 by percent, 5, by RPM -* @exception Should always succeed. -*/ -int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (hwmgr->fan_ctrl_is_in_default_mode) { - hwmgr->fan_ctrl_default_mode = - REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, FDO_PWM_MODE); - hwmgr->tmin = - REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TMIN); - hwmgr->fan_ctrl_is_in_default_mode = false; - } - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TMIN, 0)); - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, FDO_PWM_MODE, mode)); - - return 0; -} - -/** -* Reset Fan Speed Control to default mode. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Should always succeed. -*/ -int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (!hwmgr->fan_ctrl_is_in_default_mode) { - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, FDO_PWM_MODE, - hwmgr->fan_ctrl_default_mode)); - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TMIN, - hwmgr->tmin << CG_FDO_CTRL2__TMIN__SHIFT)); - hwmgr->fan_ctrl_is_in_default_mode = true; - } - - return 0; -} - -/** - * @fn vega10_enable_fan_control_feature - * @brief Enables the SMC Fan Control Feature. - * - * @param hwmgr - the address of the powerplay hardware manager. - * @return 0 on success. -1 otherwise. - */ -static int vega10_enable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( - hwmgr, true, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap), - "Attempt to Enable FAN CONTROL feature Failed!", - return -1); - data->smu_features[GNLD_FAN_CONTROL].enabled = true; - } - - return 0; -} - -static int vega10_disable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features( - hwmgr, false, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap), - "Attempt to Enable FAN CONTROL feature Failed!", - return -1); - data->smu_features[GNLD_FAN_CONTROL].enabled = false; - } - - return 0; -} - -int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return -1; - - PP_ASSERT_WITH_CODE(!vega10_enable_fan_control_feature(hwmgr), - "Attempt to Enable SMC FAN CONTROL Feature Failed!", - return -1); - - return 0; -} - - -int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return -1; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - PP_ASSERT_WITH_CODE(!vega10_disable_fan_control_feature(hwmgr), - "Attempt to Disable SMC FAN CONTROL Feature Failed!", - return -1); - } - return 0; -} - -/** -* Set Fan Speed in percent. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (0% - 100%) to be set. -* @exception Fails is the 100% setting appears to be 0. -*/ -int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t speed) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t duty100; - uint32_t duty; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - if (speed > 100) - speed = 100; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega10_fan_ctrl_stop_smc_fan_control(hwmgr); - - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); - - return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); -} - -/** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. -*/ -int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->thermal_controller.fanInfo.bNoFan) - return 0; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - return vega10_fan_ctrl_start_smc_fan_control(hwmgr); - else - return vega10_fan_ctrl_set_default_mode(hwmgr); -} - -/** -* Set Fan Speed in RPM. -* @param hwmgr the address of the powerplay hardware manager. -* @param speed is the percentage value (min - max) to be set. -* @exception Fails is the speed not lie between min and max. -*/ -int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t tach_period; - uint32_t crystal_clock_freq; - int result = 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan || - speed == 0 || - (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || - (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) - return -1; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr); - - if (!result) { - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); - WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), - CG_TACH_CTRL, TARGET_PERIOD, - tach_period)); - } - return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); -} - -/** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int temp; - - temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); - - temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> - CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; - - temp = temp & 0x1ff; - - temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return temp; -} - -/** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ -static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - uint32_t val; - - if (low < range->min) - low = range->min; - if (high > range->max) - high = range->max; - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) & - (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) & - (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - return 0; -} - -/** -* Programs thermal controller one-time setting registers -* -* @param hwmgr The address of the hardware manager. -*/ -static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { - WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), - CG_TACH_CTRL, EDGE_PER_REV, - hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1)); - } - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28)); - - return 0; -} - -/** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct vega10_hwmgr *data = hwmgr->backend; - uint32_t val = 0; - - if (data->smu_features[GNLD_FW_CTF].supported) { - if (data->smu_features[GNLD_FW_CTF].enabled) - printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n"); - - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - true, - data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), - "Attempt to Enable FW CTF feature Failed!", - return -1); - data->smu_features[GNLD_FW_CTF].enabled = true; - } - - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); - - return 0; -} - -/** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ -int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct vega10_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FW_CTF].supported) { - if (!data->smu_features[GNLD_FW_CTF].enabled) - printk("[Thermal_EnableAlert] FW CTF Already disabled!\n"); - - - PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, - false, - data->smu_features[GNLD_FW_CTF].smu_feature_bitmap), - "Attempt to disable FW CTF feature Failed!", - return -1); - data->smu_features[GNLD_FW_CTF].enabled = false; - } - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); - - return 0; -} - -/** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ -int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) -{ - int result = vega10_thermal_disable_alert(hwmgr); - - if (!hwmgr->thermal_controller.fanInfo.bNoFan) - vega10_fan_ctrl_set_default_mode(hwmgr); - - return result; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - int ret; - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *table = &(data->smc_state_table.pp_table); - - if (!data->smu_features[GNLD_FAN_CONTROL].supported) - return 0; - - table->FanMaximumRpm = (uint16_t)hwmgr->thermal_controller. - advanceFanControlParameters.usMaxFanRPM; - table->FanThrottlingRpm = hwmgr->thermal_controller. - advanceFanControlParameters.usFanRPMMaxLimit; - table->FanAcousticLimitRpm = (uint16_t)(hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit); - table->FanTargetTemperature = hwmgr->thermal_controller. - advanceFanControlParameters.usTMax; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanTemperatureTarget, - (uint32_t)table->FanTargetTemperature, - NULL); - - table->FanPwmMin = hwmgr->thermal_controller. - advanceFanControlParameters.usPWMMin * 255 / 100; - table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller. - advanceFanControlParameters.ulTargetGfxClk); - table->FanGainEdge = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainEdge; - table->FanGainHotspot = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainHotspot; - table->FanGainLiquid = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainLiquid; - table->FanGainVrVddc = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainVrVddc; - table->FanGainVrMvdd = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainVrMvdd; - table->FanGainPlx = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainPlx; - table->FanGainHbm = hwmgr->thermal_controller. - advanceFanControlParameters.usFanGainHbm; - table->FanZeroRpmEnable = hwmgr->thermal_controller. - advanceFanControlParameters.ucEnableZeroRPM; - table->FanStopTemp = hwmgr->thermal_controller. - advanceFanControlParameters.usZeroRPMStopTemperature; - table->FanStartTemp = hwmgr->thermal_controller. - advanceFanControlParameters.usZeroRPMStartTemperature; - - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)(&(data->smc_state_table.pp_table)), - PPTABLE, false); - if (ret) - pr_info("Failed to update Fan Control Table in PPTable!"); - - return ret; -} - -int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) -{ - struct vega10_hwmgr *data = hwmgr->backend; - PPTable_t *table = &(data->smc_state_table.pp_table); - int ret; - - if (!data->smu_features[GNLD_FAN_CONTROL].supported) - return 0; - - if (!hwmgr->thermal_controller.advanceFanControlParameters. - usMGpuThrottlingRPMLimit) - return 0; - - table->FanThrottlingRpm = hwmgr->thermal_controller. - advanceFanControlParameters.usMGpuThrottlingRPMLimit; - - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)(&(data->smc_state_table.pp_table)), - PPTABLE, false); - if (ret) { - pr_info("Failed to update fan control table in pptable!"); - return ret; - } - - ret = vega10_disable_fan_control_feature(hwmgr); - if (ret) { - pr_info("Attempt to disable SMC fan control feature failed!"); - return ret; - } - - ret = vega10_enable_fan_control_feature(hwmgr); - if (ret) - pr_info("Attempt to enable SMC fan control feature failed!"); - - return ret; -} - -/** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int vega10_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ -/* If the fantable setup has failed we could have disabled - * PHM_PlatformCaps_MicrocodeFanControl even after - * this function was included in the table. - * Make sure that we still think controlling the fan is OK. -*/ - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega10_fan_ctrl_start_smc_fan_control(hwmgr); - - return 0; -} - - -int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - int ret = 0; - - if (range == NULL) - return -EINVAL; - - vega10_thermal_initialize(hwmgr); - ret = vega10_thermal_set_temperature_range(hwmgr, range); - if (ret) - return -EINVAL; - - vega10_thermal_enable_alert(hwmgr); -/* We should restrict performance levels to low before we halt the SMC. - * On the other hand we are still in boot state when we do this - * so it would be pointless. - * If this assumption changes we have to revisit this table. - */ - ret = vega10_thermal_setup_fan_table(hwmgr); - if (ret) - return -EINVAL; - - vega10_thermal_start_smc_fan_control(hwmgr); - - return 0; -}; - - - - -int vega10_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->thermal_controller.fanInfo.bNoFan) { - vega10_fan_ctrl_set_default_mode(hwmgr); - vega10_fan_ctrl_stop_smc_fan_control(hwmgr); - } - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h deleted file mode 100644 index 4a0ede7c1f07..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2015 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 VEGA10_THERMAL_H -#define VEGA10_THERMAL_H - -#include "hwmgr.h" - -struct vega10_temperature { - uint16_t edge_temp; - uint16_t hot_spot_temp; - uint16_t hbm_temp; - uint16_t vr_soc_temp; - uint16_t vr_mem_temp; - uint16_t liquid1_temp; - uint16_t liquid2_temp; - uint16_t plx_temp; -}; - -#define VEGA10_THERMAL_HIGH_ALERT_MASK 0x1 -#define VEGA10_THERMAL_LOW_ALERT_MASK 0x2 - -#define VEGA10_THERMAL_MINIMUM_TEMP_READING -256 -#define VEGA10_THERMAL_MAXIMUM_TEMP_READING 255 - -#define VEGA10_THERMAL_MINIMUM_ALERT_TEMP 0 -#define VEGA10_THERMAL_MAXIMUM_ALERT_TEMP 255 - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - - -extern int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr); -extern int vega10_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); -extern int vega10_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info); -extern int vega10_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t *speed); -extern int vega10_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); -extern int vega10_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, - uint32_t mode); -extern int vega10_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t speed); -extern int vega10_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); -extern int vega10_thermal_ctrl_uninitialize_thermal_controller( - struct pp_hwmgr *hwmgr); -extern int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, - uint32_t speed); -extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, - uint32_t *speed); -extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); -extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range); -extern int vega10_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr); - - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c deleted file mode 100644 index bc53cce4f32d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "amdgpu.h" -#include "soc15.h" -#include "soc15_hw_ip.h" -#include "vega10_ip_offset.h" -#include "soc15_common.h" -#include "vega12_inc.h" -#include "vega12_ppsmc.h" -#include "vega12_baco.h" - -static const struct soc15_baco_cmd_entry pre_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmBIF_DOORBELL_CNTL_BASE_IDX, mmBIF_DOORBELL_CNTL, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN_MASK, BIF_DOORBELL_CNTL__DOORBELL_MONITOR_EN__SHIFT, 0, 0 }, - { CMD_WRITE, NBIF_HWID, 0, mmBIF_FB_EN_BASE_IDX, mmBIF_FB_EN, 0, 0, 0, 0 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DSTATE_BYPASS_MASK, BACO_CNTL__BACO_DSTATE_BYPASS__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_RST_INTR_MASK_MASK, BACO_CNTL__BACO_RST_INTR_MASK__SHIFT, 0, 1 } -}; - -static const struct soc15_baco_cmd_entry enter_baco_tbl[] = -{ - { CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__SOC_DOMAIN_IDLE_MASK, THM_BACO_CNTL__SOC_DOMAIN_IDLE__SHIFT, 0xffffffff, 0x80000000 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 1 }, - { CMD_DELAY_MS, 0, 0, 0, 5, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 0 }, - { CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, BACO_CNTL__BACO_MODE__SHIFT, 0xffffffff, 0x100 } -}; - -static const struct soc15_baco_cmd_entry exit_baco_tbl[] = -{ - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_POWER_OFF_MASK, BACO_CNTL__BACO_POWER_OFF__SHIFT, 0, 0 }, - { CMD_DELAY_MS, 0, 0, 0, 0, 0, 0, 10, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF_MASK, THM_BACO_CNTL__BACO_SOC_REFCLK_OFF__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ANA_ISO_EN_MASK, THM_BACO_CNTL__BACO_ANA_ISO_EN__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_AEB_ISO_EN_MASK, THM_BACO_CNTL__BACO_AEB_ISO_EN__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_ISO_EN_MASK, THM_BACO_CNTL__BACO_ISO_EN__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_PWROKRAW_CNTL_MASK, THM_BACO_CNTL__BACO_PWROKRAW_CNTL__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SMNCLK_MUX_MASK, THM_BACO_CNTL__BACO_SMNCLK_MUX__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SOC_VDCI_RESET_MASK, THM_BACO_CNTL__BACO_SOC_VDCI_RESET__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, THM_BACO_CNTL__BACO_EXIT__SHIFT, 0, 1 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_RESET_EN_MASK, THM_BACO_CNTL__BACO_RESET_EN__SHIFT, 0, 0 }, - { CMD_WAITFOR, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_EXIT_MASK, 0, 0xffffffff, 0 }, - { CMD_READMODIFYWRITE, THM_HWID, 0, mmTHM_BACO_CNTL_BASE_IDX, mmTHM_BACO_CNTL, THM_BACO_CNTL__BACO_SB_AXI_FENCE_MASK, THM_BACO_CNTL__BACO_SB_AXI_FENCE__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_DUMMY_EN_MASK, BACO_CNTL__BACO_DUMMY_EN__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_BIF_LCLK_SWITCH_MASK, BACO_CNTL__BACO_BIF_LCLK_SWITCH__SHIFT, 0, 0 }, - { CMD_READMODIFYWRITE, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_EN_MASK, BACO_CNTL__BACO_EN__SHIFT, 0, 0 }, - { CMD_WAITFOR, NBIF_HWID, 0, mmRCC_BACO_CNTL_MISC_BASE_IDX, mmBACO_CNTL, BACO_CNTL__BACO_MODE_MASK, 0, 0xffffffff, 0 } -}; - -static const struct soc15_baco_cmd_entry clean_baco_tbl[] = -{ - { CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_6_BASE_IDX, mmBIOS_SCRATCH_6, 0, 0, 0, 0 }, - { CMD_WRITE, NBIF_HWID, 0, mmBIOS_SCRATCH_7_BASE_IDX, mmBIOS_SCRATCH_7, 0, 0, 0, 0 } -}; - -int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - enum BACO_STATE cur_state; - - smu9_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - if (soc15_baco_program_registers(hwmgr, pre_baco_tbl, - ARRAY_SIZE(pre_baco_tbl))) { - if (smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnterBaco, 0, NULL)) - return -EINVAL; - - if (soc15_baco_program_registers(hwmgr, enter_baco_tbl, - ARRAY_SIZE(enter_baco_tbl))) - return 0; - } - } else if (state == BACO_STATE_OUT) { - /* HW requires at least 20ms between regulator off and on */ - msleep(20); - /* Execute Hardware BACO exit sequence */ - if (soc15_baco_program_registers(hwmgr, exit_baco_tbl, - ARRAY_SIZE(exit_baco_tbl))) { - if (soc15_baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return 0; - } - } - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h deleted file mode 100644 index 57b72e5a95ae..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_baco.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __VEGA12_BACO_H__ -#define __VEGA12_BACO_H__ -#include "smu9_baco.h" - -extern int vega12_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c deleted file mode 100644 index f0680dd58508..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ /dev/null @@ -1,2868 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include -#include -#include -#include - -#include "hwmgr.h" -#include "amd_powerplay.h" -#include "vega12_smumgr.h" -#include "hardwaremanager.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "cgs_common.h" -#include "vega12_inc.h" -#include "pppcielanes.h" -#include "vega12_hwmgr.h" -#include "vega12_processpptables.h" -#include "vega12_pptable.h" -#include "vega12_thermal.h" -#include "vega12_ppsmc.h" -#include "pp_debug.h" -#include "amd_pcie_helpers.h" -#include "ppinterrupt.h" -#include "pp_overdriver.h" -#include "pp_thermal.h" -#include "vega12_baco.h" - -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - -#define LINK_WIDTH_MAX 6 -#define LINK_SPEED_MAX 3 -static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; -static int link_speed[] = {25, 50, 80, 160}; - -static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask); -static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr, - uint32_t *clock, - PPCLK_e clock_select, - bool max); - -static void vega12_set_default_registry_data(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - data->gfxclk_average_alpha = PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT; - data->socclk_average_alpha = PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT; - data->uclk_average_alpha = PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT; - data->gfx_activity_average_alpha = PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT; - data->lowest_uclk_reserved_for_ulv = PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT; - - data->display_voltage_mode = PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT; - data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_a = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_b = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_c = PPREGKEY_VEGA12QUADRATICEQUATION_DFLT; - - data->registry_data.disallowed_features = 0x0; - data->registry_data.od_state_in_dc_support = 0; - data->registry_data.thermal_support = 1; - data->registry_data.skip_baco_hardware = 0; - - data->registry_data.log_avfs_param = 0; - data->registry_data.sclk_throttle_low_notification = 1; - data->registry_data.force_dpm_high = 0; - data->registry_data.stable_pstate_sclk_dpm_percentage = 75; - - data->registry_data.didt_support = 0; - if (data->registry_data.didt_support) { - data->registry_data.didt_mode = 6; - data->registry_data.sq_ramping_support = 1; - data->registry_data.db_ramping_support = 0; - data->registry_data.td_ramping_support = 0; - data->registry_data.tcp_ramping_support = 0; - data->registry_data.dbr_ramping_support = 0; - data->registry_data.edc_didt_support = 1; - data->registry_data.gc_didt_support = 0; - data->registry_data.psm_didt_support = 0; - } - - data->registry_data.pcie_lane_override = 0xff; - data->registry_data.pcie_speed_override = 0xff; - data->registry_data.pcie_clock_override = 0xffffffff; - data->registry_data.regulator_hot_gpio_support = 1; - data->registry_data.ac_dc_switch_gpio_support = 0; - data->registry_data.quick_transition_support = 0; - data->registry_data.zrpm_start_temp = 0xffff; - data->registry_data.zrpm_stop_temp = 0xffff; - data->registry_data.odn_feature_enable = 1; - data->registry_data.disable_water_mark = 0; - data->registry_data.disable_pp_tuning = 0; - data->registry_data.disable_xlpp_tuning = 0; - data->registry_data.disable_workload_policy = 0; - data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F; - data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919; - data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A; - data->registry_data.force_workload_policy_mask = 0; - data->registry_data.disable_3d_fs_detection = 0; - data->registry_data.fps_support = 1; - data->registry_data.disable_auto_wattman = 1; - data->registry_data.auto_wattman_debug = 0; - data->registry_data.auto_wattman_sample_period = 100; - data->registry_data.auto_wattman_threshold = 50; -} - -static int vega12_set_features_platform_caps(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - - if (data->vddci_control == VEGA12_VOLTAGE_CONTROL_NONE) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableSMU7ThermalManagement); - - if (adev->pg_flags & AMD_PG_SUPPORT_UVD) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDynamicPowerGating); - } - - if (adev->pg_flags & AMD_PG_SUPPORT_VCE) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UnTabledHardwareInterface); - - if (data->registry_data.odn_feature_enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinACSupport); - else { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6inACSupport); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinACSupport); - } - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ActivityReporting); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM); - - if (data->registry_data.od_state_in_dc_support) { - if (data->registry_data.odn_feature_enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODNinDCSupport); - else { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6inDCSupport); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD6PlusinDCSupport); - } - } - - if (data->registry_data.thermal_support - && data->registry_data.fuzzy_fan_control_support - && hwmgr->thermal_controller.advanceFanControlParameters.usTMax) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODFuzzyFanControlSupport); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPowerManagement); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMC); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalPolicyDelay); - - if (data->registry_data.force_dpm_high) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ExclusiveModeAlwaysHigh); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicUVDState); - - if (data->registry_data.sclk_throttle_low_notification) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification); - - /* power tune caps */ - /* assume disabled */ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtSupport); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtEDCEnable); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GCEDC); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PSM); - - if (data->registry_data.didt_support) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtSupport); - if (data->registry_data.sq_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SQRamping); - if (data->registry_data.db_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRamping); - if (data->registry_data.td_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TDRamping); - if (data->registry_data.tcp_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_TCPRamping); - if (data->registry_data.dbr_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DBRRamping); - if (data->registry_data.edc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DiDtEDCEnable); - if (data->registry_data.gc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_GCEDC); - if (data->registry_data.psm_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PSM); - } - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - - if (data->registry_data.ac_dc_switch_gpio_support) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); - } - - if (data->registry_data.quick_transition_support) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - } - - if (data->lowest_uclk_reserved_for_ulv != PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_LowestUclkReservedForUlv); - if (data->lowest_uclk_reserved_for_ulv == 1) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_LowestUclkReservedForUlv); - } - - if (data->registry_data.custom_fan_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CustomFanControlSupport); - - return 0; -} - -static void vega12_init_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - uint32_t top32, bottom32; - int i; - - data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = - FEATURE_DPM_PREFETCHER_BIT; - data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = - FEATURE_DPM_GFXCLK_BIT; - data->smu_features[GNLD_DPM_UCLK].smu_feature_id = - FEATURE_DPM_UCLK_BIT; - data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = - FEATURE_DPM_SOCCLK_BIT; - data->smu_features[GNLD_DPM_UVD].smu_feature_id = - FEATURE_DPM_UVD_BIT; - data->smu_features[GNLD_DPM_VCE].smu_feature_id = - FEATURE_DPM_VCE_BIT; - data->smu_features[GNLD_ULV].smu_feature_id = - FEATURE_ULV_BIT; - data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = - FEATURE_DPM_MP0CLK_BIT; - data->smu_features[GNLD_DPM_LINK].smu_feature_id = - FEATURE_DPM_LINK_BIT; - data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = - FEATURE_DPM_DCEFCLK_BIT; - data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = - FEATURE_DS_GFXCLK_BIT; - data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = - FEATURE_DS_SOCCLK_BIT; - data->smu_features[GNLD_DS_LCLK].smu_feature_id = - FEATURE_DS_LCLK_BIT; - data->smu_features[GNLD_PPT].smu_feature_id = - FEATURE_PPT_BIT; - data->smu_features[GNLD_TDC].smu_feature_id = - FEATURE_TDC_BIT; - data->smu_features[GNLD_THERMAL].smu_feature_id = - FEATURE_THERMAL_BIT; - data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = - FEATURE_GFX_PER_CU_CG_BIT; - data->smu_features[GNLD_RM].smu_feature_id = - FEATURE_RM_BIT; - data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = - FEATURE_DS_DCEFCLK_BIT; - data->smu_features[GNLD_ACDC].smu_feature_id = - FEATURE_ACDC_BIT; - data->smu_features[GNLD_VR0HOT].smu_feature_id = - FEATURE_VR0HOT_BIT; - data->smu_features[GNLD_VR1HOT].smu_feature_id = - FEATURE_VR1HOT_BIT; - data->smu_features[GNLD_FW_CTF].smu_feature_id = - FEATURE_FW_CTF_BIT; - data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = - FEATURE_LED_DISPLAY_BIT; - data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = - FEATURE_FAN_CONTROL_BIT; - data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; - data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT; - data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT; - data->smu_features[GNLD_ACG].smu_feature_id = FEATURE_ACG_BIT; - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - data->smu_features[i].smu_feature_bitmap = - (uint64_t)(1ULL << data->smu_features[i].smu_feature_id); - data->smu_features[i].allowed = - ((data->registry_data.disallowed_features >> i) & 1) ? - false : true; - } - - /* Get the SN to turn into a Unique ID */ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); - - adev->unique_id = ((uint64_t)bottom32 << 32) | top32; -} - -static int vega12_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int vega12_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - kfree(hwmgr->backend); - hwmgr->backend = NULL; - - return 0; -} - -static int vega12_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct vega12_hwmgr *data; - struct amdgpu_device *adev = hwmgr->adev; - - data = kzalloc(sizeof(struct vega12_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - - vega12_set_default_registry_data(hwmgr); - - data->disable_dpm_mask = 0xff; - data->workload_mask = 0xff; - - /* need to set voltage control types before EVV patching */ - data->vddc_control = VEGA12_VOLTAGE_CONTROL_NONE; - data->mvdd_control = VEGA12_VOLTAGE_CONTROL_NONE; - data->vddci_control = VEGA12_VOLTAGE_CONTROL_NONE; - - data->water_marks_bitmap = 0; - data->avfs_exist = false; - - vega12_set_features_platform_caps(hwmgr); - - vega12_init_dpm_defaults(hwmgr); - - /* Parse pptable data read from VBIOS */ - vega12_set_private_data_based_on_pptable(hwmgr); - - data->is_tlu_enabled = false; - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = - VEGA12_MAX_HARDWARE_POWERLEVELS; - hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; - hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - - hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ - /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ - hwmgr->platform_descriptor.clockStep.engineClock = 500; - hwmgr->platform_descriptor.clockStep.memoryClock = 500; - - data->total_active_cus = adev->gfx.cu_info.number; - /* Setup default Overdrive Fan control settings */ - data->odn_fan_table.target_fan_speed = - hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM; - data->odn_fan_table.target_temperature = - hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature; - data->odn_fan_table.min_performance_clock = - hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit; - data->odn_fan_table.min_fan_limit = - hwmgr->thermal_controller.advanceFanControlParameters.usFanPWMMinLimit * - hwmgr->thermal_controller.fanInfo.ulMaxRPM / 100; - - if (hwmgr->feature_mask & PP_GFXOFF_MASK) - data->gfxoff_controlled_by_driver = true; - else - data->gfxoff_controlled_by_driver = false; - - return result; -} - -static int vega12_init_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - data->low_sclk_interrupt_threshold = 0; - - return 0; -} - -static int vega12_setup_asic_task(struct pp_hwmgr *hwmgr) -{ - PP_ASSERT_WITH_CODE(!vega12_init_sclk_threshold(hwmgr), - "Failed to init sclk threshold!", - return -EINVAL); - - return 0; -} - -/* - * @fn vega12_init_dpm_state - * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. - * - * @param dpm_state - the address of the DPM Table to initiailize. - * @return None. - */ -static void vega12_init_dpm_state(struct vega12_dpm_state *dpm_state) -{ - dpm_state->soft_min_level = 0x0; - dpm_state->soft_max_level = 0xffff; - dpm_state->hard_min_level = 0x0; - dpm_state->hard_max_level = 0xffff; -} - -static int vega12_get_number_of_dpm_level(struct pp_hwmgr *hwmgr, - PPCLK_e clk_id, uint32_t *num_of_levels) -{ - int ret = 0; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmFreqByIndex, - (clk_id << 16 | 0xFF), - num_of_levels); - PP_ASSERT_WITH_CODE(!ret, - "[GetNumOfDpmLevel] failed to get dpm levels!", - return ret); - - return ret; -} - -static int vega12_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr, - PPCLK_e clkID, uint32_t index, uint32_t *clock) -{ - /* - *SMU expects the Clock ID to be in the top 16 bits. - *Lower 16 bits specify the level - */ - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmFreqByIndex, (clkID << 16 | index), - clock) == 0, - "[GetDpmFrequencyByIndex] Failed to get dpm frequency from SMU!", - return -EINVAL); - - return 0; -} - -static int vega12_setup_single_dpm_table(struct pp_hwmgr *hwmgr, - struct vega12_single_dpm_table *dpm_table, PPCLK_e clk_id) -{ - int ret = 0; - uint32_t i, num_of_levels, clk; - - ret = vega12_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels); - PP_ASSERT_WITH_CODE(!ret, - "[SetupSingleDpmTable] failed to get clk levels!", - return ret); - - dpm_table->count = num_of_levels; - - for (i = 0; i < num_of_levels; i++) { - ret = vega12_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk); - PP_ASSERT_WITH_CODE(!ret, - "[SetupSingleDpmTable] failed to get clk of specific level!", - return ret); - dpm_table->dpm_levels[i].value = clk; - dpm_table->dpm_levels[i].enabled = true; - } - - return ret; -} - -/* - * This function is to initialize all DPM state tables - * for SMU based on the dependency table. - * Dynamic state patching function will then trim these - * state tables to the allowed range based - * on the power policy or external client requests, - * such as UVD request, etc. - */ -static int vega12_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) -{ - - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *dpm_table; - int ret = 0; - - memset(&data->dpm_table, 0, sizeof(data->dpm_table)); - - /* socclk */ - dpm_table = &(data->dpm_table.soc_table); - if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get socclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* gfxclk */ - dpm_table = &(data->dpm_table.gfx_table); - if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* memclk */ - dpm_table = &(data->dpm_table.mem_table); - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get memclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* eclk */ - dpm_table = &(data->dpm_table.eclk_table); - if (data->smu_features[GNLD_DPM_VCE].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get eclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* vclk */ - dpm_table = &(data->dpm_table.vclk_table); - if (data->smu_features[GNLD_DPM_UVD].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get vclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* dclk */ - dpm_table = &(data->dpm_table.dclk_table); - if (data->smu_features[GNLD_DPM_UVD].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* dcefclk */ - dpm_table = &(data->dpm_table.dcef_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100; - } - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* pixclk */ - dpm_table = &(data->dpm_table.pixel_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get pixclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* dispclk */ - dpm_table = &(data->dpm_table.display_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dispclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* phyclk */ - dpm_table = &(data->dpm_table.phy_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega12_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get phyclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega12_init_dpm_state(&(dpm_table->dpm_state)); - - /* save a copy of the default DPM table */ - memcpy(&(data->golden_dpm_table), &(data->dpm_table), - sizeof(struct vega12_dpm_table)); - - return 0; -} - -#if 0 -static int vega12_save_default_power_profile(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); - uint32_t min_level; - - hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; - hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; - - /* Optimize compute power profile: Use only highest - * 2 power levels (if more than 2 are available) - */ - if (dpm_table->count > 2) - min_level = dpm_table->count - 2; - else if (dpm_table->count == 2) - min_level = 1; - else - min_level = 0; - - hwmgr->default_compute_power_profile.min_sclk = - dpm_table->dpm_levels[min_level].value; - - hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; - - return 0; -} -#endif - -/** -* Initializes the SMC table and uploads it -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data (PowerState) -* @return always 0 -*/ -static int vega12_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct pp_atomfwctrl_bios_boot_up_values boot_up_values; - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - - result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); - if (!result) { - data->vbios_boot_state.vddc = boot_up_values.usVddc; - data->vbios_boot_state.vddci = boot_up_values.usVddci; - data->vbios_boot_state.mvddc = boot_up_values.usMvddc; - data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; - data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; - data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; - data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; - data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID; - data->vbios_boot_state.eclock = boot_up_values.ulEClk; - data->vbios_boot_state.dclock = boot_up_values.ulDClk; - data->vbios_boot_state.vclock = boot_up_values.ulVClk; - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinDeepSleepDcefclk, - (uint32_t)(data->vbios_boot_state.dcef_clock / 100), - NULL); - } - - memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t)); - - result = smum_smc_table_manager(hwmgr, - (uint8_t *)pp_table, TABLE_PPTABLE, false); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload PPtable!", return result); - - return 0; -} - -static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr) -{ - uint32_t result; - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc, &result) == 0, - "[Run_ACG_BTC] Attempt to run ACG BTC failed!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(result == 1, - "Failed to run ACG BTC!", return -EINVAL); - - return 0; -} - -static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - int i; - uint32_t allowed_features_low = 0, allowed_features_high = 0; - - for (i = 0; i < GNLD_FEATURES_MAX; i++) - if (data->smu_features[i].allowed) - data->smu_features[i].smu_feature_id > 31 ? - (allowed_features_high |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) & 0xFFFFFFFF)) : - (allowed_features_low |= ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) & 0xFFFFFFFF)); - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, - NULL) == 0, - "[SetAllowedFeaturesMask] Attempt to set allowed features mask (high) failed!", - return -1); - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, - NULL) == 0, - "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!", - return -1); - - return 0; -} - -static void vega12_init_powergate_state(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - data->uvd_power_gated = true; - data->vce_power_gated = true; - - if (data->smu_features[GNLD_DPM_UVD].enabled) - data->uvd_power_gated = false; - - if (data->smu_features[GNLD_DPM_VCE].enabled) - data->vce_power_gated = false; -} - -static int vega12_enable_all_smu_features(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, NULL) == 0, - "[EnableAllSMUFeatures] Failed to enable all smu features!", - return -1); - - if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) { - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - } - } - - vega12_init_powergate_state(hwmgr); - - return 0; -} - -static int vega12_disable_all_smu_features(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisableAllSmuFeatures, NULL) == 0, - "[DisableAllSMUFeatures] Failed to disable all smu features!", - return -1); - - if (vega12_get_enabled_smc_features(hwmgr, &features_enabled) == 0) { - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - } - } - - return 0; -} - -static int vega12_odn_initialize_default_settings( - struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int vega12_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, - uint32_t adjust_percent) -{ - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_OverDriveSetPercentage, adjust_percent, - NULL); -} - -static int vega12_power_control_set_level(struct pp_hwmgr *hwmgr) -{ - int adjust_percent, result = 0; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - adjust_percent = - hwmgr->platform_descriptor.TDPAdjustmentPolarity ? - hwmgr->platform_descriptor.TDPAdjustment : - (-1 * hwmgr->platform_descriptor.TDPAdjustment); - result = vega12_set_overdrive_target_percentage(hwmgr, - (uint32_t)adjust_percent); - } - return result; -} - -static int vega12_get_all_clock_ranges_helper(struct pp_hwmgr *hwmgr, - PPCLK_e clkid, struct vega12_clock_range *clock) -{ - /* AC Max */ - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMaxDpmFreq, (clkid << 16), - &(clock->ACMax)) == 0, - "[GetClockRanges] Failed to get max ac clock from SMC!", - return -EINVAL); - - /* AC Min */ - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetMinDpmFreq, (clkid << 16), - &(clock->ACMin)) == 0, - "[GetClockRanges] Failed to get min ac clock from SMC!", - return -EINVAL); - - /* DC Max */ - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDcModeMaxDpmFreq, (clkid << 16), - &(clock->DCMax)) == 0, - "[GetClockRanges] Failed to get max dc clock from SMC!", - return -EINVAL); - - return 0; -} - -static int vega12_get_all_clock_ranges(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t i; - - for (i = 0; i < PPCLK_COUNT; i++) - PP_ASSERT_WITH_CODE(!vega12_get_all_clock_ranges_helper(hwmgr, - i, &(data->clk_range[i])), - "Failed to get clk range from SMC!", - return -EINVAL); - - return 0; -} - -static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int tmp_result, result = 0; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, 0, NULL); - - result = vega12_set_allowed_featuresmask(hwmgr); - PP_ASSERT_WITH_CODE(result == 0, - "[EnableDPMTasks] Failed to set allowed featuresmask!\n", - return result); - - tmp_result = vega12_init_smc_table(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to initialize SMC table!", - result = tmp_result); - - tmp_result = vega12_run_acg_btc(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to run ACG BTC!", - result = tmp_result); - - result = vega12_enable_all_smu_features(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to enable all smu features!", - return result); - - tmp_result = vega12_power_control_set_level(hwmgr); - PP_ASSERT_WITH_CODE(!tmp_result, - "Failed to power control set level!", - result = tmp_result); - - result = vega12_get_all_clock_ranges(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to get all clock ranges!", - return result); - - result = vega12_odn_initialize_default_settings(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to power control set level!", - return result); - - result = vega12_setup_default_dpm_tables(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to setup default DPM tables!", - return result); - return result; -} - -static int vega12_patch_boot_state(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps) -{ - return 0; -} - -static uint32_t vega12_find_lowest_dpm_level( - struct vega12_single_dpm_table *table) -{ - uint32_t i; - - for (i = 0; i < table->count; i++) { - if (table->dpm_levels[i].enabled) - break; - } - - if (i >= table->count) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return i; -} - -static uint32_t vega12_find_highest_dpm_level( - struct vega12_single_dpm_table *table) -{ - int32_t i = 0; - PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, - "[FindHighestDPMLevel] DPM Table has too many entries!", - return MAX_REGULAR_DPM_NUMBER - 1); - - for (i = table->count - 1; i >= 0; i--) { - if (table->dpm_levels[i].enabled) - break; - } - - if (i < 0) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return (uint32_t)i; -} - -static int vega12_upload_dpm_min_level(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = hwmgr->backend; - uint32_t min_freq; - int ret = 0; - - if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { - min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min gfxclk !", - return ret); - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_UCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min memclk !", - return ret); - - min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set hard min memclk !", - return ret); - } - - if (data->smu_features[GNLD_DPM_UVD].enabled) { - min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_VCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min vclk!", - return ret); - - min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_DCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min dclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_VCE].enabled) { - min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_ECLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min eclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { - min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min socclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetHardMinByFreq, - (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set hard min dcefclk!", - return ret); - } - - return ret; - -} - -static int vega12_upload_dpm_max_level(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = hwmgr->backend; - uint32_t max_freq; - int ret = 0; - - if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { - max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max gfxclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_UCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max memclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_UVD].enabled) { - max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_VCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max vclk!", - return ret); - - max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_DCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max dclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_VCE].enabled) { - max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_ECLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max eclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { - max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max socclk!", - return ret); - } - - return ret; -} - -int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_DPM_VCE].supported) { - PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap), - "Attempt to Enable/Disable DPM VCE Failed!", - return -1); - data->smu_features[GNLD_DPM_VCE].enabled = enable; - } - - return 0; -} - -static uint32_t vega12_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t gfx_clk; - - if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) - return -1; - - if (low) - PP_ASSERT_WITH_CODE( - vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false) == 0, - "[GetSclks]: fail to get min PPCLK_GFXCLK\n", - return -1); - else - PP_ASSERT_WITH_CODE( - vega12_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true) == 0, - "[GetSclks]: fail to get max PPCLK_GFXCLK\n", - return -1); - - return (gfx_clk * 100); -} - -static uint32_t vega12_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t mem_clk; - - if (!data->smu_features[GNLD_DPM_UCLK].enabled) - return -1; - - if (low) - PP_ASSERT_WITH_CODE( - vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false) == 0, - "[GetMclks]: fail to get min PPCLK_UCLK\n", - return -1); - else - PP_ASSERT_WITH_CODE( - vega12_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true) == 0, - "[GetMclks]: fail to get max PPCLK_UCLK\n", - return -1); - - return (mem_clk * 100); -} - -static int vega12_get_metrics_table(struct pp_hwmgr *hwmgr, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (bypass_cache || - !data->metrics_time || - time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)(&data->metrics_table), - TABLE_SMU_METRICS, - true); - if (ret) { - pr_info("Failed to export SMU metrics table!\n"); - return ret; - } - data->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); - - return ret; -} - -static int vega12_get_gpu_power(struct pp_hwmgr *hwmgr, uint32_t *query) -{ - SmuMetrics_t metrics_table; - int ret = 0; - - ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *query = metrics_table.CurrSocketPower << 8; - - return ret; -} - -static int vega12_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq) -{ - uint32_t gfx_clk = 0; - - *gfx_freq = 0; - - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16), - &gfx_clk) == 0, - "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!", - return -EINVAL); - - *gfx_freq = gfx_clk * 100; - - return 0; -} - -static int vega12_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq) -{ - uint32_t mem_clk = 0; - - *mclk_freq = 0; - - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16), - &mem_clk) == 0, - "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!", - return -EINVAL); - - *mclk_freq = mem_clk * 100; - - return 0; -} - -static int vega12_get_current_activity_percent( - struct pp_hwmgr *hwmgr, - int idx, - uint32_t *activity_percent) -{ - SmuMetrics_t metrics_table; - int ret = 0; - - ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - switch (idx) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - *activity_percent = metrics_table.AverageGfxActivity; - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - *activity_percent = metrics_table.AverageUclkActivity; - break; - default: - pr_err("Invalid index for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static int vega12_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - SmuMetrics_t metrics_table; - int ret = 0; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = vega12_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = vega12_get_current_mclk_freq(hwmgr, (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_LOAD: - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = vega12_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_TEMP: - *((uint32_t *)value) = vega12_thermal_get_temperature(hwmgr); - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *((uint32_t *)value) = metrics_table.TemperatureHotspot * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega12_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *((uint32_t *)value) = metrics_table.TemperatureHBM * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_UVD_POWER: - *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VCE_POWER: - *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - ret = vega12_get_gpu_power(hwmgr, (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: - ret = vega12_get_enabled_smc_features(hwmgr, (uint64_t *)value); - if (!ret) - *size = 8; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int vega12_notify_smc_display_change(struct pp_hwmgr *hwmgr, - bool has_disp) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_DPM_UCLK].enabled) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetUclkFastSwitch, - has_disp ? 1 : 0, - NULL); - - return 0; -} - -static int vega12_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock_req) -{ - int result = 0; - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - enum amd_pp_clock_type clk_type = clock_req->clock_type; - uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; - PPCLK_e clk_select = 0; - uint32_t clk_request = 0; - - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - switch (clk_type) { - case amd_pp_dcef_clock: - clk_select = PPCLK_DCEFCLK; - break; - case amd_pp_disp_clock: - clk_select = PPCLK_DISPCLK; - break; - case amd_pp_pixel_clock: - clk_select = PPCLK_PIXCLK; - break; - case amd_pp_phy_clock: - clk_select = PPCLK_PHYCLK; - break; - default: - pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); - result = -1; - break; - } - - if (!result) { - clk_request = (clk_select << 16) | clk_freq; - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinByFreq, - clk_request, - NULL); - } - } - - return result; -} - -static int vega12_notify_smc_display_config_after_ps_adjustment( - struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - struct PP_Clocks min_clocks = {0}; - struct pp_display_clock_request clock_req; - - if ((hwmgr->display_config->num_display > 1) && - !hwmgr->display_config->multi_monitor_in_sync && - !hwmgr->display_config->nb_pstate_switch_disable) - vega12_notify_smc_display_change(hwmgr, false); - else - vega12_notify_smc_display_change(hwmgr, true); - - min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; - min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; - min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; - - if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { - clock_req.clock_type = amd_pp_dcef_clock; - clock_req.clock_freq_in_khz = min_clocks.dcefClock/10; - if (!vega12_display_clock_voltage_request(hwmgr, &clock_req)) { - if (data->smu_features[GNLD_DS_DCEFCLK].supported) - PP_ASSERT_WITH_CODE( - !smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcefClockInSR /100, - NULL), - "Attempt to set divider for DCEFCLK Failed!", - return -1); - } else { - pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); - } - } - - return 0; -} - -static int vega12_force_dpm_highest(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - uint32_t soft_level; - - soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_level].value; - - soft_level = vega12_find_highest_dpm_level(&(data->dpm_table.mem_table)); - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_level].value; - - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), - "Failed to upload boot level to highest!", - return -1); - - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -1); - - return 0; -} - -static int vega12_force_dpm_lowest(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t soft_level; - - soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_level].value; - - soft_level = vega12_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_level].value; - - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), - "Failed to upload boot level to highest!", - return -1); - - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), - "Failed to upload dpm max level to highest!", - return -1); - - return 0; - -} - -static int vega12_unforce_dpm_levels(struct pp_hwmgr *hwmgr) -{ - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_min_level(hwmgr), - "Failed to upload DPM Bootup Levels!", - return -1); - - PP_ASSERT_WITH_CODE(!vega12_upload_dpm_max_level(hwmgr), - "Failed to upload DPM Max Levels!", - return -1); - - return 0; -} - -static int vega12_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, - uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); - struct vega12_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); - struct vega12_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); - - *sclk_mask = 0; - *mclk_mask = 0; - *soc_mask = 0; - - if (gfx_dpm_table->count > VEGA12_UMD_PSTATE_GFXCLK_LEVEL && - mem_dpm_table->count > VEGA12_UMD_PSTATE_MCLK_LEVEL && - soc_dpm_table->count > VEGA12_UMD_PSTATE_SOCCLK_LEVEL) { - *sclk_mask = VEGA12_UMD_PSTATE_GFXCLK_LEVEL; - *mclk_mask = VEGA12_UMD_PSTATE_MCLK_LEVEL; - *soc_mask = VEGA12_UMD_PSTATE_SOCCLK_LEVEL; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - *sclk_mask = gfx_dpm_table->count - 1; - *mclk_mask = mem_dpm_table->count - 1; - *soc_mask = soc_dpm_table->count - 1; - } - - return 0; -} - -static void vega12_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - switch (mode) { - case AMD_FAN_CTRL_NONE: - break; - case AMD_FAN_CTRL_MANUAL: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega12_fan_ctrl_stop_smc_fan_control(hwmgr); - break; - case AMD_FAN_CTRL_AUTO: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega12_fan_ctrl_start_smc_fan_control(hwmgr); - break; - default: - break; - } -} - -static int vega12_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask = 0; - uint32_t mclk_mask = 0; - uint32_t soc_mask = 0; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = vega12_force_dpm_highest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = vega12_force_dpm_lowest(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = vega12_unforce_dpm_levels(hwmgr); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = vega12_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); - if (ret) - return ret; - vega12_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); - vega12_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - - return ret; -} - -static uint32_t vega12_get_fan_control_mode(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) - return AMD_FAN_CTRL_MANUAL; - else - return AMD_FAN_CTRL_AUTO; -} - -static int vega12_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ -#if 0 - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_clock_and_voltage_limits *max_limits = - &table_info->max_clock_voltage_on_ac; - - info->engine_max_clock = max_limits->sclk; - info->memory_max_clock = max_limits->mclk; -#endif - return 0; -} - -static int vega12_get_clock_ranges(struct pp_hwmgr *hwmgr, - uint32_t *clock, - PPCLK_e clock_select, - bool max) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (max) - *clock = data->clk_range[clock_select].ACMax; - else - *clock = data->clk_range[clock_select].ACMin; - - return 0; -} - -static int vega12_get_sclks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t ucount; - int i; - struct vega12_single_dpm_table *dpm_table; - - if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) - return -1; - - dpm_table = &(data->dpm_table.gfx_table); - ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? - MAX_NUM_CLOCKS : dpm_table->count; - - for (i = 0; i < ucount; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - - clocks->data[i].latency_in_us = 0; - } - - clocks->num_levels = ucount; - - return 0; -} - -static uint32_t vega12_get_mem_latency(struct pp_hwmgr *hwmgr, - uint32_t clock) -{ - return 25; -} - -static int vega12_get_memclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t ucount; - int i; - struct vega12_single_dpm_table *dpm_table; - if (!data->smu_features[GNLD_DPM_UCLK].enabled) - return -1; - - dpm_table = &(data->dpm_table.mem_table); - ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? - MAX_NUM_CLOCKS : dpm_table->count; - - for (i = 0; i < ucount; i++) { - clocks->data[i].clocks_in_khz = dpm_table->dpm_levels[i].value * 1000; - data->mclk_latency_table.entries[i].frequency = dpm_table->dpm_levels[i].value * 100; - clocks->data[i].latency_in_us = - data->mclk_latency_table.entries[i].latency = - vega12_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); - } - - clocks->num_levels = data->mclk_latency_table.count = ucount; - - return 0; -} - -static int vega12_get_dcefclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t ucount; - int i; - struct vega12_single_dpm_table *dpm_table; - - if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) - return -1; - - - dpm_table = &(data->dpm_table.dcef_table); - ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? - MAX_NUM_CLOCKS : dpm_table->count; - - for (i = 0; i < ucount; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - - clocks->data[i].latency_in_us = 0; - } - - clocks->num_levels = ucount; - - return 0; -} - -static int vega12_get_socclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t ucount; - int i; - struct vega12_single_dpm_table *dpm_table; - - if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) - return -1; - - - dpm_table = &(data->dpm_table.soc_table); - ucount = (dpm_table->count > MAX_NUM_CLOCKS) ? - MAX_NUM_CLOCKS : dpm_table->count; - - for (i = 0; i < ucount; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - - clocks->data[i].latency_in_us = 0; - } - - clocks->num_levels = ucount; - - return 0; - -} - -static int vega12_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - int ret; - - switch (type) { - case amd_pp_sys_clock: - ret = vega12_get_sclks(hwmgr, clocks); - break; - case amd_pp_mem_clock: - ret = vega12_get_memclocks(hwmgr, clocks); - break; - case amd_pp_dcef_clock: - ret = vega12_get_dcefclocks(hwmgr, clocks); - break; - case amd_pp_soc_clock: - ret = vega12_get_socclocks(hwmgr, clocks); - break; - default: - return -EINVAL; - } - - return ret; -} - -static int vega12_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - clocks->num_levels = 0; - - return 0; -} - -static int vega12_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_ranges) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - Watermarks_t *table = &(data->smc_state_table.water_marks_table); - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; - - if (!data->registry_data.disable_water_mark && - data->smu_features[GNLD_DPM_DCEFCLK].supported && - data->smu_features[GNLD_DPM_SOCCLK].supported) { - smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); - data->water_marks_bitmap |= WaterMarksExist; - data->water_marks_bitmap &= ~WaterMarksLoaded; - } - - return 0; -} - -static int vega12_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - uint32_t soft_min_level, soft_max_level, hard_min_level; - int ret = 0; - - switch (type) { - case PP_SCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; - - ret = vega12_upload_dpm_min_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega12_upload_dpm_max_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - break; - - case PP_MCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_levels[soft_min_level].value; - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_max_level].value; - - ret = vega12_upload_dpm_min_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega12_upload_dpm_max_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - break; - - case PP_SOCCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if (soft_max_level >= data->dpm_table.soc_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - soft_max_level, - data->dpm_table.soc_table.count - 1); - return -EINVAL; - } - - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->dpm_table.soc_table.dpm_levels[soft_min_level].value; - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->dpm_table.soc_table.dpm_levels[soft_max_level].value; - - ret = vega12_upload_dpm_min_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega12_upload_dpm_max_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - break; - - case PP_DCEFCLK: - hard_min_level = mask ? (ffs(mask) - 1) : 0; - - if (hard_min_level >= data->dpm_table.dcef_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - hard_min_level, - data->dpm_table.dcef_table.count - 1); - return -EINVAL; - } - - data->dpm_table.dcef_table.dpm_state.hard_min_level = - data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; - - ret = vega12_upload_dpm_min_level(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - //TODO: Setting DCEFCLK max dpm level is not supported - - break; - - case PP_PCIE: - break; - - default: - break; - } - - return 0; -} - -static int vega12_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) -{ - static const char *ppfeature_name[] = { - "DPM_PREFETCHER", - "GFXCLK_DPM", - "UCLK_DPM", - "SOCCLK_DPM", - "UVD_DPM", - "VCE_DPM", - "ULV", - "MP0CLK_DPM", - "LINK_DPM", - "DCEFCLK_DPM", - "GFXCLK_DS", - "SOCCLK_DS", - "LCLK_DS", - "PPT", - "TDC", - "THERMAL", - "GFX_PER_CU_CG", - "RM", - "DCEFCLK_DS", - "ACDC", - "VR0HOT", - "VR1HOT", - "FW_CTF", - "LED_DISPLAY", - "FAN_CONTROL", - "DIDT", - "GFXOFF", - "CG", - "ACG"}; - static const char *output_title[] = { - "FEATURES", - "BITMASK", - "ENABLEMENT"}; - uint64_t features_enabled; - int i; - int ret = 0; - int size = 0; - - ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", - return ret); - - size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); - size += sprintf(buf + size, "%-19s %-22s %s\n", - output_title[0], - output_title[1], - output_title[2]); - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", - ppfeature_name[i], - 1ULL << i, - (features_enabled & (1ULL << i)) ? "Y" : "N"); - } - - return size; -} - -static int vega12_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) -{ - uint64_t features_enabled; - uint64_t features_to_enable; - uint64_t features_to_disable; - int ret = 0; - - if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) - return -EINVAL; - - ret = vega12_get_enabled_smc_features(hwmgr, &features_enabled); - if (ret) - return ret; - - features_to_disable = - features_enabled & ~new_ppfeature_masks; - features_to_enable = - ~features_enabled & new_ppfeature_masks; - - pr_debug("features_to_disable 0x%llx\n", features_to_disable); - pr_debug("features_to_enable 0x%llx\n", features_to_enable); - - if (features_to_disable) { - ret = vega12_enable_smc_features(hwmgr, false, features_to_disable); - if (ret) - return ret; - } - - if (features_to_enable) { - ret = vega12_enable_smc_features(hwmgr, true, features_to_enable); - if (ret) - return ret; - } - - return 0; -} - -static int vega12_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; -} - -static int vega12_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) -{ - uint32_t width_level; - - width_level = vega12_get_current_pcie_link_width_level(hwmgr); - if (width_level > LINK_WIDTH_MAX) - width_level = 0; - - return link_width[width_level]; -} - -static int vega12_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; -} - -static int vega12_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) -{ - uint32_t speed_level; - - speed_level = vega12_get_current_pcie_link_speed_level(hwmgr); - if (speed_level > LINK_SPEED_MAX) - speed_level = 0; - - return link_speed[speed_level]; -} - -static int vega12_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - int i, now, size = 0; - struct pp_clock_levels_with_latency clocks; - - switch (type) { - case PP_SCLK: - PP_ASSERT_WITH_CODE( - vega12_get_current_gfx_clk_freq(hwmgr, &now) == 0, - "Attempt to get current gfx clk Failed!", - return -1); - - PP_ASSERT_WITH_CODE( - vega12_get_sclks(hwmgr, &clocks) == 0, - "Attempt to get gfx clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); - break; - - case PP_MCLK: - PP_ASSERT_WITH_CODE( - vega12_get_current_mclk_freq(hwmgr, &now) == 0, - "Attempt to get current mclk freq Failed!", - return -1); - - PP_ASSERT_WITH_CODE( - vega12_get_memclocks(hwmgr, &clocks) == 0, - "Attempt to get memory clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now / 100) ? "*" : ""); - break; - - case PP_SOCCLK: - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmClockFreq, (PPCLK_SOCCLK << 16), - &now) == 0, - "Attempt to get Current SOCCLK Frequency Failed!", - return -EINVAL); - - PP_ASSERT_WITH_CODE( - vega12_get_socclocks(hwmgr, &clocks) == 0, - "Attempt to get soc clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); - break; - - case PP_DCEFCLK: - PP_ASSERT_WITH_CODE( - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmClockFreq, (PPCLK_DCEFCLK << 16), - &now) == 0, - "Attempt to get Current DCEFCLK Frequency Failed!", - return -EINVAL); - - PP_ASSERT_WITH_CODE( - vega12_get_dcefclocks(hwmgr, &clocks) == 0, - "Attempt to get dcef clk levels Failed!", - return -1); - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz / 1000 == now) ? "*" : ""); - break; - - case PP_PCIE: - break; - - default: - break; - } - return size; -} - -static int vega12_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *dpm_table; - bool vblank_too_short = false; - bool disable_mclk_switching; - uint32_t i, latency; - - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && - !hwmgr->display_config->multi_monitor_in_sync) || - vblank_too_short; - latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; - - /* gfxclk */ - dpm_table = &(data->dpm_table.gfx_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_GFXCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* memclk */ - dpm_table = &(data->dpm_table.mem_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_MCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* honour DAL's UCLK Hardmin */ - if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) - dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; - - /* Hardmin is dependent on displayconfig */ - if (disable_mclk_switching) { - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - for (i = 0; i < data->mclk_latency_table.count - 1; i++) { - if (data->mclk_latency_table.entries[i].latency <= latency) { - if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; - break; - } - } - } - } - - if (hwmgr->display_config->nb_pstate_switch_disable) - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - /* vclk */ - dpm_table = &(data->dpm_table.vclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* dclk */ - dpm_table = &(data->dpm_table.dclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_UVDCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* socclk */ - dpm_table = &(data->dpm_table.soc_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_SOCCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* eclk */ - dpm_table = &(data->dpm_table.eclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA12_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA12_UMD_PSTATE_VCEMCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - return 0; -} - -static int vega12_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, - struct vega12_single_dpm_table *dpm_table) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - PP_ASSERT_WITH_CODE(dpm_table->count > 0, - "[SetUclkToHightestDpmLevel] Dpm table has no entry!", - return -EINVAL); - PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, - "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", - return -EINVAL); - - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, - NULL)), - "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", - return ret); - } - - return ret; -} - -static int vega12_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - int ret = 0; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, 0, - NULL); - - ret = vega12_set_uclk_to_highest_dpm_level(hwmgr, - &data->dpm_table.mem_table); - - return ret; -} - -static int vega12_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - int result = 0; - Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); - - if ((data->water_marks_bitmap & WaterMarksExist) && - !(data->water_marks_bitmap & WaterMarksLoaded)) { - result = smum_smc_table_manager(hwmgr, - (uint8_t *)wm_table, TABLE_WATERMARKS, false); - PP_ASSERT_WITH_CODE(result, "Failed to update WMTABLE!", return EINVAL); - data->water_marks_bitmap |= WaterMarksLoaded; - } - - if ((data->water_marks_bitmap & WaterMarksExist) && - data->smu_features[GNLD_DPM_DCEFCLK].supported && - data->smu_features[GNLD_DPM_SOCCLK].supported) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, hwmgr->display_config->num_display, - NULL); - - return result; -} - -static int vega12_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_DPM_UVD].supported) { - PP_ASSERT_WITH_CODE(!vega12_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap), - "Attempt to Enable/Disable DPM UVD Failed!", - return -1); - data->smu_features[GNLD_DPM_UVD].enabled = enable; - } - - return 0; -} - -static void vega12_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->vce_power_gated == bgate) - return; - - data->vce_power_gated = bgate; - vega12_enable_disable_vce_dpm(hwmgr, !bgate); -} - -static void vega12_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->uvd_power_gated == bgate) - return; - - data->uvd_power_gated = bgate; - vega12_enable_disable_uvd_dpm(hwmgr, !bgate); -} - -static bool -vega12_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - bool is_update_required = false; - - if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) - is_update_required = true; - - if (data->registry_data.gfx_clk_deep_sleep_support) { - if (data->display_timing.min_clock_in_sr != hwmgr->display_config->min_core_set_clock_in_sr) - is_update_required = true; - } - - return is_update_required; -} - -static int vega12_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int tmp_result, result = 0; - - tmp_result = vega12_disable_all_smu_features(hwmgr); - PP_ASSERT_WITH_CODE((tmp_result == 0), - "Failed to disable all smu features!", result = tmp_result); - - return result; -} - -static int vega12_power_off_asic(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - int result; - - result = vega12_disable_dpm_tasks(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "[disable_dpm_tasks] Failed to disable DPM!", - ); - data->water_marks_bitmap &= ~(WaterMarksLoaded); - - return result; -} - -#if 0 -static void vega12_find_min_clock_index(struct pp_hwmgr *hwmgr, - uint32_t *sclk_idx, uint32_t *mclk_idx, - uint32_t min_sclk, uint32_t min_mclk) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_dpm_table *dpm_table = &(data->dpm_table); - uint32_t i; - - for (i = 0; i < dpm_table->gfx_table.count; i++) { - if (dpm_table->gfx_table.dpm_levels[i].enabled && - dpm_table->gfx_table.dpm_levels[i].value >= min_sclk) { - *sclk_idx = i; - break; - } - } - - for (i = 0; i < dpm_table->mem_table.count; i++) { - if (dpm_table->mem_table.dpm_levels[i].enabled && - dpm_table->mem_table.dpm_levels[i].value >= min_mclk) { - *mclk_idx = i; - break; - } - } -} -#endif - -#if 0 -static int vega12_set_power_profile_state(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request) -{ - return 0; -} - -static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); - struct vega12_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.gfx_table); - int value = sclk_table->dpm_levels[sclk_table->count - 1].value; - int golden_value = golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega12_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - return 0; -} - -static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); - struct vega12_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mem_table); - int value = mclk_table->dpm_levels[mclk_table->count - 1].value; - int golden_value = golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value; - - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega12_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) -{ - return 0; -} -#endif - -static int vega12_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrHigh, - virtual_addr_hi, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrLow, - virtual_addr_low, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrHigh, - mc_addr_hi, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrLow, - mc_addr_low, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramSize, - size, - NULL); - return 0; -} - -static int vega12_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *thermal_data) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - - memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); - - thermal_data->max = pp_table->TedgeLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_crit_max = pp_table->ThbmLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int vega12_enable_gfx_off(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->gfxoff_controlled_by_driver) - ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_AllowGfxOff, NULL); - - return ret; -} - -static int vega12_disable_gfx_off(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->gfxoff_controlled_by_driver) - ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_DisallowGfxOff, NULL); - - return ret; -} - -static int vega12_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) -{ - if (enable) - return vega12_enable_gfx_off(hwmgr); - else - return vega12_disable_gfx_off(hwmgr); -} - -static int vega12_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - return 0; -} - -static int vega12_set_mp1_state(struct pp_hwmgr *hwmgr, - enum pp_mp1_state mp1_state) -{ - uint16_t msg; - int ret; - - switch (mp1_state) { - case PP_MP1_STATE_UNLOAD: - msg = PPSMC_MSG_PrepareMp1ForUnload; - break; - case PP_MP1_STATE_SHUTDOWN: - case PP_MP1_STATE_RESET: - case PP_MP1_STATE_NONE: - default: - return 0; - } - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, - "[PrepareMp1] Failed!", - return ret); - - return 0; -} - -static void vega12_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) -{ - memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); - - gpu_metrics->common_header.structure_size = - sizeof(struct gpu_metrics_v1_0); - gpu_metrics->common_header.format_revision = 1; - gpu_metrics->common_header.content_revision = 0; - - gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); -} - -static ssize_t vega12_get_gpu_metrics(struct pp_hwmgr *hwmgr, - void **table) -{ - struct vega12_hwmgr *data = - (struct vega12_hwmgr *)(hwmgr->backend); - struct gpu_metrics_v1_0 *gpu_metrics = - &data->gpu_metrics_table; - SmuMetrics_t metrics; - uint32_t fan_speed_rpm; - int ret; - - ret = vega12_get_metrics_table(hwmgr, &metrics, true); - if (ret) - return ret; - - vega12_init_gpu_metrics_v1_0(gpu_metrics); - - gpu_metrics->temperature_edge = metrics.TemperatureEdge; - gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; - gpu_metrics->temperature_mem = metrics.TemperatureHBM; - gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; - gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; - - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; - gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; - gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; - - gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; - gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; - gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; - gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; - gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - vega12_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); - gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; - - gpu_metrics->pcie_link_width = - vega12_get_current_pcie_link_width(hwmgr); - gpu_metrics->pcie_link_speed = - vega12_get_current_pcie_link_speed(hwmgr); - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v1_0); -} - -static const struct pp_hwmgr_func vega12_hwmgr_funcs = { - .backend_init = vega12_hwmgr_backend_init, - .backend_fini = vega12_hwmgr_backend_fini, - .asic_setup = vega12_setup_asic_task, - .dynamic_state_management_enable = vega12_enable_dpm_tasks, - .dynamic_state_management_disable = vega12_disable_dpm_tasks, - .patch_boot_state = vega12_patch_boot_state, - .get_sclk = vega12_dpm_get_sclk, - .get_mclk = vega12_dpm_get_mclk, - .notify_smc_display_config_after_ps_adjustment = - vega12_notify_smc_display_config_after_ps_adjustment, - .force_dpm_level = vega12_dpm_force_dpm_level, - .stop_thermal_controller = vega12_thermal_stop_thermal_controller, - .get_fan_speed_info = vega12_fan_ctrl_get_fan_speed_info, - .reset_fan_speed_to_default = - vega12_fan_ctrl_reset_fan_speed_to_default, - .get_fan_speed_rpm = vega12_fan_ctrl_get_fan_speed_rpm, - .set_fan_control_mode = vega12_set_fan_control_mode, - .get_fan_control_mode = vega12_get_fan_control_mode, - .read_sensor = vega12_read_sensor, - .get_dal_power_level = vega12_get_dal_power_level, - .get_clock_by_type_with_latency = vega12_get_clock_by_type_with_latency, - .get_clock_by_type_with_voltage = vega12_get_clock_by_type_with_voltage, - .set_watermarks_for_clocks_ranges = vega12_set_watermarks_for_clocks_ranges, - .display_clock_voltage_request = vega12_display_clock_voltage_request, - .force_clock_level = vega12_force_clock_level, - .print_clock_levels = vega12_print_clock_levels, - .apply_clocks_adjust_rules = - vega12_apply_clocks_adjust_rules, - .pre_display_config_changed = - vega12_pre_display_configuration_changed_task, - .display_config_changed = vega12_display_configuration_changed_task, - .powergate_uvd = vega12_power_gate_uvd, - .powergate_vce = vega12_power_gate_vce, - .check_smc_update_required_for_display_configuration = - vega12_check_smc_update_required_for_display_configuration, - .power_off_asic = vega12_power_off_asic, - .disable_smc_firmware_ctf = vega12_thermal_disable_alert, -#if 0 - .set_power_profile_state = vega12_set_power_profile_state, - .get_sclk_od = vega12_get_sclk_od, - .set_sclk_od = vega12_set_sclk_od, - .get_mclk_od = vega12_get_mclk_od, - .set_mclk_od = vega12_set_mclk_od, -#endif - .notify_cac_buffer_info = vega12_notify_cac_buffer_info, - .get_thermal_temperature_range = vega12_get_thermal_temperature_range, - .register_irq_handlers = smu9_register_irq_handlers, - .start_thermal_controller = vega12_start_thermal_controller, - .powergate_gfx = vega12_gfx_off_control, - .get_performance_level = vega12_get_performance_level, - .get_asic_baco_capability = smu9_baco_get_capability, - .get_asic_baco_state = smu9_baco_get_state, - .set_asic_baco_state = vega12_baco_set_state, - .get_ppfeature_status = vega12_get_ppfeature_status, - .set_ppfeature_status = vega12_set_ppfeature_status, - .set_mp1_state = vega12_set_mp1_state, - .get_gpu_metrics = vega12_get_gpu_metrics, -}; - -int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) -{ - hwmgr->hwmgr_func = &vega12_hwmgr_funcs; - hwmgr->pptable_func = &vega12_pptable_funcs; - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h deleted file mode 100644 index aa63ae41942d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.h +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _VEGA12_HWMGR_H_ -#define _VEGA12_HWMGR_H_ - -#include "hwmgr.h" -#include "vega12/smu9_driver_if.h" -#include "ppatomfwctrl.h" - -#define VEGA12_MAX_HARDWARE_POWERLEVELS 2 - -#define WaterMarksExist 1 -#define WaterMarksLoaded 2 - -#define VG12_PSUEDO_NUM_GFXCLK_DPM_LEVELS 16 -#define VG12_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8 -#define VG12_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8 -#define VG12_PSUEDO_NUM_UCLK_DPM_LEVELS 4 - -enum -{ - GNLD_DPM_PREFETCHER = 0, - GNLD_DPM_GFXCLK, - GNLD_DPM_UCLK, - GNLD_DPM_SOCCLK, - GNLD_DPM_UVD, - GNLD_DPM_VCE, - GNLD_ULV, - GNLD_DPM_MP0CLK, - GNLD_DPM_LINK, - GNLD_DPM_DCEFCLK, - GNLD_DS_GFXCLK, - GNLD_DS_SOCCLK, - GNLD_DS_LCLK, - GNLD_PPT, - GNLD_TDC, - GNLD_THERMAL, - GNLD_GFX_PER_CU_CG, - GNLD_RM, - GNLD_DS_DCEFCLK, - GNLD_ACDC, - GNLD_VR0HOT, - GNLD_VR1HOT, - GNLD_FW_CTF, - GNLD_LED_DISPLAY, - GNLD_FAN_CONTROL, - GNLD_DIDT, - GNLD_GFXOFF, - GNLD_CG, - GNLD_ACG, - - GNLD_FEATURES_MAX -}; - - -#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) - -#define SMC_DPM_FEATURES 0x30F - -struct smu_features { - bool supported; - bool enabled; - bool allowed; - uint32_t smu_feature_id; - uint64_t smu_feature_bitmap; -}; - -struct vega12_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -#define VEGA12_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define MAX_REGULAR_DPM_NUMBER 16 -#define MAX_PCIE_CONF 2 -#define VEGA12_MINIMUM_ENGINE_CLOCK 2500 - -struct vega12_dpm_state { - uint32_t soft_min_level; - uint32_t soft_max_level; - uint32_t hard_min_level; - uint32_t hard_max_level; -}; - -struct vega12_single_dpm_table { - uint32_t count; - struct vega12_dpm_state dpm_state; - struct vega12_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega12_odn_dpm_control { - uint32_t count; - uint32_t entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega12_pcie_table { - uint16_t count; - uint8_t pcie_gen[MAX_PCIE_CONF]; - uint8_t pcie_lane[MAX_PCIE_CONF]; - uint32_t lclk[MAX_PCIE_CONF]; -}; - -struct vega12_dpm_table { - struct vega12_single_dpm_table soc_table; - struct vega12_single_dpm_table gfx_table; - struct vega12_single_dpm_table mem_table; - struct vega12_single_dpm_table eclk_table; - struct vega12_single_dpm_table vclk_table; - struct vega12_single_dpm_table dclk_table; - struct vega12_single_dpm_table dcef_table; - struct vega12_single_dpm_table pixel_table; - struct vega12_single_dpm_table display_table; - struct vega12_single_dpm_table phy_table; - struct vega12_pcie_table pcie_table; -}; - -#define VEGA12_MAX_LEAKAGE_COUNT 8 -struct vega12_leakage_voltage { - uint16_t count; - uint16_t leakage_id[VEGA12_MAX_LEAKAGE_COUNT]; - uint16_t actual_voltage[VEGA12_MAX_LEAKAGE_COUNT]; -}; - -struct vega12_display_timing { - uint32_t min_clock_in_sr; - uint32_t num_existing_displays; -}; - -struct vega12_dpmlevel_enable_mask { - uint32_t uvd_dpm_enable_mask; - uint32_t vce_dpm_enable_mask; - uint32_t samu_dpm_enable_mask; - uint32_t sclk_dpm_enable_mask; - uint32_t mclk_dpm_enable_mask; -}; - -struct vega12_vbios_boot_state { - bool bsoc_vddc_lock; - uint8_t uc_cooling_id; - uint16_t vddc; - uint16_t vddci; - uint16_t mvddc; - uint16_t vdd_gfx; - uint32_t gfx_clock; - uint32_t mem_clock; - uint32_t soc_clock; - uint32_t dcef_clock; - uint32_t eclock; - uint32_t dclock; - uint32_t vclock; -}; - -#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 -#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 -#define DPMTABLE_UPDATE_SCLK 0x00000004 -#define DPMTABLE_UPDATE_MCLK 0x00000008 -#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 - -struct vega12_smc_state_table { - uint32_t soc_boot_level; - uint32_t gfx_boot_level; - uint32_t dcef_boot_level; - uint32_t mem_boot_level; - uint32_t uvd_boot_level; - uint32_t vce_boot_level; - uint32_t gfx_max_level; - uint32_t mem_max_level; - uint8_t vr_hot_gpio; - uint8_t ac_dc_gpio; - uint8_t therm_out_gpio; - uint8_t therm_out_polarity; - uint8_t therm_out_mode; - PPTable_t pp_table; - Watermarks_t water_marks_table; - AvfsDebugTable_t avfs_debug_table; - AvfsFuseOverride_t avfs_fuse_override_table; - SmuMetrics_t smu_metrics; - DriverSmuConfig_t driver_smu_config; - DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint; - OverDriveTable_t overdrive_table; -}; - -struct vega12_mclk_latency_entries { - uint32_t frequency; - uint32_t latency; -}; - -struct vega12_mclk_latency_table { - uint32_t count; - struct vega12_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega12_registry_data { - uint64_t disallowed_features; - uint8_t ac_dc_switch_gpio_support; - uint8_t acg_loop_support; - uint8_t clock_stretcher_support; - uint8_t db_ramping_support; - uint8_t didt_mode; - uint8_t didt_support; - uint8_t edc_didt_support; - uint8_t force_dpm_high; - uint8_t fuzzy_fan_control_support; - uint8_t mclk_dpm_key_disabled; - uint8_t od_state_in_dc_support; - uint8_t pcie_lane_override; - uint8_t pcie_speed_override; - uint32_t pcie_clock_override; - uint8_t pcie_dpm_key_disabled; - uint8_t dcefclk_dpm_key_disabled; - uint8_t prefetcher_dpm_key_disabled; - uint8_t quick_transition_support; - uint8_t regulator_hot_gpio_support; - uint8_t master_deep_sleep_support; - uint8_t gfx_clk_deep_sleep_support; - uint8_t sclk_deep_sleep_support; - uint8_t lclk_deep_sleep_support; - uint8_t dce_fclk_deep_sleep_support; - uint8_t sclk_dpm_key_disabled; - uint8_t sclk_throttle_low_notification; - uint8_t skip_baco_hardware; - uint8_t socclk_dpm_key_disabled; - uint8_t sq_ramping_support; - uint8_t tcp_ramping_support; - uint8_t td_ramping_support; - uint8_t dbr_ramping_support; - uint8_t gc_didt_support; - uint8_t psm_didt_support; - uint8_t thermal_support; - uint8_t fw_ctf_enabled; - uint8_t led_dpm_enabled; - uint8_t fan_control_support; - uint8_t ulv_support; - uint8_t odn_feature_enable; - uint8_t disable_water_mark; - uint8_t disable_workload_policy; - uint32_t force_workload_policy_mask; - uint8_t disable_3d_fs_detection; - uint8_t disable_pp_tuning; - uint8_t disable_xlpp_tuning; - uint32_t perf_ui_tuning_profile_turbo; - uint32_t perf_ui_tuning_profile_powerSave; - uint32_t perf_ui_tuning_profile_xl; - uint16_t zrpm_stop_temp; - uint16_t zrpm_start_temp; - uint32_t stable_pstate_sclk_dpm_percentage; - uint8_t fps_support; - uint8_t vr0hot; - uint8_t vr1hot; - uint8_t disable_auto_wattman; - uint32_t auto_wattman_debug; - uint32_t auto_wattman_sample_period; - uint8_t auto_wattman_threshold; - uint8_t log_avfs_param; - uint8_t enable_enginess; - uint8_t custom_fan_support; - uint8_t disable_pcc_limit_control; -}; - -struct vega12_odn_clock_voltage_dependency_table { - uint32_t count; - struct phm_ppt_v1_clock_voltage_dependency_record - entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega12_odn_dpm_table { - struct vega12_odn_dpm_control control_gfxclk_state; - struct vega12_odn_dpm_control control_memclk_state; - struct phm_odn_clock_levels odn_core_clock_dpm_levels; - struct phm_odn_clock_levels odn_memory_clock_dpm_levels; - struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; - struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; - struct vega12_odn_clock_voltage_dependency_table vdd_dependency_on_socclk; - uint32_t odn_mclk_min_limit; -}; - -struct vega12_odn_fan_table { - uint32_t target_fan_speed; - uint32_t target_temperature; - uint32_t min_performance_clock; - uint32_t min_fan_limit; - bool force_fan_pwm; -}; - -struct vega12_clock_range { - uint32_t ACMax; - uint32_t ACMin; - uint32_t DCMax; -}; - -struct vega12_hwmgr { - struct vega12_dpm_table dpm_table; - struct vega12_dpm_table golden_dpm_table; - struct vega12_registry_data registry_data; - struct vega12_vbios_boot_state vbios_boot_state; - struct vega12_mclk_latency_table mclk_latency_table; - - struct vega12_leakage_voltage vddc_leakage; - - uint32_t vddc_control; - struct pp_atomfwctrl_voltage_table vddc_voltage_table; - uint32_t mvdd_control; - struct pp_atomfwctrl_voltage_table mvdd_voltage_table; - uint32_t vddci_control; - struct pp_atomfwctrl_voltage_table vddci_voltage_table; - - uint32_t active_auto_throttle_sources; - uint32_t water_marks_bitmap; - - struct vega12_odn_dpm_table odn_dpm_table; - struct vega12_odn_fan_table odn_fan_table; - - /* ---- General data ---- */ - uint8_t need_update_dpm_table; - - bool cac_enabled; - bool battery_state; - bool is_tlu_enabled; - bool avfs_exist; - - uint32_t low_sclk_interrupt_threshold; - - uint32_t total_active_cus; - - struct vega12_display_timing display_timing; - - /* ---- Vega12 Dyn Register Settings ---- */ - - uint32_t debug_settings; - uint32_t lowest_uclk_reserved_for_ulv; - uint32_t gfxclk_average_alpha; - uint32_t socclk_average_alpha; - uint32_t uclk_average_alpha; - uint32_t gfx_activity_average_alpha; - uint32_t display_voltage_mode; - uint32_t dcef_clk_quad_eqn_a; - uint32_t dcef_clk_quad_eqn_b; - uint32_t dcef_clk_quad_eqn_c; - uint32_t disp_clk_quad_eqn_a; - uint32_t disp_clk_quad_eqn_b; - uint32_t disp_clk_quad_eqn_c; - uint32_t pixel_clk_quad_eqn_a; - uint32_t pixel_clk_quad_eqn_b; - uint32_t pixel_clk_quad_eqn_c; - uint32_t phy_clk_quad_eqn_a; - uint32_t phy_clk_quad_eqn_b; - uint32_t phy_clk_quad_eqn_c; - - /* ---- Thermal Temperature Setting ---- */ - struct vega12_dpmlevel_enable_mask dpm_level_enable_mask; - - /* ---- Power Gating States ---- */ - bool uvd_power_gated; - bool vce_power_gated; - bool samu_power_gated; - bool need_long_memory_training; - - /* Internal settings to apply the application power optimization parameters */ - bool apply_optimized_settings; - uint32_t disable_dpm_mask; - - /* ---- Overdrive next setting ---- */ - uint32_t apply_overdrive_next_settings_mask; - - /* ---- Workload Mask ---- */ - uint32_t workload_mask; - - /* ---- SMU9 ---- */ - uint32_t smu_version; - struct smu_features smu_features[GNLD_FEATURES_MAX]; - struct vega12_smc_state_table smc_state_table; - - struct vega12_clock_range clk_range[PPCLK_COUNT]; - - /* ---- Gfxoff ---- */ - bool gfxoff_controlled_by_driver; - - unsigned long metrics_time; - SmuMetrics_t metrics_table; - struct gpu_metrics_v1_0 gpu_metrics_table; -}; - -#define VEGA12_DPM2_NEAR_TDP_DEC 10 -#define VEGA12_DPM2_ABOVE_SAFE_INC 5 -#define VEGA12_DPM2_BELOW_SAFE_INC 20 - -#define VEGA12_DPM2_LTA_WINDOW_SIZE 7 - -#define VEGA12_DPM2_LTS_TRUNCATE 0 - -#define VEGA12_DPM2_TDP_SAFE_LIMIT_PERCENT 80 - -#define VEGA12_DPM2_MAXPS_PERCENT_M 90 -#define VEGA12_DPM2_MAXPS_PERCENT_H 90 - -#define VEGA12_DPM2_PWREFFICIENCYRATIO_MARGIN 50 - -#define VEGA12_DPM2_SQ_RAMP_MAX_POWER 0x3FFF -#define VEGA12_DPM2_SQ_RAMP_MIN_POWER 0x12 -#define VEGA12_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 -#define VEGA12_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E -#define VEGA12_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF - -#define VEGA12_VOLTAGE_CONTROL_NONE 0x0 -#define VEGA12_VOLTAGE_CONTROL_BY_GPIO 0x1 -#define VEGA12_VOLTAGE_CONTROL_BY_SVID2 0x2 -#define VEGA12_VOLTAGE_CONTROL_MERGED 0x3 -/* To convert to Q8.8 format for firmware */ -#define VEGA12_Q88_FORMAT_CONVERSION_UNIT 256 - -#define VEGA12_UNUSED_GPIO_PIN 0x7F - -#define VEGA12_THERM_OUT_MODE_DISABLE 0x0 -#define VEGA12_THERM_OUT_MODE_THERM_ONLY 0x1 -#define VEGA12_THERM_OUT_MODE_THERM_VRHOT 0x2 - -#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff -#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff - -#define PPVEGA12_VEGA12GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA12_VEGA12SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA12_VEGA12UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA12_VEGA12GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA12_VEGA12LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff -#define PPVEGA12_VEGA12DISPLAYVOLTAGEMODE_DFLT 0xffffffff -#define PPREGKEY_VEGA12QUADRATICEQUATION_DFLT 0xffffffff - -#define VEGA12_UMD_PSTATE_GFXCLK_LEVEL 0x3 -#define VEGA12_UMD_PSTATE_SOCCLK_LEVEL 0x3 -#define VEGA12_UMD_PSTATE_MCLK_LEVEL 0x2 -#define VEGA12_UMD_PSTATE_UVDCLK_LEVEL 0x3 -#define VEGA12_UMD_PSTATE_VCEMCLK_LEVEL 0x3 - -int vega12_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); - -#endif /* _VEGA12_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h deleted file mode 100644 index e6d9e84059e1..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_inc.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef VEGA12_INC_H -#define VEGA12_INC_H - -#include "asic_reg/thm/thm_9_0_default.h" -#include "asic_reg/thm/thm_9_0_offset.h" -#include "asic_reg/thm/thm_9_0_sh_mask.h" - -#include "asic_reg/mp/mp_9_0_offset.h" -#include "asic_reg/mp/mp_9_0_sh_mask.h" - -#include "asic_reg/gc/gc_9_2_1_offset.h" -#include "asic_reg/gc/gc_9_2_1_sh_mask.h" - -#include "asic_reg/nbio/nbio_6_1_offset.h" -#include "asic_reg/nbio/nbio_6_1_offset.h" -#include "asic_reg/nbio/nbio_6_1_sh_mask.h" - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h deleted file mode 100644 index bf4f5095b80d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_pptable.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _VEGA12_PPTABLE_H_ -#define _VEGA12_PPTABLE_H_ - -#pragma pack(push, 1) - -#define ATOM_VEGA12_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_VEGA12_PP_THERMALCONTROLLER_VEGA12 25 - -#define ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY 0x1 -#define ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 -#define ATOM_VEGA12_PP_PLATFORM_CAP_HARDWAREDC 0x4 -#define ATOM_VEGA12_PP_PLATFORM_CAP_BACO 0x8 -#define ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO 0x10 -#define ATOM_VEGA12_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20 - -#define ATOM_VEGA12_TABLE_REVISION_VEGA12 9 - -enum ATOM_VEGA12_ODSETTING_ID { - ATOM_VEGA12_ODSETTING_GFXCLKFMAX = 0, - ATOM_VEGA12_ODSETTING_GFXCLKFMIN, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P1, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P2, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEFREQ_P3, - ATOM_VEGA12_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3, - ATOM_VEGA12_ODSETTING_UCLKFMAX, - ATOM_VEGA12_ODSETTING_POWERPERCENTAGE, - ATOM_VEGA12_ODSETTING_FANRPMMIN, - ATOM_VEGA12_ODSETTING_FANRPMACOUSTICLIMIT, - ATOM_VEGA12_ODSETTING_FANTARGETTEMPERATURE, - ATOM_VEGA12_ODSETTING_OPERATINGTEMPMAX, - ATOM_VEGA12_ODSETTING_COUNT, -}; -typedef enum ATOM_VEGA12_ODSETTING_ID ATOM_VEGA12_ODSETTING_ID; - -enum ATOM_VEGA12_PPCLOCK_ID { - ATOM_VEGA12_PPCLOCK_GFXCLK = 0, - ATOM_VEGA12_PPCLOCK_VCLK, - ATOM_VEGA12_PPCLOCK_DCLK, - ATOM_VEGA12_PPCLOCK_ECLK, - ATOM_VEGA12_PPCLOCK_SOCCLK, - ATOM_VEGA12_PPCLOCK_UCLK, - ATOM_VEGA12_PPCLOCK_DCEFCLK, - ATOM_VEGA12_PPCLOCK_DISPCLK, - ATOM_VEGA12_PPCLOCK_PIXCLK, - ATOM_VEGA12_PPCLOCK_PHYCLK, - ATOM_VEGA12_PPCLOCK_COUNT, -}; -typedef enum ATOM_VEGA12_PPCLOCK_ID ATOM_VEGA12_PPCLOCK_ID; - - -typedef struct _ATOM_VEGA12_POWERPLAYTABLE -{ - struct atom_common_table_header sHeader; - UCHAR ucTableRevision; - USHORT usTableSize; - ULONG ulGoldenPPID; - ULONG ulGoldenRevision; - USHORT usFormatID; - - ULONG ulPlatformCaps; - - UCHAR ucThermalControllerType; - - USHORT usSmallPowerLimit1; - USHORT usSmallPowerLimit2; - USHORT usBoostPowerLimit; - USHORT usODTurboPowerLimit; - USHORT usODPowerSavePowerLimit; - USHORT usSoftwareShutdownTemp; - - ULONG PowerSavingClockMax [ATOM_VEGA12_PPCLOCK_COUNT]; - ULONG PowerSavingClockMin [ATOM_VEGA12_PPCLOCK_COUNT]; - - ULONG ODSettingsMax [ATOM_VEGA12_ODSETTING_COUNT]; - ULONG ODSettingsMin [ATOM_VEGA12_ODSETTING_COUNT]; - - USHORT usReserve[5]; - - PPTable_t smcPPTable; - -} ATOM_Vega12_POWERPLAYTABLE; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c deleted file mode 100644 index 195d8539fbb4..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include -#include -#include - -#include "vega12/smu9_driver_if.h" -#include "vega12_processpptables.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "pp_debug.h" -#include "cgs_common.h" -#include "vega12_pptable.h" - -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, - enum phm_platform_caps cap) -{ - if (enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - -static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) -{ - int index = GetIndexIntoMasterDataTable(powerplayinfo); - - u16 size; - u8 frev, crev; - const void *table_address = hwmgr->soft_pp_table; - - if (!table_address) { - table_address = (ATOM_Vega12_POWERPLAYTABLE *) - smu_atom_get_data_table(hwmgr->adev, index, - &size, &frev, &crev); - - hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ - hwmgr->soft_pp_table_size = size; - } - - return table_address; -} - -static int check_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Vega12_POWERPLAYTABLE *powerplay_table) -{ - PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= - ATOM_VEGA12_TABLE_REVISION_VEGA12), - "Unsupported PPTable format!", return -1); - PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, - "Invalid PowerPlay Table!", return -1); - - return 0; -} - -static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) -{ - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA12_PP_PLATFORM_CAP_BAMACO), - PHM_PlatformCaps_BAMACO); - - return 0; -} - -static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable) -{ - struct pp_atomfwctrl_smc_dpm_parameters smc_dpm_table; - - PP_ASSERT_WITH_CODE( - pp_atomfwctrl_get_smc_dpm_information(hwmgr, &smc_dpm_table) == 0, - "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", - return -1); - - ppsmc_pptable->Liquid1_I2C_address = smc_dpm_table.liquid1_i2c_address; - ppsmc_pptable->Liquid2_I2C_address = smc_dpm_table.liquid2_i2c_address; - ppsmc_pptable->Vr_I2C_address = smc_dpm_table.vr_i2c_address; - ppsmc_pptable->Plx_I2C_address = smc_dpm_table.plx_i2c_address; - - ppsmc_pptable->Liquid_I2C_LineSCL = smc_dpm_table.liquid_i2c_linescl; - ppsmc_pptable->Liquid_I2C_LineSDA = smc_dpm_table.liquid_i2c_linesda; - ppsmc_pptable->Vr_I2C_LineSCL = smc_dpm_table.vr_i2c_linescl; - ppsmc_pptable->Vr_I2C_LineSDA = smc_dpm_table.vr_i2c_linesda; - - ppsmc_pptable->Plx_I2C_LineSCL = smc_dpm_table.plx_i2c_linescl; - ppsmc_pptable->Plx_I2C_LineSDA = smc_dpm_table.plx_i2c_linesda; - ppsmc_pptable->VrSensorPresent = smc_dpm_table.vrsensorpresent; - ppsmc_pptable->LiquidSensorPresent = smc_dpm_table.liquidsensorpresent; - - ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table.maxvoltagestepgfx; - ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table.maxvoltagestepsoc; - - ppsmc_pptable->VddGfxVrMapping = smc_dpm_table.vddgfxvrmapping; - ppsmc_pptable->VddSocVrMapping = smc_dpm_table.vddsocvrmapping; - ppsmc_pptable->VddMem0VrMapping = smc_dpm_table.vddmem0vrmapping; - ppsmc_pptable->VddMem1VrMapping = smc_dpm_table.vddmem1vrmapping; - - ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table.gfxulvphasesheddingmask; - ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table.soculvphasesheddingmask; - - ppsmc_pptable->GfxMaxCurrent = smc_dpm_table.gfxmaxcurrent; - ppsmc_pptable->GfxOffset = smc_dpm_table.gfxoffset; - ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table.padding_telemetrygfx; - - ppsmc_pptable->SocMaxCurrent = smc_dpm_table.socmaxcurrent; - ppsmc_pptable->SocOffset = smc_dpm_table.socoffset; - ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table.padding_telemetrysoc; - - ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table.mem0maxcurrent; - ppsmc_pptable->Mem0Offset = smc_dpm_table.mem0offset; - ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table.padding_telemetrymem0; - - ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table.mem1maxcurrent; - ppsmc_pptable->Mem1Offset = smc_dpm_table.mem1offset; - ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table.padding_telemetrymem1; - - ppsmc_pptable->AcDcGpio = smc_dpm_table.acdcgpio; - ppsmc_pptable->AcDcPolarity = smc_dpm_table.acdcpolarity; - ppsmc_pptable->VR0HotGpio = smc_dpm_table.vr0hotgpio; - ppsmc_pptable->VR0HotPolarity = smc_dpm_table.vr0hotpolarity; - - ppsmc_pptable->VR1HotGpio = smc_dpm_table.vr1hotgpio; - ppsmc_pptable->VR1HotPolarity = smc_dpm_table.vr1hotpolarity; - ppsmc_pptable->Padding1 = smc_dpm_table.padding1; - ppsmc_pptable->Padding2 = smc_dpm_table.padding2; - - ppsmc_pptable->LedPin0 = smc_dpm_table.ledpin0; - ppsmc_pptable->LedPin1 = smc_dpm_table.ledpin1; - ppsmc_pptable->LedPin2 = smc_dpm_table.ledpin2; - - ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table.pllgfxclkspreadenabled; - ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table.pllgfxclkspreadpercent; - ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table.pllgfxclkspreadfreq; - - ppsmc_pptable->UclkSpreadEnabled = 0; - ppsmc_pptable->UclkSpreadPercent = smc_dpm_table.uclkspreadpercent; - ppsmc_pptable->UclkSpreadFreq = smc_dpm_table.uclkspreadfreq; - - ppsmc_pptable->SocclkSpreadEnabled = 0; - ppsmc_pptable->SocclkSpreadPercent = smc_dpm_table.socclkspreadpercent; - ppsmc_pptable->SocclkSpreadFreq = smc_dpm_table.socclkspreadfreq; - - ppsmc_pptable->AcgGfxclkSpreadEnabled = smc_dpm_table.acggfxclkspreadenabled; - ppsmc_pptable->AcgGfxclkSpreadPercent = smc_dpm_table.acggfxclkspreadpercent; - ppsmc_pptable->AcgGfxclkSpreadFreq = smc_dpm_table.acggfxclkspreadfreq; - - ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; - - ppsmc_pptable->Vr2_I2C_address = smc_dpm_table.Vr2_I2C_address; - - return 0; -} - -#define VEGA12_ENGINECLOCK_HARDMAX 198000 -static int init_powerplay_table_information( - struct pp_hwmgr *hwmgr, - const ATOM_Vega12_POWERPLAYTABLE *powerplay_table) -{ - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - uint32_t disable_power_control = 0; - int result; - - hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType; - pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType; - - set_hw_cap(hwmgr, - ATOM_VEGA12_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - - if (le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]) > VEGA12_ENGINECLOCK_HARDMAX) - hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA12_ENGINECLOCK_HARDMAX; - else - hwmgr->platform_descriptor.overdriveLimit.engineClock = - le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]); - hwmgr->platform_descriptor.overdriveLimit.memoryClock = - le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX]); - - phm_copy_overdrive_settings_limits_array(hwmgr, - &pptable_information->od_settings_max, - powerplay_table->ODSettingsMax, - ATOM_VEGA12_ODSETTING_COUNT); - phm_copy_overdrive_settings_limits_array(hwmgr, - &pptable_information->od_settings_min, - powerplay_table->ODSettingsMin, - ATOM_VEGA12_ODSETTING_COUNT); - - /* hwmgr->platformDescriptor.minOverdriveVDDC = 0; - hwmgr->platformDescriptor.maxOverdriveVDDC = 0; - hwmgr->platformDescriptor.overdriveVDDCStep = 0; */ - - if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 - && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport); - - pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1); - pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2); - pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit); - pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit); - pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit); - - pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp); - - hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE]); - - disable_power_control = 0; - if (!disable_power_control) { - /* enable TDP overdrive (PowerControl) feature as well if supported */ - if (hwmgr->platform_descriptor.TDPODLimit) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerControl); - } - - phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT); - phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT); - - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); - if (pptable_information->smc_pptable == NULL) - return -ENOMEM; - - memcpy(pptable_information->smc_pptable, &(powerplay_table->smcPPTable), sizeof(PPTable_t)); - - result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); - - return result; -} - -static int vega12_pp_tables_initialize(struct pp_hwmgr *hwmgr) -{ - int result = 0; - const ATOM_Vega12_POWERPLAYTABLE *powerplay_table; - - hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL); - PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), - "Failed to allocate hwmgr->pptable!", return -ENOMEM); - - powerplay_table = get_powerplay_table(hwmgr); - PP_ASSERT_WITH_CODE((powerplay_table != NULL), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_powerplay_table_information(hwmgr, powerplay_table); - PP_ASSERT_WITH_CODE((result == 0), - "init_powerplay_table_information failed", return result); - - return result; -} - -static int vega12_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v3_information *pp_table_info = - (struct phm_ppt_v3_information *)(hwmgr->pptable); - - kfree(pp_table_info->power_saving_clock_max); - pp_table_info->power_saving_clock_max = NULL; - - kfree(pp_table_info->power_saving_clock_min); - pp_table_info->power_saving_clock_min = NULL; - - kfree(pp_table_info->od_settings_max); - pp_table_info->od_settings_max = NULL; - - kfree(pp_table_info->od_settings_min); - pp_table_info->od_settings_min = NULL; - - kfree(pp_table_info->smc_pptable); - pp_table_info->smc_pptable = NULL; - - kfree(hwmgr->pptable); - hwmgr->pptable = NULL; - - return 0; -} - -const struct pp_table_func vega12_pptable_funcs = { - .pptable_init = vega12_pp_tables_initialize, - .pptable_fini = vega12_pp_tables_uninitialize, -}; - -#if 0 -static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, - uint16_t classification, uint16_t classification2) -{ - uint32_t result = 0; - - if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) - result |= PP_StateClassificationFlag_Boot; - - if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) - result |= PP_StateClassificationFlag_Thermal; - - if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) - result |= PP_StateClassificationFlag_LimitedPowerSource; - - if (classification & ATOM_PPLIB_CLASSIFICATION_REST) - result |= PP_StateClassificationFlag_Rest; - - if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) - result |= PP_StateClassificationFlag_Forced; - - if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) - result |= PP_StateClassificationFlag_ACPI; - - if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) - result |= PP_StateClassificationFlag_LimitedPowerSource_2; - - return result; -} - -int vega12_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, - uint32_t entry_index, struct pp_power_state *power_state, - int (*call_back_func)(struct pp_hwmgr *, void *, - struct pp_power_state *, void *, uint32_t)) -{ - int result = 0; - const ATOM_Vega12_State_Array *state_arrays; - const ATOM_Vega12_State *state_entry; - const ATOM_Vega12_POWERPLAYTABLE *pp_table = - get_powerplay_table(hwmgr); - - PP_ASSERT_WITH_CODE(pp_table, "Missing PowerPlay Table!", - return -1;); - power_state->classification.bios_index = entry_index; - - if (pp_table->sHeader.format_revision >= - ATOM_Vega12_TABLE_REVISION_VEGA12) { - state_arrays = (ATOM_Vega12_State_Array *) - (((unsigned long)pp_table) + - le16_to_cpu(pp_table->usStateArrayOffset)); - - PP_ASSERT_WITH_CODE(pp_table->usStateArrayOffset > 0, - "Invalid PowerPlay Table State Array Offset.", - return -1); - PP_ASSERT_WITH_CODE(state_arrays->ucNumEntries > 0, - "Invalid PowerPlay Table State Array.", - return -1); - PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), - "Invalid PowerPlay Table State Array Entry.", - return -1); - - state_entry = &(state_arrays->states[entry_index]); - - result = call_back_func(hwmgr, (void *)state_entry, power_state, - (void *)pp_table, - make_classification_flags(hwmgr, - le16_to_cpu(state_entry->usClassification), - le16_to_cpu(state_entry->usClassification2))); - } - - if (!result && (power_state->classification.flags & - PP_StateClassificationFlag_Boot)) - result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); - - return result; -} -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h deleted file mode 100644 index 65652ae65929..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef VEGA12_PROCESSPPTABLES_H -#define VEGA12_PROCESSPPTABLES_H - -#include "hwmgr.h" - -enum Vega12_I2CLineID { - Vega12_I2CLineID_DDC1 = 0x90, - Vega12_I2CLineID_DDC2 = 0x91, - Vega12_I2CLineID_DDC3 = 0x92, - Vega12_I2CLineID_DDC4 = 0x93, - Vega12_I2CLineID_DDC5 = 0x94, - Vega12_I2CLineID_DDC6 = 0x95, - Vega12_I2CLineID_SCLSDA = 0x96, - Vega12_I2CLineID_DDCVGA = 0x97 -}; - -#define Vega12_I2C_DDC1DATA 0 -#define Vega12_I2C_DDC1CLK 1 -#define Vega12_I2C_DDC2DATA 2 -#define Vega12_I2C_DDC2CLK 3 -#define Vega12_I2C_DDC3DATA 4 -#define Vega12_I2C_DDC3CLK 5 -#define Vega12_I2C_SDA 40 -#define Vega12_I2C_SCL 41 -#define Vega12_I2C_DDC4DATA 65 -#define Vega12_I2C_DDC4CLK 66 -#define Vega12_I2C_DDC5DATA 0x48 -#define Vega12_I2C_DDC5CLK 0x49 -#define Vega12_I2C_DDC6DATA 0x4a -#define Vega12_I2C_DDC6CLK 0x4b -#define Vega12_I2C_DDCVGADATA 0x4c -#define Vega12_I2C_DDCVGACLK 0x4d - -extern const struct pp_table_func vega12_pptable_funcs; -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c deleted file mode 100644 index c15b9756025d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "vega12_thermal.h" -#include "vega12_hwmgr.h" -#include "vega12_smumgr.h" -#include "vega12_ppsmc.h" -#include "vega12_inc.h" -#include "soc15_common.h" -#include "pp_debug.h" - -static int vega12_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) -{ - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetCurrentRpm, - current_rpm), - "Attempt to get current RPM from SMC Failed!", - return -EINVAL); - - return 0; -} - -int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info) -{ - memset(fan_speed_info, 0, sizeof(*fan_speed_info)); - fan_speed_info->supports_percent_read = false; - fan_speed_info->supports_percent_write = false; - fan_speed_info->supports_rpm_read = true; - fan_speed_info->supports_rpm_write = true; - - return 0; -} - -int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) -{ - *speed = 0; - - return vega12_get_current_rpm(hwmgr, speed); -} - -/** - * @fn vega12_enable_fan_control_feature - * @brief Enables the SMC Fan Control Feature. - * - * @param hwmgr - the address of the powerplay hardware manager. - * @return 0 on success. -1 otherwise. - */ -static int vega12_enable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ -#if 0 - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - PP_ASSERT_WITH_CODE(!vega12_enable_smc_features( - hwmgr, true, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap), - "Attempt to Enable FAN CONTROL feature Failed!", - return -1); - data->smu_features[GNLD_FAN_CONTROL].enabled = true; - } -#endif - return 0; -} - -static int vega12_disable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ -#if 0 - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - PP_ASSERT_WITH_CODE(!vega12_enable_smc_features( - hwmgr, false, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap), - "Attempt to Enable FAN CONTROL feature Failed!", - return -1); - data->smu_features[GNLD_FAN_CONTROL].enabled = false; - } -#endif - return 0; -} - -int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].supported) - PP_ASSERT_WITH_CODE( - !vega12_enable_fan_control_feature(hwmgr), - "Attempt to Enable SMC FAN CONTROL Feature Failed!", - return -1); - - return 0; -} - - -int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].supported) - PP_ASSERT_WITH_CODE(!vega12_disable_fan_control_feature(hwmgr), - "Attempt to Disable SMC FAN CONTROL Feature Failed!", - return -1); - - return 0; -} - -/** -* Reset Fan Speed to default. -* @param hwmgr the address of the powerplay hardware manager. -* @exception Always succeeds. -*/ -int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) -{ - return vega12_fan_ctrl_start_smc_fan_control(hwmgr); -} - -/** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int temp = 0; - - temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); - - temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> - CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; - - temp = temp & 0x1ff; - - temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - return temp; -} - -/** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ -static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - uint32_t val; - - if (low < range->min) - low = range->min; - if (high > range->max) - high = range->max; - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - return 0; -} - -/** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -static int vega12_thermal_enable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t val = 0; - - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); - - return 0; -} - -/** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ -int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); - - return 0; -} - -/** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ -int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) -{ - int result = vega12_thermal_disable_alert(hwmgr); - - return result; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int vega12_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - int ret; - struct vega12_hwmgr *data = (struct vega12_hwmgr *)(hwmgr->backend); - PPTable_t *table = &(data->smc_state_table.pp_table); - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanTemperatureTarget, - (uint32_t)table->FanTargetTemperature, - NULL); - - return ret; -} - -/** -* Start the fan control on the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int vega12_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - /* If the fantable setup has failed we could have disabled - * PHM_PlatformCaps_MicrocodeFanControl even after - * this function was included in the table. - * Make sure that we still think controlling the fan is OK. - */ - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega12_fan_ctrl_start_smc_fan_control(hwmgr); - - return 0; -} - - -int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - int ret = 0; - - if (range == NULL) - return -EINVAL; - - ret = vega12_thermal_set_temperature_range(hwmgr, range); - if (ret) - return -EINVAL; - - vega12_thermal_enable_alert(hwmgr); - /* We should restrict performance levels to low before we halt the SMC. - * On the other hand we are still in boot state when we do this - * so it would be pointless. - * If this assumption changes we have to revisit this table. - */ - ret = vega12_thermal_setup_fan_table(hwmgr); - if (ret) - return -EINVAL; - - vega12_thermal_start_smc_fan_control(hwmgr); - - return 0; -}; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h deleted file mode 100644 index 0d8ed039ab12..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef VEGA12_THERMAL_H -#define VEGA12_THERMAL_H - -#include "hwmgr.h" - -struct vega12_temperature { - uint16_t edge_temp; - uint16_t hot_spot_temp; - uint16_t hbm_temp; - uint16_t vr_soc_temp; - uint16_t vr_mem_temp; - uint16_t liquid1_temp; - uint16_t liquid2_temp; - uint16_t plx_temp; -}; - -#define VEGA12_THERMAL_HIGH_ALERT_MASK 0x1 -#define VEGA12_THERMAL_LOW_ALERT_MASK 0x2 - -#define VEGA12_THERMAL_MINIMUM_TEMP_READING -256 -#define VEGA12_THERMAL_MAXIMUM_TEMP_READING 255 - -#define VEGA12_THERMAL_MINIMUM_ALERT_TEMP 0 -#define VEGA12_THERMAL_MAXIMUM_ALERT_TEMP 255 - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -extern int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr); -extern int vega12_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); -extern int vega12_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info); -extern int vega12_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); -extern int vega12_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, - uint32_t *speed); -extern int vega12_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega12_thermal_disable_alert(struct pp_hwmgr *hwmgr); -extern int vega12_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega12_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c deleted file mode 100644 index 2a28c9df15a0..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2018 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 "amdgpu.h" -#include "soc15.h" -#include "soc15_hw_ip.h" -#include "soc15_common.h" -#include "vega20_inc.h" -#include "vega20_ppsmc.h" -#include "vega20_baco.h" -#include "vega20_smumgr.h" - -#include "amdgpu_ras.h" - -static const struct soc15_baco_cmd_entry clean_baco_tbl[] = -{ - {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_6), 0, 0, 0, 0}, - {CMD_WRITE, SOC15_REG_ENTRY(NBIF, 0, mmBIOS_SCRATCH_7), 0, 0, 0, 0}, -}; - -int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - uint32_t reg; - - *cap = false; - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_BACO)) - return 0; - - if (((RREG32(0x17569) & 0x20000000) >> 29) == 0x1) { - reg = RREG32_SOC15(NBIF, 0, mmRCC_BIF_STRAP0); - - if (reg & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) - *cap = true; - } - - return 0; -} - -int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - uint32_t reg; - - reg = RREG32_SOC15(NBIF, 0, mmBACO_CNTL); - - if (reg & BACO_CNTL__BACO_MODE_MASK) - /* gfx has already entered BACO state */ - *state = BACO_STATE_IN; - else - *state = BACO_STATE_OUT; - return 0; -} - -int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - enum BACO_STATE cur_state; - uint32_t data; - - vega20_baco_get_state(hwmgr, &cur_state); - - if (cur_state == state) - /* aisc already in the target state */ - return 0; - - if (state == BACO_STATE_IN) { - if (!ras || !ras->supported) { - data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); - data |= 0x80000000; - WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); - - if(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnterBaco, 0, NULL)) - return -EINVAL; - } else { - if(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnterBaco, 1, NULL)) - return -EINVAL; - } - - } else if (state == BACO_STATE_OUT) { - if (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ExitBaco, NULL)) - return -EINVAL; - if (!soc15_baco_program_registers(hwmgr, clean_baco_tbl, - ARRAY_SIZE(clean_baco_tbl))) - return -EINVAL; - } - - return 0; -} - -int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - ret = vega20_set_pptable_driver_address(hwmgr); - if (ret) - return ret; - - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_BacoWorkAroundFlushVDCI, NULL); -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h deleted file mode 100644 index f06471e712dc..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_baco.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2018 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 __VEGA20_BACO_H__ -#define __VEGA20_BACO_H__ -#include "hwmgr.h" -#include "common_baco.h" - -extern int vega20_baco_get_capability(struct pp_hwmgr *hwmgr, bool *cap); -extern int vega20_baco_get_state(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); -extern int vega20_baco_set_state(struct pp_hwmgr *hwmgr, enum BACO_STATE state); -extern int vega20_baco_apply_vdci_flush_workaround(struct pp_hwmgr *hwmgr); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c deleted file mode 100644 index c7216362b68d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ /dev/null @@ -1,4409 +0,0 @@ -/* - * Copyright 2018 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 -#include -#include -#include - -#include "hwmgr.h" -#include "amd_powerplay.h" -#include "vega20_smumgr.h" -#include "hardwaremanager.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "cgs_common.h" -#include "vega20_powertune.h" -#include "vega20_inc.h" -#include "pppcielanes.h" -#include "vega20_hwmgr.h" -#include "vega20_processpptables.h" -#include "vega20_pptable.h" -#include "vega20_thermal.h" -#include "vega20_ppsmc.h" -#include "pp_debug.h" -#include "amd_pcie_helpers.h" -#include "ppinterrupt.h" -#include "pp_overdriver.h" -#include "pp_thermal.h" -#include "soc15_common.h" -#include "vega20_baco.h" -#include "smuio/smuio_9_0_offset.h" -#include "smuio/smuio_9_0_sh_mask.h" -#include "nbio/nbio_7_4_sh_mask.h" - -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 - -#define LINK_WIDTH_MAX 6 -#define LINK_SPEED_MAX 3 -static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; -static int link_speed[] = {25, 50, 80, 160}; - -static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - - data->gfxclk_average_alpha = PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT; - data->socclk_average_alpha = PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT; - data->uclk_average_alpha = PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT; - data->gfx_activity_average_alpha = PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT; - data->lowest_uclk_reserved_for_ulv = PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT; - - data->display_voltage_mode = PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT; - data->dcef_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->dcef_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->disp_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->pixel_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_a = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; - - /* - * Disable the following features for now: - * GFXCLK DS - * SOCLK DS - * LCLK DS - * DCEFCLK DS - * FCLK DS - * MP1CLK DS - * MP0CLK DS - */ - data->registry_data.disallowed_features = 0xE0041C00; - /* ECC feature should be disabled on old SMUs */ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version); - if (hwmgr->smu_version < 0x282100) - data->registry_data.disallowed_features |= FEATURE_ECC_MASK; - - if (!(hwmgr->feature_mask & PP_PCIE_DPM_MASK)) - data->registry_data.disallowed_features |= FEATURE_DPM_LINK_MASK; - - if (!(hwmgr->feature_mask & PP_SCLK_DPM_MASK)) - data->registry_data.disallowed_features |= FEATURE_DPM_GFXCLK_MASK; - - if (!(hwmgr->feature_mask & PP_SOCCLK_DPM_MASK)) - data->registry_data.disallowed_features |= FEATURE_DPM_SOCCLK_MASK; - - if (!(hwmgr->feature_mask & PP_MCLK_DPM_MASK)) - data->registry_data.disallowed_features |= FEATURE_DPM_UCLK_MASK; - - if (!(hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK)) - data->registry_data.disallowed_features |= FEATURE_DPM_DCEFCLK_MASK; - - if (!(hwmgr->feature_mask & PP_ULV_MASK)) - data->registry_data.disallowed_features |= FEATURE_ULV_MASK; - - if (!(hwmgr->feature_mask & PP_SCLK_DEEP_SLEEP_MASK)) - data->registry_data.disallowed_features |= FEATURE_DS_GFXCLK_MASK; - - data->registry_data.od_state_in_dc_support = 0; - data->registry_data.thermal_support = 1; - data->registry_data.skip_baco_hardware = 0; - - data->registry_data.log_avfs_param = 0; - data->registry_data.sclk_throttle_low_notification = 1; - data->registry_data.force_dpm_high = 0; - data->registry_data.stable_pstate_sclk_dpm_percentage = 75; - - data->registry_data.didt_support = 0; - if (data->registry_data.didt_support) { - data->registry_data.didt_mode = 6; - data->registry_data.sq_ramping_support = 1; - data->registry_data.db_ramping_support = 0; - data->registry_data.td_ramping_support = 0; - data->registry_data.tcp_ramping_support = 0; - data->registry_data.dbr_ramping_support = 0; - data->registry_data.edc_didt_support = 1; - data->registry_data.gc_didt_support = 0; - data->registry_data.psm_didt_support = 0; - } - - data->registry_data.pcie_lane_override = 0xff; - data->registry_data.pcie_speed_override = 0xff; - data->registry_data.pcie_clock_override = 0xffffffff; - data->registry_data.regulator_hot_gpio_support = 1; - data->registry_data.ac_dc_switch_gpio_support = 0; - data->registry_data.quick_transition_support = 0; - data->registry_data.zrpm_start_temp = 0xffff; - data->registry_data.zrpm_stop_temp = 0xffff; - data->registry_data.od8_feature_enable = 1; - data->registry_data.disable_water_mark = 0; - data->registry_data.disable_pp_tuning = 0; - data->registry_data.disable_xlpp_tuning = 0; - data->registry_data.disable_workload_policy = 0; - data->registry_data.perf_ui_tuning_profile_turbo = 0x19190F0F; - data->registry_data.perf_ui_tuning_profile_powerSave = 0x19191919; - data->registry_data.perf_ui_tuning_profile_xl = 0x00000F0A; - data->registry_data.force_workload_policy_mask = 0; - data->registry_data.disable_3d_fs_detection = 0; - data->registry_data.fps_support = 1; - data->registry_data.disable_auto_wattman = 1; - data->registry_data.auto_wattman_debug = 0; - data->registry_data.auto_wattman_sample_period = 100; - data->registry_data.fclk_gfxclk_ratio = 0; - data->registry_data.auto_wattman_threshold = 50; - data->registry_data.gfxoff_controlled_by_driver = 1; - data->gfxoff_allowed = false; - data->counter_gfxoff = 0; -} - -static int vega20_set_features_platform_caps(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - - if (data->vddci_control == VEGA20_VOLTAGE_CONTROL_NONE) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ControlVDDCI); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TablelessHardwareInterface); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_BACO); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EnableSMU7ThermalManagement); - - if (adev->pg_flags & AMD_PG_SUPPORT_UVD) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating); - - if (adev->pg_flags & AMD_PG_SUPPORT_VCE) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UnTabledHardwareInterface); - - if (data->registry_data.od8_feature_enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD8inACSupport); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ActivityReporting); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_FanSpeedInTableIsRPM); - - if (data->registry_data.od_state_in_dc_support) { - if (data->registry_data.od8_feature_enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_OD8inDCSupport); - } - - if (data->registry_data.thermal_support && - data->registry_data.fuzzy_fan_control_support && - hwmgr->thermal_controller.advanceFanControlParameters.usTMax) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ODFuzzyFanControlSupport); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicPowerManagement); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMC); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalPolicyDelay); - - if (data->registry_data.force_dpm_high) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ExclusiveModeAlwaysHigh); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DynamicUVDState); - - if (data->registry_data.sclk_throttle_low_notification) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification); - - /* power tune caps */ - /* assume disabled */ - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtSupport); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRRamping); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtEDCEnable); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GCEDC); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PSM); - - if (data->registry_data.didt_support) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtSupport); - if (data->registry_data.sq_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SQRamping); - if (data->registry_data.db_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRamping); - if (data->registry_data.td_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TDRamping); - if (data->registry_data.tcp_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_TCPRamping); - if (data->registry_data.dbr_ramping_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DBRRamping); - if (data->registry_data.edc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_DiDtEDCEnable); - if (data->registry_data.gc_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_GCEDC); - if (data->registry_data.psm_didt_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PSM); - } - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - - if (data->registry_data.ac_dc_switch_gpio_support) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); - } - - if (data->registry_data.quick_transition_support) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - } - - if (data->lowest_uclk_reserved_for_ulv != PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_LowestUclkReservedForUlv); - if (data->lowest_uclk_reserved_for_ulv == 1) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_LowestUclkReservedForUlv); - } - - if (data->registry_data.custom_fan_support) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CustomFanControlSupport); - - return 0; -} - -static void vega20_init_dpm_defaults(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - uint32_t top32, bottom32; - int i; - - data->smu_features[GNLD_DPM_PREFETCHER].smu_feature_id = - FEATURE_DPM_PREFETCHER_BIT; - data->smu_features[GNLD_DPM_GFXCLK].smu_feature_id = - FEATURE_DPM_GFXCLK_BIT; - data->smu_features[GNLD_DPM_UCLK].smu_feature_id = - FEATURE_DPM_UCLK_BIT; - data->smu_features[GNLD_DPM_SOCCLK].smu_feature_id = - FEATURE_DPM_SOCCLK_BIT; - data->smu_features[GNLD_DPM_UVD].smu_feature_id = - FEATURE_DPM_UVD_BIT; - data->smu_features[GNLD_DPM_VCE].smu_feature_id = - FEATURE_DPM_VCE_BIT; - data->smu_features[GNLD_ULV].smu_feature_id = - FEATURE_ULV_BIT; - data->smu_features[GNLD_DPM_MP0CLK].smu_feature_id = - FEATURE_DPM_MP0CLK_BIT; - data->smu_features[GNLD_DPM_LINK].smu_feature_id = - FEATURE_DPM_LINK_BIT; - data->smu_features[GNLD_DPM_DCEFCLK].smu_feature_id = - FEATURE_DPM_DCEFCLK_BIT; - data->smu_features[GNLD_DS_GFXCLK].smu_feature_id = - FEATURE_DS_GFXCLK_BIT; - data->smu_features[GNLD_DS_SOCCLK].smu_feature_id = - FEATURE_DS_SOCCLK_BIT; - data->smu_features[GNLD_DS_LCLK].smu_feature_id = - FEATURE_DS_LCLK_BIT; - data->smu_features[GNLD_PPT].smu_feature_id = - FEATURE_PPT_BIT; - data->smu_features[GNLD_TDC].smu_feature_id = - FEATURE_TDC_BIT; - data->smu_features[GNLD_THERMAL].smu_feature_id = - FEATURE_THERMAL_BIT; - data->smu_features[GNLD_GFX_PER_CU_CG].smu_feature_id = - FEATURE_GFX_PER_CU_CG_BIT; - data->smu_features[GNLD_RM].smu_feature_id = - FEATURE_RM_BIT; - data->smu_features[GNLD_DS_DCEFCLK].smu_feature_id = - FEATURE_DS_DCEFCLK_BIT; - data->smu_features[GNLD_ACDC].smu_feature_id = - FEATURE_ACDC_BIT; - data->smu_features[GNLD_VR0HOT].smu_feature_id = - FEATURE_VR0HOT_BIT; - data->smu_features[GNLD_VR1HOT].smu_feature_id = - FEATURE_VR1HOT_BIT; - data->smu_features[GNLD_FW_CTF].smu_feature_id = - FEATURE_FW_CTF_BIT; - data->smu_features[GNLD_LED_DISPLAY].smu_feature_id = - FEATURE_LED_DISPLAY_BIT; - data->smu_features[GNLD_FAN_CONTROL].smu_feature_id = - FEATURE_FAN_CONTROL_BIT; - data->smu_features[GNLD_DIDT].smu_feature_id = FEATURE_GFX_EDC_BIT; - data->smu_features[GNLD_GFXOFF].smu_feature_id = FEATURE_GFXOFF_BIT; - data->smu_features[GNLD_CG].smu_feature_id = FEATURE_CG_BIT; - data->smu_features[GNLD_DPM_FCLK].smu_feature_id = FEATURE_DPM_FCLK_BIT; - data->smu_features[GNLD_DS_FCLK].smu_feature_id = FEATURE_DS_FCLK_BIT; - data->smu_features[GNLD_DS_MP1CLK].smu_feature_id = FEATURE_DS_MP1CLK_BIT; - data->smu_features[GNLD_DS_MP0CLK].smu_feature_id = FEATURE_DS_MP0CLK_BIT; - data->smu_features[GNLD_XGMI].smu_feature_id = FEATURE_XGMI_BIT; - data->smu_features[GNLD_ECC].smu_feature_id = FEATURE_ECC_BIT; - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - data->smu_features[i].smu_feature_bitmap = - (uint64_t)(1ULL << data->smu_features[i].smu_feature_id); - data->smu_features[i].allowed = - ((data->registry_data.disallowed_features >> i) & 1) ? - false : true; - } - - /* Get the SN to turn into a Unique ID */ - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumTop32, &top32); - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ReadSerialNumBottom32, &bottom32); - - adev->unique_id = ((uint64_t)bottom32 << 32) | top32; -} - -static int vega20_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int vega20_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) -{ - kfree(hwmgr->backend); - hwmgr->backend = NULL; - - return 0; -} - -static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data; - struct amdgpu_device *adev = hwmgr->adev; - - data = kzalloc(sizeof(struct vega20_hwmgr), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - hwmgr->backend = data; - - hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT]; - hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT; - - vega20_set_default_registry_data(hwmgr); - - data->disable_dpm_mask = 0xff; - - /* need to set voltage control types before EVV patching */ - data->vddc_control = VEGA20_VOLTAGE_CONTROL_NONE; - data->mvdd_control = VEGA20_VOLTAGE_CONTROL_NONE; - data->vddci_control = VEGA20_VOLTAGE_CONTROL_NONE; - - data->water_marks_bitmap = 0; - data->avfs_exist = false; - - vega20_set_features_platform_caps(hwmgr); - - vega20_init_dpm_defaults(hwmgr); - - /* Parse pptable data read from VBIOS */ - vega20_set_private_data_based_on_pptable(hwmgr); - - data->is_tlu_enabled = false; - - hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = - VEGA20_MAX_HARDWARE_POWERLEVELS; - hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; - hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; - - hwmgr->platform_descriptor.vbiosInterruptId = 0x20000400; /* IRQ_SOURCE1_SW_INT */ - /* The true clock step depends on the frequency, typically 4.5 or 9 MHz. Here we use 5. */ - hwmgr->platform_descriptor.clockStep.engineClock = 500; - hwmgr->platform_descriptor.clockStep.memoryClock = 500; - - data->total_active_cus = adev->gfx.cu_info.number; - data->is_custom_profile_set = false; - - return 0; -} - -static int vega20_init_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - - data->low_sclk_interrupt_threshold = 0; - - return 0; -} - -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 && - (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || - (adev->in_runpm && amdgpu_asic_supports_baco(adev)); - - ret = vega20_init_sclk_threshold(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "Failed to init sclk threshold!", - return ret); - - if (use_baco) { - ret = vega20_baco_apply_vdci_flush_workaround(hwmgr); - if (ret) - pr_err("Failed to apply vega20 baco workaround!\n"); - } - - return ret; -} - -/* - * @fn vega20_init_dpm_state - * @brief Function to initialize all Soft Min/Max and Hard Min/Max to 0xff. - * - * @param dpm_state - the address of the DPM Table to initiailize. - * @return None. - */ -static void vega20_init_dpm_state(struct vega20_dpm_state *dpm_state) -{ - dpm_state->soft_min_level = 0x0; - dpm_state->soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_state->hard_min_level = 0x0; - dpm_state->hard_max_level = VG20_CLOCK_MAX_DEFAULT; -} - -static int vega20_get_number_of_dpm_level(struct pp_hwmgr *hwmgr, - PPCLK_e clk_id, uint32_t *num_of_levels) -{ - int ret = 0; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmFreqByIndex, - (clk_id << 16 | 0xFF), - num_of_levels); - PP_ASSERT_WITH_CODE(!ret, - "[GetNumOfDpmLevel] failed to get dpm levels!", - return ret); - - return ret; -} - -static int vega20_get_dpm_frequency_by_index(struct pp_hwmgr *hwmgr, - PPCLK_e clk_id, uint32_t index, uint32_t *clk) -{ - int ret = 0; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmFreqByIndex, - (clk_id << 16 | index), - clk); - PP_ASSERT_WITH_CODE(!ret, - "[GetDpmFreqByIndex] failed to get dpm freq by index!", - return ret); - - return ret; -} - -static int vega20_setup_single_dpm_table(struct pp_hwmgr *hwmgr, - struct vega20_single_dpm_table *dpm_table, PPCLK_e clk_id) -{ - int ret = 0; - uint32_t i, num_of_levels, clk; - - ret = vega20_get_number_of_dpm_level(hwmgr, clk_id, &num_of_levels); - PP_ASSERT_WITH_CODE(!ret, - "[SetupSingleDpmTable] failed to get clk levels!", - return ret); - - dpm_table->count = num_of_levels; - - for (i = 0; i < num_of_levels; i++) { - ret = vega20_get_dpm_frequency_by_index(hwmgr, clk_id, i, &clk); - PP_ASSERT_WITH_CODE(!ret, - "[SetupSingleDpmTable] failed to get clk of specific level!", - return ret); - dpm_table->dpm_levels[i].value = clk; - dpm_table->dpm_levels[i].enabled = true; - } - - return ret; -} - -static int vega20_setup_gfxclk_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table; - int ret = 0; - - dpm_table = &(data->dpm_table.gfx_table); - if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_GFXCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get gfxclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.gfx_clock / 100; - } - - return ret; -} - -static int vega20_setup_memclk_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table; - int ret = 0; - - dpm_table = &(data->dpm_table.mem_table); - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_UCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get memclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.mem_clock / 100; - } - - return ret; -} - -/* - * This function is to initialize all DPM state tables - * for SMU based on the dependency table. - * Dynamic state patching function will then trim these - * state tables to the allowed range based - * on the power policy or external client requests, - * such as UVD request, etc. - */ -static int vega20_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table; - int ret = 0; - - memset(&data->dpm_table, 0, sizeof(data->dpm_table)); - - /* socclk */ - dpm_table = &(data->dpm_table.soc_table); - if (data->smu_features[GNLD_DPM_SOCCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_SOCCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get socclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.soc_clock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* gfxclk */ - dpm_table = &(data->dpm_table.gfx_table); - ret = vega20_setup_gfxclk_dpm_table(hwmgr); - if (ret) - return ret; - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* memclk */ - dpm_table = &(data->dpm_table.mem_table); - ret = vega20_setup_memclk_dpm_table(hwmgr); - if (ret) - return ret; - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* eclk */ - dpm_table = &(data->dpm_table.eclk_table); - if (data->smu_features[GNLD_DPM_VCE].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_ECLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get eclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.eclock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* vclk */ - dpm_table = &(data->dpm_table.vclk_table); - if (data->smu_features[GNLD_DPM_UVD].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_VCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get vclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.vclock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* dclk */ - dpm_table = &(data->dpm_table.dclk_table); - if (data->smu_features[GNLD_DPM_UVD].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.dclock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* dcefclk */ - dpm_table = &(data->dpm_table.dcef_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DCEFCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dcefclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.dcef_clock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* pixclk */ - dpm_table = &(data->dpm_table.pixel_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PIXCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get pixclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* dispclk */ - dpm_table = &(data->dpm_table.display_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_DISPCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get dispclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* phyclk */ - dpm_table = &(data->dpm_table.phy_table); - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_PHYCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get phyclk dpm levels!", - return ret); - } else - dpm_table->count = 0; - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* fclk */ - dpm_table = &(data->dpm_table.fclk_table); - if (data->smu_features[GNLD_DPM_FCLK].enabled) { - ret = vega20_setup_single_dpm_table(hwmgr, dpm_table, PPCLK_FCLK); - PP_ASSERT_WITH_CODE(!ret, - "[SetupDefaultDpmTable] failed to get fclk dpm levels!", - return ret); - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = data->vbios_boot_state.fclock / 100; - } - vega20_init_dpm_state(&(dpm_table->dpm_state)); - - /* save a copy of the default DPM table */ - memcpy(&(data->golden_dpm_table), &(data->dpm_table), - sizeof(struct vega20_dpm_table)); - - return 0; -} - -/** -* Initializes the SMC table and uploads it -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data (PowerState) -* @return always 0 -*/ -static int vega20_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct pp_atomfwctrl_bios_boot_up_values boot_up_values; - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - - result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values); - PP_ASSERT_WITH_CODE(!result, - "[InitSMCTable] Failed to get vbios bootup values!", - return result); - - data->vbios_boot_state.vddc = boot_up_values.usVddc; - data->vbios_boot_state.vddci = boot_up_values.usVddci; - data->vbios_boot_state.mvddc = boot_up_values.usMvddc; - data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk; - data->vbios_boot_state.mem_clock = boot_up_values.ulUClk; - data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk; - data->vbios_boot_state.dcef_clock = boot_up_values.ulDCEFClk; - data->vbios_boot_state.eclock = boot_up_values.ulEClk; - data->vbios_boot_state.vclock = boot_up_values.ulVClk; - data->vbios_boot_state.dclock = boot_up_values.ulDClk; - data->vbios_boot_state.fclock = boot_up_values.ulFClk; - data->vbios_boot_state.uc_cooling_id = boot_up_values.ucCoolingID; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinDeepSleepDcefclk, - (uint32_t)(data->vbios_boot_state.dcef_clock / 100), - NULL); - - memcpy(pp_table, pptable_information->smc_pptable, sizeof(PPTable_t)); - - result = smum_smc_table_manager(hwmgr, - (uint8_t *)pp_table, TABLE_PPTABLE, false); - PP_ASSERT_WITH_CODE(!result, - "[InitSMCTable] Failed to upload PPtable!", - return result); - - return 0; -} - -/* - * Override PCIe link speed and link width for DPM Level 1. PPTable entries - * reflect the ASIC capabilities and not the system capabilities. For e.g. - * Vega20 board in a PCI Gen3 system. In this case, when SMU's tries to switch - * to DPM1, it fails as system doesn't support Gen4. - */ -static int vega20_override_pcie_parameters(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t pcie_gen = 0, pcie_width = 0, smu_pcie_arg; - int ret; - - if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4) - pcie_gen = 3; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) - pcie_gen = 2; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) - pcie_gen = 1; - else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1) - pcie_gen = 0; - - if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16) - pcie_width = 6; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12) - pcie_width = 5; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X8) - pcie_width = 4; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X4) - pcie_width = 3; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X2) - pcie_width = 2; - else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X1) - pcie_width = 1; - - /* Bit 31:16: LCLK DPM level. 0 is DPM0, and 1 is DPM1 - * Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4 - * Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 - */ - smu_pcie_arg = (1 << 16) | (pcie_gen << 8) | pcie_width; - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_OverridePcieParameters, smu_pcie_arg, - NULL); - PP_ASSERT_WITH_CODE(!ret, - "[OverridePcieParameters] Attempt to override pcie params failed!", - return ret); - - data->pcie_parameters_override = true; - data->pcie_gen_level1 = pcie_gen; - data->pcie_width_level1 = pcie_width; - - return 0; -} - -static int vega20_set_allowed_featuresmask(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t allowed_features_low = 0, allowed_features_high = 0; - int i; - int ret = 0; - - for (i = 0; i < GNLD_FEATURES_MAX; i++) - if (data->smu_features[i].allowed) - data->smu_features[i].smu_feature_id > 31 ? - (allowed_features_high |= - ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_HIGH_SHIFT) - & 0xFFFFFFFF)) : - (allowed_features_low |= - ((data->smu_features[i].smu_feature_bitmap >> SMU_FEATURES_LOW_SHIFT) - & 0xFFFFFFFF)); - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetAllowedFeaturesMaskHigh, allowed_features_high, NULL); - PP_ASSERT_WITH_CODE(!ret, - "[SetAllowedFeaturesMask] Attempt to set allowed features mask(high) failed!", - return ret); - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetAllowedFeaturesMaskLow, allowed_features_low, NULL); - PP_ASSERT_WITH_CODE(!ret, - "[SetAllowedFeaturesMask] Attempt to set allowed features mask (low) failed!", - return ret); - - return 0; -} - -static int vega20_run_btc(struct pp_hwmgr *hwmgr) -{ - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunBtc, NULL); -} - -static int vega20_run_btc_afll(struct pp_hwmgr *hwmgr) -{ - return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAfllBtc, NULL); -} - -static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint64_t features_enabled; - int i; - bool enabled; - int ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_EnableAllSmuFeatures, - NULL)) == 0, - "[EnableAllSMUFeatures] Failed to enable all smu features!", - return ret); - - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", - return ret); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? - true : false; - data->smu_features[i].enabled = enabled; - data->smu_features[i].supported = enabled; - -#if 0 - if (data->smu_features[i].allowed && !enabled) - pr_info("[EnableAllSMUFeatures] feature %d is expected enabled!", i); - else if (!data->smu_features[i].allowed && enabled) - pr_info("[EnableAllSMUFeatures] feature %d is expected disabled!", i); -#endif - } - - return 0; -} - -static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_DPM_UCLK].enabled) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetUclkFastSwitch, - 1, - NULL); - - return 0; -} - -static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFclkGfxClkRatio, - data->registry_data.fclk_gfxclk_ratio, - NULL); -} - -static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - int i, ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_DisableAllSmuFeatures, - NULL)) == 0, - "[DisableAllSMUFeatures] Failed to disable all smu features!", - return ret); - - for (i = 0; i < GNLD_FEATURES_MAX; i++) - data->smu_features[i].enabled = 0; - - return 0; -} - -static int vega20_od8_set_feature_capabilities( - struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - struct vega20_od8_settings *od_settings = &(data->od8_settings); - - od_settings->overdrive8_capabilities = 0; - - if (data->smu_features[GNLD_DPM_GFXCLK].enabled) { - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS] && - pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] > 0 && - pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_FMAX] >= - pptable_information->od_settings_min[OD8_SETTING_GFXCLK_FMIN])) - od_settings->overdrive8_capabilities |= OD8_GFXCLK_LIMITS; - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE] && - (pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1] >= - pp_table->MinVoltageGfx / VOLTAGE_SCALE) && - (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] <= - pp_table->MaxVoltageGfx / VOLTAGE_SCALE) && - (pptable_information->od_settings_max[OD8_SETTING_GFXCLK_VOLTAGE3] >= - pptable_information->od_settings_min[OD8_SETTING_GFXCLK_VOLTAGE1])) - od_settings->overdrive8_capabilities |= OD8_GFXCLK_CURVE; - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] = - data->dpm_table.mem_table.dpm_levels[data->dpm_table.mem_table.count - 2].value; - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_UCLK_MAX] && - pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX] > 0 && - pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_UCLK_FMAX] >= - pptable_information->od_settings_min[OD8_SETTING_UCLK_FMAX])) - od_settings->overdrive8_capabilities |= OD8_UCLK_MAX; - } - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_POWER_LIMIT] && - pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] > 0 && - pptable_information->od_settings_max[OD8_SETTING_POWER_PERCENTAGE] <= 100 && - pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] > 0 && - pptable_information->od_settings_min[OD8_SETTING_POWER_PERCENTAGE] <= 100) - od_settings->overdrive8_capabilities |= OD8_POWER_LIMIT; - - if (data->smu_features[GNLD_FAN_CONTROL].enabled) { - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT] && - pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && - pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_FAN_ACOUSTIC_LIMIT] >= - pptable_information->od_settings_min[OD8_SETTING_FAN_ACOUSTIC_LIMIT])) - od_settings->overdrive8_capabilities |= OD8_ACOUSTIC_LIMIT_SCLK; - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN] && - (pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED] >= - (pp_table->FanPwmMin * pp_table->FanMaximumRpm / 100)) && - pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_FAN_MIN_SPEED] >= - pptable_information->od_settings_min[OD8_SETTING_FAN_MIN_SPEED])) - od_settings->overdrive8_capabilities |= OD8_FAN_SPEED_MIN; - } - - if (data->smu_features[GNLD_THERMAL].enabled) { - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN] && - pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] > 0 && - pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_FAN_TARGET_TEMP] >= - pptable_information->od_settings_min[OD8_SETTING_FAN_TARGET_TEMP])) - od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_FAN; - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM] && - pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && - pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX] > 0 && - (pptable_information->od_settings_max[OD8_SETTING_OPERATING_TEMP_MAX] >= - pptable_information->od_settings_min[OD8_SETTING_OPERATING_TEMP_MAX])) - od_settings->overdrive8_capabilities |= OD8_TEMPERATURE_SYSTEM; - } - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE]) - od_settings->overdrive8_capabilities |= OD8_MEMORY_TIMING_TUNE; - - if (pptable_information->od_feature_capabilities[ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL] && - pp_table->FanZeroRpmEnable) - od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL; - - if (!od_settings->overdrive8_capabilities) - hwmgr->od_enabled = false; - - return 0; -} - -static int vega20_od8_set_feature_id( - struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_od8_settings *od_settings = &(data->od8_settings); - - if (od_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = - OD8_GFXCLK_LIMITS; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = - OD8_GFXCLK_LIMITS; - } else { - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].feature_id = - 0; - } - - if (od_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = - OD8_GFXCLK_CURVE; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = - OD8_GFXCLK_CURVE; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = - OD8_GFXCLK_CURVE; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = - OD8_GFXCLK_CURVE; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = - OD8_GFXCLK_CURVE; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = - OD8_GFXCLK_CURVE; - } else { - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].feature_id = - 0; - od_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id = - 0; - } - - if (od_settings->overdrive8_capabilities & OD8_UCLK_MAX) - od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = OD8_UCLK_MAX; - else - od_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].feature_id = 0; - - if (od_settings->overdrive8_capabilities & OD8_POWER_LIMIT) - od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = OD8_POWER_LIMIT; - else - od_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].feature_id = 0; - - if (od_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) - od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = - OD8_ACOUSTIC_LIMIT_SCLK; - else - od_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].feature_id = - 0; - - if (od_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) - od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = - OD8_FAN_SPEED_MIN; - else - od_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].feature_id = - 0; - - if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) - od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = - OD8_TEMPERATURE_FAN; - else - od_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].feature_id = - 0; - - if (od_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) - od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = - OD8_TEMPERATURE_SYSTEM; - else - od_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].feature_id = - 0; - - return 0; -} - -static int vega20_od8_get_gfx_clock_base_voltage( - struct pp_hwmgr *hwmgr, - uint32_t *voltage, - uint32_t freq) -{ - int ret = 0; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetAVFSVoltageByDpm, - ((AVFS_CURVE << 24) | (OD8_HOTCURVE_TEMPERATURE << 16) | freq), - voltage); - PP_ASSERT_WITH_CODE(!ret, - "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!", - return ret); - - *voltage = *voltage / VOLTAGE_SCALE; - - return 0; -} - -static int vega20_od8_initialize_default_settings( - struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_od8_settings *od8_settings = &(data->od8_settings); - OverDriveTable_t *od_table = &(data->smc_state_table.overdrive_table); - int i, ret = 0; - - /* Set Feature Capabilities */ - vega20_od8_set_feature_capabilities(hwmgr); - - /* Map FeatureID to individual settings */ - vega20_od8_set_feature_id(hwmgr); - - /* Set default values */ - ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, true); - PP_ASSERT_WITH_CODE(!ret, - "Failed to export over drive table!", - return ret); - - if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_LIMITS) { - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = - od_table->GfxclkFmin; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = - od_table->GfxclkFmax; - } else { - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMIN].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FMAX].default_value = - 0; - } - - if (od8_settings->overdrive8_capabilities & OD8_GFXCLK_CURVE) { - od_table->GfxclkFreq1 = od_table->GfxclkFmin; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = - od_table->GfxclkFreq1; - - od_table->GfxclkFreq3 = od_table->GfxclkFmax; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = - od_table->GfxclkFreq3; - - od_table->GfxclkFreq2 = (od_table->GfxclkFreq1 + od_table->GfxclkFreq3) / 2; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = - od_table->GfxclkFreq2; - - PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, - &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value), - od_table->GfxclkFreq1), - "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = 0); - od_table->GfxclkVolt1 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value - * VOLTAGE_SCALE; - - PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, - &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value), - od_table->GfxclkFreq2), - "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = 0); - od_table->GfxclkVolt2 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value - * VOLTAGE_SCALE; - - PP_ASSERT_WITH_CODE(!vega20_od8_get_gfx_clock_base_voltage(hwmgr, - &(od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value), - od_table->GfxclkFreq3), - "[PhwVega20_OD8_InitializeDefaultSettings] Failed to get Base clock voltage from SMU!", - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = 0); - od_table->GfxclkVolt3 = od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value - * VOLTAGE_SCALE; - } else { - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ1].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE1].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ2].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE2].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_FREQ3].default_value = - 0; - od8_settings->od8_settings_array[OD8_SETTING_GFXCLK_VOLTAGE3].default_value = - 0; - } - - if (od8_settings->overdrive8_capabilities & OD8_UCLK_MAX) - od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = - od_table->UclkFmax; - else - od8_settings->od8_settings_array[OD8_SETTING_UCLK_FMAX].default_value = - 0; - - if (od8_settings->overdrive8_capabilities & OD8_POWER_LIMIT) - od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = - od_table->OverDrivePct; - else - od8_settings->od8_settings_array[OD8_SETTING_POWER_PERCENTAGE].default_value = - 0; - - if (od8_settings->overdrive8_capabilities & OD8_ACOUSTIC_LIMIT_SCLK) - od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = - od_table->FanMaximumRpm; - else - od8_settings->od8_settings_array[OD8_SETTING_FAN_ACOUSTIC_LIMIT].default_value = - 0; - - if (od8_settings->overdrive8_capabilities & OD8_FAN_SPEED_MIN) - od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = - od_table->FanMinimumPwm * data->smc_state_table.pp_table.FanMaximumRpm / 100; - else - od8_settings->od8_settings_array[OD8_SETTING_FAN_MIN_SPEED].default_value = - 0; - - if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_FAN) - od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = - od_table->FanTargetTemperature; - else - od8_settings->od8_settings_array[OD8_SETTING_FAN_TARGET_TEMP].default_value = - 0; - - if (od8_settings->overdrive8_capabilities & OD8_TEMPERATURE_SYSTEM) - od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = - od_table->MaxOpTemp; - else - od8_settings->od8_settings_array[OD8_SETTING_OPERATING_TEMP_MAX].default_value = - 0; - - for (i = 0; i < OD8_SETTING_COUNT; i++) { - if (od8_settings->od8_settings_array[i].feature_id) { - od8_settings->od8_settings_array[i].min_value = - pptable_information->od_settings_min[i]; - od8_settings->od8_settings_array[i].max_value = - pptable_information->od_settings_max[i]; - od8_settings->od8_settings_array[i].current_value = - od8_settings->od8_settings_array[i].default_value; - } else { - od8_settings->od8_settings_array[i].min_value = - 0; - od8_settings->od8_settings_array[i].max_value = - 0; - od8_settings->od8_settings_array[i].current_value = - 0; - } - } - - ret = smum_smc_table_manager(hwmgr, (uint8_t *)od_table, TABLE_OVERDRIVE, false); - PP_ASSERT_WITH_CODE(!ret, - "Failed to import over drive table!", - return ret); - - return 0; -} - -static int vega20_od8_set_settings( - struct pp_hwmgr *hwmgr, - uint32_t index, - uint32_t value) -{ - OverDriveTable_t od_table; - int ret = 0; - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_od8_single_setting *od8_settings = - data->od8_settings.od8_settings_array; - - ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, true); - PP_ASSERT_WITH_CODE(!ret, - "Failed to export over drive table!", - return ret); - - switch(index) { - case OD8_SETTING_GFXCLK_FMIN: - od_table.GfxclkFmin = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_FMAX: - if (value < od8_settings[OD8_SETTING_GFXCLK_FMAX].min_value || - value > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) - return -EINVAL; - - od_table.GfxclkFmax = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_FREQ1: - od_table.GfxclkFreq1 = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_VOLTAGE1: - od_table.GfxclkVolt1 = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_FREQ2: - od_table.GfxclkFreq2 = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_VOLTAGE2: - od_table.GfxclkVolt2 = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_FREQ3: - od_table.GfxclkFreq3 = (uint16_t)value; - break; - case OD8_SETTING_GFXCLK_VOLTAGE3: - od_table.GfxclkVolt3 = (uint16_t)value; - break; - case OD8_SETTING_UCLK_FMAX: - if (value < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || - value > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) - return -EINVAL; - od_table.UclkFmax = (uint16_t)value; - break; - case OD8_SETTING_POWER_PERCENTAGE: - od_table.OverDrivePct = (int16_t)value; - break; - case OD8_SETTING_FAN_ACOUSTIC_LIMIT: - od_table.FanMaximumRpm = (uint16_t)value; - break; - case OD8_SETTING_FAN_MIN_SPEED: - od_table.FanMinimumPwm = (uint16_t)value; - break; - case OD8_SETTING_FAN_TARGET_TEMP: - od_table.FanTargetTemperature = (uint16_t)value; - break; - case OD8_SETTING_OPERATING_TEMP_MAX: - od_table.MaxOpTemp = (uint16_t)value; - break; - } - - ret = smum_smc_table_manager(hwmgr, (uint8_t *)(&od_table), TABLE_OVERDRIVE, false); - PP_ASSERT_WITH_CODE(!ret, - "Failed to import over drive table!", - return ret); - - return 0; -} - -static int vega20_get_sclk_od( - struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - struct vega20_single_dpm_table *sclk_table = - &(data->dpm_table.gfx_table); - struct vega20_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.gfx_table); - int value = sclk_table->dpm_levels[sclk_table->count - 1].value; - int golden_value = golden_sclk_table->dpm_levels - [golden_sclk_table->count - 1].value; - - /* od percentage */ - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega20_set_sclk_od( - struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct vega20_hwmgr *data = hwmgr->backend; - struct vega20_single_dpm_table *golden_sclk_table = - &(data->golden_dpm_table.gfx_table); - uint32_t od_sclk; - int ret = 0; - - od_sclk = golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value * value; - od_sclk /= 100; - od_sclk += golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; - - ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_GFXCLK_FMAX, od_sclk); - PP_ASSERT_WITH_CODE(!ret, - "[SetSclkOD] failed to set od gfxclk!", - return ret); - - /* retrieve updated gfxclk table */ - ret = vega20_setup_gfxclk_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "[SetSclkOD] failed to refresh gfxclk table!", - return ret); - - return 0; -} - -static int vega20_get_mclk_od( - struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - struct vega20_single_dpm_table *mclk_table = - &(data->dpm_table.mem_table); - struct vega20_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mem_table); - int value = mclk_table->dpm_levels[mclk_table->count - 1].value; - int golden_value = golden_mclk_table->dpm_levels - [golden_mclk_table->count - 1].value; - - /* od percentage */ - value -= golden_value; - value = DIV_ROUND_UP(value * 100, golden_value); - - return value; -} - -static int vega20_set_mclk_od( - struct pp_hwmgr *hwmgr, uint32_t value) -{ - struct vega20_hwmgr *data = hwmgr->backend; - struct vega20_single_dpm_table *golden_mclk_table = - &(data->golden_dpm_table.mem_table); - uint32_t od_mclk; - int ret = 0; - - od_mclk = golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value * value; - od_mclk /= 100; - od_mclk += golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; - - ret = vega20_od8_set_settings(hwmgr, OD8_SETTING_UCLK_FMAX, od_mclk); - PP_ASSERT_WITH_CODE(!ret, - "[SetMclkOD] failed to set od memclk!", - return ret); - - /* retrieve updated memclk table */ - ret = vega20_setup_memclk_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "[SetMclkOD] failed to refresh memclk table!", - return ret); - - return 0; -} - -static int vega20_populate_umdpstate_clocks( - struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *gfx_table = &(data->dpm_table.gfx_table); - struct vega20_single_dpm_table *mem_table = &(data->dpm_table.mem_table); - - hwmgr->pstate_sclk = gfx_table->dpm_levels[0].value; - hwmgr->pstate_mclk = mem_table->dpm_levels[0].value; - - if (gfx_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && - mem_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL) { - hwmgr->pstate_sclk = gfx_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; - hwmgr->pstate_mclk = mem_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; - } - - hwmgr->pstate_sclk = hwmgr->pstate_sclk * 100; - hwmgr->pstate_mclk = hwmgr->pstate_mclk * 100; - - return 0; -} - -static int vega20_get_max_sustainable_clock(struct pp_hwmgr *hwmgr, - PP_Clock *clock, PPCLK_e clock_select) -{ - int ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDcModeMaxDpmFreq, - (clock_select << 16), - clock)) == 0, - "[GetMaxSustainableClock] Failed to get max DC clock from SMC!", - return ret); - - /* if DC limit is zero, return AC limit */ - if (*clock == 0) { - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetMaxDpmFreq, - (clock_select << 16), - clock)) == 0, - "[GetMaxSustainableClock] failed to get max AC clock from SMC!", - return ret); - } - - return 0; -} - -static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_max_sustainable_clocks *max_sustainable_clocks = - &(data->max_sustainable_clocks); - int ret = 0; - - max_sustainable_clocks->uclock = data->vbios_boot_state.mem_clock / 100; - max_sustainable_clocks->soc_clock = data->vbios_boot_state.soc_clock / 100; - max_sustainable_clocks->dcef_clock = data->vbios_boot_state.dcef_clock / 100; - max_sustainable_clocks->display_clock = 0xFFFFFFFF; - max_sustainable_clocks->phy_clock = 0xFFFFFFFF; - max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; - - if (data->smu_features[GNLD_DPM_UCLK].enabled) - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->uclock), - PPCLK_UCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max UCLK from SMC!", - return ret); - - if (data->smu_features[GNLD_DPM_SOCCLK].enabled) - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->soc_clock), - PPCLK_SOCCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max SOCCLK from SMC!", - return ret); - - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->dcef_clock), - PPCLK_DCEFCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max DCEFCLK from SMC!", - return ret); - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->display_clock), - PPCLK_DISPCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max DISPCLK from SMC!", - return ret); - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->phy_clock), - PPCLK_PHYCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max PHYCLK from SMC!", - return ret); - PP_ASSERT_WITH_CODE((ret = vega20_get_max_sustainable_clock(hwmgr, - &(max_sustainable_clocks->pixel_clock), - PPCLK_PIXCLK)) == 0, - "[InitMaxSustainableClocks] failed to get max PIXCLK from SMC!", - return ret); - } - - if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) - max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; - - return 0; -} - -static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr) -{ - int result; - - result = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_SetMGpuFanBoostLimitRpm, - NULL); - PP_ASSERT_WITH_CODE(!result, - "[EnableMgpuFan] Failed to enable mgpu fan boost!", - return result); - - return 0; -} - -static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - - data->uvd_power_gated = true; - data->vce_power_gated = true; -} - -static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, 0, NULL); - - result = vega20_set_allowed_featuresmask(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to set allowed featuresmask!\n", - return result); - - result = vega20_init_smc_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to initialize SMC table!", - return result); - - result = vega20_run_btc(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to run btc!", - return result); - - result = vega20_run_btc_afll(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to run btc afll!", - return result); - - result = vega20_enable_all_smu_features(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to enable all smu features!", - return result); - - result = vega20_override_pcie_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to override pcie parameters!", - return result); - - result = vega20_notify_smc_display_change(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to notify smc display change!", - return result); - - result = vega20_send_clock_ratio(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to send clock ratio!", - return result); - - /* Initialize UVD/VCE powergating state */ - vega20_init_powergate_state(hwmgr); - - result = vega20_setup_default_dpm_tables(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to setup default DPM tables!", - return result); - - result = vega20_init_max_sustainable_clocks(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to get maximum sustainable clocks!", - return result); - - result = vega20_power_control_set_level(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to power control set level!", - return result); - - result = vega20_od8_initialize_default_settings(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to initialize odn settings!", - return result); - - result = vega20_populate_umdpstate_clocks(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "[EnableDPMTasks] Failed to populate umdpstate clocks!", - return result); - - result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit, - POWER_SOURCE_AC << 16, &hwmgr->default_power_limit); - PP_ASSERT_WITH_CODE(!result, - "[GetPptLimit] get default PPT limit failed!", - return result); - hwmgr->power_limit = - hwmgr->default_power_limit; - - return 0; -} - -static uint32_t vega20_find_lowest_dpm_level( - struct vega20_single_dpm_table *table) -{ - uint32_t i; - - for (i = 0; i < table->count; i++) { - if (table->dpm_levels[i].enabled) - break; - } - if (i >= table->count) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return i; -} - -static uint32_t vega20_find_highest_dpm_level( - struct vega20_single_dpm_table *table) -{ - int i = 0; - - PP_ASSERT_WITH_CODE(table != NULL, - "[FindHighestDPMLevel] DPM Table does not exist!", - return 0); - PP_ASSERT_WITH_CODE(table->count > 0, - "[FindHighestDPMLevel] DPM Table has no entry!", - return 0); - PP_ASSERT_WITH_CODE(table->count <= MAX_REGULAR_DPM_NUMBER, - "[FindHighestDPMLevel] DPM Table has too many entries!", - return MAX_REGULAR_DPM_NUMBER - 1); - - for (i = table->count - 1; i >= 0; i--) { - if (table->dpm_levels[i].enabled) - break; - } - if (i < 0) { - i = 0; - table->dpm_levels[i].enabled = true; - } - - return i; -} - -static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t min_freq; - int ret = 0; - - if (data->smu_features[GNLD_DPM_GFXCLK].enabled && - (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { - min_freq = data->dpm_table.gfx_table.dpm_state.soft_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_GFXCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min gfxclk !", - return ret); - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled && - (feature_mask & FEATURE_DPM_UCLK_MASK)) { - min_freq = data->dpm_table.mem_table.dpm_state.soft_min_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_UCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min memclk !", - return ret); - } - - if (data->smu_features[GNLD_DPM_UVD].enabled && - (feature_mask & FEATURE_DPM_UVD_MASK)) { - min_freq = data->dpm_table.vclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_VCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min vclk!", - return ret); - - min_freq = data->dpm_table.dclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_DCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min dclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_VCE].enabled && - (feature_mask & FEATURE_DPM_VCE_MASK)) { - min_freq = data->dpm_table.eclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_ECLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min eclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_SOCCLK].enabled && - (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { - min_freq = data->dpm_table.soc_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_SOCCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min socclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_FCLK].enabled && - (feature_mask & FEATURE_DPM_FCLK_MASK)) { - min_freq = data->dpm_table.fclk_table.dpm_state.soft_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_FCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set soft min fclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled && - (feature_mask & FEATURE_DPM_DCEFCLK_MASK)) { - min_freq = data->dpm_table.dcef_table.dpm_state.hard_min_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetHardMinByFreq, - (PPCLK_DCEFCLK << 16) | (min_freq & 0xffff), - NULL)), - "Failed to set hard min dcefclk!", - return ret); - } - - return ret; -} - -static int vega20_upload_dpm_max_level(struct pp_hwmgr *hwmgr, uint32_t feature_mask) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t max_freq; - int ret = 0; - - if (data->smu_features[GNLD_DPM_GFXCLK].enabled && - (feature_mask & FEATURE_DPM_GFXCLK_MASK)) { - max_freq = data->dpm_table.gfx_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_GFXCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max gfxclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled && - (feature_mask & FEATURE_DPM_UCLK_MASK)) { - max_freq = data->dpm_table.mem_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_UCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max memclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_UVD].enabled && - (feature_mask & FEATURE_DPM_UVD_MASK)) { - max_freq = data->dpm_table.vclk_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_VCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max vclk!", - return ret); - - max_freq = data->dpm_table.dclk_table.dpm_state.soft_max_level; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_DCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max dclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_VCE].enabled && - (feature_mask & FEATURE_DPM_VCE_MASK)) { - max_freq = data->dpm_table.eclk_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_ECLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max eclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_SOCCLK].enabled && - (feature_mask & FEATURE_DPM_SOCCLK_MASK)) { - max_freq = data->dpm_table.soc_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_SOCCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max socclk!", - return ret); - } - - if (data->smu_features[GNLD_DPM_FCLK].enabled && - (feature_mask & FEATURE_DPM_FCLK_MASK)) { - max_freq = data->dpm_table.fclk_table.dpm_state.soft_max_level; - - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetSoftMaxByFreq, - (PPCLK_FCLK << 16) | (max_freq & 0xffff), - NULL)), - "Failed to set soft max fclk!", - return ret); - } - - return ret; -} - -static int vega20_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->smu_features[GNLD_DPM_VCE].supported) { - if (data->smu_features[GNLD_DPM_VCE].enabled == enable) { - if (enable) - PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already enabled!\n"); - else - PP_DBG_LOG("[EnableDisableVCEDPM] feature VCE DPM already disabled!\n"); - } - - ret = vega20_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_VCE].smu_feature_bitmap); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to Enable/Disable DPM VCE Failed!", - return ret); - data->smu_features[GNLD_DPM_VCE].enabled = enable; - } - - return 0; -} - -static int vega20_get_clock_ranges(struct pp_hwmgr *hwmgr, - uint32_t *clock, - PPCLK_e clock_select, - bool max) -{ - int ret; - *clock = 0; - - if (max) { - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetMaxDpmFreq, (clock_select << 16), - clock)) == 0, - "[GetClockRanges] Failed to get max clock from SMC!", - return ret); - } else { - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetMinDpmFreq, - (clock_select << 16), - clock)) == 0, - "[GetClockRanges] Failed to get min clock from SMC!", - return ret); - } - - return 0; -} - -static uint32_t vega20_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t gfx_clk; - int ret = 0; - - PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_GFXCLK].enabled, - "[GetSclks]: gfxclk dpm not enabled!\n", - return -EPERM); - - if (low) { - ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, false); - PP_ASSERT_WITH_CODE(!ret, - "[GetSclks]: fail to get min PPCLK_GFXCLK\n", - return ret); - } else { - ret = vega20_get_clock_ranges(hwmgr, &gfx_clk, PPCLK_GFXCLK, true); - PP_ASSERT_WITH_CODE(!ret, - "[GetSclks]: fail to get max PPCLK_GFXCLK\n", - return ret); - } - - return (gfx_clk * 100); -} - -static uint32_t vega20_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t mem_clk; - int ret = 0; - - PP_ASSERT_WITH_CODE(data->smu_features[GNLD_DPM_UCLK].enabled, - "[MemMclks]: memclk dpm not enabled!\n", - return -EPERM); - - if (low) { - ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, false); - PP_ASSERT_WITH_CODE(!ret, - "[GetMclks]: fail to get min PPCLK_UCLK\n", - return ret); - } else { - ret = vega20_get_clock_ranges(hwmgr, &mem_clk, PPCLK_UCLK, true); - PP_ASSERT_WITH_CODE(!ret, - "[GetMclks]: fail to get max PPCLK_UCLK\n", - return ret); - } - - return (mem_clk * 100); -} - -static int vega20_get_metrics_table(struct pp_hwmgr *hwmgr, - SmuMetrics_t *metrics_table, - bool bypass_cache) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (bypass_cache || - !data->metrics_time || - time_after(jiffies, data->metrics_time + msecs_to_jiffies(1))) { - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)(&data->metrics_table), - TABLE_SMU_METRICS, - true); - if (ret) { - pr_info("Failed to export SMU metrics table!\n"); - return ret; - } - data->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, &data->metrics_table, sizeof(SmuMetrics_t)); - - return ret; -} - -static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, - uint32_t *query) -{ - int ret = 0; - SmuMetrics_t metrics_table; - - ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - /* For the 40.46 release, they changed the value name */ - if (hwmgr->smu_version == 0x282e00) - *query = metrics_table.AverageSocketPower << 8; - else - *query = metrics_table.CurrSocketPower << 8; - - return ret; -} - -static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, - PPCLK_e clk_id, uint32_t *clk_freq) -{ - int ret = 0; - - *clk_freq = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetDpmClockFreq, (clk_id << 16), - clk_freq)) == 0, - "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", - return ret); - - *clk_freq = *clk_freq * 100; - - return 0; -} - -static int vega20_get_current_activity_percent(struct pp_hwmgr *hwmgr, - int idx, - uint32_t *activity_percent) -{ - int ret = 0; - SmuMetrics_t metrics_table; - - ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - switch (idx) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - *activity_percent = metrics_table.AverageGfxActivity; - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - *activity_percent = metrics_table.AverageUclkActivity; - break; - default: - pr_err("Invalid index for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, - void *value, int *size) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct amdgpu_device *adev = hwmgr->adev; - SmuMetrics_t metrics_table; - uint32_t val_vid; - int ret = 0; - - switch (idx) { - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *((uint32_t *)value) = metrics_table.AverageGfxclkFrequency * 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = vega20_get_current_clk_freq(hwmgr, - PPCLK_UCLK, - (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_LOAD: - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = vega20_get_current_activity_percent(hwmgr, idx, (uint32_t *)value); - if (!ret) - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - *((uint32_t *)value) = vega20_thermal_get_temperature(hwmgr); - *size = 4; - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *((uint32_t *)value) = metrics_table.TemperatureEdge * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = vega20_get_metrics_table(hwmgr, &metrics_table, false); - if (ret) - return ret; - - *((uint32_t *)value) = metrics_table.TemperatureHBM * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - *size = 4; - break; - case AMDGPU_PP_SENSOR_UVD_POWER: - *((uint32_t *)value) = data->uvd_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VCE_POWER: - *((uint32_t *)value) = data->vce_power_gated ? 0 : 1; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - *size = 16; - ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value); - break; - case AMDGPU_PP_SENSOR_VDDGFX: - val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & - SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> - SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; - *((uint32_t *)value) = - (uint32_t)convert_to_vddc((uint8_t)val_vid); - break; - case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK: - ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value); - if (!ret) - *size = 8; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -static int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock_req) -{ - int result = 0; - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - enum amd_pp_clock_type clk_type = clock_req->clock_type; - uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; - PPCLK_e clk_select = 0; - uint32_t clk_request = 0; - - if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { - switch (clk_type) { - case amd_pp_dcef_clock: - clk_select = PPCLK_DCEFCLK; - break; - case amd_pp_disp_clock: - clk_select = PPCLK_DISPCLK; - break; - case amd_pp_pixel_clock: - clk_select = PPCLK_PIXCLK; - break; - case amd_pp_phy_clock: - clk_select = PPCLK_PHYCLK; - break; - default: - pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!"); - result = -EINVAL; - break; - } - - if (!result) { - clk_request = (clk_select << 16) | clk_freq; - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinByFreq, - clk_request, - NULL); - } - } - - return result; -} - -static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level) -{ - return 0; -} - -static int vega20_notify_smc_display_config_after_ps_adjustment( - struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = - &data->dpm_table.mem_table; - struct PP_Clocks min_clocks = {0}; - struct pp_display_clock_request clock_req; - int ret = 0; - - min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk; - min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk; - min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; - - if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { - clock_req.clock_type = amd_pp_dcef_clock; - clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; - if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { - if (data->smu_features[GNLD_DS_DCEFCLK].supported) - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( - hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcefClockInSR / 100, - NULL)) == 0, - "Attempt to set divider for DCEFCLK Failed!", - return ret); - } else { - pr_info("Attempt to set Hard Min for DCEFCLK Failed!"); - } - } - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, - NULL)), - "[SetHardMinFreq] Set hard min uclk failed!", - return ret); - } - - return 0; -} - -static int vega20_force_dpm_highest(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t soft_level; - int ret = 0; - - soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_level].value; - - soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_level].value; - - soft_level = vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); - - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->dpm_table.soc_table.dpm_levels[soft_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to highest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - return 0; -} - -static int vega20_force_dpm_lowest(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t soft_level; - int ret = 0; - - soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_level].value; - - soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_level].value; - - soft_level = vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); - - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->dpm_table.soc_table.dpm_levels[soft_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to highest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - return 0; - -} - -static int vega20_unforce_dpm_levels(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t soft_min_level, soft_max_level; - int ret = 0; - - /* gfxclk soft min/max settings */ - soft_min_level = - vega20_find_lowest_dpm_level(&(data->dpm_table.gfx_table)); - soft_max_level = - vega20_find_highest_dpm_level(&(data->dpm_table.gfx_table)); - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; - - /* uclk soft min/max settings */ - soft_min_level = - vega20_find_lowest_dpm_level(&(data->dpm_table.mem_table)); - soft_max_level = - vega20_find_highest_dpm_level(&(data->dpm_table.mem_table)); - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_levels[soft_min_level].value; - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_max_level].value; - - /* socclk soft min/max settings */ - soft_min_level = - vega20_find_lowest_dpm_level(&(data->dpm_table.soc_table)); - soft_max_level = - vega20_find_highest_dpm_level(&(data->dpm_table.soc_table)); - - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->dpm_table.soc_table.dpm_levels[soft_min_level].value; - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->dpm_table.soc_table.dpm_levels[soft_max_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload DPM Bootup Levels!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK | - FEATURE_DPM_UCLK_MASK | - FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload DPM Max Levels!", - return ret); - - return 0; -} - -static int vega20_get_profiling_clk_mask(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level, - uint32_t *sclk_mask, uint32_t *mclk_mask, uint32_t *soc_mask) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *gfx_dpm_table = &(data->dpm_table.gfx_table); - struct vega20_single_dpm_table *mem_dpm_table = &(data->dpm_table.mem_table); - struct vega20_single_dpm_table *soc_dpm_table = &(data->dpm_table.soc_table); - - *sclk_mask = 0; - *mclk_mask = 0; - *soc_mask = 0; - - if (gfx_dpm_table->count > VEGA20_UMD_PSTATE_GFXCLK_LEVEL && - mem_dpm_table->count > VEGA20_UMD_PSTATE_MCLK_LEVEL && - soc_dpm_table->count > VEGA20_UMD_PSTATE_SOCCLK_LEVEL) { - *sclk_mask = VEGA20_UMD_PSTATE_GFXCLK_LEVEL; - *mclk_mask = VEGA20_UMD_PSTATE_MCLK_LEVEL; - *soc_mask = VEGA20_UMD_PSTATE_SOCCLK_LEVEL; - } - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - *sclk_mask = gfx_dpm_table->count - 1; - *mclk_mask = mem_dpm_table->count - 1; - *soc_mask = soc_dpm_table->count - 1; - } - - return 0; -} - -static int vega20_force_clock_level(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, uint32_t mask) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - uint32_t soft_min_level, soft_max_level, hard_min_level; - int ret = 0; - - switch (type) { - case PP_SCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if (soft_max_level >= data->dpm_table.gfx_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - soft_max_level, - data->dpm_table.gfx_table.count - 1); - return -EINVAL; - } - - data->dpm_table.gfx_table.dpm_state.soft_min_level = - data->dpm_table.gfx_table.dpm_levels[soft_min_level].value; - data->dpm_table.gfx_table.dpm_state.soft_max_level = - data->dpm_table.gfx_table.dpm_levels[soft_max_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_GFXCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - break; - - case PP_MCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if (soft_max_level >= data->dpm_table.mem_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - soft_max_level, - data->dpm_table.mem_table.count - 1); - return -EINVAL; - } - - data->dpm_table.mem_table.dpm_state.soft_min_level = - data->dpm_table.mem_table.dpm_levels[soft_min_level].value; - data->dpm_table.mem_table.dpm_state.soft_max_level = - data->dpm_table.mem_table.dpm_levels[soft_max_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_UCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_UCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - break; - - case PP_SOCCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if (soft_max_level >= data->dpm_table.soc_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - soft_max_level, - data->dpm_table.soc_table.count - 1); - return -EINVAL; - } - - data->dpm_table.soc_table.dpm_state.soft_min_level = - data->dpm_table.soc_table.dpm_levels[soft_min_level].value; - data->dpm_table.soc_table.dpm_state.soft_max_level = - data->dpm_table.soc_table.dpm_levels[soft_max_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_SOCCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - break; - - case PP_FCLK: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if (soft_max_level >= data->dpm_table.fclk_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - soft_max_level, - data->dpm_table.fclk_table.count - 1); - return -EINVAL; - } - - data->dpm_table.fclk_table.dpm_state.soft_min_level = - data->dpm_table.fclk_table.dpm_levels[soft_min_level].value; - data->dpm_table.fclk_table.dpm_state.soft_max_level = - data->dpm_table.fclk_table.dpm_levels[soft_max_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_FCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - ret = vega20_upload_dpm_max_level(hwmgr, FEATURE_DPM_FCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload dpm max level to highest!", - return ret); - - break; - - case PP_DCEFCLK: - hard_min_level = mask ? (ffs(mask) - 1) : 0; - - if (hard_min_level >= data->dpm_table.dcef_table.count) { - pr_err("Clock level specified %d is over max allowed %d\n", - hard_min_level, - data->dpm_table.dcef_table.count - 1); - return -EINVAL; - } - - data->dpm_table.dcef_table.dpm_state.hard_min_level = - data->dpm_table.dcef_table.dpm_levels[hard_min_level].value; - - ret = vega20_upload_dpm_min_level(hwmgr, FEATURE_DPM_DCEFCLK_MASK); - PP_ASSERT_WITH_CODE(!ret, - "Failed to upload boot level to lowest!", - return ret); - - //TODO: Setting DCEFCLK max dpm level is not supported - - break; - - case PP_PCIE: - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - if (soft_min_level >= NUM_LINK_LEVELS || - soft_max_level >= NUM_LINK_LEVELS) - return -EINVAL; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetMinLinkDpmByIndex, soft_min_level, - NULL); - PP_ASSERT_WITH_CODE(!ret, - "Failed to set min link dpm level!", - return ret); - - break; - - default: - break; - } - - return 0; -} - -static int vega20_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = vega20_force_dpm_highest(hwmgr); - break; - - case AMD_DPM_FORCED_LEVEL_LOW: - ret = vega20_force_dpm_lowest(hwmgr); - break; - - case AMD_DPM_FORCED_LEVEL_AUTO: - ret = vega20_unforce_dpm_levels(hwmgr); - break; - - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = vega20_get_profiling_clk_mask(hwmgr, level, &sclk_mask, &mclk_mask, &soc_mask); - if (ret) - return ret; - vega20_force_clock_level(hwmgr, PP_SCLK, 1 << sclk_mask); - vega20_force_clock_level(hwmgr, PP_MCLK, 1 << mclk_mask); - vega20_force_clock_level(hwmgr, PP_SOCCLK, 1 << soc_mask); - break; - - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - - return ret; -} - -static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_FAN_CONTROL].enabled == false) - return AMD_FAN_CTRL_MANUAL; - else - return AMD_FAN_CTRL_AUTO; -} - -static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - switch (mode) { - case AMD_FAN_CTRL_NONE: - vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100); - break; - case AMD_FAN_CTRL_MANUAL: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega20_fan_ctrl_stop_smc_fan_control(hwmgr); - break; - case AMD_FAN_CTRL_AUTO: - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega20_fan_ctrl_start_smc_fan_control(hwmgr); - break; - default: - break; - } -} - -static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info) -{ -#if 0 - struct phm_ppt_v2_information *table_info = - (struct phm_ppt_v2_information *)hwmgr->pptable; - struct phm_clock_and_voltage_limits *max_limits = - &table_info->max_clock_voltage_on_ac; - - info->engine_max_clock = max_limits->sclk; - info->memory_max_clock = max_limits->mclk; -#endif - return 0; -} - - -static int vega20_get_sclks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.gfx_table); - int i, count; - - if (!data->smu_features[GNLD_DPM_GFXCLK].enabled) - return -1; - - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = count; - - for (i = 0; i < count; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - clocks->data[i].latency_in_us = 0; - } - - return 0; -} - -static uint32_t vega20_get_mem_latency(struct pp_hwmgr *hwmgr, - uint32_t clock) -{ - return 25; -} - -static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.mem_table); - int i, count; - - if (!data->smu_features[GNLD_DPM_UCLK].enabled) - return -1; - - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = data->mclk_latency_table.count = count; - - for (i = 0; i < count; i++) { - clocks->data[i].clocks_in_khz = - data->mclk_latency_table.entries[i].frequency = - dpm_table->dpm_levels[i].value * 1000; - clocks->data[i].latency_in_us = - data->mclk_latency_table.entries[i].latency = - vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); - } - - return 0; -} - -static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.dcef_table); - int i, count; - - if (!data->smu_features[GNLD_DPM_DCEFCLK].enabled) - return -1; - - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = count; - - for (i = 0; i < count; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - clocks->data[i].latency_in_us = 0; - } - - return 0; -} - -static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, - struct pp_clock_levels_with_latency *clocks) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.soc_table); - int i, count; - - if (!data->smu_features[GNLD_DPM_SOCCLK].enabled) - return -1; - - count = (dpm_table->count > MAX_NUM_CLOCKS) ? MAX_NUM_CLOCKS : dpm_table->count; - clocks->num_levels = count; - - for (i = 0; i < count; i++) { - clocks->data[i].clocks_in_khz = - dpm_table->dpm_levels[i].value * 1000; - clocks->data[i].latency_in_us = 0; - } - - return 0; - -} - -static int vega20_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks) -{ - int ret; - - switch (type) { - case amd_pp_sys_clock: - ret = vega20_get_sclks(hwmgr, clocks); - break; - case amd_pp_mem_clock: - ret = vega20_get_memclocks(hwmgr, clocks); - break; - case amd_pp_dcef_clock: - ret = vega20_get_dcefclocks(hwmgr, clocks); - break; - case amd_pp_soc_clock: - ret = vega20_get_socclocks(hwmgr, clocks); - break; - default: - return -EINVAL; - } - - return ret; -} - -static int vega20_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks) -{ - clocks->num_levels = 0; - - return 0; -} - -static int vega20_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_ranges) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - Watermarks_t *table = &(data->smc_state_table.water_marks_table); - struct dm_pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges = clock_ranges; - - if (!data->registry_data.disable_water_mark && - data->smu_features[GNLD_DPM_DCEFCLK].supported && - data->smu_features[GNLD_DPM_SOCCLK].supported) { - smu_set_watermarks_for_clocks_ranges(table, wm_with_clock_ranges); - data->water_marks_bitmap |= WaterMarksExist; - data->water_marks_bitmap &= ~WaterMarksLoaded; - } - - return 0; -} - -static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_od8_single_setting *od8_settings = - data->od8_settings.od8_settings_array; - OverDriveTable_t *od_table = - &(data->smc_state_table.overdrive_table); - int32_t input_index, input_clk, input_vol, i; - int od8_id; - int ret; - - PP_ASSERT_WITH_CODE(input, "NULL user input for clock and voltage", - return -EINVAL); - - switch (type) { - case PP_OD_EDIT_SCLK_VDDC_TABLE: - if (!(od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id)) { - pr_info("Sclk min/max frequency overdrive not supported\n"); - return -EOPNOTSUPP; - } - - for (i = 0; i < size; i += 2) { - if (i + 2 > size) { - pr_info("invalid number of input parameters %d\n", - size); - return -EINVAL; - } - - input_index = input[i]; - input_clk = input[i + 1]; - - if (input_index != 0 && input_index != 1) { - pr_info("Invalid index %d\n", input_index); - pr_info("Support min/max sclk frequency setting only which index by 0/1\n"); - return -EINVAL; - } - - if (input_clk < od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value || - input_clk > od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value) { - pr_info("clock freq %d is not within allowed range [%d - %d]\n", - input_clk, - od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, - od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); - return -EINVAL; - } - - if ((input_index == 0 && od_table->GfxclkFmin != input_clk) || - (input_index == 1 && od_table->GfxclkFmax != input_clk)) - data->gfxclk_overdrive = true; - - if (input_index == 0) - od_table->GfxclkFmin = input_clk; - else - od_table->GfxclkFmax = input_clk; - } - - break; - - case PP_OD_EDIT_MCLK_VDDC_TABLE: - if (!od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { - pr_info("Mclk max frequency overdrive not supported\n"); - return -EOPNOTSUPP; - } - - for (i = 0; i < size; i += 2) { - if (i + 2 > size) { - pr_info("invalid number of input parameters %d\n", - size); - return -EINVAL; - } - - input_index = input[i]; - input_clk = input[i + 1]; - - if (input_index != 1) { - pr_info("Invalid index %d\n", input_index); - pr_info("Support max Mclk frequency setting only which index by 1\n"); - return -EINVAL; - } - - if (input_clk < od8_settings[OD8_SETTING_UCLK_FMAX].min_value || - input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { - pr_info("clock freq %d is not within allowed range [%d - %d]\n", - input_clk, - od8_settings[OD8_SETTING_UCLK_FMAX].min_value, - od8_settings[OD8_SETTING_UCLK_FMAX].max_value); - return -EINVAL; - } - - if (input_index == 1 && od_table->UclkFmax != input_clk) - data->memclk_overdrive = true; - - od_table->UclkFmax = input_clk; - } - - break; - - case PP_OD_EDIT_VDDC_CURVE: - if (!(od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id)) { - pr_info("Voltage curve calibrate not supported\n"); - return -EOPNOTSUPP; - } - - for (i = 0; i < size; i += 3) { - if (i + 3 > size) { - pr_info("invalid number of input parameters %d\n", - size); - return -EINVAL; - } - - input_index = input[i]; - input_clk = input[i + 1]; - input_vol = input[i + 2]; - - if (input_index > 2) { - pr_info("Setting for point %d is not supported\n", - input_index + 1); - pr_info("Three supported points index by 0, 1, 2\n"); - return -EINVAL; - } - - od8_id = OD8_SETTING_GFXCLK_FREQ1 + 2 * input_index; - if (input_clk < od8_settings[od8_id].min_value || - input_clk > od8_settings[od8_id].max_value) { - pr_info("clock freq %d is not within allowed range [%d - %d]\n", - input_clk, - od8_settings[od8_id].min_value, - od8_settings[od8_id].max_value); - return -EINVAL; - } - - od8_id = OD8_SETTING_GFXCLK_VOLTAGE1 + 2 * input_index; - if (input_vol < od8_settings[od8_id].min_value || - input_vol > od8_settings[od8_id].max_value) { - pr_info("clock voltage %d is not within allowed range [%d - %d]\n", - input_vol, - od8_settings[od8_id].min_value, - od8_settings[od8_id].max_value); - return -EINVAL; - } - - switch (input_index) { - case 0: - od_table->GfxclkFreq1 = input_clk; - od_table->GfxclkVolt1 = input_vol * VOLTAGE_SCALE; - break; - case 1: - od_table->GfxclkFreq2 = input_clk; - od_table->GfxclkVolt2 = input_vol * VOLTAGE_SCALE; - break; - case 2: - od_table->GfxclkFreq3 = input_clk; - od_table->GfxclkVolt3 = input_vol * VOLTAGE_SCALE; - break; - } - } - break; - - case PP_OD_RESTORE_DEFAULT_TABLE: - data->gfxclk_overdrive = false; - data->memclk_overdrive = false; - - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)od_table, - TABLE_OVERDRIVE, true); - PP_ASSERT_WITH_CODE(!ret, - "Failed to export overdrive table!", - return ret); - break; - - case PP_OD_COMMIT_DPM_TABLE: - ret = smum_smc_table_manager(hwmgr, - (uint8_t *)od_table, - TABLE_OVERDRIVE, false); - PP_ASSERT_WITH_CODE(!ret, - "Failed to import overdrive table!", - return ret); - - /* retrieve updated gfxclk table */ - if (data->gfxclk_overdrive) { - data->gfxclk_overdrive = false; - - ret = vega20_setup_gfxclk_dpm_table(hwmgr); - if (ret) - return ret; - } - - /* retrieve updated memclk table */ - if (data->memclk_overdrive) { - data->memclk_overdrive = false; - - ret = vega20_setup_memclk_dpm_table(hwmgr); - if (ret) - return ret; - } - break; - - default: - return -EINVAL; - } - - return 0; -} - -static int vega20_set_mp1_state(struct pp_hwmgr *hwmgr, - enum pp_mp1_state mp1_state) -{ - uint16_t msg; - int ret; - - switch (mp1_state) { - case PP_MP1_STATE_SHUTDOWN: - msg = PPSMC_MSG_PrepareMp1ForShutdown; - break; - case PP_MP1_STATE_UNLOAD: - msg = PPSMC_MSG_PrepareMp1ForUnload; - break; - case PP_MP1_STATE_RESET: - msg = PPSMC_MSG_PrepareMp1ForReset; - break; - case PP_MP1_STATE_NONE: - default: - return 0; - } - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, msg, NULL)) == 0, - "[PrepareMp1] Failed!", - return ret); - - return 0; -} - -static int vega20_get_ppfeature_status(struct pp_hwmgr *hwmgr, char *buf) -{ - static const char *ppfeature_name[] = { - "DPM_PREFETCHER", - "GFXCLK_DPM", - "UCLK_DPM", - "SOCCLK_DPM", - "UVD_DPM", - "VCE_DPM", - "ULV", - "MP0CLK_DPM", - "LINK_DPM", - "DCEFCLK_DPM", - "GFXCLK_DS", - "SOCCLK_DS", - "LCLK_DS", - "PPT", - "TDC", - "THERMAL", - "GFX_PER_CU_CG", - "RM", - "DCEFCLK_DS", - "ACDC", - "VR0HOT", - "VR1HOT", - "FW_CTF", - "LED_DISPLAY", - "FAN_CONTROL", - "GFX_EDC", - "GFXOFF", - "CG", - "FCLK_DPM", - "FCLK_DS", - "MP1CLK_DS", - "MP0CLK_DS", - "XGMI", - "ECC"}; - static const char *output_title[] = { - "FEATURES", - "BITMASK", - "ENABLEMENT"}; - uint64_t features_enabled; - int i; - int ret = 0; - int size = 0; - - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - PP_ASSERT_WITH_CODE(!ret, - "[EnableAllSmuFeatures] Failed to get enabled smc features!", - return ret); - - size += sprintf(buf + size, "Current ppfeatures: 0x%016llx\n", features_enabled); - size += sprintf(buf + size, "%-19s %-22s %s\n", - output_title[0], - output_title[1], - output_title[2]); - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - size += sprintf(buf + size, "%-19s 0x%016llx %6s\n", - ppfeature_name[i], - 1ULL << i, - (features_enabled & (1ULL << i)) ? "Y" : "N"); - } - - return size; -} - -static int vega20_set_ppfeature_status(struct pp_hwmgr *hwmgr, uint64_t new_ppfeature_masks) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - uint64_t features_enabled, features_to_enable, features_to_disable; - int i, ret = 0; - bool enabled; - - if (new_ppfeature_masks >= (1ULL << GNLD_FEATURES_MAX)) - return -EINVAL; - - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - if (ret) - return ret; - - features_to_disable = - features_enabled & ~new_ppfeature_masks; - features_to_enable = - ~features_enabled & new_ppfeature_masks; - - pr_debug("features_to_disable 0x%llx\n", features_to_disable); - pr_debug("features_to_enable 0x%llx\n", features_to_enable); - - if (features_to_disable) { - ret = vega20_enable_smc_features(hwmgr, false, features_to_disable); - if (ret) - return ret; - } - - if (features_to_enable) { - ret = vega20_enable_smc_features(hwmgr, true, features_to_enable); - if (ret) - return ret; - } - - /* Update the cached feature enablement state */ - ret = vega20_get_enabled_smc_features(hwmgr, &features_enabled); - if (ret) - return ret; - - for (i = 0; i < GNLD_FEATURES_MAX; i++) { - enabled = (features_enabled & data->smu_features[i].smu_feature_bitmap) ? - true : false; - data->smu_features[i].enabled = enabled; - } - - return 0; -} - -static int vega20_get_current_pcie_link_width_level(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; -} - -static int vega20_get_current_pcie_link_width(struct pp_hwmgr *hwmgr) -{ - uint32_t width_level; - - width_level = vega20_get_current_pcie_link_width_level(hwmgr); - if (width_level > LINK_WIDTH_MAX) - width_level = 0; - - return link_width[width_level]; -} - -static int vega20_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; -} - -static int vega20_get_current_pcie_link_speed(struct pp_hwmgr *hwmgr) -{ - uint32_t speed_level; - - speed_level = vega20_get_current_pcie_link_speed_level(hwmgr); - if (speed_level > LINK_SPEED_MAX) - speed_level = 0; - - return link_speed[speed_level]; -} - -static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, - enum pp_clock_type type, char *buf) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_od8_single_setting *od8_settings = - data->od8_settings.od8_settings_array; - OverDriveTable_t *od_table = - &(data->smc_state_table.overdrive_table); - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - PPTable_t *pptable = (PPTable_t *)pptable_information->smc_pptable; - struct pp_clock_levels_with_latency clocks; - struct vega20_single_dpm_table *fclk_dpm_table = - &(data->dpm_table.fclk_table); - int i, now, size = 0; - int ret = 0; - uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width; - - switch (type) { - case PP_SCLK: - ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to get current gfx clk Failed!", - return ret); - - if (vega20_get_sclks(hwmgr, &clocks)) { - size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; - - case PP_MCLK: - ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to get current mclk freq Failed!", - return ret); - - if (vega20_get_memclocks(hwmgr, &clocks)) { - size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; - - case PP_SOCCLK: - ret = vega20_get_current_clk_freq(hwmgr, PPCLK_SOCCLK, &now); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to get current socclk freq Failed!", - return ret); - - if (vega20_get_socclocks(hwmgr, &clocks)) { - size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; - - case PP_FCLK: - ret = vega20_get_current_clk_freq(hwmgr, PPCLK_FCLK, &now); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to get current fclk freq Failed!", - return ret); - - for (i = 0; i < fclk_dpm_table->count; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, fclk_dpm_table->dpm_levels[i].value, - fclk_dpm_table->dpm_levels[i].value == (now / 100) ? "*" : ""); - break; - - case PP_DCEFCLK: - ret = vega20_get_current_clk_freq(hwmgr, PPCLK_DCEFCLK, &now); - PP_ASSERT_WITH_CODE(!ret, - "Attempt to get current dcefclk freq Failed!", - return ret); - - if (vega20_get_dcefclocks(hwmgr, &clocks)) { - size += sprintf(buf + size, "0: %uMhz * (DPM disabled)\n", - now / 100); - break; - } - - for (i = 0; i < clocks.num_levels; i++) - size += sprintf(buf + size, "%d: %uMhz %s\n", - i, clocks.data[i].clocks_in_khz / 1000, - (clocks.data[i].clocks_in_khz == now * 10) ? "*" : ""); - break; - - case PP_PCIE: - current_gen_speed = - vega20_get_current_pcie_link_speed_level(hwmgr); - current_lane_width = - vega20_get_current_pcie_link_width_level(hwmgr); - for (i = 0; i < NUM_LINK_LEVELS; i++) { - if (i == 1 && data->pcie_parameters_override) { - gen_speed = data->pcie_gen_level1; - lane_width = data->pcie_width_level1; - } else { - gen_speed = pptable->PcieGenSpeed[i]; - lane_width = pptable->PcieLaneCount[i]; - } - size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, - (gen_speed == 0) ? "2.5GT/s," : - (gen_speed == 1) ? "5.0GT/s," : - (gen_speed == 2) ? "8.0GT/s," : - (gen_speed == 3) ? "16.0GT/s," : "", - (lane_width == 1) ? "x1" : - (lane_width == 2) ? "x2" : - (lane_width == 3) ? "x4" : - (lane_width == 4) ? "x8" : - (lane_width == 5) ? "x12" : - (lane_width == 6) ? "x16" : "", - pptable->LclkFreq[i], - (current_gen_speed == gen_speed) && - (current_lane_width == lane_width) ? - "*" : ""); - } - break; - - case OD_SCLK: - if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { - size = sprintf(buf, "%s:\n", "OD_SCLK"); - size += sprintf(buf + size, "0: %10uMhz\n", - od_table->GfxclkFmin); - size += sprintf(buf + size, "1: %10uMhz\n", - od_table->GfxclkFmax); - } - break; - - case OD_MCLK: - if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { - size = sprintf(buf, "%s:\n", "OD_MCLK"); - size += sprintf(buf + size, "1: %10uMhz\n", - od_table->UclkFmax); - } - - break; - - case OD_VDDC_CURVE: - if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { - size = sprintf(buf, "%s:\n", "OD_VDDC_CURVE"); - size += sprintf(buf + size, "0: %10uMhz %10dmV\n", - od_table->GfxclkFreq1, - od_table->GfxclkVolt1 / VOLTAGE_SCALE); - size += sprintf(buf + size, "1: %10uMhz %10dmV\n", - od_table->GfxclkFreq2, - od_table->GfxclkVolt2 / VOLTAGE_SCALE); - size += sprintf(buf + size, "2: %10uMhz %10dmV\n", - od_table->GfxclkFreq3, - od_table->GfxclkVolt3 / VOLTAGE_SCALE); - } - - break; - - case OD_RANGE: - size = sprintf(buf, "%s:\n", "OD_RANGE"); - - if (od8_settings[OD8_SETTING_GFXCLK_FMIN].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FMAX].feature_id) { - size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FMIN].min_value, - od8_settings[OD8_SETTING_GFXCLK_FMAX].max_value); - } - - if (od8_settings[OD8_SETTING_UCLK_FMAX].feature_id) { - size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_UCLK_FMAX].min_value, - od8_settings[OD8_SETTING_UCLK_FMAX].max_value); - } - - if (od8_settings[OD8_SETTING_GFXCLK_FREQ1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_FREQ3].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].feature_id && - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].feature_id) { - size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ1].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ1].max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE1].max_value); - size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ2].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ2].max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE2].max_value); - size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", - od8_settings[OD8_SETTING_GFXCLK_FREQ3].min_value, - od8_settings[OD8_SETTING_GFXCLK_FREQ3].max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].min_value, - od8_settings[OD8_SETTING_GFXCLK_VOLTAGE3].max_value); - } - - break; - default: - break; - } - return size; -} - -static int vega20_set_uclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr, - struct vega20_single_dpm_table *dpm_table) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->smu_features[GNLD_DPM_UCLK].enabled) { - PP_ASSERT_WITH_CODE(dpm_table->count > 0, - "[SetUclkToHightestDpmLevel] Dpm table has no entry!", - return -EINVAL); - PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_UCLK_DPM_LEVELS, - "[SetUclkToHightestDpmLevel] Dpm table has too many entries!", - return -EINVAL); - - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetHardMinByFreq, - (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level, - NULL)), - "[SetUclkToHightestDpmLevel] Set hard min uclk failed!", - return ret); - } - - return ret; -} - -static int vega20_set_fclk_to_highest_dpm_level(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table = &(data->dpm_table.fclk_table); - int ret = 0; - - if (data->smu_features[GNLD_DPM_FCLK].enabled) { - PP_ASSERT_WITH_CODE(dpm_table->count > 0, - "[SetFclkToHightestDpmLevel] Dpm table has no entry!", - return -EINVAL); - PP_ASSERT_WITH_CODE(dpm_table->count <= NUM_FCLK_DPM_LEVELS, - "[SetFclkToHightestDpmLevel] Dpm table has too many entries!", - return -EINVAL); - - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSoftMinByFreq, - (PPCLK_FCLK << 16 ) | dpm_table->dpm_state.soft_min_level, - NULL)), - "[SetFclkToHightestDpmLevel] Set soft min fclk failed!", - return ret); - } - - return ret; -} - -static int vega20_pre_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - int ret = 0; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, 0, NULL); - - ret = vega20_set_uclk_to_highest_dpm_level(hwmgr, - &data->dpm_table.mem_table); - if (ret) - return ret; - - return vega20_set_fclk_to_highest_dpm_level(hwmgr); -} - -static int vega20_display_configuration_changed_task(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - int result = 0; - Watermarks_t *wm_table = &(data->smc_state_table.water_marks_table); - - if ((data->water_marks_bitmap & WaterMarksExist) && - !(data->water_marks_bitmap & WaterMarksLoaded)) { - result = smum_smc_table_manager(hwmgr, - (uint8_t *)wm_table, TABLE_WATERMARKS, false); - PP_ASSERT_WITH_CODE(!result, - "Failed to update WMTABLE!", - return result); - data->water_marks_bitmap |= WaterMarksLoaded; - } - - if ((data->water_marks_bitmap & WaterMarksExist) && - data->smu_features[GNLD_DPM_DCEFCLK].supported && - data->smu_features[GNLD_DPM_SOCCLK].supported) { - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_NumOfDisplays, - hwmgr->display_config->num_display, - NULL); - } - - return result; -} - -static int vega20_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - int ret = 0; - - if (data->smu_features[GNLD_DPM_UVD].supported) { - if (data->smu_features[GNLD_DPM_UVD].enabled == enable) { - if (enable) - PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already enabled!\n"); - else - PP_DBG_LOG("[EnableDisableUVDDPM] feature DPM UVD already disabled!\n"); - } - - ret = vega20_enable_smc_features(hwmgr, - enable, - data->smu_features[GNLD_DPM_UVD].smu_feature_bitmap); - PP_ASSERT_WITH_CODE(!ret, - "[EnableDisableUVDDPM] Attempt to Enable/Disable DPM UVD Failed!", - return ret); - data->smu_features[GNLD_DPM_UVD].enabled = enable; - } - - return 0; -} - -static void vega20_power_gate_vce(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - - if (data->vce_power_gated == bgate) - return ; - - data->vce_power_gated = bgate; - if (bgate) { - vega20_enable_disable_vce_dpm(hwmgr, !bgate); - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_GATE); - } else { - amdgpu_device_ip_set_powergating_state(hwmgr->adev, - AMD_IP_BLOCK_TYPE_VCE, - AMD_PG_STATE_UNGATE); - vega20_enable_disable_vce_dpm(hwmgr, !bgate); - } - -} - -static void vega20_power_gate_uvd(struct pp_hwmgr *hwmgr, bool bgate) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - - if (data->uvd_power_gated == bgate) - return ; - - data->uvd_power_gated = bgate; - vega20_enable_disable_uvd_dpm(hwmgr, !bgate); -} - -static int vega20_apply_clocks_adjust_rules(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - struct vega20_single_dpm_table *dpm_table; - bool vblank_too_short = false; - bool disable_mclk_switching; - bool disable_fclk_switching; - uint32_t i, latency; - - disable_mclk_switching = ((1 < hwmgr->display_config->num_display) && - !hwmgr->display_config->multi_monitor_in_sync) || - vblank_too_short; - latency = hwmgr->display_config->dce_tolerable_mclk_in_active_latency; - - /* gfxclk */ - dpm_table = &(data->dpm_table.gfx_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_GFXCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_GFXCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* memclk */ - dpm_table = &(data->dpm_table.mem_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_MCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_MCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[0].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* honour DAL's UCLK Hardmin */ - if (dpm_table->dpm_state.hard_min_level < (hwmgr->display_config->min_mem_set_clock / 100)) - dpm_table->dpm_state.hard_min_level = hwmgr->display_config->min_mem_set_clock / 100; - - /* Hardmin is dependent on displayconfig */ - if (disable_mclk_switching) { - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - for (i = 0; i < data->mclk_latency_table.count - 1; i++) { - if (data->mclk_latency_table.entries[i].latency <= latency) { - if (dpm_table->dpm_levels[i].value >= (hwmgr->display_config->min_mem_set_clock / 100)) { - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[i].value; - break; - } - } - } - } - - if (hwmgr->display_config->nb_pstate_switch_disable) - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - if ((disable_mclk_switching && - (dpm_table->dpm_state.hard_min_level == dpm_table->dpm_levels[dpm_table->count - 1].value)) || - hwmgr->display_config->min_mem_set_clock / 100 >= dpm_table->dpm_levels[dpm_table->count - 1].value) - disable_fclk_switching = true; - else - disable_fclk_switching = false; - - /* fclk */ - dpm_table = &(data->dpm_table.fclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - if (hwmgr->display_config->nb_pstate_switch_disable || disable_fclk_switching) - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - - /* vclk */ - dpm_table = &(data->dpm_table.vclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* dclk */ - dpm_table = &(data->dpm_table.dclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_UVDCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_UVDCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* socclk */ - dpm_table = &(data->dpm_table.soc_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_SOCCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_SOCCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - /* eclk */ - dpm_table = &(data->dpm_table.eclk_table); - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.soft_max_level = VG20_CLOCK_MAX_DEFAULT; - dpm_table->dpm_state.hard_min_level = dpm_table->dpm_levels[0].value; - dpm_table->dpm_state.hard_max_level = VG20_CLOCK_MAX_DEFAULT; - - if (PP_CAP(PHM_PlatformCaps_UMDPState)) { - if (VEGA20_UMD_PSTATE_VCEMCLK_LEVEL < dpm_table->count) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[VEGA20_UMD_PSTATE_VCEMCLK_LEVEL].value; - } - - if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - dpm_table->dpm_state.soft_min_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - dpm_table->dpm_state.soft_max_level = dpm_table->dpm_levels[dpm_table->count - 1].value; - } - } - - return 0; -} - -static bool -vega20_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - bool is_update_required = false; - - if (data->display_timing.num_existing_displays != - hwmgr->display_config->num_display) - is_update_required = true; - - if (data->registry_data.gfx_clk_deep_sleep_support && - (data->display_timing.min_clock_in_sr != - hwmgr->display_config->min_core_set_clock_in_sr)) - is_update_required = true; - - return is_update_required; -} - -static int vega20_disable_dpm_tasks(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - - ret = vega20_disable_all_smu_features(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "[DisableDpmTasks] Failed to disable all smu features!", - return ret); - - return 0; -} - -static int vega20_power_off_asic(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - int result; - - result = vega20_disable_dpm_tasks(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "[PowerOffAsic] Failed to disable DPM!", - ); - data->water_marks_bitmap &= ~(WaterMarksLoaded); - - return result; -} - -static int conv_power_profile_to_pplib_workload(int power_profile) -{ - int pplib_workload = 0; - - switch (power_profile) { - case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT: - pplib_workload = WORKLOAD_DEFAULT_BIT; - break; - case PP_SMC_POWER_PROFILE_FULLSCREEN3D: - pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT; - break; - case PP_SMC_POWER_PROFILE_POWERSAVING: - pplib_workload = WORKLOAD_PPLIB_POWER_SAVING_BIT; - break; - case PP_SMC_POWER_PROFILE_VIDEO: - pplib_workload = WORKLOAD_PPLIB_VIDEO_BIT; - break; - case PP_SMC_POWER_PROFILE_VR: - pplib_workload = WORKLOAD_PPLIB_VR_BIT; - break; - case PP_SMC_POWER_PROFILE_COMPUTE: - pplib_workload = WORKLOAD_PPLIB_COMPUTE_BIT; - break; - case PP_SMC_POWER_PROFILE_CUSTOM: - pplib_workload = WORKLOAD_PPLIB_CUSTOM_BIT; - break; - } - - return pplib_workload; -} - -static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - uint32_t i, size = 0; - uint16_t workload_type = 0; - static const char *profile_name[] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - static const char *title[] = { - "PROFILE_INDEX(NAME)", - "CLOCK_TYPE(NAME)", - "FPS", - "UseRlcBusy", - "MinActiveFreqType", - "MinActiveFreq", - "BoosterFreqType", - "BoosterFreq", - "PD_Data_limit_c", - "PD_Data_error_coeff", - "PD_Data_error_rate_coeff"}; - int result = 0; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", - title[0], title[1], title[2], title[3], title[4], title[5], - title[6], title[7], title[8], title[9], title[10]); - - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = conv_power_profile_to_pplib_workload(i); - result = vega20_get_activity_monitor_coeff(hwmgr, - (uint8_t *)(&activity_monitor), workload_type); - PP_ASSERT_WITH_CODE(!result, - "[GetPowerProfile] Failed to get activity monitor!", - return result); - - size += sprintf(buf + size, "%2d %14s%s:\n", - i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " "); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 0, - "GFXCLK", - activity_monitor.Gfx_FPS, - activity_monitor.Gfx_UseRlcBusy, - activity_monitor.Gfx_MinActiveFreqType, - activity_monitor.Gfx_MinActiveFreq, - activity_monitor.Gfx_BoosterFreqType, - activity_monitor.Gfx_BoosterFreq, - activity_monitor.Gfx_PD_Data_limit_c, - activity_monitor.Gfx_PD_Data_error_coeff, - activity_monitor.Gfx_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 1, - "SOCCLK", - activity_monitor.Soc_FPS, - activity_monitor.Soc_UseRlcBusy, - activity_monitor.Soc_MinActiveFreqType, - activity_monitor.Soc_MinActiveFreq, - activity_monitor.Soc_BoosterFreqType, - activity_monitor.Soc_BoosterFreq, - activity_monitor.Soc_PD_Data_limit_c, - activity_monitor.Soc_PD_Data_error_coeff, - activity_monitor.Soc_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 2, - "UCLK", - activity_monitor.Mem_FPS, - activity_monitor.Mem_UseRlcBusy, - activity_monitor.Mem_MinActiveFreqType, - activity_monitor.Mem_MinActiveFreq, - activity_monitor.Mem_BoosterFreqType, - activity_monitor.Mem_BoosterFreq, - activity_monitor.Mem_PD_Data_limit_c, - activity_monitor.Mem_PD_Data_error_coeff, - activity_monitor.Mem_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 3, - "FCLK", - activity_monitor.Fclk_FPS, - activity_monitor.Fclk_UseRlcBusy, - activity_monitor.Fclk_MinActiveFreqType, - activity_monitor.Fclk_MinActiveFreq, - activity_monitor.Fclk_BoosterFreqType, - activity_monitor.Fclk_BoosterFreq, - activity_monitor.Fclk_PD_Data_limit_c, - activity_monitor.Fclk_PD_Data_error_coeff, - activity_monitor.Fclk_PD_Data_error_rate_coeff); - } - - return size; -} - -static int vega20_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - int workload_type, result = 0; - uint32_t power_profile_mode = input[size]; - - if (power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - pr_err("Invalid power profile mode %d\n", power_profile_mode); - return -EINVAL; - } - - if (power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - if (size == 0 && !data->is_custom_profile_set) - return -EINVAL; - if (size < 10 && size != 0) - return -EINVAL; - - result = vega20_get_activity_monitor_coeff(hwmgr, - (uint8_t *)(&activity_monitor), - WORKLOAD_PPLIB_CUSTOM_BIT); - PP_ASSERT_WITH_CODE(!result, - "[SetPowerProfile] Failed to get activity monitor!", - return result); - - /* If size==0, then we want to apply the already-configured - * CUSTOM profile again. Just apply it, since we checked its - * validity above - */ - if (size == 0) - goto out; - - switch (input[0]) { - case 0: /* Gfxclk */ - activity_monitor.Gfx_FPS = input[1]; - activity_monitor.Gfx_UseRlcBusy = input[2]; - activity_monitor.Gfx_MinActiveFreqType = input[3]; - activity_monitor.Gfx_MinActiveFreq = input[4]; - activity_monitor.Gfx_BoosterFreqType = input[5]; - activity_monitor.Gfx_BoosterFreq = input[6]; - activity_monitor.Gfx_PD_Data_limit_c = input[7]; - activity_monitor.Gfx_PD_Data_error_coeff = input[8]; - activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; - break; - case 1: /* Socclk */ - activity_monitor.Soc_FPS = input[1]; - activity_monitor.Soc_UseRlcBusy = input[2]; - activity_monitor.Soc_MinActiveFreqType = input[3]; - activity_monitor.Soc_MinActiveFreq = input[4]; - activity_monitor.Soc_BoosterFreqType = input[5]; - activity_monitor.Soc_BoosterFreq = input[6]; - activity_monitor.Soc_PD_Data_limit_c = input[7]; - activity_monitor.Soc_PD_Data_error_coeff = input[8]; - activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; - break; - case 2: /* Uclk */ - activity_monitor.Mem_FPS = input[1]; - activity_monitor.Mem_UseRlcBusy = input[2]; - activity_monitor.Mem_MinActiveFreqType = input[3]; - activity_monitor.Mem_MinActiveFreq = input[4]; - activity_monitor.Mem_BoosterFreqType = input[5]; - activity_monitor.Mem_BoosterFreq = input[6]; - activity_monitor.Mem_PD_Data_limit_c = input[7]; - activity_monitor.Mem_PD_Data_error_coeff = input[8]; - activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; - break; - case 3: /* Fclk */ - activity_monitor.Fclk_FPS = input[1]; - activity_monitor.Fclk_UseRlcBusy = input[2]; - activity_monitor.Fclk_MinActiveFreqType = input[3]; - activity_monitor.Fclk_MinActiveFreq = input[4]; - activity_monitor.Fclk_BoosterFreqType = input[5]; - activity_monitor.Fclk_BoosterFreq = input[6]; - activity_monitor.Fclk_PD_Data_limit_c = input[7]; - activity_monitor.Fclk_PD_Data_error_coeff = input[8]; - activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; - break; - } - - result = vega20_set_activity_monitor_coeff(hwmgr, - (uint8_t *)(&activity_monitor), - WORKLOAD_PPLIB_CUSTOM_BIT); - data->is_custom_profile_set = true; - PP_ASSERT_WITH_CODE(!result, - "[SetPowerProfile] Failed to set activity monitor!", - return result); - } - -out: - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = - conv_power_profile_to_pplib_workload(power_profile_mode); - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask, - 1 << workload_type, - NULL); - - hwmgr->power_profile_mode = power_profile_mode; - - return 0; -} - -static int vega20_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size) -{ - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrHigh, - virtual_addr_hi, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetSystemVirtualDramAddrLow, - virtual_addr_low, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrHigh, - mc_addr_hi, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramAddrLow, - mc_addr_low, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DramLogSetDramSize, - size, - NULL); - return 0; -} - -static int vega20_get_thermal_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *thermal_data) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - - memcpy(thermal_data, &SMU7ThermalWithDelayPolicy[0], sizeof(struct PP_TemperatureRange)); - - thermal_data->max = pp_table->TedgeLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->edge_emergency_max = (pp_table->TedgeLimit + CTF_OFFSET_EDGE) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_crit_max = pp_table->ThotspotLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->hotspot_emergency_max = (pp_table->ThotspotLimit + CTF_OFFSET_HOTSPOT) * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_crit_max = pp_table->ThbmLimit * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - thermal_data->mem_emergency_max = (pp_table->ThbmLimit + CTF_OFFSET_HBM)* - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int vega20_smu_i2c_bus_access(struct pp_hwmgr *hwmgr, bool acquire) -{ - int res; - - /* I2C bus access can happen very early, when SMU not loaded yet */ - if (!vega20_is_smc_ram_running(hwmgr)) - return 0; - - res = smum_send_msg_to_smc_with_parameter(hwmgr, - (acquire ? - PPSMC_MSG_RequestI2CBus : - PPSMC_MSG_ReleaseI2CBus), - 0, - NULL); - - PP_ASSERT_WITH_CODE(!res, "[SmuI2CAccessBus] Failed to access bus!", return res); - return res; -} - -static int vega20_set_df_cstate(struct pp_hwmgr *hwmgr, - enum pp_df_cstate state) -{ - int ret; - - /* PPSMC_MSG_DFCstateControl is supported with 40.50 and later fws */ - if (hwmgr->smu_version < 0x283200) { - pr_err("Df cstate control is supported with 40.50 and later SMC fw!\n"); - return -EINVAL; - } - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DFCstateControl, state, - NULL); - if (ret) - pr_err("SetDfCstate failed!\n"); - - return ret; -} - -static int vega20_set_xgmi_pstate(struct pp_hwmgr *hwmgr, - uint32_t pstate) -{ - int ret; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetXgmiMode, - pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, - NULL); - if (ret) - pr_err("SetXgmiPstate failed!\n"); - - return ret; -} - -static void vega20_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) -{ - memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); - - gpu_metrics->common_header.structure_size = - sizeof(struct gpu_metrics_v1_0); - gpu_metrics->common_header.format_revision = 1; - gpu_metrics->common_header.content_revision = 0; - - gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); -} - -static ssize_t vega20_get_gpu_metrics(struct pp_hwmgr *hwmgr, - void **table) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - struct gpu_metrics_v1_0 *gpu_metrics = - &data->gpu_metrics_table; - SmuMetrics_t metrics; - uint32_t fan_speed_rpm; - int ret; - - ret = vega20_get_metrics_table(hwmgr, &metrics, true); - if (ret) - return ret; - - vega20_init_gpu_metrics_v1_0(gpu_metrics); - - gpu_metrics->temperature_edge = metrics.TemperatureEdge; - gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; - gpu_metrics->temperature_mem = metrics.TemperatureHBM; - gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; - gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; - gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; - - gpu_metrics->average_socket_power = metrics.AverageSocketPower; - - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; - gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; - gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; - - gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; - gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; - gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; - gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; - gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - vega20_fan_ctrl_get_fan_speed_rpm(hwmgr, &fan_speed_rpm); - gpu_metrics->current_fan_speed = (uint16_t)fan_speed_rpm; - - gpu_metrics->pcie_link_width = - vega20_get_current_pcie_link_width(hwmgr); - gpu_metrics->pcie_link_speed = - vega20_get_current_pcie_link_speed(hwmgr); - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v1_0); -} - -static const struct pp_hwmgr_func vega20_hwmgr_funcs = { - /* init/fini related */ - .backend_init = vega20_hwmgr_backend_init, - .backend_fini = vega20_hwmgr_backend_fini, - .asic_setup = vega20_setup_asic_task, - .power_off_asic = vega20_power_off_asic, - .dynamic_state_management_enable = vega20_enable_dpm_tasks, - .dynamic_state_management_disable = vega20_disable_dpm_tasks, - /* power state related */ - .apply_clocks_adjust_rules = vega20_apply_clocks_adjust_rules, - .pre_display_config_changed = vega20_pre_display_configuration_changed_task, - .display_config_changed = vega20_display_configuration_changed_task, - .check_smc_update_required_for_display_configuration = - vega20_check_smc_update_required_for_display_configuration, - .notify_smc_display_config_after_ps_adjustment = - vega20_notify_smc_display_config_after_ps_adjustment, - /* export to DAL */ - .get_sclk = vega20_dpm_get_sclk, - .get_mclk = vega20_dpm_get_mclk, - .get_dal_power_level = vega20_get_dal_power_level, - .get_clock_by_type_with_latency = vega20_get_clock_by_type_with_latency, - .get_clock_by_type_with_voltage = vega20_get_clock_by_type_with_voltage, - .set_watermarks_for_clocks_ranges = vega20_set_watermarks_for_clocks_ranges, - .display_clock_voltage_request = vega20_display_clock_voltage_request, - .get_performance_level = vega20_get_performance_level, - /* UMD pstate, profile related */ - .force_dpm_level = vega20_dpm_force_dpm_level, - .get_power_profile_mode = vega20_get_power_profile_mode, - .set_power_profile_mode = vega20_set_power_profile_mode, - /* od related */ - .set_power_limit = vega20_set_power_limit, - .get_sclk_od = vega20_get_sclk_od, - .set_sclk_od = vega20_set_sclk_od, - .get_mclk_od = vega20_get_mclk_od, - .set_mclk_od = vega20_set_mclk_od, - .odn_edit_dpm_table = vega20_odn_edit_dpm_table, - /* for sysfs to retrive/set gfxclk/memclk */ - .force_clock_level = vega20_force_clock_level, - .print_clock_levels = vega20_print_clock_levels, - .read_sensor = vega20_read_sensor, - .get_ppfeature_status = vega20_get_ppfeature_status, - .set_ppfeature_status = vega20_set_ppfeature_status, - /* powergate related */ - .powergate_uvd = vega20_power_gate_uvd, - .powergate_vce = vega20_power_gate_vce, - /* thermal related */ - .start_thermal_controller = vega20_start_thermal_controller, - .stop_thermal_controller = vega20_thermal_stop_thermal_controller, - .get_thermal_temperature_range = vega20_get_thermal_temperature_range, - .register_irq_handlers = smu9_register_irq_handlers, - .disable_smc_firmware_ctf = vega20_thermal_disable_alert, - /* fan control related */ - .get_fan_speed_percent = vega20_fan_ctrl_get_fan_speed_percent, - .set_fan_speed_percent = vega20_fan_ctrl_set_fan_speed_percent, - .get_fan_speed_info = vega20_fan_ctrl_get_fan_speed_info, - .get_fan_speed_rpm = vega20_fan_ctrl_get_fan_speed_rpm, - .set_fan_speed_rpm = vega20_fan_ctrl_set_fan_speed_rpm, - .get_fan_control_mode = vega20_get_fan_control_mode, - .set_fan_control_mode = vega20_set_fan_control_mode, - /* smu memory related */ - .notify_cac_buffer_info = vega20_notify_cac_buffer_info, - .enable_mgpu_fan_boost = vega20_enable_mgpu_fan_boost, - /* BACO related */ - .get_asic_baco_capability = vega20_baco_get_capability, - .get_asic_baco_state = vega20_baco_get_state, - .set_asic_baco_state = vega20_baco_set_state, - .set_mp1_state = vega20_set_mp1_state, - .smu_i2c_bus_access = vega20_smu_i2c_bus_access, - .set_df_cstate = vega20_set_df_cstate, - .set_xgmi_pstate = vega20_set_xgmi_pstate, - .get_gpu_metrics = vega20_get_gpu_metrics, -}; - -int vega20_hwmgr_init(struct pp_hwmgr *hwmgr) -{ - hwmgr->hwmgr_func = &vega20_hwmgr_funcs; - hwmgr->pptable_func = &vega20_pptable_funcs; - - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h deleted file mode 100644 index 075c0094da9c..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright 2018 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 _VEGA20_HWMGR_H_ -#define _VEGA20_HWMGR_H_ - -#include "hwmgr.h" -#include "smu11_driver_if.h" -#include "ppatomfwctrl.h" - -#define VEGA20_MAX_HARDWARE_POWERLEVELS 2 - -#define WaterMarksExist 1 -#define WaterMarksLoaded 2 - -#define VG20_PSUEDO_NUM_GFXCLK_DPM_LEVELS 8 -#define VG20_PSUEDO_NUM_SOCCLK_DPM_LEVELS 8 -#define VG20_PSUEDO_NUM_DCEFCLK_DPM_LEVELS 8 -#define VG20_PSUEDO_NUM_UCLK_DPM_LEVELS 4 - -//OverDriver8 macro defs -#define AVFS_CURVE 0 -#define OD8_HOTCURVE_TEMPERATURE 85 - -#define VG20_CLOCK_MAX_DEFAULT 0xFFFF - -typedef uint32_t PP_Clock; - -enum { - GNLD_DPM_PREFETCHER = 0, - GNLD_DPM_GFXCLK, - GNLD_DPM_UCLK, - GNLD_DPM_SOCCLK, - GNLD_DPM_UVD, - GNLD_DPM_VCE, - GNLD_ULV, - GNLD_DPM_MP0CLK, - GNLD_DPM_LINK, - GNLD_DPM_DCEFCLK, - GNLD_DS_GFXCLK, - GNLD_DS_SOCCLK, - GNLD_DS_LCLK, - GNLD_PPT, - GNLD_TDC, - GNLD_THERMAL, - GNLD_GFX_PER_CU_CG, - GNLD_RM, - GNLD_DS_DCEFCLK, - GNLD_ACDC, - GNLD_VR0HOT, - GNLD_VR1HOT, - GNLD_FW_CTF, - GNLD_LED_DISPLAY, - GNLD_FAN_CONTROL, - GNLD_DIDT, - GNLD_GFXOFF, - GNLD_CG, - GNLD_DPM_FCLK, - GNLD_DS_FCLK, - GNLD_DS_MP1CLK, - GNLD_DS_MP0CLK, - GNLD_XGMI, - GNLD_ECC, - - GNLD_FEATURES_MAX -}; - - -#define GNLD_DPM_MAX (GNLD_DPM_DCEFCLK + 1) - -#define SMC_DPM_FEATURES 0x30F - -struct smu_features { - bool supported; - bool enabled; - bool allowed; - uint32_t smu_feature_id; - uint64_t smu_feature_bitmap; -}; - -struct vega20_performance_level { - uint32_t soc_clock; - uint32_t gfx_clock; - uint32_t mem_clock; -}; - -struct vega20_bacos { - uint32_t baco_flags; - /* struct vega20_performance_level performance_level; */ -}; - -struct vega20_uvd_clocks { - uint32_t vclk; - uint32_t dclk; -}; - -struct vega20_vce_clocks { - uint32_t evclk; - uint32_t ecclk; -}; - -struct vega20_power_state { - uint32_t magic; - struct vega20_uvd_clocks uvd_clks; - struct vega20_vce_clocks vce_clks; - uint16_t performance_level_count; - bool dc_compatible; - uint32_t sclk_threshold; - struct vega20_performance_level performance_levels[VEGA20_MAX_HARDWARE_POWERLEVELS]; -}; - -struct vega20_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -#define VEGA20_MAX_DEEPSLEEP_DIVIDER_ID 5 -#define MAX_REGULAR_DPM_NUMBER 16 -#define MAX_PCIE_CONF 2 -#define VEGA20_MINIMUM_ENGINE_CLOCK 2500 - -struct vega20_max_sustainable_clocks { - PP_Clock display_clock; - PP_Clock phy_clock; - PP_Clock pixel_clock; - PP_Clock uclock; - PP_Clock dcef_clock; - PP_Clock soc_clock; -}; - -struct vega20_dpm_state { - uint32_t soft_min_level; - uint32_t soft_max_level; - uint32_t hard_min_level; - uint32_t hard_max_level; -}; - -struct vega20_single_dpm_table { - uint32_t count; - struct vega20_dpm_state dpm_state; - struct vega20_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega20_odn_dpm_control { - uint32_t count; - uint32_t entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega20_pcie_table { - uint16_t count; - uint8_t pcie_gen[MAX_PCIE_CONF]; - uint8_t pcie_lane[MAX_PCIE_CONF]; - uint32_t lclk[MAX_PCIE_CONF]; -}; - -struct vega20_dpm_table { - struct vega20_single_dpm_table soc_table; - struct vega20_single_dpm_table gfx_table; - struct vega20_single_dpm_table mem_table; - struct vega20_single_dpm_table eclk_table; - struct vega20_single_dpm_table vclk_table; - struct vega20_single_dpm_table dclk_table; - struct vega20_single_dpm_table dcef_table; - struct vega20_single_dpm_table pixel_table; - struct vega20_single_dpm_table display_table; - struct vega20_single_dpm_table phy_table; - struct vega20_single_dpm_table fclk_table; - struct vega20_pcie_table pcie_table; -}; - -#define VEGA20_MAX_LEAKAGE_COUNT 8 -struct vega20_leakage_voltage { - uint16_t count; - uint16_t leakage_id[VEGA20_MAX_LEAKAGE_COUNT]; - uint16_t actual_voltage[VEGA20_MAX_LEAKAGE_COUNT]; -}; - -struct vega20_display_timing { - uint32_t min_clock_in_sr; - uint32_t num_existing_displays; -}; - -struct vega20_dpmlevel_enable_mask { - uint32_t uvd_dpm_enable_mask; - uint32_t vce_dpm_enable_mask; - uint32_t samu_dpm_enable_mask; - uint32_t sclk_dpm_enable_mask; - uint32_t mclk_dpm_enable_mask; -}; - -struct vega20_vbios_boot_state { - uint8_t uc_cooling_id; - uint16_t vddc; - uint16_t vddci; - uint16_t mvddc; - uint16_t vdd_gfx; - uint32_t gfx_clock; - uint32_t mem_clock; - uint32_t soc_clock; - uint32_t dcef_clock; - uint32_t eclock; - uint32_t dclock; - uint32_t vclock; - uint32_t fclock; -}; - -#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 -#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 -#define DPMTABLE_UPDATE_SCLK 0x00000004 -#define DPMTABLE_UPDATE_MCLK 0x00000008 -#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 -#define DPMTABLE_OD_UPDATE_SCLK_MASK 0x00000020 -#define DPMTABLE_OD_UPDATE_MCLK_MASK 0x00000040 - -// To determine if sclk and mclk are in overdrive state -#define SCLK_MASK_OVERDRIVE_ENABLED 0x00000008 -#define MCLK_MASK_OVERDRIVE_ENABLED 0x00000010 -#define SOCCLK_OVERDRIVE_ENABLED 0x00000020 - -struct vega20_smc_state_table { - uint32_t soc_boot_level; - uint32_t gfx_boot_level; - uint32_t dcef_boot_level; - uint32_t mem_boot_level; - uint32_t uvd_boot_level; - uint32_t vce_boot_level; - uint32_t gfx_max_level; - uint32_t mem_max_level; - uint8_t vr_hot_gpio; - uint8_t ac_dc_gpio; - uint8_t therm_out_gpio; - uint8_t therm_out_polarity; - uint8_t therm_out_mode; - PPTable_t pp_table; - Watermarks_t water_marks_table; - AvfsDebugTable_t avfs_debug_table; - AvfsFuseOverride_t avfs_fuse_override_table; - SmuMetrics_t smu_metrics; - DriverSmuConfig_t driver_smu_config; - DpmActivityMonitorCoeffInt_t dpm_activity_monitor_coeffint; - OverDriveTable_t overdrive_table; -}; - -struct vega20_mclk_latency_entries { - uint32_t frequency; - uint32_t latency; -}; - -struct vega20_mclk_latency_table { - uint32_t count; - struct vega20_mclk_latency_entries entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega20_registry_data { - uint64_t disallowed_features; - uint8_t ac_dc_switch_gpio_support; - uint8_t acg_loop_support; - uint8_t clock_stretcher_support; - uint8_t db_ramping_support; - uint8_t didt_mode; - uint8_t didt_support; - uint8_t edc_didt_support; - uint8_t force_dpm_high; - uint8_t fuzzy_fan_control_support; - uint8_t mclk_dpm_key_disabled; - uint8_t od_state_in_dc_support; - uint8_t pcie_lane_override; - uint8_t pcie_speed_override; - uint32_t pcie_clock_override; - uint8_t pcie_dpm_key_disabled; - uint8_t dcefclk_dpm_key_disabled; - uint8_t prefetcher_dpm_key_disabled; - uint8_t quick_transition_support; - uint8_t regulator_hot_gpio_support; - uint8_t master_deep_sleep_support; - uint8_t gfx_clk_deep_sleep_support; - uint8_t sclk_deep_sleep_support; - uint8_t lclk_deep_sleep_support; - uint8_t dce_fclk_deep_sleep_support; - uint8_t sclk_dpm_key_disabled; - uint8_t sclk_throttle_low_notification; - uint8_t skip_baco_hardware; - uint8_t socclk_dpm_key_disabled; - uint8_t sq_ramping_support; - uint8_t tcp_ramping_support; - uint8_t td_ramping_support; - uint8_t dbr_ramping_support; - uint8_t gc_didt_support; - uint8_t psm_didt_support; - uint8_t thermal_support; - uint8_t fw_ctf_enabled; - uint8_t led_dpm_enabled; - uint8_t fan_control_support; - uint8_t ulv_support; - uint8_t od8_feature_enable; - uint8_t disable_water_mark; - uint8_t disable_workload_policy; - uint32_t force_workload_policy_mask; - uint8_t disable_3d_fs_detection; - uint8_t disable_pp_tuning; - uint8_t disable_xlpp_tuning; - uint32_t perf_ui_tuning_profile_turbo; - uint32_t perf_ui_tuning_profile_powerSave; - uint32_t perf_ui_tuning_profile_xl; - uint16_t zrpm_stop_temp; - uint16_t zrpm_start_temp; - uint32_t stable_pstate_sclk_dpm_percentage; - uint8_t fps_support; - uint8_t vr0hot; - uint8_t vr1hot; - uint8_t disable_auto_wattman; - uint32_t auto_wattman_debug; - uint32_t auto_wattman_sample_period; - uint32_t fclk_gfxclk_ratio; - uint8_t auto_wattman_threshold; - uint8_t log_avfs_param; - uint8_t enable_enginess; - uint8_t custom_fan_support; - uint8_t disable_pcc_limit_control; - uint8_t gfxoff_controlled_by_driver; -}; - -struct vega20_odn_clock_voltage_dependency_table { - uint32_t count; - struct phm_ppt_v1_clock_voltage_dependency_record - entries[MAX_REGULAR_DPM_NUMBER]; -}; - -struct vega20_odn_dpm_table { - struct vega20_odn_dpm_control control_gfxclk_state; - struct vega20_odn_dpm_control control_memclk_state; - struct phm_odn_clock_levels odn_core_clock_dpm_levels; - struct phm_odn_clock_levels odn_memory_clock_dpm_levels; - struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_sclk; - struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_mclk; - struct vega20_odn_clock_voltage_dependency_table vdd_dependency_on_socclk; - uint32_t odn_mclk_min_limit; -}; - -struct vega20_odn_fan_table { - uint32_t target_fan_speed; - uint32_t target_temperature; - uint32_t min_performance_clock; - uint32_t min_fan_limit; - bool force_fan_pwm; -}; - -struct vega20_odn_temp_table { - uint16_t target_operating_temp; - uint16_t default_target_operating_temp; - uint16_t operating_temp_min_limit; - uint16_t operating_temp_max_limit; - uint16_t operating_temp_step; -}; - -struct vega20_odn_data { - uint32_t apply_overdrive_next_settings_mask; - uint32_t overdrive_next_state; - uint32_t overdrive_next_capabilities; - uint32_t odn_sclk_dpm_enable_mask; - uint32_t odn_mclk_dpm_enable_mask; - struct vega20_odn_dpm_table odn_dpm_table; - struct vega20_odn_fan_table odn_fan_table; - struct vega20_odn_temp_table odn_temp_table; -}; - -enum OD8_FEATURE_ID -{ - OD8_GFXCLK_LIMITS = 1 << 0, - OD8_GFXCLK_CURVE = 1 << 1, - OD8_UCLK_MAX = 1 << 2, - OD8_POWER_LIMIT = 1 << 3, - OD8_ACOUSTIC_LIMIT_SCLK = 1 << 4, //FanMaximumRpm - OD8_FAN_SPEED_MIN = 1 << 5, //FanMinimumPwm - OD8_TEMPERATURE_FAN = 1 << 6, //FanTargetTemperature - OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp - OD8_MEMORY_TIMING_TUNE = 1 << 8, - OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 -}; - -enum OD8_SETTING_ID -{ - OD8_SETTING_GFXCLK_FMIN = 0, - OD8_SETTING_GFXCLK_FMAX, - OD8_SETTING_GFXCLK_FREQ1, - OD8_SETTING_GFXCLK_VOLTAGE1, - OD8_SETTING_GFXCLK_FREQ2, - OD8_SETTING_GFXCLK_VOLTAGE2, - OD8_SETTING_GFXCLK_FREQ3, - OD8_SETTING_GFXCLK_VOLTAGE3, - OD8_SETTING_UCLK_FMAX, - OD8_SETTING_POWER_PERCENTAGE, - OD8_SETTING_FAN_ACOUSTIC_LIMIT, - OD8_SETTING_FAN_MIN_SPEED, - OD8_SETTING_FAN_TARGET_TEMP, - OD8_SETTING_OPERATING_TEMP_MAX, - OD8_SETTING_AC_TIMING, - OD8_SETTING_FAN_ZERO_RPM_CONTROL, - OD8_SETTING_COUNT -}; - -struct vega20_od8_single_setting { - uint32_t feature_id; - int32_t min_value; - int32_t max_value; - int32_t current_value; - int32_t default_value; -}; - -struct vega20_od8_settings { - uint32_t overdrive8_capabilities; - struct vega20_od8_single_setting od8_settings_array[OD8_SETTING_COUNT]; -}; - -struct vega20_hwmgr { - struct vega20_dpm_table dpm_table; - struct vega20_dpm_table golden_dpm_table; - struct vega20_registry_data registry_data; - struct vega20_vbios_boot_state vbios_boot_state; - struct vega20_mclk_latency_table mclk_latency_table; - - struct vega20_max_sustainable_clocks max_sustainable_clocks; - - struct vega20_leakage_voltage vddc_leakage; - - uint32_t vddc_control; - struct pp_atomfwctrl_voltage_table vddc_voltage_table; - uint32_t mvdd_control; - struct pp_atomfwctrl_voltage_table mvdd_voltage_table; - uint32_t vddci_control; - struct pp_atomfwctrl_voltage_table vddci_voltage_table; - - uint32_t active_auto_throttle_sources; - struct vega20_bacos bacos; - - /* ---- General data ---- */ - uint8_t need_update_dpm_table; - - bool cac_enabled; - bool battery_state; - bool is_tlu_enabled; - bool avfs_exist; - - uint32_t low_sclk_interrupt_threshold; - - uint32_t total_active_cus; - - uint32_t water_marks_bitmap; - - struct vega20_display_timing display_timing; - - /* ---- Vega20 Dyn Register Settings ---- */ - - uint32_t debug_settings; - uint32_t lowest_uclk_reserved_for_ulv; - uint32_t gfxclk_average_alpha; - uint32_t socclk_average_alpha; - uint32_t uclk_average_alpha; - uint32_t gfx_activity_average_alpha; - uint32_t display_voltage_mode; - uint32_t dcef_clk_quad_eqn_a; - uint32_t dcef_clk_quad_eqn_b; - uint32_t dcef_clk_quad_eqn_c; - uint32_t disp_clk_quad_eqn_a; - uint32_t disp_clk_quad_eqn_b; - uint32_t disp_clk_quad_eqn_c; - uint32_t pixel_clk_quad_eqn_a; - uint32_t pixel_clk_quad_eqn_b; - uint32_t pixel_clk_quad_eqn_c; - uint32_t phy_clk_quad_eqn_a; - uint32_t phy_clk_quad_eqn_b; - uint32_t phy_clk_quad_eqn_c; - - /* ---- Thermal Temperature Setting ---- */ - struct vega20_dpmlevel_enable_mask dpm_level_enable_mask; - - /* ---- Power Gating States ---- */ - bool uvd_power_gated; - bool vce_power_gated; - bool samu_power_gated; - bool need_long_memory_training; - - /* Internal settings to apply the application power optimization parameters */ - bool apply_optimized_settings; - uint32_t disable_dpm_mask; - - /* ---- Overdrive next setting ---- */ - struct vega20_odn_data odn_data; - bool gfxclk_overdrive; - bool memclk_overdrive; - - /* ---- Overdrive8 Setting ---- */ - struct vega20_od8_settings od8_settings; - - /* ---- Workload Mask ---- */ - uint32_t workload_mask; - - /* ---- SMU9 ---- */ - uint32_t smu_version; - struct smu_features smu_features[GNLD_FEATURES_MAX]; - struct vega20_smc_state_table smc_state_table; - - /* ---- Gfxoff ---- */ - bool gfxoff_allowed; - uint32_t counter_gfxoff; - - unsigned long metrics_time; - SmuMetrics_t metrics_table; - struct gpu_metrics_v1_0 gpu_metrics_table; - - bool pcie_parameters_override; - uint32_t pcie_gen_level1; - uint32_t pcie_width_level1; - - bool is_custom_profile_set; -}; - -#define VEGA20_DPM2_NEAR_TDP_DEC 10 -#define VEGA20_DPM2_ABOVE_SAFE_INC 5 -#define VEGA20_DPM2_BELOW_SAFE_INC 20 - -#define VEGA20_DPM2_LTA_WINDOW_SIZE 7 - -#define VEGA20_DPM2_LTS_TRUNCATE 0 - -#define VEGA20_DPM2_TDP_SAFE_LIMIT_PERCENT 80 - -#define VEGA20_DPM2_MAXPS_PERCENT_M 90 -#define VEGA20_DPM2_MAXPS_PERCENT_H 90 - -#define VEGA20_DPM2_PWREFFICIENCYRATIO_MARGIN 50 - -#define VEGA20_DPM2_SQ_RAMP_MAX_POWER 0x3FFF -#define VEGA20_DPM2_SQ_RAMP_MIN_POWER 0x12 -#define VEGA20_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 -#define VEGA20_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E -#define VEGA20_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF - -#define VEGA20_VOLTAGE_CONTROL_NONE 0x0 -#define VEGA20_VOLTAGE_CONTROL_BY_GPIO 0x1 -#define VEGA20_VOLTAGE_CONTROL_BY_SVID2 0x2 -#define VEGA20_VOLTAGE_CONTROL_MERGED 0x3 -/* To convert to Q8.8 format for firmware */ -#define VEGA20_Q88_FORMAT_CONVERSION_UNIT 256 - -#define VEGA20_UNUSED_GPIO_PIN 0x7F - -#define VEGA20_THERM_OUT_MODE_DISABLE 0x0 -#define VEGA20_THERM_OUT_MODE_THERM_ONLY 0x1 -#define VEGA20_THERM_OUT_MODE_THERM_VRHOT 0x2 - -#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff -#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff - -#define PPVEGA20_VEGA20GFXCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA20_VEGA20SOCCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA20_VEGA20UCLKCLKAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA20_VEGA20GFXACTIVITYAVERAGEALPHA_DFLT 25 /* 10% * 255 = 25 */ -#define PPVEGA20_VEGA20LOWESTUCLKRESERVEDFORULV_DFLT 0xffffffff -#define PPVEGA20_VEGA20DISPLAYVOLTAGEMODE_DFLT 0xffffffff -#define PPREGKEY_VEGA20QUADRATICEQUATION_DFLT 0xffffffff - -#define VEGA20_UMD_PSTATE_GFXCLK_LEVEL 0x3 -#define VEGA20_UMD_PSTATE_SOCCLK_LEVEL 0x3 -#define VEGA20_UMD_PSTATE_MCLK_LEVEL 0x2 -#define VEGA20_UMD_PSTATE_UVDCLK_LEVEL 0x3 -#define VEGA20_UMD_PSTATE_VCEMCLK_LEVEL 0x3 - -#endif /* _VEGA20_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h deleted file mode 100644 index 613cb1989b3d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_inc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2018 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 VEGA20_INC_H -#define VEGA20_INC_H - -#include "asic_reg/thm/thm_11_0_2_offset.h" -#include "asic_reg/thm/thm_11_0_2_sh_mask.h" - -#include "asic_reg/mp/mp_9_0_offset.h" -#include "asic_reg/mp/mp_9_0_sh_mask.h" - -#include "asic_reg/nbio/nbio_7_4_offset.h" -#include "asic_reg/nbio/nbio_7_4_sh_mask.h" - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c deleted file mode 100644 index d7cc3d2d9e17..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2018 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 "hwmgr.h" -#include "vega20_hwmgr.h" -#include "vega20_powertune.h" -#include "vega20_smumgr.h" -#include "vega20_ppsmc.h" -#include "vega20_inc.h" -#include "pp_debug.h" - -int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) -{ - struct vega20_hwmgr *data = - (struct vega20_hwmgr *)(hwmgr->backend); - - if (data->smu_features[GNLD_PPT].enabled) - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetPptLimit, n, - NULL); - - return 0; -} - -int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr, - uint32_t tdp_percentage_adjustment, uint32_t tdp_absolute_value_adjustment) -{ - return (tdp_percentage_adjustment > hwmgr->platform_descriptor.TDPLimit) ? -1 : 0; -} - -static int vega20_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr, - uint32_t adjust_percent) -{ - return smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_OverDriveSetPercentage, adjust_percent, - NULL); -} - -int vega20_power_control_set_level(struct pp_hwmgr *hwmgr) -{ - int adjust_percent, result = 0; - - if (PP_CAP(PHM_PlatformCaps_PowerContainment)) { - adjust_percent = - hwmgr->platform_descriptor.TDPAdjustmentPolarity ? - hwmgr->platform_descriptor.TDPAdjustment : - (-1 * hwmgr->platform_descriptor.TDPAdjustment); - result = vega20_set_overdrive_target_percentage(hwmgr, - (uint32_t)adjust_percent); - } - return result; -} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h deleted file mode 100644 index d68c734c0f4e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_powertune.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018 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 _VEGA20_POWERTUNE_H_ -#define _VEGA20_POWERTUNE_H_ - -int vega20_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); -int vega20_power_control_set_level(struct pp_hwmgr *hwmgr); -int vega20_validate_power_level_request(struct pp_hwmgr *hwmgr, - uint32_t tdp_percentage_adjustment, - uint32_t tdp_absolute_value_adjustment); -#endif /* _VEGA20_POWERTUNE_H_ */ - diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h deleted file mode 100644 index 2222e29405c6..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_pptable.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2018 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 _VEGA20_PPTABLE_H_ -#define _VEGA20_PPTABLE_H_ - -#pragma pack(push, 1) - -#define ATOM_VEGA20_PP_THERMALCONTROLLER_NONE 0 -#define ATOM_VEGA20_PP_THERMALCONTROLLER_VEGA20 26 - -#define ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY 0x1 -#define ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x2 -#define ATOM_VEGA20_PP_PLATFORM_CAP_HARDWAREDC 0x4 -#define ATOM_VEGA20_PP_PLATFORM_CAP_BACO 0x8 -#define ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO 0x10 -#define ATOM_VEGA20_PP_PLATFORM_CAP_ENABLESHADOWPSTATE 0x20 - -#define ATOM_VEGA20_TABLE_REVISION_VEGA20 11 -#define ATOM_VEGA20_ODFEATURE_MAX_COUNT 32 -#define ATOM_VEGA20_ODSETTING_MAX_COUNT 32 -#define ATOM_VEGA20_PPCLOCK_MAX_COUNT 16 - -enum ATOM_VEGA20_ODFEATURE_ID { - ATOM_VEGA20_ODFEATURE_GFXCLK_LIMITS = 0, - ATOM_VEGA20_ODFEATURE_GFXCLK_CURVE, - ATOM_VEGA20_ODFEATURE_UCLK_MAX, - ATOM_VEGA20_ODFEATURE_POWER_LIMIT, - ATOM_VEGA20_ODFEATURE_FAN_ACOUSTIC_LIMIT, //FanMaximumRpm - ATOM_VEGA20_ODFEATURE_FAN_SPEED_MIN, //FanMinimumPwm - ATOM_VEGA20_ODFEATURE_TEMPERATURE_FAN, //FanTargetTemperature - ATOM_VEGA20_ODFEATURE_TEMPERATURE_SYSTEM, //MaxOpTemp - ATOM_VEGA20_ODFEATURE_MEMORY_TIMING_TUNE, - ATOM_VEGA20_ODFEATURE_FAN_ZERO_RPM_CONTROL, - ATOM_VEGA20_ODFEATURE_COUNT, -}; - -enum ATOM_VEGA20_ODSETTING_ID { - ATOM_VEGA20_ODSETTING_GFXCLKFMAX = 0, - ATOM_VEGA20_ODSETTING_GFXCLKFMIN, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P1, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P1, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P2, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P2, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEFREQ_P3, - ATOM_VEGA20_ODSETTING_VDDGFXCURVEVOLTAGEOFFSET_P3, - ATOM_VEGA20_ODSETTING_UCLKFMAX, - ATOM_VEGA20_ODSETTING_POWERPERCENTAGE, - ATOM_VEGA20_ODSETTING_FANRPMMIN, - ATOM_VEGA20_ODSETTING_FANRPMACOUSTICLIMIT, - ATOM_VEGA20_ODSETTING_FANTARGETTEMPERATURE, - ATOM_VEGA20_ODSETTING_OPERATINGTEMPMAX, - ATOM_VEGA20_ODSETTING_COUNT, -}; -typedef enum ATOM_VEGA20_ODSETTING_ID ATOM_VEGA20_ODSETTING_ID; - -typedef struct _ATOM_VEGA20_OVERDRIVE8_RECORD -{ - UCHAR ucODTableRevision; - ULONG ODFeatureCount; - UCHAR ODFeatureCapabilities [ATOM_VEGA20_ODFEATURE_MAX_COUNT]; //OD feature support flags - ULONG ODSettingCount; - ULONG ODSettingsMax [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Upper Limit for each OD Setting - ULONG ODSettingsMin [ATOM_VEGA20_ODSETTING_MAX_COUNT]; //Lower Limit for each OD Setting -} ATOM_VEGA20_OVERDRIVE8_RECORD; - -enum ATOM_VEGA20_PPCLOCK_ID { - ATOM_VEGA20_PPCLOCK_GFXCLK = 0, - ATOM_VEGA20_PPCLOCK_VCLK, - ATOM_VEGA20_PPCLOCK_DCLK, - ATOM_VEGA20_PPCLOCK_ECLK, - ATOM_VEGA20_PPCLOCK_SOCCLK, - ATOM_VEGA20_PPCLOCK_UCLK, - ATOM_VEGA20_PPCLOCK_FCLK, - ATOM_VEGA20_PPCLOCK_DCEFCLK, - ATOM_VEGA20_PPCLOCK_DISPCLK, - ATOM_VEGA20_PPCLOCK_PIXCLK, - ATOM_VEGA20_PPCLOCK_PHYCLK, - ATOM_VEGA20_PPCLOCK_COUNT, -}; -typedef enum ATOM_VEGA20_PPCLOCK_ID ATOM_VEGA20_PPCLOCK_ID; - -typedef struct _ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD -{ - UCHAR ucTableRevision; - ULONG PowerSavingClockCount; // Count of PowerSavingClock Mode - ULONG PowerSavingClockMax [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Maximum array In MHz - ULONG PowerSavingClockMin [ATOM_VEGA20_PPCLOCK_MAX_COUNT]; // PowerSavingClock Mode Clock Minimum array In MHz -} ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD; - -typedef struct _ATOM_VEGA20_POWERPLAYTABLE -{ - struct atom_common_table_header sHeader; - UCHAR ucTableRevision; - USHORT usTableSize; - ULONG ulGoldenPPID; - ULONG ulGoldenRevision; - USHORT usFormatID; - - ULONG ulPlatformCaps; - - UCHAR ucThermalControllerType; - - USHORT usSmallPowerLimit1; - USHORT usSmallPowerLimit2; - USHORT usBoostPowerLimit; - USHORT usODTurboPowerLimit; - USHORT usODPowerSavePowerLimit; - USHORT usSoftwareShutdownTemp; - - ATOM_VEGA20_POWER_SAVING_CLOCK_RECORD PowerSavingClockTable; //PowerSavingClock Mode Clock Min/Max array - - ATOM_VEGA20_OVERDRIVE8_RECORD OverDrive8Table; //OverDrive8 Feature capabilities and Settings Range (Max and Min) - - USHORT usReserve[5]; - - PPTable_t smcPPTable; - -} ATOM_Vega20_POWERPLAYTABLE; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c deleted file mode 100644 index f56a3cbdfa3b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ /dev/null @@ -1,972 +0,0 @@ -/* - * Copyright 2018 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 -#include -#include - -#include "smu11_driver_if.h" -#include "vega20_processpptables.h" -#include "ppatomfwctrl.h" -#include "atomfirmware.h" -#include "pp_debug.h" -#include "cgs_common.h" -#include "vega20_pptable.h" - -#define VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE 105 - -static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, - enum phm_platform_caps cap) -{ - if (enable) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); - else - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); -} - -static const void *get_powerplay_table(struct pp_hwmgr *hwmgr) -{ - int index = GetIndexIntoMasterDataTable(powerplayinfo); - - u16 size; - u8 frev, crev; - const void *table_address = hwmgr->soft_pp_table; - - if (!table_address) { - table_address = (ATOM_Vega20_POWERPLAYTABLE *) - smu_atom_get_data_table(hwmgr->adev, index, - &size, &frev, &crev); - - hwmgr->soft_pp_table = table_address; - hwmgr->soft_pp_table_size = size; - } - - return table_address; -} - -#if 0 -static void dump_pptable(PPTable_t *pptable) -{ - int i; - - pr_info("Version = 0x%08x\n", pptable->Version); - - pr_info("FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); - pr_info("FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); - - pr_info("SocketPowerLimitAc0 = %d\n", pptable->SocketPowerLimitAc0); - pr_info("SocketPowerLimitAc0Tau = %d\n", pptable->SocketPowerLimitAc0Tau); - pr_info("SocketPowerLimitAc1 = %d\n", pptable->SocketPowerLimitAc1); - pr_info("SocketPowerLimitAc1Tau = %d\n", pptable->SocketPowerLimitAc1Tau); - pr_info("SocketPowerLimitAc2 = %d\n", pptable->SocketPowerLimitAc2); - pr_info("SocketPowerLimitAc2Tau = %d\n", pptable->SocketPowerLimitAc2Tau); - pr_info("SocketPowerLimitAc3 = %d\n", pptable->SocketPowerLimitAc3); - pr_info("SocketPowerLimitAc3Tau = %d\n", pptable->SocketPowerLimitAc3Tau); - pr_info("SocketPowerLimitDc = %d\n", pptable->SocketPowerLimitDc); - pr_info("SocketPowerLimitDcTau = %d\n", pptable->SocketPowerLimitDcTau); - pr_info("TdcLimitSoc = %d\n", pptable->TdcLimitSoc); - pr_info("TdcLimitSocTau = %d\n", pptable->TdcLimitSocTau); - pr_info("TdcLimitGfx = %d\n", pptable->TdcLimitGfx); - pr_info("TdcLimitGfxTau = %d\n", pptable->TdcLimitGfxTau); - - pr_info("TedgeLimit = %d\n", pptable->TedgeLimit); - pr_info("ThotspotLimit = %d\n", pptable->ThotspotLimit); - pr_info("ThbmLimit = %d\n", pptable->ThbmLimit); - pr_info("Tvr_gfxLimit = %d\n", pptable->Tvr_gfxLimit); - pr_info("Tvr_memLimit = %d\n", pptable->Tvr_memLimit); - pr_info("Tliquid1Limit = %d\n", pptable->Tliquid1Limit); - pr_info("Tliquid2Limit = %d\n", pptable->Tliquid2Limit); - pr_info("TplxLimit = %d\n", pptable->TplxLimit); - pr_info("FitLimit = %d\n", pptable->FitLimit); - - pr_info("PpmPowerLimit = %d\n", pptable->PpmPowerLimit); - pr_info("PpmTemperatureThreshold = %d\n", pptable->PpmTemperatureThreshold); - - pr_info("MemoryOnPackage = 0x%02x\n", pptable->MemoryOnPackage); - pr_info("padding8_limits = 0x%02x\n", pptable->padding8_limits); - pr_info("Tvr_SocLimit = %d\n", pptable->Tvr_SocLimit); - - pr_info("UlvVoltageOffsetSoc = %d\n", pptable->UlvVoltageOffsetSoc); - pr_info("UlvVoltageOffsetGfx = %d\n", pptable->UlvVoltageOffsetGfx); - - pr_info("UlvSmnclkDid = %d\n", pptable->UlvSmnclkDid); - pr_info("UlvMp1clkDid = %d\n", pptable->UlvMp1clkDid); - pr_info("UlvGfxclkBypass = %d\n", pptable->UlvGfxclkBypass); - pr_info("Padding234 = 0x%02x\n", pptable->Padding234); - - pr_info("MinVoltageGfx = %d\n", pptable->MinVoltageGfx); - pr_info("MinVoltageSoc = %d\n", pptable->MinVoltageSoc); - pr_info("MaxVoltageGfx = %d\n", pptable->MaxVoltageGfx); - pr_info("MaxVoltageSoc = %d\n", pptable->MaxVoltageSoc); - - pr_info("LoadLineResistanceGfx = %d\n", pptable->LoadLineResistanceGfx); - pr_info("LoadLineResistanceSoc = %d\n", pptable->LoadLineResistanceSoc); - - pr_info("[PPCLK_GFXCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_GFXCLK].padding, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c); - - pr_info("[PPCLK_VCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_VCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_VCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_VCLK].padding, - pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_VCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_VCLK].SsCurve.c); - - pr_info("[PPCLK_DCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_DCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DCLK].padding, - pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DCLK].SsCurve.c); - - pr_info("[PPCLK_ECLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_ECLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_ECLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_ECLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_ECLK].padding, - pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_ECLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_ECLK].SsCurve.c); - - pr_info("[PPCLK_SOCCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_SOCCLK].padding, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c); - - pr_info("[PPCLK_UCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_UCLK].padding, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c); - - pr_info("[PPCLK_DCEFCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_DCEFCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DCEFCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DCEFCLK].padding, - pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DCEFCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DCEFCLK].SsCurve.c); - - pr_info("[PPCLK_DISPCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_DISPCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DISPCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DISPCLK].padding, - pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DISPCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DISPCLK].SsCurve.c); - - pr_info("[PPCLK_PIXCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_PIXCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_PIXCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_PIXCLK].padding, - pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_PIXCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_PIXCLK].SsCurve.c); - - pr_info("[PPCLK_PHYCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_PHYCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_PHYCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_PHYCLK].padding, - pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_PHYCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_PHYCLK].SsCurve.c); - - pr_info("[PPCLK_FCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n", - pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_FCLK].padding, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c); - - - pr_info("FreqTableGfx\n"); - for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableGfx[i]); - - pr_info("FreqTableVclk\n"); - for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableVclk[i]); - - pr_info("FreqTableDclk\n"); - for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDclk[i]); - - pr_info("FreqTableEclk\n"); - for (i = 0; i < NUM_ECLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableEclk[i]); - - pr_info("FreqTableSocclk\n"); - for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableSocclk[i]); - - pr_info("FreqTableUclk\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableUclk[i]); - - pr_info("FreqTableFclk\n"); - for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableFclk[i]); - - pr_info("FreqTableDcefclk\n"); - for (i = 0; i < NUM_DCEFCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDcefclk[i]); - - pr_info("FreqTableDispclk\n"); - for (i = 0; i < NUM_DISPCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTableDispclk[i]); - - pr_info("FreqTablePixclk\n"); - for (i = 0; i < NUM_PIXCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePixclk[i]); - - pr_info("FreqTablePhyclk\n"); - for (i = 0; i < NUM_PHYCLK_DPM_LEVELS; i++) - pr_info(" .[%02d] = %d\n", i, pptable->FreqTablePhyclk[i]); - - pr_info("DcModeMaxFreq[PPCLK_GFXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]); - pr_info("DcModeMaxFreq[PPCLK_VCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_VCLK]); - pr_info("DcModeMaxFreq[PPCLK_DCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCLK]); - pr_info("DcModeMaxFreq[PPCLK_ECLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_ECLK]); - pr_info("DcModeMaxFreq[PPCLK_SOCCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]); - pr_info("DcModeMaxFreq[PPCLK_UCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_UCLK]); - pr_info("DcModeMaxFreq[PPCLK_DCEFCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DCEFCLK]); - pr_info("DcModeMaxFreq[PPCLK_DISPCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_DISPCLK]); - pr_info("DcModeMaxFreq[PPCLK_PIXCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PIXCLK]); - pr_info("DcModeMaxFreq[PPCLK_PHYCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_PHYCLK]); - pr_info("DcModeMaxFreq[PPCLK_FCLK] = %d\n", pptable->DcModeMaxFreq[PPCLK_FCLK]); - pr_info("Padding8_Clks = %d\n", pptable->Padding8_Clks); - - pr_info("Mp0clkFreq\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->Mp0clkFreq[i]); - - pr_info("Mp0DpmVoltage\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->Mp0DpmVoltage[i]); - - pr_info("GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); - pr_info("GfxclkSlewRate = 0x%x\n", pptable->GfxclkSlewRate); - pr_info("CksEnableFreq = 0x%x\n", pptable->CksEnableFreq); - pr_info("Padding789 = 0x%x\n", pptable->Padding789); - pr_info("CksVoltageOffset[a = 0x%08x b = 0x%08x c = 0x%08x]\n", - pptable->CksVoltageOffset.a, - pptable->CksVoltageOffset.b, - pptable->CksVoltageOffset.c); - pr_info("Padding567[0] = 0x%x\n", pptable->Padding567[0]); - pr_info("Padding567[1] = 0x%x\n", pptable->Padding567[1]); - pr_info("Padding567[2] = 0x%x\n", pptable->Padding567[2]); - pr_info("Padding567[3] = 0x%x\n", pptable->Padding567[3]); - pr_info("GfxclkDsMaxFreq = %d\n", pptable->GfxclkDsMaxFreq); - pr_info("GfxclkSource = 0x%x\n", pptable->GfxclkSource); - pr_info("Padding456 = 0x%x\n", pptable->Padding456); - - pr_info("LowestUclkReservedForUlv = %d\n", pptable->LowestUclkReservedForUlv); - pr_info("Padding8_Uclk[0] = 0x%x\n", pptable->Padding8_Uclk[0]); - pr_info("Padding8_Uclk[1] = 0x%x\n", pptable->Padding8_Uclk[1]); - pr_info("Padding8_Uclk[2] = 0x%x\n", pptable->Padding8_Uclk[2]); - - pr_info("PcieGenSpeed\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->PcieGenSpeed[i]); - - pr_info("PcieLaneCount\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->PcieLaneCount[i]); - - pr_info("LclkFreq\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->LclkFreq[i]); - - pr_info("EnableTdpm = %d\n", pptable->EnableTdpm); - pr_info("TdpmHighHystTemperature = %d\n", pptable->TdpmHighHystTemperature); - pr_info("TdpmLowHystTemperature = %d\n", pptable->TdpmLowHystTemperature); - pr_info("GfxclkFreqHighTempLimit = %d\n", pptable->GfxclkFreqHighTempLimit); - - pr_info("FanStopTemp = %d\n", pptable->FanStopTemp); - pr_info("FanStartTemp = %d\n", pptable->FanStartTemp); - - pr_info("FanGainEdge = %d\n", pptable->FanGainEdge); - pr_info("FanGainHotspot = %d\n", pptable->FanGainHotspot); - pr_info("FanGainLiquid = %d\n", pptable->FanGainLiquid); - pr_info("FanGainVrGfx = %d\n", pptable->FanGainVrGfx); - pr_info("FanGainVrSoc = %d\n", pptable->FanGainVrSoc); - pr_info("FanGainPlx = %d\n", pptable->FanGainPlx); - pr_info("FanGainHbm = %d\n", pptable->FanGainHbm); - pr_info("FanPwmMin = %d\n", pptable->FanPwmMin); - pr_info("FanAcousticLimitRpm = %d\n", pptable->FanAcousticLimitRpm); - pr_info("FanThrottlingRpm = %d\n", pptable->FanThrottlingRpm); - pr_info("FanMaximumRpm = %d\n", pptable->FanMaximumRpm); - pr_info("FanTargetTemperature = %d\n", pptable->FanTargetTemperature); - pr_info("FanTargetGfxclk = %d\n", pptable->FanTargetGfxclk); - pr_info("FanZeroRpmEnable = %d\n", pptable->FanZeroRpmEnable); - pr_info("FanTachEdgePerRev = %d\n", pptable->FanTachEdgePerRev); - - pr_info("FuzzyFan_ErrorSetDelta = %d\n", pptable->FuzzyFan_ErrorSetDelta); - pr_info("FuzzyFan_ErrorRateSetDelta = %d\n", pptable->FuzzyFan_ErrorRateSetDelta); - pr_info("FuzzyFan_PwmSetDelta = %d\n", pptable->FuzzyFan_PwmSetDelta); - pr_info("FuzzyFan_Reserved = %d\n", pptable->FuzzyFan_Reserved); - - pr_info("OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); - pr_info("OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); - pr_info("Padding8_Avfs[0] = %d\n", pptable->Padding8_Avfs[0]); - pr_info("Padding8_Avfs[1] = %d\n", pptable->Padding8_Avfs[1]); - - pr_info("qAvfsGb[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].a, - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].b, - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].c); - pr_info("qAvfsGb[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].a, - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].b, - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].c); - pr_info("dBtcGbGfxCksOn{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxCksOn.a, - pptable->dBtcGbGfxCksOn.b, - pptable->dBtcGbGfxCksOn.c); - pr_info("dBtcGbGfxCksOff{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxCksOff.a, - pptable->dBtcGbGfxCksOff.b, - pptable->dBtcGbGfxCksOff.c); - pr_info("dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxAfll.a, - pptable->dBtcGbGfxAfll.b, - pptable->dBtcGbGfxAfll.c); - pr_info("dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbSoc.a, - pptable->dBtcGbSoc.b, - pptable->dBtcGbSoc.c); - pr_info("qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, - pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); - pr_info("qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, - pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); - - pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); - pr_info("qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); - - pr_info("DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); - pr_info("DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); - - pr_info("DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); - pr_info("DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); - pr_info("Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); - pr_info("Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); - - pr_info("DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); - pr_info("DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); - pr_info("DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); - pr_info("DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); - - pr_info("XgmiLinkSpeed\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkSpeed[i]); - pr_info("XgmiLinkWidth\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiLinkWidth[i]); - pr_info("XgmiFclkFreq\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiFclkFreq[i]); - pr_info("XgmiUclkFreq\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiUclkFreq[i]); - pr_info("XgmiSocclkFreq\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiSocclkFreq[i]); - pr_info("XgmiSocVoltage\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - pr_info(" .[%d] = %d\n", i, pptable->XgmiSocVoltage[i]); - - pr_info("DebugOverrides = 0x%x\n", pptable->DebugOverrides); - pr_info("ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation0.a, - pptable->ReservedEquation0.b, - pptable->ReservedEquation0.c); - pr_info("ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation1.a, - pptable->ReservedEquation1.b, - pptable->ReservedEquation1.c); - pr_info("ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation2.a, - pptable->ReservedEquation2.b, - pptable->ReservedEquation2.c); - pr_info("ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation3.a, - pptable->ReservedEquation3.b, - pptable->ReservedEquation3.c); - - pr_info("MinVoltageUlvGfx = %d\n", pptable->MinVoltageUlvGfx); - pr_info("MinVoltageUlvSoc = %d\n", pptable->MinVoltageUlvSoc); - - pr_info("MGpuFanBoostLimitRpm = %d\n", pptable->MGpuFanBoostLimitRpm); - pr_info("padding16_Fan = %d\n", pptable->padding16_Fan); - - pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0); - pr_info("FanGainVrMem0 = %d\n", pptable->FanGainVrMem0); - - pr_info("DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); - pr_info("DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); - - for (i = 0; i < 11; i++) - pr_info("Reserved[%d] = 0x%x\n", i, pptable->Reserved[i]); - - for (i = 0; i < 3; i++) - pr_info("Padding32[%d] = 0x%x\n", i, pptable->Padding32[i]); - - pr_info("MaxVoltageStepGfx = 0x%x\n", pptable->MaxVoltageStepGfx); - pr_info("MaxVoltageStepSoc = 0x%x\n", pptable->MaxVoltageStepSoc); - - pr_info("VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); - pr_info("VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); - pr_info("VddMem0VrMapping = 0x%x\n", pptable->VddMem0VrMapping); - pr_info("VddMem1VrMapping = 0x%x\n", pptable->VddMem1VrMapping); - - pr_info("GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); - pr_info("SocUlvPhaseSheddingMask = 0x%x\n", pptable->SocUlvPhaseSheddingMask); - pr_info("ExternalSensorPresent = 0x%x\n", pptable->ExternalSensorPresent); - pr_info("Padding8_V = 0x%x\n", pptable->Padding8_V); - - pr_info("GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); - pr_info("GfxOffset = 0x%x\n", pptable->GfxOffset); - pr_info("Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); - - pr_info("SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); - pr_info("SocOffset = 0x%x\n", pptable->SocOffset); - pr_info("Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); - - pr_info("Mem0MaxCurrent = 0x%x\n", pptable->Mem0MaxCurrent); - pr_info("Mem0Offset = 0x%x\n", pptable->Mem0Offset); - pr_info("Padding_TelemetryMem0 = 0x%x\n", pptable->Padding_TelemetryMem0); - - pr_info("Mem1MaxCurrent = 0x%x\n", pptable->Mem1MaxCurrent); - pr_info("Mem1Offset = 0x%x\n", pptable->Mem1Offset); - pr_info("Padding_TelemetryMem1 = 0x%x\n", pptable->Padding_TelemetryMem1); - - pr_info("AcDcGpio = %d\n", pptable->AcDcGpio); - pr_info("AcDcPolarity = %d\n", pptable->AcDcPolarity); - pr_info("VR0HotGpio = %d\n", pptable->VR0HotGpio); - pr_info("VR0HotPolarity = %d\n", pptable->VR0HotPolarity); - - pr_info("VR1HotGpio = %d\n", pptable->VR1HotGpio); - pr_info("VR1HotPolarity = %d\n", pptable->VR1HotPolarity); - pr_info("Padding1 = 0x%x\n", pptable->Padding1); - pr_info("Padding2 = 0x%x\n", pptable->Padding2); - - pr_info("LedPin0 = %d\n", pptable->LedPin0); - pr_info("LedPin1 = %d\n", pptable->LedPin1); - pr_info("LedPin2 = %d\n", pptable->LedPin2); - pr_info("padding8_4 = 0x%x\n", pptable->padding8_4); - - pr_info("PllGfxclkSpreadEnabled = %d\n", pptable->PllGfxclkSpreadEnabled); - pr_info("PllGfxclkSpreadPercent = %d\n", pptable->PllGfxclkSpreadPercent); - pr_info("PllGfxclkSpreadFreq = %d\n", pptable->PllGfxclkSpreadFreq); - - pr_info("UclkSpreadEnabled = %d\n", pptable->UclkSpreadEnabled); - pr_info("UclkSpreadPercent = %d\n", pptable->UclkSpreadPercent); - pr_info("UclkSpreadFreq = %d\n", pptable->UclkSpreadFreq); - - pr_info("FclkSpreadEnabled = %d\n", pptable->FclkSpreadEnabled); - pr_info("FclkSpreadPercent = %d\n", pptable->FclkSpreadPercent); - pr_info("FclkSpreadFreq = %d\n", pptable->FclkSpreadFreq); - - pr_info("FllGfxclkSpreadEnabled = %d\n", pptable->FllGfxclkSpreadEnabled); - pr_info("FllGfxclkSpreadPercent = %d\n", pptable->FllGfxclkSpreadPercent); - pr_info("FllGfxclkSpreadFreq = %d\n", pptable->FllGfxclkSpreadFreq); - - for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { - pr_info("I2cControllers[%d]:\n", i); - pr_info(" .Enabled = %d\n", - pptable->I2cControllers[i].Enabled); - pr_info(" .SlaveAddress = 0x%x\n", - pptable->I2cControllers[i].SlaveAddress); - pr_info(" .ControllerPort = %d\n", - pptable->I2cControllers[i].ControllerPort); - pr_info(" .ControllerName = %d\n", - pptable->I2cControllers[i].ControllerName); - pr_info(" .ThermalThrottler = %d\n", - pptable->I2cControllers[i].ThermalThrottler); - pr_info(" .I2cProtocol = %d\n", - pptable->I2cControllers[i].I2cProtocol); - pr_info(" .I2cSpeed = %d\n", - pptable->I2cControllers[i].I2cSpeed); - } - - for (i = 0; i < 10; i++) - pr_info("BoardReserved[%d] = 0x%x\n", i, pptable->BoardReserved[i]); - - for (i = 0; i < 8; i++) - pr_info("MmHubPadding[%d] = 0x%x\n", i, pptable->MmHubPadding[i]); -} -#endif - -static int check_powerplay_tables( - struct pp_hwmgr *hwmgr, - const ATOM_Vega20_POWERPLAYTABLE *powerplay_table) -{ - PP_ASSERT_WITH_CODE((powerplay_table->sHeader.format_revision >= - ATOM_VEGA20_TABLE_REVISION_VEGA20), - "Unsupported PPTable format!", return -1); - PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, - "Invalid PowerPlay Table!", return -1); - - if (powerplay_table->smcPPTable.Version != PPTABLE_V20_SMU_VERSION) { - pr_info("Unmatch PPTable version: " - "pptable from VBIOS is V%d while driver supported is V%d!", - powerplay_table->smcPPTable.Version, - PPTABLE_V20_SMU_VERSION); - return -EINVAL; - } - - //dump_pptable(&powerplay_table->smcPPTable); - - return 0; -} - -static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) -{ - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_POWERPLAY), - PHM_PlatformCaps_PowerPlaySupport); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), - PHM_PlatformCaps_BiosPowerSourceControl); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BACO), - PHM_PlatformCaps_BACO); - - set_hw_cap( - hwmgr, - 0 != (powerplay_caps & ATOM_VEGA20_PP_PLATFORM_CAP_BAMACO), - PHM_PlatformCaps_BAMACO); - - return 0; -} - -static int copy_overdrive_feature_capabilities_array( - struct pp_hwmgr *hwmgr, - uint8_t **pptable_info_array, - const uint8_t *pptable_array, - uint8_t od_feature_count) -{ - uint32_t array_size, i; - uint8_t *table; - bool od_supported = false; - - array_size = sizeof(uint8_t) * od_feature_count; - table = kzalloc(array_size, GFP_KERNEL); - if (NULL == table) - return -ENOMEM; - - for (i = 0; i < od_feature_count; i++) { - table[i] = le32_to_cpu(pptable_array[i]); - if (table[i]) - od_supported = true; - } - - *pptable_info_array = table; - - if (od_supported) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ACOverdriveSupport); - - return 0; -} - -static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable) -{ - struct atom_smc_dpm_info_v4_4 *smc_dpm_table; - int index = GetIndexIntoMasterDataTable(smc_dpm_info); - int i; - - PP_ASSERT_WITH_CODE( - smc_dpm_table = smu_atom_get_data_table(hwmgr->adev, index, NULL, NULL, NULL), - "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", - return -1); - - ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; - ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; - - ppsmc_pptable->VddGfxVrMapping = smc_dpm_table->vddgfxvrmapping; - ppsmc_pptable->VddSocVrMapping = smc_dpm_table->vddsocvrmapping; - ppsmc_pptable->VddMem0VrMapping = smc_dpm_table->vddmem0vrmapping; - ppsmc_pptable->VddMem1VrMapping = smc_dpm_table->vddmem1vrmapping; - - ppsmc_pptable->GfxUlvPhaseSheddingMask = smc_dpm_table->gfxulvphasesheddingmask; - ppsmc_pptable->SocUlvPhaseSheddingMask = smc_dpm_table->soculvphasesheddingmask; - ppsmc_pptable->ExternalSensorPresent = smc_dpm_table->externalsensorpresent; - - ppsmc_pptable->GfxMaxCurrent = smc_dpm_table->gfxmaxcurrent; - ppsmc_pptable->GfxOffset = smc_dpm_table->gfxoffset; - ppsmc_pptable->Padding_TelemetryGfx = smc_dpm_table->padding_telemetrygfx; - - ppsmc_pptable->SocMaxCurrent = smc_dpm_table->socmaxcurrent; - ppsmc_pptable->SocOffset = smc_dpm_table->socoffset; - ppsmc_pptable->Padding_TelemetrySoc = smc_dpm_table->padding_telemetrysoc; - - ppsmc_pptable->Mem0MaxCurrent = smc_dpm_table->mem0maxcurrent; - ppsmc_pptable->Mem0Offset = smc_dpm_table->mem0offset; - ppsmc_pptable->Padding_TelemetryMem0 = smc_dpm_table->padding_telemetrymem0; - - ppsmc_pptable->Mem1MaxCurrent = smc_dpm_table->mem1maxcurrent; - ppsmc_pptable->Mem1Offset = smc_dpm_table->mem1offset; - ppsmc_pptable->Padding_TelemetryMem1 = smc_dpm_table->padding_telemetrymem1; - - ppsmc_pptable->AcDcGpio = smc_dpm_table->acdcgpio; - ppsmc_pptable->AcDcPolarity = smc_dpm_table->acdcpolarity; - ppsmc_pptable->VR0HotGpio = smc_dpm_table->vr0hotgpio; - ppsmc_pptable->VR0HotPolarity = smc_dpm_table->vr0hotpolarity; - - ppsmc_pptable->VR1HotGpio = smc_dpm_table->vr1hotgpio; - ppsmc_pptable->VR1HotPolarity = smc_dpm_table->vr1hotpolarity; - ppsmc_pptable->Padding1 = smc_dpm_table->padding1; - ppsmc_pptable->Padding2 = smc_dpm_table->padding2; - - ppsmc_pptable->LedPin0 = smc_dpm_table->ledpin0; - ppsmc_pptable->LedPin1 = smc_dpm_table->ledpin1; - ppsmc_pptable->LedPin2 = smc_dpm_table->ledpin2; - - ppsmc_pptable->PllGfxclkSpreadEnabled = smc_dpm_table->pllgfxclkspreadenabled; - ppsmc_pptable->PllGfxclkSpreadPercent = smc_dpm_table->pllgfxclkspreadpercent; - ppsmc_pptable->PllGfxclkSpreadFreq = smc_dpm_table->pllgfxclkspreadfreq; - - ppsmc_pptable->UclkSpreadEnabled = 0; - ppsmc_pptable->UclkSpreadPercent = smc_dpm_table->uclkspreadpercent; - ppsmc_pptable->UclkSpreadFreq = smc_dpm_table->uclkspreadfreq; - - ppsmc_pptable->FclkSpreadEnabled = smc_dpm_table->fclkspreadenabled; - ppsmc_pptable->FclkSpreadPercent = smc_dpm_table->fclkspreadpercent; - ppsmc_pptable->FclkSpreadFreq = smc_dpm_table->fclkspreadfreq; - - ppsmc_pptable->FllGfxclkSpreadEnabled = smc_dpm_table->fllgfxclkspreadenabled; - ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; - ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; - - for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { - ppsmc_pptable->I2cControllers[i].Enabled = - smc_dpm_table->i2ccontrollers[i].enabled; - ppsmc_pptable->I2cControllers[i].SlaveAddress = - smc_dpm_table->i2ccontrollers[i].slaveaddress; - ppsmc_pptable->I2cControllers[i].ControllerPort = - smc_dpm_table->i2ccontrollers[i].controllerport; - ppsmc_pptable->I2cControllers[i].ThermalThrottler = - smc_dpm_table->i2ccontrollers[i].thermalthrottler; - ppsmc_pptable->I2cControllers[i].I2cProtocol = - smc_dpm_table->i2ccontrollers[i].i2cprotocol; - ppsmc_pptable->I2cControllers[i].I2cSpeed = - smc_dpm_table->i2ccontrollers[i].i2cspeed; - } - - return 0; -} - -static int override_powerplay_table_fantargettemperature(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - PPTable_t *ppsmc_pptable = (PPTable_t *)(pptable_information->smc_pptable); - - ppsmc_pptable->FanTargetTemperature = VEGA20_FAN_TARGET_TEMPERATURE_OVERRIDE; - - return 0; -} - -#define VEGA20_ENGINECLOCK_HARDMAX 198000 -static int init_powerplay_table_information( - struct pp_hwmgr *hwmgr, - const ATOM_Vega20_POWERPLAYTABLE *powerplay_table) -{ - struct phm_ppt_v3_information *pptable_information = - (struct phm_ppt_v3_information *)hwmgr->pptable; - uint32_t disable_power_control = 0; - uint32_t od_feature_count, od_setting_count, power_saving_clock_count; - int result; - - hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType; - pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType; - hwmgr->thermal_controller.fanInfo.ulMinRPM = 0; - hwmgr->thermal_controller.fanInfo.ulMaxRPM = powerplay_table->smcPPTable.FanMaximumRpm; - - set_hw_cap(hwmgr, - ATOM_VEGA20_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, - PHM_PlatformCaps_ThermalController); - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - - if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) { - od_feature_count = - (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) > - ATOM_VEGA20_ODFEATURE_COUNT) ? - ATOM_VEGA20_ODFEATURE_COUNT : - le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount); - od_setting_count = - (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) > - ATOM_VEGA20_ODSETTING_COUNT) ? - ATOM_VEGA20_ODSETTING_COUNT : - le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount); - - copy_overdrive_feature_capabilities_array(hwmgr, - &pptable_information->od_feature_capabilities, - powerplay_table->OverDrive8Table.ODFeatureCapabilities, - od_feature_count); - phm_copy_overdrive_settings_limits_array(hwmgr, - &pptable_information->od_settings_max, - powerplay_table->OverDrive8Table.ODSettingsMax, - od_setting_count); - phm_copy_overdrive_settings_limits_array(hwmgr, - &pptable_information->od_settings_min, - powerplay_table->OverDrive8Table.ODSettingsMin, - od_setting_count); - } - - pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1); - pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2); - pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit); - pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit); - pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit); - - pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp); - - hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]); - - disable_power_control = 0; - if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit) - /* enable TDP overdrive (PowerControl) feature as well if supported */ - phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerControl); - - if (powerplay_table->PowerSavingClockTable.ucTableRevision == 1) { - power_saving_clock_count = - (le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount) >= - ATOM_VEGA20_PPCLOCK_COUNT) ? - ATOM_VEGA20_PPCLOCK_COUNT : - le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount); - phm_copy_clock_limits_array(hwmgr, - &pptable_information->power_saving_clock_max, - powerplay_table->PowerSavingClockTable.PowerSavingClockMax, - power_saving_clock_count); - phm_copy_clock_limits_array(hwmgr, - &pptable_information->power_saving_clock_min, - powerplay_table->PowerSavingClockTable.PowerSavingClockMin, - power_saving_clock_count); - } - - pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); - if (pptable_information->smc_pptable == NULL) - return -ENOMEM; - - memcpy(pptable_information->smc_pptable, - &(powerplay_table->smcPPTable), - sizeof(PPTable_t)); - - - result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); - if (result) - return result; - - result = override_powerplay_table_fantargettemperature(hwmgr); - - return result; -} - -static int vega20_pp_tables_initialize(struct pp_hwmgr *hwmgr) -{ - int result = 0; - const ATOM_Vega20_POWERPLAYTABLE *powerplay_table; - - hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v3_information), GFP_KERNEL); - PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), - "Failed to allocate hwmgr->pptable!", return -ENOMEM); - - powerplay_table = get_powerplay_table(hwmgr); - PP_ASSERT_WITH_CODE((powerplay_table != NULL), - "Missing PowerPlay Table!", return -1); - - result = check_powerplay_tables(hwmgr, powerplay_table); - PP_ASSERT_WITH_CODE((result == 0), - "check_powerplay_tables failed", return result); - - result = set_platform_caps(hwmgr, - le32_to_cpu(powerplay_table->ulPlatformCaps)); - PP_ASSERT_WITH_CODE((result == 0), - "set_platform_caps failed", return result); - - result = init_powerplay_table_information(hwmgr, powerplay_table); - PP_ASSERT_WITH_CODE((result == 0), - "init_powerplay_table_information failed", return result); - - return result; -} - -static int vega20_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) -{ - struct phm_ppt_v3_information *pp_table_info = - (struct phm_ppt_v3_information *)(hwmgr->pptable); - - kfree(pp_table_info->power_saving_clock_max); - pp_table_info->power_saving_clock_max = NULL; - - kfree(pp_table_info->power_saving_clock_min); - pp_table_info->power_saving_clock_min = NULL; - - kfree(pp_table_info->od_feature_capabilities); - pp_table_info->od_feature_capabilities = NULL; - - kfree(pp_table_info->od_settings_max); - pp_table_info->od_settings_max = NULL; - - kfree(pp_table_info->od_settings_min); - pp_table_info->od_settings_min = NULL; - - kfree(pp_table_info->smc_pptable); - pp_table_info->smc_pptable = NULL; - - kfree(hwmgr->pptable); - hwmgr->pptable = NULL; - - return 0; -} - -const struct pp_table_func vega20_pptable_funcs = { - .pptable_init = vega20_pp_tables_initialize, - .pptable_fini = vega20_pp_tables_uninitialize, -}; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h deleted file mode 100644 index 846c2cb40b35..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 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 VEGA20_PROCESSPPTABLES_H -#define VEGA20_PROCESSPPTABLES_H - -#include "hwmgr.h" - -extern const struct pp_table_func vega20_pptable_funcs; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c deleted file mode 100644 index 7add2f60f49c..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright 2018 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 "vega20_thermal.h" -#include "vega20_hwmgr.h" -#include "vega20_smumgr.h" -#include "vega20_ppsmc.h" -#include "vega20_inc.h" -#include "soc15_common.h" -#include "pp_debug.h" - -static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - int ret = 0; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - ret = vega20_enable_smc_features( - hwmgr, false, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap); - PP_ASSERT_WITH_CODE(!ret, - "Disable FAN CONTROL feature Failed!", - return ret); - data->smu_features[GNLD_FAN_CONTROL].enabled = false; - } - - return ret; -} - -int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) - return vega20_disable_fan_control_feature(hwmgr); - - return 0; -} - -static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - int ret = 0; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) { - ret = vega20_enable_smc_features( - hwmgr, true, - data->smu_features[GNLD_FAN_CONTROL]. - smu_feature_bitmap); - PP_ASSERT_WITH_CODE(!ret, - "Enable FAN CONTROL feature Failed!", - return ret); - data->smu_features[GNLD_FAN_CONTROL].enabled = true; - } - - return ret; -} - -int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) -{ - struct vega20_hwmgr *data = hwmgr->backend; - - if (data->smu_features[GNLD_FAN_CONTROL].supported) - return vega20_enable_fan_control_feature(hwmgr); - - return 0; -} - -static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) -{ - struct amdgpu_device *adev = hwmgr->adev; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TMIN, 0)); - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, FDO_PWM_MODE, mode)); - - return 0; -} - -static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm) -{ - int ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetCurrentRpm, - current_rpm)) == 0, - "Attempt to get current RPM from SMC Failed!", - return ret); - - return 0; -} - -int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t *speed) -{ - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - PPTable_t *pp_table = &(data->smc_state_table.pp_table); - uint32_t current_rpm, percent = 0; - int ret = 0; - - ret = vega20_get_current_rpm(hwmgr, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pp_table->FanMaximumRpm; - - *speed = percent > 100 ? 100 : percent; - - return 0; -} - -int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t speed) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t duty100; - uint32_t duty; - uint64_t tmp64; - - if (speed > 100) - speed = 100; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) - vega20_fan_ctrl_stop_smc_fan_control(hwmgr); - - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); - - return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); -} - -int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info) -{ - memset(fan_speed_info, 0, sizeof(*fan_speed_info)); - fan_speed_info->supports_percent_read = true; - fan_speed_info->supports_percent_write = true; - fan_speed_info->supports_rpm_read = true; - fan_speed_info->supports_rpm_write = true; - - return 0; -} - -int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) -{ - *speed = 0; - - return vega20_get_current_rpm(hwmgr, speed); -} - -int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t tach_period, crystal_clock_freq; - int result = 0; - - if (!speed) - return -EINVAL; - - if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) { - result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr); - if (result) - return result; - } - - crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); - WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), - CG_TACH_CTRL, TARGET_PERIOD, - tach_period)); - - return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM); -} - -/** -* Reads the remote temperature from the SIslands thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - int temp = 0; - - temp = RREG32_SOC15(THM, 0, mmCG_MULT_THERMAL_STATUS); - - temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> - CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; - - temp = temp & 0x1ff; - - temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - return temp; -} - -/** -* Set the requested temperature range for high and low alert signals -* -* @param hwmgr The address of the hardware manager. -* @param range Temperature range to be programmed for -* high and low alert signals -* @exception PP_Result_BadInput if the input data is not valid. -*/ -static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - uint32_t val; - - if (low < range->min) - low = range->min; - if (high > range->max) - high = range->max; - - if (low > high) - return -EINVAL; - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - return 0; -} - -/** -* Enable thermal alerts on the RV770 thermal controller. -* -* @param hwmgr The address of the hardware manager. -*/ -static int vega20_thermal_enable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t val = 0; - - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); - - return 0; -} - -/** -* Disable thermal alerts on the RV770 thermal controller. -* @param hwmgr The address of the hardware manager. -*/ -int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); - - return 0; -} - -/** -* Uninitialize the thermal controller. -* Currently just disables alerts. -* @param hwmgr The address of the hardware manager. -*/ -int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) -{ - int result = vega20_thermal_disable_alert(hwmgr); - - return result; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -static int vega20_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - int ret; - struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - PPTable_t *table = &(data->smc_state_table.pp_table); - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanTemperatureTarget, - (uint32_t)table->FanTargetTemperature, - NULL); - - return ret; -} - -int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range) -{ - int ret = 0; - - if (range == NULL) - return -EINVAL; - - ret = vega20_thermal_set_temperature_range(hwmgr, range); - if (ret) - return ret; - - ret = vega20_thermal_enable_alert(hwmgr); - if (ret) - return ret; - - ret = vega20_thermal_setup_fan_table(hwmgr); - - return ret; -}; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h deleted file mode 100644 index 2d1769bbd24e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2018 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 VEGA20_THERMAL_H -#define VEGA20_THERMAL_H - -#include "hwmgr.h" - -struct vega20_temperature { - uint16_t edge_temp; - uint16_t hot_spot_temp; - uint16_t hbm_temp; - uint16_t vr_soc_temp; - uint16_t vr_mem_temp; - uint16_t liquid1_temp; - uint16_t liquid2_temp; - uint16_t plx_temp; -}; - -#define VEGA20_THERMAL_HIGH_ALERT_MASK 0x1 -#define VEGA20_THERMAL_LOW_ALERT_MASK 0x2 - -#define VEGA20_THERMAL_MINIMUM_TEMP_READING -256 -#define VEGA20_THERMAL_MAXIMUM_TEMP_READING 255 - -#define VEGA20_THERMAL_MINIMUM_ALERT_TEMP 0 -#define VEGA20_THERMAL_MAXIMUM_ALERT_TEMP 255 - -#define FDO_PWM_MODE_STATIC 1 -#define FDO_PWM_MODE_STATIC_RPM 5 - -extern int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr); -extern int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, - struct phm_fan_speed_info *fan_speed_info); -extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, - uint32_t *speed); -extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, - uint32_t speed); -extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t *speed); -extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, - uint32_t speed); -extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); -extern int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr); -extern int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range); -extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h deleted file mode 100644 index fe3665965416..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2015 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 _AMD_POWERPLAY_H_ -#define _AMD_POWERPLAY_H_ - -#include -#include -#include -#include "amd_shared.h" -#include "cgs_common.h" -#include "dm_pp_interface.h" -#include "kgd_pp_interface.h" -#include "amdgpu.h" - -#endif /* _AMD_POWERPLAY_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h deleted file mode 100644 index bbe4a343e9f1..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h +++ /dev/null @@ -1,806 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#ifndef __AMDGPU_SMU_H__ -#define __AMDGPU_SMU_H__ - -#include "amdgpu.h" -#include "kgd_pp_interface.h" -#include "dm_pp_interface.h" -#include "dm_pp_smu.h" -#include "smu_types.h" - -#define SMU_THERMAL_MINIMUM_ALERT_TEMP 0 -#define SMU_THERMAL_MAXIMUM_ALERT_TEMP 255 -#define SMU_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 - -struct smu_hw_power_state { - unsigned int magic; -}; - -struct smu_power_state; - -enum smu_state_ui_label { - SMU_STATE_UI_LABEL_NONE, - SMU_STATE_UI_LABEL_BATTERY, - SMU_STATE_UI_TABEL_MIDDLE_LOW, - SMU_STATE_UI_LABEL_BALLANCED, - SMU_STATE_UI_LABEL_MIDDLE_HIGHT, - SMU_STATE_UI_LABEL_PERFORMANCE, - SMU_STATE_UI_LABEL_BACO, -}; - -enum smu_state_classification_flag { - SMU_STATE_CLASSIFICATION_FLAG_BOOT = 0x0001, - SMU_STATE_CLASSIFICATION_FLAG_THERMAL = 0x0002, - SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE = 0x0004, - SMU_STATE_CLASSIFICATION_FLAG_RESET = 0x0008, - SMU_STATE_CLASSIFICATION_FLAG_FORCED = 0x0010, - SMU_STATE_CLASSIFICATION_FLAG_USER_3D_PERFORMANCE = 0x0020, - SMU_STATE_CLASSIFICATION_FLAG_USER_2D_PERFORMANCE = 0x0040, - SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE = 0x0080, - SMU_STATE_CLASSIFICATION_FLAG_AC_OVERDIRVER_TEMPLATE = 0x0100, - SMU_STATE_CLASSIFICATION_FLAG_UVD = 0x0200, - SMU_STATE_CLASSIFICATION_FLAG_3D_PERFORMANCE_LOW = 0x0400, - SMU_STATE_CLASSIFICATION_FLAG_ACPI = 0x0800, - SMU_STATE_CLASSIFICATION_FLAG_HD2 = 0x1000, - SMU_STATE_CLASSIFICATION_FLAG_UVD_HD = 0x2000, - SMU_STATE_CLASSIFICATION_FLAG_UVD_SD = 0x4000, - SMU_STATE_CLASSIFICATION_FLAG_USER_DC_PERFORMANCE = 0x8000, - SMU_STATE_CLASSIFICATION_FLAG_DC_OVERDIRVER_TEMPLATE = 0x10000, - SMU_STATE_CLASSIFICATION_FLAG_BACO = 0x20000, - SMU_STATE_CLASSIFICATIN_FLAG_LIMITED_POWER_SOURCE2 = 0x40000, - SMU_STATE_CLASSIFICATION_FLAG_ULV = 0x80000, - SMU_STATE_CLASSIFICATION_FLAG_UVD_MVC = 0x100000, -}; - -struct smu_state_classification_block { - enum smu_state_ui_label ui_label; - enum smu_state_classification_flag flags; - int bios_index; - bool temporary_state; - bool to_be_deleted; -}; - -struct smu_state_pcie_block { - unsigned int lanes; -}; - -enum smu_refreshrate_source { - SMU_REFRESHRATE_SOURCE_EDID, - SMU_REFRESHRATE_SOURCE_EXPLICIT -}; - -struct smu_state_display_block { - bool disable_frame_modulation; - bool limit_refreshrate; - enum smu_refreshrate_source refreshrate_source; - int explicit_refreshrate; - int edid_refreshrate_index; - bool enable_vari_bright; -}; - -struct smu_state_memroy_block { - bool dll_off; - uint8_t m3arb; - uint8_t unused[3]; -}; - -struct smu_state_software_algorithm_block { - bool disable_load_balancing; - bool enable_sleep_for_timestamps; -}; - -struct smu_temperature_range { - int min; - int max; - int edge_emergency_max; - int hotspot_min; - int hotspot_crit_max; - int hotspot_emergency_max; - int mem_min; - int mem_crit_max; - int mem_emergency_max; - int software_shutdown_temp; -}; - -struct smu_state_validation_block { - bool single_display_only; - bool disallow_on_dc; - uint8_t supported_power_levels; -}; - -struct smu_uvd_clocks { - uint32_t vclk; - uint32_t dclk; -}; - -/** -* Structure to hold a SMU Power State. -*/ -struct smu_power_state { - uint32_t id; - struct list_head ordered_list; - struct list_head all_states_list; - - struct smu_state_classification_block classification; - struct smu_state_validation_block validation; - struct smu_state_pcie_block pcie; - struct smu_state_display_block display; - struct smu_state_memroy_block memory; - struct smu_state_software_algorithm_block software; - struct smu_uvd_clocks uvd_clocks; - struct smu_hw_power_state hardware; -}; - -enum smu_power_src_type -{ - SMU_POWER_SOURCE_AC, - SMU_POWER_SOURCE_DC, - SMU_POWER_SOURCE_COUNT, -}; - -enum smu_memory_pool_size -{ - SMU_MEMORY_POOL_SIZE_ZERO = 0, - SMU_MEMORY_POOL_SIZE_256_MB = 0x10000000, - SMU_MEMORY_POOL_SIZE_512_MB = 0x20000000, - SMU_MEMORY_POOL_SIZE_1_GB = 0x40000000, - SMU_MEMORY_POOL_SIZE_2_GB = 0x80000000, -}; - -#define SMU_TABLE_INIT(tables, table_id, s, a, d) \ - do { \ - tables[table_id].size = s; \ - tables[table_id].align = a; \ - tables[table_id].domain = d; \ - } while (0) - -struct smu_table { - uint64_t size; - uint32_t align; - uint8_t domain; - uint64_t mc_address; - void *cpu_addr; - struct amdgpu_bo *bo; -}; - -enum smu_perf_level_designation { - PERF_LEVEL_ACTIVITY, - PERF_LEVEL_POWER_CONTAINMENT, -}; - -struct smu_performance_level { - uint32_t core_clock; - uint32_t memory_clock; - uint32_t vddc; - uint32_t vddci; - uint32_t non_local_mem_freq; - uint32_t non_local_mem_width; -}; - -struct smu_clock_info { - uint32_t min_mem_clk; - uint32_t max_mem_clk; - uint32_t min_eng_clk; - uint32_t max_eng_clk; - uint32_t min_bus_bandwidth; - uint32_t max_bus_bandwidth; -}; - -struct smu_bios_boot_up_values -{ - uint32_t revision; - uint32_t gfxclk; - uint32_t uclk; - uint32_t socclk; - uint32_t dcefclk; - uint32_t eclk; - uint32_t vclk; - uint32_t dclk; - uint16_t vddc; - uint16_t vddci; - uint16_t mvddc; - uint16_t vdd_gfx; - uint8_t cooling_id; - uint32_t pp_table_id; - uint32_t format_revision; - uint32_t content_revision; - uint32_t fclk; -}; - -enum smu_table_id -{ - SMU_TABLE_PPTABLE = 0, - SMU_TABLE_WATERMARKS, - SMU_TABLE_CUSTOM_DPM, - SMU_TABLE_DPMCLOCKS, - SMU_TABLE_AVFS, - SMU_TABLE_AVFS_PSM_DEBUG, - SMU_TABLE_AVFS_FUSE_OVERRIDE, - SMU_TABLE_PMSTATUSLOG, - SMU_TABLE_SMU_METRICS, - SMU_TABLE_DRIVER_SMU_CONFIG, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, - SMU_TABLE_OVERDRIVE, - SMU_TABLE_I2C_COMMANDS, - SMU_TABLE_PACE, - SMU_TABLE_COUNT, -}; - -struct smu_table_context -{ - void *power_play_table; - uint32_t power_play_table_size; - void *hardcode_pptable; - unsigned long metrics_time; - void *metrics_table; - void *clocks_table; - void *watermarks_table; - - void *max_sustainable_clocks; - struct smu_bios_boot_up_values boot_values; - void *driver_pptable; - struct smu_table tables[SMU_TABLE_COUNT]; - /* - * The driver table is just a staging buffer for - * uploading/downloading content from the SMU. - * - * And the table_id for SMU_MSG_TransferTableSmu2Dram/ - * SMU_MSG_TransferTableDram2Smu instructs SMU - * which content driver is interested. - */ - struct smu_table driver_table; - struct smu_table memory_pool; - uint8_t thermal_controller_type; - - void *overdrive_table; - void *boot_overdrive_table; - - uint32_t gpu_metrics_table_size; - void *gpu_metrics_table; -}; - -struct smu_dpm_context { - uint32_t dpm_context_size; - void *dpm_context; - void *golden_dpm_context; - bool enable_umd_pstate; - enum amd_dpm_forced_level dpm_level; - enum amd_dpm_forced_level saved_dpm_level; - enum amd_dpm_forced_level requested_dpm_level; - struct smu_power_state *dpm_request_power_state; - struct smu_power_state *dpm_current_power_state; - struct mclock_latency_table *mclk_latency_table; -}; - -struct smu_power_gate { - bool uvd_gated; - bool vce_gated; - atomic_t vcn_gated; - atomic_t jpeg_gated; - struct mutex vcn_gate_lock; - struct mutex jpeg_gate_lock; -}; - -struct smu_power_context { - void *power_context; - uint32_t power_context_size; - struct smu_power_gate power_gate; -}; - - -#define SMU_FEATURE_MAX (64) -struct smu_feature -{ - uint32_t feature_num; - DECLARE_BITMAP(supported, SMU_FEATURE_MAX); - DECLARE_BITMAP(allowed, SMU_FEATURE_MAX); - DECLARE_BITMAP(enabled, SMU_FEATURE_MAX); - struct mutex mutex; -}; - -struct smu_clocks { - uint32_t engine_clock; - uint32_t memory_clock; - uint32_t bus_bandwidth; - uint32_t engine_clock_in_sr; - uint32_t dcef_clock; - uint32_t dcef_clock_in_sr; -}; - -#define MAX_REGULAR_DPM_NUM 16 -struct mclk_latency_entries { - uint32_t frequency; - uint32_t latency; -}; -struct mclock_latency_table { - uint32_t count; - struct mclk_latency_entries entries[MAX_REGULAR_DPM_NUM]; -}; - -enum smu_reset_mode -{ - SMU_RESET_MODE_0, - SMU_RESET_MODE_1, - SMU_RESET_MODE_2, -}; - -enum smu_baco_state -{ - SMU_BACO_STATE_ENTER = 0, - SMU_BACO_STATE_EXIT, -}; - -struct smu_baco_context -{ - struct mutex mutex; - uint32_t state; - bool platform_support; -}; - -struct pstates_clk_freq { - uint32_t min; - uint32_t standard; - uint32_t peak; -}; - -struct smu_umd_pstate_table { - struct pstates_clk_freq gfxclk_pstate; - struct pstates_clk_freq socclk_pstate; - struct pstates_clk_freq uclk_pstate; - struct pstates_clk_freq vclk_pstate; - struct pstates_clk_freq dclk_pstate; -}; - -struct cmn2asic_msg_mapping { - int valid_mapping; - int map_to; - int valid_in_vf; -}; - -struct cmn2asic_mapping { - int valid_mapping; - int map_to; -}; - -#define WORKLOAD_POLICY_MAX 7 -struct smu_context -{ - struct amdgpu_device *adev; - struct amdgpu_irq_src irq_source; - - const struct pptable_funcs *ppt_funcs; - const struct cmn2asic_msg_mapping *message_map; - const struct cmn2asic_mapping *clock_map; - const struct cmn2asic_mapping *feature_map; - const struct cmn2asic_mapping *table_map; - const struct cmn2asic_mapping *pwr_src_map; - const struct cmn2asic_mapping *workload_map; - struct mutex mutex; - struct mutex sensor_lock; - struct mutex metrics_lock; - struct mutex message_lock; - uint64_t pool_size; - - struct smu_table_context smu_table; - struct smu_dpm_context smu_dpm; - struct smu_power_context smu_power; - struct smu_feature smu_feature; - struct amd_pp_display_configuration *display_config; - struct smu_baco_context smu_baco; - struct smu_temperature_range thermal_range; - void *od_settings; -#if defined(CONFIG_DEBUG_FS) - struct dentry *debugfs_sclk; -#endif - - struct smu_umd_pstate_table pstate_table; - uint32_t pstate_sclk; - uint32_t pstate_mclk; - - bool od_enabled; - uint32_t current_power_limit; - uint32_t max_power_limit; - - /* soft pptable */ - uint32_t ppt_offset_bytes; - uint32_t ppt_size_bytes; - uint8_t *ppt_start_addr; - - bool support_power_containment; - bool disable_watermark; - -#define WATERMARKS_EXIST (1 << 0) -#define WATERMARKS_LOADED (1 << 1) - uint32_t watermarks_bitmap; - uint32_t hard_min_uclk_req_from_dal; - bool disable_uclk_switch; - - uint32_t workload_mask; - uint32_t workload_prority[WORKLOAD_POLICY_MAX]; - uint32_t workload_setting[WORKLOAD_POLICY_MAX]; - uint32_t power_profile_mode; - uint32_t default_power_profile_mode; - bool pm_enabled; - bool is_apu; - - uint32_t smc_driver_if_version; - uint32_t smc_fw_if_version; - uint32_t smc_fw_version; - - bool uploading_custom_pp_table; - bool dc_controlled_by_gpio; - - struct work_struct throttling_logging_work; - atomic64_t throttle_int_counter; -}; - -struct i2c_adapter; - -struct pptable_funcs { - int (*run_btc)(struct smu_context *smu); - int (*get_allowed_feature_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); - enum amd_pm_state_type (*get_current_power_state)(struct smu_context *smu); - int (*set_default_dpm_table)(struct smu_context *smu); - int (*set_power_state)(struct smu_context *smu); - int (*populate_umd_state_clk)(struct smu_context *smu); - int (*print_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, char *buf); - int (*force_clk_levels)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t mask); - int (*set_default_od8_settings)(struct smu_context *smu); - int (*get_od_percentage)(struct smu_context *smu, enum smu_clk_type clk_type); - int (*set_od_percentage)(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t value); - int (*od_edit_dpm_table)(struct smu_context *smu, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size); - int (*get_clock_by_type_with_latency)(struct smu_context *smu, - enum smu_clk_type clk_type, - struct - pp_clock_levels_with_latency - *clocks); - int (*get_clock_by_type_with_voltage)(struct smu_context *smu, - enum amd_pp_clock_type type, - struct - pp_clock_levels_with_voltage - *clocks); - int (*get_power_profile_mode)(struct smu_context *smu, char *buf); - int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size); - int (*dpm_set_vcn_enable)(struct smu_context *smu, bool enable); - int (*dpm_set_jpeg_enable)(struct smu_context *smu, bool enable); - int (*read_sensor)(struct smu_context *smu, enum amd_pp_sensors sensor, - void *data, uint32_t *size); - int (*pre_display_config_changed)(struct smu_context *smu); - int (*display_config_changed)(struct smu_context *smu); - int (*apply_clocks_adjust_rules)(struct smu_context *smu); - int (*notify_smc_display_config)(struct smu_context *smu); - int (*set_cpu_power_state)(struct smu_context *smu); - bool (*is_dpm_running)(struct smu_context *smu); - int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); - int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); - int (*set_watermarks_table)(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); - int (*get_thermal_temperature_range)(struct smu_context *smu, struct smu_temperature_range *range); - int (*get_uclk_dpm_states)(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states); - int (*set_default_od_settings)(struct smu_context *smu); - int (*set_performance_level)(struct smu_context *smu, enum amd_dpm_forced_level level); - int (*display_disable_memory_clock_switch)(struct smu_context *smu, bool disable_memory_clock_switch); - void (*dump_pptable)(struct smu_context *smu); - int (*get_power_limit)(struct smu_context *smu); - int (*set_df_cstate)(struct smu_context *smu, enum pp_df_cstate state); - int (*allow_xgmi_power_down)(struct smu_context *smu, bool en); - int (*update_pcie_parameters)(struct smu_context *smu, uint32_t pcie_gen_cap, uint32_t pcie_width_cap); - int (*i2c_init)(struct smu_context *smu, struct i2c_adapter *control); - void (*i2c_fini)(struct smu_context *smu, struct i2c_adapter *control); - void (*get_unique_id)(struct smu_context *smu); - int (*get_dpm_clock_table)(struct smu_context *smu, struct dpm_clocks *clock_table); - int (*init_microcode)(struct smu_context *smu); - int (*load_microcode)(struct smu_context *smu); - void (*fini_microcode)(struct smu_context *smu); - int (*init_smc_tables)(struct smu_context *smu); - int (*fini_smc_tables)(struct smu_context *smu); - int (*init_power)(struct smu_context *smu); - int (*fini_power)(struct smu_context *smu); - int (*check_fw_status)(struct smu_context *smu); - int (*setup_pptable)(struct smu_context *smu); - int (*get_vbios_bootup_values)(struct smu_context *smu); - int (*check_fw_version)(struct smu_context *smu); - int (*powergate_sdma)(struct smu_context *smu, bool gate); - int (*set_gfx_cgpg)(struct smu_context *smu, bool enable); - int (*write_pptable)(struct smu_context *smu); - int (*set_driver_table_location)(struct smu_context *smu); - int (*set_tool_table_location)(struct smu_context *smu); - int (*notify_memory_pool_location)(struct smu_context *smu); - int (*set_last_dcef_min_deep_sleep_clk)(struct smu_context *smu); - int (*system_features_control)(struct smu_context *smu, bool en); - int (*send_smc_msg_with_param)(struct smu_context *smu, - enum smu_message_type msg, uint32_t param, uint32_t *read_arg); - int (*send_smc_msg)(struct smu_context *smu, - enum smu_message_type msg, - uint32_t *read_arg); - int (*init_display_count)(struct smu_context *smu, uint32_t count); - int (*set_allowed_mask)(struct smu_context *smu); - int (*get_enabled_mask)(struct smu_context *smu, uint32_t *feature_mask, uint32_t num); - int (*feature_is_enabled)(struct smu_context *smu, enum smu_feature_mask mask); - int (*disable_all_features_with_exception)(struct smu_context *smu, enum smu_feature_mask mask); - int (*notify_display_change)(struct smu_context *smu); - int (*set_power_limit)(struct smu_context *smu, uint32_t n); - int (*init_max_sustainable_clocks)(struct smu_context *smu); - int (*enable_thermal_alert)(struct smu_context *smu); - int (*disable_thermal_alert)(struct smu_context *smu); - int (*set_min_dcef_deep_sleep)(struct smu_context *smu, uint32_t clk); - int (*set_active_display_count)(struct smu_context *smu, uint32_t count); - int (*store_cc6_data)(struct smu_context *smu, uint32_t separation_time, - bool cc6_disable, bool pstate_disable, - bool pstate_switch_disable); - int (*get_clock_by_type)(struct smu_context *smu, - enum amd_pp_clock_type type, - struct amd_pp_clocks *clocks); - int (*get_max_high_clocks)(struct smu_context *smu, - struct amd_pp_simple_clock_info *clocks); - int (*display_clock_voltage_request)(struct smu_context *smu, struct - pp_display_clock_request - *clock_req); - int (*get_dal_power_level)(struct smu_context *smu, - struct amd_pp_simple_clock_info *clocks); - int (*get_perf_level)(struct smu_context *smu, - enum smu_perf_level_designation designation, - struct smu_performance_level *level); - int (*get_current_shallow_sleep_clocks)(struct smu_context *smu, - struct smu_clock_info *clocks); - int (*notify_smu_enable_pwe)(struct smu_context *smu); - int (*conv_power_profile_to_pplib_workload)(int power_profile); - uint32_t (*get_fan_control_mode)(struct smu_context *smu); - int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode); - int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed); - int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed); - int (*set_xgmi_pstate)(struct smu_context *smu, uint32_t pstate); - int (*gfx_off_control)(struct smu_context *smu, bool enable); - uint32_t (*get_gfx_off_status)(struct smu_context *smu); - int (*register_irq_handler)(struct smu_context *smu); - int (*set_azalia_d3_pme)(struct smu_context *smu); - int (*get_max_sustainable_clocks_by_dc)(struct smu_context *smu, struct pp_smu_nv_clock_table *max_clocks); - bool (*baco_is_support)(struct smu_context *smu); - enum smu_baco_state (*baco_get_state)(struct smu_context *smu); - int (*baco_set_state)(struct smu_context *smu, enum smu_baco_state state); - int (*baco_enter)(struct smu_context *smu); - int (*baco_exit)(struct smu_context *smu); - bool (*mode1_reset_is_support)(struct smu_context *smu); - int (*mode1_reset)(struct smu_context *smu); - int (*mode2_reset)(struct smu_context *smu); - int (*get_dpm_ultimate_freq)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t *min, uint32_t *max); - int (*set_soft_freq_limited_range)(struct smu_context *smu, enum smu_clk_type clk_type, uint32_t min, uint32_t max); - int (*disable_umc_cdr_12gbps_workaround)(struct smu_context *smu); - int (*set_power_source)(struct smu_context *smu, enum smu_power_src_type power_src); - void (*log_thermal_throttling_event)(struct smu_context *smu); - size_t (*get_pp_feature_mask)(struct smu_context *smu, char *buf); - int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); - ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); - int (*enable_mgpu_fan_boost)(struct smu_context *smu); -}; - -typedef enum { - METRICS_CURR_GFXCLK, - METRICS_CURR_SOCCLK, - METRICS_CURR_UCLK, - METRICS_CURR_VCLK, - METRICS_CURR_VCLK1, - METRICS_CURR_DCLK, - METRICS_CURR_DCLK1, - METRICS_CURR_FCLK, - METRICS_CURR_DCEFCLK, - METRICS_AVERAGE_GFXCLK, - METRICS_AVERAGE_SOCCLK, - METRICS_AVERAGE_FCLK, - METRICS_AVERAGE_UCLK, - METRICS_AVERAGE_VCLK, - METRICS_AVERAGE_DCLK, - METRICS_AVERAGE_GFXACTIVITY, - METRICS_AVERAGE_MEMACTIVITY, - METRICS_AVERAGE_VCNACTIVITY, - METRICS_AVERAGE_SOCKETPOWER, - METRICS_TEMPERATURE_EDGE, - METRICS_TEMPERATURE_HOTSPOT, - METRICS_TEMPERATURE_MEM, - METRICS_TEMPERATURE_VRGFX, - METRICS_TEMPERATURE_VRSOC, - METRICS_TEMPERATURE_VRMEM, - METRICS_THROTTLER_STATUS, - METRICS_CURR_FANSPEED, -} MetricsMember_t; - -enum smu_cmn2asic_mapping_type { - CMN2ASIC_MAPPING_MSG, - CMN2ASIC_MAPPING_CLK, - CMN2ASIC_MAPPING_FEATURE, - CMN2ASIC_MAPPING_TABLE, - CMN2ASIC_MAPPING_PWR, - CMN2ASIC_MAPPING_WORKLOAD, -}; - -#define MSG_MAP(msg, index, valid_in_vf) \ - [SMU_MSG_##msg] = {1, (index), (valid_in_vf)} - -#define CLK_MAP(clk, index) \ - [SMU_##clk] = {1, (index)} - -#define FEA_MAP(fea) \ - [SMU_FEATURE_##fea##_BIT] = {1, FEATURE_##fea##_BIT} - -#define TAB_MAP(tab) \ - [SMU_TABLE_##tab] = {1, TABLE_##tab} - -#define TAB_MAP_VALID(tab) \ - [SMU_TABLE_##tab] = {1, TABLE_##tab} - -#define TAB_MAP_INVALID(tab) \ - [SMU_TABLE_##tab] = {0, TABLE_##tab} - -#define PWR_MAP(tab) \ - [SMU_POWER_SOURCE_##tab] = {1, POWER_SOURCE_##tab} - -#define WORKLOAD_MAP(profile, workload) \ - [profile] = {1, (workload)} - -#if !defined(SWSMU_CODE_LAYER_L2) && !defined(SWSMU_CODE_LAYER_L3) && !defined(SWSMU_CODE_LAYER_L4) -int smu_load_microcode(struct smu_context *smu); - -int smu_check_fw_status(struct smu_context *smu); - -int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled); - -int smu_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); - -int smu_get_power_limit(struct smu_context *smu, - uint32_t *limit, - bool max_setting); - -int smu_set_power_limit(struct smu_context *smu, uint32_t limit); -int smu_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf); -int smu_get_od_percentage(struct smu_context *smu, enum smu_clk_type type); -int smu_set_od_percentage(struct smu_context *smu, enum smu_clk_type type, uint32_t value); - -int smu_od_edit_dpm_table(struct smu_context *smu, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size); - -int smu_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size); -int smu_get_power_profile_mode(struct smu_context *smu, char *buf); - -int smu_set_power_profile_mode(struct smu_context *smu, - long *param, - uint32_t param_size, - bool lock_needed); -int smu_get_fan_control_mode(struct smu_context *smu); -int smu_set_fan_control_mode(struct smu_context *smu, int value); -int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed); -int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); -int smu_get_fan_speed_rpm(struct smu_context *smu, uint32_t *speed); - -int smu_set_deep_sleep_dcefclk(struct smu_context *smu, int clk); -int smu_set_active_display_count(struct smu_context *smu, uint32_t count); - -int smu_get_clock_by_type(struct smu_context *smu, - enum amd_pp_clock_type type, - struct amd_pp_clocks *clocks); - -int smu_get_max_high_clocks(struct smu_context *smu, - struct amd_pp_simple_clock_info *clocks); - -int smu_get_clock_by_type_with_latency(struct smu_context *smu, - enum smu_clk_type clk_type, - struct pp_clock_levels_with_latency *clocks); - -int smu_get_clock_by_type_with_voltage(struct smu_context *smu, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks); - -int smu_display_clock_voltage_request(struct smu_context *smu, - struct pp_display_clock_request *clock_req); -int smu_display_disable_memory_clock_switch(struct smu_context *smu, bool disable_memory_clock_switch); -int smu_notify_smu_enable_pwe(struct smu_context *smu); - -int smu_set_xgmi_pstate(struct smu_context *smu, - uint32_t pstate); - -int smu_set_azalia_d3_pme(struct smu_context *smu); - -bool smu_baco_is_support(struct smu_context *smu); - -int smu_baco_get_state(struct smu_context *smu, enum smu_baco_state *state); - -int smu_baco_enter(struct smu_context *smu); -int smu_baco_exit(struct smu_context *smu); - -bool smu_mode1_reset_is_support(struct smu_context *smu); -int smu_mode1_reset(struct smu_context *smu); -int smu_mode2_reset(struct smu_context *smu); - -extern const struct amd_ip_funcs smu_ip_funcs; - -extern const struct amdgpu_ip_block_version smu_v11_0_ip_block; -extern const struct amdgpu_ip_block_version smu_v12_0_ip_block; - -bool is_support_sw_smu(struct amdgpu_device *adev); -int smu_reset(struct smu_context *smu); -int smu_sys_get_pp_table(struct smu_context *smu, void **table); -int smu_sys_set_pp_table(struct smu_context *smu, void *buf, size_t size); -int smu_get_power_num_states(struct smu_context *smu, struct pp_states_info *state_info); -enum amd_pm_state_type smu_get_current_power_state(struct smu_context *smu); -int smu_write_watermarks_table(struct smu_context *smu); -int smu_set_watermarks_for_clock_ranges( - struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); - -/* smu to display interface */ -extern int smu_display_configuration_change(struct smu_context *smu, const - struct amd_pp_display_configuration - *display_config); -extern int smu_get_current_clocks(struct smu_context *smu, - struct amd_pp_clock_info *clocks); -extern int smu_dpm_set_power_gate(struct smu_context *smu,uint32_t block_type, bool gate); -extern int smu_handle_task(struct smu_context *smu, - enum amd_dpm_forced_level level, - enum amd_pp_task task_id, - bool lock_needed); -int smu_switch_power_profile(struct smu_context *smu, - enum PP_SMC_POWER_PROFILE type, - bool en); -int smu_get_dpm_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max); -int smu_set_soft_freq_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max); -enum amd_dpm_forced_level smu_get_performance_level(struct smu_context *smu); -int smu_force_performance_level(struct smu_context *smu, enum amd_dpm_forced_level level); -int smu_set_display_count(struct smu_context *smu, uint32_t count); -int smu_set_ac_dc(struct smu_context *smu); -size_t smu_sys_get_pp_feature_mask(struct smu_context *smu, char *buf); -int smu_sys_set_pp_feature_mask(struct smu_context *smu, uint64_t new_mask); -int smu_force_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t mask); -int smu_set_mp1_state(struct smu_context *smu, - enum pp_mp1_state mp1_state); -int smu_set_df_cstate(struct smu_context *smu, - enum pp_df_cstate state); -int smu_allow_xgmi_power_down(struct smu_context *smu, bool en); - -int smu_get_max_sustainable_clocks_by_dc(struct smu_context *smu, - struct pp_smu_nv_clock_table *max_clocks); - -int smu_get_uclk_dpm_states(struct smu_context *smu, - unsigned int *clock_values_in_khz, - unsigned int *num_states); - -int smu_get_dpm_clock_table(struct smu_context *smu, - struct dpm_clocks *clock_table); - -int smu_get_status_gfxoff(struct amdgpu_device *adev, uint32_t *value); - -ssize_t smu_sys_get_gpu_metrics(struct smu_context *smu, void **table); - -int smu_enable_mgpu_fan_boost(struct smu_context *smu); - -#endif -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h deleted file mode 100644 index 79afb132164e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/arcturus_ppsmc.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef ARCTURUS_PP_SMC_H -#define ARCTURUS_PP_SMC_H - -#pragma pack(push, 1) - -// SMU Response Codes: -#define PPSMC_Result_OK 0x1 -#define PPSMC_Result_Failed 0xFF -#define PPSMC_Result_UnknownCmd 0xFE -#define PPSMC_Result_CmdRejectedPrereq 0xFD -#define PPSMC_Result_CmdRejectedBusy 0xFC - -// Message Definitions: -// BASIC -#define PPSMC_MSG_TestMessage 0x1 -#define PPSMC_MSG_GetSmuVersion 0x2 -#define PPSMC_MSG_GetDriverIfVersion 0x3 -#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 -#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 -#define PPSMC_MSG_EnableAllSmuFeatures 0x6 -#define PPSMC_MSG_DisableAllSmuFeatures 0x7 -#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 -#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 -#define PPSMC_MSG_DisableSmuFeaturesLow 0xA -#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB -#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC -#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD -#define PPSMC_MSG_SetDriverDramAddrHigh 0xE -#define PPSMC_MSG_SetDriverDramAddrLow 0xF -#define PPSMC_MSG_SetToolsDramAddrHigh 0x10 -#define PPSMC_MSG_SetToolsDramAddrLow 0x11 -#define PPSMC_MSG_TransferTableSmu2Dram 0x12 -#define PPSMC_MSG_TransferTableDram2Smu 0x13 -#define PPSMC_MSG_UseDefaultPPTable 0x14 -#define PPSMC_MSG_UseBackupPPTable 0x15 -#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x16 -#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x17 - -//BACO/BAMACO/BOMACO -#define PPSMC_MSG_EnterBaco 0x18 -#define PPSMC_MSG_ExitBaco 0x19 -#define PPSMC_MSG_ArmD3 0x1A - -//DPM -#define PPSMC_MSG_SetSoftMinByFreq 0x1B -#define PPSMC_MSG_SetSoftMaxByFreq 0x1C -#define PPSMC_MSG_SetHardMinByFreq 0x1D -#define PPSMC_MSG_SetHardMaxByFreq 0x1E -#define PPSMC_MSG_GetMinDpmFreq 0x1F -#define PPSMC_MSG_GetMaxDpmFreq 0x20 -#define PPSMC_MSG_GetDpmFreqByIndex 0x21 - -#define PPSMC_MSG_SetWorkloadMask 0x22 -#define PPSMC_MSG_SetDfSwitchType 0x23 -#define PPSMC_MSG_GetVoltageByDpm 0x24 -#define PPSMC_MSG_GetVoltageByDpmOverdrive 0x25 - -#define PPSMC_MSG_SetPptLimit 0x26 -#define PPSMC_MSG_GetPptLimit 0x27 - -//Power Gating -#define PPSMC_MSG_PowerUpVcn0 0x28 -#define PPSMC_MSG_PowerDownVcn0 0x29 -#define PPSMC_MSG_PowerUpVcn1 0x2A -#define PPSMC_MSG_PowerDownVcn1 0x2B - -//Resets and reload -#define PPSMC_MSG_PrepareMp1ForUnload 0x2C -#define PPSMC_MSG_PrepareMp1ForReset 0x2D -#define PPSMC_MSG_PrepareMp1ForShutdown 0x2E -#define PPSMC_MSG_SoftReset 0x2F - -//BTC -#define PPSMC_MSG_RunAfllBtc 0x30 -#define PPSMC_MSG_RunDcBtc 0x31 - -//Debug -#define PPSMC_MSG_DramLogSetDramAddrHigh 0x33 -#define PPSMC_MSG_DramLogSetDramAddrLow 0x34 -#define PPSMC_MSG_DramLogSetDramSize 0x35 -#define PPSMC_MSG_GetDebugData 0x36 - -//WAFL and XGMI -#define PPSMC_MSG_WaflTest 0x37 -#define PPSMC_MSG_SetXgmiMode 0x38 - -//Others -#define PPSMC_MSG_SetMemoryChannelEnable 0x39 - -//OOB -#define PPSMC_MSG_SetNumBadHbmPagesRetired 0x3A - -#define PPSMC_MSG_DFCstateControl 0x3B -#define PPSMC_MSG_GmiPwrDnControl 0x3D -#define PPSMC_Message_Count 0x3E - -#define PPSMC_MSG_ReadSerialNumTop32 0x40 -#define PPSMC_MSG_ReadSerialNumBottom32 0x41 - -typedef uint32_t PPSMC_Result; -typedef uint32_t PPSMC_Msg; -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h deleted file mode 100644 index 9b698780aed8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2014 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 CZ_PP_SMC_H -#define CZ_PP_SMC_H - -#pragma pack(push, 1) - -/* Fan control algorithm:*/ -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -enum DPM_ARRAY { - DPM_ARRAY_HARD_MAX, - DPM_ARRAY_HARD_MIN, - DPM_ARRAY_SOFT_MAX, - DPM_ARRAY_SOFT_MIN -}; - -/* - * Return codes for driver to SMC communication. - * Leave these #define-s, enums might not be exactly 8-bits on the microcontroller. - */ -#define PPSMC_Result_OK ((uint16_t)0x01) -#define PPSMC_Result_NoMore ((uint16_t)0x02) -#define PPSMC_Result_NotNow ((uint16_t)0x03) -#define PPSMC_Result_Failed ((uint16_t)0xFF) -#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) -#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) - -#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) - -/* - * Supported driver messages - */ -#define PPSMC_MSG_Test ((uint16_t) 0x1) -#define PPSMC_MSG_GetFeatureStatus ((uint16_t) 0x2) -#define PPSMC_MSG_EnableAllSmuFeatures ((uint16_t) 0x3) -#define PPSMC_MSG_DisableAllSmuFeatures ((uint16_t) 0x4) -#define PPSMC_MSG_OptimizeBattery ((uint16_t) 0x5) -#define PPSMC_MSG_MaximizePerf ((uint16_t) 0x6) -#define PPSMC_MSG_UVDPowerOFF ((uint16_t) 0x7) -#define PPSMC_MSG_UVDPowerON ((uint16_t) 0x8) -#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x9) -#define PPSMC_MSG_VCEPowerON ((uint16_t) 0xA) -#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0xB) -#define PPSMC_MSG_ACPPowerON ((uint16_t) 0xC) -#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0xD) -#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0xE) -#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0xF) -#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x10) -#define PPSMC_MSG_SetMinDeepSleepSclk ((uint16_t) 0x11) -#define PPSMC_MSG_SetSclkSoftMin ((uint16_t) 0x12) -#define PPSMC_MSG_SetSclkSoftMax ((uint16_t) 0x13) -#define PPSMC_MSG_SetSclkHardMin ((uint16_t) 0x14) -#define PPSMC_MSG_SetSclkHardMax ((uint16_t) 0x15) -#define PPSMC_MSG_SetLclkSoftMin ((uint16_t) 0x16) -#define PPSMC_MSG_SetLclkSoftMax ((uint16_t) 0x17) -#define PPSMC_MSG_SetLclkHardMin ((uint16_t) 0x18) -#define PPSMC_MSG_SetLclkHardMax ((uint16_t) 0x19) -#define PPSMC_MSG_SetUvdSoftMin ((uint16_t) 0x1A) -#define PPSMC_MSG_SetUvdSoftMax ((uint16_t) 0x1B) -#define PPSMC_MSG_SetUvdHardMin ((uint16_t) 0x1C) -#define PPSMC_MSG_SetUvdHardMax ((uint16_t) 0x1D) -#define PPSMC_MSG_SetEclkSoftMin ((uint16_t) 0x1E) -#define PPSMC_MSG_SetEclkSoftMax ((uint16_t) 0x1F) -#define PPSMC_MSG_SetEclkHardMin ((uint16_t) 0x20) -#define PPSMC_MSG_SetEclkHardMax ((uint16_t) 0x21) -#define PPSMC_MSG_SetAclkSoftMin ((uint16_t) 0x22) -#define PPSMC_MSG_SetAclkSoftMax ((uint16_t) 0x23) -#define PPSMC_MSG_SetAclkHardMin ((uint16_t) 0x24) -#define PPSMC_MSG_SetAclkHardMax ((uint16_t) 0x25) -#define PPSMC_MSG_SetNclkSoftMin ((uint16_t) 0x26) -#define PPSMC_MSG_SetNclkSoftMax ((uint16_t) 0x27) -#define PPSMC_MSG_SetNclkHardMin ((uint16_t) 0x28) -#define PPSMC_MSG_SetNclkHardMax ((uint16_t) 0x29) -#define PPSMC_MSG_SetPstateSoftMin ((uint16_t) 0x2A) -#define PPSMC_MSG_SetPstateSoftMax ((uint16_t) 0x2B) -#define PPSMC_MSG_SetPstateHardMin ((uint16_t) 0x2C) -#define PPSMC_MSG_SetPstateHardMax ((uint16_t) 0x2D) -#define PPSMC_MSG_DisableLowMemoryPstate ((uint16_t) 0x2E) -#define PPSMC_MSG_EnableLowMemoryPstate ((uint16_t) 0x2F) -#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x30) -#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x31) -#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x32) -#define PPSMC_MSG_DriverDramAddrHi ((uint16_t) 0x33) -#define PPSMC_MSG_DriverDramAddrLo ((uint16_t) 0x34) -#define PPSMC_MSG_CondExecDramAddrHi ((uint16_t) 0x35) -#define PPSMC_MSG_CondExecDramAddrLo ((uint16_t) 0x36) -#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x37) -#define PPSMC_MSG_DriverResetMode ((uint16_t) 0x38) -#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x39) -#define PPSMC_MSG_SetDisplayPhyConfig ((uint16_t) 0x3A) -#define PPSMC_MSG_GetMaxSclkLevel ((uint16_t) 0x3B) -#define PPSMC_MSG_GetMaxLclkLevel ((uint16_t) 0x3C) -#define PPSMC_MSG_GetMaxUvdLevel ((uint16_t) 0x3D) -#define PPSMC_MSG_GetMaxEclkLevel ((uint16_t) 0x3E) -#define PPSMC_MSG_GetMaxAclkLevel ((uint16_t) 0x3F) -#define PPSMC_MSG_GetMaxNclkLevel ((uint16_t) 0x40) -#define PPSMC_MSG_GetMaxPstate ((uint16_t) 0x41) -#define PPSMC_MSG_DramAddrHiVirtual ((uint16_t) 0x42) -#define PPSMC_MSG_DramAddrLoVirtual ((uint16_t) 0x43) -#define PPSMC_MSG_DramAddrHiPhysical ((uint16_t) 0x44) -#define PPSMC_MSG_DramAddrLoPhysical ((uint16_t) 0x45) -#define PPSMC_MSG_DramBufferSize ((uint16_t) 0x46) -#define PPSMC_MSG_SetMmPwrLogDramAddrHi ((uint16_t) 0x47) -#define PPSMC_MSG_SetMmPwrLogDramAddrLo ((uint16_t) 0x48) -#define PPSMC_MSG_SetClkTableAddrHi ((uint16_t) 0x49) -#define PPSMC_MSG_SetClkTableAddrLo ((uint16_t) 0x4A) -#define PPSMC_MSG_GetConservativePowerLimit ((uint16_t) 0x4B) - -#define PPSMC_MSG_InitJobs ((uint16_t) 0x252) -#define PPSMC_MSG_ExecuteJob ((uint16_t) 0x254) - -#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) -#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) - -#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) -#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) - -#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) -#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) - -#define PPSMC_MSG_AllowLowSclkInterrupt ((uint16_t) 0x184) -#define PPSMC_MSG_MmPowerMonitorStart ((uint16_t) 0x18F) -#define PPSMC_MSG_MmPowerMonitorStop ((uint16_t) 0x190) -#define PPSMC_MSG_MmPowerMonitorRestart ((uint16_t) 0x191) - -#define PPSMC_MSG_SetClockGateMask ((uint16_t) 0x260) -#define PPSMC_MSG_SetFpsThresholdLo ((uint16_t) 0x264) -#define PPSMC_MSG_SetFpsThresholdHi ((uint16_t) 0x265) -#define PPSMC_MSG_SetLowSclkIntrThreshold ((uint16_t) 0x266) - -#define PPSMC_MSG_ClkTableXferToDram ((uint16_t) 0x267) -#define PPSMC_MSG_ClkTableXferToSmu ((uint16_t) 0x268) -#define PPSMC_MSG_GetAverageGraphicsActivity ((uint16_t) 0x269) -#define PPSMC_MSG_GetAverageGioActivity ((uint16_t) 0x26A) -#define PPSMC_MSG_SetLoggerBufferSize ((uint16_t) 0x26B) -#define PPSMC_MSG_SetLoggerAddressHigh ((uint16_t) 0x26C) -#define PPSMC_MSG_SetLoggerAddressLow ((uint16_t) 0x26D) -#define PPSMC_MSG_SetWatermarkFrequency ((uint16_t) 0x26E) -#define PPSMC_MSG_SetDisplaySizePowerParams ((uint16_t) 0x26F) - -/* REMOVE LATER*/ -#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) - -/* Feature Enable Masks*/ -#define NB_DPM_MASK 0x00000800 -#define VDDGFX_MASK 0x00800000 -#define VCE_DPM_MASK 0x00400000 -#define ACP_DPM_MASK 0x00040000 -#define UVD_DPM_MASK 0x00010000 -#define GFX_CU_PG_MASK 0x00004000 -#define SCLK_DPM_MASK 0x00080000 - -#if !defined(SMC_MICROCODE) -#pragma pack(pop) - -#endif - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h deleted file mode 100644 index 7ae494569a60..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Copyright 2015 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 _FIJI_PP_SMC_H_ -#define _FIJI_PP_SMC_H_ - -#pragma pack(push, 1) - -#define PPSMC_SWSTATE_FLAG_DC 0x01 -#define PPSMC_SWSTATE_FLAG_UVD 0x02 -#define PPSMC_SWSTATE_FLAG_VCE 0x04 - -#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff - -#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -#define PPSMC_SYSTEMFLAG_GDDR5 0x04 - -#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 - -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 - -/* Defines for DPM 2.0 */ -#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 -#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 -#define PPSMC_DPM2FLAGS_OCP 0x04 - -/* Defines for display watermark level */ -#define PPSMC_DISPLAY_WATERMARK_LOW 0 -#define PPSMC_DISPLAY_WATERMARK_HIGH 1 - -/* In the HW performance level's state flags: */ -#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -#define PPSMC_STATEFLAG_POWERBOOST 0x02 -#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 -#define PPSMC_STATEFLAG_POWERSHIFT 0x08 -#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 -#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 - -/* Fan control algorithm: */ -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -/* Gemini Modes*/ -#define PPSMC_GeminiModeNone 0 /*Single GPU board*/ -#define PPSMC_GeminiModeMaster 1 /*Master GPU on a Gemini board*/ -#define PPSMC_GeminiModeSlave 2 /*Slave GPU on a Gemini board*/ - - -/* Return codes for driver to SMC communication. */ -#define PPSMC_Result_OK ((uint16_t)0x01) -#define PPSMC_Result_NoMore ((uint16_t)0x02) - -#define PPSMC_Result_NotNow ((uint16_t)0x03) - -#define PPSMC_Result_Failed ((uint16_t)0xFF) -#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) -#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) - -#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) - - -#define PPSMC_MSG_Halt ((uint16_t)0x10) -#define PPSMC_MSG_Resume ((uint16_t)0x11) -#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) -#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) -#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) -#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) -#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) -#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) -#define PPSMC_MSG_LevelUp ((uint16_t)0x18) -#define PPSMC_MSG_LevelDown ((uint16_t)0x19) -#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) -#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) - -#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) -#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) -#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) -#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) -#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) - -#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) -#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) -#define PPSMC_MSG_EnableCac ((uint16_t)0x53) -#define PPSMC_MSG_DisableCac ((uint16_t)0x54) -#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) -#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) -#define PPSMC_CACHistoryStart ((uint16_t)0x57) -#define PPSMC_CACHistoryStop ((uint16_t)0x58) -#define PPSMC_TDPClampingActive ((uint16_t)0x59) -#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) -#define PPSMC_StartFanControl ((uint16_t)0x5B) -#define PPSMC_StopFanControl ((uint16_t)0x5C) -#define PPSMC_NoDisplay ((uint16_t)0x5D) -#define PPSMC_HasDisplay ((uint16_t)0x5E) -#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) -#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) -#define PPSMC_MSG_EnableULV ((uint16_t)0x62) -#define PPSMC_MSG_DisableULV ((uint16_t)0x63) -#define PPSMC_MSG_EnterULV ((uint16_t)0x64) -#define PPSMC_MSG_ExitULV ((uint16_t)0x65) -#define PPSMC_PowerShiftActive ((uint16_t)0x6A) -#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) -#define PPSMC_OCPActive ((uint16_t)0x6C) -#define PPSMC_OCPInactive ((uint16_t)0x6D) -#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) -#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) -#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) -#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) -#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) -#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) -#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) -#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) -#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) -#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) -#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) -#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) -#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) -#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) -#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) -#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) - -#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) -#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) -#define PPSMC_FlushDataCache ((uint16_t)0x80) -#define PPSMC_FlushInstrCache ((uint16_t)0x81) - -#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) -#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) - -#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) - -#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) -#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) -#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) -#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) - -#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) - -#define PPSMC_MSG_BREAK ((uint16_t)0xF8) - -/* Trinity Specific Messages*/ -#define PPSMC_MSG_Test ((uint16_t) 0x100) -#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) -#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) -#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) -#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) -#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) -#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) -#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) -#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) -#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) -#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) -#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) -#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) -#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) -#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) -#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) -#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) -#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) -#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) -#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) -#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) -#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) -#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) -#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) -#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) -#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) -#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) -#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) -#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) -#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) -#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) -#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) -#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) -#define PPSMC_MSG_VddNB_Request ((uint16_t) 0x125) -#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint32_t) 0x126) -#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint32_t) 0x127) -#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) - -#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) -#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) -#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) -#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) -#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) -#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) -#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) -#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) -#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) -#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) -#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) -#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) -#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) -#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) -#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) -#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) -#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) -#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) -#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) -#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) -#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) -#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) -#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) -#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) -#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) -#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) -#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) -#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) -#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) -#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) -#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) -#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) -#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) -#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) -#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) - -#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) -#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) - -#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) -#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) -#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150) -#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151) -#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t) 0x152) -#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t) 0x153) -#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154) -#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155) -#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156) -#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157) -#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158) -#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159) -#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a) -#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b) -#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t) 0x15c) -#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) -#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) -#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) -#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) -#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) -#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) -#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) -#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) -#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) -#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) -#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) -#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) -#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) -#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) -#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) -#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t) 0x16c) -#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t) 0x16d) -#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t) 0x16e) -#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t) 0x16f) -#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) -#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) -#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) -#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) -#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) -#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) -#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) -#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) -#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) -#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) -#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) -#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) -#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) -#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) -#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) -#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) -#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) -#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) -#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) -#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) -#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) -#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) -#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) -#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) -#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) -#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) -#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) -#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) -#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) -#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) -#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) -#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) -#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) -#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) -#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) -#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) -#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) -#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) -#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) -#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) -#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) -#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) -#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) -#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) -#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) -#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) -#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) - -#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) -#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) -#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) -#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) -#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) -#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) -#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) -#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) -#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) - -#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) -#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) -#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) -#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) -#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) -#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) -#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) - -#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) -#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) -#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) -#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) -#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) -#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) -#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) -#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) -#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) -#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) -#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) -#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) -#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) -#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) -#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) -#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) -#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) -#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) -#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) -#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) -#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) -#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) -#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) -#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) -#define PPSMC_MSG_EnableAvfs ((uint16_t) 0x26A) -#define PPSMC_MSG_DisableAvfs ((uint16_t) 0x26B) -#define PPSMC_MSG_PerformBtc ((uint16_t) 0x26C) -#define PPSMC_MSG_GetHbmCode ((uint16_t) 0x26D) -#define PPSMC_MSG_GetVrVddcTemperature ((uint16_t) 0x26E) -#define PPSMC_MSG_GetVrMvddTemperature ((uint16_t) 0x26F) -#define PPSMC_MSG_GetLiquidTemperature ((uint16_t) 0x270) -#define PPSMC_MSG_GetPlxTemperature ((uint16_t) 0x271) -#define PPSMC_MSG_RequestI2CControl ((uint16_t) 0x272) -#define PPSMC_MSG_ReleaseI2CControl ((uint16_t) 0x273) -#define PPSMC_MSG_LedConfig ((uint16_t) 0x274) -#define PPSMC_MSG_SetHbmFanCode ((uint16_t) 0x275) -#define PPSMC_MSG_SetHbmThrottleCode ((uint16_t) 0x276) - -#define PPSMC_MSG_GetEnabledPsm ((uint16_t) 0x400) -#define PPSMC_MSG_AgmStartPsm ((uint16_t) 0x401) -#define PPSMC_MSG_AgmReadPsm ((uint16_t) 0x402) -#define PPSMC_MSG_AgmResetPsm ((uint16_t) 0x403) -#define PPSMC_MSG_ReadVftCell ((uint16_t) 0x404) - -/* AVFS Only - Remove Later */ -#define PPSMC_MSG_VftTableIsValid ((uint16_t) 0x666) - -/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ -#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 -#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 -#define PPSMC_EVENT_STATUS_DC 0x00000004 - -typedef uint16_t PPSMC_Msg; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h deleted file mode 100644 index 6e0be6027705..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright 2015 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 _HARDWARE_MANAGER_H_ -#define _HARDWARE_MANAGER_H_ - - - -struct pp_hwmgr; -struct pp_hw_power_state; -struct pp_power_state; -enum amd_dpm_forced_level; -struct PP_TemperatureRange; - - -struct phm_fan_speed_info { - uint32_t min_percent; - uint32_t max_percent; - uint32_t min_rpm; - uint32_t max_rpm; - bool supports_percent_read; - bool supports_percent_write; - bool supports_rpm_read; - bool supports_rpm_write; -}; - -/* Automatic Power State Throttling */ -enum PHM_AutoThrottleSource -{ - PHM_AutoThrottleSource_Thermal, - PHM_AutoThrottleSource_External -}; - -typedef enum PHM_AutoThrottleSource PHM_AutoThrottleSource; - -enum phm_platform_caps { - PHM_PlatformCaps_AtomBiosPpV1 = 0, - PHM_PlatformCaps_PowerPlaySupport, - PHM_PlatformCaps_ACOverdriveSupport, - PHM_PlatformCaps_BacklightSupport, - PHM_PlatformCaps_ThermalController, - PHM_PlatformCaps_BiosPowerSourceControl, - PHM_PlatformCaps_DisableVoltageTransition, - PHM_PlatformCaps_DisableEngineTransition, - PHM_PlatformCaps_DisableMemoryTransition, - PHM_PlatformCaps_DynamicPowerManagement, - PHM_PlatformCaps_EnableASPML0s, - PHM_PlatformCaps_EnableASPML1, - PHM_PlatformCaps_OD5inACSupport, - PHM_PlatformCaps_OD5inDCSupport, - PHM_PlatformCaps_SoftStateOD5, - PHM_PlatformCaps_NoOD5Support, - PHM_PlatformCaps_ContinuousHardwarePerformanceRange, - PHM_PlatformCaps_ActivityReporting, - PHM_PlatformCaps_EnableBackbias, - PHM_PlatformCaps_OverdriveDisabledByPowerBudget, - PHM_PlatformCaps_ShowPowerBudgetWarning, - PHM_PlatformCaps_PowerBudgetWaiverAvailable, - PHM_PlatformCaps_GFXClockGatingSupport, - PHM_PlatformCaps_MMClockGatingSupport, - PHM_PlatformCaps_AutomaticDCTransition, - PHM_PlatformCaps_GeminiPrimary, - PHM_PlatformCaps_MemorySpreadSpectrumSupport, - PHM_PlatformCaps_EngineSpreadSpectrumSupport, - PHM_PlatformCaps_StepVddc, - PHM_PlatformCaps_DynamicPCIEGen2Support, - PHM_PlatformCaps_SMC, - PHM_PlatformCaps_FaultyInternalThermalReading, /* Internal thermal controller reports faulty temperature value when DAC2 is active */ - PHM_PlatformCaps_EnableVoltageControl, /* indicates voltage can be controlled */ - PHM_PlatformCaps_EnableSideportControl, /* indicates Sideport can be controlled */ - PHM_PlatformCaps_VideoPlaybackEEUNotification, /* indicates EEU notification of video start/stop is required */ - PHM_PlatformCaps_TurnOffPll_ASPML1, /* PCIE Turn Off PLL in ASPM L1 */ - PHM_PlatformCaps_EnableHTLinkControl, /* indicates HT Link can be controlled by ACPI or CLMC overridden/automated mode. */ - PHM_PlatformCaps_PerformanceStateOnly, /* indicates only performance power state to be used on current system. */ - PHM_PlatformCaps_ExclusiveModeAlwaysHigh, /* In Exclusive (3D) mode always stay in High state. */ - PHM_PlatformCaps_DisableMGClockGating, /* to disable Medium Grain Clock Gating or not */ - PHM_PlatformCaps_DisableMGCGTSSM, /* TO disable Medium Grain Clock Gating Shader Complex control */ - PHM_PlatformCaps_UVDAlwaysHigh, /* In UVD mode always stay in High state */ - PHM_PlatformCaps_DisablePowerGating, /* to disable power gating */ - PHM_PlatformCaps_CustomThermalPolicy, /* indicates only performance power state to be used on current system. */ - PHM_PlatformCaps_StayInBootState, /* Stay in Boot State, do not do clock/voltage or PCIe Lane and Gen switching (RV7xx and up). */ - PHM_PlatformCaps_SMCAllowSeparateSWThermalState, /* SMC use separate SW thermal state, instead of the default SMC thermal policy. */ - PHM_PlatformCaps_MultiUVDStateSupport, /* Powerplay state table supports multi UVD states. */ - PHM_PlatformCaps_EnableSCLKDeepSleepForUVD, /* With HW ECOs, we don't need to disable SCLK Deep Sleep for UVD state. */ - PHM_PlatformCaps_EnableMCUHTLinkControl, /* Enable HT link control by MCU */ - PHM_PlatformCaps_ABM, /* ABM support.*/ - PHM_PlatformCaps_KongThermalPolicy, /* A thermal policy specific for Kong */ - PHM_PlatformCaps_SwitchVDDNB, /* if the users want to switch VDDNB */ - PHM_PlatformCaps_ULPS, /* support ULPS mode either through ACPI state or ULPS state */ - PHM_PlatformCaps_NativeULPS, /* hardware capable of ULPS state (other than through the ACPI state) */ - PHM_PlatformCaps_EnableMVDDControl, /* indicates that memory voltage can be controlled */ - PHM_PlatformCaps_ControlVDDCI, /* Control VDDCI separately from VDDC. */ - PHM_PlatformCaps_DisableDCODT, /* indicates if DC ODT apply or not */ - PHM_PlatformCaps_DynamicACTiming, /* if the SMC dynamically re-programs MC SEQ register values */ - PHM_PlatformCaps_EnableThermalIntByGPIO, /* enable throttle control through GPIO */ - PHM_PlatformCaps_BootStateOnAlert, /* Go to boot state on alerts, e.g. on an AC->DC transition. */ - PHM_PlatformCaps_DontWaitForVBlankOnAlert, /* Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). */ - PHM_PlatformCaps_Force3DClockSupport, /* indicates if the platform supports force 3D clock. */ - PHM_PlatformCaps_MicrocodeFanControl, /* Fan is controlled by the SMC microcode. */ - PHM_PlatformCaps_AdjustUVDPriorityForSP, - PHM_PlatformCaps_DisableLightSleep, /* Light sleep for evergreen family. */ - PHM_PlatformCaps_DisableMCLS, /* MC Light sleep */ - PHM_PlatformCaps_RegulatorHot, /* Enable throttling on 'regulator hot' events. */ - PHM_PlatformCaps_BACO, /* Support Bus Alive Chip Off mode */ - PHM_PlatformCaps_DisableDPM, /* Disable DPM, supported from Llano */ - PHM_PlatformCaps_DynamicM3Arbiter, /* support dynamically change m3 arbitor parameters */ - PHM_PlatformCaps_SclkDeepSleep, /* support sclk deep sleep */ - PHM_PlatformCaps_DynamicPatchPowerState, /* this ASIC supports to patch power state dynamically */ - PHM_PlatformCaps_ThermalAutoThrottling, /* enabling auto thermal throttling, */ - PHM_PlatformCaps_SumoThermalPolicy, /* A thermal policy specific for Sumo */ - PHM_PlatformCaps_PCIEPerformanceRequest, /* support to change RC voltage */ - PHM_PlatformCaps_BLControlledByGPU, /* support varibright */ - PHM_PlatformCaps_PowerContainment, /* support DPM2 power containment (AKA TDP clamping) */ - PHM_PlatformCaps_SQRamping, /* support DPM2 SQ power throttle */ - PHM_PlatformCaps_CAC, /* support Capacitance * Activity power estimation */ - PHM_PlatformCaps_NIChipsets, /* Northern Island and beyond chipsets */ - PHM_PlatformCaps_TrinityChipsets, /* Trinity chipset */ - PHM_PlatformCaps_EvergreenChipsets, /* Evergreen family chipset */ - PHM_PlatformCaps_PowerControl, /* Cayman and beyond chipsets */ - PHM_PlatformCaps_DisableLSClockGating, /* to disable Light Sleep control for HDP memories */ - PHM_PlatformCaps_BoostState, /* this ASIC supports boost state */ - PHM_PlatformCaps_UserMaxClockForMultiDisplays, /* indicates if max memory clock is used for all status when multiple displays are connected */ - PHM_PlatformCaps_RegWriteDelay, /* indicates if back to back reg write delay is required */ - PHM_PlatformCaps_NonABMSupportInPPLib, /* ABM is not supported in PPLIB, (moved from PPLIB to DAL) */ - PHM_PlatformCaps_GFXDynamicMGPowerGating, /* Enable Dynamic MG PowerGating on Trinity */ - PHM_PlatformCaps_DisableSMUUVDHandshake, /* Disable SMU UVD Handshake */ - PHM_PlatformCaps_DTE, /* Support Digital Temperature Estimation */ - PHM_PlatformCaps_W5100Specifc_SmuSkipMsgDTE, /* This is for the feature requested by David B., and Tonny W.*/ - PHM_PlatformCaps_UVDPowerGating, /* enable UVD power gating, supported from Llano */ - PHM_PlatformCaps_UVDDynamicPowerGating, /* enable UVD Dynamic power gating, supported from UVD5 */ - PHM_PlatformCaps_VCEPowerGating, /* Enable VCE power gating, supported for TN and later ASICs */ - PHM_PlatformCaps_SamuPowerGating, /* Enable SAMU power gating, supported for KV and later ASICs */ - PHM_PlatformCaps_UVDDPM, /* UVD clock DPM */ - PHM_PlatformCaps_VCEDPM, /* VCE clock DPM */ - PHM_PlatformCaps_SamuDPM, /* SAMU clock DPM */ - PHM_PlatformCaps_AcpDPM, /* ACP clock DPM */ - PHM_PlatformCaps_SclkDeepSleepAboveLow, /* Enable SCLK Deep Sleep on all DPM states */ - PHM_PlatformCaps_DynamicUVDState, /* Dynamic UVD State */ - PHM_PlatformCaps_WantSAMClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ - PHM_PlatformCaps_WantUVDClkWithDummyBackEnd, /* Set UVD Clk With Dummy Back End */ - PHM_PlatformCaps_WantVCEClkWithDummyBackEnd, /* Set VCE Clk With Dummy Back End */ - PHM_PlatformCaps_WantACPClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ - PHM_PlatformCaps_OD6inACSupport, /* indicates that the ASIC/back end supports OD6 */ - PHM_PlatformCaps_OD6inDCSupport, /* indicates that the ASIC/back end supports OD6 in DC */ - PHM_PlatformCaps_EnablePlatformPowerManagement, /* indicates that Platform Power Management feature is supported */ - PHM_PlatformCaps_SurpriseRemoval, /* indicates that surprise removal feature is requested */ - PHM_PlatformCaps_NewCACVoltage, /* indicates new CAC voltage table support */ - PHM_PlatformCaps_DiDtSupport, /* for dI/dT feature */ - PHM_PlatformCaps_DBRamping, /* for dI/dT feature */ - PHM_PlatformCaps_TDRamping, /* for dI/dT feature */ - PHM_PlatformCaps_TCPRamping, /* for dI/dT feature */ - PHM_PlatformCaps_DBRRamping, /* for dI/dT feature */ - PHM_PlatformCaps_DiDtEDCEnable, /* for dI/dT feature */ - PHM_PlatformCaps_GCEDC, /* for dI/dT feature */ - PHM_PlatformCaps_PSM, /* for dI/dT feature */ - PHM_PlatformCaps_EnableSMU7ThermalManagement, /* SMC will manage thermal events */ - PHM_PlatformCaps_FPS, /* FPS support */ - PHM_PlatformCaps_ACP, /* ACP support */ - PHM_PlatformCaps_SclkThrottleLowNotification, /* SCLK Throttle Low Notification */ - PHM_PlatformCaps_XDMAEnabled, /* XDMA engine is enabled */ - PHM_PlatformCaps_UseDummyBackEnd, /* use dummy back end */ - PHM_PlatformCaps_EnableDFSBypass, /* Enable DFS bypass */ - PHM_PlatformCaps_VddNBDirectRequest, - PHM_PlatformCaps_PauseMMSessions, - PHM_PlatformCaps_UnTabledHardwareInterface, /* Tableless/direct call hardware interface for CI and newer ASICs */ - PHM_PlatformCaps_SMU7, /* indicates that vpuRecoveryBegin without SMU shutdown */ - PHM_PlatformCaps_RevertGPIO5Polarity, /* indicates revert GPIO5 plarity table support */ - PHM_PlatformCaps_Thermal2GPIO17, /* indicates thermal2GPIO17 table support */ - PHM_PlatformCaps_ThermalOutGPIO, /* indicates ThermalOutGPIO support, pin number is assigned by VBIOS */ - PHM_PlatformCaps_DisableMclkSwitchingForFrameLock, /* Disable memory clock switch during Framelock */ - PHM_PlatformCaps_ForceMclkHigh, /* Disable memory clock switching by forcing memory clock high */ - PHM_PlatformCaps_VRHotGPIOConfigurable, /* indicates VR_HOT GPIO configurable */ - PHM_PlatformCaps_TempInversion, /* enable Temp Inversion feature */ - PHM_PlatformCaps_IOIC3, - PHM_PlatformCaps_ConnectedStandby, - PHM_PlatformCaps_EVV, - PHM_PlatformCaps_EnableLongIdleBACOSupport, - PHM_PlatformCaps_CombinePCCWithThermalSignal, - PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc, - PHM_PlatformCaps_StablePState, - PHM_PlatformCaps_OD6PlusinACSupport, - PHM_PlatformCaps_OD6PlusinDCSupport, - PHM_PlatformCaps_ODThermalLimitUnlock, - PHM_PlatformCaps_ReducePowerLimit, - PHM_PlatformCaps_ODFuzzyFanControlSupport, - PHM_PlatformCaps_GeminiRegulatorFanControlSupport, - PHM_PlatformCaps_ControlVDDGFX, - PHM_PlatformCaps_BBBSupported, - PHM_PlatformCaps_DisableVoltageIsland, - PHM_PlatformCaps_FanSpeedInTableIsRPM, - PHM_PlatformCaps_GFXClockGatingManagedInCAIL, - PHM_PlatformCaps_IcelandULPSSWWorkAround, - PHM_PlatformCaps_FPSEnhancement, - PHM_PlatformCaps_LoadPostProductionFirmware, - PHM_PlatformCaps_VpuRecoveryInProgress, - PHM_PlatformCaps_Falcon_QuickTransition, - PHM_PlatformCaps_AVFS, - PHM_PlatformCaps_ClockStretcher, - PHM_PlatformCaps_TablelessHardwareInterface, - PHM_PlatformCaps_EnableDriverEVV, - PHM_PlatformCaps_SPLLShutdownSupport, - PHM_PlatformCaps_VirtualBatteryState, - PHM_PlatformCaps_IgnoreForceHighClockRequestsInAPUs, - PHM_PlatformCaps_DisableMclkSwitchForVR, - PHM_PlatformCaps_SMU8, - PHM_PlatformCaps_VRHotPolarityHigh, - PHM_PlatformCaps_IPS_UlpsExclusive, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme, - PHM_PlatformCaps_GeminiAsymmetricPower, - PHM_PlatformCaps_OCLPowerOptimization, - PHM_PlatformCaps_MaxPCIEBandWidth, - PHM_PlatformCaps_PerfPerWattOptimizationSupport, - PHM_PlatformCaps_UVDClientMCTuning, - PHM_PlatformCaps_ODNinACSupport, - PHM_PlatformCaps_ODNinDCSupport, - PHM_PlatformCaps_OD8inACSupport, - PHM_PlatformCaps_OD8inDCSupport, - PHM_PlatformCaps_UMDPState, - PHM_PlatformCaps_AutoWattmanSupport, - PHM_PlatformCaps_AutoWattmanEnable_CCCState, - PHM_PlatformCaps_FreeSyncActive, - PHM_PlatformCaps_EnableShadowPstate, - PHM_PlatformCaps_customThermalManagement, - PHM_PlatformCaps_staticFanControl, - PHM_PlatformCaps_Virtual_System, - PHM_PlatformCaps_LowestUclkReservedForUlv, - PHM_PlatformCaps_EnableBoostState, - PHM_PlatformCaps_AVFSSupport, - PHM_PlatformCaps_ThermalPolicyDelay, - PHM_PlatformCaps_CustomFanControlSupport, - PHM_PlatformCaps_BAMACO, - PHM_PlatformCaps_Max -}; - -#define PHM_MAX_NUM_CAPS_BITS_PER_FIELD (sizeof(uint32_t)*8) - -/* Number of uint32_t entries used by CAPS table */ -#define PHM_MAX_NUM_CAPS_ULONG_ENTRIES \ - ((PHM_PlatformCaps_Max + ((PHM_MAX_NUM_CAPS_BITS_PER_FIELD) - 1)) / (PHM_MAX_NUM_CAPS_BITS_PER_FIELD)) - -struct pp_hw_descriptor { - uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; -}; - -enum PHM_PerformanceLevelDesignation { - PHM_PerformanceLevelDesignation_Activity, - PHM_PerformanceLevelDesignation_PowerContainment -}; - -typedef enum PHM_PerformanceLevelDesignation PHM_PerformanceLevelDesignation; - -struct PHM_PerformanceLevel { - uint32_t coreClock; - uint32_t memory_clock; - uint32_t vddc; - uint32_t vddci; - uint32_t nonLocalMemoryFreq; - uint32_t nonLocalMemoryWidth; -}; - -typedef struct PHM_PerformanceLevel PHM_PerformanceLevel; - -/* Function for setting a platform cap */ -static inline void phm_cap_set(uint32_t *caps, - enum phm_platform_caps c) -{ - caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] |= (1UL << - (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); -} - -static inline void phm_cap_unset(uint32_t *caps, - enum phm_platform_caps c) -{ - caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &= ~(1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); -} - -static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps c) -{ - return (0 != (caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] & - (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))))); -} - -#define PP_CAP(c) phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, (c)) - -#define PP_PCIEGenInvalid 0xffff -enum PP_PCIEGen { - PP_PCIEGen1 = 0, /* PCIE 1.0 - Transfer rate of 2.5 GT/s */ - PP_PCIEGen2, /*PCIE 2.0 - Transfer rate of 5.0 GT/s */ - PP_PCIEGen3 /*PCIE 3.0 - Transfer rate of 8.0 GT/s */ -}; - -typedef enum PP_PCIEGen PP_PCIEGen; - -#define PP_Min_PCIEGen PP_PCIEGen1 -#define PP_Max_PCIEGen PP_PCIEGen3 -#define PP_Min_PCIELane 1 -#define PP_Max_PCIELane 16 - -enum phm_clock_Type { - PHM_DispClock = 1, - PHM_SClock, - PHM_MemClock -}; - -#define MAX_NUM_CLOCKS 16 - -struct PP_Clocks { - uint32_t engineClock; - uint32_t memoryClock; - uint32_t BusBandwidth; - uint32_t engineClockInSR; - uint32_t dcefClock; - uint32_t dcefClockInSR; -}; - -struct pp_clock_info { - uint32_t min_mem_clk; - uint32_t max_mem_clk; - uint32_t min_eng_clk; - uint32_t max_eng_clk; - uint32_t min_bus_bandwidth; - uint32_t max_bus_bandwidth; -}; - -struct phm_platform_descriptor { - uint32_t platformCaps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; - uint32_t vbiosInterruptId; - struct PP_Clocks overdriveLimit; - struct PP_Clocks clockStep; - uint32_t hardwareActivityPerformanceLevels; - uint32_t minimumClocksReductionPercentage; - uint32_t minOverdriveVDDC; - uint32_t maxOverdriveVDDC; - uint32_t overdriveVDDCStep; - uint32_t hardwarePerformanceLevels; - uint16_t powerBudget; - uint32_t TDPLimit; - uint32_t nearTDPLimit; - uint32_t nearTDPLimitAdjusted; - uint32_t SQRampingThreshold; - uint32_t CACLeakage; - uint16_t TDPODLimit; - uint32_t TDPAdjustment; - bool TDPAdjustmentPolarity; - uint16_t LoadLineSlope; - uint32_t VidMinLimit; - uint32_t VidMaxLimit; - uint32_t VidStep; - uint32_t VidAdjustment; - bool VidAdjustmentPolarity; -}; - -struct phm_clocks { - uint32_t num_of_entries; - uint32_t clock[MAX_NUM_CLOCKS]; -}; - -#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 -#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 -#define DPMTABLE_UPDATE_SCLK 0x00000004 -#define DPMTABLE_UPDATE_MCLK 0x00000008 -#define DPMTABLE_OD_UPDATE_VDDC 0x00000010 -#define DPMTABLE_UPDATE_SOCCLK 0x00000020 - -struct phm_odn_performance_level { - uint32_t clock; - uint32_t vddc; - bool enabled; -}; - -struct phm_odn_clock_levels { - uint32_t size; - uint32_t options; - uint32_t flags; - uint32_t num_of_pl; - /* variable-sized array, specify by num_of_pl. */ - struct phm_odn_performance_level entries[8]; -}; - -extern int phm_disable_clock_power_gatings(struct pp_hwmgr *hwmgr); -extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); -extern int phm_setup_asic(struct pp_hwmgr *hwmgr); -extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); -extern int phm_disable_dynamic_state_management(struct pp_hwmgr *hwmgr); -extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); -extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); -extern int phm_set_power_state(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pcurrent_state, - const struct pp_hw_power_state *pnew_power_state); - -extern int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, - struct pp_power_state *adjusted_ps, - const struct pp_power_state *current_ps); - -extern int phm_apply_clock_adjust_rules(struct pp_hwmgr *hwmgr); - -extern int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level); -extern int phm_pre_display_configuration_changed(struct pp_hwmgr *hwmgr); -extern int phm_display_configuration_changed(struct pp_hwmgr *hwmgr); -extern int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); -extern int phm_register_irq_handlers(struct pp_hwmgr *hwmgr); -extern int phm_start_thermal_controller(struct pp_hwmgr *hwmgr); -extern int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr); -extern bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr); - -extern int phm_check_states_equal(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pstate1, - const struct pp_hw_power_state *pstate2, - bool *equal); - -extern int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, - const struct amd_pp_display_configuration *display_config); - -extern int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info); - -extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr); - -extern int phm_power_down_asic(struct pp_hwmgr *hwmgr); - -extern int phm_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - PHM_PerformanceLevelDesignation designation, uint32_t index, - PHM_PerformanceLevel *level); - -extern int phm_get_clock_info(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, - struct pp_clock_info *pclock_info, - PHM_PerformanceLevelDesignation designation); - -extern int phm_get_current_shallow_sleep_clocks(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, struct pp_clock_info *clock_info); - -extern int phm_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks); - -extern int phm_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks); -extern int phm_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks); -extern int phm_set_watermarks_for_clocks_ranges(struct pp_hwmgr *hwmgr, - void *clock_ranges); -extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock); - -extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); -extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr); - -extern int phm_set_active_display_count(struct pp_hwmgr *hwmgr, uint32_t count); - -#endif /* _HARDWARE_MANAGER_H_ */ - diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h deleted file mode 100644 index 1b3529efc91e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Copyright 2015 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 _HWMGR_H_ -#define _HWMGR_H_ - -#include -#include "amd_powerplay.h" -#include "hardwaremanager.h" -#include "hwmgr_ppt.h" -#include "ppatomctrl.h" -#include "power_state.h" -#include "smu_helper.h" - -struct pp_hwmgr; -struct phm_fan_speed_info; -struct pp_atomctrl_voltage_table; - -#define VOLTAGE_SCALE 4 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 - -enum DISPLAY_GAP { - DISPLAY_GAP_VBLANK_OR_WM = 0, /* Wait for vblank or MCHG watermark. */ - DISPLAY_GAP_VBLANK = 1, /* Wait for vblank. */ - DISPLAY_GAP_WATERMARK = 2, /* Wait for MCHG watermark. (Note that HW may deassert WM in VBI depending on DC_STUTTER_CNTL.) */ - DISPLAY_GAP_IGNORE = 3 /* Do not wait. */ -}; -typedef enum DISPLAY_GAP DISPLAY_GAP; - -enum BACO_STATE { - BACO_STATE_OUT = 0, - BACO_STATE_IN, -}; - -struct vi_dpm_level { - bool enabled; - uint32_t value; - uint32_t param1; -}; - -struct vi_dpm_table { - uint32_t count; - struct vi_dpm_level dpm_level[1]; -}; - -#define PCIE_PERF_REQ_REMOVE_REGISTRY 0 -#define PCIE_PERF_REQ_FORCE_LOWPOWER 1 -#define PCIE_PERF_REQ_GEN1 2 -#define PCIE_PERF_REQ_GEN2 3 -#define PCIE_PERF_REQ_GEN3 4 - -enum PHM_BackEnd_Magic { - PHM_Dummy_Magic = 0xAA5555AA, - PHM_RV770_Magic = 0xDCBAABCD, - PHM_Kong_Magic = 0x239478DF, - PHM_NIslands_Magic = 0x736C494E, - PHM_Sumo_Magic = 0x8339FA11, - PHM_SIslands_Magic = 0x369431AC, - PHM_Trinity_Magic = 0x96751873, - PHM_CIslands_Magic = 0x38AC78B0, - PHM_Kv_Magic = 0xDCBBABC0, - PHM_VIslands_Magic = 0x20130307, - PHM_Cz_Magic = 0x67DCBA25, - PHM_Rv_Magic = 0x20161121 -}; - -struct phm_set_power_state_input { - const struct pp_hw_power_state *pcurrent_state; - const struct pp_hw_power_state *pnew_state; -}; - -struct phm_clock_array { - uint32_t count; - uint32_t values[1]; -}; - -struct phm_clock_voltage_dependency_record { - uint32_t clk; - uint32_t v; -}; - -struct phm_vceclock_voltage_dependency_record { - uint32_t ecclk; - uint32_t evclk; - uint32_t v; -}; - -struct phm_uvdclock_voltage_dependency_record { - uint32_t vclk; - uint32_t dclk; - uint32_t v; -}; - -struct phm_samuclock_voltage_dependency_record { - uint32_t samclk; - uint32_t v; -}; - -struct phm_acpclock_voltage_dependency_record { - uint32_t acpclk; - uint32_t v; -}; - -struct phm_clock_voltage_dependency_table { - uint32_t count; /* Number of entries. */ - struct phm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -struct phm_phase_shedding_limits_record { - uint32_t Voltage; - uint32_t Sclk; - uint32_t Mclk; -}; - -struct phm_uvd_clock_voltage_dependency_record { - uint32_t vclk; - uint32_t dclk; - uint32_t v; -}; - -struct phm_uvd_clock_voltage_dependency_table { - uint8_t count; - struct phm_uvd_clock_voltage_dependency_record entries[1]; -}; - -struct phm_acp_clock_voltage_dependency_record { - uint32_t acpclk; - uint32_t v; -}; - -struct phm_acp_clock_voltage_dependency_table { - uint32_t count; - struct phm_acp_clock_voltage_dependency_record entries[1]; -}; - -struct phm_vce_clock_voltage_dependency_record { - uint32_t ecclk; - uint32_t evclk; - uint32_t v; -}; - -struct phm_phase_shedding_limits_table { - uint32_t count; - struct phm_phase_shedding_limits_record entries[1]; -}; - -struct phm_vceclock_voltage_dependency_table { - uint8_t count; /* Number of entries. */ - struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -struct phm_uvdclock_voltage_dependency_table { - uint8_t count; /* Number of entries. */ - struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -struct phm_samuclock_voltage_dependency_table { - uint8_t count; /* Number of entries. */ - struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -struct phm_acpclock_voltage_dependency_table { - uint32_t count; /* Number of entries. */ - struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ -}; - -struct phm_vce_clock_voltage_dependency_table { - uint8_t count; - struct phm_vce_clock_voltage_dependency_record entries[1]; -}; - - -enum SMU_ASIC_RESET_MODE -{ - SMU_ASIC_RESET_MODE_0, - SMU_ASIC_RESET_MODE_1, - SMU_ASIC_RESET_MODE_2, -}; - -struct pp_smumgr_func { - char *name; - int (*smu_init)(struct pp_hwmgr *hwmgr); - int (*smu_fini)(struct pp_hwmgr *hwmgr); - int (*start_smu)(struct pp_hwmgr *hwmgr); - int (*check_fw_load_finish)(struct pp_hwmgr *hwmgr, - uint32_t firmware); - int (*request_smu_load_fw)(struct pp_hwmgr *hwmgr); - int (*request_smu_load_specific_fw)(struct pp_hwmgr *hwmgr, - uint32_t firmware); - uint32_t (*get_argument)(struct pp_hwmgr *hwmgr); - int (*send_msg_to_smc)(struct pp_hwmgr *hwmgr, uint16_t msg); - int (*send_msg_to_smc_with_parameter)(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter); - int (*download_pptable_settings)(struct pp_hwmgr *hwmgr, - void **table); - int (*upload_pptable_settings)(struct pp_hwmgr *hwmgr); - int (*update_smc_table)(struct pp_hwmgr *hwmgr, uint32_t type); - int (*process_firmware_header)(struct pp_hwmgr *hwmgr); - int (*update_sclk_threshold)(struct pp_hwmgr *hwmgr); - int (*thermal_setup_fan_table)(struct pp_hwmgr *hwmgr); - int (*thermal_avfs_enable)(struct pp_hwmgr *hwmgr); - int (*init_smc_table)(struct pp_hwmgr *hwmgr); - int (*populate_all_graphic_levels)(struct pp_hwmgr *hwmgr); - int (*populate_all_memory_levels)(struct pp_hwmgr *hwmgr); - int (*initialize_mc_reg_table)(struct pp_hwmgr *hwmgr); - uint32_t (*get_offsetof)(uint32_t type, uint32_t member); - uint32_t (*get_mac_definition)(uint32_t value); - bool (*is_dpm_running)(struct pp_hwmgr *hwmgr); - bool (*is_hw_avfs_present)(struct pp_hwmgr *hwmgr); - int (*update_dpm_settings)(struct pp_hwmgr *hwmgr, void *profile_setting); - int (*smc_table_manager)(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); /*rw: true for read, false for write */ -}; - -struct pp_hwmgr_func { - int (*backend_init)(struct pp_hwmgr *hw_mgr); - int (*backend_fini)(struct pp_hwmgr *hw_mgr); - int (*asic_setup)(struct pp_hwmgr *hw_mgr); - int (*get_power_state_size)(struct pp_hwmgr *hw_mgr); - - int (*apply_state_adjust_rules)(struct pp_hwmgr *hwmgr, - struct pp_power_state *prequest_ps, - const struct pp_power_state *pcurrent_ps); - - int (*apply_clocks_adjust_rules)(struct pp_hwmgr *hwmgr); - - int (*force_dpm_level)(struct pp_hwmgr *hw_mgr, - enum amd_dpm_forced_level level); - - int (*dynamic_state_management_enable)( - struct pp_hwmgr *hw_mgr); - int (*dynamic_state_management_disable)( - struct pp_hwmgr *hw_mgr); - - int (*patch_boot_state)(struct pp_hwmgr *hwmgr, - struct pp_hw_power_state *hw_ps); - - int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, - unsigned long, struct pp_power_state *); - int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); - int (*powerdown_uvd)(struct pp_hwmgr *hwmgr); - void (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); - void (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); - void (*powergate_acp)(struct pp_hwmgr *hwmgr, bool bgate); - uint32_t (*get_mclk)(struct pp_hwmgr *hwmgr, bool low); - uint32_t (*get_sclk)(struct pp_hwmgr *hwmgr, bool low); - int (*power_state_set)(struct pp_hwmgr *hwmgr, - const void *state); - int (*notify_smc_display_config_after_ps_adjustment)(struct pp_hwmgr *hwmgr); - int (*pre_display_config_changed)(struct pp_hwmgr *hwmgr); - int (*display_config_changed)(struct pp_hwmgr *hwmgr); - int (*disable_clock_power_gating)(struct pp_hwmgr *hwmgr); - int (*update_clock_gatings)(struct pp_hwmgr *hwmgr, - const uint32_t *msg_id); - int (*set_max_fan_rpm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); - int (*set_max_fan_pwm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); - int (*stop_thermal_controller)(struct pp_hwmgr *hwmgr); - int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); - void (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode); - uint32_t (*get_fan_control_mode)(struct pp_hwmgr *hwmgr); - int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent); - int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed); - int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent); - int (*get_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t *speed); - int (*reset_fan_speed_to_default)(struct pp_hwmgr *hwmgr); - int (*uninitialize_thermal_controller)(struct pp_hwmgr *hwmgr); - int (*register_irq_handlers)(struct pp_hwmgr *hwmgr); - bool (*check_smc_update_required_for_display_configuration)(struct pp_hwmgr *hwmgr); - int (*check_states_equal)(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *pstate1, - const struct pp_hw_power_state *pstate2, - bool *equal); - int (*set_cpu_power_state)(struct pp_hwmgr *hwmgr); - int (*store_cc6_data)(struct pp_hwmgr *hwmgr, uint32_t separation_time, - bool cc6_disable, bool pstate_disable, - bool pstate_switch_disable); - int (*get_dal_power_level)(struct pp_hwmgr *hwmgr, - struct amd_pp_simple_clock_info *info); - int (*get_performance_level)(struct pp_hwmgr *, const struct pp_hw_power_state *, - PHM_PerformanceLevelDesignation, uint32_t, PHM_PerformanceLevel *); - int (*get_current_shallow_sleep_clocks)(struct pp_hwmgr *hwmgr, - const struct pp_hw_power_state *state, struct pp_clock_info *clock_info); - int (*get_clock_by_type)(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type type, struct amd_pp_clocks *clocks); - int (*get_clock_by_type_with_latency)(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_latency *clocks); - int (*get_clock_by_type_with_voltage)(struct pp_hwmgr *hwmgr, - enum amd_pp_clock_type type, - struct pp_clock_levels_with_voltage *clocks); - int (*set_watermarks_for_clocks_ranges)(struct pp_hwmgr *hwmgr, void *clock_ranges); - int (*display_clock_voltage_request)(struct pp_hwmgr *hwmgr, - struct pp_display_clock_request *clock); - int (*get_max_high_clocks)(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); - int (*power_off_asic)(struct pp_hwmgr *hwmgr); - int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); - int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); - int (*powergate_gfx)(struct pp_hwmgr *hwmgr, bool enable); - int (*get_sclk_od)(struct pp_hwmgr *hwmgr); - int (*set_sclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); - int (*get_mclk_od)(struct pp_hwmgr *hwmgr); - int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value); - int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size); - int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable); - int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr); - int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); - int (*set_min_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); - int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); - int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, - uint32_t virtual_addr_low, - uint32_t virtual_addr_hi, - uint32_t mc_addr_low, - uint32_t mc_addr_hi, - uint32_t size); - int (*update_nbdpm_pstate)(struct pp_hwmgr *hwmgr, - bool enable, - bool lock); - int (*get_thermal_temperature_range)(struct pp_hwmgr *hwmgr, - struct PP_TemperatureRange *range); - int (*get_power_profile_mode)(struct pp_hwmgr *hwmgr, char *buf); - int (*set_power_profile_mode)(struct pp_hwmgr *hwmgr, long *input, uint32_t size); - int (*odn_edit_dpm_table)(struct pp_hwmgr *hwmgr, - enum PP_OD_DPM_TABLE_COMMAND type, - long *input, uint32_t size); - int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n); - int (*powergate_mmhub)(struct pp_hwmgr *hwmgr); - int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr); - int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate); - int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr); - int (*set_hard_min_dcefclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); - int (*set_hard_min_fclk_by_freq)(struct pp_hwmgr *hwmgr, uint32_t clock); - int (*get_asic_baco_capability)(struct pp_hwmgr *hwmgr, bool *cap); - int (*get_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE *state); - int (*set_asic_baco_state)(struct pp_hwmgr *hwmgr, enum BACO_STATE state); - int (*get_ppfeature_status)(struct pp_hwmgr *hwmgr, char *buf); - int (*set_ppfeature_status)(struct pp_hwmgr *hwmgr, uint64_t ppfeature_masks); - int (*set_mp1_state)(struct pp_hwmgr *hwmgr, enum pp_mp1_state mp1_state); - int (*asic_reset)(struct pp_hwmgr *hwmgr, enum SMU_ASIC_RESET_MODE mode); - int (*smu_i2c_bus_access)(struct pp_hwmgr *hwmgr, bool aquire); - int (*set_df_cstate)(struct pp_hwmgr *hwmgr, enum pp_df_cstate state); - int (*set_xgmi_pstate)(struct pp_hwmgr *hwmgr, uint32_t pstate); - int (*disable_power_features_for_compute_performance)(struct pp_hwmgr *hwmgr, - bool disable); - ssize_t (*get_gpu_metrics)(struct pp_hwmgr *hwmgr, void **table); -}; - -struct pp_table_func { - int (*pptable_init)(struct pp_hwmgr *hw_mgr); - int (*pptable_fini)(struct pp_hwmgr *hw_mgr); - int (*pptable_get_number_of_vce_state_table_entries)(struct pp_hwmgr *hw_mgr); - int (*pptable_get_vce_state_table_entry)( - struct pp_hwmgr *hwmgr, - unsigned long i, - struct amd_vce_state *vce_state, - void **clock_info, - unsigned long *flag); -}; - -union phm_cac_leakage_record { - struct { - uint16_t Vddc; /* in CI, we use it for StdVoltageHiSidd */ - uint32_t Leakage; /* in CI, we use it for StdVoltageLoSidd */ - }; - struct { - uint16_t Vddc1; - uint16_t Vddc2; - uint16_t Vddc3; - }; -}; - -struct phm_cac_leakage_table { - uint32_t count; - union phm_cac_leakage_record entries[1]; -}; - -struct phm_samu_clock_voltage_dependency_record { - uint32_t samclk; - uint32_t v; -}; - - -struct phm_samu_clock_voltage_dependency_table { - uint8_t count; - struct phm_samu_clock_voltage_dependency_record entries[1]; -}; - -struct phm_cac_tdp_table { - uint16_t usTDP; - uint16_t usConfigurableTDP; - uint16_t usTDC; - uint16_t usBatteryPowerLimit; - uint16_t usSmallPowerLimit; - uint16_t usLowCACLeakage; - uint16_t usHighCACLeakage; - uint16_t usMaximumPowerDeliveryLimit; - uint16_t usEDCLimit; - uint16_t usOperatingTempMinLimit; - uint16_t usOperatingTempMaxLimit; - uint16_t usOperatingTempStep; - uint16_t usOperatingTempHyst; - uint16_t usDefaultTargetOperatingTemp; - uint16_t usTargetOperatingTemp; - uint16_t usPowerTuneDataSetID; - uint16_t usSoftwareShutdownTemp; - uint16_t usClockStretchAmount; - uint16_t usTemperatureLimitHotspot; - uint16_t usTemperatureLimitLiquid1; - uint16_t usTemperatureLimitLiquid2; - uint16_t usTemperatureLimitVrVddc; - uint16_t usTemperatureLimitVrMvdd; - uint16_t usTemperatureLimitPlx; - uint8_t ucLiquid1_I2C_address; - uint8_t ucLiquid2_I2C_address; - uint8_t ucLiquid_I2C_Line; - uint8_t ucVr_I2C_address; - uint8_t ucVr_I2C_Line; - uint8_t ucPlx_I2C_address; - uint8_t ucPlx_I2C_Line; - uint32_t usBoostPowerLimit; - uint8_t ucCKS_LDO_REFSEL; -}; - -struct phm_tdp_table { - uint16_t usTDP; - uint16_t usConfigurableTDP; - uint16_t usTDC; - uint16_t usBatteryPowerLimit; - uint16_t usSmallPowerLimit; - uint16_t usLowCACLeakage; - uint16_t usHighCACLeakage; - uint16_t usMaximumPowerDeliveryLimit; - uint16_t usEDCLimit; - uint16_t usOperatingTempMinLimit; - uint16_t usOperatingTempMaxLimit; - uint16_t usOperatingTempStep; - uint16_t usOperatingTempHyst; - uint16_t usDefaultTargetOperatingTemp; - uint16_t usTargetOperatingTemp; - uint16_t usPowerTuneDataSetID; - uint16_t usSoftwareShutdownTemp; - uint16_t usClockStretchAmount; - uint16_t usTemperatureLimitTedge; - uint16_t usTemperatureLimitHotspot; - uint16_t usTemperatureLimitLiquid1; - uint16_t usTemperatureLimitLiquid2; - uint16_t usTemperatureLimitHBM; - uint16_t usTemperatureLimitVrVddc; - uint16_t usTemperatureLimitVrMvdd; - uint16_t usTemperatureLimitPlx; - uint8_t ucLiquid1_I2C_address; - uint8_t ucLiquid2_I2C_address; - uint8_t ucLiquid_I2C_Line; - uint8_t ucVr_I2C_address; - uint8_t ucVr_I2C_Line; - uint8_t ucPlx_I2C_address; - uint8_t ucPlx_I2C_Line; - uint8_t ucLiquid_I2C_LineSDA; - uint8_t ucVr_I2C_LineSDA; - uint8_t ucPlx_I2C_LineSDA; - uint32_t usBoostPowerLimit; - uint16_t usBoostStartTemperature; - uint16_t usBoostStopTemperature; - uint32_t ulBoostClock; -}; - -struct phm_ppm_table { - uint8_t ppm_design; - uint16_t cpu_core_number; - uint32_t platform_tdp; - uint32_t small_ac_platform_tdp; - uint32_t platform_tdc; - uint32_t small_ac_platform_tdc; - uint32_t apu_tdp; - uint32_t dgpu_tdp; - uint32_t dgpu_ulv_power; - uint32_t tj_max; -}; - -struct phm_vq_budgeting_record { - uint32_t ulCUs; - uint32_t ulSustainableSOCPowerLimitLow; - uint32_t ulSustainableSOCPowerLimitHigh; - uint32_t ulMinSclkLow; - uint32_t ulMinSclkHigh; - uint8_t ucDispConfig; - uint32_t ulDClk; - uint32_t ulEClk; - uint32_t ulSustainableSclk; - uint32_t ulSustainableCUs; -}; - -struct phm_vq_budgeting_table { - uint8_t numEntries; - struct phm_vq_budgeting_record entries[1]; -}; - -struct phm_clock_and_voltage_limits { - uint32_t sclk; - uint32_t mclk; - uint32_t gfxclk; - uint16_t vddc; - uint16_t vddci; - uint16_t vddgfx; - uint16_t vddmem; -}; - -/* Structure to hold PPTable information */ - -struct phm_ppt_v1_information { - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_socclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dcefclk; - struct phm_clock_array *valid_sclk_values; - struct phm_clock_array *valid_mclk_values; - struct phm_clock_array *valid_socclk_values; - struct phm_clock_array *valid_dcefclk_values; - struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; - struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; - struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; - struct phm_ppm_table *ppm_parameter_table; - struct phm_cac_tdp_table *cac_dtp_table; - struct phm_tdp_table *tdp_table; - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table; - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddmem_lookup_table; - struct phm_ppt_v1_pcie_table *pcie_table; - struct phm_ppt_v1_gpio_table *gpio_table; - uint16_t us_ulv_voltage_offset; - uint16_t us_ulv_smnclk_did; - uint16_t us_ulv_mp1clk_did; - uint16_t us_ulv_gfxclk_bypass; - uint16_t us_gfxclk_slew_rate; - uint16_t us_min_gfxclk_freq_limit; -}; - -struct phm_ppt_v2_information { - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_socclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dcefclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_pixclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_dispclk; - struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_phyclk; - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table; - - struct phm_clock_voltage_dependency_table *vddc_dep_on_dalpwrl; - - struct phm_clock_array *valid_sclk_values; - struct phm_clock_array *valid_mclk_values; - struct phm_clock_array *valid_socclk_values; - struct phm_clock_array *valid_dcefclk_values; - - struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; - struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; - - struct phm_ppm_table *ppm_parameter_table; - struct phm_cac_tdp_table *cac_dtp_table; - struct phm_tdp_table *tdp_table; - - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddmem_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddci_lookup_table; - - struct phm_ppt_v1_pcie_table *pcie_table; - - uint16_t us_ulv_voltage_offset; - uint16_t us_ulv_smnclk_did; - uint16_t us_ulv_mp1clk_did; - uint16_t us_ulv_gfxclk_bypass; - uint16_t us_gfxclk_slew_rate; - uint16_t us_min_gfxclk_freq_limit; - - uint8_t uc_gfx_dpm_voltage_mode; - uint8_t uc_soc_dpm_voltage_mode; - uint8_t uc_uclk_dpm_voltage_mode; - uint8_t uc_uvd_dpm_voltage_mode; - uint8_t uc_vce_dpm_voltage_mode; - uint8_t uc_mp0_dpm_voltage_mode; - uint8_t uc_dcef_dpm_voltage_mode; -}; - -struct phm_ppt_v3_information -{ - uint8_t uc_thermal_controller_type; - - uint16_t us_small_power_limit1; - uint16_t us_small_power_limit2; - uint16_t us_boost_power_limit; - - uint16_t us_od_turbo_power_limit; - uint16_t us_od_powersave_power_limit; - uint16_t us_software_shutdown_temp; - - uint32_t *power_saving_clock_max; - uint32_t *power_saving_clock_min; - - uint8_t *od_feature_capabilities; - uint32_t *od_settings_max; - uint32_t *od_settings_min; - - void *smc_pptable; -}; - -struct phm_dynamic_state_info { - struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk; - struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk; - struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk; - struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk; - struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; - struct phm_clock_array *valid_sclk_values; - struct phm_clock_array *valid_mclk_values; - struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; - struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; - uint32_t mclk_sclk_ratio; - uint32_t sclk_mclk_delta; - uint32_t vddc_vddci_delta; - uint32_t min_vddc_for_pcie_gen2; - struct phm_cac_leakage_table *cac_leakage_table; - struct phm_phase_shedding_limits_table *vddc_phase_shed_limits_table; - - struct phm_vce_clock_voltage_dependency_table - *vce_clock_voltage_dependency_table; - struct phm_uvd_clock_voltage_dependency_table - *uvd_clock_voltage_dependency_table; - struct phm_acp_clock_voltage_dependency_table - *acp_clock_voltage_dependency_table; - struct phm_samu_clock_voltage_dependency_table - *samu_clock_voltage_dependency_table; - - struct phm_ppm_table *ppm_parameter_table; - struct phm_cac_tdp_table *cac_dtp_table; - struct phm_clock_voltage_dependency_table *vdd_gfx_dependency_on_sclk; -}; - -struct pp_fan_info { - bool bNoFan; - uint8_t ucTachometerPulsesPerRevolution; - uint32_t ulMinRPM; - uint32_t ulMaxRPM; -}; - -struct pp_advance_fan_control_parameters { - uint16_t usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ - uint16_t usTMed; /* The middle temperature where we change slopes. */ - uint16_t usTHigh; /* The high temperature for setting the second slope. */ - uint16_t usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ - uint16_t usPWMMed; /* The PWM value (in percent) at TMed. */ - uint16_t usPWMHigh; /* The PWM value at THigh. */ - uint8_t ucTHyst; /* Temperature hysteresis. Integer. */ - uint32_t ulCycleDelay; /* The time between two invocations of the fan control routine in microseconds. */ - uint16_t usTMax; /* The max temperature */ - uint8_t ucFanControlMode; - uint16_t usFanPWMMinLimit; - uint16_t usFanPWMMaxLimit; - uint16_t usFanPWMStep; - uint16_t usDefaultMaxFanPWM; - uint16_t usFanOutputSensitivity; - uint16_t usDefaultFanOutputSensitivity; - uint16_t usMaxFanPWM; /* The max Fan PWM value for Fuzzy Fan Control feature */ - uint16_t usFanRPMMinLimit; /* Minimum limit range in percentage, need to calculate based on minRPM/MaxRpm */ - uint16_t usFanRPMMaxLimit; /* Maximum limit range in percentage, usually set to 100% by default */ - uint16_t usFanRPMStep; /* Step increments/decerements, in percent */ - uint16_t usDefaultMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, default from PPTable */ - uint16_t usMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, user defined */ - uint16_t usFanCurrentLow; /* Low current */ - uint16_t usFanCurrentHigh; /* High current */ - uint16_t usFanRPMLow; /* Low RPM */ - uint16_t usFanRPMHigh; /* High RPM */ - uint32_t ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ - uint8_t ucTargetTemperature; /* Advanced fan controller target temperature. */ - uint8_t ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ - uint16_t usFanGainEdge; /* The following is added for Fiji */ - uint16_t usFanGainHotspot; - uint16_t usFanGainLiquid; - uint16_t usFanGainVrVddc; - uint16_t usFanGainVrMvdd; - uint16_t usFanGainPlx; - uint16_t usFanGainHbm; - uint8_t ucEnableZeroRPM; - uint8_t ucFanStopTemperature; - uint8_t ucFanStartTemperature; - uint32_t ulMaxFanSCLKAcousticLimit; /* Maximum Fan Controller SCLK Frequency Acoustic Limit. */ - uint32_t ulTargetGfxClk; - uint16_t usZeroRPMStartTemperature; - uint16_t usZeroRPMStopTemperature; - uint16_t usMGpuThrottlingRPMLimit; -}; - -struct pp_thermal_controller_info { - uint8_t ucType; - uint8_t ucI2cLine; - uint8_t ucI2cAddress; - uint8_t use_hw_fan_control; - struct pp_fan_info fanInfo; - struct pp_advance_fan_control_parameters advanceFanControlParameters; -}; - -struct phm_microcode_version_info { - uint32_t SMC; - uint32_t DMCU; - uint32_t MC; - uint32_t NB; -}; - -enum PP_TABLE_VERSION { - PP_TABLE_V0 = 0, - PP_TABLE_V1, - PP_TABLE_V2, - PP_TABLE_MAX -}; - -/** - * The main hardware manager structure. - */ -#define Workload_Policy_Max 6 - -struct pp_hwmgr { - void *adev; - uint32_t chip_family; - uint32_t chip_id; - uint32_t smu_version; - bool not_vf; - bool pm_en; - bool pp_one_vf; - struct mutex smu_lock; - struct mutex msg_lock; - - uint32_t pp_table_version; - void *device; - struct pp_smumgr *smumgr; - const void *soft_pp_table; - uint32_t soft_pp_table_size; - void *hardcode_pp_table; - bool need_pp_table_upload; - - struct amd_vce_state vce_states[AMD_MAX_VCE_LEVELS]; - uint32_t num_vce_state_tables; - - enum amd_dpm_forced_level dpm_level; - enum amd_dpm_forced_level saved_dpm_level; - enum amd_dpm_forced_level request_dpm_level; - uint32_t usec_timeout; - void *pptable; - struct phm_platform_descriptor platform_descriptor; - void *backend; - - void *smu_backend; - const struct pp_smumgr_func *smumgr_funcs; - bool is_kicker; - - enum PP_DAL_POWERLEVEL dal_power_level; - struct phm_dynamic_state_info dyn_state; - const struct pp_hwmgr_func *hwmgr_func; - const struct pp_table_func *pptable_func; - - struct pp_power_state *ps; - uint32_t num_ps; - struct pp_thermal_controller_info thermal_controller; - bool fan_ctrl_is_in_default_mode; - uint32_t fan_ctrl_default_mode; - bool fan_ctrl_enabled; - uint32_t tmin; - struct phm_microcode_version_info microcode_version_info; - uint32_t ps_size; - struct pp_power_state *current_ps; - struct pp_power_state *request_ps; - struct pp_power_state *boot_ps; - struct pp_power_state *uvd_ps; - const struct amd_pp_display_configuration *display_config; - uint32_t feature_mask; - bool avfs_supported; - /* UMD Pstate */ - bool en_umd_pstate; - uint32_t power_profile_mode; - uint32_t default_power_profile_mode; - uint32_t pstate_sclk; - uint32_t pstate_mclk; - bool od_enabled; - uint32_t power_limit; - uint32_t default_power_limit; - uint32_t workload_mask; - uint32_t workload_prority[Workload_Policy_Max]; - uint32_t workload_setting[Workload_Policy_Max]; - bool gfxoff_state_changed_by_workload; -}; - -int hwmgr_early_init(struct pp_hwmgr *hwmgr); -int hwmgr_sw_init(struct pp_hwmgr *hwmgr); -int hwmgr_sw_fini(struct pp_hwmgr *hwmgr); -int hwmgr_hw_init(struct pp_hwmgr *hwmgr); -int hwmgr_hw_fini(struct pp_hwmgr *hwmgr); -int hwmgr_suspend(struct pp_hwmgr *hwmgr); -int hwmgr_resume(struct pp_hwmgr *hwmgr); - -int hwmgr_handle_task(struct pp_hwmgr *hwmgr, - enum amd_pp_task task_id, - enum amd_pm_state_type *user_state); - - -#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU - - -#endif /* _HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h b/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h deleted file mode 100644 index 6a53b7e74ccd..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h +++ /dev/null @@ -1,1793 +0,0 @@ -/* - * Copyright 2015 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 _POLARIS10_PWRVIRUS_H -#define _POLARIS10_PWRVIRUS_H - - -#define mmCP_HYP_MEC1_UCODE_ADDR 0xf81a -#define mmCP_HYP_MEC1_UCODE_DATA 0xf81b -#define mmCP_HYP_MEC2_UCODE_ADDR 0xf81c -#define mmCP_HYP_MEC2_UCODE_DATA 0xf81d - -struct PWR_Command_Table { - uint32_t data; - uint32_t reg; -}; - -typedef struct PWR_Command_Table PWR_Command_Table; - -struct PWR_DFY_Section { - uint32_t dfy_cntl; - uint32_t dfy_addr_hi, dfy_addr_lo; - uint32_t dfy_size; - uint32_t dfy_data[]; -}; - -typedef struct PWR_DFY_Section PWR_DFY_Section; - -static const PWR_Command_Table pwr_virus_table_pre[] = { - { 0x00000000, mmRLC_CNTL }, - { 0x00000002, mmRLC_SRM_CNTL }, - { 0x15000000, mmCP_ME_CNTL }, - { 0x50000000, mmCP_MEC_CNTL }, - { 0x80000004, mmCP_DFY_CNTL }, - { 0x0840800a, mmCP_RB0_CNTL }, - { 0xf30fff0f, mmTCC_CTRL }, - { 0x00000002, mmTCC_EXE_DISABLE }, - { 0x000000ff, mmTCP_ADDR_CONFIG }, - { 0x540ff000, mmCP_CPC_IC_BASE_LO }, - { 0x000000b4, mmCP_CPC_IC_BASE_HI }, - { 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, - { 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, - { 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { 0x00000000, 0xFFFFFFFF }, -}; - -static const PWR_DFY_Section pwr_virus_section1 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x540fe800, - .dfy_data = { - 0x7e000200, 0x7e020201, 0x7e040204, 0x7e060205, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, - 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, - 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x54106f00, 0x000400b4, 0x00004000, 0x00804fac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 416 -}; - -static const PWR_DFY_Section pwr_virus_section2 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x540fef00, - .dfy_data = { - 0xc0031502, 0x00001e00, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 16 -}; - -static const PWR_DFY_Section pwr_virus_section3 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x540ff000, - .dfy_data = { - 0xc424000b, 0x80000145, 0x94800001, 0x94c00001, 0x95000001, 0x95400001, 0x95800001, 0xdc810000, - 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xc4080061, 0xd8400013, 0xd8000003, 0xc40c0001, - 0x24ccffff, 0x3cd08000, 0x9500fffd, 0x1cd0ffcf, 0x7d018001, 0xc4140004, 0x050c0019, 0xd8400008, - 0x84c00000, 0x80000023, 0x80000067, 0x8000006a, 0x8000006d, 0x80000079, 0x80000084, 0x8000008f, - 0x80000099, 0x800000a0, 0x800000af, 0xd8400053, 0xc4080007, 0x388c0001, 0x08880002, 0x04100003, - 0x94c00005, 0x98800003, 0x04100004, 0x8000002d, 0x04100005, 0x8c00003f, 0x8c000043, 0x28cc0000, - 0xccc00050, 0x8c000055, 0x28080001, 0xcc000004, 0x7d808001, 0xd8400013, 0xd88130b8, 0xcd400008, - 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, 0xcc800005, 0xdc080000, 0x80000168, 0xc40c000e, - 0x28cc0008, 0xccc00013, 0x90000000, 0xcd013278, 0xc4113278, 0x95000001, 0x24cc0700, 0xd8400029, - 0xc4113255, 0xcd01324f, 0xc4113254, 0x1d10ffdf, 0xcd013254, 0x10cc0014, 0x1d10c017, 0x7d0d000a, - 0xd8400013, 0xd8400008, 0xcd0130b7, 0x14cc0010, 0x90000000, 0xd9c00036, 0x8000005d, 0xd8400013, - 0xc00c4000, 0xccc130b5, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc40c0021, 0x14d00011, 0x9500fffe, - 0xdc030000, 0xd800000c, 0xd800000d, 0xc40c005e, 0x94c01b10, 0xd8400013, 0x90000000, 0xc00e0080, - 0xccc130b5, 0x8000013b, 0xc00e0800, 0xccc130b5, 0x8000013b, 0xd8400053, 0x04100006, 0x8c00003f, - 0x8c000043, 0x28cc0000, 0xccc00050, 0x8c000055, 0x280c0008, 0xccc00052, 0xd8000021, 0x28180039, - 0x80000034, 0xd8400053, 0x04100007, 0x8c00003f, 0x8c000043, 0x28cc0001, 0xccc00050, 0x8c000055, - 0x280c0010, 0xccc00052, 0x28180039, 0x80000034, 0xd8400053, 0x04100008, 0x8c00003f, 0x8c000043, - 0x28cc0003, 0xccc00050, 0x8c000055, 0x280c0020, 0xccc00052, 0x28180039, 0x80000034, 0xdc030000, - 0xd8000069, 0x28080001, 0xc428000d, 0x7ca88004, 0xcc800079, 0x04280001, 0xcc00006f, 0x8000013b, - 0x80000034, 0x04100010, 0x8c00003f, 0x8c000043, 0xccc00078, 0x8c000055, 0x28180080, 0x80000034, - 0x04100001, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xcd013278, 0xc4113278, 0x95000001, 0xc00c4000, - 0xc4113254, 0x1d10c017, 0xd8400013, 0xd8400008, 0xccc130b5, 0xcd0130b7, 0x8000013b, 0x95c00001, - 0x96000001, 0x96400001, 0x96800001, 0x96c00001, 0x97000001, 0x97400001, 0x97800001, 0x97c00001, - 0xdc810000, 0xc40c000c, 0xcd4c0380, 0xcdcc0388, 0x55dc0020, 0xcdcc038c, 0xce0c0390, 0x56200020, - 0xce0c0394, 0xce4c0398, 0x56640020, 0xce4c039c, 0xce8c03a0, 0x56a80020, 0xce8c03a4, 0xcecc03a8, - 0x56ec0020, 0xcecc03ac, 0xcf0c03b0, 0x57300020, 0xcf0c03b4, 0xcf4c03b8, 0x57740020, 0xcf4c03bc, - 0xcf8c03c0, 0x57b80020, 0xcf8c03c4, 0xcfcc03c8, 0x57fc0020, 0xcfcc03cc, 0xd9000033, 0xc41c0009, - 0x25dc0010, 0x95c0fffe, 0xd8400013, 0xc41c000c, 0x05dc002f, 0xcdc12009, 0xc41d200a, 0xd8400013, - 0xcc012009, 0xd9000034, 0x25e01c00, 0x12200013, 0x25e40300, 0x12640008, 0x25e800c0, 0x12a80002, - 0x25ec003f, 0x7e25c00a, 0x7eae400a, 0x7de5c00a, 0xddc10000, 0xc02ee000, 0xcec1c200, 0xc40c005f, - 0xccc00037, 0x24d000ff, 0x31100006, 0x9500007b, 0x8c000190, 0xdc1c0000, 0xd8400013, 0xcdc1c200, - 0xc40c000c, 0xc4df0388, 0xc4d7038c, 0x51540020, 0x7d5dc01a, 0xc4e30390, 0xc4d70394, 0x51540020, - 0x7d62001a, 0xc4e70398, 0xc4d7039c, 0x51540020, 0x7d66401a, 0xc4eb03a0, 0xc4d703a4, 0x51540020, - 0x7d6a801a, 0xc4ef03a8, 0xc4d703ac, 0x51540020, 0x7d6ec01a, 0xc4f303b0, 0xc4d703b4, 0x51540020, - 0x7d73001a, 0xc4f703b8, 0xc4d703bc, 0x51540020, 0x7d77401a, 0xc4fb03c0, 0xc4d703c4, 0x51540020, - 0x7d7b801a, 0xc4ff03c8, 0xc4d703cc, 0x51540020, 0x7d7fc01a, 0xdc080000, 0xcc800013, 0xc4d70380, - 0xc4080001, 0x1c88001c, 0xcd400008, 0xc40c0083, 0x94c00010, 0xdc0e0000, 0x94c0000e, 0xc40c0082, - 0x24d00001, 0x9900000b, 0x18cc01e3, 0x3cd00004, 0x95000008, 0xc40c0085, 0x18cc006a, 0x98c00005, - 0xc40c0082, 0x18cc01e3, 0x3cd00004, 0x9900fffa, 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, - 0xcc800004, 0xdc080000, 0x90000000, 0xc4080001, 0x1c88001c, 0xcd400008, 0xdc180000, 0xdc140000, - 0xdc100000, 0xdc0c0000, 0xcc800004, 0xdc080000, 0x90000000, 0xd8400051, 0xc428000c, 0x04180018, - 0x32640002, 0x9a80001f, 0x9a40001e, 0xcd800013, 0xc4293265, 0x040c0000, 0x1aac0027, 0x2aa80080, - 0xce813265, 0x9ac00017, 0xd80002f1, 0x04080002, 0x08880001, 0xd8080250, 0xd8080258, 0xd8080230, - 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, 0xd8080278, 0xd8080280, 0xd8080228, - 0xd8000367, 0x9880fff3, 0x04080010, 0x08880001, 0xd80c0309, 0xd80c0319, 0x04cc0001, 0x9880fffc, - 0x7c408001, 0x88000000, 0xc00e0100, 0xd8400013, 0xd8400008, 0xccc130b5, 0x8000016e, 0xc4180032, - 0x29980008, 0xcd800013, 0x95800001, 0x7c40c001, 0x18d0003f, 0x24d4001f, 0x24d80001, 0x155c0001, - 0x05e80180, 0x9900000b, 0x202c003d, 0xcd800010, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x86800000, - 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0xc4200007, 0x0a200001, 0xce000010, 0x80001b70, - 0x7c40c001, 0x8c000190, 0xc410001b, 0xd8000032, 0xd8000031, 0x9900091a, 0x7c408001, 0x88000000, - 0x24d000ff, 0x05280196, 0x18d4fe04, 0x29540008, 0xcd400013, 0x86800000, 0x800001b4, 0x8000032b, - 0x80000350, 0x80000352, 0x8000035f, 0x80000701, 0x8000047c, 0x8000019f, 0x80000800, 0xc419325b, - 0x1d98001f, 0xcd81325b, 0x8c00003f, 0xc4140004, 0xd8400008, 0x04100002, 0x8c000043, 0x28cc0002, - 0xccc00050, 0xc43c0044, 0x27fc0003, 0x9bc00002, 0x97c00006, 0xc00c4000, 0xccc130b5, 0x8c000055, - 0xd8400013, 0xd88130b8, 0xcd400008, 0x90000000, 0xd8400008, 0xcd400013, 0x7d40c001, 0xd8400028, - 0xd8400029, 0xd9400036, 0xc4193256, 0xc41d3254, 0x15540008, 0xcd400009, 0xcd40005b, 0xcd40005e, - 0xcd40005d, 0xd840006d, 0xc421325a, 0xc42d3249, 0x11540015, 0x19a4003c, 0x1998003f, 0x1af0007d, - 0x11dc000b, 0x1264001f, 0x15dc000d, 0x7d65400a, 0x13300018, 0x1a38003f, 0x7dd5c00a, 0x7df1c00a, - 0xcd800045, 0xcdc00100, 0xc411326a, 0xc415326b, 0xc419326c, 0xc41d326d, 0xc425326e, 0xc4293279, - 0xce800077, 0xcd000056, 0xcd400057, 0xcd800058, 0xcdc00059, 0xc4193265, 0x259c8000, 0x99c00004, - 0xce40005a, 0x29988000, 0xcd813265, 0xc4113248, 0x2510000f, 0xcd000073, 0xc418000d, 0xc411326f, - 0x17300019, 0x97000009, 0x25140fff, 0x95400007, 0xd800003a, 0x8c001b6d, 0xc4153279, 0xcd400077, - 0xcd00005f, 0xd8000075, 0x26f00001, 0x15100010, 0x7d190004, 0xcd000035, 0x97000035, 0x1af07fe8, - 0xd8800013, 0xd8400010, 0xd8400008, 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, - 0x04300010, 0xdf430000, 0x7c434001, 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, - 0xdf030000, 0xd4412e40, 0xd8400013, 0xcc41c030, 0xcc41c031, 0xc43dc031, 0xccc00013, 0x04343000, - 0xc4113246, 0xc41d3245, 0xcf413267, 0x51100020, 0x7dd1c01a, 0xc4353267, 0x45dc0160, 0xc810001f, - 0x1b4c0057, 0x1b700213, 0x1b740199, 0x7f4f400a, 0x7f73400a, 0x55180020, 0x2198003f, 0xd1c00025, - 0xcf400024, 0xcd000026, 0xcd800026, 0xd8400027, 0x9bc00001, 0x248dfffe, 0xd8800013, 0xccc12e00, - 0x7c434001, 0x7c434001, 0x8c00142b, 0xc43c000e, 0x1af4007d, 0x2bfc0008, 0x33740003, 0x26d80001, - 0xcfc00013, 0x1ae8003e, 0x9680000c, 0xc4253277, 0x26680001, 0x96800009, 0x2a640002, 0xce413277, - 0xd8400013, 0xc4253348, 0xce413348, 0xc4253348, 0x96400001, 0xcfc00013, 0x9b400003, 0x958000d8, - 0x80000315, 0xc4253277, 0x04303000, 0x26680001, 0xcf013267, 0xc4193246, 0xc41d3245, 0xc4313267, - 0x96800041, 0x51980020, 0x1b342010, 0x7d9d801a, 0x1714000c, 0x25540800, 0x1b30c012, 0x459801b0, - 0x7d77400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0xd180001e, 0xd8400021, 0x04240010, 0x199c01e2, - 0x7e5e4002, 0x3e5c0004, 0x3e540002, 0xc428000f, 0x9a80ffff, 0x95c00006, 0xc80c0011, 0xc8140011, - 0x54d00020, 0x55580020, 0x80000282, 0x95400015, 0xc80c0011, 0x0a640002, 0x041c0001, 0x45980008, - 0x54d00020, 0x96400004, 0xc8140011, 0x45980004, 0x041c0000, 0xcf00001c, 0xd180001e, 0xd8400021, - 0xc428000f, 0x9a80ffff, 0x99c00003, 0xc8180011, 0x80000282, 0xc8140011, 0x55580020, 0x80000282, - 0x45980004, 0xc80c0011, 0xcf00001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8100011, - 0xc8140011, 0x55580020, 0xd8400013, 0xccc1334e, 0xcd01334f, 0xcd413350, 0xcd813351, 0xd881334d, - 0xcfc00013, 0xc4193273, 0xc41d3275, 0xc40d3271, 0xc4113270, 0xc4153274, 0x50cc0020, 0x7cd0c01a, - 0x7cdcc011, 0x05900008, 0xcd00006a, 0xcdc0006b, 0xc41d3272, 0x7d594002, 0x54d00020, 0xd8800013, - 0xccc12e23, 0xcd012e24, 0xcdc12e25, 0xcfc00013, 0xc4193246, 0xc41d3245, 0xc4313267, 0x15540002, - 0x51980020, 0x7d9d801a, 0xc81c001f, 0x1b340057, 0x1b280213, 0x1b300199, 0x45980198, 0x7f37000a, - 0x7f2b000a, 0x55e40020, 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0xcd40000d, - 0xcd40000a, 0xc40d3249, 0x20cc003c, 0xccc13249, 0xc4113274, 0xdd430000, 0xc01e0001, 0x29dc0002, - 0x04280000, 0xd8000036, 0xcc400078, 0xcc400078, 0x2d540002, 0x95400022, 0x078c0000, 0x07d40000, - 0x8c00120d, 0x8c001239, 0x8c001232, 0x04f80000, 0x057c0000, 0xcdc00013, 0xc414000d, 0xc41c0019, - 0x7dd5c005, 0x25dc0001, 0xd840007c, 0xd8400074, 0xd8400069, 0xc40c005e, 0x94c018a6, 0xd4412e22, - 0xd800007c, 0xc40c005e, 0x94c018a2, 0x95c00007, 0xc40c0019, 0x7cd4c005, 0x24cc0001, 0x94c00008, - 0x9680fffc, 0x800002e3, 0xc40c0057, 0x7cd0c002, 0x94c00003, 0x9680fffd, 0x800002e3, 0xd8000069, - 0xcfc00013, 0xcd013273, 0xcd013275, 0xd8000074, 0xc414005e, 0x9540188f, 0xcfc00013, 0xc40d3249, - 0xc013cfff, 0x7cd0c009, 0xccc13249, 0x9680000b, 0xc40c0077, 0x38d00001, 0x99000006, 0x04cc0002, - 0xdcc30000, 0xc40c005e, 0x94c01882, 0xd4400078, 0xd800000d, 0x80000304, 0x7c41c001, 0x7c41c001, - 0xd840002f, 0xc41c0015, 0x95c0ffff, 0xd8400030, 0xc41c0016, 0x95c0ffff, 0xd8000030, 0xc41c0016, - 0x99c0ffff, 0xd800002f, 0xc41c0015, 0x99c0ffff, 0xc81c001f, 0x49980198, 0x55e40020, 0x459801a0, - 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0x04302000, 0xcfc00013, 0xcf013267, - 0xc4313267, 0x96800004, 0x97000001, 0xd8000036, 0x80000329, 0xd8800013, 0xcc812e00, 0x04302000, - 0xcfc00013, 0xcf013267, 0xc4313267, 0x97000001, 0xc4193256, 0xc42d3249, 0x16ec001f, 0xd8000028, - 0xd800002b, 0x1998003e, 0xcec00031, 0xd8000036, 0xd8000010, 0x97800004, 0xd8400010, 0xce00000a, - 0x1a18003e, 0xcd800008, 0x90000000, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, - 0x7d43c001, 0xcd400013, 0xc4093249, 0x1888003e, 0x94800015, 0xd8400074, 0x8c000671, 0xcd400013, - 0x9a400006, 0xc419324c, 0x259c0001, 0x1598001f, 0x95c0000d, 0x9580000c, 0x99000003, 0xd8400036, - 0x04100001, 0xc40c0021, 0x14d80011, 0x24dc00ff, 0x31e00002, 0x31dc0003, 0x9580fff0, 0x9a000003, - 0x99c00002, 0xd9c00036, 0x94800004, 0xd8000074, 0xc418005e, 0x95801827, 0xcf800008, 0x90000000, - 0xd8800036, 0x90000000, 0xd8c00036, 0xc424000b, 0x32640002, 0x9a400004, 0xc4180014, 0x9580ffff, - 0xd840002f, 0xc40c0021, 0x14dc0011, 0x95c0fffe, 0xccc00037, 0x8c000190, 0x90000000, 0xd8400008, - 0xd800006d, 0xc41d3246, 0xc4193245, 0x51dc0020, 0x7d9d801a, 0xd8400028, 0xd8400029, 0xc420000b, - 0x32200002, 0x9a0000ad, 0x04200032, 0xd9000010, 0xde030000, 0xd8400033, 0x04080000, 0xc43c0009, - 0x27fc0002, 0x97c0fffe, 0xc42c0015, 0x96c0ffff, 0xd800002e, 0xc42d3249, 0x1af4003e, 0x9740004d, - 0xc428000d, 0xc4080060, 0x7ca88005, 0x24880001, 0x7f4b4009, 0x97400046, 0xc4313274, 0xc4100057, - 0x7d33400c, 0x97400009, 0x28240100, 0x7e6a4004, 0xce400079, 0x1eecffdd, 0xcec13249, 0xcf013273, - 0xcf013275, 0x800003c3, 0xc429326f, 0x1aa80030, 0x96800006, 0x28240001, 0xc428000d, 0x06a80008, - 0x7e6a8004, 0xce800035, 0xc41d3272, 0x25cc0001, 0x10cc0004, 0x19e80042, 0x25dc0006, 0x11dc0001, - 0x7e8e800a, 0x7de9c00a, 0xc40d3271, 0xc4293270, 0x50cc0020, 0x7ce8c01a, 0x7cd30011, 0x11e80007, - 0x2aa80000, 0xce80001c, 0xd300001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc4300011, 0x1b30003f, - 0x33300000, 0xc4240059, 0x1660001f, 0x7e320009, 0xc0328000, 0x7e72400a, 0x0430000c, 0x9a000002, - 0x04300008, 0xc02ac000, 0x7d310002, 0x17300002, 0x2aa87600, 0x7cd0c011, 0xcdc00024, 0xd0c00025, - 0xce800026, 0x04280222, 0xce800026, 0x96000002, 0xce400026, 0xd8400027, 0xc4280058, 0x22ec003d, - 0xcec13249, 0xcd013273, 0xce813275, 0xd800007b, 0xc8380018, 0x57b00020, 0x04343108, 0xc429325d, - 0x040c3000, 0x13740008, 0x2374007e, 0x32a80003, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, - 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0x94800003, 0xd4400078, 0x800003e7, 0x04200022, 0xde030000, - 0xccc00024, 0xd1800025, 0xcf400026, 0xd4400026, 0xd8400027, 0x04200010, 0xde030000, 0xccc00024, - 0x45980104, 0xd1800025, 0xd4400026, 0xcf800026, 0xcf000026, 0xd8400027, 0x49980104, 0x9a80000a, - 0xc81c001f, 0x45980168, 0x55e00020, 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, - 0x800003f2, 0x8c000448, 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xc40d3249, - 0x18cc003e, 0xd8400030, 0xc42c0016, 0x96c0ffff, 0xd8000030, 0xc42c0016, 0x9ac0ffff, 0xd800002f, - 0xc42c0015, 0x9ac0ffff, 0xd8400034, 0xc4300025, 0xc4340024, 0xc4380081, 0xcf813279, 0xcf41326e, - 0xcf01326d, 0x94c0000d, 0x254c0700, 0xc424001e, 0x10cc0010, 0x1a641fe8, 0x28cc0726, 0x2a640200, - 0xd8400013, 0xccc1237b, 0x2264003f, 0xcd400013, 0xd8813260, 0xce41325b, 0xc4240033, 0xc4280034, - 0xd9000036, 0xd8000010, 0x8c001427, 0x96400006, 0xde430000, 0xce40000c, 0xc40c005e, 0x94c01755, - 0xd4400078, 0x9680000a, 0xce80000a, 0x06a80002, 0xd8400010, 0xde830000, 0xce80000d, 0xc40c005e, - 0x94c0174c, 0xd4400078, 0xd8000010, 0x8c00142b, 0xc4393265, 0x2bb80040, 0xd8400032, 0xcf813265, - 0xc4200012, 0x9a00ffff, 0xc4100044, 0x19180024, 0xc8100072, 0x551c003f, 0x99c00003, 0x95800010, - 0x8000043d, 0xc00c8000, 0xd840006c, 0x28200000, 0x8000043f, 0xc00c4000, 0x282000f0, 0xcd400013, - 0xd8400008, 0xc4113255, 0xcd01324f, 0xd8400013, 0xd88130b8, 0xccc130b5, 0xce000053, 0x90000000, - 0x195c00e8, 0xc4100004, 0x2555fff0, 0xc0360001, 0x042c0000, 0x29540001, 0xd8400008, 0x04240000, - 0x04280004, 0xc420000b, 0x32200002, 0x9a000009, 0xcd400013, 0xcec1c200, 0xc5e124dc, 0x0aa80001, - 0x7ef6c001, 0x7e624001, 0x96000001, 0x9a80fff9, 0xc02ee000, 0xcd400013, 0x2555fff0, 0xcec1c200, - 0x29540008, 0xc81c001f, 0xcd400013, 0x55e00020, 0xc42d3255, 0xc4353259, 0xd8013260, 0x45980158, - 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, 0x49980158, 0x45980170, 0xc4200012, - 0x16200010, 0x9a00fffe, 0xccc00024, 0xd1800025, 0xc429324f, 0xce400026, 0xce800026, 0xcec00026, - 0xcf400026, 0xd8400027, 0xcd000008, 0x90000000, 0xc40d325b, 0x7d43c001, 0x195400e8, 0x1154000a, - 0x18dc00e8, 0x05e80488, 0x18d0006c, 0x18f807f0, 0x18e40077, 0x18ec0199, 0x7e6e400a, 0x86800000, - 0x8000048e, 0x80000494, 0x800004de, 0x80000685, 0x80000686, 0x800006ac, 0x1ccc001f, 0xccc1325b, - 0xc411325d, 0x251001ef, 0xcd01325d, 0x90000000, 0xc4293254, 0x1264000a, 0xc4300004, 0x7d79400a, - 0x7e7a400a, 0x52a8001e, 0x15180001, 0x7d69401a, 0x202c007d, 0xcec1325b, 0x95000008, 0x95800028, - 0xc42d3267, 0xc4193246, 0xc41d3245, 0x1aec0028, 0xc40d325c, 0x800004cc, 0xc42d3256, 0xc419324e, - 0x26e8003f, 0x1aec003e, 0x12f4000e, 0xc41d324d, 0xc40d324f, 0x7d75401a, 0x04100002, 0x7d290004, - 0x7f8f4001, 0x7f52800f, 0x51980020, 0x7d9d801a, 0x50e00002, 0x51980008, 0x9a800002, 0x800004d1, - 0x7d0dc002, 0x6665fc00, 0x7e5e401a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, - 0xce400002, 0x7f534002, 0x6665fc00, 0x7e76401a, 0xd1800002, 0xce400002, 0x800004d7, 0xc42d325a, - 0xc4193258, 0x1aec003e, 0xc41d3257, 0xc4213259, 0x12f4000e, 0x7d75401a, 0x51980020, 0x52200002, - 0x7d9d801a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, 0xce400002, 0x202c003d, - 0xcf000008, 0xcfc00013, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x90000000, 0xc4193260, 0x259c0007, - 0x15980004, 0x05e804e3, 0x86800000, 0x800004e7, 0x800004f0, 0x80000505, 0x8000016a, 0xc4380004, - 0xcfc00013, 0xd8400008, 0xc435325d, 0xd801325b, 0x277401ef, 0xcf41325d, 0xcf800008, 0x90000000, - 0xc4380004, 0xd8400008, 0x8c000671, 0x9640fff4, 0x17e00008, 0xc418000d, 0xce000009, 0xd84131db, - 0xcf800008, 0xcd800009, 0xc430001e, 0xcfc00013, 0xc42d325b, 0x1b301ff8, 0x2b300400, 0x2330003f, - 0x26edf000, 0x7ef2c00a, 0xd8413260, 0xcec1325b, 0x90000000, 0x05a80507, 0x86800000, 0x8000050c, - 0x80000528, 0x8000057d, 0x800005c2, 0x800005f3, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, - 0x9a400012, 0x1bd400e8, 0xc42c004a, 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000c, 0xc4100019, - 0x7d150005, 0x25100001, 0x99000008, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, - 0xd801326f, 0x80000624, 0x04240012, 0x1be00fe4, 0xce413260, 0xce000066, 0xcf800008, 0x90000000, - 0xd8400068, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, 0x9a400013, 0x1bd400e8, 0xc42c004a, - 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000d, 0xc4100019, 0x7d150005, 0x25100001, 0x99000009, - 0xd8400067, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, 0xd801326f, 0x80000624, - 0x1bd400e8, 0xc42c0060, 0x7ed6c005, 0x26ec0001, 0xc4113271, 0xc4153270, 0xc4193272, 0xc41d3273, - 0x04280022, 0x51100020, 0x7d51401a, 0xc4113274, 0xc4213275, 0xc4253276, 0xc4313248, 0xd1400061, - 0x2730000f, 0x13300010, 0x7db1800a, 0xcd800060, 0x96c00002, 0x05dc0008, 0xcdc00062, 0x042c3000, - 0xcd000063, 0xce000064, 0xce400065, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xce813260, - 0x52ec0020, 0x7ef2c01a, 0xc820001f, 0x1b700057, 0x1b680213, 0x1b740199, 0x46ec0188, 0x7f73400a, - 0x7f6b400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, - 0xc418000d, 0x17e00008, 0xce000009, 0xcec13267, 0xc42d3267, 0x26e01000, 0x9a00fffe, 0xd8400013, - 0xd9c131fc, 0xcd800009, 0xcf800008, 0x96c00001, 0x90000000, 0xc4380004, 0xd8400008, 0xc4113277, - 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0x29dc0001, 0x25140001, 0x191807e4, - 0x192007ec, 0x95400004, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x9580000e, 0x09980001, 0x041c0001, - 0x95800005, 0x09980001, 0x51dc0001, 0x69dc0001, 0x9980fffd, 0x7de20014, 0x561c0020, 0xd8400013, - 0xce013344, 0xcdc13345, 0xcfc00013, 0x95400022, 0x042c3000, 0xcec13267, 0xc42d3246, 0xc4313245, - 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, 0xc419334e, 0xc41d334f, 0xc4213350, - 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, 0x1b740199, 0x46ec01b0, 0x7f6b400a, - 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, 0xcdc00026, 0xce000026, 0xce400026, - 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, 0x04280032, 0xce813260, 0xd8800068, - 0xcf800008, 0x90000000, 0xc4380004, 0xd8400008, 0x2010007d, 0xcd01325b, 0xc411325b, 0x1910003e, - 0x9500fffe, 0x04100040, 0xcd00001b, 0xd8400021, 0xc410000f, 0x9900ffff, 0x04100060, 0xcd00001b, - 0xd8400021, 0xc410000f, 0x9900ffff, 0xcfc00013, 0x2010003d, 0xcd01325b, 0xc4113277, 0x25140001, - 0x191807e4, 0x9540000b, 0x2511fffd, 0xcd013277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, - 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x95800005, 0xd8400013, 0xd8013344, 0xd8013345, - 0xcfc00013, 0xc4180050, 0xc41c0052, 0x04280042, 0xcd813273, 0xcdc13275, 0xce813260, 0xd9000068, - 0xd8400067, 0xcf800008, 0x90000000, 0x07d40000, 0x8c00120d, 0x8c00124f, 0x8c001232, 0x057c0000, - 0x042c3000, 0xc4380004, 0xcfc00013, 0xd8400008, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, - 0x52ec0020, 0x7ef2c01a, 0x1b680057, 0x1b700213, 0x1b740199, 0xc820001f, 0x46ec0190, 0x7f6b400a, - 0x7f73400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, - 0xcfc00013, 0xcec13267, 0xc4153249, 0x2154003d, 0xc41c0019, 0x1bd800e8, 0x7dd9c005, 0x25dc0001, - 0xc42c004a, 0xcd80005e, 0xc420004d, 0xcec0005e, 0x11dc0010, 0x7e1e000a, 0xcd413249, 0xce01326f, - 0x28340001, 0x05980008, 0x7f598004, 0xcd800035, 0x1be800e8, 0xc42c004a, 0xce80005e, 0xd801327a, - 0xd800005f, 0xd8000075, 0xd800007f, 0xc424004c, 0xce41326e, 0xcec0005e, 0x28240100, 0x7e6a4004, - 0xce400079, 0xc435325d, 0x277401ef, 0x04240020, 0xce41325e, 0xd801325b, 0xd8013260, 0xcf41325d, - 0xda000068, 0xcf800008, 0x90000000, 0xc4113277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, - 0x11dc0008, 0x29dc0001, 0x25140001, 0x9540002d, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x042c3000, - 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, - 0xc419334e, 0xc41d334f, 0xc4213350, 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, - 0x1b740199, 0x46ec01b0, 0x7f6b400a, 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, - 0xcdc00026, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, - 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, - 0x90000000, 0xc430000b, 0x33300002, 0x04240000, 0x9b000010, 0x1be000e8, 0x042c0000, 0xc0360001, - 0x04280004, 0xd8400013, 0xcec1c200, 0xc63124dc, 0x0aa80001, 0x7ef6c001, 0x7e724001, 0x97000001, - 0x9a80fff9, 0xc02ee000, 0xd8400013, 0xcec1c200, 0x90000000, 0x90000000, 0xc4253260, 0x7fc14001, - 0xc40d3249, 0x18cc003e, 0x98c00005, 0x194c1c03, 0xccc0003b, 0xc40c002d, 0x80000697, 0xc420004a, - 0x194c00e8, 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x98c00003, - 0x8c0007e0, 0x95c00008, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, 0xcf01325b, - 0x90000000, 0xcd400013, 0xd801325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x25100007, 0x31100005, - 0x9900008e, 0xc40c0007, 0xd9000010, 0x8000075e, 0x202c007d, 0xcec1325b, 0xc4293265, 0xc4353254, - 0x26a9feff, 0xc4380004, 0xd8400008, 0x1374000b, 0xc40c000d, 0xd8000009, 0x1774000d, 0xd8400013, - 0xc41d30b8, 0xcfc00013, 0x95c00008, 0xc411325d, 0xd801325b, 0xccc00009, 0xcf800008, 0x251001ef, - 0xcd01325d, 0x90000000, 0xce813265, 0xcf400100, 0xc00ac006, 0xc00e0000, 0x28880700, 0x28cc0014, - 0x8c0006de, 0x14cc0010, 0x30d4000f, 0x04cc0001, 0x10cc0010, 0x28cc0014, 0x99400009, 0xd8400013, - 0xc41530b8, 0xcfc00013, 0xc4193265, 0x19980028, 0x99400003, 0x99800002, 0x800006c8, 0xcfc00013, - 0xc411325d, 0xd801325b, 0xcf800008, 0x251001ef, 0xcd01325d, 0x90000000, 0x15600008, 0xce000009, - 0xc8380023, 0xc4180081, 0x11a00002, 0x7fa38011, 0xc4100026, 0x05980008, 0x7d1a0002, 0x282c2002, - 0x3e280008, 0xcec00013, 0xc4300027, 0x042c0008, 0xd3800025, 0xcf000024, 0x202400d0, 0x7ca48001, - 0xcc800026, 0xccc00026, 0x28240006, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800004, 0x32280000, - 0x9a800002, 0x9a000000, 0xd8400027, 0x24d8003f, 0xd840003c, 0xcec0003a, 0xd8800013, 0xcd81a2a4, - 0x90000000, 0xc41d325d, 0x25dc0007, 0xc40d3249, 0x18cc003e, 0x94c0000a, 0xc420004a, 0x194c00e8, - 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x80000712, 0x194c1c03, - 0xccc0003b, 0xc40c002d, 0x05e80714, 0x86800000, 0x8000071c, 0x80000720, 0x80000747, 0x8000071d, - 0x800007c4, 0x80000732, 0x80000745, 0x80000744, 0x90000000, 0x98c00006, 0x8000072e, 0x90000000, - 0x98c00003, 0x8c0007e0, 0x95c0000c, 0xcd400013, 0xc4253265, 0x2a64008c, 0xce413265, 0xc430001e, - 0x1b301fe8, 0x2b300400, 0x2330003f, 0xd8013260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, - 0x04240000, 0x8000075e, 0x98c0fff1, 0x8c0007e0, 0x95c00002, 0x80000723, 0xcd400013, 0xc41f02f1, - 0x95c00004, 0xd8013247, 0xd801325d, 0x80000743, 0xd8813247, 0xd801325d, 0xc4100004, 0xd8400008, - 0xd8400013, 0xd88130b8, 0xcd000008, 0x90000000, 0x04100001, 0x98c0ffde, 0x8000072e, 0x98c00003, - 0x8c0007e0, 0x95c00012, 0xc4340004, 0xd8400008, 0x15600008, 0xc418000d, 0xce000009, 0xd8400013, - 0xd84131db, 0xcf400008, 0xcd800009, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, - 0xd8413260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, 0x04240000, 0xcd400013, 0x041c3000, - 0xcdc13267, 0xc41d3267, 0xc41d3265, 0x25dc8000, 0x95c00007, 0xc41c004a, 0x195800e8, 0xcd80005e, - 0xc418004c, 0xcd81326e, 0xcdc0005e, 0xc41d3265, 0x25dd7fff, 0xcdc13265, 0xc41d3246, 0xc4193245, - 0xc42d3267, 0x51e00020, 0x7e1a001a, 0x46200200, 0x04283247, 0x04300033, 0x1af80057, 0x1af40213, - 0x042c000c, 0x7f7b400a, 0x7f6f400a, 0xcf400024, 0xd2000025, 0xcd800026, 0xcdc00026, 0xc6990000, - 0x329c325d, 0x99c00008, 0x329c3269, 0x99c00006, 0x329c3267, 0x95c00005, 0xc01defff, 0x7d9d8009, - 0x8000078a, 0x25980000, 0x0b300001, 0x06a80001, 0xcd800026, 0x9b00fff2, 0xd8400027, 0xc43c0012, - 0x9bc0ffff, 0xcd400013, 0xd801325b, 0xc431325a, 0xc03e7ff0, 0x7f3f0009, 0xcf01325a, 0xc4313249, - 0x1f30001f, 0xcf013249, 0xc03e4000, 0xcfc13254, 0xcd400013, 0xd8013254, 0xc431325d, 0xd801324f, - 0xd8013255, 0xd8013247, 0xd801325d, 0x1b300028, 0x8c00120d, 0x8c001219, 0x8c001232, 0xc4380004, - 0xd8400008, 0xd8400013, 0x9900000d, 0xd88130b8, 0x9700000b, 0xc43d30b5, 0x1bf0003a, 0x9b000b80, - 0x203c003a, 0xc430000e, 0x27300700, 0x13300014, 0x2b300001, 0xcf0130b7, 0xcfc130b5, 0x46200008, - 0xcf400024, 0xd2000025, 0xd8000026, 0xd8400027, 0x043c2000, 0xcd400013, 0xcfc13267, 0xc43d3267, - 0x9bc00001, 0xccc00010, 0xcf800008, 0x90000000, 0xc4080007, 0xd9000010, 0xc4193260, 0x259c0003, - 0x31dc0003, 0x95c00014, 0x040c3000, 0xd8400008, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, - 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0xc4193246, 0xc41d3245, 0x51980020, 0x7d9d801a, 0x8c000448, - 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xcc800010, 0xd801325d, 0x90000000, - 0xc418000b, 0x31980002, 0x041c0000, 0x9980001c, 0x19580066, 0x15600008, 0x040c0000, 0xc0120001, - 0x11980003, 0x04240004, 0x7da18001, 0xc4200007, 0xc4340004, 0xd9000010, 0xd8400008, 0xd8400013, - 0xccc1c200, 0xc41d24db, 0x7cd0c001, 0x0a640001, 0x7dd9c005, 0x25dc0001, 0x99c00002, 0x9a40fff8, - 0xc418005e, 0x9580137b, 0xc00ee000, 0xd8400013, 0xccc1c200, 0xce000010, 0xcf400008, 0x90000000, - 0xd840004f, 0xc4113269, 0x19080070, 0x190c00e8, 0x2510003f, 0x2518000f, 0xcd813268, 0x05a80809, - 0x86800000, 0x8000080e, 0x8000080f, 0x80000898, 0x80000946, 0x800009e1, 0x80000a5a, 0x04a80811, - 0x86800000, 0x80000815, 0x80000834, 0x8000085e, 0x8000085e, 0x04341001, 0xcf400013, 0xc4380004, - 0xd8400008, 0xc42d3045, 0xcec1c091, 0x31300021, 0x9700000b, 0xd84002f1, 0xd8400013, 0xc43130b8, - 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, 0xcf800008, 0x9b000241, 0x8000084a, 0xcf400013, - 0xd8400008, 0xc43130b6, 0x9b000003, 0xc02f0001, 0xcec130b6, 0xc4252087, 0x5668001a, 0x26a80005, - 0x9a80fffd, 0xcf400013, 0xd80130b6, 0x8000084a, 0xc4380004, 0xd8400008, 0x04341001, 0xcf400013, - 0xc431ecaa, 0x27300080, 0x9b000010, 0xc02e0001, 0xcec130b6, 0xcf400013, 0xd80130b6, 0x31300021, - 0x9700000a, 0xd84002f1, 0xd8400013, 0xc43130b8, 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, - 0xcf800008, 0x9b00021d, 0xdd410000, 0x040c0005, 0xd84802e9, 0x8c001a41, 0xc43b02f1, 0x9b800006, - 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0xcf800008, 0xcec80278, 0x56f00020, 0xcf080280, - 0x8c001608, 0xdc140000, 0xcd400013, 0xd8813247, 0xd80802e9, 0x8000085e, 0xcd400013, 0x31100011, - 0x950001fa, 0xc02e0001, 0x2aec0008, 0xc01c0020, 0xc0180001, 0xc00c0007, 0x11a40006, 0x7de6000a, - 0x10e40008, 0x7e26000a, 0x7e2e000a, 0xce000013, 0xc4113254, 0x1d10ffdf, 0x2110003e, 0xcd013254, - 0xd801324f, 0xd8013255, 0x1d10ff9e, 0xcd013254, 0xd8013247, 0xd801325d, 0xd801325e, 0xc0245301, - 0xce413249, 0xd801325f, 0xc425326c, 0xc0121fff, 0x29108eff, 0x7e524009, 0xce41326c, 0xc425325a, - 0xc0127ff0, 0x7e524009, 0xce41325a, 0xc425325b, 0xc0131fff, 0x7e524009, 0xce41325b, 0xd801326d, - 0xd801326e, 0xd8013279, 0x94c00003, 0x08cc0001, 0x80000866, 0xc00c0007, 0x95800003, 0x09980001, - 0x80000866, 0xc0100010, 0x7dd2400c, 0x9a400004, 0xc0180003, 0x7dd1c002, 0x80000866, 0x80000a5a, - 0x04a8089a, 0x86800000, 0x8000089e, 0x800008fa, 0x80000945, 0x80000945, 0x31300022, 0x97000007, - 0xc4380004, 0xd8400008, 0xd8400013, 0xc43130b8, 0x27300001, 0xcf800008, 0xcd400013, 0x04183000, - 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, - 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, - 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000036, 0x45980008, 0xd180001e, - 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002f, 0xc43c0004, 0xd8400008, 0xd8400013, - 0x13b80001, 0xc79d3300, 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, - 0x964012a4, 0x7c028009, 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x800008d2, - 0xc4180006, 0x9980ffff, 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, - 0x9980fffd, 0xc02620c0, 0xce41c078, 0xce81c080, 0xcc01c081, 0xcf01c082, 0x57240020, 0xce41c083, - 0xc0260400, 0x7e6e400a, 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x800008d2, 0xc4180006, 0x9980ffff, - 0xcdf93300, 0xce393301, 0xcfc00008, 0xcd400013, 0xc43c0004, 0xd8400008, 0x04182000, 0xcd813267, - 0xcfc00008, 0x80000903, 0x31240022, 0x96400008, 0x04100001, 0xc4380004, 0xd8400008, 0xd8400013, - 0xc43130b8, 0x27300001, 0xcf800008, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x7ec30011, - 0x32f80000, 0x9b800011, 0x043c0020, 0x04280000, 0x67180001, 0x0bfc0001, 0x57300001, 0x95800006, - 0x8c001628, 0x9a400003, 0xd981325d, 0x80000915, 0xd9c1325d, 0x06a80001, 0x9bc0fff6, 0x7f818001, - 0x8c001606, 0x7d838001, 0x94800010, 0xcd400013, 0xc41d3259, 0xc421325a, 0x16240014, 0x12640014, - 0x1a2801f0, 0x12a80010, 0x2620ffff, 0x7e2a000a, 0x7de1c001, 0x7e5e400a, 0x9b800002, 0x2264003f, - 0xce41325a, 0xd8013259, 0xc40c0007, 0xd9000010, 0x8c00075e, 0xc4af0228, 0x043c0000, 0x66d80001, - 0x95800010, 0x04300002, 0x1330000d, 0x13f40014, 0x7f73400a, 0xcf400013, 0x04380040, 0xcf80001b, - 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, - 0x07fc0001, 0x56ec0001, 0x33e80010, 0x9680ffec, 0x80000a5a, 0x80000a5a, 0x04a80948, 0x86800000, - 0x8000094c, 0x8000099b, 0x800009e0, 0x800009e0, 0xc43c0004, 0xd8400008, 0xcd400013, 0x04183000, - 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, - 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, - 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000033, 0x45980008, 0xd180001e, - 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002c, 0xd8400013, 0x13b80001, 0xc79d3300, - 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, 0x964011fe, 0x7c028009, - 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x80000978, 0xc4180006, 0x9980ffff, - 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, 0x9980fffd, 0xc0260010, - 0xce41c078, 0xcf01c080, 0x57240020, 0xce41c081, 0xce81c082, 0xcc01c083, 0xc0260800, 0x7e6e400a, - 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x80000978, 0xc4180006, 0x9980ffff, 0xcdf93300, 0xce393301, - 0x04182000, 0xcd813267, 0xcfc00008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, 0x7dda801a, - 0x7d41c001, 0x7e838011, 0xd84802e9, 0x8c001802, 0x469c0390, 0xc4313267, 0x04183000, 0xcd813267, - 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, - 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, 0x45dc0004, 0xd1c0001e, - 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4240011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, - 0x9980ffff, 0xc4280011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc42c0011, - 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4300011, 0x45dc0004, 0xd1c0001e, - 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4340011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, - 0x9980ffff, 0xc4380011, 0xcd400013, 0x04182000, 0xcd813267, 0x043c0001, 0x8c0014df, 0x80000a5a, - 0x80000a5a, 0x31280014, 0xce8802ef, 0x9a800062, 0x31280034, 0x9a800060, 0x04a809e8, 0x86800000, - 0x800009ec, 0x80000a45, 0x80000a59, 0x80000a59, 0xcd400013, 0xc4113246, 0xc4193245, 0x51100020, - 0x7d91801a, 0x45980400, 0xc4b30258, 0xc4a70250, 0x53300020, 0x7e72401a, 0xc4313267, 0x1b342010, - 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0x042c0020, - 0x66740001, 0x97400041, 0xcd400013, 0x04383000, 0xcf813267, 0xc4393267, 0x9b800001, 0xd180001e, - 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4300011, 0x1b38007e, 0x33b40003, 0x9b400003, 0x4598001c, - 0x9740002f, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc40c0011, 0x45980004, - 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x45980004, 0xd180001e, 0xd8400021, - 0xc438000f, 0x9b80ffff, 0xc4340011, 0xcf4002eb, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, - 0x9b80ffff, 0xc4340011, 0xcf4002ec, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, - 0xc4340011, 0xcf4002ed, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4340011, - 0xcf4002ee, 0x45980004, 0xcd400013, 0x04382000, 0xcf813267, 0xd84802e9, 0x8c001715, 0xcd400013, - 0x04382000, 0xcf813267, 0x56640001, 0x0aec0001, 0x9ac0ffbc, 0xc4380004, 0xd8400008, 0x04341001, - 0xcf400013, 0x94800005, 0xc431ecaa, 0x27300080, 0x97000002, 0x80000a55, 0xc43130b6, 0x233c0032, - 0xcfc130b6, 0xcf400013, 0xcf0130b6, 0xc49302ef, 0x99000003, 0xcd400013, 0xd8413247, 0xcf800008, - 0x80000a5a, 0x80000a5a, 0xcd400013, 0x04180001, 0x5198001f, 0xcd813268, 0xc4193269, 0x2598000f, - 0x9980fffe, 0xd80002f1, 0xcd400013, 0xd8013268, 0xd800004f, 0x90000000, 0xcd400013, 0x04380001, - 0x53b8001f, 0x7db9801a, 0xcd813268, 0x80000a5e, 0xd8400029, 0xc40c005e, 0x94c01106, 0xd8800013, - 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xd8400029, 0xc40c005e, 0x94c010fd, - 0x7c40c001, 0x50640020, 0x7ce4c01a, 0xd0c00072, 0xc80c0072, 0x58e801fc, 0x12a80009, 0x2aa80000, - 0xd0c0001e, 0xce80001c, 0xd8400021, 0xc424000f, 0x9a40ffff, 0x04240010, 0x18dc01e2, 0x7e5e4002, - 0x3e5c0003, 0x3e540002, 0x95c00006, 0xc8180011, 0xc8100011, 0xc8100011, 0x55140020, 0x80000aa2, - 0x9540000a, 0xc8180011, 0x44cc0008, 0x55900020, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, - 0xc4140011, 0x80000aa2, 0x44cc0004, 0xc4180011, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, - 0xc8100011, 0x55140020, 0xd8800013, 0xcd812e01, 0xcd012e02, 0xcd412e03, 0xcc412e00, 0xc428000e, - 0x2aa80008, 0xce800013, 0xc4253249, 0x2264003f, 0xce413249, 0xce800013, 0xc4253249, 0x96400001, - 0xd800002a, 0xc410001a, 0xc40c0021, 0xc4140028, 0x95000005, 0x1e64001f, 0xce800013, 0xce413249, - 0x80001b70, 0x14d00010, 0xc4180030, 0xc41c0007, 0x99000004, 0x99400009, 0x9980000c, 0x80000ab1, - 0xccc00037, 0x8c000190, 0xc420001c, 0xd8000032, 0x9a0010ac, 0x80000aa7, 0xd880003f, 0x95c00002, - 0xd8c0003f, 0x80001082, 0xd8800040, 0x95c00002, 0xd8c00040, 0x800010de, 0xc010ffff, 0x18d403f7, - 0x7d0cc009, 0xc41b0367, 0x7d958004, 0x7d85800a, 0xdc1e0000, 0x90000000, 0xc424000b, 0x32640002, - 0x7c40c001, 0x18d001fc, 0x05280adc, 0x86800000, 0x80000af1, 0x80000adf, 0x80000ae7, 0x8c000ace, - 0xd8c00013, 0x96400002, 0xd8400013, 0xcd8d2000, 0x99c00010, 0x7c408001, 0x88000000, 0x18d803f7, - 0xc010ffff, 0x7d0cc009, 0x04140000, 0x11940014, 0x29544001, 0x9a400002, 0x29544003, 0xcd400013, - 0x80000af4, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44d2000, 0x7c408001, 0x88000000, 0xc424000b, - 0x32640002, 0x7c40c001, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44dc000, 0x7c408001, 0x88000000, - 0x7c40c001, 0x18d0003c, 0x95000006, 0x8c000ace, 0xd8800013, 0xcd8d2c00, 0x99c00003, 0x80000b0a, - 0xd8800013, 0xd44d2c00, 0x7c408001, 0x88000000, 0x7c40c001, 0x28148004, 0x24d800ff, 0xccc00019, - 0xcd400013, 0xd4593240, 0x7c408001, 0x88000000, 0xd8400029, 0xc40c005e, 0x94c0105e, 0x7c410001, - 0x50540020, 0x7c418001, 0x2198003f, 0x199c0034, 0xc40c0007, 0x95c00028, 0xc428000e, 0x2aa80008, - 0xce800013, 0xc42d324f, 0xc4313255, 0x7ef3400c, 0x9b400021, 0xd800002a, 0x80001b70, 0xc40c0007, - 0x14e80001, 0x9a8000af, 0xd9000010, 0x041c0002, 0x042c01c8, 0x8c000d61, 0xccc00010, 0xd8400029, - 0xc40c005e, 0x94c01043, 0x7c410001, 0x50540020, 0x7c418001, 0x18a01fe8, 0x3620005c, 0x9a00000e, - 0x2464003f, 0xd8400013, 0xc6290ce7, 0x16ac001f, 0x96c00004, 0x26ac003f, 0x7ee6c00d, 0x96c00005, - 0x06200001, 0x2620000f, 0x9a00fff8, 0x8000016a, 0xce000367, 0xc424005e, 0x9640102e, 0xc428000e, - 0x199c0037, 0x19a00035, 0x2aa80008, 0xce800013, 0x95c0005d, 0xd800002a, 0xc42d3256, 0xc431325a, - 0x2330003f, 0x16f8001f, 0x9780000d, 0xc4253248, 0xc035f0ff, 0x7e764009, 0x19b401f8, 0x13740008, - 0x7e76400a, 0xce800013, 0xce413248, 0xcf01325a, 0xce800013, 0xc431325a, 0x97000001, 0x7d15001a, - 0xd1000072, 0xc8100072, 0x55140020, 0x199c0034, 0xd8400010, 0xd8400029, 0x9b800004, 0x1ae4003e, - 0xce400008, 0x80000b7c, 0xc4353254, 0x16a80008, 0x1aec003c, 0x19a4003f, 0x12a80015, 0x12ec001f, - 0x1374000b, 0x7eae800a, 0xc02e4000, 0x1774000d, 0x7eae800a, 0xce400008, 0x7f6b400a, 0x95c00005, - 0xc43d3248, 0x1bfc01e8, 0x13fc0018, 0x7dbd800a, 0x1d98ff15, 0x592c00fc, 0xcd80000a, 0x12e00016, - 0x7da1800a, 0x592c007e, 0x12e00015, 0x7da1800a, 0xd1000001, 0xcd800001, 0x11a0000c, 0x1264001e, - 0x1620000c, 0x7e26000a, 0x7e32000a, 0x12e4001b, 0x7e26000a, 0x5924007e, 0x12640017, 0x7e26000a, - 0x19a4003c, 0x12640018, 0x7e26000a, 0xd800002a, 0xce01325a, 0xcd013257, 0xcd413258, 0xc429325a, - 0xc40c005e, 0x94c00fdb, 0x96800001, 0x95c00003, 0x7c40c001, 0x7c410001, 0x9780f5ca, 0xcf400100, - 0xc40c0007, 0xd9000010, 0x8c00120d, 0x8c001219, 0x8c001232, 0xccc00010, 0x8c001b6d, 0x7c408001, - 0x88000000, 0xc42d324e, 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x52ec0008, - 0x07740003, 0x04240002, 0x269c003f, 0x7e5e4004, 0x7f67000f, 0x97000003, 0x7f674002, 0x0b740001, - 0x53740002, 0x7ef6c011, 0x1ab42010, 0x1ab8c006, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f7b400a, - 0x7f6b400a, 0xcf40001c, 0xd2c0001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4180011, 0x9a000003, - 0x8c000bec, 0x80000b47, 0xc42c001d, 0xc4313256, 0x1b34060b, 0x1b300077, 0x7f370009, 0x13300017, - 0x04340100, 0x26ec00ff, 0xc03a8004, 0x7ef6c00a, 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, - 0xc40c0032, 0xc410001d, 0x28cc0008, 0xccc00013, 0xc415325b, 0x7c418001, 0x7c418001, 0x18580037, - 0x251000ff, 0xc421325d, 0x262001ef, 0xce01325d, 0x99800004, 0x7d15400a, 0xcd41325b, 0x80000168, - 0x1d54001f, 0xcd41325b, 0x7c408001, 0x88000000, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, - 0x7eae800a, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0xcd280200, 0xcd680208, - 0xcda80210, 0x9b00000c, 0x9b400014, 0x9b800017, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, - 0x7eae800a, 0xc6930200, 0xc6970208, 0xc69b0210, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, - 0x8c000190, 0xd8000032, 0x90000000, 0xd8000028, 0xd800002b, 0x80000168, 0xd900003f, 0x97c00002, - 0xd940003f, 0x80001082, 0xd9000040, 0x97c00002, 0xd9400040, 0x800010de, 0xc40c0021, 0x14fc0011, - 0x24f800ff, 0x33b80001, 0x97c0fffc, 0x9b800007, 0xccc00037, 0x8c000190, 0xd8000032, 0xd8000028, - 0xd800002b, 0x80001b70, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, 0x04140000, - 0xc418000e, 0x29980008, 0x7d83c001, 0xcd800013, 0xc4093249, 0x1888003e, 0x94800020, 0xd8400074, - 0x8c000671, 0x9a400009, 0xc418000e, 0x29980008, 0xcd800013, 0xc419324c, 0x259c0001, 0x1598001f, - 0x95c00016, 0x95800015, 0x99000003, 0xd8400036, 0x04100001, 0xc40c0021, 0x14d80011, 0x24e000ff, - 0x321c0002, 0x32200001, 0x9580ffee, 0x99c00014, 0x96000004, 0xccc00037, 0x04140001, 0x80000c30, - 0x9480000a, 0xd8000074, 0xc418005e, 0x95800f29, 0xcf800008, 0x80000c16, 0x94800004, 0xd8000074, - 0xc418005e, 0x95800f23, 0xd9c00036, 0x99400002, 0xccc00037, 0xcf800008, 0x80000c16, 0x94800004, - 0xd8000074, 0xc418005e, 0x95800f1a, 0xccc00037, 0xd8800036, 0x80001b70, 0x041c0003, 0x042c01c8, - 0x8c000d61, 0xc4200007, 0xc40c0077, 0x94c00001, 0x7c418001, 0xc428000e, 0x9600f502, 0x0a200001, - 0x98c0f500, 0x2aa80008, 0xce000010, 0x9a000f05, 0xce800013, 0xc431325a, 0xc42d3256, 0x1f30001f, - 0x16e4001f, 0xcf01325a, 0xc431325a, 0x97000001, 0x9640f4f4, 0xc434000b, 0x33740002, 0x9b40f4f1, - 0xc4353254, 0x16a80008, 0x1aec003c, 0x12a80015, 0x12ec001f, 0x1374000b, 0x7eae800a, 0xc02e4000, - 0x1774000d, 0x7eae800a, 0x7f6b400a, 0xcf400100, 0x12780001, 0x2bb80001, 0xc00ac005, 0xc00e0002, - 0x28cc8000, 0x28884900, 0x28cc0014, 0x80000ff3, 0xc43c0007, 0x7c40c001, 0x17fc0001, 0xd8400013, - 0x9bc00004, 0xd8400029, 0xc424005e, 0x96400ee1, 0xcc41c40a, 0xcc41c40c, 0xcc41c40d, 0x7c414001, - 0x24d0007f, 0x15580010, 0x255400ff, 0xcd01c411, 0xcd81c40f, 0xcd41c40e, 0xcc41c410, 0x7c414001, - 0x7c418001, 0x04200000, 0x18e80033, 0x18ec0034, 0xcc41c414, 0xcc41c415, 0xcd81c413, 0xcd41c412, - 0x18dc0032, 0x7c030011, 0x7c038011, 0x95c00027, 0x96c00002, 0xc431c417, 0xc435c416, 0x96800004, - 0x96c00002, 0xc439c419, 0xc43dc418, 0xc41c000e, 0x29dc0008, 0xcdc00013, 0xcf413261, 0x96c00002, - 0xcf013262, 0x96800004, 0xcfc13263, 0x96c00002, 0xcf813264, 0x18dc0030, 0xc43c0007, 0x95c00017, - 0x17fc0001, 0x9ac00005, 0x7d77000c, 0x9bc00015, 0x9700000a, 0x80000cd6, 0x51b80020, 0x53300020, - 0x7f97801a, 0x7f37001a, 0x7f3b000c, 0x9bc0000d, 0x97800002, 0x80000cd6, 0x9a000018, 0xd8400013, - 0x28200001, 0x80000ca7, 0x18dc0031, 0x95c00003, 0xc435c40b, 0x9740fffd, 0xd800002a, 0x80001b70, - 0xc4280032, 0x2aa80008, 0xce800013, 0xc40d325b, 0x97000002, 0x800012c2, 0xc438001d, 0x1bb81ff0, - 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0xc428000e, 0xc43c0007, - 0x2aa80008, 0xc438001d, 0xce800013, 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, - 0x7ff3c00a, 0x80000cf4, 0xc43d325a, 0x1bfc0677, 0x13fc0017, 0x04300100, 0x1bb81fe8, 0x7f73400a, - 0xc032800b, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, 0x80000c16, 0xc43c0007, 0x7c40c001, - 0x18d42011, 0x17fc0001, 0x18d001e8, 0x24cc007f, 0x7cd4c00a, 0x9bc00004, 0xd8400029, 0xc428005e, - 0x96800e6c, 0x7c414001, 0x50580020, 0x7d59401a, 0xd1400072, 0xc8140072, 0x596001fc, 0x12200009, - 0x7ce0c00a, 0x7c418001, 0x505c0020, 0x7d9d801a, 0x7c41c001, 0x50600020, 0x7de1c01a, 0x7c420001, - 0xccc0001b, 0xd140001d, 0xd180001f, 0xd1c00020, 0xd8400021, 0x95000010, 0x04300000, 0xc428000f, - 0x9a80ffff, 0xc8240010, 0x7e5e800c, 0x9bc00015, 0x9a80000c, 0x9b000024, 0x28300001, 0x122c0004, - 0x06ec0001, 0x0aec0001, 0x9ac0ffff, 0xd8400021, 0x80000d1f, 0xc428000f, 0x9a80ffff, 0xc8240010, - 0x566c0020, 0xc428000e, 0x2aa80008, 0xce800013, 0xce413261, 0xcec13262, 0xd800002a, 0x80001b70, - 0xc4340032, 0x2b740008, 0xcf400013, 0xc40d325b, 0x96800005, 0x566c0020, 0xce413261, 0xcec13262, - 0x800012c2, 0xc438001d, 0x1bb81fe8, 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, - 0x80001b70, 0xc43c0007, 0xc438001d, 0xc428000e, 0x2aa80008, 0xce800013, 0x13f4000c, 0x9bc00006, - 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x80000d57, 0xc43d325a, 0x1bfc0677, 0x13fc0017, - 0x04300100, 0x1bb81fe8, 0x7f73400a, 0xc0328009, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, - 0x80000c16, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0xc4253246, 0xc4113245, 0x04143000, 0xcd413267, - 0x52640020, 0x7e51001a, 0xc4153267, 0x7d2d0011, 0x19640057, 0x19580213, 0x19600199, 0x7da6400a, - 0x7e26400a, 0xd1000025, 0xce400024, 0xcdc00026, 0xd8400027, 0x04142000, 0xcfc00013, 0xcd413267, - 0xc4153267, 0x99400001, 0x90000000, 0x7c40c001, 0x18d001e8, 0x18d40030, 0x18d80034, 0x05280d83, - 0x7c420001, 0x7c424001, 0x86800000, 0x80000d8a, 0x8000016a, 0x80000d95, 0x80000db1, 0x8000016a, - 0x80000d95, 0x80000dbc, 0x11540010, 0x7e010001, 0x8c00187c, 0x7d75400a, 0xcd400013, 0xd4610000, - 0x9580f3d8, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0xd8000016, 0x526c0020, 0x18e80058, - 0x7e2ec01a, 0xd2c00072, 0xc82c0072, 0x5ae0073a, 0x7ea2800a, 0x9940000a, 0xce800024, 0xd2c00025, - 0xd4400026, 0xd8400027, 0x9580f3c6, 0xc4380012, 0x9b80ffff, 0x7c408001, 0x88000000, 0xdc3a0000, - 0x0bb80001, 0xce800024, 0xd2c00025, 0xcc400026, 0xd8400027, 0x9b80fffb, 0x9980fff5, 0x7c408001, - 0x88000000, 0xc02a0001, 0x2aa80001, 0x16200002, 0xce800013, 0xce01c405, 0xd441c406, 0x9580f3b1, - 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, 0x32640002, 0x9a40000b, 0x11540010, - 0x29540002, 0xcd400013, 0xd4610000, 0x9580f3a5, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, - 0x88000000, 0xd4400078, 0x80000168, 0xd8400029, 0xc40c005e, 0x94c00da7, 0x7c40c001, 0x50500020, - 0x7cd0c01a, 0xd0c00072, 0xc8280072, 0x5aac007e, 0x12d80017, 0x7c41c001, 0x7d9d800a, 0x56a00020, - 0x2620ffff, 0x7da1800a, 0x51980020, 0x7e82400a, 0x7e58c01a, 0x19d4003d, 0x28182002, 0x99400030, - 0x8c00104f, 0xc430000d, 0xc4340035, 0xd800002a, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, - 0xc011000f, 0xc4240004, 0x11a00002, 0x7c908009, 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, - 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, 0x20880188, 0x54ec0020, 0x7cb4800a, 0xc4300027, - 0x04380008, 0xd1400025, 0xcf000024, 0x20240090, 0x7ca48001, 0xcc800026, 0xccc00026, 0xcec00026, - 0xcec00026, 0x28240004, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800005, 0x32280000, 0x9a800002, - 0x9a000000, 0x7c018001, 0xd8400027, 0xd8000016, 0xcf80003a, 0xd901a2a4, 0x80001037, 0xc418000e, - 0x29980008, 0xcd800013, 0xc421326c, 0x1624001f, 0x9a40fffe, 0xd841325f, 0xd8800033, 0xc43c0009, - 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xd8800034, 0xc429325f, - 0x26ac0001, 0x9ac0fffe, 0x26ac0002, 0x96c00003, 0xd800002a, 0x80001b70, 0xc43c0007, 0xc430001e, - 0xd8800033, 0x13f4000c, 0x1b301ff0, 0x2b300300, 0x2330003f, 0x7f37000a, 0x9680000b, 0xc43c0009, - 0x27fc0004, 0x97c0fffe, 0xd8400039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xcf01325b, 0xd8800034, - 0x80000c16, 0xd8800034, 0x8c0001a2, 0x80001b70, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, - 0x18ac0024, 0x2b304000, 0x7c40c001, 0xcec00008, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, - 0x29980008, 0xcd800013, 0xc4113249, 0x1910003e, 0x99000002, 0xd840003d, 0x7c410001, 0xd4400078, - 0x51100020, 0xcf01326c, 0x7cd0c01a, 0xc421326c, 0x12a80014, 0x2220003f, 0x7e2a000a, 0xcd800013, - 0xce01326c, 0xd8800033, 0xc43c0009, 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, - 0x9bc0ffff, 0xd8800034, 0x80001190, 0x7c40c001, 0x18dc003d, 0x95c00004, 0x041c0001, 0x042c01c8, - 0x8c000d61, 0x18d40030, 0x18d001e8, 0x18fc0034, 0x24e8000f, 0x06a80e71, 0x7c418001, 0x7c41c001, - 0x86800000, 0x80000edd, 0x80000e91, 0x80000e91, 0x80000ea1, 0x80000eaa, 0x80000e7c, 0x80000e7f, - 0x80000e7f, 0x80000e87, 0x80000e8f, 0x8000016a, 0x51dc0020, 0x7d9e001a, 0x80000ee6, 0xc420000e, - 0x2a200008, 0xce000013, 0xc4213262, 0xc4253261, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc420000e, - 0x2a200008, 0xce000013, 0xc4213264, 0xc4253263, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc820001f, - 0x80000ee6, 0x18e82005, 0x51e00020, 0x2aa80000, 0x7da1801a, 0xd1800072, 0xc8180072, 0x59a001fc, - 0x12200009, 0x7ea2800a, 0xce80001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8200011, - 0x80000ee6, 0x15980002, 0xd8400013, 0xcd81c400, 0xc421c401, 0x95400041, 0xc425c401, 0x52640020, - 0x7e26001a, 0x80000ee6, 0x31ac2580, 0x9ac00011, 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, - 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, - 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, 0xc4340004, 0xd8400008, 0x80000ede, 0x39ac7c06, - 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, - 0x80000ebc, 0x39acc335, 0x3db0c336, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9002, 0x3db09001, - 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9012, 0x3db09011, 0x9ac00003, 0x97000002, 0x80000ebc, - 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000ebc, 0xc4340004, 0xd8400013, 0xc5a10000, - 0x95400005, 0x05980001, 0xc5a50000, 0x52640020, 0x7e26001a, 0xcf400008, 0x05280eea, 0x7c418001, - 0x7c41c001, 0x86800000, 0x80000ef1, 0x8000016a, 0x80000efe, 0x80000f11, 0x80000f2e, 0x80000efe, - 0x80000f1f, 0xc4340004, 0xd8400013, 0xce190000, 0x95400005, 0x05980001, 0x56200020, 0xce190000, - 0xcf400008, 0x97c0f26f, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x51ec0020, 0x18e80058, - 0x7daec01a, 0xd2c00072, 0xc82c0072, 0x5af8073a, 0x7eba800a, 0xd2c00025, 0xce800024, 0xce000026, - 0x95400003, 0x56240020, 0xce400026, 0xd8400027, 0x97c0f25c, 0xc4380012, 0x9b80ffff, 0x7c408001, - 0x88000000, 0xc02a0001, 0x2aa80001, 0x15980002, 0xce800013, 0xcd81c405, 0xce01c406, 0x95400003, - 0x56240020, 0xce41c406, 0x97c0f24e, 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, - 0x32640002, 0x9a40f247, 0xd8800013, 0xce190000, 0x95400004, 0x05980001, 0x56200020, 0xce190000, - 0x97c0f240, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x31ac2580, 0x9ac00011, - 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, - 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, - 0xc4340004, 0xd8400008, 0x80000ef2, 0x39ac7c06, 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000f40, - 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, 0x80000f40, 0x39acc335, 0x3db0c336, 0x9ac00003, - 0x97000002, 0x80000f40, 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9002, - 0x3db09002, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9012, 0x3db09012, 0x9ac00003, 0x97000002, - 0x80000f40, 0x80000ef1, 0xc40c0006, 0x98c0ffff, 0x7c40c001, 0x7c410001, 0x7c414001, 0x7c418001, - 0x7c41c001, 0x7c43c001, 0x95c00001, 0xc434000e, 0x2b740008, 0x2b780001, 0xcf400013, 0xd8c1325e, - 0xcf80001a, 0xd8400013, 0x7c034001, 0x7c038001, 0x18e0007d, 0x32240003, 0x9a400006, 0x32240000, - 0x9a400004, 0xcd01c080, 0xcd41c081, 0x80000f88, 0x51640020, 0x7e52401a, 0xd2400072, 0xc8280072, - 0xce81c080, 0x56ac0020, 0x26f0ffff, 0xcf01c081, 0x1af000fc, 0x1334000a, 0x24e02000, 0x7f63400a, - 0x18e00074, 0x32240003, 0x9a400006, 0x32240000, 0x9a400004, 0xcd81c082, 0xcdc1c083, 0x80000f9d, - 0x51e40020, 0x7e5a401a, 0xd2400072, 0xc8280072, 0xce81c082, 0x56ac0020, 0x26f0ffff, 0xcf01c083, - 0x1af000fc, 0x13380016, 0x18e00039, 0x12200019, 0x7fa3800a, 0x7fb7800a, 0x18e0007d, 0x1220001d, - 0x7fa3800a, 0x18e00074, 0x12200014, 0x7fa3800a, 0xcf81c078, 0xcfc1c084, 0x80000c16, 0x7c40c001, - 0x18dc003d, 0x95c00004, 0x041c0000, 0x042c01c8, 0x8c000d61, 0x18d001e8, 0x31140005, 0x99400003, - 0x31140006, 0x95400002, 0x8c00104f, 0x05280fb7, 0x28140002, 0xcd400013, 0x86800000, 0x80000fbe, - 0x80000fbe, 0x80000fc2, 0x80000fbe, 0x80000fd1, 0x80000ff2, 0x80000ff2, 0x24cc003f, 0xccc1a2a4, - 0x7c408001, 0x88000000, 0x7c414001, 0x18e80039, 0x52a8003b, 0x50580020, 0x24cc003f, 0x7d59401a, - 0xd1400072, 0xc8140072, 0x7d69401a, 0xc41c0017, 0x99c0ffff, 0xd140004b, 0xccc1a2a4, 0x7c408001, - 0x88000000, 0xc414000d, 0x04180001, 0x24cc003f, 0x7d958004, 0xcd800035, 0xccc1a2a4, 0xc43c000e, - 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x97c00002, 0xd8400074, 0xc4100019, 0x7d150005, - 0x25100001, 0x9500000b, 0x97c0fffc, 0xc4180021, 0x159c0011, 0x259800ff, 0x31a00003, 0x31a40001, - 0x7e25800a, 0x95c0fff5, 0x9580fff4, 0x80000fef, 0xc411326f, 0x1d100010, 0xcd01326f, 0x97c00002, - 0xd8000074, 0x80001b70, 0x04380000, 0xc430000d, 0xc8140023, 0xc4180081, 0x13300005, 0xc011000f, - 0xc4240004, 0x33b40003, 0x97400003, 0xc0340008, 0x80000ffe, 0xc4340035, 0x11a00002, 0x7c908009, - 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x282c2002, - 0x208801a8, 0x3e280008, 0x7cb4800a, 0xcec00013, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, - 0x20240030, 0x7ca48001, 0xcc800026, 0xccc00026, 0x9b800013, 0xcc400026, 0x7c414001, 0x28340000, - 0xcf400013, 0x507c0020, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, - 0xcd400026, 0xcfc00026, 0xd4400026, 0x9a80000e, 0x32280000, 0x9a80000b, 0x8000102f, 0xcc000026, - 0xcc000026, 0xcc000026, 0xcc000026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, - 0x7c018001, 0xcc000026, 0xd8400027, 0x1cccfe08, 0xd8800013, 0xcec0003a, 0xccc1a2a4, 0xc43c000e, - 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x9bc00007, 0xc428000e, 0x16a80008, 0xce800009, - 0xc42c005e, 0x96c00b33, 0xd840003c, 0xc4200025, 0x7da2400f, 0x7da28002, 0x7e1ac002, 0x0aec0001, - 0x96400002, 0x7d2ac002, 0x3ef40010, 0x9b40f11d, 0x04380030, 0xcf81325e, 0x80000c16, 0xde410000, - 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xddc10000, 0xde010000, 0xc40c000e, 0x7c024001, - 0x28cc0008, 0xccc00013, 0xc8100086, 0x5510003f, 0xc40d3249, 0x18cc003e, 0x98c00003, 0x99000011, - 0x80001075, 0x9900000c, 0xc40c0026, 0xc4100081, 0xc4140025, 0x7d15800f, 0x7d15c002, 0x7d520002, - 0x0a200001, 0x95800002, 0x7cde0002, 0x3e20001a, 0x9a000009, 0x040c0030, 0xccc1325e, 0x80001071, - 0xd9c00036, 0xd8400029, 0xc40c005e, 0x94c00b01, 0x04240001, 0xdc200000, 0xdc1c0000, 0xdc180000, - 0xdc140000, 0xdc100000, 0xdc0c0000, 0x96400004, 0xdc240000, 0xdc0c0000, 0x80000c16, 0xdc240000, - 0x90000000, 0xcc40003f, 0xd8c00010, 0xc4080029, 0xcc80003b, 0xc418000e, 0x18a800e5, 0x1d980008, - 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0x18a400e5, 0x12500009, 0x248c0008, 0x94c00006, - 0x200c006d, 0x7cd0c00a, 0xccc1326c, 0xc421326c, 0x96000001, 0xcd800013, 0x200c0228, 0x7cd0c00a, - 0xccc1326c, 0xc421326c, 0x96000001, 0xc40c002a, 0xc410002b, 0x18881fe8, 0x18d4072c, 0x18cc00d1, - 0x7cd4c00a, 0x3094000d, 0x38d80000, 0x311c0003, 0x99400006, 0x30940007, 0x1620001f, 0x9940001d, - 0x9a000023, 0x800010c4, 0x9580001a, 0x99c00019, 0xccc00041, 0x25140001, 0xc418002c, 0x9940000d, - 0x259c007f, 0x95c00013, 0x19a00030, 0xcdc0001b, 0xd8400021, 0xd8400022, 0xc430000f, 0x17300001, - 0x9b00fffe, 0x9a000012, 0xd8400023, 0x800010cb, 0x199c0fe8, 0xcdc0001b, 0xd8400021, 0xd8400023, - 0xc430000f, 0x17300001, 0x9b00fffe, 0x800010cb, 0xd8c00010, 0xd8000022, 0xd8000023, 0xc430005e, - 0x97000aac, 0x7c408001, 0x88000000, 0xc43c000e, 0xc434002e, 0x2bfc0008, 0x2020002c, 0xcfc00013, - 0xce01326c, 0x17780001, 0x27740001, 0x07a810d8, 0xcf400010, 0xc421326c, 0x96000001, 0x86800000, - 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0x8000104c, 0xcc400040, 0xd8800010, 0xc4180032, - 0x29980008, 0xcd800013, 0x200c007d, 0xccc1325b, 0xc411325b, 0x95000001, 0x7c408001, 0x88000000, - 0x28240007, 0xde430000, 0xd4400078, 0x80001190, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, - 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0xc40d3249, 0x18cc003e, - 0x98c00002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x7c40c001, 0x7c410001, 0x7c414001, - 0x192400fd, 0x50580020, 0x7d59401a, 0x7c41c001, 0x06681110, 0x7c420001, 0xcc400078, 0x18ac0024, - 0x19180070, 0x19100078, 0xcec00008, 0x18f40058, 0x5978073a, 0x7f7b400a, 0x97000001, 0x86800000, - 0x80001117, 0x80001118, 0x80001122, 0x8000112d, 0x80001130, 0x80001133, 0x8000016a, 0x8000117b, - 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, 0xcf400024, 0xcdc00026, - 0xd8400027, 0x8000117b, 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, - 0xcf400024, 0xcdc00026, 0xce000026, 0xd8400027, 0x8000117b, 0xc81c001f, 0x55e00020, 0x80001122, - 0xc81c0020, 0x55e00020, 0x80001122, 0x8c00116b, 0xd8400013, 0xc02a0200, 0x7e8e8009, 0x22a8003d, - 0x22a80074, 0x2774001c, 0x13740014, 0x7eb6800a, 0x25ecffff, 0x55700020, 0x15f40010, 0x13740002, - 0x275c001f, 0x95c00027, 0x7c018001, 0x7f41c001, 0x15dc0002, 0x39e00008, 0x25dc0007, 0x7dc1c01e, - 0x05dc0001, 0x96000004, 0x05e40008, 0x8c00116e, 0x80001168, 0x7dc2001e, 0x06200001, 0x05e40008, - 0x7e62000e, 0x9a000004, 0x7da58001, 0x8c00116e, 0x80001165, 0x7dc2001e, 0x06200001, 0x7e1a0001, - 0x05cc0008, 0x7e0d000e, 0x95000007, 0x7e02401e, 0x06640001, 0x06640008, 0x05d80008, 0x8c00116e, - 0x80001168, 0x7dc2401e, 0x06640001, 0x7da58001, 0x8c00116e, 0x05e00008, 0x7da2000c, 0x9600ffe6, - 0x17640002, 0x8c00116e, 0x80001190, 0xc4200006, 0x9a00ffff, 0x90000000, 0x8c00116b, 0xc420000e, - 0x2a200001, 0xce00001a, 0xce81c078, 0xcec1c080, 0xcc01c081, 0xcd41c082, 0xcf01c083, 0x12640002, - 0x22640435, 0xce41c084, 0x90000000, 0x0528117e, 0x312c0003, 0x86800000, 0x80001190, 0x80001185, - 0x80001182, 0x80001182, 0xc4300012, 0x9b00ffff, 0x9ac0000c, 0xc03a0400, 0xc4340004, 0xd8400013, - 0xd8400008, 0xc418000e, 0x15980008, 0x1198001c, 0x7d81c00a, 0xcdc130b7, 0xcf8130b5, 0xcf400008, - 0x04240008, 0xc418000e, 0xc41c0049, 0x19a000e8, 0x29a80008, 0x7de2c00c, 0xce800013, 0xc421325e, - 0x26200010, 0xc415326d, 0x9a000006, 0xc420007d, 0x96000004, 0x96c00003, 0xce40003e, 0x800011a3, - 0x7d654001, 0xcd41326d, 0x7c020001, 0x96000005, 0xc4100026, 0xc4240081, 0xc4140025, 0x800011b6, - 0xc4253279, 0xc415326d, 0xc431326c, 0x2730003f, 0x3b380006, 0x97800004, 0x3f38000b, 0x9b800004, - 0x800011b4, 0x04300006, 0x800011b4, 0x0430000b, 0x04380002, 0x7fb10004, 0x7e57000f, 0x7e578002, - 0x7d67c002, 0x0be40001, 0x97000002, 0x7d3a4002, 0x202c002c, 0xc421325e, 0x04280020, 0xcec1326c, - 0x26200010, 0x3e640010, 0x96000003, 0x96400002, 0xce81325e, 0xc4300028, 0xc434002e, 0x17780001, - 0x27740001, 0x07a811cf, 0x9b00feb8, 0xcf400010, 0xc414005e, 0x954009a7, 0x86800000, 0x80000168, - 0x80000aa7, 0x80000bfc, 0x800012e9, 0x80000168, 0x8c00120d, 0x7c40c001, 0xccc1c07c, 0xcc41c07d, - 0xcc41c08c, 0x7c410001, 0xcc41c079, 0xcd01c07e, 0x7c414001, 0x18f0012f, 0x18f40612, 0x18cc00c1, - 0x7f73400a, 0x7cf7400a, 0x39600004, 0x9a000002, 0xc0140004, 0x11600001, 0x18fc003e, 0x9740001c, - 0xcf400041, 0xc425c07f, 0x97c00003, 0x166c001f, 0x800011ee, 0x1a6c003e, 0x96c00006, 0x04200002, - 0x0a200001, 0x9a00ffff, 0xd8400013, 0x800011e8, 0xc428002c, 0x96800010, 0x26ac007f, 0xcec0001b, - 0xd8400021, 0x1ab00030, 0x1aac0fe8, 0xc434000f, 0x9b40ffff, 0x97000008, 0xcec0001b, 0xd8400021, - 0xc434000f, 0x9b40ffff, 0x80001205, 0x0a200001, 0x9a00ffff, 0xd8400013, 0xc425c07f, 0x166c001f, - 0x11600001, 0x9ac0fffa, 0x8c001232, 0x7c408001, 0x88000000, 0xd8000033, 0xc438000b, 0xc43c0009, - 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, 0x7ffbc00c, 0x97c0fffd, - 0x90000000, 0xc03a2800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380040, - 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, - 0x9b80ffff, 0x04380002, 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, - 0x9bc0fffa, 0x90000000, 0xd8400013, 0xd801c07f, 0xd8400013, 0xc43dc07f, 0xcfc00078, 0xd8000034, - 0x90000000, 0xc03ae000, 0xcf81c200, 0xc03a0800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, - 0xcc01c07e, 0x04380040, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380002, 0x0bb80001, - 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, 0xc03ae000, - 0xcf81c200, 0xc03a4000, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380002, - 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, - 0xc40c0007, 0x30d00002, 0x99000052, 0xd8400029, 0xc424005e, 0x9640090f, 0x7c410001, 0xc428000e, - 0x1514001f, 0x19180038, 0x2aa80008, 0x99400030, 0x30dc0001, 0xce800013, 0x99c0000a, 0xc42d324e, - 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x1ab0c006, 0x52ec0008, 0x8000127f, - 0xc42d3258, 0xc4313257, 0x52ec0020, 0x7ef2c01a, 0xc4353259, 0xc429325a, 0x1ab0c012, 0x07740001, - 0x04240002, 0x26a0003f, 0x7e624004, 0x7f67800f, 0x97800002, 0x04340000, 0x53740002, 0x7ef6c011, - 0x1ab42010, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f73400a, 0x7f6b400a, 0xcf40001c, 0xd2c0001e, - 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x1514001f, 0x99400006, 0x9980000a, 0x8c0012e1, - 0xc40c0007, 0x04100000, 0x80001267, 0xd800002a, 0xc424005e, 0x964008d7, 0xd9800036, 0x80000c16, - 0xc42c001d, 0x95c00005, 0xc431325a, 0x1b300677, 0x11dc000c, 0x800012aa, 0xc4313256, 0x1b34060b, - 0x1b300077, 0x7f37000a, 0x13300017, 0x04340100, 0x26ec00ff, 0xc03a8002, 0x7ef6c00a, 0x7edec00a, - 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, 0xc4140032, 0xc410001d, 0x29540008, 0xcd400013, - 0xc40d325b, 0x1858003f, 0x251000ff, 0x99800007, 0x7d0cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, - 0xcd01325d, 0x80000168, 0x18d0006c, 0x18d407f0, 0x9900000e, 0x04100002, 0xc4193256, 0xc41d324f, - 0x2598003f, 0x7d190004, 0x7d5d4001, 0x7d52000f, 0x9a000003, 0xcd41324f, 0x800012d8, 0x7d514002, - 0xcd41324f, 0x800012d8, 0xc4193259, 0xc41d325a, 0x7d958001, 0x7dd5c002, 0xcd813259, 0xcdc1325a, - 0xc411325d, 0x251001ef, 0xcd01325d, 0x1ccc001e, 0xccc1325b, 0xc40d325b, 0x94c00001, 0x7c408001, - 0x88000000, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0x9b000004, 0x9b40000c, - 0x9b80000f, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, 0x8c000190, 0xd8000032, 0x90000000, - 0xd8000028, 0xd800002b, 0x80000168, 0xd980003f, 0x97c00002, 0xd9c0003f, 0x80001082, 0xd9800040, - 0x97c00002, 0xd9c00040, 0x800010de, 0xc43c0007, 0x33f80003, 0x97800051, 0xcc80003b, 0x24b00008, - 0xc418000e, 0x1330000a, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, - 0xc4353249, 0x1b74003e, 0x9b400002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x97000001, - 0x7c434001, 0x1b4c00f8, 0x7c410001, 0x7c414001, 0x50700020, 0x04e81324, 0x18ac0024, 0x7c41c001, - 0x50600020, 0xcc400078, 0x30e40004, 0x9a400007, 0x7d71401a, 0x596401fc, 0x12640009, 0x1b74008d, - 0x7e76400a, 0x2a640000, 0xcec00008, 0x86800000, 0x8000016a, 0x8000016a, 0x8000016a, 0x8000016a, - 0x8000132c, 0x8000133b, 0x80001344, 0x8000016a, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42530b5, - 0x1a68003a, 0x9a80fffe, 0x2024003a, 0xc418000e, 0x25980700, 0x11980014, 0x7d19000a, 0xcd0130b7, - 0xce4130b5, 0xcf400008, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, 0x9a80ffff, - 0xc4240011, 0x7de6800f, 0x9a80ffea, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, - 0x9a80ffff, 0xc8240011, 0x7de1c01a, 0x7de6800f, 0x9a80ffe0, 0x80001190, 0x8c00104f, 0x28182002, - 0xc430000d, 0xc4340035, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, 0xc4240004, 0x11a00002, - 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, - 0x7cb4800a, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, 0x20240030, 0x7ca48001, 0xcc800026, - 0x7c434001, 0x1b4c00f8, 0xcf400026, 0xcc400026, 0x28340000, 0xcf400013, 0x7c414001, 0x507c0020, - 0x30e40004, 0x9a400005, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, - 0xcd400026, 0xcfc00026, 0xd4400026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, - 0x7c018001, 0xd8400027, 0xd8800013, 0x04380028, 0xcec0003a, 0xcf81a2a4, 0x80001037, 0xd8400029, - 0xc40c005e, 0x94c007eb, 0x7c40c001, 0x50500020, 0x7d0d001a, 0xd1000072, 0xc8100072, 0x591c01fc, - 0x11dc0009, 0x45140210, 0x595801fc, 0x11980009, 0x29dc0000, 0xcdc0001c, 0xd140001e, 0xd8400021, - 0xc418000f, 0x9980ffff, 0xc4200011, 0x1624001f, 0x96400069, 0xc40c000e, 0x28cc0008, 0xccc00013, - 0xce013249, 0x1a307fe8, 0xcf00000a, 0x23304076, 0xd1000001, 0xcf000001, 0xc41d3254, 0xc4253256, - 0x18cc00e8, 0x10cc0015, 0x4514020c, 0xd140001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, - 0xce013248, 0x1a2001e8, 0x12200014, 0x2a204001, 0xce000013, 0x1a64003c, 0x1264001f, 0x11dc0009, - 0x15dc000b, 0x7dcdc00a, 0x7e5dc00a, 0xcdc00100, 0xd8800013, 0xd8400010, 0xd800002a, 0xd8400008, - 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, 0x04300010, 0xdf430000, 0x7c434001, - 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, 0xdf030000, 0xd4412e40, 0xd8400013, - 0xcc41c030, 0xcc41c031, 0x248dfffe, 0xccc12e00, 0xd8800013, 0xcc812e00, 0x7c434001, 0x7c434001, - 0x8c00142b, 0xd8000010, 0xc40c000e, 0x28cc0008, 0xccc00013, 0x45140248, 0xd140001e, 0xd8400021, - 0xc418000f, 0x9980ffff, 0xc8200011, 0xce013257, 0x56200020, 0xce013258, 0x0434000c, 0xdb000024, - 0xd1400025, 0xd8000026, 0xd8000026, 0xd8400027, 0x45540008, 0xd140001e, 0xd8400021, 0xc418000f, - 0x9980ffff, 0xc8200011, 0xce013259, 0x56200020, 0xc0337fff, 0x7f220009, 0xce01325a, 0x55300020, - 0x7d01c001, 0x042c01d0, 0x8c000d61, 0x06ec0004, 0x7f01c001, 0x8c000d61, 0x041c0002, 0x042c01c8, - 0x8c000d61, 0xc4380012, 0x9b80ffff, 0xd800002a, 0x80000aa7, 0xd800002a, 0x7c408001, 0x88000000, - 0xd8400029, 0x7c40c001, 0x50500020, 0x8c001427, 0x7cd0c01a, 0xc4200007, 0xd0c00072, 0xc8240072, - 0xd240001e, 0x7c414001, 0x19682011, 0x5a6c01fc, 0x12ec0009, 0x7eeac00a, 0x2aec0000, 0xcec0001c, - 0xd8400021, 0xc430000f, 0x9b00ffff, 0xc4180011, 0x7c438001, 0x99800007, 0xdf830000, 0xcfa0000c, - 0x8c00142b, 0xd4400078, 0xd800002a, 0x80001b70, 0x8c00142b, 0xd800002a, 0x80001b70, 0xd8000012, - 0xc43c0008, 0x9bc0ffff, 0x90000000, 0xd8400012, 0xc43c0008, 0x97c0ffff, 0x90000000, 0xc4380007, - 0x7c40c001, 0x17b80001, 0x18d40038, 0x7c410001, 0x9b800004, 0xd8400029, 0xc414005e, 0x9540073d, - 0x18c80066, 0x7c414001, 0x30880001, 0x7c418001, 0x94800008, 0x8c00187c, 0xcf400013, 0xc42c0004, - 0xd8400008, 0xcd910000, 0xcec00008, 0x7d410001, 0x043c0000, 0x7c41c001, 0x7c420001, 0x04240001, - 0x06200001, 0x4220000c, 0x0a640001, 0xcc000078, 0x9a40fffe, 0x24e80007, 0x24ec0010, 0xd8400013, - 0x9ac00006, 0xc42c0004, 0xd8400008, 0xc5310000, 0xcec00008, 0x80001465, 0x51540020, 0x7d15001a, - 0xd1000072, 0xc82c0072, 0xd2c0001e, 0x18f02011, 0x5aec01fc, 0x12ec0009, 0x7ef2c00a, 0x2aec0000, - 0xcec0001c, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc4300011, 0x96800012, 0x12a80001, 0x0aa80001, - 0x06a8146a, 0x7f1f0009, 0x86800000, 0x7f1b400f, 0x80001478, 0x7f1b400e, 0x80001478, 0x7f1b400c, - 0x8000147a, 0x7f1b400d, 0x8000147a, 0x7f1b400f, 0x8000147a, 0x7f1b400e, 0x8000147a, 0x7f334002, - 0x97400014, 0x8000147b, 0x9b400012, 0x9b800005, 0x9bc0001f, 0x7e024001, 0x043c0001, 0x8000144a, - 0xc40c0032, 0xc438001d, 0x28cc0008, 0xccc00013, 0xc43d325b, 0x1bb81ff0, 0x7fbfc00a, 0xcfc1325b, - 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0x94800007, 0x8c00187c, 0xcf400013, 0xc42c0004, - 0xd8400008, 0xcd910000, 0xcec00008, 0x9b800003, 0xd800002a, 0x80001b70, 0xc40c0032, 0x28cc0008, - 0xccc00013, 0xc40d325b, 0x800012c2, 0xc40c000e, 0xc43c0007, 0xc438001d, 0x28cc0008, 0xccc00013, - 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x800014a9, 0xc43d325a, - 0x1bfc0677, 0x04300100, 0x1bb81ff0, 0x7f73400a, 0xc0328007, 0x7fb7800a, 0x13fc0017, 0x7ff3c00a, - 0x7ffbc00a, 0xcfc1325b, 0xc03a0002, 0xc4340004, 0xd8400013, 0xd8400008, 0xcf8130b5, 0xcf400008, - 0x80000c16, 0x043c0000, 0xc414000e, 0x29540008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, - 0x7dd9c01a, 0x45dc0390, 0xc4313267, 0x04183000, 0xcd813267, 0x1b380057, 0x1b340213, 0x1b300199, - 0x7f7b400a, 0x7f73400a, 0xcf400024, 0xd1c00025, 0xcc800026, 0x7c420001, 0xce000026, 0x7c424001, - 0xce400026, 0x7c428001, 0xce800026, 0x7c42c001, 0xcec00026, 0x7c430001, 0xcf000026, 0x7c434001, - 0xcf400026, 0x7c438001, 0xcf800026, 0xd8400027, 0xcd400013, 0x04182000, 0xcd813267, 0xd840004f, - 0x1a0800fd, 0x109c000a, 0xc4193265, 0x7dd9c00a, 0xcdc13265, 0x2620ffff, 0xce080228, 0x9880000e, - 0xce480250, 0xce880258, 0xd8080230, 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, - 0xd8080278, 0xd8080280, 0xd800004f, 0x97c0ec75, 0x90000000, 0x040c0000, 0x041c0010, 0x26180001, - 0x09dc0001, 0x16200001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80230, 0xd8080238, 0xd8080240, - 0xd8080248, 0x040c0000, 0xce480250, 0xce880258, 0x52a80020, 0x7e6a401a, 0x041c0020, 0x66580001, - 0x09dc0001, 0x56640001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80260, 0xd8080268, 0xd8080270, - 0xd8080278, 0xd8080280, 0x040c0000, 0xcec80288, 0xcf080290, 0xcec80298, 0xcf0802a0, 0x040c0000, - 0x041c0010, 0xcf4802a8, 0x27580001, 0x09dc0001, 0x17740001, 0x95800002, 0x04cc0001, 0x99c0fffb, - 0xccc802b0, 0xd80802b8, 0x178c000b, 0x27b8003f, 0x7cf8c001, 0xcf8802c0, 0xccc802c8, 0xcf8802d0, - 0xcf8802d8, 0xd800004f, 0x97c00002, 0x90000000, 0x7c408001, 0x88000000, 0xc40c000e, 0x28cc0008, - 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c418001, 0x25b8ffff, 0xc4930240, 0xc48f0238, 0x04cc0001, - 0x24cc000f, 0x7cd2800c, 0x9a80000b, 0xc5230309, 0x2620ffff, 0x7e3a400c, 0x9a400004, 0x05100001, - 0x2510000f, 0x80001539, 0xcd08034b, 0xd4400078, 0x80000168, 0xc48f0230, 0xc4930240, 0x98c00004, - 0xcd880353, 0x8c00163f, 0xc49b0353, 0xc4930238, 0xc48f0228, 0x05100001, 0x2510000f, 0x7cd14005, - 0x25540001, 0x99400004, 0x05100001, 0x2510000f, 0x8000154f, 0xc48f0230, 0x7c41c001, 0xcd080238, - 0xcd08034b, 0x08cc0001, 0x2598ffff, 0x3d200008, 0xccc80230, 0xcd900309, 0xd8100319, 0x04340801, - 0x2198003f, 0xcf400013, 0xcd910ce7, 0xc4190ce6, 0x7d918005, 0x25980001, 0x9580fffd, 0x7d918004, - 0xcd810ce6, 0x9a000003, 0xcdd1054f, 0x8000156e, 0x090c0008, 0xcdcd050e, 0x040c0000, 0x110c0014, - 0x28cc4001, 0xccc00013, 0xcc41230a, 0xcc41230b, 0xcc41230c, 0xcc41230d, 0xcc480329, 0xcc48032a, - 0xcc4802e0, 0xd8000055, 0xc48f02e0, 0x24d8003f, 0x09940001, 0x44100001, 0x9580002c, 0x95400005, - 0x09540001, 0x51100001, 0x69100001, 0x8000157f, 0x24cc003f, 0xc4970290, 0xc49b0288, 0x51540020, - 0x7d59401a, 0xc49b02a0, 0xc49f0298, 0x51980020, 0x7d9d801a, 0x041c0040, 0x04200000, 0x7dcdc002, - 0x7d924019, 0x7d26400c, 0x09dc0001, 0x9a400008, 0x51100001, 0x06200001, 0x99c0fffa, 0xc48f0230, - 0xc4930240, 0x8c00163f, 0x80001579, 0x7d010021, 0x7d914019, 0xc4930238, 0x55580020, 0xcd480298, - 0xcd8802a0, 0x10d40010, 0x12180016, 0xc51f0309, 0x7d95800a, 0x7d62000a, 0x7dd9c00a, 0xd8400013, - 0xcdd00309, 0xce113320, 0xc48f02e0, 0xc49b02b0, 0x18dc01e8, 0x7dd9400e, 0xc48f0230, 0xc4930240, - 0x95c0001d, 0x95400003, 0x8c00163f, 0x800015aa, 0xc48f0238, 0xc4a302b8, 0x12240004, 0x7e5e400a, - 0xc4ab02a8, 0x04100000, 0xce4c0319, 0x7d9d8002, 0x7ea14005, 0x25540001, 0x99400004, 0x06200001, - 0x2620000f, 0x800015bc, 0x09dc0001, 0x04240001, 0x7e624004, 0x06200001, 0x7d25000a, 0x2620000f, - 0x99c0fff4, 0xd8400013, 0xcd0d3330, 0xce0802b8, 0xcd8802b0, 0xc4ab02e0, 0x1aa807f0, 0xc48f02d0, - 0xc49702d8, 0xc49b02c8, 0xc49f02c0, 0x96800028, 0x7d4e000f, 0x9600000b, 0x7d964002, 0x7e6a000f, - 0x96000003, 0x7d694001, 0x800015e9, 0x7cde4002, 0x7e6a000f, 0x96000008, 0x7de94001, 0x800015e9, - 0x7cd64002, 0x7e6a000e, 0x96000003, 0x7d694001, 0x800015e9, 0xc48f0230, 0xc4930240, 0x8c00163f, - 0x800015cd, 0xc4930238, 0x7d698002, 0xcd4802d8, 0x129c0008, 0xc50f0319, 0x11a0000e, 0x11140001, - 0xc4340004, 0xd8400008, 0xd8400013, 0x7e1e000a, 0x1198000a, 0xcd953300, 0x7e0e000a, 0x12a8000a, - 0xce953301, 0xce100319, 0xcf400008, 0xc4b70280, 0xc4b30278, 0x7f73800a, 0x536c0020, 0x7ef2c01a, - 0x9780eb68, 0x8c001608, 0xd8080278, 0xd8080280, 0x7c408001, 0x88000000, 0x043c0003, 0x80001609, - 0x043c0001, 0x30b40000, 0x9b400011, 0xc4b70258, 0xc4b30250, 0x53780020, 0x7fb3801a, 0x7faf8019, - 0x04300020, 0x04280000, 0x67b40001, 0x0b300001, 0x57b80001, 0x97400002, 0x06a80001, 0x9b00fffb, - 0xc4bb0260, 0x7fab8001, 0xcf880260, 0x04300020, 0x04280000, 0x66f40001, 0x0b300001, 0x56ec0001, - 0x97400005, 0x8c001628, 0xc4353247, 0x7f7f4009, 0x9b40fffe, 0x06a80001, 0x9b00fff7, 0x90000000, - 0x269c0007, 0x11dc0008, 0x29dc0008, 0x26a00018, 0x12200003, 0x7de1c00a, 0x26a00060, 0x06200020, - 0x16200001, 0x7de1c00a, 0xcdc00013, 0x90000000, 0x269c0018, 0x26a00007, 0x26a40060, 0x11dc0006, - 0x12200006, 0x16640001, 0x29dc0008, 0x7de1c00a, 0x7de5c00a, 0xcdc00013, 0x90000000, 0xc4b70228, - 0x05100001, 0x04cc0001, 0x2510000f, 0xccc80230, 0x7f514005, 0x25540001, 0x99400004, 0x05100001, - 0x2510000f, 0x80001644, 0xc4b30248, 0xcd080240, 0x7f130005, 0x27300001, 0x9b000002, 0x8c001688, - 0x8c00120d, 0x8c001219, 0x8c001232, 0x04300001, 0x04340801, 0x7f130004, 0xcf400013, 0xcf01051e, - 0xc42d051f, 0x7ed2c005, 0x26ec0001, 0x96c0fffd, 0xcf01051f, 0xd8000055, 0xc5170309, 0x195c07f0, - 0x196007f6, 0x04340000, 0x95c00008, 0x09dc0001, 0x04340001, 0x95c00005, 0x09dc0001, 0x53740001, - 0x6b740001, 0x80001665, 0xc4a702a0, 0xc4ab0298, 0x52640020, 0x7e6a401a, 0x7f634014, 0x7e76401a, - 0xc4300004, 0xd8400008, 0xd8400013, 0x56680020, 0xd8113320, 0xce480298, 0xce8802a0, 0xc5170319, - 0xc4b702b0, 0x255c000f, 0x7f5f4001, 0xd8113330, 0xcf4802b0, 0x11340001, 0x195c07e8, 0x196007ee, - 0xd8353300, 0x7e1e4001, 0xd8353301, 0xce4802d0, 0xd8100309, 0xd8100319, 0xcf000008, 0x90000000, - 0xc4970258, 0xc48f0250, 0x51540020, 0x7cd4c01a, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, - 0x04140020, 0x04280000, 0x64d80001, 0x09540001, 0x54cc0001, 0x95800060, 0x8c001628, 0xc4193247, - 0x25980001, 0x9580005c, 0x7dc24001, 0xc41d3248, 0x25dc000f, 0x7dd2000c, 0x96000057, 0xc41d3255, - 0xc435324f, 0x7df5c00c, 0x99c00004, 0xc4193265, 0x25980040, 0x9580fffe, 0xc439325b, 0x1bb0003f, - 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, 0x1bb000e4, - 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x800016f1, 0xce400013, 0xc033ffff, - 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, 0xd8c00033, - 0xc4300009, 0x27300008, 0x9700fffe, 0x1a7003e6, 0x27380003, 0x13b80004, 0x27300003, 0x13300003, - 0x7fb38001, 0x1a7000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, 0x1a700064, - 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, - 0x0b300003, 0x800016df, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, - 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xce400013, 0xc431325d, - 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xd841325d, 0x2030007b, 0xcf01325b, - 0x800016f2, 0xd841325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9c, 0x8c001608, - 0xd8080278, 0xd8080280, 0x90000000, 0xd840004f, 0xc414000e, 0x29540008, 0xcd400013, 0xc43d3265, - 0x1bc800ea, 0xd80802e9, 0x7c40c001, 0x18fc0064, 0x9bc00042, 0xc4193246, 0xc41d3245, 0x51980020, - 0x7dd9801a, 0x45980400, 0xc4313267, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x9bc00001, 0x1b380057, - 0x1b340213, 0x1b300199, 0x7f7b400a, 0x7f73400a, 0xcf400024, 0x14f4001d, 0xc4bf02e9, 0x9bc0001c, - 0x7c410001, 0x192807fa, 0xc4bf0258, 0xc4a70250, 0x53fc0020, 0x7e7e401a, 0x042c0000, 0x04300000, - 0x667c0001, 0x56640001, 0x06ec0001, 0x97c0fffd, 0x07300001, 0x0aec0001, 0x7eebc00c, 0x06ec0001, - 0x97c0fff8, 0x0b300001, 0x43300007, 0x53300002, 0x7db30011, 0xd3000025, 0xc03ec005, 0x2bfca200, - 0xcfc00026, 0xccc00026, 0xcd000026, 0x192807fa, 0xc01f007f, 0x7d1d0009, 0x2110007d, 0x8c001628, - 0x203c003f, 0xcfc13256, 0x8c0017f5, 0xcd013254, 0x18fc01e8, 0xcfc13248, 0x8c00185b, 0xd8413247, - 0x0b740001, 0x9b40ffd5, 0xd800004f, 0xc4bf02e9, 0x97c0ea24, 0x90000000, 0x14d4001d, 0xc4930260, - 0x7d52400e, 0xc49f0258, 0xc4a30250, 0x51dc0020, 0x7de1801a, 0x96400017, 0x7d534002, 0xc4af0270, - 0x7dae4005, 0x26640001, 0x32e0001f, 0x9a400006, 0x06ec0001, 0x96000002, 0x042c0000, 0xcec80270, - 0x8000174f, 0x0b740001, 0x8c00178a, 0x05100001, 0x9b40fff3, 0xc4af0280, 0xc4b30278, 0x52ec0020, - 0x7ef2c01a, 0x8c001608, 0xd8080278, 0xd8080280, 0xc4ab0268, 0x7daa4005, 0x26640001, 0x32a0001f, - 0x9a400005, 0x06a80001, 0x96000002, 0x24280000, 0x80001765, 0x7c410001, 0xc01f007f, 0x09540001, - 0x7d1d0009, 0x2110007d, 0x8c001628, 0xd8013256, 0x8c0017f2, 0xcd013254, 0xc4113248, 0x15100004, - 0x11100004, 0xc4b3034b, 0x7f13000a, 0xcf013248, 0xc4930260, 0x8c001855, 0x32a4001f, 0xd8413247, - 0xd800004f, 0x09100001, 0x06a80001, 0x96400002, 0x24280000, 0xcd080260, 0xce880268, 0x9940ffc0, - 0x7c408001, 0x88000000, 0x7ec28001, 0x8c001628, 0x32e0001f, 0xc4253247, 0x26640001, 0x9640005e, - 0xc4293265, 0xc4253255, 0xc431324f, 0x7e72400c, 0x26a80040, 0x9a400002, 0x9680fff7, 0xc429325b, - 0x1aa4003f, 0x96400049, 0x1aa400e8, 0x32680003, 0x9a800046, 0x32640002, 0x9640000a, 0xc4293260, - 0x1aa400e4, 0x32640004, 0x96400040, 0xc425325d, 0x26640010, 0x9a40fffe, 0x800017e2, 0xcdc00013, - 0xc027ffff, 0x2e6400ff, 0xc429325b, 0x7e6a4009, 0xce41325b, 0xc429325b, 0x26a800ff, 0x9a80fffe, - 0xd8c00033, 0xc4240009, 0x26640008, 0x9640fffe, 0x19e403e6, 0x26680003, 0x12a80004, 0x26640003, - 0x12640003, 0x7ea68001, 0x19e400e8, 0x7ea68001, 0x12640001, 0x7ea68001, 0x06a80002, 0xd8400013, - 0x19e40064, 0x32640002, 0x96400009, 0x16a40005, 0x06640003, 0xce412082, 0xcc01203f, 0xd8400013, - 0xcc01203f, 0x0a640003, 0x800017d0, 0x16a40005, 0xce412082, 0xcc01203f, 0xd8400013, 0xcc01203f, - 0x12640005, 0x7ea64002, 0xc4292083, 0x7ea68005, 0x26a80001, 0x9a80ffdf, 0xd8c00034, 0xcdc00013, - 0xc425325d, 0x26640010, 0x9a40fffe, 0xc429325b, 0x26a400ff, 0x9a40ffca, 0xd841325d, 0x2024007b, - 0xce41325b, 0x800017e3, 0xd841325d, 0xc4a70280, 0xc4ab0278, 0x52640020, 0x7e6a401a, 0x04280001, - 0x7eae8014, 0x7e6a401a, 0x56680020, 0xce480278, 0xce880280, 0x06ec0001, 0x96000002, 0x042c0000, - 0xcec80270, 0x90000000, 0x7c438001, 0x7c420001, 0x800017fe, 0xc4bf02e9, 0x9bc00006, 0x7c438001, - 0x7c420001, 0xcf800026, 0xce000026, 0x800017fe, 0xc43b02eb, 0xc42302ec, 0xcf813245, 0xce013246, - 0x52200020, 0x7fa3801a, 0x47b8020c, 0x15e00008, 0x1220000a, 0x2a206032, 0x513c001e, 0x7e3e001a, - 0xc4bf02e9, 0x9bc00005, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x8000180f, 0xcd400013, 0xc4313267, - 0x1b3c0077, 0x1b300199, 0x7ff3000a, 0x1330000a, 0x2b300032, 0x043c3000, 0xcfc13267, 0xc43d3267, - 0xd200000b, 0xc4200007, 0xd3800002, 0xcf000002, 0xd8000040, 0x96000002, 0xd8400040, 0xd8400018, - 0x043c2000, 0xcfc13267, 0xd8000018, 0xd8800010, 0xcdc00013, 0x7dc30001, 0xdc1e0000, 0x04380032, - 0xcf80000e, 0x8c001427, 0xcc413248, 0xc43d3269, 0x27fc000f, 0x33fc0003, 0x97c00011, 0x043c001f, - 0xdfc30000, 0xd4413249, 0x7c43c001, 0x7c43c001, 0x043c0024, 0x0bfc0021, 0xdfc30000, 0xd441326a, - 0x173c0008, 0x1b300303, 0x7f3f0001, 0x043c0001, 0x7ff3c004, 0xcfc13084, 0x80001842, 0x043c0024, - 0xdfc30000, 0xd4413249, 0x7c43c001, 0x23fc003f, 0xcfc1326d, 0x0bb80026, 0xdf830000, 0xd441326e, - 0x7c438001, 0x7c438001, 0xc4393265, 0x1fb8ffc6, 0xddc30000, 0xcf813265, 0x9a000003, 0xcdc0000c, - 0x80001852, 0xcdc0000d, 0xce000010, 0x8c00142b, 0x90000000, 0x7c41c001, 0x7c420001, 0xcdc13252, - 0xce013253, 0x8c001628, 0x80001878, 0xc49f02e9, 0x99c00018, 0x7c41c001, 0x7c420001, 0xcdc13252, - 0xce013253, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x97c0ffff, - 0xcdc00026, 0xce000026, 0xd8400027, 0xc41c0012, 0x99c0ffff, 0xc43c000e, 0x2bfc0008, 0xcfc00013, - 0x043c2000, 0xcfc13267, 0x8c001628, 0x80001878, 0xc41f02ed, 0xc42302ee, 0xcdc13252, 0xce013253, - 0x04200001, 0x7e2a0004, 0xce013084, 0x90000000, 0x28340001, 0x313c0bcc, 0x9bc00010, 0x393c051f, - 0x9bc00004, 0x3d3c050e, 0x9bc0000c, 0x97c0000c, 0x393c0560, 0x9bc00004, 0x3d3c054f, 0x9bc00007, - 0x97c00007, 0x393c1538, 0x9bc00005, 0x3d3c1537, 0x9bc00002, 0x97c00002, 0x2b740800, 0x90000000, - 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e8007c, 0x7c42c001, - 0x06a8189a, 0x86800000, 0x8000189e, 0x800018c5, 0x800018f2, 0x8000016a, 0x7c414001, 0x18d0007e, - 0x50580020, 0x09200001, 0x7d59401a, 0xd1400072, 0xc8140072, 0x09240002, 0x7c418001, 0x7c41c001, - 0x99000011, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42130b5, 0x1a24002c, 0x9a40fffe, 0x2020002c, - 0xc418000d, 0x1198001c, 0x10cc0004, 0x14cc0004, 0x7cd8c00a, 0xccc130b7, 0xce0130b5, 0xcf400008, - 0x80000168, 0xd1400025, 0x5978073a, 0x2bb80002, 0xcf800024, 0xcd800026, 0xcdc00026, 0xd8400027, - 0x9600e8a8, 0xc4300012, 0x9b00ffff, 0x9640e8a5, 0x800018a9, 0x04140000, 0xc55b0309, 0x3d5c0010, - 0x05540001, 0x2598ffff, 0x09780001, 0x7dad800c, 0x99c0ffd2, 0x9580fff9, 0xc4970258, 0xc4930250, - 0x51540020, 0x7d15001a, 0x04140020, 0x04280000, 0x442c0000, 0x65180001, 0x09540001, 0x55100001, - 0x9580000b, 0x8c001628, 0xc41d3248, 0x04300001, 0x7f2b0014, 0x25dc000f, 0x7df9c00c, 0x95c00004, - 0x7ef2c01a, 0xd8c13260, 0xd901325d, 0x06a80001, 0x9940fff1, 0x04140020, 0x04280000, 0x66d80001, - 0x09540001, 0x56ec0001, 0x95800005, 0x8c001628, 0xc421325d, 0x26240007, 0x9a40fffe, 0x06a80001, - 0x9940fff7, 0x8000189e, 0x04140020, 0x04280000, 0x09540001, 0x8c001628, 0xc41d3254, 0xc023007f, - 0x19e4003e, 0x7de1c009, 0x7dee000c, 0x96400008, 0x96000007, 0xd8c13260, 0xd901325d, 0xc421325d, - 0x261c0007, 0x99c0fffe, 0x8000189e, 0x06a80001, 0x9940fff0, 0x8000189e, 0xc40c000e, 0x28cc0008, - 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e00064, 0x06281911, 0x14f4001d, 0x24cc0003, - 0x86800000, 0x80001915, 0x800019af, 0x80001a2b, 0x8000016a, 0xcc48032b, 0xcc480333, 0xcc48033b, - 0xcc480343, 0x98800011, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, - 0x04203000, 0xce013267, 0xc4213267, 0x9a000001, 0x1b3c0057, 0x1b200213, 0x1b300199, 0x7e3e000a, - 0x7e32000a, 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, - 0x52ec0020, 0x7ef2c01a, 0x04180000, 0x04140020, 0x04280000, 0x7f438001, 0x8c001628, 0xc41d3247, - 0x25dc0001, 0x95c00068, 0xc4213254, 0x1a1c003e, 0x95c00065, 0xc01f007f, 0x7e1e0009, 0x97800062, - 0x0bb80001, 0x43bc0008, 0x7fcbc001, 0xc7df032b, 0x7e1fc00c, 0x97c0fffa, 0x043c0101, 0x94c00002, - 0x043c0102, 0xc439325b, 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, - 0x97000009, 0xc4393260, 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, - 0x80001994, 0x8c001628, 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, - 0x27b800ff, 0x9b80fffe, 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, - 0x13b80004, 0x27300003, 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, - 0x07b80002, 0xd8400013, 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, - 0xcc01203f, 0xd8400013, 0xcc01203f, 0x0b300003, 0x80001982, 0x17b00005, 0xcf012082, 0xcc01203f, - 0xd8400013, 0xcc01203f, 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, - 0xd8c00034, 0xcdc00013, 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffcb, - 0xcfc1325d, 0x2030007b, 0xcf01325b, 0x80001995, 0xcfc1325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, - 0x98800009, 0x41bc0007, 0x53fc0002, 0x7e7fc011, 0xd3c00025, 0xd8000026, 0xd8400027, 0xc43c0012, - 0x9bc0ffff, 0x653c0001, 0x7dbd8001, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff8f, 0xc43c000e, - 0x2bfc0008, 0xcfc00013, 0x043c2000, 0xcfc13267, 0xd8080278, 0xd8080280, 0x80000168, 0x7c410001, - 0x04140000, 0xc55b0309, 0x3d5c0010, 0x2598ffff, 0x05540001, 0x7d91800c, 0x95c00003, 0xd4400078, - 0x80000168, 0x9580fff8, 0x09780001, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, - 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x09540001, 0x55100001, - 0x9580005d, 0x8c001628, 0xc4253247, 0x26640001, 0x04200101, 0x96400058, 0x7dc24001, 0xc41d3248, - 0x25dc000f, 0x7df9c00c, 0x95c00053, 0x94c00002, 0x04200102, 0x7e41c001, 0xc425325b, 0x1a70003f, - 0x97000049, 0x1a7000e8, 0x33240003, 0x9a400046, 0x33300002, 0x9700000a, 0xc4253260, 0x1a7000e4, - 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001a21, 0xcdc00013, 0xc033ffff, - 0x2f3000ff, 0xc425325b, 0x7f270009, 0xcf01325b, 0xc425325b, 0x266400ff, 0x9a40fffe, 0xd8c00033, - 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27240003, 0x12640004, 0x27300003, 0x13300003, - 0x7e724001, 0x19f000e8, 0x7e724001, 0x13300001, 0x7e724001, 0x06640002, 0xd8400013, 0x19f00064, - 0x33300002, 0x97000009, 0x16700005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, - 0x0b300003, 0x80001a0f, 0x16700005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, - 0x7e730002, 0xc4252083, 0x7e724005, 0x26640001, 0x9a40ffdf, 0xd8c00034, 0xcdc00013, 0xc431325d, - 0x27300010, 0x9b00fffe, 0xc425325b, 0x267000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, 0xcf01325b, - 0x80001a22, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9f, 0xd4400078, - 0xd8080278, 0xd8080280, 0x80000168, 0x8c001a31, 0xd4400078, 0xd8080278, 0xd8080280, 0x7c408001, - 0x88000000, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, 0x04203000, - 0xce013267, 0xc4213267, 0x9a000001, 0x1b180057, 0x1b200213, 0x1b300199, 0x7e1a000a, 0x7e32000a, - 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, 0x52ec0020, - 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x95800060, 0x8c001628, 0xc4193247, 0x25980001, - 0x04200101, 0x94c00005, 0x30f00005, 0x04200005, 0x9b000002, 0x04200102, 0x95800056, 0xc439325b, - 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, - 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001aa2, 0xcdc00013, - 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, - 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, 0x13b80004, 0x27300003, - 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, - 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, - 0xcc01203f, 0x0b300003, 0x80001a90, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, - 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xcdc00013, - 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, - 0xcf00325b, 0x80001aa3, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0xc49b02e9, 0x99800005, - 0xd2400025, 0x4664001c, 0xd8000026, 0xd8400027, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff9c, - 0xc49b02e9, 0x99800008, 0xc430000e, 0x2b300008, 0xcf000013, 0x04302000, 0xcf013267, 0xc4313267, - 0x97000001, 0x90000000, 0x244c00ff, 0xcc4c0200, 0x7c408001, 0x88000000, 0xc44f0200, 0xc410000b, - 0xc414000c, 0x7d158010, 0x059cc000, 0xd8400013, 0xccdd0000, 0x7c408001, 0x88000000, 0xc40c0037, - 0x94c0ffff, 0xcc000049, 0xc40c003a, 0x94c0ffff, 0x7c40c001, 0x24d00001, 0x9500e69a, 0x18d0003b, - 0x18d40021, 0x99400006, 0xd840004a, 0xc40c003c, 0x94c0ffff, 0x14cc0001, 0x94c00028, 0xd8000033, - 0xc438000b, 0xc43c0009, 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, - 0x7ffbc00c, 0x97c0fffd, 0x99000004, 0xc0120840, 0x282c0040, 0x80001ae8, 0xc0121841, 0x282c001a, - 0xcd01c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04200004, 0xcec0001b, 0xd8400021, - 0x0a200001, 0x9a00ffff, 0xc425c07f, 0x166c001f, 0x04200004, 0x9ac0fffb, 0xc434000f, 0x9b40ffff, - 0xd801c07f, 0xd8400013, 0xc425c07f, 0xce400078, 0xd8000034, 0x9940e66b, 0xd800004a, 0x7c408001, - 0x88000000, 0xc40c0036, 0x24d00001, 0x9900fffe, 0x18cc0021, 0xccc00047, 0xcc000046, 0xc40c0039, - 0x94c0ffff, 0xc40c003d, 0x98c0ffff, 0x7c40c001, 0x24d003ff, 0x18d47fea, 0x18d87ff4, 0xcd00004c, - 0xcd40004e, 0xcd80004d, 0xd8400013, 0xcd41c405, 0xc02a0001, 0x2aa80001, 0xce800013, 0xcd01c406, - 0xcc01c406, 0xcc01c406, 0xc40c0006, 0x98c0ffff, 0xc414000e, 0x29540008, 0x295c0001, 0xcd400013, - 0xd8c1325e, 0xcdc0001a, 0x11980002, 0x4110000c, 0xc0160800, 0x7d15000a, 0xc0164010, 0xd8400013, - 0xcd41c078, 0xcc01c080, 0xcc01c081, 0xcd81c082, 0xcc01c083, 0xcd01c084, 0xc40c0006, 0x98c0ffff, - 0xd8400048, 0xc40c003b, 0x94c0ffff, 0x80000c16, 0xd8400013, 0xd801c40a, 0xd901c40d, 0xd801c410, - 0xd801c40e, 0xd801c40f, 0xc40c0040, 0x04140001, 0x09540001, 0x9940ffff, 0x04140096, 0xd8400013, - 0xccc1c400, 0xc411c401, 0x9500fffa, 0xc424003e, 0x04d00001, 0x11100002, 0xcd01c40c, 0xc0180034, - 0xcd81c411, 0xd841c414, 0x0a540001, 0xcd41c412, 0x2468000f, 0xc419c416, 0x41980003, 0xc41c003f, - 0x7dda0001, 0x12200002, 0x10cc0002, 0xccc1c40c, 0xd901c411, 0xce41c412, 0xd8800013, 0xce292e40, - 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xc43c0007, 0xdc120000, 0x31144000, - 0x95400005, 0xdc030000, 0xd800002a, 0xcc3c000c, 0x80001b70, 0x33f80003, 0xd4400078, 0x9780e601, - 0x188cfff0, 0x04e40002, 0x80001190, 0x7c408001, 0x88000000, 0xc424005e, 0x96400006, 0x90000000, - 0xc424005e, 0x96400003, 0x7c408001, 0x88000000, 0x80001b74, 0x80000168, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, - 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 7440 -}; - -static const PWR_DFY_Section pwr_virus_section4 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x54106500, - .dfy_data = { - 0x7e000200, 0x7e020204, 0xc00a0505, 0x00000000, 0xbf8c007f, 0xb8900904, 0xb8911a04, 0xb8920304, - 0xb8930b44, 0x921c0d0c, 0x921c1c13, 0x921d0c12, 0x811c1d1c, 0x811c111c, 0x921cff1c, 0x00000400, - 0x921dff10, 0x00000100, 0x81181d1c, 0x7e040218, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, - 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 240 -}; - -static const PWR_DFY_Section pwr_virus_section5 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x54106900, - .dfy_data = { - 0x7e080200, 0x7e100204, 0xbefc00ff, 0x00010000, 0x24200087, 0x262200ff, 0x000001f0, 0x20222282, - 0x28182111, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, - 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, - 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, - 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, - 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, - 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, - 0x1100000c, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 384 -}; - -static const PWR_DFY_Section pwr_virus_section6 = { - .dfy_cntl = 0x80000004, - .dfy_addr_hi = 0x000000b4, - .dfy_addr_lo = 0x54116f00, - .dfy_data = { - 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4540fe8, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000041, 0x0000000c, 0x00000000, 0x07808000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x54116f00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, - 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, - 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb454105e, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x000000c0, 0x00000010, 0x00000000, 0x07808000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x54117300, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, - 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, - 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541065, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x0000001c, 0x00000000, 0x07808000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x54117700, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, - 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, - 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541069, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000444, 0x0000008a, 0x00000000, 0x07808000, 0xffffffff, - 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, - 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x54117b00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, - 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, - 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }, - .dfy_size = 1024 -}; - -static const PWR_Command_Table pwr_virus_table_post[] = { - { 0x00000000, mmCP_MEC_CNTL }, - { 0x00000000, mmCP_MEC_CNTL }, - { 0x00000004, mmSRBM_GFX_CNTL }, - { 0x54116f00, mmCP_MQD_BASE_ADDR }, - { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { 0xb4540fef, mmCP_HQD_PQ_BASE }, - { 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { 0x00010000, mmCP_HQD_VMID }, - { 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { 0x00000005, mmSRBM_GFX_CNTL }, - { 0x54117300, mmCP_MQD_BASE_ADDR }, - { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { 0xb4540fef, mmCP_HQD_PQ_BASE }, - { 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { 0x00010000, mmCP_HQD_VMID }, - { 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { 0x00000006, mmSRBM_GFX_CNTL }, - { 0x54117700, mmCP_MQD_BASE_ADDR }, - { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { 0xb4540fef, mmCP_HQD_PQ_BASE }, - { 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { 0x00010000, mmCP_HQD_VMID }, - { 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { 0x00000007, mmSRBM_GFX_CNTL }, - { 0x54117b00, mmCP_MQD_BASE_ADDR }, - { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { 0xb4540fef, mmCP_HQD_PQ_BASE }, - { 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { 0x00010000, mmCP_HQD_VMID }, - { 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { 0x00000004, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000104, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000204, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000304, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000404, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000504, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000604, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000704, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000005, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000105, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000205, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000305, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000405, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000505, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000605, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000705, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000006, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000106, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000206, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000306, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000406, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000506, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000606, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000706, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000007, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000107, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000207, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000307, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000407, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000507, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000607, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000707, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000008, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000108, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000208, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000308, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000408, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000508, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000608, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000708, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000009, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000109, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000209, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000309, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000409, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000509, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000609, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000709, mmSRBM_GFX_CNTL }, - { 0x00000000, mmCP_HQD_ACTIVE }, - { 0x00000000, mmCP_HQD_PQ_RPTR }, - { 0x00000000, mmCP_HQD_PQ_WPTR }, - { 0x00000001, mmCP_HQD_ACTIVE }, - { 0x00000004, mmSRBM_GFX_CNTL }, - { 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, - { 0x00000000, mmGRBM_STATUS }, - { 0x00000000, mmGRBM_STATUS }, - { 0x00000000, mmGRBM_STATUS }, - { 0x00000000, 0xFFFFFFFF }, -}; - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h deleted file mode 100644 index a5f2227a3971..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/power_state.h +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2015 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 PP_POWERSTATE_H -#define PP_POWERSTATE_H - -struct pp_hw_power_state { - unsigned int magic; -}; - -struct pp_power_state; - - -#define PP_INVALID_POWER_STATE_ID (0) - - -/* - * An item of a list containing Power States. - */ - -struct PP_StateLinkedList { - struct pp_power_state *next; - struct pp_power_state *prev; -}; - - -enum PP_StateUILabel { - PP_StateUILabel_None, - PP_StateUILabel_Battery, - PP_StateUILabel_MiddleLow, - PP_StateUILabel_Balanced, - PP_StateUILabel_MiddleHigh, - PP_StateUILabel_Performance, - PP_StateUILabel_BACO -}; - -enum PP_StateClassificationFlag { - PP_StateClassificationFlag_Boot = 0x0001, - PP_StateClassificationFlag_Thermal = 0x0002, - PP_StateClassificationFlag_LimitedPowerSource = 0x0004, - PP_StateClassificationFlag_Rest = 0x0008, - PP_StateClassificationFlag_Forced = 0x0010, - PP_StateClassificationFlag_User3DPerformance = 0x0020, - PP_StateClassificationFlag_User2DPerformance = 0x0040, - PP_StateClassificationFlag_3DPerformance = 0x0080, - PP_StateClassificationFlag_ACOverdriveTemplate = 0x0100, - PP_StateClassificationFlag_Uvd = 0x0200, - PP_StateClassificationFlag_3DPerformanceLow = 0x0400, - PP_StateClassificationFlag_ACPI = 0x0800, - PP_StateClassificationFlag_HD2 = 0x1000, - PP_StateClassificationFlag_UvdHD = 0x2000, - PP_StateClassificationFlag_UvdSD = 0x4000, - PP_StateClassificationFlag_UserDCPerformance = 0x8000, - PP_StateClassificationFlag_DCOverdriveTemplate = 0x10000, - PP_StateClassificationFlag_BACO = 0x20000, - PP_StateClassificationFlag_LimitedPowerSource_2 = 0x40000, - PP_StateClassificationFlag_ULV = 0x80000, - PP_StateClassificationFlag_UvdMVC = 0x100000, -}; - -typedef unsigned int PP_StateClassificationFlags; - -struct PP_StateClassificationBlock { - enum PP_StateUILabel ui_label; - enum PP_StateClassificationFlag flags; - int bios_index; - bool temporary_state; - bool to_be_deleted; -}; - -struct PP_StatePcieBlock { - unsigned int lanes; -}; - -enum PP_RefreshrateSource { - PP_RefreshrateSource_EDID, - PP_RefreshrateSource_Explicit -}; - -struct PP_StateDisplayBlock { - bool disableFrameModulation; - bool limitRefreshrate; - enum PP_RefreshrateSource refreshrateSource; - int explicitRefreshrate; - int edidRefreshrateIndex; - bool enableVariBright; -}; - -struct PP_StateMemroyBlock { - bool dllOff; - uint8_t m3arb; - uint8_t unused[3]; -}; - -struct PP_StateSoftwareAlgorithmBlock { - bool disableLoadBalancing; - bool enableSleepForTimestamps; -}; - -#define PP_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 - -/** - * Type to hold a temperature range. - */ -struct PP_TemperatureRange { - int min; - int max; - int edge_emergency_max; - int hotspot_min; - int hotspot_crit_max; - int hotspot_emergency_max; - int mem_min; - int mem_crit_max; - int mem_emergency_max; -}; - -struct PP_StateValidationBlock { - bool singleDisplayOnly; - bool disallowOnDC; - uint8_t supportedPowerLevels; -}; - -struct PP_UVD_CLOCKS { - uint32_t VCLK; - uint32_t DCLK; -}; - -/** -* Structure to hold a PowerPlay Power State. -*/ -struct pp_power_state { - uint32_t id; - struct PP_StateLinkedList orderedList; - struct PP_StateLinkedList allStatesList; - - struct PP_StateClassificationBlock classification; - struct PP_StateValidationBlock validation; - struct PP_StatePcieBlock pcie; - struct PP_StateDisplayBlock display; - struct PP_StateMemroyBlock memory; - struct PP_TemperatureRange temperatures; - struct PP_StateSoftwareAlgorithmBlock software; - struct PP_UVD_CLOCKS uvd_clocks; - struct pp_hw_power_state hardware; -}; - -enum PP_MMProfilingState { - PP_MMProfilingState_NA = 0, - PP_MMProfilingState_Started, - PP_MMProfilingState_Stopped -}; - -struct pp_clock_engine_request { - unsigned long client_type; - unsigned long ctx_id; - uint64_t context_handle; - unsigned long sclk; - unsigned long sclk_hard_min; - unsigned long mclk; - unsigned long iclk; - unsigned long evclk; - unsigned long ecclk; - unsigned long ecclk_hard_min; - unsigned long vclk; - unsigned long dclk; - unsigned long sclk_over_drive; - unsigned long mclk_over_drive; - unsigned long sclk_threshold; - unsigned long flag; - unsigned long vclk_ceiling; - unsigned long dclk_ceiling; - unsigned long num_cus; - unsigned long pm_flag; - enum PP_MMProfilingState mm_profiling_state; -}; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h deleted file mode 100644 index cea65093b6ad..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h +++ /dev/null @@ -1,62 +0,0 @@ - -/* - * Copyright 2015 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 PP_DEBUG_H -#define PP_DEBUG_H - -#ifdef pr_fmt -#undef pr_fmt -#endif - -#define pr_fmt(fmt) "amdgpu: [powerplay] " fmt - -#include -#include -#include - -#define PP_ASSERT_WITH_CODE(cond, msg, code) \ - do { \ - if (!(cond)) { \ - pr_warn_ratelimited("%s\n", msg); \ - code; \ - } \ - } while (0) - -#define PP_ASSERT(cond, msg) \ - do { \ - if (!(cond)) { \ - pr_warn_ratelimited("%s\n", msg); \ - } \ - } while (0) - -#define PP_DBG_LOG(fmt, ...) \ - do { \ - pr_debug(fmt, ##__VA_ARGS__); \ - } while (0) - - -#define GET_FLEXIBLE_ARRAY_MEMBER_ADDR(type, member, ptr, n) \ - (type *)((char *)&(ptr)->member + (sizeof(type) * (n))) - -#endif /* PP_DEBUG_H */ - diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_endian.h b/drivers/gpu/drm/amd/powerplay/inc/pp_endian.h deleted file mode 100644 index f49d1963fe85..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_endian.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2016 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 _PP_ENDIAN_H_ -#define _PP_ENDIAN_H_ - -#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X) -#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X) - -#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X) -#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X) - -#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X)) -#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X)) - -#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X)) - -#endif /* _PP_ENDIAN_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h b/drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h deleted file mode 100644 index 3e30768f9e1c..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_thermal.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2018 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 PP_THERMAL_H -#define PP_THERMAL_H - -#include "power_state.h" - -static const struct PP_TemperatureRange SMU7ThermalWithDelayPolicy[] = -{ - {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, - { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, -}; - -static const struct PP_TemperatureRange SMU7ThermalPolicy[] = -{ - {-273150, 99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000}, - { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000}, -}; - -#define CTF_OFFSET_EDGE 5 -#define CTF_OFFSET_HOTSPOT 5 -#define CTF_OFFSET_HBM 5 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h b/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h deleted file mode 100644 index c067e0925b6b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2015 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 _PP_INTERRUPT_H_ -#define _PP_INTERRUPT_H_ - -enum amd_thermal_irq { - AMD_THERMAL_IRQ_LOW_TO_HIGH = 0, - AMD_THERMAL_IRQ_HIGH_TO_LOW, - - AMD_THERMAL_IRQ_LAST -}; - -/* The type of the interrupt callback functions in PowerPlay */ -typedef int (*irq_handler_func_t)(void *private_data, - unsigned src_id, const uint32_t *iv_entry); - -/* Event Manager action chain list information */ -struct pp_interrupt_registration_info { - irq_handler_func_t call_back; /* Pointer to callback function */ - void *context; /* Pointer to callback function context */ - uint32_t src_id; /* Registered interrupt id */ - const uint32_t *iv_entry; -}; - -#endif /* _PP_INTERRUPT_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h deleted file mode 100644 index df4677da736c..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef RAVEN_PP_SMC_H -#define RAVEN_PP_SMC_H - -#pragma pack(push, 1) - -#define PPSMC_Result_OK 0x1 -#define PPSMC_Result_Failed 0xFF -#define PPSMC_Result_UnknownCmd 0xFE -#define PPSMC_Result_CmdRejectedPrereq 0xFD -#define PPSMC_Result_CmdRejectedBusy 0xFC - -#define PPSMC_MSG_TestMessage 0x1 -#define PPSMC_MSG_GetSmuVersion 0x2 -#define PPSMC_MSG_GetDriverIfVersion 0x3 -#define PPSMC_MSG_PowerUpGfx 0x6 -#define PPSMC_MSG_EnableGfxOff 0x7 -#define PPSMC_MSG_DisableGfxOff 0x8 -#define PPSMC_MSG_PowerDownIspByTile 0x9 -#define PPSMC_MSG_PowerUpIspByTile 0xA -#define PPSMC_MSG_PowerDownVcn 0xB -#define PPSMC_MSG_PowerUpVcn 0xC -#define PPSMC_MSG_PowerDownSdma 0xD -#define PPSMC_MSG_PowerUpSdma 0xE -#define PPSMC_MSG_SetHardMinIspclkByFreq 0xF -#define PPSMC_MSG_SetHardMinVcn 0x10 -#define PPSMC_MSG_SetMinDisplayClock 0x11 -#define PPSMC_MSG_SetHardMinFclkByFreq 0x12 -#define PPSMC_MSG_SetAllowFclkSwitch 0x13 -#define PPSMC_MSG_SetMinVideoGfxclkFreq 0x14 -#define PPSMC_MSG_ActiveProcessNotify 0x15 -#define PPSMC_MSG_SetCustomPolicy 0x16 -#define PPSMC_MSG_SetVideoFps 0x17 -#define PPSMC_MSG_SetDisplayCount 0x18 -#define PPSMC_MSG_QueryPowerLimit 0x19 -#define PPSMC_MSG_SetDriverDramAddrHigh 0x1A -#define PPSMC_MSG_SetDriverDramAddrLow 0x1B -#define PPSMC_MSG_TransferTableSmu2Dram 0x1C -#define PPSMC_MSG_TransferTableDram2Smu 0x1D -#define PPSMC_MSG_DeviceDriverReset 0x1E -#define PPSMC_MSG_SetGfxclkOverdriveByFreqVid 0x1F -#define PPSMC_MSG_SetHardMinDcefclkByFreq 0x20 -#define PPSMC_MSG_SetHardMinSocclkByFreq 0x21 -#define PPSMC_MSG_SetMinVddcrSocVoltage 0x22 -#define PPSMC_MSG_SetMinVideoFclkFreq 0x23 -#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x24 -#define PPSMC_MSG_ForcePowerDownGfx 0x25 -#define PPSMC_MSG_SetPhyclkVoltageByFreq 0x26 -#define PPSMC_MSG_SetDppclkVoltageByFreq 0x27 -#define PPSMC_MSG_SetSoftMinVcn 0x28 -#define PPSMC_MSG_GetGfxclkFrequency 0x2A -#define PPSMC_MSG_GetFclkFrequency 0x2B -#define PPSMC_MSG_GetMinGfxclkFrequency 0x2C -#define PPSMC_MSG_GetMaxGfxclkFrequency 0x2D -#define PPSMC_MSG_SoftReset 0x2E -#define PPSMC_MSG_SetGfxCGPG 0x2F -#define PPSMC_MSG_SetSoftMaxGfxClk 0x30 -#define PPSMC_MSG_SetHardMinGfxClk 0x31 -#define PPSMC_MSG_SetSoftMaxSocclkByFreq 0x32 -#define PPSMC_MSG_SetSoftMaxFclkByFreq 0x33 -#define PPSMC_MSG_SetSoftMaxVcn 0x34 -#define PPSMC_MSG_PowerGateMmHub 0x35 -#define PPSMC_MSG_SetRccPfcPmeRestoreRegister 0x36 -#define PPSMC_Message_Count 0x37 - -typedef uint16_t PPSMC_Result; -typedef int PPSMC_Msg; - - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu10.h b/drivers/gpu/drm/amd/powerplay/inc/smu10.h deleted file mode 100644 index b96520528240..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu10.h +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SMU10_H -#define SMU10_H - -#pragma pack(push, 1) - -#define ENABLE_DEBUG_FEATURES - -/* Feature Control Defines */ -#define FEATURE_CCLK_CONTROLLER_BIT 0 -#define FEATURE_FAN_CONTROLLER_BIT 1 -#define FEATURE_DATA_CALCULATION_BIT 2 -#define FEATURE_PPT_BIT 3 -#define FEATURE_TDC_BIT 4 -#define FEATURE_THERMAL_BIT 5 -#define FEATURE_FIT_BIT 6 -#define FEATURE_EDC_BIT 7 -#define FEATURE_PLL_POWER_DOWN_BIT 8 -#define FEATURE_ULV_BIT 9 -#define FEATURE_VDDOFF_BIT 10 -#define FEATURE_VCN_DPM_BIT 11 -#define FEATURE_ACP_DPM_BIT 12 -#define FEATURE_ISP_DPM_BIT 13 -#define FEATURE_FCLK_DPM_BIT 14 -#define FEATURE_SOCCLK_DPM_BIT 15 -#define FEATURE_MP0CLK_DPM_BIT 16 -#define FEATURE_LCLK_DPM_BIT 17 -#define FEATURE_SHUBCLK_DPM_BIT 18 -#define FEATURE_DCEFCLK_DPM_BIT 19 -#define FEATURE_GFX_DPM_BIT 20 -#define FEATURE_DS_GFXCLK_BIT 21 -#define FEATURE_DS_SOCCLK_BIT 22 -#define FEATURE_DS_LCLK_BIT 23 -#define FEATURE_DS_DCEFCLK_BIT 24 -#define FEATURE_DS_SHUBCLK_BIT 25 -#define FEATURE_RM_BIT 26 -#define FEATURE_S0i2_BIT 27 -#define FEATURE_WHISPER_MODE_BIT 28 -#define FEATURE_DS_FCLK_BIT 29 -#define FEATURE_DS_SMNCLK_BIT 30 -#define FEATURE_DS_MP1CLK_BIT 31 -#define FEATURE_DS_MP0CLK_BIT 32 -#define FEATURE_MGCG_BIT 33 -#define FEATURE_DS_FUSE_SRAM_BIT 34 -#define FEATURE_GFX_CKS 35 -#define FEATURE_PSI0_BIT 36 -#define FEATURE_PROCHOT_BIT 37 -#define FEATURE_CPUOFF_BIT 38 -#define FEATURE_STAPM_BIT 39 -#define FEATURE_CORE_CSTATES_BIT 40 -#define FEATURE_SPARE_41_BIT 41 -#define FEATURE_SPARE_42_BIT 42 -#define FEATURE_SPARE_43_BIT 43 -#define FEATURE_SPARE_44_BIT 44 -#define FEATURE_SPARE_45_BIT 45 -#define FEATURE_SPARE_46_BIT 46 -#define FEATURE_SPARE_47_BIT 47 -#define FEATURE_SPARE_48_BIT 48 -#define FEATURE_SPARE_49_BIT 49 -#define FEATURE_SPARE_50_BIT 50 -#define FEATURE_SPARE_51_BIT 51 -#define FEATURE_SPARE_52_BIT 52 -#define FEATURE_SPARE_53_BIT 53 -#define FEATURE_SPARE_54_BIT 54 -#define FEATURE_SPARE_55_BIT 55 -#define FEATURE_SPARE_56_BIT 56 -#define FEATURE_SPARE_57_BIT 57 -#define FEATURE_SPARE_58_BIT 58 -#define FEATURE_SPARE_59_BIT 59 -#define FEATURE_SPARE_60_BIT 60 -#define FEATURE_SPARE_61_BIT 61 -#define FEATURE_SPARE_62_BIT 62 -#define FEATURE_SPARE_63_BIT 63 - -#define NUM_FEATURES 64 - -#define FEATURE_CCLK_CONTROLLER_MASK (1 << FEATURE_CCLK_CONTROLLER_BIT) -#define FEATURE_FAN_CONTROLLER_MASK (1 << FEATURE_FAN_CONTROLLER_BIT) -#define FEATURE_DATA_CALCULATION_MASK (1 << FEATURE_DATA_CALCULATION_BIT) -#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT) -#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT) -#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT) -#define FEATURE_FIT_MASK (1 << FEATURE_FIT_BIT) -#define FEATURE_EDC_MASK (1 << FEATURE_EDC_BIT) -#define FEATURE_PLL_POWER_DOWN_MASK (1 << FEATURE_PLL_POWER_DOWN_BIT) -#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT) -#define FEATURE_VDDOFF_MASK (1 << FEATURE_VDDOFF_BIT) -#define FEATURE_VCN_DPM_MASK (1 << FEATURE_VCN_DPM_BIT) -#define FEATURE_ACP_DPM_MASK (1 << FEATURE_ACP_DPM_BIT) -#define FEATURE_ISP_DPM_MASK (1 << FEATURE_ISP_DPM_BIT) -#define FEATURE_FCLK_DPM_MASK (1 << FEATURE_FCLK_DPM_BIT) -#define FEATURE_SOCCLK_DPM_MASK (1 << FEATURE_SOCCLK_DPM_BIT) -#define FEATURE_MP0CLK_DPM_MASK (1 << FEATURE_MP0CLK_DPM_BIT) -#define FEATURE_LCLK_DPM_MASK (1 << FEATURE_LCLK_DPM_BIT) -#define FEATURE_SHUBCLK_DPM_MASK (1 << FEATURE_SHUBCLK_DPM_BIT) -#define FEATURE_DCEFCLK_DPM_MASK (1 << FEATURE_DCEFCLK_DPM_BIT) -#define FEATURE_GFX_DPM_MASK (1 << FEATURE_GFX_DPM_BIT) -#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT) -#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT) -#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT) -#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT) -#define FEATURE_DS_SHUBCLK_MASK (1 << FEATURE_DS_SHUBCLK_BIT) -#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT) -#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT) -#define FEATURE_DS_SMNCLK_MASK (1 << FEATURE_DS_SMNCLK_BIT) -#define FEATURE_DS_MP1CLK_MASK (1 << FEATURE_DS_MP1CLK_BIT) -#define FEATURE_DS_MP0CLK_MASK (1 << FEATURE_DS_MP0CLK_BIT) -#define FEATURE_MGCG_MASK (1 << FEATURE_MGCG_BIT) -#define FEATURE_DS_FUSE_SRAM_MASK (1 << FEATURE_DS_FUSE_SRAM_BIT) -#define FEATURE_PSI0_MASK (1 << FEATURE_PSI0_BIT) -#define FEATURE_STAPM_MASK (1 << FEATURE_STAPM_BIT) -#define FEATURE_PROCHOT_MASK (1 << FEATURE_PROCHOT_BIT) -#define FEATURE_CPUOFF_MASK (1 << FEATURE_CPUOFF_BIT) -#define FEATURE_CORE_CSTATES_MASK (1 << FEATURE_CORE_CSTATES_BIT) - -/* Workload bits */ -#define WORKLOAD_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 -#define WORKLOAD_PPLIB_VIDEO_BIT 3 -#define WORKLOAD_PPLIB_VR_BIT 4 -#define WORKLOAD_PPLIB_COMPUTE_BIT 5 -#define WORKLOAD_PPLIB_CUSTOM_BIT 6 -#define WORKLOAD_PPLIB_COUNT 7 - -typedef struct { - /* MP1_EXT_SCRATCH0 */ - uint32_t CurrLevel_ACP : 4; - uint32_t CurrLevel_ISP : 4; - uint32_t CurrLevel_VCN : 4; - uint32_t CurrLevel_LCLK : 4; - uint32_t CurrLevel_MP0CLK : 4; - uint32_t CurrLevel_FCLK : 4; - uint32_t CurrLevel_SOCCLK : 4; - uint32_t CurrLevel_DCEFCLK : 4; - /* MP1_EXT_SCRATCH1 */ - uint32_t TargLevel_ACP : 4; - uint32_t TargLevel_ISP : 4; - uint32_t TargLevel_VCN : 4; - uint32_t TargLevel_LCLK : 4; - uint32_t TargLevel_MP0CLK : 4; - uint32_t TargLevel_FCLK : 4; - uint32_t TargLevel_SOCCLK : 4; - uint32_t TargLevel_DCEFCLK : 4; - /* MP1_EXT_SCRATCH2 */ - uint32_t CurrLevel_SHUBCLK : 4; - uint32_t TargLevel_SHUBCLK : 4; - uint32_t InUlv : 1; - uint32_t InS0i2 : 1; - uint32_t InWhisperMode : 1; - uint32_t Reserved : 21; - /* MP1_EXT_SCRATCH3-4 */ - uint32_t Reserved2[2]; - /* MP1_EXT_SCRATCH5 */ - uint32_t FeatureStatus[NUM_FEATURES / 32]; -} FwStatus_t; - -#define TABLE_BIOS_IF 0 /* Called by BIOS */ -#define TABLE_WATERMARKS 1 /* Called by Driver */ -#define TABLE_CUSTOM_DPM 2 /* Called by Driver */ -#define TABLE_PMSTATUSLOG 3 /* Called by Tools for Agm logging */ -#define TABLE_DPMCLOCKS 4 /* Called by Driver */ -#define TABLE_MOMENTARY_PM 5 /* Called by Tools */ -#define TABLE_COUNT 6 - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h deleted file mode 100644 index dea8fe93da63..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu10_driver_if.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SMU10_DRIVER_IF_H -#define SMU10_DRIVER_IF_H - -#define SMU10_DRIVER_IF_VERSION 0x6 - -#define NUM_DSPCLK_LEVELS 8 - -typedef struct { - int32_t value; - uint32_t numFractionalBits; -} FloatInIntFormat_t; - -typedef enum { - DSPCLK_DCEFCLK = 0, - DSPCLK_DISPCLK, - DSPCLK_PIXCLK, - DSPCLK_PHYCLK, - DSPCLK_COUNT, -} DSPCLK_e; - -typedef struct { - uint16_t Freq; - uint16_t Vid; -} DisplayClockTable_t; - - -typedef struct { - uint16_t MinClock; /* This is either DCFCLK or SOCCLK (in MHz) */ - uint16_t MaxClock; /* This is either DCFCLK or SOCCLK (in MHz) */ - uint16_t MinMclk; - uint16_t MaxMclk; - - uint8_t WmSetting; - uint8_t Padding[3]; -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCFCLK, - WM_COUNT, -} WM_CLOCK_e; - -typedef struct { - WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; - uint32_t MmHubPadding[7]; -} Watermarks_t; - -typedef enum { - CUSTOM_DPM_SETTING_GFXCLK, - CUSTOM_DPM_SETTING_CCLK, - CUSTOM_DPM_SETTING_FCLK_CCX, - CUSTOM_DPM_SETTING_FCLK_GFX, - CUSTOM_DPM_SETTING_FCLK_STALLS, - CUSTOM_DPM_SETTING_LCLK, - CUSTOM_DPM_SETTING_COUNT, -} CUSTOM_DPM_SETTING_e; - -typedef struct { - uint8_t ActiveHystLimit; - uint8_t IdleHystLimit; - uint8_t FPS; - uint8_t MinActiveFreqType; - FloatInIntFormat_t MinActiveFreq; - FloatInIntFormat_t PD_Data_limit; - FloatInIntFormat_t PD_Data_time_constant; - FloatInIntFormat_t PD_Data_error_coeff; - FloatInIntFormat_t PD_Data_error_rate_coeff; -} DpmActivityMonitorCoeffExt_t; - -typedef struct { - DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT]; -} CustomDpmSettings_t; - -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 4 -#define NUM_FCLK_DPM_LEVELS 4 -#define NUM_MEMCLK_DPM_LEVELS 4 - -typedef struct { - uint32_t Freq; /* In MHz */ - uint32_t Vol; /* Millivolts with 2 fractional bits */ -} DpmClock_t; - -typedef struct { - DpmClock_t DcefClocks[NUM_DCEFCLK_DPM_LEVELS]; - DpmClock_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; - DpmClock_t FClocks[NUM_FCLK_DPM_LEVELS]; - DpmClock_t MemClocks[NUM_MEMCLK_DPM_LEVELS]; -} DpmClocks_t; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h deleted file mode 100644 index fdc6b7a57bc9..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h +++ /dev/null @@ -1,893 +0,0 @@ -/* - * Copyright 2018 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 SMU11_DRIVER_IF_H -#define SMU11_DRIVER_IF_H - -// *** IMPORTANT *** -// SMU TEAM: Always increment the interface version if -// any structure is changed in this file -// Be aware of that the version should be updated in -// smu_v11_0.h, rename is also needed. -// #define SMU11_DRIVER_IF_VERSION 0x13 - -#define PPTABLE_V20_SMU_VERSION 3 - -#define NUM_GFXCLK_DPM_LEVELS 16 -#define NUM_VCLK_DPM_LEVELS 8 -#define NUM_DCLK_DPM_LEVELS 8 -#define NUM_ECLK_DPM_LEVELS 8 -#define NUM_MP0CLK_DPM_LEVELS 2 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_UCLK_DPM_LEVELS 4 -#define NUM_FCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 8 -#define NUM_DISPCLK_DPM_LEVELS 8 -#define NUM_PIXCLK_DPM_LEVELS 8 -#define NUM_PHYCLK_DPM_LEVELS 8 -#define NUM_LINK_LEVELS 2 -#define NUM_XGMI_LEVELS 2 - -#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) -#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) -#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) -#define MAX_ECLK_DPM_LEVEL (NUM_ECLK_DPM_LEVELS - 1) -#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) -#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) -#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) -#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) -#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) -#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) -#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) -#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) -#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) -#define MAX_XGMI_LEVEL (NUM_XGMI_LEVELS - 1) - -#define PPSMC_GeminiModeNone 0 -#define PPSMC_GeminiModeMaster 1 -#define PPSMC_GeminiModeSlave 2 - - -#define FEATURE_DPM_PREFETCHER_BIT 0 -#define FEATURE_DPM_GFXCLK_BIT 1 -#define FEATURE_DPM_UCLK_BIT 2 -#define FEATURE_DPM_SOCCLK_BIT 3 -#define FEATURE_DPM_UVD_BIT 4 -#define FEATURE_DPM_VCE_BIT 5 -#define FEATURE_ULV_BIT 6 -#define FEATURE_DPM_MP0CLK_BIT 7 -#define FEATURE_DPM_LINK_BIT 8 -#define FEATURE_DPM_DCEFCLK_BIT 9 -#define FEATURE_DS_GFXCLK_BIT 10 -#define FEATURE_DS_SOCCLK_BIT 11 -#define FEATURE_DS_LCLK_BIT 12 -#define FEATURE_PPT_BIT 13 -#define FEATURE_TDC_BIT 14 -#define FEATURE_THERMAL_BIT 15 -#define FEATURE_GFX_PER_CU_CG_BIT 16 -#define FEATURE_RM_BIT 17 -#define FEATURE_DS_DCEFCLK_BIT 18 -#define FEATURE_ACDC_BIT 19 -#define FEATURE_VR0HOT_BIT 20 -#define FEATURE_VR1HOT_BIT 21 -#define FEATURE_FW_CTF_BIT 22 -#define FEATURE_LED_DISPLAY_BIT 23 -#define FEATURE_FAN_CONTROL_BIT 24 -#define FEATURE_GFX_EDC_BIT 25 -#define FEATURE_GFXOFF_BIT 26 -#define FEATURE_CG_BIT 27 -#define FEATURE_DPM_FCLK_BIT 28 -#define FEATURE_DS_FCLK_BIT 29 -#define FEATURE_DS_MP1CLK_BIT 30 -#define FEATURE_DS_MP0CLK_BIT 31 -#define FEATURE_XGMI_BIT 32 -#define FEATURE_ECC_BIT 33 -#define FEATURE_SPARE_34_BIT 34 -#define FEATURE_SPARE_35_BIT 35 -#define FEATURE_SPARE_36_BIT 36 -#define FEATURE_SPARE_37_BIT 37 -#define FEATURE_SPARE_38_BIT 38 -#define FEATURE_SPARE_39_BIT 39 -#define FEATURE_SPARE_40_BIT 40 -#define FEATURE_SPARE_41_BIT 41 -#define FEATURE_SPARE_42_BIT 42 -#define FEATURE_SPARE_43_BIT 43 -#define FEATURE_SPARE_44_BIT 44 -#define FEATURE_SPARE_45_BIT 45 -#define FEATURE_SPARE_46_BIT 46 -#define FEATURE_SPARE_47_BIT 47 -#define FEATURE_SPARE_48_BIT 48 -#define FEATURE_SPARE_49_BIT 49 -#define FEATURE_SPARE_50_BIT 50 -#define FEATURE_SPARE_51_BIT 51 -#define FEATURE_SPARE_52_BIT 52 -#define FEATURE_SPARE_53_BIT 53 -#define FEATURE_SPARE_54_BIT 54 -#define FEATURE_SPARE_55_BIT 55 -#define FEATURE_SPARE_56_BIT 56 -#define FEATURE_SPARE_57_BIT 57 -#define FEATURE_SPARE_58_BIT 58 -#define FEATURE_SPARE_59_BIT 59 -#define FEATURE_SPARE_60_BIT 60 -#define FEATURE_SPARE_61_BIT 61 -#define FEATURE_SPARE_62_BIT 62 -#define FEATURE_SPARE_63_BIT 63 - -#define NUM_FEATURES 64 - -#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) -#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) -#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) -#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) -#define FEATURE_DPM_UVD_MASK (1 << FEATURE_DPM_UVD_BIT ) -#define FEATURE_DPM_VCE_MASK (1 << FEATURE_DPM_VCE_BIT ) -#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT ) -#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) -#define FEATURE_DPM_LINK_MASK (1 << FEATURE_DPM_LINK_BIT ) -#define FEATURE_DPM_DCEFCLK_MASK (1 << FEATURE_DPM_DCEFCLK_BIT ) -#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) -#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) -#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) -#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) -#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) -#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) -#define FEATURE_GFX_PER_CU_CG_MASK (1 << FEATURE_GFX_PER_CU_CG_BIT ) -#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT ) -#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT ) -#define FEATURE_ACDC_MASK (1 << FEATURE_ACDC_BIT ) -#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) -#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) -#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) -#define FEATURE_LED_DISPLAY_MASK (1 << FEATURE_LED_DISPLAY_BIT ) -#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) -#define FEATURE_GFX_EDC_MASK (1 << FEATURE_GFX_EDC_BIT ) -#define FEATURE_GFXOFF_MASK (1 << FEATURE_GFXOFF_BIT ) -#define FEATURE_CG_MASK (1 << FEATURE_CG_BIT ) -#define FEATURE_DPM_FCLK_MASK (1 << FEATURE_DPM_FCLK_BIT ) -#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT ) -#define FEATURE_DS_MP1CLK_MASK (1 << FEATURE_DS_MP1CLK_BIT ) -#define FEATURE_DS_MP0CLK_MASK (1 << FEATURE_DS_MP0CLK_BIT ) -#define FEATURE_XGMI_MASK (1ULL << FEATURE_XGMI_BIT ) -#define FEATURE_ECC_MASK (1ULL << FEATURE_ECC_BIT ) - -#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 -#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_SOCCLK 0x00000004 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_UCLK 0x00000008 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000010 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_UCLK 0x00000020 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000040 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_UCLK 0x00000080 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_SOCCLK 0x00000100 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_UCLK 0x00000200 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_SOCCLK 0x00000400 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_UCLK 0x00000800 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00001000 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00002000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_GFXCLK_SWITCH 0x00004000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_SOCCLK_SWITCH 0x00008000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_UCLK_SWITCH 0x00010000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_FCLK_SWITCH 0x00020000 - -#define I2C_CONTROLLER_ENABLED 1 -#define I2C_CONTROLLER_DISABLED 0 - -#define VR_MAPPING_VR_SELECT_MASK 0x01 -#define VR_MAPPING_VR_SELECT_SHIFT 0x00 - -#define VR_MAPPING_PLANE_SELECT_MASK 0x02 -#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 - - -#define PSI_SEL_VR0_PLANE0_PSI0 0x01 -#define PSI_SEL_VR0_PLANE0_PSI1 0x02 -#define PSI_SEL_VR0_PLANE1_PSI0 0x04 -#define PSI_SEL_VR0_PLANE1_PSI1 0x08 -#define PSI_SEL_VR1_PLANE0_PSI0 0x10 -#define PSI_SEL_VR1_PLANE0_PSI1 0x20 -#define PSI_SEL_VR1_PLANE1_PSI0 0x40 -#define PSI_SEL_VR1_PLANE1_PSI1 0x80 - - -#define THROTTLER_STATUS_PADDING_BIT 0 -#define THROTTLER_STATUS_TEMP_EDGE_BIT 1 -#define THROTTLER_STATUS_TEMP_HOTSPOT_BIT 2 -#define THROTTLER_STATUS_TEMP_HBM_BIT 3 -#define THROTTLER_STATUS_TEMP_VR_GFX_BIT 4 -#define THROTTLER_STATUS_TEMP_VR_SOC_BIT 5 -#define THROTTLER_STATUS_TEMP_VR_MEM0_BIT 6 -#define THROTTLER_STATUS_TEMP_VR_MEM1_BIT 7 -#define THROTTLER_STATUS_TEMP_LIQUID_BIT 8 -#define THROTTLER_STATUS_TEMP_PLX_BIT 9 -#define THROTTLER_STATUS_TEMP_SKIN_BIT 10 -#define THROTTLER_STATUS_TDC_GFX_BIT 11 -#define THROTTLER_STATUS_TDC_SOC_BIT 12 -#define THROTTLER_STATUS_PPT_BIT 13 -#define THROTTLER_STATUS_FIT_BIT 14 -#define THROTTLER_STATUS_PPM_BIT 15 - - -#define TABLE_TRANSFER_OK 0x0 -#define TABLE_TRANSFER_FAILED 0xFF - - -#define WORKLOAD_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 -#define WORKLOAD_PPLIB_VIDEO_BIT 3 -#define WORKLOAD_PPLIB_VR_BIT 4 -#define WORKLOAD_PPLIB_COMPUTE_BIT 5 -#define WORKLOAD_PPLIB_CUSTOM_BIT 6 -#define WORKLOAD_PPLIB_COUNT 7 - - -#define XGMI_STATE_D0 1 -#define XGMI_STATE_D3 0 - -typedef enum { - I2C_CONTROLLER_PORT_0 = 0, - I2C_CONTROLLER_PORT_1 = 1, -} I2cControllerPort_e; - -typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_VDDCI, - I2C_CONTROLLER_NAME_VR_HBM, - I2C_CONTROLLER_NAME_LIQUID_0, - I2C_CONTROLLER_NAME_LIQUID_1, - I2C_CONTROLLER_NAME_PLX, - I2C_CONTROLLER_NAME_COUNT, -} I2cControllerName_e; - -typedef enum { - I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, - I2C_CONTROLLER_THROTTLER_VR_GFX, - I2C_CONTROLLER_THROTTLER_VR_SOC, - I2C_CONTROLLER_THROTTLER_VR_VDDCI, - I2C_CONTROLLER_THROTTLER_VR_HBM, - I2C_CONTROLLER_THROTTLER_LIQUID_0, - I2C_CONTROLLER_THROTTLER_LIQUID_1, - I2C_CONTROLLER_THROTTLER_PLX, -} I2cControllerThrottler_e; - -typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, - I2C_CONTROLLER_PROTOCOL_VR_IR35217, - I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, - I2C_CONTROLLER_PROTOCOL_SPARE_0, - I2C_CONTROLLER_PROTOCOL_SPARE_1, - I2C_CONTROLLER_PROTOCOL_SPARE_2, -} I2cControllerProtocol_e; - -typedef enum { - I2C_CONTROLLER_SPEED_SLOW = 0, - I2C_CONTROLLER_SPEED_FAST = 1, -} I2cControllerSpeed_e; - -typedef struct { - uint32_t Enabled; - uint32_t SlaveAddress; - uint32_t ControllerPort; - uint32_t ControllerName; - - uint32_t ThermalThrottler; - uint32_t I2cProtocol; - uint32_t I2cSpeed; -} I2cControllerConfig_t; - -typedef struct { - uint32_t a; - uint32_t b; - uint32_t c; -} QuadraticInt_t; - -typedef struct { - uint32_t m; - uint32_t b; -} LinearInt_t; - -typedef struct { - uint32_t a; - uint32_t b; - uint32_t c; -} DroopInt_t; - -typedef enum { - PPCLK_GFXCLK, - PPCLK_VCLK, - PPCLK_DCLK, - PPCLK_ECLK, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_DCEFCLK, - PPCLK_DISPCLK, - PPCLK_PIXCLK, - PPCLK_PHYCLK, - PPCLK_FCLK, - PPCLK_COUNT, -} PPCLK_e; - -typedef enum { - POWER_SOURCE_AC, - POWER_SOURCE_DC, - POWER_SOURCE_COUNT, -} POWER_SOURCE_e; - -typedef enum { - VOLTAGE_MODE_AVFS = 0, - VOLTAGE_MODE_AVFS_SS, - VOLTAGE_MODE_SS, - VOLTAGE_MODE_COUNT, -} VOLTAGE_MODE_e; - - -typedef enum { - AVFS_VOLTAGE_GFX = 0, - AVFS_VOLTAGE_SOC, - AVFS_VOLTAGE_COUNT, -} AVFS_VOLTAGE_TYPE_e; - - -typedef struct { - uint8_t VoltageMode; - uint8_t SnapToDiscrete; - uint8_t NumDiscreteLevels; - uint8_t padding; - LinearInt_t ConversionToAvfsClk; - QuadraticInt_t SsCurve; -} DpmDescriptor_t; - -typedef struct { - uint32_t Version; - - - uint32_t FeaturesToRun[2]; - - - uint16_t SocketPowerLimitAc0; - uint16_t SocketPowerLimitAc0Tau; - uint16_t SocketPowerLimitAc1; - uint16_t SocketPowerLimitAc1Tau; - uint16_t SocketPowerLimitAc2; - uint16_t SocketPowerLimitAc2Tau; - uint16_t SocketPowerLimitAc3; - uint16_t SocketPowerLimitAc3Tau; - uint16_t SocketPowerLimitDc; - uint16_t SocketPowerLimitDcTau; - uint16_t TdcLimitSoc; - uint16_t TdcLimitSocTau; - uint16_t TdcLimitGfx; - uint16_t TdcLimitGfxTau; - - uint16_t TedgeLimit; - uint16_t ThotspotLimit; - uint16_t ThbmLimit; - uint16_t Tvr_gfxLimit; - uint16_t Tvr_memLimit; - uint16_t Tliquid1Limit; - uint16_t Tliquid2Limit; - uint16_t TplxLimit; - uint32_t FitLimit; - - uint16_t PpmPowerLimit; - uint16_t PpmTemperatureThreshold; - - uint8_t MemoryOnPackage; - uint8_t padding8_limits; - uint16_t Tvr_SocLimit; - - uint16_t UlvVoltageOffsetSoc; - uint16_t UlvVoltageOffsetGfx; - - uint8_t UlvSmnclkDid; - uint8_t UlvMp1clkDid; - uint8_t UlvGfxclkBypass; - uint8_t Padding234; - - - uint16_t MinVoltageGfx; - uint16_t MinVoltageSoc; - uint16_t MaxVoltageGfx; - uint16_t MaxVoltageSoc; - - uint16_t LoadLineResistanceGfx; - uint16_t LoadLineResistanceSoc; - - DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; - - uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; - uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; - uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; - uint16_t FreqTableEclk [NUM_ECLK_DPM_LEVELS ]; - uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; - uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; - uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; - uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; - uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; - uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; - uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; - - uint16_t DcModeMaxFreq [PPCLK_COUNT ]; - uint16_t Padding8_Clks; - - uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; - uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; - - - uint16_t GfxclkFidle; - uint16_t GfxclkSlewRate; - uint16_t CksEnableFreq; - uint16_t Padding789; - QuadraticInt_t CksVoltageOffset; - uint8_t Padding567[4]; - uint16_t GfxclkDsMaxFreq; - uint8_t GfxclkSource; - uint8_t Padding456; - - uint8_t LowestUclkReservedForUlv; - uint8_t Padding8_Uclk[3]; - - - uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; - uint8_t PcieLaneCount[NUM_LINK_LEVELS]; - uint16_t LclkFreq[NUM_LINK_LEVELS]; - - - uint16_t EnableTdpm; - uint16_t TdpmHighHystTemperature; - uint16_t TdpmLowHystTemperature; - uint16_t GfxclkFreqHighTempLimit; - - - uint16_t FanStopTemp; - uint16_t FanStartTemp; - - uint16_t FanGainEdge; - uint16_t FanGainHotspot; - uint16_t FanGainLiquid; - uint16_t FanGainVrGfx; - uint16_t FanGainVrSoc; - uint16_t FanGainPlx; - uint16_t FanGainHbm; - uint16_t FanPwmMin; - uint16_t FanAcousticLimitRpm; - uint16_t FanThrottlingRpm; - uint16_t FanMaximumRpm; - uint16_t FanTargetTemperature; - uint16_t FanTargetGfxclk; - uint8_t FanZeroRpmEnable; - uint8_t FanTachEdgePerRev; - - - - int16_t FuzzyFan_ErrorSetDelta; - int16_t FuzzyFan_ErrorRateSetDelta; - int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; - - - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_Avfs[2]; - - QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; - DroopInt_t dBtcGbGfxCksOn; - DroopInt_t dBtcGbGfxCksOff; - DroopInt_t dBtcGbGfxAfll; - DroopInt_t dBtcGbSoc; - LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; - - QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; - - uint16_t DcTol[AVFS_VOLTAGE_COUNT]; - - uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_GfxBtc[2]; - - int16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; - uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; - - - uint8_t XgmiLinkSpeed [NUM_XGMI_LEVELS]; - uint8_t XgmiLinkWidth [NUM_XGMI_LEVELS]; - uint16_t XgmiFclkFreq [NUM_XGMI_LEVELS]; - uint16_t XgmiUclkFreq [NUM_XGMI_LEVELS]; - uint16_t XgmiSocclkFreq [NUM_XGMI_LEVELS]; - uint16_t XgmiSocVoltage [NUM_XGMI_LEVELS]; - - uint32_t DebugOverrides; - QuadraticInt_t ReservedEquation0; - QuadraticInt_t ReservedEquation1; - QuadraticInt_t ReservedEquation2; - QuadraticInt_t ReservedEquation3; - - uint16_t MinVoltageUlvGfx; - uint16_t MinVoltageUlvSoc; - - uint16_t MGpuFanBoostLimitRpm; - uint16_t padding16_Fan; - - uint16_t FanGainVrMem0; - uint16_t FanGainVrMem1; - - uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; - - uint32_t Reserved[11]; - - uint32_t Padding32[3]; - - uint16_t MaxVoltageStepGfx; - uint16_t MaxVoltageStepSoc; - - uint8_t VddGfxVrMapping; - uint8_t VddSocVrMapping; - uint8_t VddMem0VrMapping; - uint8_t VddMem1VrMapping; - - uint8_t GfxUlvPhaseSheddingMask; - uint8_t SocUlvPhaseSheddingMask; - uint8_t ExternalSensorPresent; - uint8_t Padding8_V; - - - uint16_t GfxMaxCurrent; - int8_t GfxOffset; - uint8_t Padding_TelemetryGfx; - - uint16_t SocMaxCurrent; - int8_t SocOffset; - uint8_t Padding_TelemetrySoc; - - uint16_t Mem0MaxCurrent; - int8_t Mem0Offset; - uint8_t Padding_TelemetryMem0; - - uint16_t Mem1MaxCurrent; - int8_t Mem1Offset; - uint8_t Padding_TelemetryMem1; - - - uint8_t AcDcGpio; - uint8_t AcDcPolarity; - uint8_t VR0HotGpio; - uint8_t VR0HotPolarity; - - uint8_t VR1HotGpio; - uint8_t VR1HotPolarity; - uint8_t Padding1; - uint8_t Padding2; - - - - uint8_t LedPin0; - uint8_t LedPin1; - uint8_t LedPin2; - uint8_t padding8_4; - - - uint8_t PllGfxclkSpreadEnabled; - uint8_t PllGfxclkSpreadPercent; - uint16_t PllGfxclkSpreadFreq; - - uint8_t UclkSpreadEnabled; - uint8_t UclkSpreadPercent; - uint16_t UclkSpreadFreq; - - uint8_t FclkSpreadEnabled; - uint8_t FclkSpreadPercent; - uint16_t FclkSpreadFreq; - - uint8_t FllGfxclkSpreadEnabled; - uint8_t FllGfxclkSpreadPercent; - uint16_t FllGfxclkSpreadFreq; - - I2cControllerConfig_t I2cControllers[I2C_CONTROLLER_NAME_COUNT]; - - uint32_t BoardReserved[10]; - - - uint32_t MmHubPadding[8]; - -} PPTable_t; - -typedef struct { - - uint16_t GfxclkAverageLpfTau; - uint16_t SocclkAverageLpfTau; - uint16_t UclkAverageLpfTau; - uint16_t GfxActivityLpfTau; - uint16_t UclkActivityLpfTau; - uint16_t SocketPowerLpfTau; - - - uint32_t MmHubPadding[8]; -} DriverSmuConfig_t; - -typedef struct { - - uint16_t GfxclkFmin; - uint16_t GfxclkFmax; - uint16_t GfxclkFreq1; - uint16_t GfxclkVolt1; - uint16_t GfxclkFreq2; - uint16_t GfxclkVolt2; - uint16_t GfxclkFreq3; - uint16_t GfxclkVolt3; - uint16_t UclkFmax; - int16_t OverDrivePct; - uint16_t FanMaximumRpm; - uint16_t FanMinimumPwm; - uint16_t FanTargetTemperature; - uint16_t MaxOpTemp; - uint16_t FanZeroRpmEnable; - uint16_t Padding; - -} OverDriveTable_t; - -typedef struct { - uint16_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageSocclkFrequency; - uint16_t AverageUclkFrequency ; - uint16_t AverageGfxActivity ; - uint16_t AverageUclkActivity ; - uint8_t CurrSocVoltageOffset ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t CurrSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureHBM ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrSoc ; - uint16_t TemperatureVrMem0 ; - uint16_t TemperatureVrMem1 ; - uint16_t TemperatureLiquid ; - uint16_t TemperaturePlx ; - uint32_t ThrottlerStatus ; - - uint8_t LinkDpmLevel; - uint16_t AverageSocketPower; - uint8_t Padding; - - - uint32_t MmHubPadding[7]; -} SmuMetrics_t; - -typedef struct { - uint16_t MinClock; - uint16_t MaxClock; - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Padding[3]; -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCEFCLK, - WM_COUNT_PP, -} WM_CLOCK_e; - -typedef struct { - - WatermarkRowGeneric_t WatermarkRow[WM_COUNT_PP][NUM_WM_RANGES]; - - uint32_t MmHubPadding[7]; -} Watermarks_t; - -typedef struct { - uint16_t avgPsmCount[45]; - uint16_t minPsmCount[45]; - float avgPsmVoltage[45]; - float minPsmVoltage[45]; - - uint16_t avgScsPsmCount; - uint16_t minScsPsmCount; - float avgScsPsmVoltage; - float minScsPsmVoltage; - - - uint32_t MmHubPadding[6]; -} AvfsDebugTable_t; - -typedef struct { - uint8_t AvfsVersion; - uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; - - int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; - int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; - int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; - - int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; - int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; - int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; - - int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; - int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; - int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; - - int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; - int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; - int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; - - int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; - int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; - int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; - - uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; - - uint32_t VInversion[AVFS_VOLTAGE_COUNT]; - - - int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; - int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; - int32_t P2V_b[AVFS_VOLTAGE_COUNT]; - - uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; - - uint32_t EnabledAvfsModules; - - uint32_t MmHubPadding[7]; -} AvfsFuseOverride_t; - -typedef struct { - - uint8_t Gfx_ActiveHystLimit; - uint8_t Gfx_IdleHystLimit; - uint8_t Gfx_FPS; - uint8_t Gfx_MinActiveFreqType; - uint8_t Gfx_BoosterFreqType; - uint8_t Gfx_UseRlcBusy; - uint16_t Gfx_MinActiveFreq; - uint16_t Gfx_BoosterFreq; - uint16_t Gfx_PD_Data_time_constant; - uint32_t Gfx_PD_Data_limit_a; - uint32_t Gfx_PD_Data_limit_b; - uint32_t Gfx_PD_Data_limit_c; - uint32_t Gfx_PD_Data_error_coeff; - uint32_t Gfx_PD_Data_error_rate_coeff; - - uint8_t Soc_ActiveHystLimit; - uint8_t Soc_IdleHystLimit; - uint8_t Soc_FPS; - uint8_t Soc_MinActiveFreqType; - uint8_t Soc_BoosterFreqType; - uint8_t Soc_UseRlcBusy; - uint16_t Soc_MinActiveFreq; - uint16_t Soc_BoosterFreq; - uint16_t Soc_PD_Data_time_constant; - uint32_t Soc_PD_Data_limit_a; - uint32_t Soc_PD_Data_limit_b; - uint32_t Soc_PD_Data_limit_c; - uint32_t Soc_PD_Data_error_coeff; - uint32_t Soc_PD_Data_error_rate_coeff; - - uint8_t Mem_ActiveHystLimit; - uint8_t Mem_IdleHystLimit; - uint8_t Mem_FPS; - uint8_t Mem_MinActiveFreqType; - uint8_t Mem_BoosterFreqType; - uint8_t Mem_UseRlcBusy; - uint16_t Mem_MinActiveFreq; - uint16_t Mem_BoosterFreq; - uint16_t Mem_PD_Data_time_constant; - uint32_t Mem_PD_Data_limit_a; - uint32_t Mem_PD_Data_limit_b; - uint32_t Mem_PD_Data_limit_c; - uint32_t Mem_PD_Data_error_coeff; - uint32_t Mem_PD_Data_error_rate_coeff; - - uint8_t Fclk_ActiveHystLimit; - uint8_t Fclk_IdleHystLimit; - uint8_t Fclk_FPS; - uint8_t Fclk_MinActiveFreqType; - uint8_t Fclk_BoosterFreqType; - uint8_t Fclk_UseRlcBusy; - uint16_t Fclk_MinActiveFreq; - uint16_t Fclk_BoosterFreq; - uint16_t Fclk_PD_Data_time_constant; - uint32_t Fclk_PD_Data_limit_a; - uint32_t Fclk_PD_Data_limit_b; - uint32_t Fclk_PD_Data_limit_c; - uint32_t Fclk_PD_Data_error_coeff; - uint32_t Fclk_PD_Data_error_rate_coeff; - -} DpmActivityMonitorCoeffInt_t; - -#define TABLE_PPTABLE 0 -#define TABLE_WATERMARKS 1 -#define TABLE_AVFS 2 -#define TABLE_AVFS_PSM_DEBUG 3 -#define TABLE_AVFS_FUSE_OVERRIDE 4 -#define TABLE_PMSTATUSLOG 5 -#define TABLE_SMU_METRICS 6 -#define TABLE_DRIVER_SMU_CONFIG 7 -#define TABLE_ACTIVITY_MONITOR_COEFF 8 -#define TABLE_OVERDRIVE 9 -#define TABLE_COUNT 10 - - -#define UCLK_SWITCH_SLOW 0 -#define UCLK_SWITCH_FAST 1 - - -#define SQ_Enable_MASK 0x1 -#define SQ_IR_MASK 0x2 -#define SQ_PCC_MASK 0x4 -#define SQ_EDC_MASK 0x8 - -#define TCP_Enable_MASK 0x100 -#define TCP_IR_MASK 0x200 -#define TCP_PCC_MASK 0x400 -#define TCP_EDC_MASK 0x800 - -#define TD_Enable_MASK 0x10000 -#define TD_IR_MASK 0x20000 -#define TD_PCC_MASK 0x40000 -#define TD_EDC_MASK 0x80000 - -#define DB_Enable_MASK 0x1000000 -#define DB_IR_MASK 0x2000000 -#define DB_PCC_MASK 0x4000000 -#define DB_EDC_MASK 0x8000000 - -#define SQ_Enable_SHIFT 0 -#define SQ_IR_SHIFT 1 -#define SQ_PCC_SHIFT 2 -#define SQ_EDC_SHIFT 3 - -#define TCP_Enable_SHIFT 8 -#define TCP_IR_SHIFT 9 -#define TCP_PCC_SHIFT 10 -#define TCP_EDC_SHIFT 11 - -#define TD_Enable_SHIFT 16 -#define TD_IR_SHIFT 17 -#define TD_PCC_SHIFT 18 -#define TD_EDC_SHIFT 19 - -#define DB_Enable_SHIFT 24 -#define DB_IR_SHIFT 25 -#define DB_PCC_SHIFT 26 -#define DB_EDC_SHIFT 27 - -#define REMOVE_FMAX_MARGIN_BIT 0x0 -#define REMOVE_DCTOL_MARGIN_BIT 0x1 -#define REMOVE_PLATFORM_MARGIN_BIT 0x2 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h deleted file mode 100644 index 43d43d6addc0..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_arcturus.h +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SMU11_DRIVER_IF_ARCTURUS_H -#define SMU11_DRIVER_IF_ARCTURUS_H - -// *** IMPORTANT *** -// SMU TEAM: Always increment the interface version if -// any structure is changed in this file -//#define SMU11_DRIVER_IF_VERSION 0x09 - -#define PPTABLE_ARCTURUS_SMU_VERSION 4 - -#define NUM_GFXCLK_DPM_LEVELS 16 -#define NUM_VCLK_DPM_LEVELS 8 -#define NUM_DCLK_DPM_LEVELS 8 -#define NUM_MP0CLK_DPM_LEVELS 2 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_UCLK_DPM_LEVELS 4 -#define NUM_FCLK_DPM_LEVELS 8 -#define NUM_XGMI_LEVELS 2 -#define NUM_XGMI_PSTATE_LEVELS 4 - -#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) -#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) -#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) -#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) -#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) -#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) -#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) -#define MAX_XGMI_LEVEL (NUM_XGMI_LEVELS - 1) -#define MAX_XGMI_PSTATE_LEVEL (NUM_XGMI_PSTATE_LEVELS - 1) - -// Feature Control Defines -// DPM -#define FEATURE_DPM_PREFETCHER_BIT 0 -#define FEATURE_DPM_GFXCLK_BIT 1 -#define FEATURE_DPM_UCLK_BIT 2 -#define FEATURE_DPM_SOCCLK_BIT 3 -#define FEATURE_DPM_FCLK_BIT 4 -#define FEATURE_DPM_MP0CLK_BIT 5 -#define FEATURE_DPM_XGMI_BIT 6 -// Idle -#define FEATURE_DS_GFXCLK_BIT 7 -#define FEATURE_DS_SOCCLK_BIT 8 -#define FEATURE_DS_LCLK_BIT 9 -#define FEATURE_DS_FCLK_BIT 10 -#define FEATURE_DS_UCLK_BIT 11 -#define FEATURE_GFX_ULV_BIT 12 -#define FEATURE_DPM_VCN_BIT 13 -#define FEATURE_RSMU_SMN_CG_BIT 14 -#define FEATURE_WAFL_CG_BIT 15 -// Throttler/Response -#define FEATURE_PPT_BIT 16 -#define FEATURE_TDC_BIT 17 -#define FEATURE_APCC_PLUS_BIT 18 -#define FEATURE_VR0HOT_BIT 19 -#define FEATURE_VR1HOT_BIT 20 -#define FEATURE_FW_CTF_BIT 21 -#define FEATURE_FAN_CONTROL_BIT 22 -#define FEATURE_THERMAL_BIT 23 -// Other -#define FEATURE_OUT_OF_BAND_MONITOR_BIT 24 -#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 25 -#define FEATURE_PER_PART_VMIN_BIT 26 - -#define FEATURE_SPARE_27_BIT 27 -#define FEATURE_SPARE_28_BIT 28 -#define FEATURE_SPARE_29_BIT 29 -#define FEATURE_SPARE_30_BIT 30 -#define FEATURE_SPARE_31_BIT 31 -#define FEATURE_SPARE_32_BIT 32 -#define FEATURE_SPARE_33_BIT 33 -#define FEATURE_SPARE_34_BIT 34 -#define FEATURE_SPARE_35_BIT 35 -#define FEATURE_SPARE_36_BIT 36 -#define FEATURE_SPARE_37_BIT 37 -#define FEATURE_SPARE_38_BIT 38 -#define FEATURE_SPARE_39_BIT 39 -#define FEATURE_SPARE_40_BIT 40 -#define FEATURE_SPARE_41_BIT 41 -#define FEATURE_SPARE_42_BIT 42 -#define FEATURE_SPARE_43_BIT 43 -#define FEATURE_SPARE_44_BIT 44 -#define FEATURE_SPARE_45_BIT 45 -#define FEATURE_SPARE_46_BIT 46 -#define FEATURE_SPARE_47_BIT 47 -#define FEATURE_SPARE_48_BIT 48 -#define FEATURE_SPARE_49_BIT 49 -#define FEATURE_SPARE_50_BIT 50 -#define FEATURE_SPARE_51_BIT 51 -#define FEATURE_SPARE_52_BIT 52 -#define FEATURE_SPARE_53_BIT 53 -#define FEATURE_SPARE_54_BIT 54 -#define FEATURE_SPARE_55_BIT 55 -#define FEATURE_SPARE_56_BIT 56 -#define FEATURE_SPARE_57_BIT 57 -#define FEATURE_SPARE_58_BIT 58 -#define FEATURE_SPARE_59_BIT 59 -#define FEATURE_SPARE_60_BIT 60 -#define FEATURE_SPARE_61_BIT 61 -#define FEATURE_SPARE_62_BIT 62 -#define FEATURE_SPARE_63_BIT 63 - -#define NUM_FEATURES 64 - - -#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) -#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) -#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) -#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) -#define FEATURE_DPM_FCLK_MASK (1 << FEATURE_DPM_FCLK_BIT ) -#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) -#define FEATURE_DPM_XGMI_MASK (1 << FEATURE_DPM_XGMI_BIT ) - -#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) -#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) -#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) -#define FEATURE_DS_FCLK_MASK (1 << FEATURE_DS_FCLK_BIT ) -#define FEATURE_DS_UCLK_MASK (1 << FEATURE_DS_UCLK_BIT ) -#define FEATURE_GFX_ULV_MASK (1 << FEATURE_GFX_ULV_BIT ) -#define FEATURE_DPM_VCN_MASK (1 << FEATURE_DPM_VCN_BIT ) -#define FEATURE_RSMU_SMN_CG_MASK (1 << FEATURE_RSMU_SMN_CG_BIT ) -#define FEATURE_WAFL_CG_MASK (1 << FEATURE_WAFL_CG_BIT ) - -#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) -#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) -#define FEATURE_APCC_PLUS_MASK (1 << FEATURE_APCC_PLUS_BIT ) -#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) -#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) -#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) -#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) -#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) - -#define FEATURE_OUT_OF_BAND_MONITOR_MASK (1 << FEATURE_OUT_OF_BAND_MONITOR_BIT ) -#define FEATURE_TEMP_DEPENDENT_VMIN_MASK (1 << FEATURE_TEMP_DEPENDENT_VMIN_BIT ) -#define FEATURE_PER_PART_VMIN_MASK (1 << FEATURE_PER_PART_VMIN_BIT ) - - -//FIXME need updating -// Debug Overrides Bitmask -#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000001 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000002 - -// I2C Config Bit Defines -#define I2C_CONTROLLER_ENABLED 1 -#define I2C_CONTROLLER_DISABLED 0 - -// VR Mapping Bit Defines -#define VR_MAPPING_VR_SELECT_MASK 0x01 -#define VR_MAPPING_VR_SELECT_SHIFT 0x00 - -#define VR_MAPPING_PLANE_SELECT_MASK 0x02 -#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 - -// PSI Bit Defines -#define PSI_SEL_VR0_PLANE0_PSI0 0x01 -#define PSI_SEL_VR0_PLANE0_PSI1 0x02 -#define PSI_SEL_VR0_PLANE1_PSI0 0x04 -#define PSI_SEL_VR0_PLANE1_PSI1 0x08 -#define PSI_SEL_VR1_PLANE0_PSI0 0x10 -#define PSI_SEL_VR1_PLANE0_PSI1 0x20 -#define PSI_SEL_VR1_PLANE1_PSI0 0x40 -#define PSI_SEL_VR1_PLANE1_PSI1 0x80 - -// Throttler Control/Status Bits -#define THROTTLER_PADDING_BIT 0 -#define THROTTLER_TEMP_EDGE_BIT 1 -#define THROTTLER_TEMP_HOTSPOT_BIT 2 -#define THROTTLER_TEMP_MEM_BIT 3 -#define THROTTLER_TEMP_VR_GFX_BIT 4 -#define THROTTLER_TEMP_VR_MEM_BIT 5 -#define THROTTLER_TEMP_VR_SOC_BIT 6 -#define THROTTLER_TDC_GFX_BIT 7 -#define THROTTLER_TDC_SOC_BIT 8 -#define THROTTLER_PPT0_BIT 9 -#define THROTTLER_PPT1_BIT 10 -#define THROTTLER_PPT2_BIT 11 -#define THROTTLER_PPT3_BIT 12 -#define THROTTLER_PPM_BIT 13 -#define THROTTLER_FIT_BIT 14 -#define THROTTLER_APCC_BIT 15 -#define THROTTLER_VRHOT0_BIT 16 -#define THROTTLER_VRHOT1_BIT 17 - -// Table transfer status -#define TABLE_TRANSFER_OK 0x0 -#define TABLE_TRANSFER_FAILED 0xFF -#define TABLE_TRANSFER_PENDING 0xAB - -// Workload bits -#define WORKLOAD_PPLIB_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 1 -#define WORKLOAD_PPLIB_VIDEO_BIT 2 -#define WORKLOAD_PPLIB_COMPUTE_BIT 3 -#define WORKLOAD_PPLIB_CUSTOM_BIT 4 -#define WORKLOAD_PPLIB_COUNT 5 - -//XGMI performance states -#define XGMI_STATE_D0 1 -#define XGMI_STATE_D3 0 - -#define NUM_I2C_CONTROLLERS 8 - -#define I2C_CONTROLLER_ENABLED 1 -#define I2C_CONTROLLER_DISABLED 0 - -#define MAX_SW_I2C_COMMANDS 8 - -typedef enum { - I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 - I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 - I2C_CONTROLLER_PORT_COUNT, -} I2cControllerPort_e; - -typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_MEM, - I2C_CONTROLLER_NAME_SPARE, - I2C_CONTROLLER_NAME_COUNT, -} I2cControllerName_e; - -typedef enum { - I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, - I2C_CONTROLLER_THROTTLER_VR_GFX, - I2C_CONTROLLER_THROTTLER_VR_SOC, - I2C_CONTROLLER_THROTTLER_VR_MEM, - I2C_CONTROLLER_THROTTLER_COUNT, -} I2cControllerThrottler_e; - -typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_0, - I2C_CONTROLLER_PROTOCOL_VR_1, - I2C_CONTROLLER_PROTOCOL_TMP_0, - I2C_CONTROLLER_PROTOCOL_TMP_1, - I2C_CONTROLLER_PROTOCOL_SPARE_0, - I2C_CONTROLLER_PROTOCOL_SPARE_1, - I2C_CONTROLLER_PROTOCOL_COUNT, -} I2cControllerProtocol_e; - -typedef struct { - uint8_t Enabled; - uint8_t Speed; - uint8_t Padding[2]; - uint32_t SlaveAddress; - uint8_t ControllerPort; - uint8_t ControllerName; - uint8_t ThermalThrotter; - uint8_t I2cProtocol; -} I2cControllerConfig_t; - -typedef enum { - I2C_PORT_SVD_SCL = 0, - I2C_PORT_GPIO, -} I2cPort_e; - -typedef enum { - I2C_SPEED_FAST_50K = 0, //50 Kbits/s - I2C_SPEED_FAST_100K, //100 Kbits/s - I2C_SPEED_FAST_400K, //400 Kbits/s - I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) - I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) - I2C_SPEED_HIGH_2M, //2.3 Mbits/s - I2C_SPEED_COUNT, -} I2cSpeed_e; - -typedef enum { - I2C_CMD_READ = 0, - I2C_CMD_WRITE, - I2C_CMD_COUNT, -} I2cCmdType_e; - -#define CMDCONFIG_STOP_BIT 0 -#define CMDCONFIG_RESTART_BIT 1 - -#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) -#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) - -typedef struct { - uint8_t RegisterAddr; ////only valid for write, ignored for read - uint8_t Cmd; //Read(0) or Write(1) - uint8_t Data; //Return data for read. Data to send for write - uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command -} SwI2cCmd_t; //SW I2C Command Table - -typedef struct { - uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) - uint8_t I2CSpeed; //Slow(0) or Fast(1) - uint16_t SlaveAddress; - uint8_t NumCmds; //Number of commands - uint8_t Padding[3]; - - SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; - - uint32_t MmHubPadding[8]; // SMU internal use - -} SwI2cRequest_t; // SW I2C Request Table - -//D3HOT sequences -typedef enum { - BACO_SEQUENCE, - MSR_SEQUENCE, - BAMACO_SEQUENCE, - ULPS_SEQUENCE, - D3HOT_SEQUENCE_COUNT, -}D3HOTSequence_e; - -//THis is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_DYNAMIC_MODE = 0, - PG_STATIC_MODE, -} PowerGatingMode_e; - -//This is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_POWER_DOWN = 0, - PG_POWER_UP, -} PowerGatingSettings_e; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} QuadraticInt_t; - -typedef struct { - uint32_t m; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable -} LinearInt_t; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} DroopInt_t; - -typedef enum { - GFXCLK_SOURCE_PLL = 0, - GFXCLK_SOURCE_AFLL, - GFXCLK_SOURCE_COUNT, -} GfxclkSrc_e; - -typedef enum { - PPCLK_GFXCLK, - PPCLK_VCLK, - PPCLK_DCLK, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_FCLK, - PPCLK_COUNT, -} PPCLK_e; - -typedef enum { - POWER_SOURCE_AC, - POWER_SOURCE_DC, - POWER_SOURCE_COUNT, -} POWER_SOURCE_e; - -typedef enum { - TEMP_EDGE, - TEMP_HOTSPOT, - TEMP_MEM, - TEMP_VR_GFX, - TEMP_VR_SOC, - TEMP_VR_MEM, - TEMP_COUNT -} TEMP_TYPE_e; - -typedef enum { - PPT_THROTTLER_PPT0, - PPT_THROTTLER_PPT1, - PPT_THROTTLER_PPT2, - PPT_THROTTLER_PPT3, - PPT_THROTTLER_COUNT -} PPT_THROTTLER_e; - -typedef enum { - VOLTAGE_MODE_AVFS = 0, - VOLTAGE_MODE_AVFS_SS, - VOLTAGE_MODE_SS, - VOLTAGE_MODE_COUNT, -} VOLTAGE_MODE_e; - -typedef enum { - AVFS_VOLTAGE_GFX = 0, - AVFS_VOLTAGE_SOC, - AVFS_VOLTAGE_COUNT, -} AVFS_VOLTAGE_TYPE_e; - -typedef enum { - GPIO_INT_POLARITY_ACTIVE_LOW = 0, - GPIO_INT_POLARITY_ACTIVE_HIGH, -} GpioIntPolarity_e; - -typedef enum { - MEMORY_TYPE_GDDR6 = 0, - MEMORY_TYPE_HBM, -} MemoryType_e; - -typedef enum { - PWR_CONFIG_TDP = 0, - PWR_CONFIG_TGP, - PWR_CONFIG_TCP_ESTIMATED, - PWR_CONFIG_TCP_MEASURED, -} PwrConfig_e; - -typedef enum { - XGMI_LINK_RATE_2 = 2, // 2Gbps - XGMI_LINK_RATE_4 = 4, // 4Gbps - XGMI_LINK_RATE_8 = 8, // 8Gbps - XGMI_LINK_RATE_12 = 12, // 12Gbps - XGMI_LINK_RATE_16 = 16, // 16Gbps - XGMI_LINK_RATE_17 = 17, // 17Gbps - XGMI_LINK_RATE_18 = 18, // 18Gbps - XGMI_LINK_RATE_19 = 19, // 19Gbps - XGMI_LINK_RATE_20 = 20, // 20Gbps - XGMI_LINK_RATE_21 = 21, // 21Gbps - XGMI_LINK_RATE_22 = 22, // 22Gbps - XGMI_LINK_RATE_23 = 23, // 23Gbps - XGMI_LINK_RATE_24 = 24, // 24Gbps - XGMI_LINK_RATE_25 = 25, // 25Gbps - XGMI_LINK_RATE_COUNT -} XGMI_LINK_RATE_e; - -typedef enum { - XGMI_LINK_WIDTH_1 = 1, // x1 - XGMI_LINK_WIDTH_2 = 2, // x2 - XGMI_LINK_WIDTH_4 = 4, // x4 - XGMI_LINK_WIDTH_8 = 8, // x8 - XGMI_LINK_WIDTH_9 = 9, // x9 - XGMI_LINK_WIDTH_16 = 16, // x16 - XGMI_LINK_WIDTH_COUNT -} XGMI_LINK_WIDTH_e; - -typedef struct { - uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only - uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM - uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used - uint8_t padding; - LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) - QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) - uint16_t SsFmin; // Fmin for SS curve. If SS curve is selected, will use V@SSFmin for F <= Fmin - uint16_t Padding16; -} DpmDescriptor_t; - -typedef struct { - uint32_t Version; - - // SECTION: Feature Enablement - uint32_t FeaturesToRun[2]; - - // SECTION: Infrastructure Limits - uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; - uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; - uint16_t TdcLimitSoc; // Amps - uint16_t TdcLimitSocTau; // Time constant of LPF in ms - uint16_t TdcLimitGfx; // Amps - uint16_t TdcLimitGfxTau; // Time constant of LPF in ms - - uint16_t TedgeLimit; // Celcius - uint16_t ThotspotLimit; // Celcius - uint16_t TmemLimit; // Celcius - uint16_t Tvr_gfxLimit; // Celcius - uint16_t Tvr_memLimit; // Celcius - uint16_t Tvr_socLimit; // Celcius - uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) - - uint16_t PpmPowerLimit; // Switch this this power limit when temperature is above PpmTempThreshold - uint16_t PpmTemperatureThreshold; - - // SECTION: Throttler settings - uint32_t ThrottlerControlMask; // See Throtter masks defines - - // SECTION: ULV Settings - uint16_t UlvVoltageOffsetGfx; // In mV(Q2) - uint16_t UlvPadding; // Padding - - uint8_t UlvGfxclkBypass; // 1 to turn off/bypass Gfxclk during ULV, 0 to leave Gfxclk on during ULV - uint8_t Padding234[3]; - - // SECTION: Voltage Control Parameters - uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX - uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC - uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX - uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC - - uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits - uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits - - //SECTION: DPM Config 1 - DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; - - uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz - - uint32_t Paddingclks[16]; - - // SECTION: DPM Config 2 - uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz - uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) - - // GFXCLK DPM - uint16_t GfxclkFidle; // In MHz - uint16_t GfxclkSlewRate; // for PLL babystepping??? - uint8_t Padding567[4]; - uint16_t GfxclkDsMaxFreq; // In MHz - uint8_t GfxclkSource; // 0 = PLL, 1 = AFLL - uint8_t Padding456; - - // GFXCLK Thermal DPM (formerly 'Boost' Settings) - uint16_t EnableTdpm; - uint16_t TdpmHighHystTemperature; - uint16_t TdpmLowHystTemperature; - uint16_t GfxclkFreqHighTempLimit; // High limit on GFXCLK when temperature is high, for reliability. - - // SECTION: Fan Control - uint16_t FanStopTemp; //Celcius - uint16_t FanStartTemp; //Celcius - - uint16_t FanGainEdge; - uint16_t FanGainHotspot; - uint16_t FanGainVrGfx; - uint16_t FanGainVrSoc; - uint16_t FanGainVrMem; - uint16_t FanGainHbm; - uint16_t FanPwmMin; - uint16_t FanAcousticLimitRpm; - uint16_t FanThrottlingRpm; - uint16_t FanMaximumRpm; - uint16_t FanTargetTemperature; - uint16_t FanTargetGfxclk; - uint8_t FanZeroRpmEnable; - uint8_t FanTachEdgePerRev; - uint8_t FanTempInputSelect; - uint8_t padding8_Fan; - - // The following are AFC override parameters. Leave at 0 to use FW defaults. - int16_t FuzzyFan_ErrorSetDelta; - int16_t FuzzyFan_ErrorRateSetDelta; - int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; - - - // SECTION: AVFS - // Overrides - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_Avfs[2]; - - QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve - DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb - DroopInt_t dBtcGbGfxAfll; // GHz->V BtcGb - DroopInt_t dBtcGbSoc; // GHz->V BtcGb - LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V - - QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V - - uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 - - uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_GfxBtc[2]; - - uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 - uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 - - uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; // mV Q2 - - // SECTION: XGMI - uint8_t XgmiDpmPstates[NUM_XGMI_LEVELS]; // 2 DPM states, high and low. 0-P0, 1-P1, 2-P2, 3-P3. - uint8_t XgmiDpmSpare[2]; - - // Temperature Dependent Vmin - uint16_t VDDGFX_TVmin; //Celcius - uint16_t VDDSOC_TVmin; //Celcius - uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 - uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 - uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 - uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 - - uint16_t VDDGFX_TVminHystersis; // Celcius - uint16_t VDDSOC_TVminHystersis; // Celcius - - - // SECTION: Advanced Options - uint32_t DebugOverrides; - QuadraticInt_t ReservedEquation0; - QuadraticInt_t ReservedEquation1; - QuadraticInt_t ReservedEquation2; - QuadraticInt_t ReservedEquation3; - - uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode - uint16_t PaddingUlv; // Padding - - // Total Power configuration, use defines from PwrConfig_e - uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured - uint8_t TotalPowerSpare1; - uint16_t TotalPowerSpare2; - - // APCC Settings - uint16_t PccThresholdLow; - uint16_t PccThresholdHigh; - uint32_t PaddingAPCC[6]; //FIXME pending SPEC - - // OOB Settings - uint16_t BasePerformanceCardPower; - uint16_t MaxPerformanceCardPower; - uint16_t BasePerformanceFrequencyCap; //In Mhz - uint16_t MaxPerformanceFrequencyCap; //In Mhz - - // Per-Part Vmin - uint16_t VDDGFX_VminLow; // mv Q2 - uint16_t VDDGFX_TVminLow; //Celcius - uint16_t VDDGFX_VminLow_HiTemp; // mv Q2 - uint16_t VDDGFX_VminLow_LoTemp; // mv Q2 - - // SECTION: Reserved - uint32_t Reserved[7]; - - // SECTION: BOARD PARAMETERS - - // SVI2 Board Parameters - uint16_t MaxVoltageStepGfx; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. - uint16_t MaxVoltageStepSoc; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. - - uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddMemVrMapping; // Use VR_MAPPING* bitfields - uint8_t BoardVrMapping; // Use VR_MAPPING* bitfields - - uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t ExternalSensorPresent; // External RDI connected to TMON (aka TEMP IN) - uint8_t Padding8_V[2]; - - // Telemetry Settings - uint16_t GfxMaxCurrent; // in Amps - int8_t GfxOffset; // in Amps - uint8_t Padding_TelemetryGfx; - - uint16_t SocMaxCurrent; // in Amps - int8_t SocOffset; // in Amps - uint8_t Padding_TelemetrySoc; - - uint16_t MemMaxCurrent; // in Amps - int8_t MemOffset; // in Amps - uint8_t Padding_TelemetryMem; - - uint16_t BoardMaxCurrent; // in Amps - int8_t BoardOffset; // in Amps - uint8_t Padding_TelemetryBoardInput; - - // GPIO Settings - uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event - uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event - uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event - uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event - - // GFXCLK PLL Spread Spectrum - uint8_t PllGfxclkSpreadEnabled; // on or off - uint8_t PllGfxclkSpreadPercent; // Q4.4 - uint16_t PllGfxclkSpreadFreq; // kHz - - // UCLK Spread Spectrum - uint8_t UclkSpreadEnabled; // on or off - uint8_t UclkSpreadPercent; // Q4.4 - uint16_t UclkSpreadFreq; // kHz - - // FCLK Spread Spectrum - uint8_t FclkSpreadEnabled; // on or off - uint8_t FclkSpreadPercent; // Q4.4 - uint16_t FclkSpreadFreq; // kHz - - // GFXCLK Fll Spread Spectrum - uint8_t FllGfxclkSpreadEnabled; // on or off - uint8_t FllGfxclkSpreadPercent; // Q4.4 - uint16_t FllGfxclkSpreadFreq; // kHz - - // I2C Controller Structure - I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; - - // Memory section - uint32_t MemoryChannelEnabled; // For DRAM use only, Max 32 channels enabled bit mask. - - uint8_t DramBitWidth; // For DRAM use only. See Dram Bit width type defines - uint8_t PaddingMem[3]; - - // Total board power - uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power - uint16_t BoardPadding; - - // SECTION: XGMI Training - uint8_t XgmiLinkSpeed [NUM_XGMI_PSTATE_LEVELS]; - uint8_t XgmiLinkWidth [NUM_XGMI_PSTATE_LEVELS]; - - uint16_t XgmiFclkFreq [NUM_XGMI_PSTATE_LEVELS]; - uint16_t XgmiSocVoltage [NUM_XGMI_PSTATE_LEVELS]; - - // GPIO pins for I2C communications with 2nd controller for Input Telemetry Sequence - uint8_t GpioI2cScl; // Serial Clock - uint8_t GpioI2cSda; // Serial Data - uint16_t GpioPadding; - - // Platform input telemetry voltage coefficient - uint32_t BoardVoltageCoeffA; // decode by /1000 - uint32_t BoardVoltageCoeffB; // decode by /1000 - - uint32_t BoardReserved[7]; - - // Padding for MMHUB - do not modify this - uint32_t MmHubPadding[8]; // SMU internal use - -} PPTable_t; - -typedef struct { - // Time constant parameters for clock averages in ms - uint16_t GfxclkAverageLpfTau; - uint16_t SocclkAverageLpfTau; - uint16_t UclkAverageLpfTau; - uint16_t GfxActivityLpfTau; - uint16_t UclkActivityLpfTau; - - uint16_t SocketPowerLpfTau; - - uint16_t VcnClkAverageLpfTau; - uint16_t padding16; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} DriverSmuConfig_t; - -typedef struct { - uint16_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageSocclkFrequency; - uint16_t AverageUclkFrequency ; - uint16_t AverageGfxActivity ; - uint16_t AverageUclkActivity ; - uint8_t CurrSocVoltageOffset ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t AverageSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureHBM ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrSoc ; - uint16_t TemperatureVrMem ; - uint32_t ThrottlerStatus ; - - uint16_t CurrFanSpeed ; - uint16_t AverageVclkFrequency ; - uint16_t AverageDclkFrequency ; - uint16_t VcnActivityPercentage ; - uint32_t EnergyAccumulator ; - - uint32_t Padding[2]; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} SmuMetrics_t; - - -typedef struct { - uint16_t avgPsmCount[75]; - uint16_t minPsmCount[75]; - float avgPsmVoltage[75]; - float minPsmVoltage[75]; - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsDebugTable_t; - -typedef struct { - uint8_t AvfsVersion; - uint8_t Padding; - uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; - - int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; - - uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits - - - int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units - - uint32_t EnabledAvfsModules[3]; - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsFuseOverride_t; - -typedef struct { - uint8_t Gfx_ActiveHystLimit; - uint8_t Gfx_IdleHystLimit; - uint8_t Gfx_FPS; - uint8_t Gfx_MinActiveFreqType; - uint8_t Gfx_BoosterFreqType; - uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint8_t Gfx_UseRlcBusy; - uint8_t PaddingGfx[3]; - uint16_t Gfx_MinActiveFreq; // MHz - uint16_t Gfx_BoosterFreq; // MHz - uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Gfx_PD_Data_limit_a; // Q16 - uint32_t Gfx_PD_Data_limit_b; // Q16 - uint32_t Gfx_PD_Data_limit_c; // Q16 - uint32_t Gfx_PD_Data_error_coeff; // Q16 - uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 - - uint8_t Mem_ActiveHystLimit; - uint8_t Mem_IdleHystLimit; - uint8_t Mem_FPS; - uint8_t Mem_MinActiveFreqType; - uint8_t Mem_BoosterFreqType; - uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint8_t Mem_UseRlcBusy; - uint8_t PaddingMem[3]; - uint16_t Mem_MinActiveFreq; // MHz - uint16_t Mem_BoosterFreq; // MHz - uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Mem_PD_Data_limit_a; // Q16 - uint32_t Mem_PD_Data_limit_b; // Q16 - uint32_t Mem_PD_Data_limit_c; // Q16 - uint32_t Mem_PD_Data_error_coeff; // Q16 - uint32_t Mem_PD_Data_error_rate_coeff; // Q16 - - uint32_t Mem_UpThreshold_Limit; // Q16 - uint8_t Mem_UpHystLimit; - uint8_t Mem_DownHystLimit; - uint16_t Mem_Fps; - - uint32_t BusyThreshold; // Q16 - uint32_t BusyHyst; - uint32_t IdleHyst; - - uint32_t MmHubPadding[8]; // SMU internal use -} DpmActivityMonitorCoeffInt_t; - -// These defines are used with the following messages: -// SMC_MSG_TransferTableDram2Smu -// SMC_MSG_TransferTableSmu2Dram -#define TABLE_PPTABLE 0 -#define TABLE_AVFS 1 -#define TABLE_AVFS_PSM_DEBUG 2 -#define TABLE_AVFS_FUSE_OVERRIDE 3 -#define TABLE_PMSTATUSLOG 4 -#define TABLE_SMU_METRICS 5 -#define TABLE_DRIVER_SMU_CONFIG 6 -#define TABLE_OVERDRIVE 7 -#define TABLE_WAFL_XGMI_TOPOLOGY 8 -#define TABLE_I2C_COMMANDS 9 -#define TABLE_ACTIVITY_MONITOR_COEFF 10 -#define TABLE_COUNT 11 - -// These defines are used with the SMC_MSG_SetUclkFastSwitch message. -typedef enum { - DF_SWITCH_TYPE_FAST = 0, - DF_SWITCH_TYPE_SLOW, - DF_SWITCH_TYPE_COUNT, -} DF_SWITCH_TYPE_e; - -typedef enum { - DRAM_BIT_WIDTH_DISABLED = 0, - DRAM_BIT_WIDTH_X_8, - DRAM_BIT_WIDTH_X_16, - DRAM_BIT_WIDTH_X_32, - DRAM_BIT_WIDTH_X_64, // NOT USED. - DRAM_BIT_WIDTH_X_128, - DRAM_BIT_WIDTH_COUNT, -} DRAM_BIT_WIDTH_TYPE_e; - -#define REMOVE_FMAX_MARGIN_BIT 0x0 -#define REMOVE_DCTOL_MARGIN_BIT 0x1 -#define REMOVE_PLATFORM_MARGIN_BIT 0x2 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h deleted file mode 100644 index 246d3951a78a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_navi10.h +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __SMU11_DRIVER_IF_NAVI10_H__ -#define __SMU11_DRIVER_IF_NAVI10_H__ - -// *** IMPORTANT *** -// SMU TEAM: Always increment the interface version if -// any structure is changed in this file -// Be aware of that the version should be updated in -// smu_v11_0.h, maybe rename is also needed. -// #define SMU11_DRIVER_IF_VERSION 0x33 - -#define PPTABLE_NV10_SMU_VERSION 8 - -#define NUM_GFXCLK_DPM_LEVELS 16 -#define NUM_SMNCLK_DPM_LEVELS 2 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_MP0CLK_DPM_LEVELS 2 -#define NUM_DCLK_DPM_LEVELS 8 -#define NUM_VCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 8 -#define NUM_PHYCLK_DPM_LEVELS 8 -#define NUM_DISPCLK_DPM_LEVELS 8 -#define NUM_PIXCLK_DPM_LEVELS 8 -#define NUM_UCLK_DPM_LEVELS 4 -#define NUM_MP1CLK_DPM_LEVELS 2 -#define NUM_LINK_LEVELS 2 - - -#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) -#define MAX_SMNCLK_DPM_LEVEL (NUM_SMNCLK_DPM_LEVELS - 1) -#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) -#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) -#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) -#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) -#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) -#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) -#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) -#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) -#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) -#define MAX_MP1CLK_DPM_LEVEL (NUM_MP1CLK_DPM_LEVELS - 1) -#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) - -//Gemini Modes -#define PPSMC_GeminiModeNone 0 //Single GPU board -#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board -#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board - -// Feature Control Defines -// DPM -#define FEATURE_DPM_PREFETCHER_BIT 0 -#define FEATURE_DPM_GFXCLK_BIT 1 -#define FEATURE_DPM_GFX_PACE_BIT 2 -#define FEATURE_DPM_UCLK_BIT 3 -#define FEATURE_DPM_SOCCLK_BIT 4 -#define FEATURE_DPM_MP0CLK_BIT 5 -#define FEATURE_DPM_LINK_BIT 6 -#define FEATURE_DPM_DCEFCLK_BIT 7 -#define FEATURE_MEM_VDDCI_SCALING_BIT 8 -#define FEATURE_MEM_MVDD_SCALING_BIT 9 - -//Idle -#define FEATURE_DS_GFXCLK_BIT 10 -#define FEATURE_DS_SOCCLK_BIT 11 -#define FEATURE_DS_LCLK_BIT 12 -#define FEATURE_DS_DCEFCLK_BIT 13 -#define FEATURE_DS_UCLK_BIT 14 -#define FEATURE_GFX_ULV_BIT 15 -#define FEATURE_FW_DSTATE_BIT 16 -#define FEATURE_GFXOFF_BIT 17 -#define FEATURE_BACO_BIT 18 -#define FEATURE_VCN_PG_BIT 19 -#define FEATURE_JPEG_PG_BIT 20 -#define FEATURE_USB_PG_BIT 21 -#define FEATURE_RSMU_SMN_CG_BIT 22 -//Throttler/Response -#define FEATURE_PPT_BIT 23 -#define FEATURE_TDC_BIT 24 -#define FEATURE_GFX_EDC_BIT 25 -#define FEATURE_APCC_PLUS_BIT 26 -#define FEATURE_GTHR_BIT 27 -#define FEATURE_ACDC_BIT 28 -#define FEATURE_VR0HOT_BIT 29 -#define FEATURE_VR1HOT_BIT 30 -#define FEATURE_FW_CTF_BIT 31 -#define FEATURE_FAN_CONTROL_BIT 32 -#define FEATURE_THERMAL_BIT 33 -#define FEATURE_GFX_DCS_BIT 34 -//VF -#define FEATURE_RM_BIT 35 -#define FEATURE_LED_DISPLAY_BIT 36 -//Other -#define FEATURE_GFX_SS_BIT 37 -#define FEATURE_OUT_OF_BAND_MONITOR_BIT 38 -#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 39 - -#define FEATURE_MMHUB_PG_BIT 40 -#define FEATURE_ATHUB_PG_BIT 41 -#define FEATURE_APCC_DFLL_BIT 42 -#define FEATURE_SPARE_43_BIT 43 -#define FEATURE_SPARE_44_BIT 44 -#define FEATURE_SPARE_45_BIT 45 -#define FEATURE_SPARE_46_BIT 46 -#define FEATURE_SPARE_47_BIT 47 -#define FEATURE_SPARE_48_BIT 48 -#define FEATURE_SPARE_49_BIT 49 -#define FEATURE_SPARE_50_BIT 50 -#define FEATURE_SPARE_51_BIT 51 -#define FEATURE_SPARE_52_BIT 52 -#define FEATURE_SPARE_53_BIT 53 -#define FEATURE_SPARE_54_BIT 54 -#define FEATURE_SPARE_55_BIT 55 -#define FEATURE_SPARE_56_BIT 56 -#define FEATURE_SPARE_57_BIT 57 -#define FEATURE_SPARE_58_BIT 58 -#define FEATURE_SPARE_59_BIT 59 -#define FEATURE_SPARE_60_BIT 60 -#define FEATURE_SPARE_61_BIT 61 -#define FEATURE_SPARE_62_BIT 62 -#define FEATURE_SPARE_63_BIT 63 -#define NUM_FEATURES 64 - -// Debug Overrides Bitmask -#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 -#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_SOCCLK 0x00000004 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000008 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000010 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00000020 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00000040 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_DCE_SOCCLK 0x00000080 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_MP0_SOCCLK 0x00000100 -#define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 -#define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 - -// VR Mapping Bit Defines -#define VR_MAPPING_VR_SELECT_MASK 0x01 -#define VR_MAPPING_VR_SELECT_SHIFT 0x00 - -#define VR_MAPPING_PLANE_SELECT_MASK 0x02 -#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 - -// PSI Bit Defines -#define PSI_SEL_VR0_PLANE0_PSI0 0x01 -#define PSI_SEL_VR0_PLANE0_PSI1 0x02 -#define PSI_SEL_VR0_PLANE1_PSI0 0x04 -#define PSI_SEL_VR0_PLANE1_PSI1 0x08 -#define PSI_SEL_VR1_PLANE0_PSI0 0x10 -#define PSI_SEL_VR1_PLANE0_PSI1 0x20 -#define PSI_SEL_VR1_PLANE1_PSI0 0x40 -#define PSI_SEL_VR1_PLANE1_PSI1 0x80 - -// Throttler Control/Status Bits -#define THROTTLER_PADDING_BIT 0 -#define THROTTLER_TEMP_EDGE_BIT 1 -#define THROTTLER_TEMP_HOTSPOT_BIT 2 -#define THROTTLER_TEMP_MEM_BIT 3 -#define THROTTLER_TEMP_VR_GFX_BIT 4 -#define THROTTLER_TEMP_VR_MEM0_BIT 5 -#define THROTTLER_TEMP_VR_MEM1_BIT 6 -#define THROTTLER_TEMP_VR_SOC_BIT 7 -#define THROTTLER_TEMP_LIQUID0_BIT 8 -#define THROTTLER_TEMP_LIQUID1_BIT 9 -#define THROTTLER_TEMP_PLX_BIT 10 -#define THROTTLER_TEMP_SKIN_BIT 11 -#define THROTTLER_TDC_GFX_BIT 12 -#define THROTTLER_TDC_SOC_BIT 13 -#define THROTTLER_PPT0_BIT 14 -#define THROTTLER_PPT1_BIT 15 -#define THROTTLER_PPT2_BIT 16 -#define THROTTLER_PPT3_BIT 17 -#define THROTTLER_FIT_BIT 18 -#define THROTTLER_PPM_BIT 19 -#define THROTTLER_APCC_BIT 20 - -// FW DState Features Control Bits -#define FW_DSTATE_SOC_ULV_BIT 0 -#define FW_DSTATE_G6_HSR_BIT 1 -#define FW_DSTATE_G6_PHY_VDDCI_OFF_BIT 2 -#define FW_DSTATE_MP0_DS_BIT 3 -#define FW_DSTATE_SMN_DS_BIT 4 -#define FW_DSTATE_MP1_DS_BIT 5 -#define FW_DSTATE_MP1_WHISPER_MODE_BIT 6 -#define FW_DSTATE_LIV_MIN_BIT 7 -#define FW_DSTATE_SOC_PLL_PWRDN_BIT 8 - -#define FW_DSTATE_SOC_ULV_MASK (1 << FW_DSTATE_SOC_ULV_BIT ) -#define FW_DSTATE_G6_HSR_MASK (1 << FW_DSTATE_G6_HSR_BIT ) -#define FW_DSTATE_G6_PHY_VDDCI_OFF_MASK (1 << FW_DSTATE_G6_PHY_VDDCI_OFF_BIT ) -#define FW_DSTATE_MP1_DS_MASK (1 << FW_DSTATE_MP1_DS_BIT ) -#define FW_DSTATE_MP0_DS_MASK (1 << FW_DSTATE_MP0_DS_BIT ) -#define FW_DSTATE_SMN_DS_MASK (1 << FW_DSTATE_SMN_DS_BIT ) -#define FW_DSTATE_MP1_WHISPER_MODE_MASK (1 << FW_DSTATE_MP1_WHISPER_MODE_BIT ) -#define FW_DSTATE_LIV_MIN_MASK (1 << FW_DSTATE_LIV_MIN_BIT ) -#define FW_DSTATE_SOC_PLL_PWRDN_MASK (1 << FW_DSTATE_SOC_PLL_PWRDN_BIT ) - -//I2C Interface - -#define NUM_I2C_CONTROLLERS 8 - -#define I2C_CONTROLLER_ENABLED 1 -#define I2C_CONTROLLER_DISABLED 0 - -#define MAX_SW_I2C_COMMANDS 8 - -typedef enum { - I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 - I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 - I2C_CONTROLLER_PORT_COUNT, -} I2cControllerPort_e; - -typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_VDDCI, - I2C_CONTROLLER_NAME_VR_MVDD, - I2C_CONTROLLER_NAME_LIQUID0, - I2C_CONTROLLER_NAME_LIQUID1, - I2C_CONTROLLER_NAME_PLX, - I2C_CONTROLLER_NAME_SPARE, - I2C_CONTROLLER_NAME_COUNT, -} I2cControllerName_e; - -typedef enum { - I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, - I2C_CONTROLLER_THROTTLER_VR_GFX, - I2C_CONTROLLER_THROTTLER_VR_SOC, - I2C_CONTROLLER_THROTTLER_VR_VDDCI, - I2C_CONTROLLER_THROTTLER_VR_MVDD, - I2C_CONTROLLER_THROTTLER_LIQUID0, - I2C_CONTROLLER_THROTTLER_LIQUID1, - I2C_CONTROLLER_THROTTLER_PLX, - I2C_CONTROLLER_THROTTLER_COUNT, -} I2cControllerThrottler_e; - -typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_0, - I2C_CONTROLLER_PROTOCOL_VR_1, - I2C_CONTROLLER_PROTOCOL_TMP_0, - I2C_CONTROLLER_PROTOCOL_TMP_1, - I2C_CONTROLLER_PROTOCOL_SPARE_0, - I2C_CONTROLLER_PROTOCOL_SPARE_1, - I2C_CONTROLLER_PROTOCOL_COUNT, -} I2cControllerProtocol_e; - -typedef struct { - uint8_t Enabled; - uint8_t Speed; - uint8_t Padding[2]; - uint32_t SlaveAddress; - uint8_t ControllerPort; - uint8_t ControllerName; - uint8_t ThermalThrotter; - uint8_t I2cProtocol; -} I2cControllerConfig_t; - -typedef enum { - I2C_PORT_SVD_SCL = 0, - I2C_PORT_GPIO, -} I2cPort_e; - -typedef enum { - I2C_SPEED_FAST_50K = 0, //50 Kbits/s - I2C_SPEED_FAST_100K, //100 Kbits/s - I2C_SPEED_FAST_400K, //400 Kbits/s - I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) - I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) - I2C_SPEED_HIGH_2M, //2.3 Mbits/s - I2C_SPEED_COUNT, -} I2cSpeed_e; - -typedef enum { - I2C_CMD_READ = 0, - I2C_CMD_WRITE, - I2C_CMD_COUNT, -} I2cCmdType_e; - -#define CMDCONFIG_STOP_BIT 0 -#define CMDCONFIG_RESTART_BIT 1 - -#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) -#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) - -typedef struct { - uint8_t RegisterAddr; ////only valid for write, ignored for read - uint8_t Cmd; //Read(0) or Write(1) - uint8_t Data; //Return data for read. Data to send for write - uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command -} SwI2cCmd_t; //SW I2C Command Table - -typedef struct { - uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) - uint8_t I2CSpeed; //Slow(0) or Fast(1) - uint16_t SlaveAddress; - uint8_t NumCmds; //Number of commands - uint8_t Padding[3]; - - SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; - - uint32_t MmHubPadding[8]; // SMU internal use - -} SwI2cRequest_t; // SW I2C Request Table - -//D3HOT sequences -typedef enum { - BACO_SEQUENCE, - MSR_SEQUENCE, - BAMACO_SEQUENCE, - ULPS_SEQUENCE, - D3HOT_SEQUENCE_COUNT, -}D3HOTSequence_e; - -//THis is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_DYNAMIC_MODE = 0, - PG_STATIC_MODE, -} PowerGatingMode_e; - -//This is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_POWER_DOWN = 0, - PG_POWER_UP, -} PowerGatingSettings_e; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} QuadraticInt_t; - -typedef struct { - uint32_t m; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable -} LinearInt_t; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} DroopInt_t; - -typedef enum { - GFXCLK_SOURCE_PLL = 0, - GFXCLK_SOURCE_DFLL, - GFXCLK_SOURCE_COUNT, -} GfxclkSrc_e; - -//Only Clks that have DPM descriptors are listed here -typedef enum { - PPCLK_GFXCLK = 0, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_DCLK, - PPCLK_VCLK, - PPCLK_DCEFCLK, - PPCLK_DISPCLK, - PPCLK_PIXCLK, - PPCLK_PHYCLK, - PPCLK_COUNT, -} PPCLK_e; - -typedef enum { - POWER_SOURCE_AC, - POWER_SOURCE_DC, - POWER_SOURCE_COUNT, -} POWER_SOURCE_e; - -typedef enum { - PPT_THROTTLER_PPT0, - PPT_THROTTLER_PPT1, - PPT_THROTTLER_PPT2, - PPT_THROTTLER_PPT3, - PPT_THROTTLER_COUNT -} PPT_THROTTLER_e; - -typedef enum { - VOLTAGE_MODE_AVFS = 0, - VOLTAGE_MODE_AVFS_SS, - VOLTAGE_MODE_SS, - VOLTAGE_MODE_COUNT, -} VOLTAGE_MODE_e; - - -typedef enum { - AVFS_VOLTAGE_GFX = 0, - AVFS_VOLTAGE_SOC, - AVFS_VOLTAGE_COUNT, -} AVFS_VOLTAGE_TYPE_e; - -typedef enum { - UCLK_DIV_BY_1 = 0, - UCLK_DIV_BY_2, - UCLK_DIV_BY_4, - UCLK_DIV_BY_8, -} UCLK_DIV_e; - -typedef enum { - GPIO_INT_POLARITY_ACTIVE_LOW = 0, - GPIO_INT_POLARITY_ACTIVE_HIGH, -} GpioIntPolarity_e; - -typedef enum { - MEMORY_TYPE_GDDR6 = 0, - MEMORY_TYPE_HBM, -} MemoryType_e; - -typedef enum { - PWR_CONFIG_TDP = 0, - PWR_CONFIG_TGP, - PWR_CONFIG_TCP_ESTIMATED, - PWR_CONFIG_TCP_MEASURED, -} PwrConfig_e; - -typedef struct { - uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only - uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM - uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used - uint8_t Padding; - LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) - QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) -} DpmDescriptor_t; - -typedef enum { - TEMP_EDGE, - TEMP_HOTSPOT, - TEMP_MEM, - TEMP_VR_GFX, - TEMP_VR_MEM0, - TEMP_VR_MEM1, - TEMP_VR_SOC, - TEMP_LIQUID0, - TEMP_LIQUID1, - TEMP_PLX, - TEMP_COUNT -} TEMP_e; - -//Out of band monitor status defines -//see SPEC //gpu/doc/soc_arch/spec/feature/SMBUS/SMBUS.xlsx -#define POWER_MANAGER_CONTROLLER_NOT_RUNNING 0 -#define POWER_MANAGER_CONTROLLER_RUNNING 1 - -#define POWER_MANAGER_CONTROLLER_BIT 0 -#define MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_BIT 8 -#define GPU_DIE_TEMPERATURE_THROTTLING_BIT 9 -#define HBM_DIE_TEMPERATURE_THROTTLING_BIT 10 -#define TGP_THROTTLING_BIT 11 -#define PCC_THROTTLING_BIT 12 -#define HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_BIT 13 -#define HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_BIT 14 - -#define POWER_MANAGER_CONTROLLER_MASK (1 << POWER_MANAGER_CONTROLLER_BIT ) -#define MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_MASK (1 << MAXIMUM_DPM_STATE_GFX_ENGINE_RESTRICTED_BIT ) -#define GPU_DIE_TEMPERATURE_THROTTLING_MASK (1 << GPU_DIE_TEMPERATURE_THROTTLING_BIT ) -#define HBM_DIE_TEMPERATURE_THROTTLING_MASK (1 << HBM_DIE_TEMPERATURE_THROTTLING_BIT ) -#define TGP_THROTTLING_MASK (1 << TGP_THROTTLING_BIT ) -#define PCC_THROTTLING_MASK (1 << PCC_THROTTLING_BIT ) -#define HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_MASK (1 << HBM_TEMPERATURE_EXCEEDING_TEMPERATURE_LIMIT_BIT ) -#define HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_MASK (1 << HBM_TEMPERATURE_EXCEEDING_MAX_MEMORY_TEMPERATURE_BIT) - -//This structure to be DMA to SMBUS Config register space -typedef struct { - uint8_t MinorInfoVersion; - uint8_t MajorInfoVersion; - uint8_t TableSize; - uint8_t Reserved; - - uint8_t Reserved1; - uint8_t RevID; - uint16_t DeviceID; - - uint16_t DieTemperatureLimit; - uint16_t FanTargetTemperature; - - uint16_t MemoryTemperatureLimit; - uint16_t MemoryTemperatureLimit1; - - uint16_t TGP; - uint16_t CardPower; - - uint32_t DieTemperatureRegisterOffset; - - uint32_t Reserved2; - - uint32_t Reserved3; - - uint32_t Status; - - uint16_t DieTemperature; - uint16_t CurrentMemoryTemperature; - - uint16_t MemoryTemperature; - uint8_t MemoryHotspotPosition; - uint8_t Reserved4; - - uint32_t BoardLevelEnergyAccumulator; -} OutOfBandMonitor_t; - -typedef struct { - uint32_t Version; - - // SECTION: Feature Enablement - uint32_t FeaturesToRun[2]; - - // SECTION: Infrastructure Limits - uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; - uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; - uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; - uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; - - uint16_t TdcLimitSoc; // Amps - uint16_t TdcLimitSocTau; // Time constant of LPF in ms - uint16_t TdcLimitGfx; // Amps - uint16_t TdcLimitGfxTau; // Time constant of LPF in ms - - uint16_t TedgeLimit; // Celcius - uint16_t ThotspotLimit; // Celcius - uint16_t TmemLimit; // Celcius - uint16_t Tvr_gfxLimit; // Celcius - uint16_t Tvr_mem0Limit; // Celcius - uint16_t Tvr_mem1Limit; // Celcius - uint16_t Tvr_socLimit; // Celcius - uint16_t Tliquid0Limit; // Celcius - uint16_t Tliquid1Limit; // Celcius - uint16_t TplxLimit; // Celcius - uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) - - uint16_t PpmPowerLimit; // Switch this this power limit when temperature is above PpmTempThreshold - uint16_t PpmTemperatureThreshold; - - // SECTION: Throttler settings - uint32_t ThrottlerControlMask; // See Throtter masks defines - - // SECTION: FW DSTATE Settings - uint32_t FwDStateMask; // See FW DState masks defines - - // SECTION: ULV Settings - uint16_t UlvVoltageOffsetSoc; // In mV(Q2) - uint16_t UlvVoltageOffsetGfx; // In mV(Q2) - - uint8_t GceaLinkMgrIdleThreshold; //Set by SMU FW during enablment of SOC_ULV. Controls delay for GFX SDP port disconnection during idle events - uint8_t paddingRlcUlvParams[3]; - - uint8_t UlvSmnclkDid; //DID for ULV mode. 0 means CLK will not be modified in ULV. - uint8_t UlvMp1clkDid; //DID for ULV mode. 0 means CLK will not be modified in ULV. - uint8_t UlvGfxclkBypass; // 1 to turn off/bypass Gfxclk during ULV, 0 to leave Gfxclk on during ULV - uint8_t Padding234; - - uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode - uint16_t MinVoltageUlvSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC in ULV mode - - - // SECTION: Voltage Control Parameters - uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX - uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC - uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX - uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC - - uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits - uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits - - //SECTION: DPM Config 1 - DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; - - uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; // In MHz - uint32_t Paddingclks[16]; - - uint16_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz - uint16_t Padding8_Clks; - - uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 - - // SECTION: DPM Config 2 - uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz - uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) - uint16_t MemVddciVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) - uint16_t MemMvddVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) - // GFXCLK DPM - uint16_t GfxclkFgfxoffEntry; // in Mhz - uint16_t GfxclkFinit; // in Mhz - uint16_t GfxclkFidle; // in MHz - uint16_t GfxclkSlewRate; // for PLL babystepping??? - uint16_t GfxclkFopt; // in Mhz - uint8_t Padding567[2]; - uint16_t GfxclkDsMaxFreq; // in MHz - uint8_t GfxclkSource; // 0 = PLL, 1 = DFLL - uint8_t Padding456; - - // UCLK section - uint8_t LowestUclkReservedForUlv; // Set this to 1 if UCLK DPM0 is reserved for ULV-mode only - uint8_t paddingUclk[3]; - - uint8_t MemoryType; // 0-GDDR6, 1-HBM - uint8_t MemoryChannels; - uint8_t PaddingMem[2]; - - // Link DPM Settings - uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 - uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 - uint16_t LclkFreq[NUM_LINK_LEVELS]; - - // GFXCLK Thermal DPM (formerly 'Boost' Settings) - uint16_t EnableTdpm; - uint16_t TdpmHighHystTemperature; - uint16_t TdpmLowHystTemperature; - uint16_t GfxclkFreqHighTempLimit; // High limit on GFXCLK when temperature is high, for reliability. - - // SECTION: Fan Control - uint16_t FanStopTemp; //Celcius - uint16_t FanStartTemp; //Celcius - - uint16_t FanGainEdge; - uint16_t FanGainHotspot; - uint16_t FanGainLiquid0; - uint16_t FanGainLiquid1; - uint16_t FanGainVrGfx; - uint16_t FanGainVrSoc; - uint16_t FanGainVrMem0; - uint16_t FanGainVrMem1; - uint16_t FanGainPlx; - uint16_t FanGainMem; - uint16_t FanPwmMin; - uint16_t FanAcousticLimitRpm; - uint16_t FanThrottlingRpm; - uint16_t FanMaximumRpm; - uint16_t FanTargetTemperature; - uint16_t FanTargetGfxclk; - uint8_t FanTempInputSelect; - uint8_t FanPadding; - uint8_t FanZeroRpmEnable; - uint8_t FanTachEdgePerRev; - //uint8_t padding8_Fan[2]; - - // The following are AFC override parameters. Leave at 0 to use FW defaults. - int16_t FuzzyFan_ErrorSetDelta; - int16_t FuzzyFan_ErrorRateSetDelta; - int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; - - - // SECTION: AVFS - // Overrides - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_Avfs[2]; - - QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve - DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb - DroopInt_t dBtcGbGfxDfll; // GHz->V BtcGb - DroopInt_t dBtcGbSoc; // GHz->V BtcGb - LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V - - QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V - - uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 - - uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_GfxBtc[2]; - - uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 - uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 - - // SECTION: Advanced Options - uint32_t DebugOverrides; - QuadraticInt_t ReservedEquation0; - QuadraticInt_t ReservedEquation1; - QuadraticInt_t ReservedEquation2; - QuadraticInt_t ReservedEquation3; - - // Total Power configuration, use defines from PwrConfig_e - uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured - uint8_t TotalPowerSpare1; - uint16_t TotalPowerSpare2; - - // APCC Settings - uint16_t PccThresholdLow; - uint16_t PccThresholdHigh; - uint32_t MGpuFanBoostLimitRpm; - uint32_t PaddingAPCC[5]; - - // Temperature Dependent Vmin - uint16_t VDDGFX_TVmin; //Celcius - uint16_t VDDSOC_TVmin; //Celcius - uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 - uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 - uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 - uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 - - uint16_t VDDGFX_TVminHystersis; // Celcius - uint16_t VDDSOC_TVminHystersis; // Celcius - - // BTC Setting - uint32_t BtcConfig; - - uint16_t SsFmin[10]; // PPtable value to function similar to VFTFmin for SS Curve; Size is PPCLK_COUNT rounded to nearest multiple of 2 - uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; - - // SECTION: Board Reserved - uint32_t Reserved[8]; - - // SECTION: BOARD PARAMETERS - // I2C Control - I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; - - // SVI2 Board Parameters - uint16_t MaxVoltageStepGfx; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. - uint16_t MaxVoltageStepSoc; // In mV(Q2) Max voltage step that SMU will request. Multiple steps are taken if voltage change exceeds this value. - - uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields - uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields - - uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t ExternalSensorPresent; // External RDI connected to TMON (aka TEMP IN) - uint8_t Padding8_V; - - // Telemetry Settings - uint16_t GfxMaxCurrent; // in Amps - int8_t GfxOffset; // in Amps - uint8_t Padding_TelemetryGfx; - - uint16_t SocMaxCurrent; // in Amps - int8_t SocOffset; // in Amps - uint8_t Padding_TelemetrySoc; - - uint16_t Mem0MaxCurrent; // in Amps - int8_t Mem0Offset; // in Amps - uint8_t Padding_TelemetryMem0; - - uint16_t Mem1MaxCurrent; // in Amps - int8_t Mem1Offset; // in Amps - uint8_t Padding_TelemetryMem1; - - // GPIO Settings - uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching - uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching - uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event - uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event - - uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event - uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event - uint8_t GthrGpio; // GPIO pin configured for GTHR Event - uint8_t GthrPolarity; // replace GPIO polarity for GTHR - - // LED Display Settings - uint8_t LedPin0; // GPIO number for LedPin[0] - uint8_t LedPin1; // GPIO number for LedPin[1] - uint8_t LedPin2; // GPIO number for LedPin[2] - uint8_t padding8_4; - - // GFXCLK PLL Spread Spectrum - uint8_t PllGfxclkSpreadEnabled; // on or off - uint8_t PllGfxclkSpreadPercent; // Q4.4 - uint16_t PllGfxclkSpreadFreq; // kHz - - // GFXCLK DFLL Spread Spectrum - uint8_t DfllGfxclkSpreadEnabled; // on or off - uint8_t DfllGfxclkSpreadPercent; // Q4.4 - uint16_t DfllGfxclkSpreadFreq; // kHz - - // UCLK Spread Spectrum - uint8_t UclkSpreadEnabled; // on or off - uint8_t UclkSpreadPercent; // Q4.4 - uint16_t UclkSpreadFreq; // kHz - - // SOCCLK Spread Spectrum - uint8_t SoclkSpreadEnabled; // on or off - uint8_t SocclkSpreadPercent; // Q4.4 - uint16_t SocclkSpreadFreq; // kHz - - // Total board power - uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power - uint16_t BoardPadding; - - // Mvdd Svi2 Div Ratio Setting - uint32_t MvddRatio; // This is used for MVDD Vid workaround. It has 16 fractional bits (Q16.16) - - uint8_t RenesesLoadLineEnabled; - uint8_t GfxLoadlineResistance; - uint8_t SocLoadlineResistance; - uint8_t Padding8_Loadline; - - uint32_t BoardReserved[8]; - - // Padding for MMHUB - do not modify this - uint32_t MmHubPadding[8]; // SMU internal use - -} PPTable_t; - -typedef struct { - // Time constant parameters for clock averages in ms - uint16_t GfxclkAverageLpfTau; - uint16_t SocclkAverageLpfTau; - uint16_t UclkAverageLpfTau; - uint16_t GfxActivityLpfTau; - uint16_t UclkActivityLpfTau; - uint16_t SocketPowerLpfTau; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} DriverSmuConfig_t; - -typedef struct { - - uint16_t GfxclkFmin; // MHz - uint16_t GfxclkFmax; // MHz - uint16_t GfxclkFreq1; // MHz - uint16_t GfxclkVolt1; // mV (Q2) - uint16_t GfxclkFreq2; // MHz - uint16_t GfxclkVolt2; // mV (Q2) - uint16_t GfxclkFreq3; // MHz - uint16_t GfxclkVolt3; // mV (Q2) - uint16_t UclkFmax; // MHz - int16_t OverDrivePct; // % - uint16_t FanMaximumRpm; - uint16_t FanMinimumPwm; - uint16_t FanTargetTemperature; // Degree Celcius - uint16_t MaxOpTemp; // Degree Celcius - uint16_t FanZeroRpmEnable; - uint16_t Padding; - - uint32_t MmHubPadding[8]; // SMU internal use - -} OverDriveTable_t; - -typedef struct { - uint16_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageSocclkFrequency; - uint16_t AverageUclkFrequency ; - uint16_t AverageGfxActivity ; - uint16_t AverageUclkActivity ; - uint8_t CurrSocVoltageOffset ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t AverageSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureMem ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrMem0 ; - uint16_t TemperatureVrMem1 ; - uint16_t TemperatureVrSoc ; - uint16_t TemperatureLiquid0 ; - uint16_t TemperatureLiquid1 ; - uint16_t TemperaturePlx ; - uint16_t Padding16 ; - uint32_t ThrottlerStatus ; - - uint8_t LinkDpmLevel; - uint8_t Padding8_2; - uint16_t CurrFanSpeed; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} SmuMetrics_t; - -typedef struct { - uint16_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageSocclkFrequency; - uint16_t AverageUclkFrequency ; - uint16_t AverageGfxActivity ; - uint16_t AverageUclkActivity ; - uint8_t CurrSocVoltageOffset ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t AverageSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureMem ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrMem0 ; - uint16_t TemperatureVrMem1 ; - uint16_t TemperatureVrSoc ; - uint16_t TemperatureLiquid0 ; - uint16_t TemperatureLiquid1 ; - uint16_t TemperaturePlx ; - uint16_t Padding16 ; - uint32_t ThrottlerStatus ; - - uint8_t LinkDpmLevel; - uint8_t Padding8_2; - uint16_t CurrFanSpeed; - - uint32_t EnergyAccumulator; - uint16_t AverageVclkFrequency ; - uint16_t AverageDclkFrequency ; - uint16_t VcnActivityPercentage ; - uint16_t padding16_2; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} SmuMetrics_NV12_t; - -typedef struct { - uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Padding[3]; - - uint32_t MmHubPadding[8]; // SMU internal use -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCEFCLK, - WM_COUNT, -} WM_CLOCK_e; - -typedef struct { - // Watermarks - WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; - - uint32_t MmHubPadding[8]; // SMU internal use -} Watermarks_t; - -typedef struct { - uint16_t avgPsmCount[28]; - uint16_t minPsmCount[28]; - float avgPsmVoltage[28]; - float minPsmVoltage[28]; - - uint32_t MmHubPadding[32]; // SMU internal use -} AvfsDebugTable_t_NV14; - -typedef struct { - uint16_t avgPsmCount[36]; - uint16_t minPsmCount[36]; - float avgPsmVoltage[36]; - float minPsmVoltage[36]; - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsDebugTable_t_NV10; - -typedef struct { - uint8_t AvfsVersion; - uint8_t Padding; - - uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; - - int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; - - uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits - - - int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units - - uint32_t EnabledAvfsModules[2]; //NV10 - 36 AVFS modules - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsFuseOverride_t; - -typedef struct { - - uint8_t Gfx_ActiveHystLimit; - uint8_t Gfx_IdleHystLimit; - uint8_t Gfx_FPS; - uint8_t Gfx_MinActiveFreqType; - uint8_t Gfx_BoosterFreqType; - uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Gfx_MinActiveFreq; // MHz - uint16_t Gfx_BoosterFreq; // MHz - uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Gfx_PD_Data_limit_a; // Q16 - uint32_t Gfx_PD_Data_limit_b; // Q16 - uint32_t Gfx_PD_Data_limit_c; // Q16 - uint32_t Gfx_PD_Data_error_coeff; // Q16 - uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 - - uint8_t Soc_ActiveHystLimit; - uint8_t Soc_IdleHystLimit; - uint8_t Soc_FPS; - uint8_t Soc_MinActiveFreqType; - uint8_t Soc_BoosterFreqType; - uint8_t Soc_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Soc_MinActiveFreq; // MHz - uint16_t Soc_BoosterFreq; // MHz - uint16_t Soc_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Soc_PD_Data_limit_a; // Q16 - uint32_t Soc_PD_Data_limit_b; // Q16 - uint32_t Soc_PD_Data_limit_c; // Q16 - uint32_t Soc_PD_Data_error_coeff; // Q16 - uint32_t Soc_PD_Data_error_rate_coeff; // Q16 - - uint8_t Mem_ActiveHystLimit; - uint8_t Mem_IdleHystLimit; - uint8_t Mem_FPS; - uint8_t Mem_MinActiveFreqType; - uint8_t Mem_BoosterFreqType; - uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Mem_MinActiveFreq; // MHz - uint16_t Mem_BoosterFreq; // MHz - uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Mem_PD_Data_limit_a; // Q16 - uint32_t Mem_PD_Data_limit_b; // Q16 - uint32_t Mem_PD_Data_limit_c; // Q16 - uint32_t Mem_PD_Data_error_coeff; // Q16 - uint32_t Mem_PD_Data_error_rate_coeff; // Q16 - - uint32_t Mem_UpThreshold_Limit; // Q16 - uint8_t Mem_UpHystLimit; - uint8_t Mem_DownHystLimit; - uint16_t Mem_Fps; - - uint32_t MmHubPadding[8]; // SMU internal use - -} DpmActivityMonitorCoeffInt_t; - - -// Workload bits -#define WORKLOAD_PPLIB_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 -#define WORKLOAD_PPLIB_VIDEO_BIT 3 -#define WORKLOAD_PPLIB_VR_BIT 4 -#define WORKLOAD_PPLIB_COMPUTE_BIT 5 -#define WORKLOAD_PPLIB_CUSTOM_BIT 6 -#define WORKLOAD_PPLIB_COUNT 7 - - -// These defines are used with the following messages: -// SMC_MSG_TransferTableDram2Smu -// SMC_MSG_TransferTableSmu2Dram - -// Table transfer status -#define TABLE_TRANSFER_OK 0x0 -#define TABLE_TRANSFER_FAILED 0xFF - -// Table types -#define TABLE_PPTABLE 0 -#define TABLE_WATERMARKS 1 -#define TABLE_AVFS 2 -#define TABLE_AVFS_PSM_DEBUG 3 -#define TABLE_AVFS_FUSE_OVERRIDE 4 -#define TABLE_PMSTATUSLOG 5 -#define TABLE_SMU_METRICS 6 -#define TABLE_DRIVER_SMU_CONFIG 7 -#define TABLE_ACTIVITY_MONITOR_COEFF 8 -#define TABLE_OVERDRIVE 9 -#define TABLE_I2C_COMMANDS 10 -#define TABLE_PACE 11 -#define TABLE_COUNT 12 - -//RLC Pace Table total number of levels -#define RLC_PACE_TABLE_NUM_LEVELS 16 - -typedef struct { - float FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; - - uint32_t MmHubPadding[8]; // SMU internal use -} RlcPaceFlopsPerByteOverride_t; - -// These defines are used with the SMC_MSG_SetUclkFastSwitch message. -#define UCLK_SWITCH_SLOW 0 -#define UCLK_SWITCH_FAST 1 -#endif 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 deleted file mode 100644 index 5ef9c92f57c4..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if_sienna_cichlid.h +++ /dev/null @@ -1,1242 +0,0 @@ -/* - * 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 __SMU11_DRIVER_IF_SIENNA_CICHLID_H__ -#define __SMU11_DRIVER_IF_SIENNA_CICHLID_H__ - -// *** IMPORTANT *** -// SMU TEAM: Always increment the interface version if -// any structure is changed in this file -#define SMU11_DRIVER_IF_VERSION 0x35 - -#define PPTABLE_Sienna_Cichlid_SMU_VERSION 5 - -#define NUM_GFXCLK_DPM_LEVELS 16 -#define NUM_SMNCLK_DPM_LEVELS 2 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_MP0CLK_DPM_LEVELS 2 -#define NUM_DCLK_DPM_LEVELS 8 -#define NUM_VCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 8 -#define NUM_PHYCLK_DPM_LEVELS 8 -#define NUM_DISPCLK_DPM_LEVELS 8 -#define NUM_PIXCLK_DPM_LEVELS 8 -#define NUM_DTBCLK_DPM_LEVELS 8 -#define NUM_UCLK_DPM_LEVELS 4 -#define NUM_MP1CLK_DPM_LEVELS 2 -#define NUM_LINK_LEVELS 2 -#define NUM_FCLK_DPM_LEVELS 8 -#define NUM_XGMI_LEVELS 2 -#define NUM_XGMI_PSTATE_LEVELS 4 -#define NUM_OD_FAN_MAX_POINTS 6 - -#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) -#define MAX_SMNCLK_DPM_LEVEL (NUM_SMNCLK_DPM_LEVELS - 1) -#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) -#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) -#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) -#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) -#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) -#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) -#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) -#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) -#define MAX_DTBCLK_DPM_LEVEL (NUM_DTBCLK_DPM_LEVELS - 1) -#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) -#define MAX_MP1CLK_DPM_LEVEL (NUM_MP1CLK_DPM_LEVELS - 1) -#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) -#define MAX_FCLK_DPM_LEVEL (NUM_FCLK_DPM_LEVELS - 1) - -//Gemini Modes -#define PPSMC_GeminiModeNone 0 //Single GPU board -#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board -#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board - -// Feature Control Defines -// DPM -#define FEATURE_DPM_PREFETCHER_BIT 0 -#define FEATURE_DPM_GFXCLK_BIT 1 -#define FEATURE_DPM_GFX_GPO_BIT 2 -#define FEATURE_DPM_UCLK_BIT 3 -#define FEATURE_DPM_FCLK_BIT 4 -#define FEATURE_DPM_SOCCLK_BIT 5 -#define FEATURE_DPM_MP0CLK_BIT 6 -#define FEATURE_DPM_LINK_BIT 7 -#define FEATURE_DPM_DCEFCLK_BIT 8 -#define FEATURE_DPM_XGMI_BIT 9 -#define FEATURE_MEM_VDDCI_SCALING_BIT 10 -#define FEATURE_MEM_MVDD_SCALING_BIT 11 - -//Idle -#define FEATURE_DS_GFXCLK_BIT 12 -#define FEATURE_DS_SOCCLK_BIT 13 -#define FEATURE_DS_FCLK_BIT 14 -#define FEATURE_DS_LCLK_BIT 15 -#define FEATURE_DS_DCEFCLK_BIT 16 -#define FEATURE_DS_UCLK_BIT 17 -#define FEATURE_GFX_ULV_BIT 18 -#define FEATURE_FW_DSTATE_BIT 19 -#define FEATURE_GFXOFF_BIT 20 -#define FEATURE_BACO_BIT 21 -#define FEATURE_MM_DPM_PG_BIT 22 -#define FEATURE_SPARE_23_BIT 23 -//Throttler/Response -#define FEATURE_PPT_BIT 24 -#define FEATURE_TDC_BIT 25 -#define FEATURE_APCC_PLUS_BIT 26 -#define FEATURE_GTHR_BIT 27 -#define FEATURE_ACDC_BIT 28 -#define FEATURE_VR0HOT_BIT 29 -#define FEATURE_VR1HOT_BIT 30 -#define FEATURE_FW_CTF_BIT 31 -#define FEATURE_FAN_CONTROL_BIT 32 -#define FEATURE_THERMAL_BIT 33 -#define FEATURE_GFX_DCS_BIT 34 -//VF -#define FEATURE_RM_BIT 35 -#define FEATURE_LED_DISPLAY_BIT 36 -//Other -#define FEATURE_GFX_SS_BIT 37 -#define FEATURE_OUT_OF_BAND_MONITOR_BIT 38 -#define FEATURE_TEMP_DEPENDENT_VMIN_BIT 39 - -#define FEATURE_MMHUB_PG_BIT 40 -#define FEATURE_ATHUB_PG_BIT 41 -#define FEATURE_APCC_DFLL_BIT 42 -#define FEATURE_DF_SUPERV_BIT 43 -#define FEATURE_RSMU_SMN_CG_BIT 44 -#define FEATURE_DF_CSTATE_BIT 45 -#define FEATURE_2_STEP_PSTATE_BIT 46 -#define FEATURE_SMNCLK_DPM_BIT 47 -#define FEATURE_PERLINK_GMIDOWN_BIT 48 -#define FEATURE_GFX_EDC_BIT 49 -#define FEATURE_SPARE_50_BIT 50 -#define FEATURE_SPARE_51_BIT 51 -#define FEATURE_SPARE_52_BIT 52 -#define FEATURE_SPARE_53_BIT 53 -#define FEATURE_SPARE_54_BIT 54 -#define FEATURE_SPARE_55_BIT 55 -#define FEATURE_SPARE_56_BIT 56 -#define FEATURE_SPARE_57_BIT 57 -#define FEATURE_SPARE_58_BIT 58 -#define FEATURE_SPARE_59_BIT 59 -#define FEATURE_SPARE_60_BIT 60 -#define FEATURE_SPARE_61_BIT 61 -#define FEATURE_SPARE_62_BIT 62 -#define FEATURE_SPARE_63_BIT 63 -#define NUM_FEATURES 64 - -//For use with feature control messages -typedef enum { - FEATURE_PWR_ALL, - FEATURE_PWR_S5, - FEATURE_PWR_BACO, - FEATURE_PWR_SOC, - FEATURE_PWR_GFX, - FEATURE_PWR_DOMAIN_COUNT, -} FEATURE_PWR_DOMAIN_e; - - -// Debug Overrides Bitmask -#define DPM_OVERRIDE_DISABLE_FCLK_PID 0x00000001 -#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_FCLK 0x00000004 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_FCLK 0x00000008 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_FCLK 0x00000010 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00000020 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00000040 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_DCE_FCLK 0x00000080 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_MP0_SOCCLK 0x00000100 -#define DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN 0x00000200 -#define DPM_OVERRIDE_DISABLE_MEMORY_TEMPERATURE_READ 0x00000400 -#define DPM_OVERRIDE_DISABLE_VOLT_LINK_VCN_DCEFCLK 0x00000800 -#define DPM_OVERRIDE_ENABLE_FAST_FCLK_TIMER 0x00001000 -#define DPM_OVERRIDE_DISABLE_VCN_PG 0x00002000 -#define DPM_OVERRIDE_DISABLE_FMAX_VMAX 0x00004000 - -// VR Mapping Bit Defines -#define VR_MAPPING_VR_SELECT_MASK 0x01 -#define VR_MAPPING_VR_SELECT_SHIFT 0x00 - -#define VR_MAPPING_PLANE_SELECT_MASK 0x02 -#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 - -// PSI Bit Defines -#define PSI_SEL_VR0_PLANE0_PSI0 0x01 -#define PSI_SEL_VR0_PLANE0_PSI1 0x02 -#define PSI_SEL_VR0_PLANE1_PSI0 0x04 -#define PSI_SEL_VR0_PLANE1_PSI1 0x08 -#define PSI_SEL_VR1_PLANE0_PSI0 0x10 -#define PSI_SEL_VR1_PLANE0_PSI1 0x20 -#define PSI_SEL_VR1_PLANE1_PSI0 0x40 -#define PSI_SEL_VR1_PLANE1_PSI1 0x80 - -// Throttler Control/Status Bits -#define THROTTLER_PADDING_BIT 0 -#define THROTTLER_TEMP_EDGE_BIT 1 -#define THROTTLER_TEMP_HOTSPOT_BIT 2 -#define THROTTLER_TEMP_MEM_BIT 3 -#define THROTTLER_TEMP_VR_GFX_BIT 4 -#define THROTTLER_TEMP_VR_MEM0_BIT 5 -#define THROTTLER_TEMP_VR_MEM1_BIT 6 -#define THROTTLER_TEMP_VR_SOC_BIT 7 -#define THROTTLER_TEMP_LIQUID0_BIT 8 -#define THROTTLER_TEMP_LIQUID1_BIT 9 -#define THROTTLER_TEMP_PLX_BIT 10 -#define THROTTLER_TDC_GFX_BIT 11 -#define THROTTLER_TDC_SOC_BIT 12 -#define THROTTLER_PPT0_BIT 13 -#define THROTTLER_PPT1_BIT 14 -#define THROTTLER_PPT2_BIT 15 -#define THROTTLER_PPT3_BIT 16 -#define THROTTLER_FIT_BIT 17 -#define THROTTLER_PPM_BIT 18 -#define THROTTLER_APCC_BIT 19 - -// FW DState Features Control Bits -// FW DState Features Control Bits -#define FW_DSTATE_SOC_ULV_BIT 0 -#define FW_DSTATE_G6_HSR_BIT 1 -#define FW_DSTATE_G6_PHY_VDDCI_OFF_BIT 2 -#define FW_DSTATE_MP0_DS_BIT 3 -#define FW_DSTATE_SMN_DS_BIT 4 -#define FW_DSTATE_MP1_DS_BIT 5 -#define FW_DSTATE_MP1_WHISPER_MODE_BIT 6 -#define FW_DSTATE_SOC_LIV_MIN_BIT 7 -#define FW_DSTATE_SOC_PLL_PWRDN_BIT 8 -#define FW_DSTATE_MEM_PLL_PWRDN_BIT 9 -#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT 10 -#define FW_DSTATE_MEM_PSI_BIT 11 - -#define FW_DSTATE_SOC_ULV_MASK (1 << FW_DSTATE_SOC_ULV_BIT ) -#define FW_DSTATE_G6_HSR_MASK (1 << FW_DSTATE_G6_HSR_BIT ) -#define FW_DSTATE_G6_PHY_VDDCI_OFF_MASK (1 << FW_DSTATE_G6_PHY_VDDCI_OFF_BIT ) -#define FW_DSTATE_MP1_DS_MASK (1 << FW_DSTATE_MP1_DS_BIT ) -#define FW_DSTATE_MP0_DS_MASK (1 << FW_DSTATE_MP0_DS_BIT ) -#define FW_DSTATE_SMN_DS_MASK (1 << FW_DSTATE_SMN_DS_BIT ) -#define FW_DSTATE_MP1_WHISPER_MODE_MASK (1 << FW_DSTATE_MP1_WHISPER_MODE_BIT ) -#define FW_DSTATE_SOC_LIV_MIN_MASK (1 << FW_DSTATE_SOC_LIV_MIN_BIT ) -#define FW_DSTATE_SOC_PLL_PWRDN_MASK (1 << FW_DSTATE_SOC_PLL_PWRDN_BIT ) -#define FW_DSTATE_MEM_PLL_PWRDN_MASK (1 << FW_DSTATE_MEM_PLL_PWRDN_BIT ) -#define FW_DSTATE_OPTIMIZE_MALL_REFRESH_MASK (1 << FW_DSTATE_OPTIMIZE_MALL_REFRESH_BIT ) -#define FW_DSTATE_MEM_PSI_MASK (1 << FW_DSTATE_MEM_PSI_BIT ) - -// GFX GPO Feature Contains PACE and DEM sub features -#define GFX_GPO_PACE_BIT 0 -#define GFX_GPO_DEM_BIT 1 - -#define GFX_GPO_PACE_MASK (1 << GFX_GPO_PACE_BIT) -#define GFX_GPO_DEM_MASK (1 << GFX_GPO_DEM_BIT ) - -#define GPO_UPDATE_REQ_UCLKDPM_MASK 0x1 -#define GPO_UPDATE_REQ_FCLKDPM_MASK 0x2 -#define GPO_UPDATE_REQ_MALLHIT_MASK 0x4 - - -//LED Display Mask & Control Bits -#define LED_DISPLAY_GFX_DPM_BIT 0 -#define LED_DISPLAY_PCIE_BIT 1 -#define LED_DISPLAY_ERROR_BIT 2 - -//RLC Pace Table total number of levels -#define RLC_PACE_TABLE_NUM_LEVELS 16 - -typedef enum { - DRAM_BIT_WIDTH_DISABLED = 0, - DRAM_BIT_WIDTH_X_8, - DRAM_BIT_WIDTH_X_16, - DRAM_BIT_WIDTH_X_32, - DRAM_BIT_WIDTH_X_64, // NOT USED. - DRAM_BIT_WIDTH_X_128, - DRAM_BIT_WIDTH_COUNT, -} DRAM_BIT_WIDTH_TYPE_e; - -//I2C Interface -#define NUM_I2C_CONTROLLERS 16 - -#define I2C_CONTROLLER_ENABLED 1 -#define I2C_CONTROLLER_DISABLED 0 - -#define MAX_SW_I2C_COMMANDS 24 - -typedef enum { - I2C_CONTROLLER_PORT_0 = 0, //CKSVII2C0 - I2C_CONTROLLER_PORT_1 = 1, //CKSVII2C1 - I2C_CONTROLLER_PORT_COUNT, -} I2cControllerPort_e; - -typedef enum { - I2C_CONTROLLER_NAME_VR_GFX = 0, - I2C_CONTROLLER_NAME_VR_SOC, - I2C_CONTROLLER_NAME_VR_VDDCI, - I2C_CONTROLLER_NAME_VR_MVDD, - I2C_CONTROLLER_NAME_LIQUID0, - I2C_CONTROLLER_NAME_LIQUID1, - I2C_CONTROLLER_NAME_PLX, - I2C_CONTROLLER_NAME_OTHER, - I2C_CONTROLLER_NAME_COUNT, -} I2cControllerName_e; - -typedef enum { - I2C_CONTROLLER_THROTTLER_TYPE_NONE = 0, - I2C_CONTROLLER_THROTTLER_VR_GFX, - I2C_CONTROLLER_THROTTLER_VR_SOC, - I2C_CONTROLLER_THROTTLER_VR_VDDCI, - I2C_CONTROLLER_THROTTLER_VR_MVDD, - I2C_CONTROLLER_THROTTLER_LIQUID0, - I2C_CONTROLLER_THROTTLER_LIQUID1, - I2C_CONTROLLER_THROTTLER_PLX, - I2C_CONTROLLER_THROTTLER_INA3221, - I2C_CONTROLLER_THROTTLER_COUNT, -} I2cControllerThrottler_e; - -typedef enum { - I2C_CONTROLLER_PROTOCOL_VR_XPDE132G5, - I2C_CONTROLLER_PROTOCOL_VR_IR35217, - I2C_CONTROLLER_PROTOCOL_TMP_TMP102A, - I2C_CONTROLLER_PROTOCOL_INA3221, - I2C_CONTROLLER_PROTOCOL_COUNT, -} I2cControllerProtocol_e; - -typedef struct { - uint8_t Enabled; - uint8_t Speed; - uint8_t SlaveAddress; - uint8_t ControllerPort; - uint8_t ControllerName; - uint8_t ThermalThrotter; - uint8_t I2cProtocol; - uint8_t PaddingConfig; -} I2cControllerConfig_t; - -typedef enum { - I2C_PORT_SVD_SCL = 0, - I2C_PORT_GPIO, -} I2cPort_e; - -typedef enum { - I2C_SPEED_FAST_50K = 0, //50 Kbits/s - I2C_SPEED_FAST_100K, //100 Kbits/s - I2C_SPEED_FAST_400K, //400 Kbits/s - I2C_SPEED_FAST_PLUS_1M, //1 Mbits/s (in fast mode) - I2C_SPEED_HIGH_1M, //1 Mbits/s (in high speed mode) - I2C_SPEED_HIGH_2M, //2.3 Mbits/s - I2C_SPEED_COUNT, -} I2cSpeed_e; - -typedef enum { - I2C_CMD_READ = 0, - I2C_CMD_WRITE, - I2C_CMD_COUNT, -} I2cCmdType_e; - -typedef enum { - FAN_MODE_AUTO = 0, - FAN_MODE_MANUAL_LINEAR, -} FanMode_e; - -#define CMDCONFIG_STOP_BIT 0 -#define CMDCONFIG_RESTART_BIT 1 -#define CMDCONFIG_READWRITE_BIT 2 //bit should be 0 for read, 1 for write - -#define CMDCONFIG_STOP_MASK (1 << CMDCONFIG_STOP_BIT) -#define CMDCONFIG_RESTART_MASK (1 << CMDCONFIG_RESTART_BIT) -#define CMDCONFIG_READWRITE_MASK (1 << CMDCONFIG_READWRITE_BIT) - -typedef struct { - uint8_t ReadWriteData; //Return data for read. Data to send for write - uint8_t CmdConfig; //Includes whether associated command should have a stop or restart command, and is a read or write -} SwI2cCmd_t; //SW I2C Command Table - -typedef struct { - uint8_t I2CcontrollerPort; //CKSVII2C0(0) or //CKSVII2C1(1) - uint8_t I2CSpeed; //Use I2cSpeed_e to indicate speed to select - uint8_t SlaveAddress; //Slave address of device - uint8_t NumCmds; //Number of commands - - SwI2cCmd_t SwI2cCmds[MAX_SW_I2C_COMMANDS]; -} SwI2cRequest_t; // SW I2C Request Table - -typedef struct { - SwI2cRequest_t SwI2cRequest; - - uint32_t Spare[8]; - uint32_t MmHubPadding[8]; // SMU internal use -} SwI2cRequestExternal_t; - -//D3HOT sequences -typedef enum { - BACO_SEQUENCE, - MSR_SEQUENCE, - BAMACO_SEQUENCE, - ULPS_SEQUENCE, - D3HOT_SEQUENCE_COUNT, -} D3HOTSequence_e; - -//THis is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_DYNAMIC_MODE = 0, - PG_STATIC_MODE, -} PowerGatingMode_e; - -//This is aligned with RSMU PGFSM Register Mapping -typedef enum { - PG_POWER_DOWN = 0, - PG_POWER_UP, -} PowerGatingSettings_e; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} QuadraticInt_t; - -typedef struct { - uint32_t a; // store in fixed point, [31:20] signed integer, [19:0] fractional bits - uint32_t b; // store in fixed point, [31:20] signed integer, [19:0] fractional bits - uint32_t c; // store in fixed point, [31:20] signed integer, [19:0] fractional bits -} QuadraticFixedPoint_t; - -typedef struct { - uint32_t m; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable -} LinearInt_t; - -typedef struct { - uint32_t a; // store in IEEE float format in this variable - uint32_t b; // store in IEEE float format in this variable - uint32_t c; // store in IEEE float format in this variable -} DroopInt_t; - -//Piecewise linear droop model, Sienna_Cichlid currently used only for GFX DFLL -#define NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS 5 -typedef enum { - PIECEWISE_LINEAR_FUSED_MODEL = 0, - PIECEWISE_LINEAR_PP_MODEL, - QUADRATIC_PP_MODEL, -} DfllDroopModelSelect_e; - -typedef struct { - uint32_t Fset[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //in GHz, store in IEEE float format - uint32_t Vdroop[NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS]; //in V , store in IEEE float format -}PiecewiseLinearDroopInt_t; - -typedef enum { - GFXCLK_SOURCE_PLL = 0, - GFXCLK_SOURCE_DFLL, - GFXCLK_SOURCE_COUNT, -} GFXCLK_SOURCE_e; - -//Only Clks that have DPM descriptors are listed here -typedef enum { - PPCLK_GFXCLK = 0, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_FCLK, - PPCLK_DCLK_0, - PPCLK_VCLK_0, - PPCLK_DCLK_1, - PPCLK_VCLK_1, - PPCLK_DCEFCLK, - PPCLK_DISPCLK, - PPCLK_PIXCLK, - PPCLK_PHYCLK, - PPCLK_DTBCLK, - PPCLK_COUNT, -} PPCLK_e; - -typedef enum { - VOLTAGE_MODE_AVFS = 0, - VOLTAGE_MODE_AVFS_SS, - VOLTAGE_MODE_SS, - VOLTAGE_MODE_COUNT, -} VOLTAGE_MODE_e; - - -typedef enum { - AVFS_VOLTAGE_GFX = 0, - AVFS_VOLTAGE_SOC, - AVFS_VOLTAGE_COUNT, -} AVFS_VOLTAGE_TYPE_e; - -typedef enum { - UCLK_DIV_BY_1 = 0, - UCLK_DIV_BY_2, - UCLK_DIV_BY_4, - UCLK_DIV_BY_8, -} UCLK_DIV_e; - -typedef enum { - GPIO_INT_POLARITY_ACTIVE_LOW = 0, - GPIO_INT_POLARITY_ACTIVE_HIGH, -} GpioIntPolarity_e; - -typedef enum { - PWR_CONFIG_TDP = 0, - PWR_CONFIG_TGP, - PWR_CONFIG_TCP_ESTIMATED, - PWR_CONFIG_TCP_MEASURED, -} PwrConfig_e; - -typedef enum { - XGMI_LINK_RATE_2 = 2, // 2Gbps - XGMI_LINK_RATE_4 = 4, // 4Gbps - XGMI_LINK_RATE_8 = 8, // 8Gbps - XGMI_LINK_RATE_12 = 12, // 12Gbps - XGMI_LINK_RATE_16 = 16, // 16Gbps - XGMI_LINK_RATE_17 = 17, // 17Gbps - XGMI_LINK_RATE_18 = 18, // 18Gbps - XGMI_LINK_RATE_19 = 19, // 19Gbps - XGMI_LINK_RATE_20 = 20, // 20Gbps - XGMI_LINK_RATE_21 = 21, // 21Gbps - XGMI_LINK_RATE_22 = 22, // 22Gbps - XGMI_LINK_RATE_23 = 23, // 23Gbps - XGMI_LINK_RATE_24 = 24, // 24Gbps - XGMI_LINK_RATE_25 = 25, // 25Gbps - XGMI_LINK_RATE_COUNT -} XGMI_LINK_RATE_e; - -typedef enum { - XGMI_LINK_WIDTH_1 = 0, // x1 - XGMI_LINK_WIDTH_2, // x2 - XGMI_LINK_WIDTH_4, // x4 - XGMI_LINK_WIDTH_8, // x8 - XGMI_LINK_WIDTH_9, // x9 - XGMI_LINK_WIDTH_16, // x16 - XGMI_LINK_WIDTH_COUNT -} XGMI_LINK_WIDTH_e; - -typedef struct { - uint8_t VoltageMode; // 0 - AVFS only, 1- min(AVFS,SS), 2-SS only - uint8_t SnapToDiscrete; // 0 - Fine grained DPM, 1 - Discrete DPM - uint8_t NumDiscreteLevels; // Set to 2 (Fmin, Fmax) when using fine grained DPM, otherwise set to # discrete levels used - uint8_t Padding; - LinearInt_t ConversionToAvfsClk; // Transfer function to AVFS Clock (GHz->GHz) - QuadraticInt_t SsCurve; // Slow-slow curve (GHz->V) - uint16_t SsFmin; // Fmin for SS curve. If SS curve is selected, will use V@SSFmin for F <= Fmin - uint16_t Padding16; -} DpmDescriptor_t; - -typedef enum { - PPT_THROTTLER_PPT0, - PPT_THROTTLER_PPT1, - PPT_THROTTLER_PPT2, - PPT_THROTTLER_PPT3, - PPT_THROTTLER_COUNT -} PPT_THROTTLER_e; - -typedef enum { - TEMP_EDGE, - TEMP_HOTSPOT, - TEMP_MEM, - TEMP_VR_GFX, - TEMP_VR_MEM0, - TEMP_VR_MEM1, - TEMP_VR_SOC, - TEMP_LIQUID0, - TEMP_LIQUID1, - TEMP_PLX, - TEMP_COUNT, -} TEMP_e; - -typedef enum { - TDC_THROTTLER_GFX, - TDC_THROTTLER_SOC, - TDC_THROTTLER_COUNT -} TDC_THROTTLER_e; - -typedef enum { - CUSTOMER_VARIANT_ROW, - CUSTOMER_VARIANT_FALCON, - CUSTOMER_VARIANT_COUNT, -} CUSTOMER_VARIANT_e; - -// Used for 2-step UCLK DPM change workaround -typedef struct { - uint16_t Fmin; - uint16_t Fmax; -} UclkDpmChangeRange_t; - -typedef struct { - // MAJOR SECTION: SKU PARAMETERS - - uint32_t Version; - - // SECTION: Feature Enablement - uint32_t FeaturesToRun[NUM_FEATURES / 32]; - - // SECTION: Infrastructure Limits - uint16_t SocketPowerLimitAc[PPT_THROTTLER_COUNT]; // Watts - uint16_t SocketPowerLimitAcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms - uint16_t SocketPowerLimitDc[PPT_THROTTLER_COUNT]; // Watts - uint16_t SocketPowerLimitDcTau[PPT_THROTTLER_COUNT]; // Time constant of LPF in ms - - uint16_t TdcLimit[TDC_THROTTLER_COUNT]; // Amps - uint16_t TdcLimitTau[TDC_THROTTLER_COUNT]; // Time constant of LPF in ms - - uint16_t TemperatureLimit[TEMP_COUNT]; // Celcius - - uint32_t FitLimit; // Failures in time (failures per million parts over the defined lifetime) - - // SECTION: Power Configuration - uint8_t TotalPowerConfig; //0-TDP, 1-TGP, 2-TCP Estimated, 3-TCP Measured. Use defines from PwrConfig_e - uint8_t TotalPowerPadding[3]; - - // SECTION: APCC Settings - uint32_t ApccPlusResidencyLimit; - - //SECTION: SMNCLK DPM - uint16_t SmnclkDpmFreq [NUM_SMNCLK_DPM_LEVELS]; // in MHz - uint16_t SmnclkDpmVoltage [NUM_SMNCLK_DPM_LEVELS]; // mV(Q2) - - uint32_t PaddingAPCC[4]; - - // SECTION: Throttler settings - uint32_t ThrottlerControlMask; // See Throtter masks defines - - // SECTION: FW DSTATE Settings - uint32_t FwDStateMask; // See FW DState masks defines - - // SECTION: ULV Settings - uint16_t UlvVoltageOffsetSoc; // In mV(Q2) - uint16_t UlvVoltageOffsetGfx; // In mV(Q2) - - uint16_t MinVoltageUlvGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX in ULV mode - uint16_t MinVoltageUlvSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC in ULV mode - - uint16_t SocLIVmin; // In mV(Q2) Long Idle Vmin (deep ULV), for VDD_SOC - uint16_t PaddingLIVmin; - - uint8_t GceaLinkMgrIdleThreshold; //Set by SMU FW during enablment of GFXOFF. Controls delay for GFX SDP port disconnection during idle events - uint8_t paddingRlcUlvParams[3]; - - // SECTION: Voltage Control Parameters - uint16_t MinVoltageGfx; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_GFX - uint16_t MinVoltageSoc; // In mV(Q2) Minimum Voltage ("Vmin") of VDD_SOC - uint16_t MaxVoltageGfx; // In mV(Q2) Maximum Voltage allowable of VDD_GFX - uint16_t MaxVoltageSoc; // In mV(Q2) Maximum Voltage allowable of VDD_SOC - - uint16_t LoadLineResistanceGfx; // In mOhms with 8 fractional bits - uint16_t LoadLineResistanceSoc; // In mOhms with 8 fractional bits - - // SECTION: Temperature Dependent Vmin - uint16_t VDDGFX_TVmin; //Celcius - uint16_t VDDSOC_TVmin; //Celcius - uint16_t VDDGFX_Vmin_HiTemp; // mV Q2 - uint16_t VDDGFX_Vmin_LoTemp; // mV Q2 - uint16_t VDDSOC_Vmin_HiTemp; // mV Q2 - uint16_t VDDSOC_Vmin_LoTemp; // mV Q2 - - uint16_t VDDGFX_TVminHystersis; // Celcius - uint16_t VDDSOC_TVminHystersis; // Celcius - - //SECTION: DPM Config 1 - DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; - - uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableDtbclk [NUM_DTBCLK_DPM_LEVELS ]; // In MHz - uint16_t FreqTableFclk [NUM_FCLK_DPM_LEVELS ]; // In MHz - uint32_t Paddingclks[16]; - - uint32_t DcModeMaxFreq [PPCLK_COUNT ]; // In MHz - - uint8_t FreqTableUclkDiv [NUM_UCLK_DPM_LEVELS ]; // 0:Div-1, 1:Div-1/2, 2:Div-1/4, 3:Div-1/8 - - // Used for MALL performance boost - uint16_t FclkBoostFreq; // In Mhz - uint16_t FclkParamPadding; - - // SECTION: DPM Config 2 - uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; // in MHz - uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; // mV(Q2) - uint16_t MemVddciVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) - uint16_t MemMvddVoltage [NUM_UCLK_DPM_LEVELS]; // mV(Q2) - // GFXCLK DPM - uint16_t GfxclkFgfxoffEntry; // in Mhz - uint16_t GfxclkFinit; // in Mhz - uint16_t GfxclkFidle; // in MHz - uint8_t GfxclkSource; // 0 = PLL, 1 = DFLL - uint8_t GfxclkPadding; - - // GFX GPO - uint8_t GfxGpoSubFeatureMask; // bit 0 = PACE, bit 1 = DEM - uint8_t GfxGpoEnabledWorkPolicyMask; //Any policy that GPO can be enabled - uint8_t GfxGpoDisabledWorkPolicyMask; //Any policy that GPO can be disabled - uint8_t GfxGpoPadding[1]; - uint32_t GfxGpoVotingAllow; //For indicating which feature changes should result in a GPO table recalculation - - uint32_t GfxGpoPadding32[4]; - - uint16_t GfxDcsFopt; // Optimal GFXCLK for DCS in Mhz - uint16_t GfxDcsFclkFopt; // Optimal FCLK for DCS in Mhz - uint16_t GfxDcsUclkFopt; // Optimal UCLK for DCS in Mhz - - uint16_t DcsGfxOffVoltage; //Voltage in mV(Q2) applied to VDDGFX when entering DCS GFXOFF phase - - uint16_t DcsMinGfxOffTime; //Minimum amount of time PMFW shuts GFX OFF as part of GFX DCS phase - uint16_t DcsMaxGfxOffTime; //Maximum amount of time PMFW can shut GFX OFF as part of GFX DCS phase at a stretch. - - uint32_t DcsMinCreditAccum; //Min amount of positive credit accumulation before waking GFX up as part of DCS. - - uint16_t DcsExitHysteresis; //The min amount of time power credit accumulator should have a value > 0 before SMU exits the DCS throttling phase. - uint16_t DcsTimeout; //This is the amount of time SMU FW waits for RLC to put GFX into GFXOFF before reverting to the fallback mechanism of throttling GFXCLK to Fmin. - - uint32_t DcsParamPadding[5]; - - uint16_t FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; // Q8.8 - - // UCLK section - uint8_t LowestUclkReservedForUlv; // Set this to 1 if UCLK DPM0 is reserved for ULV-mode only - uint8_t PaddingMem[3]; - - uint8_t UclkDpmPstates [NUM_UCLK_DPM_LEVELS]; // 4 DPM states, 0-P0, 1-P1, 2-P2, 3-P3. - - // Used for 2-Step UCLK change workaround - UclkDpmChangeRange_t UclkDpmSrcFreqRange; // In Mhz - UclkDpmChangeRange_t UclkDpmTargFreqRange; // In Mhz - uint16_t UclkDpmMidstepFreq; // In Mhz - uint16_t UclkMidstepPadding; - - // Link DPM Settings - uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 3:PciE-gen4 - uint8_t PcieLaneCount[NUM_LINK_LEVELS]; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 - uint16_t LclkFreq[NUM_LINK_LEVELS]; - - // SECTION: Fan Control - uint16_t FanStopTemp; //Celcius - uint16_t FanStartTemp; //Celcius - - uint16_t FanGain[TEMP_COUNT]; - - uint16_t FanPwmMin; - uint16_t FanAcousticLimitRpm; - uint16_t FanThrottlingRpm; - uint16_t FanMaximumRpm; - uint16_t MGpuFanBoostLimitRpm; - uint16_t FanTargetTemperature; - uint16_t FanTargetGfxclk; - uint16_t FanPadding16; - uint8_t FanTempInputSelect; - uint8_t FanPadding; - uint8_t FanZeroRpmEnable; - uint8_t FanTachEdgePerRev; - - // The following are AFC override parameters. Leave at 0 to use FW defaults. - int16_t FuzzyFan_ErrorSetDelta; - int16_t FuzzyFan_ErrorRateSetDelta; - int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; - - // SECTION: AVFS - // Overrides - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - uint8_t dBtcGbGfxDfllModelSelect; //0 -> fused piece-wise model, 1 -> piece-wise linear(PPTable), 2 -> quadratic model(PPTable) - uint8_t Padding8_Avfs; - - QuadraticInt_t qAvfsGb[AVFS_VOLTAGE_COUNT]; // GHz->V Override of fused curve - DroopInt_t dBtcGbGfxPll; // GHz->V BtcGb - DroopInt_t dBtcGbGfxDfll; // GHz->V BtcGb - DroopInt_t dBtcGbSoc; // GHz->V BtcGb - LinearInt_t qAgingGb[AVFS_VOLTAGE_COUNT]; // GHz->V - - PiecewiseLinearDroopInt_t PiecewiseLinearDroopIntGfxDfll; //GHz ->Vstore in IEEE float format - - QuadraticInt_t qStaticVoltageOffset[AVFS_VOLTAGE_COUNT]; // GHz->V - - uint16_t DcTol[AVFS_VOLTAGE_COUNT]; // mV Q2 - - uint8_t DcBtcEnabled[AVFS_VOLTAGE_COUNT]; - uint8_t Padding8_GfxBtc[2]; - - uint16_t DcBtcMin[AVFS_VOLTAGE_COUNT]; // mV Q2 - uint16_t DcBtcMax[AVFS_VOLTAGE_COUNT]; // mV Q2 - - uint16_t DcBtcGb[AVFS_VOLTAGE_COUNT]; // mV Q2 - - // SECTION: XGMI - uint8_t XgmiDpmPstates[NUM_XGMI_LEVELS]; // 2 DPM states, high and low. 0-P0, 1-P1, 2-P2, 3-P3. - uint8_t XgmiDpmSpare[2]; - - // SECTION: Advanced Options - uint32_t DebugOverrides; - QuadraticInt_t ReservedEquation0; - QuadraticInt_t ReservedEquation1; - QuadraticInt_t ReservedEquation2; - QuadraticInt_t ReservedEquation3; - - // SECTION: Sku Reserved - uint8_t CustomerVariant; - uint8_t Spare[3]; - uint32_t SkuReserved[14]; - - - // MAJOR SECTION: BOARD PARAMETERS - - //SECTION: Gaming Clocks - uint32_t GamingClk[6]; - - // SECTION: I2C Control - I2cControllerConfig_t I2cControllers[NUM_I2C_CONTROLLERS]; - - uint8_t GpioScl; // GPIO Number for SCL Line, used only for CKSVII2C1 - uint8_t GpioSda; // GPIO Number for SDA Line, used only for CKSVII2C1 - uint8_t FchUsbPdSlaveAddr; //For requesting USB PD controller S-states via FCH I2C when entering PME turn off - uint8_t I2cSpare[1]; - - // SECTION: SVI2 Board Parameters - uint8_t VddGfxVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddSocVrMapping; // Use VR_MAPPING* bitfields - uint8_t VddMem0VrMapping; // Use VR_MAPPING* bitfields - uint8_t VddMem1VrMapping; // Use VR_MAPPING* bitfields - - uint8_t GfxUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t SocUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t VddciUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - uint8_t MvddUlvPhaseSheddingMask; // set this to 1 to set PSI0/1 to 1 in ULV mode - - // SECTION: Telemetry Settings - uint16_t GfxMaxCurrent; // in Amps - int8_t GfxOffset; // in Amps - uint8_t Padding_TelemetryGfx; - - uint16_t SocMaxCurrent; // in Amps - int8_t SocOffset; // in Amps - uint8_t Padding_TelemetrySoc; - - uint16_t Mem0MaxCurrent; // in Amps - int8_t Mem0Offset; // in Amps - uint8_t Padding_TelemetryMem0; - - uint16_t Mem1MaxCurrent; // in Amps - int8_t Mem1Offset; // in Amps - uint8_t Padding_TelemetryMem1; - - uint32_t MvddRatio; // This is used for MVDD Svi2 Div Ratio workaround. It has 16 fractional bits (Q16.16) - - // SECTION: GPIO Settings - uint8_t AcDcGpio; // GPIO pin configured for AC/DC switching - uint8_t AcDcPolarity; // GPIO polarity for AC/DC switching - uint8_t VR0HotGpio; // GPIO pin configured for VR0 HOT event - uint8_t VR0HotPolarity; // GPIO polarity for VR0 HOT event - - uint8_t VR1HotGpio; // GPIO pin configured for VR1 HOT event - uint8_t VR1HotPolarity; // GPIO polarity for VR1 HOT event - uint8_t GthrGpio; // GPIO pin configured for GTHR Event - uint8_t GthrPolarity; // replace GPIO polarity for GTHR - - // LED Display Settings - uint8_t LedPin0; // GPIO number for LedPin[0] - uint8_t LedPin1; // GPIO number for LedPin[1] - uint8_t LedPin2; // GPIO number for LedPin[2] - uint8_t LedEnableMask; - - uint8_t LedPcie; // GPIO number for PCIE results - uint8_t LedError; // GPIO number for Error Cases - uint8_t LedSpare1[2]; - - // SECTION: Clock Spread Spectrum - - // GFXCLK PLL Spread Spectrum - uint8_t PllGfxclkSpreadEnabled; // on or off - uint8_t PllGfxclkSpreadPercent; // Q4.4 - uint16_t PllGfxclkSpreadFreq; // kHz - - // GFXCLK DFLL Spread Spectrum - uint8_t DfllGfxclkSpreadEnabled; // on or off - uint8_t DfllGfxclkSpreadPercent; // Q4.4 - uint16_t DfllGfxclkSpreadFreq; // kHz - - // UCLK Spread Spectrum - uint16_t UclkSpreadPadding; - uint16_t UclkSpreadFreq; // kHz - - // FCLK Spread Spectrum - uint8_t FclkSpreadEnabled; // on or off - uint8_t FclkSpreadPercent; // Q4.4 - uint16_t FclkSpreadFreq; // kHz - - // Section: Memory Config - uint32_t MemoryChannelEnabled; // For DRAM use only, Max 32 channels enabled bit mask. - - uint8_t DramBitWidth; // For DRAM use only. See Dram Bit width type defines - uint8_t PaddingMem1[3]; - - // Section: Total Board Power - uint16_t TotalBoardPower; //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power - uint16_t BoardPowerPadding; - - // SECTION: XGMI Training - uint8_t XgmiLinkSpeed [NUM_XGMI_PSTATE_LEVELS]; - uint8_t XgmiLinkWidth [NUM_XGMI_PSTATE_LEVELS]; - - uint16_t XgmiFclkFreq [NUM_XGMI_PSTATE_LEVELS]; - uint16_t XgmiSocVoltage [NUM_XGMI_PSTATE_LEVELS]; - - // SECTION: UMC feature flags - uint8_t HsrEnabled; - uint8_t VddqOffEnabled; - uint8_t PaddingUmcFlags[2]; - - // UCLK Spread Spectrum - uint8_t UclkSpreadPercent[16]; - - // SECTION: Board Reserved - uint32_t BoardReserved[11]; - - // SECTION: Structure Padding - - // Padding for MMHUB - do not modify this - uint32_t MmHubPadding[8]; // SMU internal use - -} PPTable_t; - -typedef struct { - // Time constant parameters for clock averages in ms - uint16_t GfxclkAverageLpfTau; - uint16_t FclkAverageLpfTau; - uint16_t UclkAverageLpfTau; - uint16_t GfxActivityLpfTau; - uint16_t UclkActivityLpfTau; - uint16_t SocketPowerLpfTau; - uint16_t VcnClkAverageLpfTau; - uint16_t padding16; -} DriverSmuConfig_t; - -typedef struct { - DriverSmuConfig_t DriverSmuConfig; - - uint32_t Spare[7]; - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} DriverSmuConfigExternal_t; - -typedef struct { - uint16_t GfxclkFmin; // MHz - uint16_t GfxclkFmax; // MHz - QuadraticInt_t CustomGfxVfCurve; // a: mV/MHz^2, b: mv/MHz, c: mV - uint16_t CustomCurveFmin; // MHz - uint16_t UclkFmin; // MHz - uint16_t UclkFmax; // MHz - int16_t OverDrivePct; // % - uint16_t FanMaximumRpm; - uint16_t FanMinimumPwm; - uint16_t FanAcousticLimitRpm; - uint16_t FanTargetTemperature; // Degree Celcius - uint8_t FanLinearPwmPoints[NUM_OD_FAN_MAX_POINTS]; - uint8_t FanLinearTempPoints[NUM_OD_FAN_MAX_POINTS]; - uint16_t MaxOpTemp; // Degree Celcius - uint16_t Padding_16[1]; - uint8_t FanZeroRpmEnable; - uint8_t FanZeroRpmStopTemp; - uint8_t FanMode; - uint8_t Padding[1]; -} OverDriveTable_t; - -typedef struct { - OverDriveTable_t OverDriveTable; - uint32_t Spare[8]; - - uint32_t MmHubPadding[8]; // SMU internal use -} OverDriveTableExternal_t; - -typedef struct { - uint32_t CurrClock[PPCLK_COUNT]; - - 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 ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t AverageSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureMem ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrMem0 ; - uint16_t TemperatureVrMem1 ; - uint16_t TemperatureVrSoc ; - uint16_t TemperatureLiquid0 ; - uint16_t TemperatureLiquid1 ; - uint16_t TemperaturePlx ; - uint16_t Padding16 ; - uint32_t ThrottlerStatus ; - - uint8_t LinkDpmLevel; - uint8_t CurrFanPwm; - uint16_t CurrFanSpeed; - - //BACO metrics, PMFW-1721 - //metrics for D3hot entry/exit and driver ARM msgs - uint8_t D3HotEntryCountPerMode[D3HOT_SEQUENCE_COUNT]; - uint8_t D3HotExitCountPerMode[D3HOT_SEQUENCE_COUNT]; - uint8_t ArmMsgReceivedCountPerMode[D3HOT_SEQUENCE_COUNT]; - - //PMFW-4362 - uint32_t EnergyAccumulator; - uint16_t AverageVclk0Frequency ; - uint16_t AverageDclk0Frequency ; - uint16_t AverageVclk1Frequency ; - uint16_t AverageDclk1Frequency ; - uint16_t VcnActivityPercentage ; //place holder, David N. to provide full sequence - uint8_t PcieRate ; - uint8_t PcieWidth ; - -} SmuMetrics_t; - -typedef struct { - SmuMetrics_t SmuMetrics; - uint32_t Spare[1]; - - // Padding - ignore - uint32_t MmHubPadding[8]; // SMU internal use -} SmuMetricsExternal_t; - -typedef struct { - uint16_t MinClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MaxClock; // This is either DCEFCLK or SOCCLK (in MHz) - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Flags; - uint8_t Padding[2]; - -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCEFCLK, - WM_COUNT, -} WM_CLOCK_e; - -typedef enum { - WATERMARKS_CLOCK_RANGE = 0, - WATERMARKS_DUMMY_PSTATE, - WATERMARKS_MALL, - WATERMARKS_COUNT, -} WATERMARKS_FLAGS_e; - -typedef struct { - // Watermarks - WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; -} Watermarks_t; - -typedef struct { - Watermarks_t Watermarks; - - uint32_t MmHubPadding[8]; // SMU internal use -} WatermarksExternal_t; - -typedef struct { - uint16_t avgPsmCount[67]; - uint16_t minPsmCount[67]; - float avgPsmVoltage[67]; - float minPsmVoltage[67]; -} AvfsDebugTable_t; - -typedef struct { - AvfsDebugTable_t AvfsDebugTable; - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsDebugTableExternal_t; - -typedef struct { - uint8_t AvfsVersion; - uint8_t Padding; - - uint8_t AvfsEn[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideVFT[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideAvfsGb[AVFS_VOLTAGE_COUNT]; - - uint8_t OverrideTemperatures[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideVInversion[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2V[AVFS_VOLTAGE_COUNT]; - uint8_t OverrideP2VCharzFreq[AVFS_VOLTAGE_COUNT]; - - int32_t VFT0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t VFT0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT1_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT1_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT1_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t VFT2_m1[AVFS_VOLTAGE_COUNT]; // Q8.16 - int32_t VFT2_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t VFT2_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AvfsGb0_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AvfsGb0_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AvfsGb0_b[AVFS_VOLTAGE_COUNT]; // Q32 - - int32_t AcBtcGb_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t AcBtcGb_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t AcBtcGb_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t AvfsTempCold[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempMid[AVFS_VOLTAGE_COUNT]; - uint32_t AvfsTempHot[AVFS_VOLTAGE_COUNT]; - - uint32_t VInversion[AVFS_VOLTAGE_COUNT]; // in mV with 2 fractional bits - - - int32_t P2V_m1[AVFS_VOLTAGE_COUNT]; // Q8.24 - int32_t P2V_m2[AVFS_VOLTAGE_COUNT]; // Q12.12 - int32_t P2V_b[AVFS_VOLTAGE_COUNT]; // Q32 - - uint32_t P2VCharzFreq[AVFS_VOLTAGE_COUNT]; // in 10KHz units - - uint32_t EnabledAvfsModules[3]; //Sienna_Cichlid - 67 AVFS modules -} AvfsFuseOverride_t; - -typedef struct { - AvfsFuseOverride_t AvfsFuseOverride; - - uint32_t MmHubPadding[8]; // SMU internal use -} AvfsFuseOverrideExternal_t; - -typedef struct { - uint8_t Gfx_ActiveHystLimit; - uint8_t Gfx_IdleHystLimit; - uint8_t Gfx_FPS; - uint8_t Gfx_MinActiveFreqType; - uint8_t Gfx_BoosterFreqType; - uint8_t Gfx_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Gfx_MinActiveFreq; // MHz - uint16_t Gfx_BoosterFreq; // MHz - uint16_t Gfx_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Gfx_PD_Data_limit_a; // Q16 - uint32_t Gfx_PD_Data_limit_b; // Q16 - uint32_t Gfx_PD_Data_limit_c; // Q16 - uint32_t Gfx_PD_Data_error_coeff; // Q16 - uint32_t Gfx_PD_Data_error_rate_coeff; // Q16 - - uint8_t Fclk_ActiveHystLimit; - uint8_t Fclk_IdleHystLimit; - uint8_t Fclk_FPS; - uint8_t Fclk_MinActiveFreqType; - uint8_t Fclk_BoosterFreqType; - uint8_t Fclk_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Fclk_MinActiveFreq; // MHz - uint16_t Fclk_BoosterFreq; // MHz - uint16_t Fclk_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Fclk_PD_Data_limit_a; // Q16 - uint32_t Fclk_PD_Data_limit_b; // Q16 - uint32_t Fclk_PD_Data_limit_c; // Q16 - uint32_t Fclk_PD_Data_error_coeff; // Q16 - uint32_t Fclk_PD_Data_error_rate_coeff; // Q16 - - uint8_t Mem_ActiveHystLimit; - uint8_t Mem_IdleHystLimit; - uint8_t Mem_FPS; - uint8_t Mem_MinActiveFreqType; - uint8_t Mem_BoosterFreqType; - uint8_t Mem_MinFreqStep; // Minimum delta between current and target frequeny in order for FW to change clock. - uint16_t Mem_MinActiveFreq; // MHz - uint16_t Mem_BoosterFreq; // MHz - uint16_t Mem_PD_Data_time_constant; // Time constant of PD controller in ms - uint32_t Mem_PD_Data_limit_a; // Q16 - uint32_t Mem_PD_Data_limit_b; // Q16 - uint32_t Mem_PD_Data_limit_c; // Q16 - uint32_t Mem_PD_Data_error_coeff; // Q16 - uint32_t Mem_PD_Data_error_rate_coeff; // Q16 - - uint32_t Mem_UpThreshold_Limit; // Q16 - uint8_t Mem_UpHystLimit; - uint8_t Mem_DownHystLimit; - uint16_t Mem_Fps; - -} DpmActivityMonitorCoeffInt_t; - - -typedef struct { - DpmActivityMonitorCoeffInt_t DpmActivityMonitorCoeffInt; - uint32_t MmHubPadding[8]; // SMU internal use -} DpmActivityMonitorCoeffIntExternal_t; - -// Workload bits -#define WORKLOAD_PPLIB_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 -#define WORKLOAD_PPLIB_VIDEO_BIT 3 -#define WORKLOAD_PPLIB_VR_BIT 4 -#define WORKLOAD_PPLIB_COMPUTE_BIT 5 -#define WORKLOAD_PPLIB_CUSTOM_BIT 6 -#define WORKLOAD_PPLIB_COUNT 7 - - -// These defines are used with the following messages: -// SMC_MSG_TransferTableDram2Smu -// SMC_MSG_TransferTableSmu2Dram - -// Table transfer status -#define TABLE_TRANSFER_OK 0x0 -#define TABLE_TRANSFER_FAILED 0xFF - -// Table types -#define TABLE_PPTABLE 0 -#define TABLE_WATERMARKS 1 -#define TABLE_AVFS_PSM_DEBUG 2 -#define TABLE_AVFS_FUSE_OVERRIDE 3 -#define TABLE_PMSTATUSLOG 4 -#define TABLE_SMU_METRICS 5 -#define TABLE_DRIVER_SMU_CONFIG 6 -#define TABLE_ACTIVITY_MONITOR_COEFF 7 -#define TABLE_OVERDRIVE 8 -#define TABLE_I2C_COMMANDS 9 -#define TABLE_PACE 10 -#define TABLE_COUNT 11 - -typedef struct { - float FlopsPerByteTable[RLC_PACE_TABLE_NUM_LEVELS]; -} RlcPaceFlopsPerByteOverride_t; - -typedef struct { - RlcPaceFlopsPerByteOverride_t RlcPaceFlopsPerByteOverride; - - uint32_t MmHubPadding[8]; // SMU internal use -} RlcPaceFlopsPerByteOverrideExternal_t; - -// These defines are used with the SMC_MSG_SetUclkFastSwitch message. -#define UCLK_SWITCH_SLOW 0 -#define UCLK_SWITCH_FAST 1 -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h deleted file mode 100644 index e9315eb5b48e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu12_driver_if.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef SMU12_DRIVER_IF_H -#define SMU12_DRIVER_IF_H - -// *** IMPORTANT *** -// SMU TEAM: Always increment the interface version if -// any structure is changed in this file -#define SMU12_DRIVER_IF_VERSION 14 - -typedef struct { - int32_t value; - uint32_t numFractionalBits; -} FloatInIntFormat_t; - -typedef enum { - DSPCLK_DCFCLK = 0, - DSPCLK_DISPCLK, - DSPCLK_PIXCLK, - DSPCLK_PHYCLK, - DSPCLK_COUNT, -} DSPCLK_e; - -typedef struct { - uint16_t Freq; // in MHz - uint16_t Vid; // min voltage in SVI2 VID -} DisplayClockTable_t; - -typedef struct { - uint16_t MinClock; // This is either DCFCLK or SOCCLK (in MHz) - uint16_t MaxClock; // This is either DCFCLK or SOCCLK (in MHz) - uint16_t MinMclk; - uint16_t MaxMclk; - - uint8_t WmSetting; - uint8_t WmType; // Used for normal pstate change or memory retraining - uint8_t Padding[2]; -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 -#define WM_PSTATE_CHG 0 -#define WM_RETRAINING 1 - -typedef enum { - WM_SOCCLK = 0, - WM_DCFCLK, - WM_COUNT, -} WM_CLOCK_e; - -typedef struct { - // Watermarks - WatermarkRowGeneric_t WatermarkRow[WM_COUNT][NUM_WM_RANGES]; - - uint32_t MmHubPadding[7]; // SMU internal use -} Watermarks_t; - -typedef enum { - CUSTOM_DPM_SETTING_GFXCLK, - CUSTOM_DPM_SETTING_CCLK, - CUSTOM_DPM_SETTING_FCLK_CCX, - CUSTOM_DPM_SETTING_FCLK_GFX, - CUSTOM_DPM_SETTING_FCLK_STALLS, - CUSTOM_DPM_SETTING_LCLK, - CUSTOM_DPM_SETTING_COUNT, -} CUSTOM_DPM_SETTING_e; - -typedef struct { - uint8_t ActiveHystLimit; - uint8_t IdleHystLimit; - uint8_t FPS; - uint8_t MinActiveFreqType; - FloatInIntFormat_t MinActiveFreq; - FloatInIntFormat_t PD_Data_limit; - FloatInIntFormat_t PD_Data_time_constant; - FloatInIntFormat_t PD_Data_error_coeff; - FloatInIntFormat_t PD_Data_error_rate_coeff; -} DpmActivityMonitorCoeffExt_t; - -typedef struct { - DpmActivityMonitorCoeffExt_t DpmActivityMonitorCoeff[CUSTOM_DPM_SETTING_COUNT]; -} CustomDpmSettings_t; - - -#define NUM_DCFCLK_DPM_LEVELS 8 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_FCLK_DPM_LEVELS 4 -#define NUM_MEMCLK_DPM_LEVELS 4 -#define NUM_VCN_DPM_LEVELS 8 - -typedef struct { - uint32_t Freq; // In MHz - uint32_t Vol; // Millivolts with 2 fractional bits -} DpmClock_t; - -typedef struct { - DpmClock_t DcfClocks[NUM_DCFCLK_DPM_LEVELS]; - DpmClock_t SocClocks[NUM_SOCCLK_DPM_LEVELS]; - DpmClock_t FClocks[NUM_FCLK_DPM_LEVELS]; - DpmClock_t MemClocks[NUM_MEMCLK_DPM_LEVELS]; - DpmClock_t VClocks[NUM_VCN_DPM_LEVELS]; - DpmClock_t DClocks[NUM_VCN_DPM_LEVELS]; - - uint8_t NumDcfClkDpmEnabled; - uint8_t NumSocClkDpmEnabled; - uint8_t NumFClkDpmEnabled; - uint8_t NumMemClkDpmEnabled; - uint8_t NumVClkDpmEnabled; - uint8_t NumDClkDpmEnabled; - uint8_t spare[2]; -} DpmClocks_t; - - -typedef enum { - CLOCK_SMNCLK = 0, - CLOCK_SOCCLK, - CLOCK_MP0CLK, - CLOCK_MP1CLK, - CLOCK_MP2CLK, - CLOCK_VCLK, - CLOCK_LCLK, - CLOCK_DCLK, - CLOCK_ACLK, - CLOCK_ISPCLK, - CLOCK_SHUBCLK, - CLOCK_DISPCLK, - CLOCK_DPPCLK, - CLOCK_DPREFCLK, - CLOCK_DCFCLK, - CLOCK_FCLK, - CLOCK_UMCCLK, - CLOCK_GFXCLK, - CLOCK_COUNT, -} CLOCK_IDs_e; - -// Throttler Status Bitmask -#define THROTTLER_STATUS_BIT_SPL 0 -#define THROTTLER_STATUS_BIT_FPPT 1 -#define THROTTLER_STATUS_BIT_SPPT 2 -#define THROTTLER_STATUS_BIT_SPPT_APU 3 -#define THROTTLER_STATUS_BIT_THM_CORE 4 -#define THROTTLER_STATUS_BIT_THM_GFX 5 -#define THROTTLER_STATUS_BIT_THM_SOC 6 -#define THROTTLER_STATUS_BIT_TDC_VDD 7 -#define THROTTLER_STATUS_BIT_TDC_SOC 8 -#define THROTTLER_STATUS_BIT_PROCHOT_CPU 9 -#define THROTTLER_STATUS_BIT_PROCHOT_GFX 10 -#define THROTTLER_STATUS_BIT_EDC_CPU 11 -#define THROTTLER_STATUS_BIT_EDC_GFX 12 - -typedef struct { - uint16_t ClockFrequency[CLOCK_COUNT]; //[MHz] - - uint16_t AverageGfxclkFrequency; //[MHz] - uint16_t AverageSocclkFrequency; //[MHz] - uint16_t AverageVclkFrequency; //[MHz] - uint16_t AverageFclkFrequency; //[MHz] - - uint16_t AverageGfxActivity; //[centi] - uint16_t AverageUvdActivity; //[centi] - - uint16_t Voltage[2]; //[mV] indices: VDDCR_VDD, VDDCR_SOC - uint16_t Current[2]; //[mA] indices: VDDCR_VDD, VDDCR_SOC - uint16_t Power[2]; //[mW] indices: VDDCR_VDD, VDDCR_SOC - - uint16_t FanPwm; //[milli] - uint16_t CurrentSocketPower; //[W] - - uint16_t CoreFrequency[8]; //[MHz] - uint16_t CorePower[8]; //[mW] - uint16_t CoreTemperature[8]; //[centi-Celsius] - uint16_t L3Frequency[2]; //[MHz] - uint16_t L3Temperature[2]; //[centi-Celsius] - - uint16_t GfxTemperature; //[centi-Celsius] - uint16_t SocTemperature; //[centi-Celsius] - uint16_t ThrottlerStatus; - uint16_t spare; - - uint16_t StapmOriginalLimit; //[W] - uint16_t StapmCurrentLimit; //[W] - uint16_t ApuPower; //[W] - uint16_t dGpuPower; //[W] - - uint16_t VddTdcValue; //[mA] - uint16_t SocTdcValue; //[mA] - uint16_t VddEdcValue; //[mA] - uint16_t SocEdcValue; //[mA] - uint16_t reserve[2]; -} SmuMetrics_t; - - -// Workload bits -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 0 -#define WORKLOAD_PPLIB_VIDEO_BIT 2 -#define WORKLOAD_PPLIB_VR_BIT 3 -#define WORKLOAD_PPLIB_COMPUTE_BIT 4 -#define WORKLOAD_PPLIB_CUSTOM_BIT 5 -#define WORKLOAD_PPLIB_COUNT 6 - -#define TABLE_BIOS_IF 0 // Called by BIOS -#define TABLE_WATERMARKS 1 // Called by Driver -#define TABLE_CUSTOM_DPM 2 // Called by Driver -#define TABLE_SPARE1 3 -#define TABLE_DPMCLOCKS 4 // Called by Driver -#define TABLE_MOMENTARY_PM 5 // Called by Tools -#define TABLE_MODERN_STDBY 6 // Called by Tools for Modern Standby Log -#define TABLE_SMU_METRICS 7 // Called by Driver -#define TABLE_COUNT 8 - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu7.h b/drivers/gpu/drm/amd/powerplay/inc/smu7.h deleted file mode 100644 index e14072d45918..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/smu7.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2013 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 SMU7_H -#define SMU7_H - -#pragma pack(push, 1) - -#define SMU7_CONTEXT_ID_SMC 1 -#define SMU7_CONTEXT_ID_VBIOS 2 - - -#define SMU7_CONTEXT_ID_SMC 1 -#define SMU7_CONTEXT_ID_VBIOS 2 - -#define SMU7_MAX_LEVELS_VDDC 8 -#define SMU7_MAX_LEVELS_VDDCI 4 -#define SMU7_MAX_LEVELS_MVDD 4 -#define SMU7_MAX_LEVELS_VDDNB 8 - -#define SMU7_MAX_LEVELS_GRAPHICS SMU__NUM_SCLK_DPM_STATE // SCLK + SQ DPM + ULV -#define SMU7_MAX_LEVELS_MEMORY SMU__NUM_MCLK_DPM_LEVELS // MCLK Levels DPM -#define SMU7_MAX_LEVELS_GIO SMU__NUM_LCLK_DPM_LEVELS // LCLK Levels -#define SMU7_MAX_LEVELS_LINK SMU__NUM_PCIE_DPM_LEVELS // PCIe speed and number of lanes. -#define SMU7_MAX_LEVELS_UVD 8 // VCLK/DCLK levels for UVD. -#define SMU7_MAX_LEVELS_VCE 8 // ECLK levels for VCE. -#define SMU7_MAX_LEVELS_ACP 8 // ACLK levels for ACP. -#define SMU7_MAX_LEVELS_SAMU 8 // SAMCLK levels for SAMU. -#define SMU7_MAX_ENTRIES_SMIO 32 // Number of entries in SMIO table. - -#define DPM_NO_LIMIT 0 -#define DPM_NO_UP 1 -#define DPM_GO_DOWN 2 -#define DPM_GO_UP 3 - -#define SMU7_FIRST_DPM_GRAPHICS_LEVEL 0 -#define SMU7_FIRST_DPM_MEMORY_LEVEL 0 - -#define GPIO_CLAMP_MODE_VRHOT 1 -#define GPIO_CLAMP_MODE_THERM 2 -#define GPIO_CLAMP_MODE_DC 4 - -#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0 -#define SCRATCH_B_TARG_PCIE_INDEX_MASK (0x7< -#include "amd_powerplay.h" -#include "hwmgr.h" - -enum SMU_TABLE { - SMU_UVD_TABLE = 0, - SMU_VCE_TABLE, - SMU_BIF_TABLE, -}; - -enum SMU_TYPE { - SMU_SoftRegisters = 0, - SMU_Discrete_DpmTable, -}; - -enum SMU_MEMBER { - HandshakeDisables = 0, - VoltageChangeTimeout, - AverageGraphicsActivity, - AverageMemoryActivity, - PreVBlankGap, - VBlankTimeout, - UcodeLoadStatus, - UvdBootLevel, - VceBootLevel, - LowSclkInterruptThreshold, - DRAM_LOG_ADDR_H, - DRAM_LOG_ADDR_L, - DRAM_LOG_PHY_ADDR_H, - DRAM_LOG_PHY_ADDR_L, - DRAM_LOG_BUFF_SIZE, -}; - - -enum SMU_MAC_DEFINITION { - SMU_MAX_LEVELS_GRAPHICS = 0, - SMU_MAX_LEVELS_MEMORY, - SMU_MAX_LEVELS_LINK, - SMU_MAX_ENTRIES_SMIO, - SMU_MAX_LEVELS_VDDC, - SMU_MAX_LEVELS_VDDGFX, - SMU_MAX_LEVELS_VDDCI, - SMU_MAX_LEVELS_MVDD, - SMU_UVD_MCLK_HANDSHAKE_DISABLE, -}; - -enum SMU9_TABLE_ID { - PPTABLE = 0, - WMTABLE, - AVFSTABLE, - TOOLSTABLE, - AVFSFUSETABLE -}; - -enum SMU10_TABLE_ID { - SMU10_WMTABLE = 0, - SMU10_CLOCKTABLE, -}; - -extern int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table); - -extern int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr); - -extern int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t *resp); - -extern int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter, - uint32_t *resp); - -extern int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr); - -extern int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); -extern int smum_process_firmware_header(struct pp_hwmgr *hwmgr); -extern int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr); -extern int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -extern int smum_init_smc_table(struct pp_hwmgr *hwmgr); -extern int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -extern int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -extern int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -extern uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, - uint32_t type, uint32_t member); -extern uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value); - -extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); - -extern bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr); - -extern int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting); - -extern int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h deleted file mode 100644 index 63631296d751..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h +++ /dev/null @@ -1,420 +0,0 @@ -/* - * Copyright 2015 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 TONGA_PP_SMC_H -#define TONGA_PP_SMC_H - -#pragma pack(push, 1) - -#define PPSMC_SWSTATE_FLAG_DC 0x01 -#define PPSMC_SWSTATE_FLAG_UVD 0x02 -#define PPSMC_SWSTATE_FLAG_VCE 0x04 -#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 - -#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff - -#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -#define PPSMC_SYSTEMFLAG_GDDR5 0x04 - -#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 - -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 -#define PPSMC_SYSTEMFLAG_12CHANNEL 0x40 - - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 - -#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x10 -#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17 0x20 -#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17 0x40 - -/* Defines for DPM 2.0 */ -#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 -#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 -#define PPSMC_DPM2FLAGS_OCP 0x04 - -/* Defines for display watermark level */ - -#define PPSMC_DISPLAY_WATERMARK_LOW 0 -#define PPSMC_DISPLAY_WATERMARK_HIGH 1 - -/* In the HW performance level's state flags:*/ -#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -#define PPSMC_STATEFLAG_POWERBOOST 0x02 -#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 -#define PPSMC_STATEFLAG_POWERSHIFT 0x08 -#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 -#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 - -/* Fan control algorithm:*/ -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -/* Return codes for driver to SMC communication.*/ - -#define PPSMC_Result_OK ((uint16_t)0x01) -#define PPSMC_Result_NoMore ((uint16_t)0x02) -#define PPSMC_Result_NotNow ((uint16_t)0x03) - -#define PPSMC_Result_Failed ((uint16_t)0xFF) -#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) -#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) - -typedef uint16_t PPSMC_Result; - -#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) - - -#define PPSMC_MSG_Halt ((uint16_t)0x10) -#define PPSMC_MSG_Resume ((uint16_t)0x11) -#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) -#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) -#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) -#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) -#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) -#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) -#define PPSMC_MSG_LevelUp ((uint16_t)0x18) -#define PPSMC_MSG_LevelDown ((uint16_t)0x19) -#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) -#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) - -#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) -#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) -#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) -#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) -#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) - -#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) -#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) -#define PPSMC_MSG_EnableCac ((uint16_t)0x53) -#define PPSMC_MSG_DisableCac ((uint16_t)0x54) -#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) -#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) -#define PPSMC_CACHistoryStart ((uint16_t)0x57) -#define PPSMC_CACHistoryStop ((uint16_t)0x58) -#define PPSMC_TDPClampingActive ((uint16_t)0x59) -#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) -#define PPSMC_StartFanControl ((uint16_t)0x5B) -#define PPSMC_StopFanControl ((uint16_t)0x5C) -#define PPSMC_NoDisplay ((uint16_t)0x5D) -#define PPSMC_HasDisplay ((uint16_t)0x5E) -#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) -#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) -#define PPSMC_MSG_EnableULV ((uint16_t)0x62) -#define PPSMC_MSG_DisableULV ((uint16_t)0x63) -#define PPSMC_MSG_EnterULV ((uint16_t)0x64) -#define PPSMC_MSG_ExitULV ((uint16_t)0x65) -#define PPSMC_PowerShiftActive ((uint16_t)0x6A) -#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) -#define PPSMC_OCPActive ((uint16_t)0x6C) -#define PPSMC_OCPInactive ((uint16_t)0x6D) -#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) -#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) -#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) -#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) -#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) -#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) -#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) -#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) -#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) -#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) -#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) -#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) -#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) -#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) -#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) -#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) - -#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) -#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) -#define PPSMC_FlushDataCache ((uint16_t)0x80) -#define PPSMC_FlushInstrCache ((uint16_t)0x81) - -#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) -#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) - -#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) - -#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) -#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) -#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) -#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) - -#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) -#define PPSMC_MSG_ChangeNearTDPLimit ((uint16_t)0x90) -#define PPSMC_MSG_ChangeSafePowerLimit ((uint16_t)0x91) - -#define PPSMC_MSG_DPMStateSweepStart ((uint16_t)0x92) -#define PPSMC_MSG_DPMStateSweepStop ((uint16_t)0x93) - -#define PPSMC_MSG_OVRDDisableSCLKDS ((uint16_t)0x94) -#define PPSMC_MSG_CancelDisableOVRDSCLKDS ((uint16_t)0x95) -#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint16_t)0x96) -#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint16_t)0x97) -#define PPSMC_MSG_GPIO17 ((uint16_t)0x98) - -#define PPSMC_MSG_API_SetSvi2Volt_Vddc ((uint16_t)0x99) -#define PPSMC_MSG_API_SetSvi2Volt_Vddci ((uint16_t)0x9A) -#define PPSMC_MSG_API_SetSvi2Volt_Mvdd ((uint16_t)0x9B) -#define PPSMC_MSG_API_GetSvi2Volt_Vddc ((uint16_t)0x9C) -#define PPSMC_MSG_API_GetSvi2Volt_Vddci ((uint16_t)0x9D) -#define PPSMC_MSG_API_GetSvi2Volt_Mvdd ((uint16_t)0x9E) - -#define PPSMC_MSG_BREAK ((uint16_t)0xF8) - -/* Trinity Specific Messages*/ -#define PPSMC_MSG_Test ((uint16_t) 0x100) -#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) -#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) -#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) -#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) -#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) -#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) -#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) -#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) -#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) -#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) -#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) -#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) -#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) -#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) -#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) -#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) -#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) -#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) -#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) -#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) -#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) -#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) -#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) -#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) -#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) -#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) -#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) -#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) -#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) -#define PPSMC_MSG_PCIE_PHYPowerDown ((uint16_t) 0x122) -#define PPSMC_MSG_PCIE_PHYPowerUp ((uint16_t) 0x123) -#define PPSMC_MSG_UVD_DPM_Config ((uint16_t) 0x124) -#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) -#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) -#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) -#define PPSMC_MSG_NBDPM_Config ((uint16_t) 0x125) -#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint16_t) 0x126) -#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint16_t) 0x127) -#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) - -#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) -#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) -#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) -#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) -#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) -#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) -#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) -#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) -#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) -#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) -#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) -#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) -#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) -#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) -#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) -#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) -#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) -#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) -#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) -#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) -#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) -#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) -#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) -#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) -#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) -#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) -#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) -#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) -#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) -#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) -#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) -#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) -#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) -#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) -#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) - -#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) -#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) - -#define PPSMC_MSG_DPM_Enable ((uint16_t)0x14e) -#define PPSMC_MSG_DPM_Disable ((uint16_t)0x14f) -#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t)0x150) -#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t)0x151) -#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t)0x152) -#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t)0x153) -#define PPSMC_MSG_UVDDPM_Enable ((uint16_t)0x154) -#define PPSMC_MSG_UVDDPM_Disable ((uint16_t)0x155) -#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t)0x156) -#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t)0x157) -#define PPSMC_MSG_ACPDPM_Enable ((uint16_t)0x158) -#define PPSMC_MSG_ACPDPM_Disable ((uint16_t)0x159) -#define PPSMC_MSG_VCEDPM_Enable ((uint16_t)0x15a) -#define PPSMC_MSG_VCEDPM_Disable ((uint16_t)0x15b) -#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t)0x15c) - -#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) -#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) -#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) -#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) -#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) -#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) -#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) -#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) -#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) -#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) -#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) -#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) -#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) -#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) -#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) -#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t)0x16c) -#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t)0x16d) -#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t)0x16e) -#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t)0x16f) -#define PPSMC_MSG_PmStatusLogStart ((uint16_t)0x170) -#define PPSMC_MSG_PmStatusLogSample ((uint16_t)0x171) -#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) -#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) -#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) -#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) -#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) -#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) -#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) -#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) -#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) -#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) -#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) -#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) -#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) -#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) -#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) -#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) -#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) -#define PPSMC_MSG_UVD_HANDSHAKE_OFF ((uint16_t) 0x183) -#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) -#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) -#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) -#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) -#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) -#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) -#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) -#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) -#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) -#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) -#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) -#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) -#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) -#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) -#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) -#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) -#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) -#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) -#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) -#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) -#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) -#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) -#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) -#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) -#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) - -#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) -#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) -#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) -#define PPSMC_MSG_Enable_PCC ((uint16_t) 0x19E) -#define PPSMC_MSG_Disable_PCC ((uint16_t) 0x19F) - -#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) -#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) -#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) -#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) -#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) -#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) -#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) -#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) -#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) - -#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) -#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) -#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) -#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) -#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) -#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) -#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) - -#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) -#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) -#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) -#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) -#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) -#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) -#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) -#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) -#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) -#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) -#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) -#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) -#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) -#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) -#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) -#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) -#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) -#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) -#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) -#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) -#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) -#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) -#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) -#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) - -typedef uint16_t PPSMC_Msg; - -/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ -#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 -#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 -#define PPSMC_EVENT_STATUS_DC 0x00000004 -#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 - - -#pragma pack(pop) -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h deleted file mode 100644 index 715b5a168831..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2016 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 PP_SMC_H -#define PP_SMC_H - -#pragma pack(push, 1) - -#define SMU_UCODE_VERSION 0x001c0800 - -/* SMU Response Codes: */ -#define PPSMC_Result_OK 0x1 -#define PPSMC_Result_Failed 0xFF -#define PPSMC_Result_UnknownCmd 0xFE -#define PPSMC_Result_CmdRejectedPrereq 0xFD -#define PPSMC_Result_CmdRejectedBusy 0xFC - -typedef uint16_t PPSMC_Result; - -/* Message Definitions */ -#define PPSMC_MSG_TestMessage 0x1 -#define PPSMC_MSG_GetSmuVersion 0x2 -#define PPSMC_MSG_GetDriverIfVersion 0x3 -#define PPSMC_MSG_EnableSmuFeatures 0x4 -#define PPSMC_MSG_DisableSmuFeatures 0x5 -#define PPSMC_MSG_GetEnabledSmuFeatures 0x6 -#define PPSMC_MSG_SetWorkloadMask 0x7 -#define PPSMC_MSG_SetPptLimit 0x8 -#define PPSMC_MSG_SetDriverDramAddrHigh 0x9 -#define PPSMC_MSG_SetDriverDramAddrLow 0xA -#define PPSMC_MSG_SetToolsDramAddrHigh 0xB -#define PPSMC_MSG_SetToolsDramAddrLow 0xC -#define PPSMC_MSG_TransferTableSmu2Dram 0xD -#define PPSMC_MSG_TransferTableDram2Smu 0xE -#define PPSMC_MSG_UseDefaultPPTable 0xF -#define PPSMC_MSG_UseBackupPPTable 0x10 -#define PPSMC_MSG_RunBtc 0x11 -#define PPSMC_MSG_RequestI2CBus 0x12 -#define PPSMC_MSG_ReleaseI2CBus 0x13 -#define PPSMC_MSG_ConfigureTelemetry 0x14 -#define PPSMC_MSG_SetUlvIpMask 0x15 -#define PPSMC_MSG_SetSocVidOffset 0x16 -#define PPSMC_MSG_SetMemVidOffset 0x17 -#define PPSMC_MSG_GetSocVidOffset 0x18 -#define PPSMC_MSG_GetMemVidOffset 0x19 -#define PPSMC_MSG_SetFloorSocVoltage 0x1A -#define PPSMC_MSG_SoftReset 0x1B -#define PPSMC_MSG_StartBacoMonitor 0x1C -#define PPSMC_MSG_CancelBacoMonitor 0x1D -#define PPSMC_MSG_EnterBaco 0x1E -#define PPSMC_MSG_AllowLowGfxclkInterrupt 0x1F -#define PPSMC_MSG_SetLowGfxclkInterruptThreshold 0x20 -#define PPSMC_MSG_SetSoftMinGfxclkByIndex 0x21 -#define PPSMC_MSG_SetSoftMaxGfxclkByIndex 0x22 -#define PPSMC_MSG_GetCurrentGfxclkIndex 0x23 -#define PPSMC_MSG_SetSoftMinUclkByIndex 0x24 -#define PPSMC_MSG_SetSoftMaxUclkByIndex 0x25 -#define PPSMC_MSG_GetCurrentUclkIndex 0x26 -#define PPSMC_MSG_SetSoftMinUvdByIndex 0x27 -#define PPSMC_MSG_SetSoftMaxUvdByIndex 0x28 -#define PPSMC_MSG_GetCurrentUvdIndex 0x29 -#define PPSMC_MSG_SetSoftMinVceByIndex 0x2A -#define PPSMC_MSG_SetSoftMaxVceByIndex 0x2B -#define PPSMC_MSG_SetHardMinVceByIndex 0x2C -#define PPSMC_MSG_GetCurrentVceIndex 0x2D -#define PPSMC_MSG_SetSoftMinSocclkByIndex 0x2E -#define PPSMC_MSG_SetHardMinSocclkByIndex 0x2F -#define PPSMC_MSG_SetSoftMaxSocclkByIndex 0x30 -#define PPSMC_MSG_GetCurrentSocclkIndex 0x31 -#define PPSMC_MSG_SetMinLinkDpmByIndex 0x32 -#define PPSMC_MSG_GetCurrentLinkIndex 0x33 -#define PPSMC_MSG_GetAverageGfxclkFrequency 0x34 -#define PPSMC_MSG_GetAverageSocclkFrequency 0x35 -#define PPSMC_MSG_GetAverageUclkFrequency 0x36 -#define PPSMC_MSG_GetAverageGfxActivity 0x37 -#define PPSMC_MSG_GetTemperatureEdge 0x38 -#define PPSMC_MSG_GetTemperatureHotspot 0x39 -#define PPSMC_MSG_GetTemperatureHBM 0x3A -#define PPSMC_MSG_GetTemperatureVrSoc 0x3B -#define PPSMC_MSG_GetTemperatureVrMem 0x3C -#define PPSMC_MSG_GetTemperatureLiquid 0x3D -#define PPSMC_MSG_GetTemperaturePlx 0x3E -#define PPSMC_MSG_OverDriveSetPercentage 0x3F -#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x40 -#define PPSMC_MSG_SwitchToAC 0x41 -#define PPSMC_MSG_SetUclkFastSwitch 0x42 -#define PPSMC_MSG_SetUclkDownHyst 0x43 -#define PPSMC_MSG_RemoveDCClamp 0x44 -#define PPSMC_MSG_GfxDeviceDriverReset 0x45 -#define PPSMC_MSG_GetCurrentRpm 0x46 -#define PPSMC_MSG_SetVideoFps 0x47 -#define PPSMC_MSG_SetCustomGfxDpmParameters 0x48 -#define PPSMC_MSG_SetTjMax 0x49 -#define PPSMC_MSG_SetFanTemperatureTarget 0x4A -#define PPSMC_MSG_PrepareMp1ForUnload 0x4B -#define PPSMC_MSG_RequestDisplayClockByFreq 0x4C -#define PPSMC_MSG_GetClockFreqMHz 0x4D -#define PPSMC_MSG_DramLogSetDramAddrHigh 0x4E -#define PPSMC_MSG_DramLogSetDramAddrLow 0x4F -#define PPSMC_MSG_DramLogSetDramSize 0x50 -#define PPSMC_MSG_SetFanMaxRpm 0x51 -#define PPSMC_MSG_SetFanMinPwm 0x52 -#define PPSMC_MSG_ConfigureGfxDidt 0x55 -#define PPSMC_MSG_NumOfDisplays 0x56 -#define PPSMC_MSG_ReadSerialNumTop32 0x58 -#define PPSMC_MSG_ReadSerialNumBottom32 0x59 -#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x5A -#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x5B -#define PPSMC_MSG_RunAcgBtc 0x5C -#define PPSMC_MSG_RunAcgInClosedLoop 0x5D -#define PPSMC_MSG_RunAcgInOpenLoop 0x5E -#define PPSMC_MSG_InitializeAcg 0x5F -#define PPSMC_MSG_GetCurrPkgPwr 0x61 -#define PPSMC_MSG_GetAverageGfxclkActualFrequency 0x63 -#define PPSMC_MSG_SetPccThrottleLevel 0x67 -#define PPSMC_MSG_UpdatePkgPwrPidAlpha 0x68 -#define PPSMC_Message_Count 0x69 - - -typedef int PPSMC_Msg; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h deleted file mode 100644 index b6ffd08784e7..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/vega12/smu9_driver_if.h +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef VEGA12_SMU9_DRIVER_IF_H -#define VEGA12_SMU9_DRIVER_IF_H - -/**** IMPORTANT *** - * SMU TEAM: Always increment the interface version if - * any structure is changed in this file - */ -#define SMU9_DRIVER_IF_VERSION 0x10 - -#define PPTABLE_V12_SMU_VERSION 1 - -#define NUM_GFXCLK_DPM_LEVELS 16 -#define NUM_VCLK_DPM_LEVELS 8 -#define NUM_DCLK_DPM_LEVELS 8 -#define NUM_ECLK_DPM_LEVELS 8 -#define NUM_MP0CLK_DPM_LEVELS 2 -#define NUM_UCLK_DPM_LEVELS 4 -#define NUM_SOCCLK_DPM_LEVELS 8 -#define NUM_DCEFCLK_DPM_LEVELS 8 -#define NUM_DISPCLK_DPM_LEVELS 8 -#define NUM_PIXCLK_DPM_LEVELS 8 -#define NUM_PHYCLK_DPM_LEVELS 8 -#define NUM_LINK_LEVELS 2 - -#define MAX_GFXCLK_DPM_LEVEL (NUM_GFXCLK_DPM_LEVELS - 1) -#define MAX_VCLK_DPM_LEVEL (NUM_VCLK_DPM_LEVELS - 1) -#define MAX_DCLK_DPM_LEVEL (NUM_DCLK_DPM_LEVELS - 1) -#define MAX_ECLK_DPM_LEVEL (NUM_ECLK_DPM_LEVELS - 1) -#define MAX_MP0CLK_DPM_LEVEL (NUM_MP0CLK_DPM_LEVELS - 1) -#define MAX_UCLK_DPM_LEVEL (NUM_UCLK_DPM_LEVELS - 1) -#define MAX_SOCCLK_DPM_LEVEL (NUM_SOCCLK_DPM_LEVELS - 1) -#define MAX_DCEFCLK_DPM_LEVEL (NUM_DCEFCLK_DPM_LEVELS - 1) -#define MAX_DISPCLK_DPM_LEVEL (NUM_DISPCLK_DPM_LEVELS - 1) -#define MAX_PIXCLK_DPM_LEVEL (NUM_PIXCLK_DPM_LEVELS - 1) -#define MAX_PHYCLK_DPM_LEVEL (NUM_PHYCLK_DPM_LEVELS - 1) -#define MAX_LINK_LEVEL (NUM_LINK_LEVELS - 1) - - -#define PPSMC_GeminiModeNone 0 -#define PPSMC_GeminiModeMaster 1 -#define PPSMC_GeminiModeSlave 2 - - -#define FEATURE_DPM_PREFETCHER_BIT 0 -#define FEATURE_DPM_GFXCLK_BIT 1 -#define FEATURE_DPM_UCLK_BIT 2 -#define FEATURE_DPM_SOCCLK_BIT 3 -#define FEATURE_DPM_UVD_BIT 4 -#define FEATURE_DPM_VCE_BIT 5 -#define FEATURE_ULV_BIT 6 -#define FEATURE_DPM_MP0CLK_BIT 7 -#define FEATURE_DPM_LINK_BIT 8 -#define FEATURE_DPM_DCEFCLK_BIT 9 -#define FEATURE_DS_GFXCLK_BIT 10 -#define FEATURE_DS_SOCCLK_BIT 11 -#define FEATURE_DS_LCLK_BIT 12 -#define FEATURE_PPT_BIT 13 -#define FEATURE_TDC_BIT 14 -#define FEATURE_THERMAL_BIT 15 -#define FEATURE_GFX_PER_CU_CG_BIT 16 -#define FEATURE_RM_BIT 17 -#define FEATURE_DS_DCEFCLK_BIT 18 -#define FEATURE_ACDC_BIT 19 -#define FEATURE_VR0HOT_BIT 20 -#define FEATURE_VR1HOT_BIT 21 -#define FEATURE_FW_CTF_BIT 22 -#define FEATURE_LED_DISPLAY_BIT 23 -#define FEATURE_FAN_CONTROL_BIT 24 -#define FEATURE_GFX_EDC_BIT 25 -#define FEATURE_GFXOFF_BIT 26 -#define FEATURE_CG_BIT 27 -#define FEATURE_ACG_BIT 28 -#define FEATURE_SPARE_29_BIT 29 -#define FEATURE_SPARE_30_BIT 30 -#define FEATURE_SPARE_31_BIT 31 - -#define NUM_FEATURES 32 - -#define FEATURE_DPM_PREFETCHER_MASK (1 << FEATURE_DPM_PREFETCHER_BIT ) -#define FEATURE_DPM_GFXCLK_MASK (1 << FEATURE_DPM_GFXCLK_BIT ) -#define FEATURE_DPM_UCLK_MASK (1 << FEATURE_DPM_UCLK_BIT ) -#define FEATURE_DPM_SOCCLK_MASK (1 << FEATURE_DPM_SOCCLK_BIT ) -#define FEATURE_DPM_UVD_MASK (1 << FEATURE_DPM_UVD_BIT ) -#define FEATURE_DPM_VCE_MASK (1 << FEATURE_DPM_VCE_BIT ) -#define FEATURE_ULV_MASK (1 << FEATURE_ULV_BIT ) -#define FEATURE_DPM_MP0CLK_MASK (1 << FEATURE_DPM_MP0CLK_BIT ) -#define FEATURE_DPM_LINK_MASK (1 << FEATURE_DPM_LINK_BIT ) -#define FEATURE_DPM_DCEFCLK_MASK (1 << FEATURE_DPM_DCEFCLK_BIT ) -#define FEATURE_DS_GFXCLK_MASK (1 << FEATURE_DS_GFXCLK_BIT ) -#define FEATURE_DS_SOCCLK_MASK (1 << FEATURE_DS_SOCCLK_BIT ) -#define FEATURE_DS_LCLK_MASK (1 << FEATURE_DS_LCLK_BIT ) -#define FEATURE_PPT_MASK (1 << FEATURE_PPT_BIT ) -#define FEATURE_TDC_MASK (1 << FEATURE_TDC_BIT ) -#define FEATURE_THERMAL_MASK (1 << FEATURE_THERMAL_BIT ) -#define FEATURE_GFX_PER_CU_CG_MASK (1 << FEATURE_GFX_PER_CU_CG_BIT ) -#define FEATURE_RM_MASK (1 << FEATURE_RM_BIT ) -#define FEATURE_DS_DCEFCLK_MASK (1 << FEATURE_DS_DCEFCLK_BIT ) -#define FEATURE_ACDC_MASK (1 << FEATURE_ACDC_BIT ) -#define FEATURE_VR0HOT_MASK (1 << FEATURE_VR0HOT_BIT ) -#define FEATURE_VR1HOT_MASK (1 << FEATURE_VR1HOT_BIT ) -#define FEATURE_FW_CTF_MASK (1 << FEATURE_FW_CTF_BIT ) -#define FEATURE_LED_DISPLAY_MASK (1 << FEATURE_LED_DISPLAY_BIT ) -#define FEATURE_FAN_CONTROL_MASK (1 << FEATURE_FAN_CONTROL_BIT ) -#define FEATURE_GFX_EDC_MASK (1 << FEATURE_GFX_EDC_BIT ) -#define FEATURE_GFXOFF_MASK (1 << FEATURE_GFXOFF_BIT ) -#define FEATURE_CG_MASK (1 << FEATURE_CG_BIT ) -#define FEATURE_ACG_MASK (1 << FEATURE_ACG_BIT) -#define FEATURE_SPARE_29_MASK (1 << FEATURE_SPARE_29_BIT ) -#define FEATURE_SPARE_30_MASK (1 << FEATURE_SPARE_30_BIT ) -#define FEATURE_SPARE_31_MASK (1 << FEATURE_SPARE_31_BIT ) - - -#define DPM_OVERRIDE_DISABLE_SOCCLK_PID 0x00000001 -#define DPM_OVERRIDE_DISABLE_UCLK_PID 0x00000002 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_SOCCLK 0x00000004 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_UVD_UCLK 0x00000008 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_SOCCLK 0x00000010 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_VCLK_UCLK 0x00000020 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_SOCCLK 0x00000040 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_DCLK_UCLK 0x00000080 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_SOCCLK 0x00000100 -#define DPM_OVERRIDE_ENABLE_VOLT_LINK_VCE_UCLK 0x00000200 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_SOCCLK 0x00000400 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_ECLK_UCLK 0x00000800 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_SOCCLK 0x00001000 -#define DPM_OVERRIDE_ENABLE_FREQ_LINK_GFXCLK_UCLK 0x00002000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_GFXCLK_SWITCH 0x00004000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_SOCCLK_SWITCH 0x00008000 -#define DPM_OVERRIDE_ENABLE_GFXOFF_UCLK_SWITCH 0x00010000 - - -#define VR_MAPPING_VR_SELECT_MASK 0x01 -#define VR_MAPPING_VR_SELECT_SHIFT 0x00 - -#define VR_MAPPING_PLANE_SELECT_MASK 0x02 -#define VR_MAPPING_PLANE_SELECT_SHIFT 0x01 - - -#define PSI_SEL_VR0_PLANE0_PSI0 0x01 -#define PSI_SEL_VR0_PLANE0_PSI1 0x02 -#define PSI_SEL_VR0_PLANE1_PSI0 0x04 -#define PSI_SEL_VR0_PLANE1_PSI1 0x08 -#define PSI_SEL_VR1_PLANE0_PSI0 0x10 -#define PSI_SEL_VR1_PLANE0_PSI1 0x20 -#define PSI_SEL_VR1_PLANE1_PSI0 0x40 -#define PSI_SEL_VR1_PLANE1_PSI1 0x80 - - -#define THROTTLER_STATUS_PADDING_BIT 0 -#define THROTTLER_STATUS_TEMP_EDGE_BIT 1 -#define THROTTLER_STATUS_TEMP_HOTSPOT_BIT 2 -#define THROTTLER_STATUS_TEMP_HBM_BIT 3 -#define THROTTLER_STATUS_TEMP_VR_GFX_BIT 4 -#define THROTTLER_STATUS_TEMP_VR_MEM_BIT 5 -#define THROTTLER_STATUS_TEMP_LIQUID_BIT 6 -#define THROTTLER_STATUS_TEMP_PLX_BIT 7 -#define THROTTLER_STATUS_TEMP_SKIN_BIT 8 -#define THROTTLER_STATUS_TDC_GFX_BIT 9 -#define THROTTLER_STATUS_TDC_SOC_BIT 10 -#define THROTTLER_STATUS_PPT_BIT 11 -#define THROTTLER_STATUS_FIT_BIT 12 -#define THROTTLER_STATUS_PPM_BIT 13 - - -#define TABLE_TRANSFER_OK 0x0 -#define TABLE_TRANSFER_FAILED 0xFF - - -#define WORKLOAD_DEFAULT_BIT 0 -#define WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT 1 -#define WORKLOAD_PPLIB_POWER_SAVING_BIT 2 -#define WORKLOAD_PPLIB_VIDEO_BIT 3 -#define WORKLOAD_PPLIB_VR_BIT 4 -#define WORKLOAD_PPLIB_COMPUTE_BIT 5 -#define WORKLOAD_PPLIB_CUSTOM_BIT 6 -#define WORKLOAD_PPLIB_COUNT 7 - -typedef struct { - uint32_t a; - uint32_t b; - uint32_t c; -} QuadraticInt_t; - -typedef struct { - uint32_t m; - uint32_t b; -} LinearInt_t; - -typedef struct { - uint32_t a; - uint32_t b; - uint32_t c; -} DroopInt_t; - -typedef enum { - PPCLK_GFXCLK, - PPCLK_VCLK, - PPCLK_DCLK, - PPCLK_ECLK, - PPCLK_SOCCLK, - PPCLK_UCLK, - PPCLK_DCEFCLK, - PPCLK_DISPCLK, - PPCLK_PIXCLK, - PPCLK_PHYCLK, - PPCLK_COUNT, -} PPCLK_e; - -enum { - VOLTAGE_MODE_AVFS, - VOLTAGE_MODE_AVFS_SS, - VOLTAGE_MODE_SS, - VOLTAGE_MODE_COUNT, -}; - -typedef struct { - uint8_t VoltageMode; - uint8_t SnapToDiscrete; - uint8_t NumDiscreteLevels; - uint8_t padding; - LinearInt_t ConversionToAvfsClk; - QuadraticInt_t SsCurve; -} DpmDescriptor_t; - -typedef struct { - uint32_t Version; - - - uint32_t FeaturesToRun[2]; - - - uint16_t SocketPowerLimitAc0; - uint16_t SocketPowerLimitAc0Tau; - uint16_t SocketPowerLimitAc1; - uint16_t SocketPowerLimitAc1Tau; - uint16_t SocketPowerLimitAc2; - uint16_t SocketPowerLimitAc2Tau; - uint16_t SocketPowerLimitAc3; - uint16_t SocketPowerLimitAc3Tau; - uint16_t SocketPowerLimitDc; - uint16_t SocketPowerLimitDcTau; - uint16_t TdcLimitSoc; - uint16_t TdcLimitSocTau; - uint16_t TdcLimitGfx; - uint16_t TdcLimitGfxTau; - - uint16_t TedgeLimit; - uint16_t ThotspotLimit; - uint16_t ThbmLimit; - uint16_t Tvr_gfxLimit; - uint16_t Tvr_memLimit; - uint16_t Tliquid1Limit; - uint16_t Tliquid2Limit; - uint16_t TplxLimit; - uint32_t FitLimit; - - uint16_t PpmPowerLimit; - uint16_t PpmTemperatureThreshold; - - uint8_t MemoryOnPackage; - uint8_t padding8_limits[3]; - - - uint16_t UlvVoltageOffsetSoc; - uint16_t UlvVoltageOffsetGfx; - - uint8_t UlvSmnclkDid; - uint8_t UlvMp1clkDid; - uint8_t UlvGfxclkBypass; - uint8_t Padding234; - - - uint16_t MinVoltageGfx; - uint16_t MinVoltageSoc; - uint16_t MaxVoltageGfx; - uint16_t MaxVoltageSoc; - - uint16_t LoadLineResistance; - uint16_t LoadLine_padding; - - - DpmDescriptor_t DpmDescriptor[PPCLK_COUNT]; - - uint16_t FreqTableGfx [NUM_GFXCLK_DPM_LEVELS ]; - uint16_t FreqTableVclk [NUM_VCLK_DPM_LEVELS ]; - uint16_t FreqTableDclk [NUM_DCLK_DPM_LEVELS ]; - uint16_t FreqTableEclk [NUM_ECLK_DPM_LEVELS ]; - uint16_t FreqTableSocclk [NUM_SOCCLK_DPM_LEVELS ]; - uint16_t FreqTableUclk [NUM_UCLK_DPM_LEVELS ]; - uint16_t FreqTableDcefclk [NUM_DCEFCLK_DPM_LEVELS ]; - uint16_t FreqTableDispclk [NUM_DISPCLK_DPM_LEVELS ]; - uint16_t FreqTablePixclk [NUM_PIXCLK_DPM_LEVELS ]; - uint16_t FreqTablePhyclk [NUM_PHYCLK_DPM_LEVELS ]; - - uint16_t DcModeMaxFreq [PPCLK_COUNT ]; - - - uint16_t Mp0clkFreq [NUM_MP0CLK_DPM_LEVELS]; - uint16_t Mp0DpmVoltage [NUM_MP0CLK_DPM_LEVELS]; - - - uint16_t GfxclkFidle; - uint16_t GfxclkSlewRate; - uint16_t CksEnableFreq; - uint16_t Padding789; - QuadraticInt_t CksVoltageOffset; - uint16_t AcgThresholdFreqHigh; - uint16_t AcgThresholdFreqLow; - uint16_t GfxclkDsMaxFreq; - uint8_t Padding456[2]; - - - uint8_t LowestUclkReservedForUlv; - uint8_t Padding8_Uclk[3]; - - - uint8_t PcieGenSpeed[NUM_LINK_LEVELS]; - uint8_t PcieLaneCount[NUM_LINK_LEVELS]; - uint16_t LclkFreq[NUM_LINK_LEVELS]; - - - uint16_t EnableTdpm; - uint16_t TdpmHighHystTemperature; - uint16_t TdpmLowHystTemperature; - uint16_t GfxclkFreqHighTempLimit; - - - uint16_t FanStopTemp; - uint16_t FanStartTemp; - - uint16_t FanGainEdge; - uint16_t FanGainHotspot; - uint16_t FanGainLiquid; - uint16_t FanGainVrVddc; - uint16_t FanGainVrMvdd; - uint16_t FanGainPlx; - uint16_t FanGainHbm; - uint16_t FanPwmMin; - uint16_t FanAcousticLimitRpm; - uint16_t FanThrottlingRpm; - uint16_t FanMaximumRpm; - uint16_t FanTargetTemperature; - uint16_t FanTargetGfxclk; - uint8_t FanZeroRpmEnable; - uint8_t FanTachEdgePerRev; - - - - int16_t FuzzyFan_ErrorSetDelta; - int16_t FuzzyFan_ErrorRateSetDelta; - int16_t FuzzyFan_PwmSetDelta; - uint16_t FuzzyFan_Reserved; - - - - - uint8_t OverrideAvfsGb; - uint8_t Padding8_Avfs[3]; - - QuadraticInt_t qAvfsGb; - DroopInt_t dBtcGbGfxCksOn; - DroopInt_t dBtcGbGfxCksOff; - DroopInt_t dBtcGbGfxAcg; - DroopInt_t dBtcGbSoc; - LinearInt_t qAgingGbGfx; - LinearInt_t qAgingGbSoc; - - QuadraticInt_t qStaticVoltageOffsetGfx; - QuadraticInt_t qStaticVoltageOffsetSoc; - - uint16_t DcTolGfx; - uint16_t DcTolSoc; - - uint8_t DcBtcGfxEnabled; - uint8_t DcBtcSocEnabled; - uint8_t Padding8_GfxBtc[2]; - - uint16_t DcBtcGfxMin; - uint16_t DcBtcGfxMax; - - uint16_t DcBtcSocMin; - uint16_t DcBtcSocMax; - - - - uint32_t DebugOverrides; - QuadraticInt_t ReservedEquation0; - QuadraticInt_t ReservedEquation1; - QuadraticInt_t ReservedEquation2; - QuadraticInt_t ReservedEquation3; - - uint16_t MinVoltageUlvGfx; - uint16_t MinVoltageUlvSoc; - - uint32_t Reserved[14]; - - - - uint8_t Liquid1_I2C_address; - uint8_t Liquid2_I2C_address; - uint8_t Vr_I2C_address; - uint8_t Plx_I2C_address; - - uint8_t Liquid_I2C_LineSCL; - uint8_t Liquid_I2C_LineSDA; - uint8_t Vr_I2C_LineSCL; - uint8_t Vr_I2C_LineSDA; - - uint8_t Plx_I2C_LineSCL; - uint8_t Plx_I2C_LineSDA; - uint8_t VrSensorPresent; - uint8_t LiquidSensorPresent; - - uint16_t MaxVoltageStepGfx; - uint16_t MaxVoltageStepSoc; - - uint8_t VddGfxVrMapping; - uint8_t VddSocVrMapping; - uint8_t VddMem0VrMapping; - uint8_t VddMem1VrMapping; - - uint8_t GfxUlvPhaseSheddingMask; - uint8_t SocUlvPhaseSheddingMask; - uint8_t ExternalSensorPresent; - uint8_t Padding8_V; - - - uint16_t GfxMaxCurrent; - int8_t GfxOffset; - uint8_t Padding_TelemetryGfx; - - uint16_t SocMaxCurrent; - int8_t SocOffset; - uint8_t Padding_TelemetrySoc; - - uint16_t Mem0MaxCurrent; - int8_t Mem0Offset; - uint8_t Padding_TelemetryMem0; - - uint16_t Mem1MaxCurrent; - int8_t Mem1Offset; - uint8_t Padding_TelemetryMem1; - - - uint8_t AcDcGpio; - uint8_t AcDcPolarity; - uint8_t VR0HotGpio; - uint8_t VR0HotPolarity; - - uint8_t VR1HotGpio; - uint8_t VR1HotPolarity; - uint8_t Padding1; - uint8_t Padding2; - - - - uint8_t LedPin0; - uint8_t LedPin1; - uint8_t LedPin2; - uint8_t padding8_4; - - - uint8_t PllGfxclkSpreadEnabled; - uint8_t PllGfxclkSpreadPercent; - uint16_t PllGfxclkSpreadFreq; - - uint8_t UclkSpreadEnabled; - uint8_t UclkSpreadPercent; - uint16_t UclkSpreadFreq; - - uint8_t SocclkSpreadEnabled; - uint8_t SocclkSpreadPercent; - uint16_t SocclkSpreadFreq; - - uint8_t AcgGfxclkSpreadEnabled; - uint8_t AcgGfxclkSpreadPercent; - uint16_t AcgGfxclkSpreadFreq; - - uint8_t Vr2_I2C_address; - uint8_t padding_vr2[3]; - - uint32_t BoardReserved[9]; - - - uint32_t MmHubPadding[7]; - -} PPTable_t; - -typedef struct { - - uint16_t GfxclkAverageLpfTau; - uint16_t SocclkAverageLpfTau; - uint16_t UclkAverageLpfTau; - uint16_t GfxActivityLpfTau; - uint16_t UclkActivityLpfTau; - - - uint32_t MmHubPadding[7]; -} DriverSmuConfig_t; - -typedef struct { - - uint16_t GfxclkFmin; - uint16_t GfxclkFmax; - uint16_t GfxclkFreq1; - uint16_t GfxclkOffsetVolt1; - uint16_t GfxclkFreq2; - uint16_t GfxclkOffsetVolt2; - uint16_t GfxclkFreq3; - uint16_t GfxclkOffsetVolt3; - uint16_t UclkFmax; - int16_t OverDrivePct; - uint16_t FanMaximumRpm; - uint16_t FanMinimumPwm; - uint16_t FanTargetTemperature; - uint16_t MaxOpTemp; - -} OverDriveTable_t; - -typedef struct { - uint16_t CurrClock[PPCLK_COUNT]; - uint16_t AverageGfxclkFrequency; - uint16_t AverageSocclkFrequency; - uint16_t AverageUclkFrequency ; - uint16_t AverageGfxActivity ; - uint16_t AverageUclkActivity ; - uint8_t CurrSocVoltageOffset ; - uint8_t CurrGfxVoltageOffset ; - uint8_t CurrMemVidOffset ; - uint8_t Padding8 ; - uint16_t CurrSocketPower ; - uint16_t TemperatureEdge ; - uint16_t TemperatureHotspot ; - uint16_t TemperatureHBM ; - uint16_t TemperatureVrGfx ; - uint16_t TemperatureVrMem ; - uint16_t TemperatureLiquid ; - uint16_t TemperaturePlx ; - uint32_t ThrottlerStatus ; - - uint8_t LinkDpmLevel; - uint8_t Padding[3]; - - - uint32_t MmHubPadding[7]; -} SmuMetrics_t; - -typedef struct { - uint16_t MinClock; - uint16_t MaxClock; - uint16_t MinUclk; - uint16_t MaxUclk; - - uint8_t WmSetting; - uint8_t Padding[3]; -} WatermarkRowGeneric_t; - -#define NUM_WM_RANGES 4 - -typedef enum { - WM_SOCCLK = 0, - WM_DCEFCLK, - WM_COUNT_PP, -} WM_CLOCK_e; - -typedef struct { - - WatermarkRowGeneric_t WatermarkRow[WM_COUNT_PP][NUM_WM_RANGES]; - - uint32_t MmHubPadding[7]; -} Watermarks_t; - -typedef struct { - uint16_t avgPsmCount[30]; - uint16_t minPsmCount[30]; - float avgPsmVoltage[30]; - float minPsmVoltage[30]; - - uint32_t MmHubPadding[7]; -} AvfsDebugTable_t; - -typedef struct { - uint8_t AvfsEn; - uint8_t AvfsVersion; - uint8_t OverrideVFT; - uint8_t OverrideAvfsGb; - - uint8_t OverrideTemperatures; - uint8_t OverrideVInversion; - uint8_t OverrideP2V; - uint8_t OverrideP2VCharzFreq; - - int32_t VFT0_m1; - int32_t VFT0_m2; - int32_t VFT0_b; - - int32_t VFT1_m1; - int32_t VFT1_m2; - int32_t VFT1_b; - - int32_t VFT2_m1; - int32_t VFT2_m2; - int32_t VFT2_b; - - int32_t AvfsGb0_m1; - int32_t AvfsGb0_m2; - int32_t AvfsGb0_b; - - int32_t AcBtcGb_m1; - int32_t AcBtcGb_m2; - int32_t AcBtcGb_b; - - uint32_t AvfsTempCold; - uint32_t AvfsTempMid; - uint32_t AvfsTempHot; - - uint32_t GfxVInversion; - uint32_t SocVInversion; - - int32_t P2V_m1; - int32_t P2V_m2; - int32_t P2V_b; - - uint32_t P2VCharzFreq; - - uint32_t EnabledAvfsModules; - - uint32_t MmHubPadding[7]; -} AvfsFuseOverride_t; - -typedef struct { - - uint8_t Gfx_ActiveHystLimit; - uint8_t Gfx_IdleHystLimit; - uint8_t Gfx_FPS; - uint8_t Gfx_MinActiveFreqType; - uint8_t Gfx_BoosterFreqType; - uint8_t Gfx_UseRlcBusy; - uint16_t Gfx_MinActiveFreq; - uint16_t Gfx_BoosterFreq; - uint16_t Gfx_PD_Data_time_constant; - uint32_t Gfx_PD_Data_limit_a; - uint32_t Gfx_PD_Data_limit_b; - uint32_t Gfx_PD_Data_limit_c; - uint32_t Gfx_PD_Data_error_coeff; - uint32_t Gfx_PD_Data_error_rate_coeff; - - uint8_t Soc_ActiveHystLimit; - uint8_t Soc_IdleHystLimit; - uint8_t Soc_FPS; - uint8_t Soc_MinActiveFreqType; - uint8_t Soc_BoosterFreqType; - uint8_t Soc_UseRlcBusy; - uint16_t Soc_MinActiveFreq; - uint16_t Soc_BoosterFreq; - uint16_t Soc_PD_Data_time_constant; - uint32_t Soc_PD_Data_limit_a; - uint32_t Soc_PD_Data_limit_b; - uint32_t Soc_PD_Data_limit_c; - uint32_t Soc_PD_Data_error_coeff; - uint32_t Soc_PD_Data_error_rate_coeff; - - uint8_t Mem_ActiveHystLimit; - uint8_t Mem_IdleHystLimit; - uint8_t Mem_FPS; - uint8_t Mem_MinActiveFreqType; - uint8_t Mem_BoosterFreqType; - uint8_t Mem_UseRlcBusy; - uint16_t Mem_MinActiveFreq; - uint16_t Mem_BoosterFreq; - uint16_t Mem_PD_Data_time_constant; - uint32_t Mem_PD_Data_limit_a; - uint32_t Mem_PD_Data_limit_b; - uint32_t Mem_PD_Data_limit_c; - uint32_t Mem_PD_Data_error_coeff; - uint32_t Mem_PD_Data_error_rate_coeff; - -} DpmActivityMonitorCoeffInt_t; - - - - -#define TABLE_PPTABLE 0 -#define TABLE_WATERMARKS 1 -#define TABLE_AVFS 2 -#define TABLE_AVFS_PSM_DEBUG 3 -#define TABLE_AVFS_FUSE_OVERRIDE 4 -#define TABLE_PMSTATUSLOG 5 -#define TABLE_SMU_METRICS 6 -#define TABLE_DRIVER_SMU_CONFIG 7 -#define TABLE_ACTIVITY_MONITOR_COEFF 8 -#define TABLE_OVERDRIVE 9 -#define TABLE_COUNT 10 - - -#define UCLK_SWITCH_SLOW 0 -#define UCLK_SWITCH_FAST 1 - - -#define SQ_Enable_MASK 0x1 -#define SQ_IR_MASK 0x2 -#define SQ_PCC_MASK 0x4 -#define SQ_EDC_MASK 0x8 - -#define TCP_Enable_MASK 0x100 -#define TCP_IR_MASK 0x200 -#define TCP_PCC_MASK 0x400 -#define TCP_EDC_MASK 0x800 - -#define TD_Enable_MASK 0x10000 -#define TD_IR_MASK 0x20000 -#define TD_PCC_MASK 0x40000 -#define TD_EDC_MASK 0x80000 - -#define DB_Enable_MASK 0x1000000 -#define DB_IR_MASK 0x2000000 -#define DB_PCC_MASK 0x4000000 -#define DB_EDC_MASK 0x8000000 - -#define SQ_Enable_SHIFT 0 -#define SQ_IR_SHIFT 1 -#define SQ_PCC_SHIFT 2 -#define SQ_EDC_SHIFT 3 - -#define TCP_Enable_SHIFT 8 -#define TCP_IR_SHIFT 9 -#define TCP_PCC_SHIFT 10 -#define TCP_EDC_SHIFT 11 - -#define TD_Enable_SHIFT 16 -#define TD_IR_SHIFT 17 -#define TD_PCC_SHIFT 18 -#define TD_EDC_SHIFT 19 - -#define DB_Enable_SHIFT 24 -#define DB_IR_SHIFT 25 -#define DB_PCC_SHIFT 26 -#define DB_EDC_SHIFT 27 - -#define REMOVE_FMAX_MARGIN_BIT 0x0 -#define REMOVE_DCTOL_MARGIN_BIT 0x1 -#define REMOVE_PLATFORM_MARGIN_BIT 0x2 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h deleted file mode 100644 index f985c78d746a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/vega12_ppsmc.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef VEGA12_PP_SMC_H -#define VEGA12_PP_SMC_H - -#pragma pack(push, 1) - -#define SMU_UCODE_VERSION 0x00270a00 - -/* SMU Response Codes: */ -#define PPSMC_Result_OK 0x1 -#define PPSMC_Result_Failed 0xFF -#define PPSMC_Result_UnknownCmd 0xFE -#define PPSMC_Result_CmdRejectedPrereq 0xFD -#define PPSMC_Result_CmdRejectedBusy 0xFC - -#define PPSMC_MSG_TestMessage 0x1 -#define PPSMC_MSG_GetSmuVersion 0x2 -#define PPSMC_MSG_GetDriverIfVersion 0x3 -#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 -#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 -#define PPSMC_MSG_EnableAllSmuFeatures 0x6 -#define PPSMC_MSG_DisableAllSmuFeatures 0x7 -#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 -#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 -#define PPSMC_MSG_DisableSmuFeaturesLow 0xA -#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB -#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC -#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD -#define PPSMC_MSG_SetWorkloadMask 0xE -#define PPSMC_MSG_SetPptLimit 0xF -#define PPSMC_MSG_SetDriverDramAddrHigh 0x10 -#define PPSMC_MSG_SetDriverDramAddrLow 0x11 -#define PPSMC_MSG_SetToolsDramAddrHigh 0x12 -#define PPSMC_MSG_SetToolsDramAddrLow 0x13 -#define PPSMC_MSG_TransferTableSmu2Dram 0x14 -#define PPSMC_MSG_TransferTableDram2Smu 0x15 -#define PPSMC_MSG_UseDefaultPPTable 0x16 -#define PPSMC_MSG_UseBackupPPTable 0x17 -#define PPSMC_MSG_RunBtc 0x18 -#define PPSMC_MSG_RequestI2CBus 0x19 -#define PPSMC_MSG_ReleaseI2CBus 0x1A -#define PPSMC_MSG_SetFloorSocVoltage 0x21 -#define PPSMC_MSG_SoftReset 0x22 -#define PPSMC_MSG_StartBacoMonitor 0x23 -#define PPSMC_MSG_CancelBacoMonitor 0x24 -#define PPSMC_MSG_EnterBaco 0x25 -#define PPSMC_MSG_SetSoftMinByFreq 0x26 -#define PPSMC_MSG_SetSoftMaxByFreq 0x27 -#define PPSMC_MSG_SetHardMinByFreq 0x28 -#define PPSMC_MSG_SetHardMaxByFreq 0x29 -#define PPSMC_MSG_GetMinDpmFreq 0x2A -#define PPSMC_MSG_GetMaxDpmFreq 0x2B -#define PPSMC_MSG_GetDpmFreqByIndex 0x2C -#define PPSMC_MSG_GetDpmClockFreq 0x2D -#define PPSMC_MSG_GetSsVoltageByDpm 0x2E -#define PPSMC_MSG_SetMemoryChannelConfig 0x2F -#define PPSMC_MSG_SetGeminiMode 0x30 -#define PPSMC_MSG_SetGeminiApertureHigh 0x31 -#define PPSMC_MSG_SetGeminiApertureLow 0x32 -#define PPSMC_MSG_SetMinLinkDpmByIndex 0x33 -#define PPSMC_MSG_OverridePcieParameters 0x34 -#define PPSMC_MSG_OverDriveSetPercentage 0x35 -#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x36 -#define PPSMC_MSG_ReenableAcDcInterrupt 0x37 -#define PPSMC_MSG_NotifyPowerSource 0x38 -#define PPSMC_MSG_SetUclkFastSwitch 0x39 -#define PPSMC_MSG_SetUclkDownHyst 0x3A -#define PPSMC_MSG_GfxDeviceDriverReset 0x3B -#define PPSMC_MSG_GetCurrentRpm 0x3C -#define PPSMC_MSG_SetVideoFps 0x3D -#define PPSMC_MSG_SetTjMax 0x3E -#define PPSMC_MSG_SetFanTemperatureTarget 0x3F -#define PPSMC_MSG_PrepareMp1ForUnload 0x40 -#define PPSMC_MSG_DramLogSetDramAddrHigh 0x41 -#define PPSMC_MSG_DramLogSetDramAddrLow 0x42 -#define PPSMC_MSG_DramLogSetDramSize 0x43 -#define PPSMC_MSG_SetFanMaxRpm 0x44 -#define PPSMC_MSG_SetFanMinPwm 0x45 -#define PPSMC_MSG_ConfigureGfxDidt 0x46 -#define PPSMC_MSG_NumOfDisplays 0x47 -#define PPSMC_MSG_RemoveMargins 0x48 -#define PPSMC_MSG_ReadSerialNumTop32 0x49 -#define PPSMC_MSG_ReadSerialNumBottom32 0x4A -#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x4B -#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x4C -#define PPSMC_MSG_RunAcgBtc 0x4D -#define PPSMC_MSG_InitializeAcg 0x4E -#define PPSMC_MSG_EnableAcgBtcTestMode 0x4F -#define PPSMC_MSG_EnableAcgSpreadSpectrum 0x50 -#define PPSMC_MSG_AllowGfxOff 0x51 -#define PPSMC_MSG_DisallowGfxOff 0x52 -#define PPSMC_MSG_GetPptLimit 0x53 -#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x54 -#define PPSMC_Message_Count 0x56 - -typedef uint16_t PPSMC_Result; -typedef int PPSMC_Msg; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h deleted file mode 100644 index 0c66f0fe1aaf..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright 2018 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 VEGA20_PP_SMC_H -#define VEGA20_PP_SMC_H - -#pragma pack(push, 1) - -// SMU Response Codes: -#define PPSMC_Result_OK 0x1 -#define PPSMC_Result_Failed 0xFF -#define PPSMC_Result_UnknownCmd 0xFE -#define PPSMC_Result_CmdRejectedPrereq 0xFD -#define PPSMC_Result_CmdRejectedBusy 0xFC - -// Message Definitions: -#define PPSMC_MSG_TestMessage 0x1 -#define PPSMC_MSG_GetSmuVersion 0x2 -#define PPSMC_MSG_GetDriverIfVersion 0x3 -#define PPSMC_MSG_SetAllowedFeaturesMaskLow 0x4 -#define PPSMC_MSG_SetAllowedFeaturesMaskHigh 0x5 -#define PPSMC_MSG_EnableAllSmuFeatures 0x6 -#define PPSMC_MSG_DisableAllSmuFeatures 0x7 -#define PPSMC_MSG_EnableSmuFeaturesLow 0x8 -#define PPSMC_MSG_EnableSmuFeaturesHigh 0x9 -#define PPSMC_MSG_DisableSmuFeaturesLow 0xA -#define PPSMC_MSG_DisableSmuFeaturesHigh 0xB -#define PPSMC_MSG_GetEnabledSmuFeaturesLow 0xC -#define PPSMC_MSG_GetEnabledSmuFeaturesHigh 0xD -#define PPSMC_MSG_SetWorkloadMask 0xE -#define PPSMC_MSG_SetPptLimit 0xF -#define PPSMC_MSG_SetDriverDramAddrHigh 0x10 -#define PPSMC_MSG_SetDriverDramAddrLow 0x11 -#define PPSMC_MSG_SetToolsDramAddrHigh 0x12 -#define PPSMC_MSG_SetToolsDramAddrLow 0x13 -#define PPSMC_MSG_TransferTableSmu2Dram 0x14 -#define PPSMC_MSG_TransferTableDram2Smu 0x15 -#define PPSMC_MSG_UseDefaultPPTable 0x16 -#define PPSMC_MSG_UseBackupPPTable 0x17 -#define PPSMC_MSG_RunBtc 0x18 -#define PPSMC_MSG_RequestI2CBus 0x19 -#define PPSMC_MSG_ReleaseI2CBus 0x1A -#define PPSMC_MSG_SetFloorSocVoltage 0x21 -#define PPSMC_MSG_SoftReset 0x22 -#define PPSMC_MSG_StartBacoMonitor 0x23 -#define PPSMC_MSG_CancelBacoMonitor 0x24 -#define PPSMC_MSG_EnterBaco 0x25 -#define PPSMC_MSG_SetSoftMinByFreq 0x26 -#define PPSMC_MSG_SetSoftMaxByFreq 0x27 -#define PPSMC_MSG_SetHardMinByFreq 0x28 -#define PPSMC_MSG_SetHardMaxByFreq 0x29 -#define PPSMC_MSG_GetMinDpmFreq 0x2A -#define PPSMC_MSG_GetMaxDpmFreq 0x2B -#define PPSMC_MSG_GetDpmFreqByIndex 0x2C -#define PPSMC_MSG_GetDpmClockFreq 0x2D -#define PPSMC_MSG_GetSsVoltageByDpm 0x2E -#define PPSMC_MSG_SetMemoryChannelConfig 0x2F -#define PPSMC_MSG_SetGeminiMode 0x30 -#define PPSMC_MSG_SetGeminiApertureHigh 0x31 -#define PPSMC_MSG_SetGeminiApertureLow 0x32 -#define PPSMC_MSG_SetMinLinkDpmByIndex 0x33 -#define PPSMC_MSG_OverridePcieParameters 0x34 -#define PPSMC_MSG_OverDriveSetPercentage 0x35 -#define PPSMC_MSG_SetMinDeepSleepDcefclk 0x36 -#define PPSMC_MSG_ReenableAcDcInterrupt 0x37 -#define PPSMC_MSG_NotifyPowerSource 0x38 -#define PPSMC_MSG_SetUclkFastSwitch 0x39 -#define PPSMC_MSG_SetUclkDownHyst 0x3A -//#define PPSMC_MSG_GfxDeviceDriverReset 0x3B -#define PPSMC_MSG_GetCurrentRpm 0x3C -#define PPSMC_MSG_SetVideoFps 0x3D -#define PPSMC_MSG_SetTjMax 0x3E -#define PPSMC_MSG_SetFanTemperatureTarget 0x3F -#define PPSMC_MSG_PrepareMp1ForUnload 0x40 -#define PPSMC_MSG_DramLogSetDramAddrHigh 0x41 -#define PPSMC_MSG_DramLogSetDramAddrLow 0x42 -#define PPSMC_MSG_DramLogSetDramSize 0x43 -#define PPSMC_MSG_SetFanMaxRpm 0x44 -#define PPSMC_MSG_SetFanMinPwm 0x45 -#define PPSMC_MSG_ConfigureGfxDidt 0x46 -#define PPSMC_MSG_NumOfDisplays 0x47 -#define PPSMC_MSG_RemoveMargins 0x48 -#define PPSMC_MSG_ReadSerialNumTop32 0x49 -#define PPSMC_MSG_ReadSerialNumBottom32 0x4A -#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x4B -#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x4C -#define PPSMC_MSG_WaflTest 0x4D -#define PPSMC_MSG_SetFclkGfxClkRatio 0x4E -// Unused ID 0x4F to 0x50 -#define PPSMC_MSG_AllowGfxOff 0x51 -#define PPSMC_MSG_DisallowGfxOff 0x52 -#define PPSMC_MSG_GetPptLimit 0x53 -#define PPSMC_MSG_GetDcModeMaxDpmFreq 0x54 -#define PPSMC_MSG_GetDebugData 0x55 -#define PPSMC_MSG_SetXgmiMode 0x56 -#define PPSMC_MSG_RunAfllBtc 0x57 -#define PPSMC_MSG_ExitBaco 0x58 -#define PPSMC_MSG_PrepareMp1ForReset 0x59 -#define PPSMC_MSG_PrepareMp1ForShutdown 0x5A -#define PPSMC_MSG_SetMGpuFanBoostLimitRpm 0x5D -#define PPSMC_MSG_GetAVFSVoltageByDpm 0x5F -#define PPSMC_MSG_BacoWorkAroundFlushVDCI 0x60 -#define PPSMC_MSG_DFCstateControl 0x63 -#define PPSMC_Message_Count 0x64 - -typedef uint32_t PPSMC_Result; -typedef uint32_t PPSMC_Msg; - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c deleted file mode 100644 index 4b4d461899df..000000000000 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ /dev/null @@ -1,2674 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#define SWSMU_CODE_LAYER_L2 - -#include -#include -#include -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "atomfirmware.h" -#include "amdgpu_atomfirmware.h" -#include "amdgpu_atombios.h" -#include "soc15_common.h" -#include "smu_v11_0.h" -#include "smu11_driver_if_navi10.h" -#include "atom.h" -#include "navi10_ppt.h" -#include "smu_v11_0_pptable.h" -#include "smu_v11_0_ppsmc.h" -#include "nbio/nbio_2_3_offset.h" -#include "nbio/nbio_2_3_sh_mask.h" -#include "thm/thm_11_0_2_offset.h" -#include "thm/thm_11_0_2_sh_mask.h" - -#include "asic_reg/mp/mp_11_0_sh_mask.h" -#include "smu_cmn.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - -#define FEATURE_MASK(feature) (1ULL << feature) -#define SMC_DPM_FEATURE ( \ - FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ - FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_GFX_PACE_BIT) | \ - FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) - -static struct cmn2asic_msg_mapping navi10_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, 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), - MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), - MSG_MAP(GetEnabledSmuFeaturesLow, PPSMC_MSG_GetEnabledSmuFeaturesLow, 1), - MSG_MAP(GetEnabledSmuFeaturesHigh, PPSMC_MSG_GetEnabledSmuFeaturesHigh, 1), - MSG_MAP(SetWorkloadMask, PPSMC_MSG_SetWorkloadMask, 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(UseBackupPPTable, PPSMC_MSG_UseBackupPPTable, 0), - MSG_MAP(RunBtc, PPSMC_MSG_RunBtc, 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, 0), - MSG_MAP(GetMinDpmFreq, PPSMC_MSG_GetMinDpmFreq, 1), - MSG_MAP(GetMaxDpmFreq, PPSMC_MSG_GetMaxDpmFreq, 1), - MSG_MAP(GetDpmFreqByIndex, PPSMC_MSG_GetDpmFreqByIndex, 1), - MSG_MAP(SetMemoryChannelConfig, PPSMC_MSG_SetMemoryChannelConfig, 0), - 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(SetMinDeepSleepDcefclk, PPSMC_MSG_SetMinDeepSleepDcefclk, 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(DramLogSetDramAddrHigh, PPSMC_MSG_DramLogSetDramAddrHigh, 0), - MSG_MAP(DramLogSetDramAddrLow, PPSMC_MSG_DramLogSetDramAddrLow, 0), - MSG_MAP(DramLogSetDramSize, PPSMC_MSG_DramLogSetDramSize, 0), - MSG_MAP(ConfigureGfxDidt, PPSMC_MSG_ConfigureGfxDidt, 0), - MSG_MAP(NumOfDisplays, PPSMC_MSG_NumOfDisplays, 0), - MSG_MAP(SetSystemVirtualDramAddrHigh, PPSMC_MSG_SetSystemVirtualDramAddrHigh, 0), - MSG_MAP(SetSystemVirtualDramAddrLow, PPSMC_MSG_SetSystemVirtualDramAddrLow, 0), - 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(GetDebugData, PPSMC_MSG_GetDebugData, 0), - MSG_MAP(ExitBaco, PPSMC_MSG_ExitBaco, 0), - MSG_MAP(PrepareMp1ForReset, PPSMC_MSG_PrepareMp1ForReset, 0), - MSG_MAP(PrepareMp1ForShutdown, PPSMC_MSG_PrepareMp1ForShutdown, 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(DAL_DISABLE_DUMMY_PSTATE_CHANGE,PPSMC_MSG_DALDisableDummyPstateChange, 0), - MSG_MAP(DAL_ENABLE_DUMMY_PSTATE_CHANGE, PPSMC_MSG_DALEnableDummyPstateChange, 0), - MSG_MAP(GetVoltageByDpm, PPSMC_MSG_GetVoltageByDpm, 0), - MSG_MAP(GetVoltageByDpmOverdrive, PPSMC_MSG_GetVoltageByDpmOverdrive, 0), - MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), -}; - -static struct cmn2asic_mapping navi10_clk_map[SMU_CLK_COUNT] = { - CLK_MAP(GFXCLK, PPCLK_GFXCLK), - CLK_MAP(SCLK, PPCLK_GFXCLK), - CLK_MAP(SOCCLK, PPCLK_SOCCLK), - CLK_MAP(FCLK, PPCLK_SOCCLK), - CLK_MAP(UCLK, PPCLK_UCLK), - CLK_MAP(MCLK, PPCLK_UCLK), - CLK_MAP(DCLK, PPCLK_DCLK), - CLK_MAP(VCLK, PPCLK_VCLK), - CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), - CLK_MAP(DISPCLK, PPCLK_DISPCLK), - CLK_MAP(PIXCLK, PPCLK_PIXCLK), - CLK_MAP(PHYCLK, PPCLK_PHYCLK), -}; - -static struct cmn2asic_mapping navi10_feature_mask_map[SMU_FEATURE_COUNT] = { - FEA_MAP(DPM_PREFETCHER), - FEA_MAP(DPM_GFXCLK), - FEA_MAP(DPM_GFX_PACE), - FEA_MAP(DPM_UCLK), - FEA_MAP(DPM_SOCCLK), - FEA_MAP(DPM_MP0CLK), - FEA_MAP(DPM_LINK), - FEA_MAP(DPM_DCEFCLK), - FEA_MAP(MEM_VDDCI_SCALING), - FEA_MAP(MEM_MVDD_SCALING), - FEA_MAP(DS_GFXCLK), - FEA_MAP(DS_SOCCLK), - FEA_MAP(DS_LCLK), - FEA_MAP(DS_DCEFCLK), - FEA_MAP(DS_UCLK), - FEA_MAP(GFX_ULV), - FEA_MAP(FW_DSTATE), - FEA_MAP(GFXOFF), - FEA_MAP(BACO), - FEA_MAP(VCN_PG), - FEA_MAP(JPEG_PG), - FEA_MAP(USB_PG), - FEA_MAP(RSMU_SMN_CG), - FEA_MAP(PPT), - FEA_MAP(TDC), - FEA_MAP(GFX_EDC), - FEA_MAP(APCC_PLUS), - FEA_MAP(GTHR), - FEA_MAP(ACDC), - FEA_MAP(VR0HOT), - FEA_MAP(VR1HOT), - FEA_MAP(FW_CTF), - FEA_MAP(FAN_CONTROL), - FEA_MAP(THERMAL), - FEA_MAP(GFX_DCS), - FEA_MAP(RM), - FEA_MAP(LED_DISPLAY), - FEA_MAP(GFX_SS), - FEA_MAP(OUT_OF_BAND_MONITOR), - FEA_MAP(TEMP_DEPENDENT_VMIN), - FEA_MAP(MMHUB_PG), - FEA_MAP(ATHUB_PG), - FEA_MAP(APCC_DFLL), -}; - -static struct cmn2asic_mapping navi10_table_map[SMU_TABLE_COUNT] = { - TAB_MAP(PPTABLE), - TAB_MAP(WATERMARKS), - TAB_MAP(AVFS), - TAB_MAP(AVFS_PSM_DEBUG), - TAB_MAP(AVFS_FUSE_OVERRIDE), - TAB_MAP(PMSTATUSLOG), - TAB_MAP(SMU_METRICS), - TAB_MAP(DRIVER_SMU_CONFIG), - TAB_MAP(ACTIVITY_MONITOR_COEFF), - TAB_MAP(OVERDRIVE), - TAB_MAP(I2C_COMMANDS), - TAB_MAP(PACE), -}; - -static struct cmn2asic_mapping navi10_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { - PWR_MAP(AC), - PWR_MAP(DC), -}; - -static struct cmn2asic_mapping navi10_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), -}; - -static bool is_asic_secure(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - bool is_secure = true; - uint32_t mp0_fw_intf; - - mp0_fw_intf = RREG32_PCIE(MP0_Public | - (smnMP0_FW_INTF & 0xffffffff)); - - if (!(mp0_fw_intf & (1 << 19))) - is_secure = false; - - return is_secure; -} - -static int -navi10_get_allowed_feature_mask(struct smu_context *smu, - uint32_t *feature_mask, uint32_t num) -{ - struct amdgpu_device *adev = smu->adev; - - if (num > 2) - return -EINVAL; - - memset(feature_mask, 0, sizeof(uint32_t) * num); - - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) - | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) - | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) - | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) - | FEATURE_MASK(FEATURE_PPT_BIT) - | FEATURE_MASK(FEATURE_TDC_BIT) - | FEATURE_MASK(FEATURE_GFX_EDC_BIT) - | FEATURE_MASK(FEATURE_APCC_PLUS_BIT) - | FEATURE_MASK(FEATURE_VR0HOT_BIT) - | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) - | FEATURE_MASK(FEATURE_THERMAL_BIT) - | FEATURE_MASK(FEATURE_LED_DISPLAY_BIT) - | FEATURE_MASK(FEATURE_DS_LCLK_BIT) - | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) - | FEATURE_MASK(FEATURE_FW_DSTATE_BIT) - | FEATURE_MASK(FEATURE_BACO_BIT) - | FEATURE_MASK(FEATURE_GFX_SS_BIT) - | FEATURE_MASK(FEATURE_APCC_DFLL_BIT) - | FEATURE_MASK(FEATURE_FW_CTF_BIT) - | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT); - - if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); - - if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); - - if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT); - - if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT); - - if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); - - if (adev->pm.pp_feature & PP_ULV_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT); - - if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); - - if (adev->pm.pp_feature & PP_GFXOFF_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_VCN_PG_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_JPEG_PG_BIT); - - if (smu->dc_controlled_by_gpio) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ACDC_BIT); - - /* disable DPM UCLK and DS SOCCLK on navi10 A0 secure board */ - if (is_asic_secure(smu)) { - /* only for navi10 A0 */ - if ((adev->asic_type == CHIP_NAVI10) && - (adev->rev_id == 0)) { - *(uint64_t *)feature_mask &= - ~(FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT)); - *(uint64_t *)feature_mask &= - ~FEATURE_MASK(FEATURE_DS_SOCCLK_BIT); - } - } - - return 0; -} - -static int navi10_check_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - struct smu_baco_context *smu_baco = &smu->smu_baco; - - if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_HARDWAREDC) - smu->dc_controlled_by_gpio = true; - - mutex_lock(&smu_baco->mutex); - if (powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_BACO || - powerplay_table->platform_caps & SMU_11_0_PP_PLATFORM_CAP_MACO) - smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); - - table_context->thermal_controller_type = - powerplay_table->thermal_controller_type; - - /* - * Instead of having its own buffer space and get overdrive_table copied, - * smu->od_settings just points to the actual overdrive_table - */ - smu->od_settings = &powerplay_table->overdrive_table; - - return 0; -} - -static int navi10_append_powerplay_table(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *smc_pptable = table_context->driver_pptable; - struct atom_smc_dpm_info_v4_5 *smc_dpm_table; - struct atom_smc_dpm_info_v4_7 *smc_dpm_table_v4_7; - int index, ret; - - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - smc_dpm_info); - - ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, - (uint8_t **)&smc_dpm_table); - if (ret) - return ret; - - dev_info(adev->dev, "smc_dpm_info table revision(format.content): %d.%d\n", - smc_dpm_table->table_header.format_revision, - smc_dpm_table->table_header.content_revision); - - if (smc_dpm_table->table_header.format_revision != 4) { - dev_err(adev->dev, "smc_dpm_info table format revision is not 4!\n"); - return -EINVAL; - } - - switch (smc_dpm_table->table_header.content_revision) { - case 5: /* nv10 and nv14 */ - memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers, - sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); - break; - case 7: /* nv12 */ - ret = amdgpu_atombios_get_data_table(adev, index, NULL, NULL, NULL, - (uint8_t **)&smc_dpm_table_v4_7); - if (ret) - return ret; - memcpy(smc_pptable->I2cControllers, smc_dpm_table_v4_7->I2cControllers, - sizeof(*smc_dpm_table_v4_7) - sizeof(smc_dpm_table_v4_7->table_header)); - break; - default: - dev_err(smu->adev->dev, "smc_dpm_info with unsupported content revision %d!\n", - smc_dpm_table->table_header.content_revision); - return -EINVAL; - } - - if (adev->pm.pp_feature & PP_GFXOFF_MASK) { - /* TODO: remove it once SMU fw fix it */ - smc_pptable->DebugOverrides |= DPM_OVERRIDE_DISABLE_DFLL_PLL_SHUTDOWN; - } - - return 0; -} - -static int navi10_store_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - - memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, - sizeof(PPTable_t)); - - return 0; -} - -static int navi10_setup_pptable(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_v11_0_setup_pptable(smu); - if (ret) - return ret; - - ret = navi10_store_powerplay_table(smu); - if (ret) - return ret; - - ret = navi10_append_powerplay_table(smu); - if (ret) - return ret; - - ret = navi10_check_powerplay_table(smu); - if (ret) - return ret; - - return ret; -} - -static int navi10_tables_init(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - struct amdgpu_device *adev = smu->adev; - - SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - if (adev->asic_type == CHIP_NAVI12) - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_NV12_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - else - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, - sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM); - - smu_table->metrics_table = kzalloc(adev->asic_type == CHIP_NAVI12 ? - sizeof(SmuMetrics_NV12_t) : - sizeof(SmuMetrics_t), GFP_KERNEL); - if (!smu_table->metrics_table) - goto err0_out; - smu_table->metrics_time = 0; - - smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); - smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); - if (!smu_table->gpu_metrics_table) - goto err1_out; - - smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); - if (!smu_table->watermarks_table) - goto err2_out; - - return 0; - -err2_out: - kfree(smu_table->gpu_metrics_table); -err1_out: - kfree(smu_table->metrics_table); -err0_out: - return -ENOMEM; -} - -static int navi10_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) -{ - struct smu_table_context *smu_table= &smu->smu_table; - /* - * This works for NV12 also. As although NV12 uses a different - * SmuMetrics structure from other NV1X ASICs, they share the - * same offsets for the heading parts(those members used here). - */ - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); - return ret; - } - - switch (member) { - case METRICS_CURR_GFXCLK: - *value = metrics->CurrClock[PPCLK_GFXCLK]; - break; - case METRICS_CURR_SOCCLK: - *value = metrics->CurrClock[PPCLK_SOCCLK]; - break; - case METRICS_CURR_UCLK: - *value = metrics->CurrClock[PPCLK_UCLK]; - break; - case METRICS_CURR_VCLK: - *value = metrics->CurrClock[PPCLK_VCLK]; - break; - case METRICS_CURR_DCLK: - *value = metrics->CurrClock[PPCLK_DCLK]; - break; - case METRICS_CURR_DCEFCLK: - *value = metrics->CurrClock[PPCLK_DCEFCLK]; - break; - case METRICS_AVERAGE_GFXCLK: - *value = metrics->AverageGfxclkFrequency; - break; - case METRICS_AVERAGE_SOCCLK: - *value = metrics->AverageSocclkFrequency; - break; - case METRICS_AVERAGE_UCLK: - *value = metrics->AverageUclkFrequency; - break; - case METRICS_AVERAGE_GFXACTIVITY: - *value = metrics->AverageGfxActivity; - break; - case METRICS_AVERAGE_MEMACTIVITY: - *value = metrics->AverageUclkActivity; - break; - case METRICS_AVERAGE_SOCKETPOWER: - *value = metrics->AverageSocketPower << 8; - break; - case METRICS_TEMPERATURE_EDGE: - *value = metrics->TemperatureEdge * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_HOTSPOT: - *value = metrics->TemperatureHotspot * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_MEM: - *value = metrics->TemperatureMem * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRGFX: - *value = metrics->TemperatureVrGfx * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRSOC: - *value = metrics->TemperatureVrSoc * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_THROTTLER_STATUS: - *value = metrics->ThrottlerStatus; - break; - case METRICS_CURR_FANSPEED: - *value = metrics->CurrFanSpeed; - break; - default: - *value = UINT_MAX; - break; - } - - mutex_unlock(&smu->metrics_lock); - - return ret; -} - -static int navi10_allocate_dpm_context(struct smu_context *smu) -{ - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - - smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), - GFP_KERNEL); - if (!smu_dpm->dpm_context) - return -ENOMEM; - - smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); - - return 0; -} - -static int navi10_init_smc_tables(struct smu_context *smu) -{ - int ret = 0; - - ret = navi10_tables_init(smu); - if (ret) - return ret; - - ret = navi10_allocate_dpm_context(smu); - if (ret) - return ret; - - return smu_v11_0_init_smc_tables(smu); -} - -static int navi10_set_default_dpm_table(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - PPTable_t *driver_ppt = smu->smu_table.driver_pptable; - struct smu_11_0_dpm_table *dpm_table; - int ret = 0; - - /* socclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.soc_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_SOCCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* gfxclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.gfx_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_GFXCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* uclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.uclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_UCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* vclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.vclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_VCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_VCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* dclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.dclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* dcefclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.dcef_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DCEFCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* pixelclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.pixel_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_PIXCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* displayclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.display_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DISPCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* phyclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.phy_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_PHYCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - return 0; -} - -static int navi10_dpm_set_vcn_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - /* vcn dpm on is a prerequisite for vcn power gate messages */ - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 1, NULL); - if (ret) - return ret; - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); - if (ret) - return ret; - } - } - - return ret; -} - -static int navi10_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpJpeg, NULL); - if (ret) - return ret; - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownJpeg, NULL); - if (ret) - return ret; - } - } - - return ret; -} - -static int navi10_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - MetricsMember_t member_type; - int clk_id = 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - switch (clk_id) { - case PPCLK_GFXCLK: - member_type = METRICS_CURR_GFXCLK; - break; - case PPCLK_UCLK: - member_type = METRICS_CURR_UCLK; - break; - case PPCLK_SOCCLK: - member_type = METRICS_CURR_SOCCLK; - break; - case PPCLK_VCLK: - member_type = METRICS_CURR_VCLK; - break; - case PPCLK_DCLK: - member_type = METRICS_CURR_DCLK; - break; - case PPCLK_DCEFCLK: - member_type = METRICS_CURR_DCEFCLK; - break; - default: - return -EINVAL; - } - - return navi10_get_smu_metrics_data(smu, - member_type, - value); -} - -static bool navi10_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - DpmDescriptor_t *dpm_desc = NULL; - uint32_t clk_index = 0; - - clk_index = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - dpm_desc = &pptable->DpmDescriptor[clk_index]; - - /* 0 - Fine grained DPM, 1 - Discrete DPM */ - return dpm_desc->SnapToDiscrete == 0 ? true : false; -} - -static inline bool navi10_od_feature_is_supported(struct smu_11_0_overdrive_table *od_table, enum SMU_11_0_ODFEATURE_CAP cap) -{ - return od_table->cap[cap]; -} - -static void navi10_od_setting_get_range(struct smu_11_0_overdrive_table *od_table, - enum SMU_11_0_ODSETTING_ID setting, - uint32_t *min, uint32_t *max) -{ - if (min) - *min = od_table->min[setting]; - if (max) - *max = od_table->max[setting]; -} - -static int navi10_print_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, char *buf) -{ - uint16_t *curve_settings; - int i, size = 0, ret = 0; - uint32_t cur_value = 0, value = 0, count = 0; - uint32_t freq_values[3] = {0}; - uint32_t mark_index = 0; - struct smu_table_context *table_context = &smu->smu_table; - uint32_t gen_speed, lane_width; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; - OverDriveTable_t *od_table = - (OverDriveTable_t *)table_context->overdrive_table; - struct smu_11_0_overdrive_table *od_settings = smu->od_settings; - uint32_t min_value, max_value; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - case SMU_SOCCLK: - case SMU_MCLK: - case SMU_UCLK: - case SMU_FCLK: - case SMU_DCEFCLK: - ret = navi10_get_current_clk_freq_by_table(smu, clk_type, &cur_value); - if (ret) - return size; - - ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); - if (ret) - return size; - - if (!navi10_is_support_fine_grained_dpm(smu, clk_type)) { - for (i = 0; i < count; i++) { - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); - if (ret) - return size; - - size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, - cur_value == value ? "*" : ""); - } - } else { - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); - if (ret) - return size; - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); - if (ret) - return size; - - freq_values[1] = cur_value; - mark_index = cur_value == freq_values[0] ? 0 : - cur_value == freq_values[2] ? 2 : 1; - if (mark_index != 1) - freq_values[1] = (freq_values[0] + freq_values[2]) / 2; - - for (i = 0; i < 3; i++) { - size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i], - i == mark_index ? "*" : ""); - } - - } - break; - case SMU_PCIE: - gen_speed = smu_v11_0_get_current_pcie_link_speed_level(smu); - lane_width = smu_v11_0_get_current_pcie_link_width_level(smu); - for (i = 0; i < NUM_LINK_LEVELS; i++) - size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "", - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "", - pptable->LclkFreq[i], - (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) && - (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ? - "*" : ""); - break; - case SMU_OD_SCLK: - if (!smu->od_enabled || !od_table || !od_settings) - break; - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) - break; - size += sprintf(buf + size, "OD_SCLK:\n"); - size += sprintf(buf + size, "0: %uMhz\n1: %uMhz\n", od_table->GfxclkFmin, od_table->GfxclkFmax); - break; - case SMU_OD_MCLK: - if (!smu->od_enabled || !od_table || !od_settings) - break; - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) - break; - size += sprintf(buf + size, "OD_MCLK:\n"); - size += sprintf(buf + size, "1: %uMHz\n", od_table->UclkFmax); - break; - case SMU_OD_VDDC_CURVE: - if (!smu->od_enabled || !od_table || !od_settings) - break; - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) - break; - size += sprintf(buf + size, "OD_VDDC_CURVE:\n"); - for (i = 0; i < 3; i++) { - switch (i) { - case 0: - curve_settings = &od_table->GfxclkFreq1; - break; - case 1: - curve_settings = &od_table->GfxclkFreq2; - break; - case 2: - curve_settings = &od_table->GfxclkFreq3; - break; - default: - break; - } - size += sprintf(buf + size, "%d: %uMHz %umV\n", i, curve_settings[0], curve_settings[1] / NAVI10_VOLTAGE_SCALE); - } - break; - case SMU_OD_RANGE: - if (!smu->od_enabled || !od_table || !od_settings) - break; - size = sprintf(buf, "%s:\n", "OD_RANGE"); - - if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMIN, - &min_value, NULL); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_GFXCLKFMAX, - NULL, &max_value); - size += sprintf(buf + size, "SCLK: %7uMhz %10uMhz\n", - min_value, max_value); - } - - if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_UCLKFMAX, - &min_value, &max_value); - size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", - min_value, max_value); - } - - if (navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_SCLK[0]: %7uMhz %10uMhz\n", - min_value, max_value); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[0]: %7dmV %11dmV\n", - min_value, max_value); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_SCLK[1]: %7uMhz %10uMhz\n", - min_value, max_value); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[1]: %7dmV %11dmV\n", - min_value, max_value); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_SCLK[2]: %7uMhz %10uMhz\n", - min_value, max_value); - navi10_od_setting_get_range(od_settings, SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3, - &min_value, &max_value); - size += sprintf(buf + size, "VDDC_CURVE_VOLT[2]: %7dmV %11dmV\n", - min_value, max_value); - } - - break; - default: - break; - } - - return size; -} - -static int navi10_force_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, uint32_t mask) -{ - - int ret = 0, size = 0; - uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; - - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - case SMU_SOCCLK: - case SMU_MCLK: - case SMU_UCLK: - case SMU_DCEFCLK: - case SMU_FCLK: - /* There is only 2 levels for fine grained DPM */ - if (navi10_is_support_fine_grained_dpm(smu, clk_type)) { - soft_max_level = (soft_max_level >= 1 ? 1 : 0); - soft_min_level = (soft_min_level >= 1 ? 1 : 0); - } - - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); - if (ret) - return size; - - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); - if (ret) - return size; - - ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); - if (ret) - return size; - break; - default: - break; - } - - return size; -} - -static int navi10_populate_umd_state_clk(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = - smu->smu_dpm.dpm_context; - struct smu_11_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_11_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_11_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_umd_pstate_table *pstate_table = - &smu->pstate_table; - struct amdgpu_device *adev = smu->adev; - uint32_t sclk_freq; - - pstate_table->gfxclk_pstate.min = gfx_table->min; - switch (adev->asic_type) { - case CHIP_NAVI10: - switch (adev->pdev->revision) { - case 0xf0: /* XTX */ - case 0xc0: - sclk_freq = NAVI10_PEAK_SCLK_XTX; - break; - case 0xf1: /* XT */ - case 0xc1: - sclk_freq = NAVI10_PEAK_SCLK_XT; - break; - default: /* XL */ - sclk_freq = NAVI10_PEAK_SCLK_XL; - break; - } - break; - case CHIP_NAVI14: - switch (adev->pdev->revision) { - case 0xc7: /* XT */ - case 0xf4: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK; - break; - case 0xc1: /* XTM */ - case 0xf2: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK; - break; - case 0xc3: /* XLM */ - case 0xf3: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - case 0xc5: /* XTX */ - case 0xf6: - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK; - break; - default: /* XL */ - sclk_freq = NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK; - break; - } - break; - case CHIP_NAVI12: - sclk_freq = NAVI12_UMD_PSTATE_PEAK_GFXCLK; - break; - default: - sclk_freq = gfx_table->dpm_levels[gfx_table->count - 1].value; - break; - } - pstate_table->gfxclk_pstate.peak = sclk_freq; - - pstate_table->uclk_pstate.min = mem_table->min; - pstate_table->uclk_pstate.peak = mem_table->max; - - pstate_table->socclk_pstate.min = soc_table->min; - pstate_table->socclk_pstate.peak = soc_table->max; - - if (gfx_table->max > NAVI10_UMD_PSTATE_PROFILING_GFXCLK && - mem_table->max > NAVI10_UMD_PSTATE_PROFILING_MEMCLK && - soc_table->max > NAVI10_UMD_PSTATE_PROFILING_SOCCLK) { - pstate_table->gfxclk_pstate.standard = - NAVI10_UMD_PSTATE_PROFILING_GFXCLK; - pstate_table->uclk_pstate.standard = - NAVI10_UMD_PSTATE_PROFILING_MEMCLK; - pstate_table->socclk_pstate.standard = - NAVI10_UMD_PSTATE_PROFILING_SOCCLK; - } else { - pstate_table->gfxclk_pstate.standard = - pstate_table->gfxclk_pstate.min; - pstate_table->uclk_pstate.standard = - pstate_table->uclk_pstate.min; - pstate_table->socclk_pstate.standard = - pstate_table->socclk_pstate.min; - } - - return 0; -} - -static int navi10_get_clock_by_type_with_latency(struct smu_context *smu, - enum smu_clk_type clk_type, - struct pp_clock_levels_with_latency *clocks) -{ - int ret = 0, i = 0; - uint32_t level_count = 0, freq = 0; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_DCEFCLK: - case SMU_SOCCLK: - case SMU_MCLK: - case SMU_UCLK: - ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &level_count); - if (ret) - return ret; - - level_count = min(level_count, (uint32_t)MAX_NUM_CLOCKS); - clocks->num_levels = level_count; - - for (i = 0; i < level_count; i++) { - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &freq); - if (ret) - return ret; - - clocks->data[i].clocks_in_khz = freq * 1000; - clocks->data[i].latency_in_us = 0; - } - break; - default: - break; - } - - return ret; -} - -static int navi10_pre_display_config_changed(struct smu_context *smu) -{ - int ret = 0; - uint32_t max_freq = 0; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); - if (ret) - return ret; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); - if (ret) - return ret; - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); - if (ret) - return ret; - } - - return ret; -} - -static int navi10_display_config_changed(struct smu_context *smu) -{ - int ret = 0; - - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, - smu->display_config->num_display, - NULL); - if (ret) - return ret; - } - - return ret; -} - -static int navi10_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int navi10_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = navi10_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static bool navi10_is_dpm_running(struct smu_context *smu) -{ - int ret = 0; - uint32_t feature_mask[2]; - unsigned long feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); - return !!(feature_enabled & SMC_DPM_FEATURE); -} - -static int navi10_get_fan_speed_rpm(struct smu_context *smu, - uint32_t *speed) -{ - if (!speed) - return -EINVAL; - - return navi10_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); -} - -static int navi10_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = navi10_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - -static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - uint32_t i, size = 0; - int16_t workload_type = 0; - static const char *profile_name[] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - static const char *title[] = { - "PROFILE_INDEX(NAME)", - "CLOCK_TYPE(NAME)", - "FPS", - "MinFreqType", - "MinActiveFreqType", - "MinActiveFreq", - "BoosterFreqType", - "BoosterFreq", - "PD_Data_limit_c", - "PD_Data_error_coeff", - "PD_Data_error_rate_coeff"}; - int result = 0; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", - title[0], title[1], title[2], title[3], title[4], title[5], - title[6], title[7], title[8], title[9], title[10]); - - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - i); - if (workload_type < 0) - return -EINVAL; - - result = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, - (void *)(&activity_monitor), false); - if (result) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return result; - } - - size += sprintf(buf + size, "%2d %14s%s:\n", - i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 0, - "GFXCLK", - activity_monitor.Gfx_FPS, - activity_monitor.Gfx_MinFreqStep, - activity_monitor.Gfx_MinActiveFreqType, - activity_monitor.Gfx_MinActiveFreq, - activity_monitor.Gfx_BoosterFreqType, - activity_monitor.Gfx_BoosterFreq, - activity_monitor.Gfx_PD_Data_limit_c, - activity_monitor.Gfx_PD_Data_error_coeff, - activity_monitor.Gfx_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 1, - "SOCCLK", - activity_monitor.Soc_FPS, - activity_monitor.Soc_MinFreqStep, - activity_monitor.Soc_MinActiveFreqType, - activity_monitor.Soc_MinActiveFreq, - activity_monitor.Soc_BoosterFreqType, - activity_monitor.Soc_BoosterFreq, - activity_monitor.Soc_PD_Data_limit_c, - activity_monitor.Soc_PD_Data_error_coeff, - activity_monitor.Soc_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 2, - "MEMLK", - activity_monitor.Mem_FPS, - activity_monitor.Mem_MinFreqStep, - activity_monitor.Mem_MinActiveFreqType, - activity_monitor.Mem_MinActiveFreq, - activity_monitor.Mem_BoosterFreqType, - activity_monitor.Mem_BoosterFreq, - activity_monitor.Mem_PD_Data_limit_c, - activity_monitor.Mem_PD_Data_error_coeff, - activity_monitor.Mem_PD_Data_error_rate_coeff); - } - - return size; -} - -static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - int workload_type, ret = 0; - - smu->power_profile_mode = input[size]; - - if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); - return -EINVAL; - } - - if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { - - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), false); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return ret; - } - - switch (input[0]) { - case 0: /* Gfxclk */ - activity_monitor.Gfx_FPS = input[1]; - activity_monitor.Gfx_MinFreqStep = input[2]; - activity_monitor.Gfx_MinActiveFreqType = input[3]; - activity_monitor.Gfx_MinActiveFreq = input[4]; - activity_monitor.Gfx_BoosterFreqType = input[5]; - activity_monitor.Gfx_BoosterFreq = input[6]; - activity_monitor.Gfx_PD_Data_limit_c = input[7]; - activity_monitor.Gfx_PD_Data_error_coeff = input[8]; - activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; - break; - case 1: /* Socclk */ - activity_monitor.Soc_FPS = input[1]; - activity_monitor.Soc_MinFreqStep = input[2]; - activity_monitor.Soc_MinActiveFreqType = input[3]; - activity_monitor.Soc_MinActiveFreq = input[4]; - activity_monitor.Soc_BoosterFreqType = input[5]; - activity_monitor.Soc_BoosterFreq = input[6]; - activity_monitor.Soc_PD_Data_limit_c = input[7]; - activity_monitor.Soc_PD_Data_error_coeff = input[8]; - activity_monitor.Soc_PD_Data_error_rate_coeff = input[9]; - break; - case 2: /* Memlk */ - activity_monitor.Mem_FPS = input[1]; - activity_monitor.Mem_MinFreqStep = input[2]; - activity_monitor.Mem_MinActiveFreqType = input[3]; - activity_monitor.Mem_MinActiveFreq = input[4]; - activity_monitor.Mem_BoosterFreqType = input[5]; - activity_monitor.Mem_BoosterFreq = input[6]; - activity_monitor.Mem_PD_Data_limit_c = input[7]; - activity_monitor.Mem_PD_Data_error_coeff = input[8]; - activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; - break; - } - - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), true); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); - return ret; - } - } - - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - smu->power_profile_mode); - if (workload_type < 0) - return -EINVAL; - smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type, NULL); - - return ret; -} - -static int navi10_notify_smc_display_config(struct smu_context *smu) -{ - struct smu_clocks min_clocks = {0}; - struct pp_display_clock_request clock_req; - int ret = 0; - - min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; - min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; - min_clocks.memory_clock = smu->display_config->min_mem_set_clock; - - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - clock_req.clock_type = amd_pp_dcef_clock; - clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; - - ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); - if (!ret) { - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcef_clock_in_sr/100, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!"); - return ret; - } - } - } else { - dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!"); - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); - if (ret) { - dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); - return ret; - } - } - - return 0; -} - -static int navi10_set_watermarks_table(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) -{ - Watermarks_t *table = smu->smu_table.watermarks_table; - int ret = 0; - int i; - - if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; - - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } - - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; - } - - smu->watermarks_bitmap |= WATERMARKS_EXIST; - } - - /* pass data to smu controller */ - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { - ret = smu_cmn_write_watermarks_table(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to update WMTABLE!"); - return ret; - } - smu->watermarks_bitmap |= WATERMARKS_LOADED; - } - - return 0; -} - -static int navi10_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = navi10_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - -static int navi10_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *pptable = table_context->driver_pptable; - - if(!data || !size) - return -EINVAL; - - mutex_lock(&smu->sensor_lock); - switch (sensor) { - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: - *(uint32_t *)data = pptable->FanMaximumRpm; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = navi10_get_current_activity_percent(smu, sensor, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - ret = navi10_get_gpu_power(smu, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - case AMDGPU_PP_SENSOR_EDGE_TEMP: - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = navi10_thermal_get_temperature(smu, sensor, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = navi10_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = navi10_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VDDGFX: - ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - mutex_unlock(&smu->sensor_lock); - - return ret; -} - -static int navi10_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states) -{ - uint32_t num_discrete_levels = 0; - uint16_t *dpm_levels = NULL; - uint16_t i = 0; - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *driver_ppt = NULL; - - if (!clocks_in_khz || !num_states || !table_context->driver_pptable) - return -EINVAL; - - driver_ppt = table_context->driver_pptable; - num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; - dpm_levels = driver_ppt->FreqTableUclk; - - if (num_discrete_levels == 0 || dpm_levels == NULL) - return -EINVAL; - - *num_states = num_discrete_levels; - for (i = 0; i < num_discrete_levels; i++) { - /* convert to khz */ - *clocks_in_khz = (*dpm_levels) * 1000; - clocks_in_khz++; - dpm_levels++; - } - - return 0; -} - -static int navi10_get_thermal_temperature_range(struct smu_context *smu, - struct smu_temperature_range *range) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_powerplay_table *powerplay_table = - table_context->power_play_table; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - if (!range) - return -EINVAL; - - memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); - - range->max = pptable->TedgeLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->edge_emergency_max = (pptable->TedgeLimit + CTF_OFFSET_EDGE) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_crit_max = pptable->ThotspotLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_emergency_max = (pptable->ThotspotLimit + CTF_OFFSET_HOTSPOT) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_crit_max = pptable->TmemLimit * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_emergency_max = (pptable->TmemLimit + CTF_OFFSET_MEM)* - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->software_shutdown_temp = powerplay_table->software_shutdown_temp; - - return 0; -} - -static int navi10_display_disable_memory_clock_switch(struct smu_context *smu, - bool disable_memory_clock_switch) -{ - int ret = 0; - struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = - (struct smu_11_0_max_sustainable_clocks *) - smu->smu_table.max_sustainable_clocks; - uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal; - uint32_t max_memory_clock = max_sustainable_clocks->uclock; - - if(smu->disable_uclk_switch == disable_memory_clock_switch) - return 0; - - if(disable_memory_clock_switch) - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); - else - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); - - if(!ret) - smu->disable_uclk_switch = disable_memory_clock_switch; - - return ret; -} - -static int navi10_get_power_limit(struct smu_context *smu) -{ - struct smu_11_0_powerplay_table *powerplay_table = - (struct smu_11_0_powerplay_table *)smu->smu_table.power_play_table; - struct smu_11_0_overdrive_table *od_settings = smu->od_settings; - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t power_limit, od_percent; - - if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; - } - smu->current_power_limit = power_limit; - - if (smu->od_enabled && - navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_POWER_LIMIT)) { - od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_ODSETTING_POWERPERCENTAGE]); - - dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - - power_limit *= (100 + od_percent); - power_limit /= 100; - } - smu->max_power_limit = power_limit; - - return 0; -} - -static int navi10_update_pcie_parameters(struct smu_context *smu, - uint32_t pcie_gen_cap, - uint32_t pcie_width_cap) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t smu_pcie_arg; - int ret, i; - - /* lclk dpm table setup */ - for (i = 0; i < MAX_PCIE_CONF; i++) { - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; - } - - for (i = 0; i < NUM_LINK_LEVELS; i++) { - smu_pcie_arg = (i << 16) | - ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? (pptable->PcieGenSpeed[i] << 8) : - (pcie_gen_cap << 8)) | ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? - pptable->PcieLaneCount[i] : pcie_width_cap); - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, - NULL); - - if (ret) - return ret; - - if (pptable->PcieGenSpeed[i] > pcie_gen_cap) - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap; - if (pptable->PcieLaneCount[i] > pcie_width_cap) - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap; - } - - return 0; -} - -static inline void navi10_dump_od_table(struct smu_context *smu, - OverDriveTable_t *od_table) -{ - dev_dbg(smu->adev->dev, "OD: Gfxclk: (%d, %d)\n", od_table->GfxclkFmin, od_table->GfxclkFmax); - dev_dbg(smu->adev->dev, "OD: Gfx1: (%d, %d)\n", od_table->GfxclkFreq1, od_table->GfxclkVolt1); - dev_dbg(smu->adev->dev, "OD: Gfx2: (%d, %d)\n", od_table->GfxclkFreq2, od_table->GfxclkVolt2); - dev_dbg(smu->adev->dev, "OD: Gfx3: (%d, %d)\n", od_table->GfxclkFreq3, od_table->GfxclkVolt3); - dev_dbg(smu->adev->dev, "OD: UclkFmax: %d\n", od_table->UclkFmax); - dev_dbg(smu->adev->dev, "OD: OverDrivePct: %d\n", od_table->OverDrivePct); -} - -static int navi10_od_setting_check_range(struct smu_context *smu, - struct smu_11_0_overdrive_table *od_table, - enum SMU_11_0_ODSETTING_ID setting, - uint32_t value) -{ - if (value < od_table->min[setting]) { - dev_warn(smu->adev->dev, "OD setting (%d, %d) is less than the minimum allowed (%d)\n", setting, value, od_table->min[setting]); - return -EINVAL; - } - if (value > od_table->max[setting]) { - dev_warn(smu->adev->dev, "OD setting (%d, %d) is greater than the maximum allowed (%d)\n", setting, value, od_table->max[setting]); - return -EINVAL; - } - return 0; -} - -static int navi10_overdrive_get_gfx_clk_base_voltage(struct smu_context *smu, - uint16_t *voltage, - uint32_t freq) -{ - uint32_t param = (freq & 0xFFFF) | (PPCLK_GFXCLK << 16); - uint32_t value = 0; - int ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetVoltageByDpm, - param, - &value); - if (ret) { - dev_err(smu->adev->dev, "[GetBaseVoltage] failed to get GFXCLK AVFS voltage from SMU!"); - return ret; - } - - *voltage = (uint16_t)value; - - return 0; -} - -static bool navi10_is_baco_supported(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t val; - - if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) - return false; - - val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); - return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; -} - -static int navi10_set_default_od_settings(struct smu_context *smu) -{ - OverDriveTable_t *od_table = - (OverDriveTable_t *)smu->smu_table.overdrive_table; - OverDriveTable_t *boot_od_table = - (OverDriveTable_t *)smu->smu_table.boot_overdrive_table; - int ret = 0; - - ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, false); - if (ret) { - dev_err(smu->adev->dev, "Failed to get overdrive table!\n"); - return ret; - } - - if (!od_table->GfxclkVolt1) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt1, - od_table->GfxclkFreq1); - if (ret) - return ret; - } - - if (!od_table->GfxclkVolt2) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt2, - od_table->GfxclkFreq2); - if (ret) - return ret; - } - - if (!od_table->GfxclkVolt3) { - ret = navi10_overdrive_get_gfx_clk_base_voltage(smu, - &od_table->GfxclkVolt3, - od_table->GfxclkFreq3); - if (ret) - return ret; - } - - memcpy(boot_od_table, od_table, sizeof(OverDriveTable_t)); - - navi10_dump_od_table(smu, od_table); - - return 0; -} - -static int navi10_od_edit_dpm_table(struct smu_context *smu, enum PP_OD_DPM_TABLE_COMMAND type, long input[], uint32_t size) { - int i; - int ret = 0; - struct smu_table_context *table_context = &smu->smu_table; - OverDriveTable_t *od_table; - struct smu_11_0_overdrive_table *od_settings; - enum SMU_11_0_ODSETTING_ID freq_setting, voltage_setting; - uint16_t *freq_ptr, *voltage_ptr; - od_table = (OverDriveTable_t *)table_context->overdrive_table; - - if (!smu->od_enabled) { - dev_warn(smu->adev->dev, "OverDrive is not enabled!\n"); - return -EINVAL; - } - - if (!smu->od_settings) { - dev_err(smu->adev->dev, "OD board limits are not set!\n"); - return -ENOENT; - } - - od_settings = smu->od_settings; - - switch (type) { - case PP_OD_EDIT_SCLK_VDDC_TABLE: - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_LIMITS)) { - dev_warn(smu->adev->dev, "GFXCLK_LIMITS not supported!\n"); - return -ENOTSUPP; - } - if (!table_context->overdrive_table) { - dev_err(smu->adev->dev, "Overdrive is not initialized\n"); - return -EINVAL; - } - for (i = 0; i < size; i += 2) { - if (i + 2 > size) { - dev_info(smu->adev->dev, "invalid number of input parameters %d\n", size); - return -EINVAL; - } - switch (input[i]) { - case 0: - freq_setting = SMU_11_0_ODSETTING_GFXCLKFMIN; - freq_ptr = &od_table->GfxclkFmin; - if (input[i + 1] > od_table->GfxclkFmax) { - dev_info(smu->adev->dev, "GfxclkFmin (%ld) must be <= GfxclkFmax (%u)!\n", - input[i + 1], - od_table->GfxclkFmin); - return -EINVAL; - } - break; - case 1: - freq_setting = SMU_11_0_ODSETTING_GFXCLKFMAX; - freq_ptr = &od_table->GfxclkFmax; - if (input[i + 1] < od_table->GfxclkFmin) { - dev_info(smu->adev->dev, "GfxclkFmax (%ld) must be >= GfxclkFmin (%u)!\n", - input[i + 1], - od_table->GfxclkFmax); - return -EINVAL; - } - break; - default: - dev_info(smu->adev->dev, "Invalid SCLK_VDDC_TABLE index: %ld\n", input[i]); - dev_info(smu->adev->dev, "Supported indices: [0:min,1:max]\n"); - return -EINVAL; - } - ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[i + 1]); - if (ret) - return ret; - *freq_ptr = input[i + 1]; - } - break; - case PP_OD_EDIT_MCLK_VDDC_TABLE: - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_UCLK_MAX)) { - dev_warn(smu->adev->dev, "UCLK_MAX not supported!\n"); - return -ENOTSUPP; - } - if (size < 2) { - dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); - return -EINVAL; - } - if (input[0] != 1) { - dev_info(smu->adev->dev, "Invalid MCLK_VDDC_TABLE index: %ld\n", input[0]); - dev_info(smu->adev->dev, "Supported indices: [1:max]\n"); - return -EINVAL; - } - ret = navi10_od_setting_check_range(smu, od_settings, SMU_11_0_ODSETTING_UCLKFMAX, input[1]); - if (ret) - return ret; - od_table->UclkFmax = input[1]; - break; - case PP_OD_RESTORE_DEFAULT_TABLE: - if (!(table_context->overdrive_table && table_context->boot_overdrive_table)) { - dev_err(smu->adev->dev, "Overdrive table was not initialized!\n"); - return -EINVAL; - } - memcpy(table_context->overdrive_table, table_context->boot_overdrive_table, sizeof(OverDriveTable_t)); - break; - case PP_OD_COMMIT_DPM_TABLE: - navi10_dump_od_table(smu, od_table); - ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)od_table, true); - if (ret) { - dev_err(smu->adev->dev, "Failed to import overdrive table!\n"); - return ret; - } - break; - case PP_OD_EDIT_VDDC_CURVE: - if (!navi10_od_feature_is_supported(od_settings, SMU_11_0_ODCAP_GFXCLK_CURVE)) { - dev_warn(smu->adev->dev, "GFXCLK_CURVE not supported!\n"); - return -ENOTSUPP; - } - if (size < 3) { - dev_info(smu->adev->dev, "invalid number of parameters: %d\n", size); - return -EINVAL; - } - if (!od_table) { - dev_info(smu->adev->dev, "Overdrive is not initialized\n"); - return -EINVAL; - } - - switch (input[0]) { - case 0: - freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P1; - voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P1; - freq_ptr = &od_table->GfxclkFreq1; - voltage_ptr = &od_table->GfxclkVolt1; - break; - case 1: - freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P2; - voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P2; - freq_ptr = &od_table->GfxclkFreq2; - voltage_ptr = &od_table->GfxclkVolt2; - break; - case 2: - freq_setting = SMU_11_0_ODSETTING_VDDGFXCURVEFREQ_P3; - voltage_setting = SMU_11_0_ODSETTING_VDDGFXCURVEVOLTAGE_P3; - freq_ptr = &od_table->GfxclkFreq3; - voltage_ptr = &od_table->GfxclkVolt3; - break; - default: - dev_info(smu->adev->dev, "Invalid VDDC_CURVE index: %ld\n", input[0]); - dev_info(smu->adev->dev, "Supported indices: [0, 1, 2]\n"); - return -EINVAL; - } - ret = navi10_od_setting_check_range(smu, od_settings, freq_setting, input[1]); - if (ret) - return ret; - // Allow setting zero to disable the OverDrive VDDC curve - if (input[2] != 0) { - ret = navi10_od_setting_check_range(smu, od_settings, voltage_setting, input[2]); - if (ret) - return ret; - *freq_ptr = input[1]; - *voltage_ptr = ((uint16_t)input[2]) * NAVI10_VOLTAGE_SCALE; - dev_dbg(smu->adev->dev, "OD: set curve %ld: (%d, %d)\n", input[0], *freq_ptr, *voltage_ptr); - } else { - // If setting 0, disable all voltage curve settings - od_table->GfxclkVolt1 = 0; - od_table->GfxclkVolt2 = 0; - od_table->GfxclkVolt3 = 0; - } - navi10_dump_od_table(smu, od_table); - break; - default: - return -ENOSYS; - } - return ret; -} - -static int navi10_run_btc(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_RunBtc, NULL); - if (ret) - dev_err(smu->adev->dev, "RunBtc failed!\n"); - - return ret; -} - -static int navi10_dummy_pstate_control(struct smu_context *smu, bool enable) -{ - int result = 0; - - if (!enable) - result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_DISABLE_DUMMY_PSTATE_CHANGE, NULL); - else - result = smu_cmn_send_smc_msg(smu, SMU_MSG_DAL_ENABLE_DUMMY_PSTATE_CHANGE, NULL); - - return result; -} - -static inline bool navi10_need_umc_cdr_12gbps_workaround(struct amdgpu_device *adev) -{ - if (adev->asic_type != CHIP_NAVI10) - return false; - - if (adev->pdev->device == 0x731f && - (adev->pdev->revision == 0xc2 || - adev->pdev->revision == 0xc3 || - adev->pdev->revision == 0xca || - adev->pdev->revision == 0xcb)) - return true; - else - return false; -} - -static int navi10_disable_umc_cdr_12gbps_workaround(struct smu_context *smu) -{ - uint32_t uclk_count, uclk_min, uclk_max; - uint32_t smu_version; - int ret = 0; - - if (!navi10_need_umc_cdr_12gbps_workaround(smu->adev)) - return 0; - - ret = smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (ret) - return ret; - - /* This workaround is available only for 42.50 or later SMC firmwares */ - if (smu_version < 0x2A3200) - return 0; - - ret = smu_v11_0_get_dpm_level_count(smu, SMU_UCLK, &uclk_count); - if (ret) - return ret; - - ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)0, &uclk_min); - if (ret) - return ret; - - ret = smu_v11_0_get_dpm_freq_by_index(smu, SMU_UCLK, (uint16_t)(uclk_count - 1), &uclk_max); - if (ret) - return ret; - - /* Force UCLK out of the highest DPM */ - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_min); - if (ret) - return ret; - - /* Revert the UCLK Hardmax */ - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, uclk_max); - if (ret) - return ret; - - /* - * In this case, SMU already disabled dummy pstate during enablement - * of UCLK DPM, we have to re-enabled it. - * */ - return navi10_dummy_pstate_control(smu, true); -} - -static void navi10_fill_i2c_req(SwI2cRequest_t *req, bool write, - uint8_t address, uint32_t numbytes, - uint8_t *data) -{ - int i; - - BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); - - req->I2CcontrollerPort = 0; - req->I2CSpeed = 2; - req->SlaveAddress = address; - req->NumCmds = numbytes; - - for (i = 0; i < numbytes; i++) { - SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; - - /* First 2 bytes are always write for lower 2b EEPROM address */ - if (i < 2) - cmd->Cmd = 1; - else - cmd->Cmd = write; - - - /* Add RESTART for read after address filled */ - cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; - - /* Add STOP in the end */ - cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; - - /* Fill with data regardless if read or write to simplify code */ - cmd->RegisterAddr = data[i]; - } -} - -static int navi10_i2c_read_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t i, ret = 0; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - struct smu_table_context *smu_table = &adev->smu.smu_table; - struct smu_table *table = &smu_table->driver_table; - - memset(&req, 0, sizeof(req)); - navi10_fill_i2c_req(&req, false, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - /* Now read data starting with that address */ - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, - true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; - - /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ - for (i = 0; i < numbytes; i++) - data[i] = res->SwI2cCmds[i].Data; - - dev_dbg(adev->dev, "navi10_i2c_read_data, address = %x, bytes = %d, data :", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - } else - dev_err(adev->dev, "navi10_i2c_read_data - error occurred :%x", ret); - - return ret; -} - -static int navi10_i2c_write_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t ret; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - - memset(&req, 0, sizeof(req)); - navi10_fill_i2c_req(&req, true, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - dev_dbg(adev->dev, "navi10_i2c_write(), address = %x, bytes = %d , data: ", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - /* - * According to EEPROM spec there is a MAX of 10 ms required for - * EEPROM to flush internal RX buffer after STOP was issued at the - * end of write transaction. During this time the EEPROM will not be - * responsive to any more commands - so wait a bit more. - */ - msleep(10); - - } else - dev_err(adev->dev, "navi10_i2c_write- error occurred :%x", ret); - - return ret; -} - -static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; - uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; - - for (i = 0; i < num; i++) { - /* - * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at - * once and hence the data needs to be spliced into chunks and sent each - * chunk separately - */ - data_size = msgs[i].len - 2; - data_chunk_size = MAX_SW_I2C_COMMANDS - 2; - next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); - data_ptr = msgs[i].buf + 2; - - for (j = 0; j < data_size / data_chunk_size; j++) { - /* Insert the EEPROM dest addess, bits 0-15 */ - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = navi10_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - - memcpy(data_ptr, data_chunk + 2, data_chunk_size); - } else { - - memcpy(data_chunk + 2, data_ptr, data_chunk_size); - - ret = navi10_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - } - - if (ret) { - num = -EIO; - goto fail; - } - - next_eeprom_addr += data_chunk_size; - data_ptr += data_chunk_size; - } - - if (data_size % data_chunk_size) { - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = navi10_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - - memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); - } else { - memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); - - ret = navi10_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - } - - if (ret) { - num = -EIO; - goto fail; - } - } - } - -fail: - return num; -} - -static u32 navi10_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - - -static const struct i2c_algorithm navi10_i2c_algo = { - .master_xfer = navi10_i2c_xfer, - .functionality = navi10_i2c_func, -}; - -static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; - - control->owner = THIS_MODULE; - control->class = I2C_CLASS_SPD; - control->dev.parent = &adev->pdev->dev; - control->algo = &navi10_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); - - return res; -} - -static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) -{ - i2c_del_adapter(control); -} - -static ssize_t navi10_get_gpu_metrics(struct smu_context *smu, - void **table) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct gpu_metrics_v1_0 *gpu_metrics = - (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; - struct amdgpu_device *adev = smu->adev; - SmuMetrics_NV12_t nv12_metrics = { 0 }; - SmuMetrics_t metrics; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - true); - if (ret) { - mutex_unlock(&smu->metrics_lock); - return ret; - } - - memcpy(&metrics, smu_table->metrics_table, sizeof(SmuMetrics_t)); - if (adev->asic_type == CHIP_NAVI12) - memcpy(&nv12_metrics, smu_table->metrics_table, sizeof(SmuMetrics_NV12_t)); - - mutex_unlock(&smu->metrics_lock); - - smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); - - gpu_metrics->temperature_edge = metrics.TemperatureEdge; - gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; - gpu_metrics->temperature_mem = metrics.TemperatureMem; - gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; - gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; - gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; - - gpu_metrics->average_socket_power = metrics.AverageSocketPower; - - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; - gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; - gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequency; - - if (adev->asic_type == CHIP_NAVI12) { - gpu_metrics->energy_accumulator = nv12_metrics.EnergyAccumulator; - gpu_metrics->average_vclk0_frequency = nv12_metrics.AverageVclkFrequency; - gpu_metrics->average_dclk0_frequency = nv12_metrics.AverageDclkFrequency; - gpu_metrics->average_mm_activity = nv12_metrics.VcnActivityPercentage; - } - - gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; - gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; - gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; - gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK]; - gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; - - gpu_metrics->pcie_link_width = - smu_v11_0_get_current_pcie_link_width(smu); - gpu_metrics->pcie_link_speed = - smu_v11_0_get_current_pcie_link_speed(smu); - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v1_0); -} - -static int navi10_enable_mgpu_fan_boost(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t param = 0; - - /* Navi12 does not support this */ - if (adev->asic_type == CHIP_NAVI12) - return 0; - - /* Workaround for WS SKU */ - if (adev->pdev->device == 0x7312 && - adev->pdev->revision == 0) - param = 0xD188; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetMGpuFanBoostLimitRpm, - param, - NULL); -} - -static const struct pptable_funcs navi10_ppt_funcs = { - .get_allowed_feature_mask = navi10_get_allowed_feature_mask, - .set_default_dpm_table = navi10_set_default_dpm_table, - .dpm_set_vcn_enable = navi10_dpm_set_vcn_enable, - .dpm_set_jpeg_enable = navi10_dpm_set_jpeg_enable, - .i2c_init = navi10_i2c_control_init, - .i2c_fini = navi10_i2c_control_fini, - .print_clk_levels = navi10_print_clk_levels, - .force_clk_levels = navi10_force_clk_levels, - .populate_umd_state_clk = navi10_populate_umd_state_clk, - .get_clock_by_type_with_latency = navi10_get_clock_by_type_with_latency, - .pre_display_config_changed = navi10_pre_display_config_changed, - .display_config_changed = navi10_display_config_changed, - .notify_smc_display_config = navi10_notify_smc_display_config, - .is_dpm_running = navi10_is_dpm_running, - .get_fan_speed_percent = navi10_get_fan_speed_percent, - .get_fan_speed_rpm = navi10_get_fan_speed_rpm, - .get_power_profile_mode = navi10_get_power_profile_mode, - .set_power_profile_mode = navi10_set_power_profile_mode, - .set_watermarks_table = navi10_set_watermarks_table, - .read_sensor = navi10_read_sensor, - .get_uclk_dpm_states = navi10_get_uclk_dpm_states, - .set_performance_level = smu_v11_0_set_performance_level, - .get_thermal_temperature_range = navi10_get_thermal_temperature_range, - .display_disable_memory_clock_switch = navi10_display_disable_memory_clock_switch, - .get_power_limit = navi10_get_power_limit, - .update_pcie_parameters = navi10_update_pcie_parameters, - .init_microcode = smu_v11_0_init_microcode, - .load_microcode = smu_v11_0_load_microcode, - .fini_microcode = smu_v11_0_fini_microcode, - .init_smc_tables = navi10_init_smc_tables, - .fini_smc_tables = smu_v11_0_fini_smc_tables, - .init_power = smu_v11_0_init_power, - .fini_power = smu_v11_0_fini_power, - .check_fw_status = smu_v11_0_check_fw_status, - .setup_pptable = navi10_setup_pptable, - .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, - .check_fw_version = smu_v11_0_check_fw_version, - .write_pptable = smu_cmn_write_pptable, - .set_driver_table_location = smu_v11_0_set_driver_table_location, - .set_tool_table_location = smu_v11_0_set_tool_table_location, - .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, - .system_features_control = smu_v11_0_system_features_control, - .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, - .send_smc_msg = smu_cmn_send_smc_msg, - .init_display_count = smu_v11_0_init_display_count, - .set_allowed_mask = smu_v11_0_set_allowed_mask, - .get_enabled_mask = smu_cmn_get_enabled_mask, - .feature_is_enabled = smu_cmn_feature_is_enabled, - .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, - .notify_display_change = smu_v11_0_notify_display_change, - .set_power_limit = smu_v11_0_set_power_limit, - .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, - .enable_thermal_alert = smu_v11_0_enable_thermal_alert, - .disable_thermal_alert = smu_v11_0_disable_thermal_alert, - .set_min_dcef_deep_sleep = smu_v11_0_set_min_deep_sleep_dcefclk, - .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, - .get_fan_control_mode = smu_v11_0_get_fan_control_mode, - .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, - .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, - .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, - .gfx_off_control = smu_v11_0_gfx_off_control, - .register_irq_handler = smu_v11_0_register_irq_handler, - .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, - .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= navi10_is_baco_supported, - .baco_get_state = smu_v11_0_baco_get_state, - .baco_set_state = smu_v11_0_baco_set_state, - .baco_enter = smu_v11_0_baco_enter, - .baco_exit = smu_v11_0_baco_exit, - .get_dpm_ultimate_freq = smu_v11_0_get_dpm_ultimate_freq, - .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .set_default_od_settings = navi10_set_default_od_settings, - .od_edit_dpm_table = navi10_od_edit_dpm_table, - .run_btc = navi10_run_btc, - .disable_umc_cdr_12gbps_workaround = navi10_disable_umc_cdr_12gbps_workaround, - .set_power_source = smu_v11_0_set_power_source, - .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, - .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, - .get_gpu_metrics = navi10_get_gpu_metrics, - .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, -}; - -void navi10_set_ppt_funcs(struct smu_context *smu) -{ - smu->ppt_funcs = &navi10_ppt_funcs; - smu->message_map = navi10_message_map; - smu->clock_map = navi10_clk_map; - smu->feature_map = navi10_feature_mask_map; - smu->table_map = navi10_table_map; - smu->pwr_src_map = navi10_pwr_src_map; - smu->workload_map = navi10_workload_map; -} diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h b/drivers/gpu/drm/amd/powerplay/navi10_ppt.h deleted file mode 100644 index 84dc5a1b6830..000000000000 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __NAVI10_PPT_H__ -#define __NAVI10_PPT_H__ - -#define NAVI10_PEAK_SCLK_XTX (1830) -#define NAVI10_PEAK_SCLK_XT (1755) -#define NAVI10_PEAK_SCLK_XL (1625) - -#define NAVI10_UMD_PSTATE_PROFILING_GFXCLK (1300) -#define NAVI10_UMD_PSTATE_PROFILING_SOCCLK (980) -#define NAVI10_UMD_PSTATE_PROFILING_MEMCLK (625) -#define NAVI10_UMD_PSTATE_PROFILING_VCLK (980) -#define NAVI10_UMD_PSTATE_PROFILING_DCLK (850) - -#define NAVI14_UMD_PSTATE_PEAK_XT_GFXCLK (1670) -#define NAVI14_UMD_PSTATE_PEAK_XTM_GFXCLK (1448) -#define NAVI14_UMD_PSTATE_PEAK_XLM_GFXCLK (1181) -#define NAVI14_UMD_PSTATE_PEAK_XTX_GFXCLK (1717) -#define NAVI14_UMD_PSTATE_PEAK_XL_GFXCLK (1448) - -#define NAVI14_UMD_PSTATE_PROFILING_GFXCLK (1200) -#define NAVI14_UMD_PSTATE_PROFILING_SOCCLK (900) -#define NAVI14_UMD_PSTATE_PROFILING_MEMCLK (600) -#define NAVI14_UMD_PSTATE_PROFILING_VCLK (900) -#define NAVI14_UMD_PSTATE_PROFILING_DCLK (800) - -#define NAVI12_UMD_PSTATE_PEAK_GFXCLK (1100) - -#define NAVI10_VOLTAGE_SCALE (4) - -extern void navi10_set_ppt_funcs(struct smu_context *smu); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c b/drivers/gpu/drm/amd/powerplay/renoir_ppt.c deleted file mode 100644 index 186929c31e9e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#define SWSMU_CODE_LAYER_L2 - -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "smu_v12_0_ppsmc.h" -#include "smu12_driver_if.h" -#include "smu_v12_0.h" -#include "renoir_ppt.h" -#include "smu_cmn.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -static struct cmn2asic_msg_mapping renoir_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(PowerUpGfx, PPSMC_MSG_PowerUpGfx, 1), - MSG_MAP(AllowGfxOff, PPSMC_MSG_EnableGfxOff, 1), - MSG_MAP(DisallowGfxOff, PPSMC_MSG_DisableGfxOff, 1), - MSG_MAP(PowerDownIspByTile, PPSMC_MSG_PowerDownIspByTile, 1), - MSG_MAP(PowerUpIspByTile, PPSMC_MSG_PowerUpIspByTile, 1), - MSG_MAP(PowerDownVcn, PPSMC_MSG_PowerDownVcn, 1), - MSG_MAP(PowerUpVcn, PPSMC_MSG_PowerUpVcn, 1), - MSG_MAP(PowerDownSdma, PPSMC_MSG_PowerDownSdma, 1), - MSG_MAP(PowerUpSdma, PPSMC_MSG_PowerUpSdma, 1), - MSG_MAP(SetHardMinIspclkByFreq, PPSMC_MSG_SetHardMinIspclkByFreq, 1), - MSG_MAP(SetHardMinVcn, PPSMC_MSG_SetHardMinVcn, 1), - MSG_MAP(Spare1, PPSMC_MSG_spare1, 1), - MSG_MAP(Spare2, PPSMC_MSG_spare2, 1), - MSG_MAP(SetAllowFclkSwitch, PPSMC_MSG_SetAllowFclkSwitch, 1), - MSG_MAP(SetMinVideoGfxclkFreq, PPSMC_MSG_SetMinVideoGfxclkFreq, 1), - MSG_MAP(ActiveProcessNotify, PPSMC_MSG_ActiveProcessNotify, 1), - MSG_MAP(SetCustomPolicy, PPSMC_MSG_SetCustomPolicy, 1), - MSG_MAP(SetVideoFps, PPSMC_MSG_SetVideoFps, 1), - MSG_MAP(NumOfDisplays, PPSMC_MSG_SetDisplayCount, 1), - MSG_MAP(QueryPowerLimit, PPSMC_MSG_QueryPowerLimit, 1), - MSG_MAP(SetDriverDramAddrHigh, PPSMC_MSG_SetDriverDramAddrHigh, 1), - MSG_MAP(SetDriverDramAddrLow, PPSMC_MSG_SetDriverDramAddrLow, 1), - MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 1), - MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 1), - MSG_MAP(GfxDeviceDriverReset, PPSMC_MSG_GfxDeviceDriverReset, 1), - MSG_MAP(SetGfxclkOverdriveByFreqVid, PPSMC_MSG_SetGfxclkOverdriveByFreqVid, 1), - MSG_MAP(SetHardMinDcfclkByFreq, PPSMC_MSG_SetHardMinDcfclkByFreq, 1), - MSG_MAP(SetHardMinSocclkByFreq, PPSMC_MSG_SetHardMinSocclkByFreq, 1), - MSG_MAP(ControlIgpuATS, PPSMC_MSG_ControlIgpuATS, 1), - MSG_MAP(SetMinVideoFclkFreq, PPSMC_MSG_SetMinVideoFclkFreq, 1), - MSG_MAP(SetMinDeepSleepDcfclk, PPSMC_MSG_SetMinDeepSleepDcfclk, 1), - MSG_MAP(ForcePowerDownGfx, PPSMC_MSG_ForcePowerDownGfx, 1), - MSG_MAP(SetPhyclkVoltageByFreq, PPSMC_MSG_SetPhyclkVoltageByFreq, 1), - MSG_MAP(SetDppclkVoltageByFreq, PPSMC_MSG_SetDppclkVoltageByFreq, 1), - MSG_MAP(SetSoftMinVcn, PPSMC_MSG_SetSoftMinVcn, 1), - MSG_MAP(EnablePostCode, PPSMC_MSG_EnablePostCode, 1), - MSG_MAP(GetGfxclkFrequency, PPSMC_MSG_GetGfxclkFrequency, 1), - MSG_MAP(GetFclkFrequency, PPSMC_MSG_GetFclkFrequency, 1), - MSG_MAP(GetMinGfxclkFrequency, PPSMC_MSG_GetMinGfxclkFrequency, 1), - MSG_MAP(GetMaxGfxclkFrequency, PPSMC_MSG_GetMaxGfxclkFrequency, 1), - MSG_MAP(SoftReset, PPSMC_MSG_SoftReset, 1), - MSG_MAP(SetGfxCGPG, PPSMC_MSG_SetGfxCGPG, 1), - MSG_MAP(SetSoftMaxGfxClk, PPSMC_MSG_SetSoftMaxGfxClk, 1), - MSG_MAP(SetHardMinGfxClk, PPSMC_MSG_SetHardMinGfxClk, 1), - MSG_MAP(SetSoftMaxSocclkByFreq, PPSMC_MSG_SetSoftMaxSocclkByFreq, 1), - MSG_MAP(SetSoftMaxFclkByFreq, PPSMC_MSG_SetSoftMaxFclkByFreq, 1), - MSG_MAP(SetSoftMaxVcn, PPSMC_MSG_SetSoftMaxVcn, 1), - MSG_MAP(PowerGateMmHub, PPSMC_MSG_PowerGateMmHub, 1), - MSG_MAP(UpdatePmeRestore, PPSMC_MSG_UpdatePmeRestore, 1), - MSG_MAP(GpuChangeState, PPSMC_MSG_GpuChangeState, 1), - MSG_MAP(SetPowerLimitPercentage, PPSMC_MSG_SetPowerLimitPercentage, 1), - MSG_MAP(ForceGfxContentSave, PPSMC_MSG_ForceGfxContentSave, 1), - MSG_MAP(EnableTmdp48MHzRefclkPwrDown, PPSMC_MSG_EnableTmdp48MHzRefclkPwrDown, 1), - MSG_MAP(PowerDownJpeg, PPSMC_MSG_PowerDownJpeg, 1), - MSG_MAP(PowerUpJpeg, PPSMC_MSG_PowerUpJpeg, 1), - MSG_MAP(PowerGateAtHub, PPSMC_MSG_PowerGateAtHub, 1), - MSG_MAP(SetSoftMinJpeg, PPSMC_MSG_SetSoftMinJpeg, 1), - MSG_MAP(SetHardMinFclkByFreq, PPSMC_MSG_SetHardMinFclkByFreq, 1), -}; - -static struct cmn2asic_mapping renoir_clk_map[SMU_CLK_COUNT] = { - CLK_MAP(GFXCLK, CLOCK_GFXCLK), - CLK_MAP(SCLK, CLOCK_GFXCLK), - CLK_MAP(SOCCLK, CLOCK_SOCCLK), - CLK_MAP(UCLK, CLOCK_FCLK), - CLK_MAP(MCLK, CLOCK_FCLK), -}; - -static struct cmn2asic_mapping renoir_table_map[SMU_TABLE_COUNT] = { - TAB_MAP_VALID(WATERMARKS), - TAB_MAP_INVALID(CUSTOM_DPM), - TAB_MAP_VALID(DPMCLOCKS), - TAB_MAP_VALID(SMU_METRICS), -}; - -static struct cmn2asic_mapping renoir_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_COMPUTE_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), -}; - -static int renoir_init_smc_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - - SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_DPMCLOCKS, sizeof(DpmClocks_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - - smu_table->clocks_table = kzalloc(sizeof(DpmClocks_t), GFP_KERNEL); - if (!smu_table->clocks_table) - goto err0_out; - - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); - if (!smu_table->metrics_table) - goto err1_out; - smu_table->metrics_time = 0; - - smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); - if (!smu_table->watermarks_table) - goto err2_out; - - smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v2_0); - smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); - if (!smu_table->gpu_metrics_table) - goto err3_out; - - return 0; - -err3_out: - kfree(smu_table->watermarks_table); -err2_out: - kfree(smu_table->metrics_table); -err1_out: - kfree(smu_table->clocks_table); -err0_out: - return -ENOMEM; -} - -/** - * This interface just for getting uclk ultimate freq and should't introduce - * other likewise function result in overmuch callback. - */ -static int renoir_get_dpm_clk_limited(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t dpm_level, uint32_t *freq) -{ - DpmClocks_t *clk_table = smu->smu_table.clocks_table; - - if (!clk_table || clk_type >= SMU_CLK_COUNT) - return -EINVAL; - - switch (clk_type) { - case SMU_SOCCLK: - if (dpm_level >= NUM_SOCCLK_DPM_LEVELS) - return -EINVAL; - *freq = clk_table->SocClocks[dpm_level].Freq; - break; - case SMU_MCLK: - if (dpm_level >= NUM_FCLK_DPM_LEVELS) - return -EINVAL; - *freq = clk_table->FClocks[dpm_level].Freq; - break; - case SMU_DCEFCLK: - if (dpm_level >= NUM_DCFCLK_DPM_LEVELS) - return -EINVAL; - *freq = clk_table->DcfClocks[dpm_level].Freq; - break; - case SMU_FCLK: - if (dpm_level >= NUM_FCLK_DPM_LEVELS) - return -EINVAL; - *freq = clk_table->FClocks[dpm_level].Freq; - break; - default: - return -EINVAL; - } - - return 0; -} - -static int renoir_get_profiling_clk_mask(struct smu_context *smu, - enum amd_dpm_forced_level level, - uint32_t *sclk_mask, - uint32_t *mclk_mask, - uint32_t *soc_mask) -{ - - if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK) { - if (sclk_mask) - *sclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK) { - if (mclk_mask) - *mclk_mask = 0; - } else if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK) { - if(sclk_mask) - /* The sclk as gfxclk and has three level about max/min/current */ - *sclk_mask = 3 - 1; - - if(mclk_mask) - *mclk_mask = NUM_MEMCLK_DPM_LEVELS - 1; - - if(soc_mask) - *soc_mask = NUM_SOCCLK_DPM_LEVELS - 1; - } - - return 0; -} - -static int renoir_get_dpm_ultimate_freq(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *min, - uint32_t *max) -{ - int ret = 0; - uint32_t mclk_mask, soc_mask; - uint32_t clock_limit; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) { - switch (clk_type) { - case SMU_MCLK: - case SMU_UCLK: - clock_limit = smu->smu_table.boot_values.uclk; - break; - case SMU_GFXCLK: - case SMU_SCLK: - clock_limit = smu->smu_table.boot_values.gfxclk; - break; - case SMU_SOCCLK: - clock_limit = smu->smu_table.boot_values.socclk; - break; - default: - clock_limit = 0; - break; - } - - /* clock in Mhz unit */ - if (min) - *min = clock_limit / 100; - if (max) - *max = clock_limit / 100; - - return 0; - } - - if (max) { - ret = renoir_get_profiling_clk_mask(smu, - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK, - NULL, - &mclk_mask, - &soc_mask); - if (ret) - goto failed; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMaxGfxclkFrequency, max); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get max GX frequency from SMC Failed !\n"); - goto failed; - } - break; - case SMU_UCLK: - case SMU_FCLK: - case SMU_MCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, mclk_mask, max); - if (ret) - goto failed; - break; - case SMU_SOCCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, soc_mask, max); - if (ret) - goto failed; - break; - default: - ret = -EINVAL; - goto failed; - } - } - - if (min) { - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetMinGfxclkFrequency, min); - if (ret) { - dev_err(smu->adev->dev, "Attempt to get min GX frequency from SMC Failed !\n"); - goto failed; - } - break; - case SMU_UCLK: - case SMU_FCLK: - case SMU_MCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); - if (ret) - goto failed; - break; - case SMU_SOCCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, 0, min); - if (ret) - goto failed; - break; - default: - ret = -EINVAL; - goto failed; - } - } -failed: - return ret; -} - -static int renoir_print_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, char *buf) -{ - int i, size = 0, ret = 0; - uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0; - SmuMetrics_t metrics; - bool cur_value_match_level = false; - - memset(&metrics, 0, sizeof(metrics)); - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - /* retirve table returned paramters unit is MHz */ - cur_value = metrics.ClockFrequency[CLOCK_GFXCLK]; - ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min, &max); - if (!ret) { - /* driver only know min/max gfx_clk, Add level 1 for all other gfx clks */ - if (cur_value == max) - i = 2; - else if (cur_value == min) - i = 0; - else - i = 1; - - size += sprintf(buf + size, "0: %uMhz %s\n", min, - i == 0 ? "*" : ""); - size += sprintf(buf + size, "1: %uMhz %s\n", - i == 1 ? cur_value : RENOIR_UMD_PSTATE_GFXCLK, - i == 1 ? "*" : ""); - size += sprintf(buf + size, "2: %uMhz %s\n", max, - i == 2 ? "*" : ""); - } - return size; - case SMU_SOCCLK: - count = NUM_SOCCLK_DPM_LEVELS; - cur_value = metrics.ClockFrequency[CLOCK_SOCCLK]; - break; - case SMU_MCLK: - count = NUM_MEMCLK_DPM_LEVELS; - cur_value = metrics.ClockFrequency[CLOCK_FCLK]; - break; - case SMU_DCEFCLK: - count = NUM_DCFCLK_DPM_LEVELS; - cur_value = metrics.ClockFrequency[CLOCK_DCFCLK]; - break; - case SMU_FCLK: - count = NUM_FCLK_DPM_LEVELS; - cur_value = metrics.ClockFrequency[CLOCK_FCLK]; - break; - default: - return -EINVAL; - } - - for (i = 0; i < count; i++) { - ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value); - if (ret) - return ret; - if (!value) - continue; - size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, - cur_value == value ? "*" : ""); - if (cur_value == value) - cur_value_match_level = true; - } - - if (!cur_value_match_level) - size += sprintf(buf + size, " %uMhz *\n", cur_value); - - return size; -} - -static enum amd_pm_state_type renoir_get_current_power_state(struct smu_context *smu) -{ - enum amd_pm_state_type pm_type; - struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - - if (!smu_dpm_ctx->dpm_context || - !smu_dpm_ctx->dpm_current_power_state) - return -EINVAL; - - switch (smu_dpm_ctx->dpm_current_power_state->classification.ui_label) { - case SMU_STATE_UI_LABEL_BATTERY: - pm_type = POWER_STATE_TYPE_BATTERY; - break; - case SMU_STATE_UI_LABEL_BALLANCED: - pm_type = POWER_STATE_TYPE_BALANCED; - break; - case SMU_STATE_UI_LABEL_PERFORMANCE: - pm_type = POWER_STATE_TYPE_PERFORMANCE; - break; - default: - if (smu_dpm_ctx->dpm_current_power_state->classification.flags & SMU_STATE_CLASSIFICATION_FLAG_BOOT) - pm_type = POWER_STATE_TYPE_INTERNAL_BOOT; - else - pm_type = POWER_STATE_TYPE_DEFAULT; - break; - } - - return pm_type; -} - -static int renoir_dpm_set_vcn_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - /* vcn dpm on is a prerequisite for vcn power gate messages */ - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); - if (ret) - return ret; - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_VCN_PG_BIT)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownVcn, NULL); - if (ret) - return ret; - } - } - - return ret; -} - -static int renoir_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); - if (ret) - return ret; - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_JPEG_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); - if (ret) - return ret; - } - } - - return ret; -} - -static int renoir_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - int ret = 0, clk_id = 0; - SmuMetrics_t metrics; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - *value = metrics.ClockFrequency[clk_id]; - - return ret; -} - -static int renoir_force_dpm_limit_value(struct smu_context *smu, bool highest) -{ - int ret = 0, i = 0; - uint32_t min_freq, max_freq, force_freq; - enum smu_clk_type clk_type; - - enum smu_clk_type clks[] = { - SMU_GFXCLK, - SMU_MCLK, - SMU_SOCCLK, - }; - - for (i = 0; i < ARRAY_SIZE(clks); i++) { - clk_type = clks[i]; - ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); - if (ret) - return ret; - - force_freq = highest ? max_freq : min_freq; - ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, force_freq, force_freq); - if (ret) - return ret; - } - - return ret; -} - -static int renoir_unforce_dpm_levels(struct smu_context *smu) { - - int ret = 0, i = 0; - uint32_t min_freq, max_freq; - enum smu_clk_type clk_type; - - struct clk_feature_map { - enum smu_clk_type clk_type; - uint32_t feature; - } clk_feature_map[] = { - {SMU_GFXCLK, SMU_FEATURE_DPM_GFXCLK_BIT}, - {SMU_MCLK, SMU_FEATURE_DPM_UCLK_BIT}, - {SMU_SOCCLK, SMU_FEATURE_DPM_SOCCLK_BIT}, - }; - - for (i = 0; i < ARRAY_SIZE(clk_feature_map); i++) { - if (!smu_cmn_feature_is_enabled(smu, clk_feature_map[i].feature)) - continue; - - clk_type = clk_feature_map[i].clk_type; - - ret = renoir_get_dpm_ultimate_freq(smu, clk_type, &min_freq, &max_freq); - if (ret) - return ret; - - ret = smu_v12_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); - if (ret) - return ret; - } - - return ret; -} - -static int renoir_get_gpu_temperature(struct smu_context *smu, uint32_t *value) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - *value = (metrics.GfxTemperature / 100) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - - return 0; -} - -static int renoir_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - SmuMetrics_t metrics; - - if (!value) - return -EINVAL; - - ret = smu_cmn_get_metrics_table(smu, &metrics, false); - if (ret) - return ret; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - *value = metrics.AverageGfxActivity / 100; - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return 0; -} - -/** - * This interface get dpm clock table for dc - */ -static int renoir_get_dpm_clock_table(struct smu_context *smu, struct dpm_clocks *clock_table) -{ - DpmClocks_t *table = smu->smu_table.clocks_table; - int i; - - if (!clock_table || !table) - return -EINVAL; - - for (i = 0; i < NUM_DCFCLK_DPM_LEVELS; i++) { - clock_table->DcfClocks[i].Freq = table->DcfClocks[i].Freq; - clock_table->DcfClocks[i].Vol = table->DcfClocks[i].Vol; - } - - for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) { - clock_table->SocClocks[i].Freq = table->SocClocks[i].Freq; - clock_table->SocClocks[i].Vol = table->SocClocks[i].Vol; - } - - for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) { - clock_table->FClocks[i].Freq = table->FClocks[i].Freq; - clock_table->FClocks[i].Vol = table->FClocks[i].Vol; - } - - for (i = 0; i< NUM_MEMCLK_DPM_LEVELS; i++) { - clock_table->MemClocks[i].Freq = table->MemClocks[i].Freq; - clock_table->MemClocks[i].Vol = table->MemClocks[i].Vol; - } - - return 0; -} - -static int renoir_force_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, uint32_t mask) -{ - - int ret = 0 ; - uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; - - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - if (soft_min_level > 2 || soft_max_level > 2) { - dev_info(smu->adev->dev, "Currently sclk only support 3 levels on APU\n"); - return -EINVAL; - } - - ret = renoir_get_dpm_ultimate_freq(smu, SMU_GFXCLK, &min_freq, &max_freq); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, - soft_max_level == 0 ? min_freq : - soft_max_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : max_freq, - NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, - soft_min_level == 2 ? max_freq : - soft_min_level == 1 ? RENOIR_UMD_PSTATE_GFXCLK : min_freq, - NULL); - if (ret) - return ret; - break; - case SMU_SOCCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); - if (ret) - return ret; - ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max_freq, NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min_freq, NULL); - if (ret) - return ret; - break; - case SMU_MCLK: - case SMU_FCLK: - ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_min_level, &min_freq); - if (ret) - return ret; - ret = renoir_get_dpm_clk_limited(smu, clk_type, soft_max_level, &max_freq); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max_freq, NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min_freq, NULL); - if (ret) - return ret; - break; - default: - break; - } - - return ret; -} - -static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) -{ - int workload_type, ret; - uint32_t profile_mode = input[size]; - - if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode); - return -EINVAL; - } - - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - profile_mode); - if (workload_type < 0) { - /* - * TODO: If some case need switch to powersave/default power mode - * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving. - */ - dev_err_once(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode); - return -EINVAL; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify, - 1 << workload_type, - NULL); - if (ret) { - dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type); - return ret; - } - - smu->power_profile_mode = profile_mode; - - return 0; -} - -static int renoir_set_peak_clock_by_device(struct smu_context *smu) -{ - int ret = 0; - uint32_t sclk_freq = 0, uclk_freq = 0; - - ret = renoir_get_dpm_ultimate_freq(smu, SMU_SCLK, NULL, &sclk_freq); - if (ret) - return ret; - - ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_SCLK, sclk_freq, sclk_freq); - if (ret) - return ret; - - ret = renoir_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &uclk_freq); - if (ret) - return ret; - - ret = smu_v12_0_set_soft_freq_limited_range(smu, SMU_UCLK, uclk_freq, uclk_freq); - if (ret) - return ret; - - return ret; -} - -static int renoir_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - int ret = 0; - uint32_t sclk_mask, mclk_mask, soc_mask; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - ret = renoir_force_dpm_limit_value(smu, true); - break; - case AMD_DPM_FORCED_LEVEL_LOW: - ret = renoir_force_dpm_limit_value(smu, false); - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - ret = renoir_unforce_dpm_levels(smu); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - ret = renoir_get_profiling_clk_mask(smu, level, - &sclk_mask, - &mclk_mask, - &soc_mask); - if (ret) - return ret; - renoir_force_clk_levels(smu, SMU_SCLK, 1 << sclk_mask); - renoir_force_clk_levels(smu, SMU_MCLK, 1 << mclk_mask); - renoir_force_clk_levels(smu, SMU_SOCCLK, 1 << soc_mask); - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - ret = renoir_set_peak_clock_by_device(smu); - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - default: - break; - } - return ret; -} - -/* save watermark settings into pplib smu structure, - * also pass data to smu controller - */ -static int renoir_set_watermarks_table( - struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges) -{ - Watermarks_t *table = smu->smu_table.watermarks_table; - int ret = 0; - int i; - - if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; - - /* save into smu->smu_table.tables[SMU_TABLE_WATERMARKS]->cpu_addr*/ - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[WM_DCFCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_DCFCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } - - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[WM_SOCCLK][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MinMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].MaxMclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz)); - table->WatermarkRow[WM_SOCCLK][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; - } - - smu->watermarks_bitmap |= WATERMARKS_EXIST; - } - - /* pass data to smu controller */ - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { - ret = smu_cmn_write_watermarks_table(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to update WMTABLE!"); - return ret; - } - smu->watermarks_bitmap |= WATERMARKS_LOADED; - } - - return 0; -} - -static int renoir_get_power_profile_mode(struct smu_context *smu, - char *buf) -{ - static const char *profile_name[] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - uint32_t i, size = 0; - int16_t workload_type = 0; - - if (!buf) - return -EINVAL; - - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { - /* - * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT - * Not all profile modes are supported on arcturus. - */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - i); - if (workload_type < 0) - continue; - - size += sprintf(buf + size, "%2d %14s%s\n", - i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); - } - - return size; -} - -static int renoir_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - - if (!data || !size) - return -EINVAL; - - mutex_lock(&smu->sensor_lock); - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = renoir_get_current_activity_percent(smu, sensor, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_TEMP: - ret = renoir_get_gpu_temperature(smu, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = renoir_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = renoir_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - mutex_unlock(&smu->sensor_lock); - - return ret; -} - -static bool renoir_is_dpm_running(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - - /* - * Until now, the pmfw hasn't exported the interface of SMU - * feature mask to APU SKU so just force on all the feature - * at early initial stage. - */ - if (adev->in_suspend) - return false; - else - return true; - -} - -static ssize_t renoir_get_gpu_metrics(struct smu_context *smu, - void **table) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct gpu_metrics_v2_0 *gpu_metrics = - (struct gpu_metrics_v2_0 *)smu_table->gpu_metrics_table; - SmuMetrics_t metrics; - int ret = 0; - - ret = smu_cmn_get_metrics_table(smu, &metrics, true); - if (ret) - return ret; - - smu_v12_0_init_gpu_metrics_v2_0(gpu_metrics); - - gpu_metrics->temperature_gfx = metrics.GfxTemperature; - gpu_metrics->temperature_soc = metrics.SocTemperature; - memcpy(&gpu_metrics->temperature_core[0], - &metrics.CoreTemperature[0], - sizeof(uint16_t) * 8); - gpu_metrics->temperature_l3[0] = metrics.L3Temperature[0]; - gpu_metrics->temperature_l3[1] = metrics.L3Temperature[1]; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_mm_activity = metrics.AverageUvdActivity; - - gpu_metrics->average_socket_power = metrics.CurrentSocketPower; - gpu_metrics->average_cpu_power = metrics.Power[0]; - gpu_metrics->average_soc_power = metrics.Power[1]; - memcpy(&gpu_metrics->average_core_power[0], - &metrics.CorePower[0], - sizeof(uint16_t) * 8); - - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequency; - gpu_metrics->average_socclk_frequency = metrics.AverageSocclkFrequency; - gpu_metrics->average_fclk_frequency = metrics.AverageFclkFrequency; - gpu_metrics->average_vclk_frequency = metrics.AverageVclkFrequency; - - gpu_metrics->current_gfxclk = metrics.ClockFrequency[CLOCK_GFXCLK]; - gpu_metrics->current_socclk = metrics.ClockFrequency[CLOCK_SOCCLK]; - gpu_metrics->current_uclk = metrics.ClockFrequency[CLOCK_UMCCLK]; - gpu_metrics->current_fclk = metrics.ClockFrequency[CLOCK_FCLK]; - gpu_metrics->current_vclk = metrics.ClockFrequency[CLOCK_VCLK]; - gpu_metrics->current_dclk = metrics.ClockFrequency[CLOCK_DCLK]; - memcpy(&gpu_metrics->current_coreclk[0], - &metrics.CoreFrequency[0], - sizeof(uint16_t) * 8); - gpu_metrics->current_l3clk[0] = metrics.L3Frequency[0]; - gpu_metrics->current_l3clk[1] = metrics.L3Frequency[1]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - gpu_metrics->fan_pwm = metrics.FanPwm; - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v2_0); -} - -static const struct pptable_funcs renoir_ppt_funcs = { - .set_power_state = NULL, - .print_clk_levels = renoir_print_clk_levels, - .get_current_power_state = renoir_get_current_power_state, - .dpm_set_vcn_enable = renoir_dpm_set_vcn_enable, - .dpm_set_jpeg_enable = renoir_dpm_set_jpeg_enable, - .force_clk_levels = renoir_force_clk_levels, - .set_power_profile_mode = renoir_set_power_profile_mode, - .set_performance_level = renoir_set_performance_level, - .get_dpm_clock_table = renoir_get_dpm_clock_table, - .set_watermarks_table = renoir_set_watermarks_table, - .get_power_profile_mode = renoir_get_power_profile_mode, - .read_sensor = renoir_read_sensor, - .check_fw_status = smu_v12_0_check_fw_status, - .check_fw_version = smu_v12_0_check_fw_version, - .powergate_sdma = smu_v12_0_powergate_sdma, - .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, - .send_smc_msg = smu_cmn_send_smc_msg, - .set_gfx_cgpg = smu_v12_0_set_gfx_cgpg, - .gfx_off_control = smu_v12_0_gfx_off_control, - .get_gfx_off_status = smu_v12_0_get_gfxoff_status, - .init_smc_tables = renoir_init_smc_tables, - .fini_smc_tables = smu_v12_0_fini_smc_tables, - .set_default_dpm_table = smu_v12_0_set_default_dpm_tables, - .get_enabled_mask = smu_cmn_get_enabled_mask, - .feature_is_enabled = smu_cmn_feature_is_enabled, - .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, - .get_dpm_ultimate_freq = renoir_get_dpm_ultimate_freq, - .mode2_reset = smu_v12_0_mode2_reset, - .set_soft_freq_limited_range = smu_v12_0_set_soft_freq_limited_range, - .set_driver_table_location = smu_v12_0_set_driver_table_location, - .is_dpm_running = renoir_is_dpm_running, - .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, - .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, - .get_gpu_metrics = renoir_get_gpu_metrics, -}; - -void renoir_set_ppt_funcs(struct smu_context *smu) -{ - smu->ppt_funcs = &renoir_ppt_funcs; - smu->message_map = renoir_message_map; - smu->clock_map = renoir_clk_map; - smu->table_map = renoir_table_map; - smu->workload_map = renoir_workload_map; - smu->smc_driver_if_version = SMU12_DRIVER_IF_VERSION; - smu->is_apu = true; -} diff --git a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h b/drivers/gpu/drm/amd/powerplay/renoir_ppt.h deleted file mode 100644 index 8c3f004cdf8d..000000000000 --- a/drivers/gpu/drm/amd/powerplay/renoir_ppt.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __RENOIR_PPT_H__ -#define __RENOIR_PPT_H__ - -extern void renoir_set_ppt_funcs(struct smu_context *smu); - -/* UMD PState Renoir Msg Parameters in MHz */ -#define RENOIR_UMD_PSTATE_GFXCLK 700 -#define RENOIR_UMD_PSTATE_SOCCLK 678 -#define RENOIR_UMD_PSTATE_FCLK 800 - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c deleted file mode 100644 index 407a11c2826b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ /dev/null @@ -1,2810 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#define SWSMU_CODE_LAYER_L2 - -#include -#include -#include -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "atomfirmware.h" -#include "amdgpu_atomfirmware.h" -#include "amdgpu_atombios.h" -#include "smu_v11_0.h" -#include "smu11_driver_if_sienna_cichlid.h" -#include "soc15_common.h" -#include "atom.h" -#include "sienna_cichlid_ppt.h" -#include "smu_v11_0_7_pptable.h" -#include "smu_v11_0_7_ppsmc.h" -#include "nbio/nbio_2_3_offset.h" -#include "nbio/nbio_2_3_sh_mask.h" -#include "thm/thm_11_0_2_offset.h" -#include "thm/thm_11_0_2_sh_mask.h" -#include "mp/mp_11_0_offset.h" -#include "mp/mp_11_0_sh_mask.h" - -#include "asic_reg/mp/mp_11_0_sh_mask.h" -#include "smu_cmn.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c)) - -#define FEATURE_MASK(feature) (1ULL << feature) -#define SMC_DPM_FEATURE ( \ - FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \ - FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_UCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ - 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), - MSG_MAP(GetDriverIfVersion, PPSMC_MSG_GetDriverIfVersion, 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), - MSG_MAP(DisableSmuFeaturesHigh, PPSMC_MSG_DisableSmuFeaturesHigh, 1), - 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, 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, 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, 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, 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, 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), - MSG_MAP(SetMGpuFanBoostLimitRpm, PPSMC_MSG_SetMGpuFanBoostLimitRpm, 0), -}; - -static struct cmn2asic_mapping sienna_cichlid_clk_map[SMU_CLK_COUNT] = { - CLK_MAP(GFXCLK, PPCLK_GFXCLK), - CLK_MAP(SCLK, PPCLK_GFXCLK), - CLK_MAP(SOCCLK, PPCLK_SOCCLK), - CLK_MAP(FCLK, PPCLK_FCLK), - CLK_MAP(UCLK, PPCLK_UCLK), - CLK_MAP(MCLK, PPCLK_UCLK), - CLK_MAP(DCLK, PPCLK_DCLK_0), - CLK_MAP(DCLK1, PPCLK_DCLK_1), - CLK_MAP(VCLK, PPCLK_VCLK_0), - CLK_MAP(VCLK1, PPCLK_VCLK_1), - CLK_MAP(DCEFCLK, PPCLK_DCEFCLK), - CLK_MAP(DISPCLK, PPCLK_DISPCLK), - CLK_MAP(PIXCLK, PPCLK_PIXCLK), - CLK_MAP(PHYCLK, PPCLK_PHYCLK), -}; - -static struct cmn2asic_mapping sienna_cichlid_feature_mask_map[SMU_FEATURE_COUNT] = { - FEA_MAP(DPM_PREFETCHER), - FEA_MAP(DPM_GFXCLK), - FEA_MAP(DPM_GFX_GPO), - FEA_MAP(DPM_UCLK), - FEA_MAP(DPM_SOCCLK), - FEA_MAP(DPM_MP0CLK), - FEA_MAP(DPM_LINK), - FEA_MAP(DPM_DCEFCLK), - FEA_MAP(MEM_VDDCI_SCALING), - FEA_MAP(MEM_MVDD_SCALING), - FEA_MAP(DS_GFXCLK), - FEA_MAP(DS_SOCCLK), - FEA_MAP(DS_LCLK), - FEA_MAP(DS_DCEFCLK), - FEA_MAP(DS_UCLK), - FEA_MAP(GFX_ULV), - FEA_MAP(FW_DSTATE), - FEA_MAP(GFXOFF), - FEA_MAP(BACO), - FEA_MAP(MM_DPM_PG), - FEA_MAP(RSMU_SMN_CG), - FEA_MAP(PPT), - FEA_MAP(TDC), - FEA_MAP(APCC_PLUS), - FEA_MAP(GTHR), - FEA_MAP(ACDC), - FEA_MAP(VR0HOT), - FEA_MAP(VR1HOT), - FEA_MAP(FW_CTF), - FEA_MAP(FAN_CONTROL), - FEA_MAP(THERMAL), - FEA_MAP(GFX_DCS), - FEA_MAP(RM), - FEA_MAP(LED_DISPLAY), - FEA_MAP(GFX_SS), - FEA_MAP(OUT_OF_BAND_MONITOR), - FEA_MAP(TEMP_DEPENDENT_VMIN), - FEA_MAP(MMHUB_PG), - FEA_MAP(ATHUB_PG), - FEA_MAP(APCC_DFLL), -}; - -static struct cmn2asic_mapping sienna_cichlid_table_map[SMU_TABLE_COUNT] = { - TAB_MAP(PPTABLE), - TAB_MAP(WATERMARKS), - TAB_MAP(AVFS_PSM_DEBUG), - TAB_MAP(AVFS_FUSE_OVERRIDE), - TAB_MAP(PMSTATUSLOG), - TAB_MAP(SMU_METRICS), - TAB_MAP(DRIVER_SMU_CONFIG), - TAB_MAP(ACTIVITY_MONITOR_COEFF), - TAB_MAP(OVERDRIVE), - TAB_MAP(I2C_COMMANDS), - TAB_MAP(PACE), -}; - -static struct cmn2asic_mapping sienna_cichlid_pwr_src_map[SMU_POWER_SOURCE_COUNT] = { - PWR_MAP(AC), - PWR_MAP(DC), -}; - -static struct cmn2asic_mapping sienna_cichlid_workload_map[PP_SMC_POWER_PROFILE_COUNT] = { - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT, WORKLOAD_PPLIB_DEFAULT_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_FULLSCREEN3D, WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_POWERSAVING, WORKLOAD_PPLIB_POWER_SAVING_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VIDEO, WORKLOAD_PPLIB_VIDEO_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_VR, WORKLOAD_PPLIB_VR_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_COMPUTE, WORKLOAD_PPLIB_CUSTOM_BIT), - WORKLOAD_MAP(PP_SMC_POWER_PROFILE_CUSTOM, WORKLOAD_PPLIB_CUSTOM_BIT), -}; - -static int -sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, - uint32_t *feature_mask, uint32_t num) -{ - struct amdgpu_device *adev = smu->adev; - - if (num > 2) - return -EINVAL; - - memset(feature_mask, 0, sizeof(uint32_t) * num); - - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) - | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) - | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) - | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) - | FEATURE_MASK(FEATURE_DS_FCLK_BIT) - | FEATURE_MASK(FEATURE_DS_UCLK_BIT) - | FEATURE_MASK(FEATURE_FW_DSTATE_BIT) - | FEATURE_MASK(FEATURE_DF_CSTATE_BIT) - | FEATURE_MASK(FEATURE_RSMU_SMN_CG_BIT) - | FEATURE_MASK(FEATURE_GFX_SS_BIT) - | FEATURE_MASK(FEATURE_VR0HOT_BIT) - | FEATURE_MASK(FEATURE_PPT_BIT) - | FEATURE_MASK(FEATURE_TDC_BIT) - | FEATURE_MASK(FEATURE_BACO_BIT) - | FEATURE_MASK(FEATURE_APCC_DFLL_BIT) - | FEATURE_MASK(FEATURE_FW_CTF_BIT) - | FEATURE_MASK(FEATURE_FAN_CONTROL_BIT) - | FEATURE_MASK(FEATURE_THERMAL_BIT) - | FEATURE_MASK(FEATURE_OUT_OF_BAND_MONITOR_BIT); - - if (adev->pm.pp_feature & PP_SCLK_DPM_MASK) { - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFXCLK_BIT); - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_GFX_GPO_BIT); - } - - if (adev->pm.pp_feature & PP_MCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_UCLK_BIT) - | FEATURE_MASK(FEATURE_MEM_VDDCI_SCALING_BIT) - | FEATURE_MASK(FEATURE_MEM_MVDD_SCALING_BIT); - - if (adev->pm.pp_feature & PP_PCIE_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_LINK_BIT); - - if (adev->pm.pp_feature & PP_DCEFCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT); - - if (adev->pm.pp_feature & PP_SOCCLK_DPM_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT); - - if (adev->pm.pp_feature & PP_ULV_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFX_ULV_BIT); - - if (adev->pm.pp_feature & PP_SCLK_DEEP_SLEEP_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DS_GFXCLK_BIT); - - if (adev->pm.pp_feature & PP_GFXOFF_MASK) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_GFXOFF_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_ATHUB) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_ATHUB_PG_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_MMHUB) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MMHUB_PG_BIT); - - if (smu->adev->pg_flags & AMD_PG_SUPPORT_VCN || - smu->adev->pg_flags & AMD_PG_SUPPORT_JPEG) - *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_MM_DPM_PG_BIT); - - return 0; -} - -static int sienna_cichlid_check_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_7_powerplay_table *powerplay_table = - table_context->power_play_table; - struct smu_baco_context *smu_baco = &smu->smu_baco; - - mutex_lock(&smu_baco->mutex); - if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO || - powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) - smu_baco->platform_support = true; - mutex_unlock(&smu_baco->mutex); - - table_context->thermal_controller_type = - powerplay_table->thermal_controller_type; - - return 0; -} - -static int sienna_cichlid_append_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *smc_pptable = table_context->driver_pptable; - struct atom_smc_dpm_info_v4_9 *smc_dpm_table; - int index, ret; - - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - smc_dpm_info); - - ret = amdgpu_atombios_get_data_table(smu->adev, index, NULL, NULL, NULL, - (uint8_t **)&smc_dpm_table); - if (ret) - return ret; - - memcpy(smc_pptable->I2cControllers, smc_dpm_table->I2cControllers, - sizeof(*smc_dpm_table) - sizeof(smc_dpm_table->table_header)); - - return 0; -} - -static int sienna_cichlid_store_powerplay_table(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_7_powerplay_table *powerplay_table = - table_context->power_play_table; - - memcpy(table_context->driver_pptable, &powerplay_table->smc_pptable, - sizeof(PPTable_t)); - - return 0; -} - -static int sienna_cichlid_setup_pptable(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_v11_0_setup_pptable(smu); - if (ret) - return ret; - - ret = sienna_cichlid_store_powerplay_table(smu); - if (ret) - return ret; - - ret = sienna_cichlid_append_powerplay_table(smu); - if (ret) - return ret; - - ret = sienna_cichlid_check_powerplay_table(smu); - if (ret) - return ret; - - return ret; -} - -static int sienna_cichlid_tables_init(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - - SMU_TABLE_INIT(tables, SMU_TABLE_PPTABLE, sizeof(PPTable_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_WATERMARKS, sizeof(Watermarks_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t), - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE, - PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM); - SMU_TABLE_INIT(tables, SMU_TABLE_ACTIVITY_MONITOR_COEFF, - sizeof(DpmActivityMonitorCoeffInt_t), PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM); - - smu_table->metrics_table = kzalloc(sizeof(SmuMetrics_t), GFP_KERNEL); - if (!smu_table->metrics_table) - goto err0_out; - smu_table->metrics_time = 0; - - smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_0); - smu_table->gpu_metrics_table = kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL); - if (!smu_table->gpu_metrics_table) - goto err1_out; - - smu_table->watermarks_table = kzalloc(sizeof(Watermarks_t), GFP_KERNEL); - if (!smu_table->watermarks_table) - goto err2_out; - - return 0; - -err2_out: - kfree(smu_table->gpu_metrics_table); -err1_out: - kfree(smu_table->metrics_table); -err0_out: - return -ENOMEM; -} - -static int sienna_cichlid_get_smu_metrics_data(struct smu_context *smu, - MetricsMember_t member, - uint32_t *value) -{ - struct smu_table_context *smu_table= &smu->smu_table; - SmuMetrics_t *metrics = (SmuMetrics_t *)smu_table->metrics_table; - int ret = 0; - - mutex_lock(&smu->metrics_lock); - - ret = smu_cmn_get_metrics_table_locked(smu, - NULL, - false); - if (ret) { - mutex_unlock(&smu->metrics_lock); - return ret; - } - - switch (member) { - case METRICS_CURR_GFXCLK: - *value = metrics->CurrClock[PPCLK_GFXCLK]; - break; - case METRICS_CURR_SOCCLK: - *value = metrics->CurrClock[PPCLK_SOCCLK]; - break; - case METRICS_CURR_UCLK: - *value = metrics->CurrClock[PPCLK_UCLK]; - break; - case METRICS_CURR_VCLK: - *value = metrics->CurrClock[PPCLK_VCLK_0]; - break; - case METRICS_CURR_VCLK1: - *value = metrics->CurrClock[PPCLK_VCLK_1]; - break; - case METRICS_CURR_DCLK: - *value = metrics->CurrClock[PPCLK_DCLK_0]; - break; - case METRICS_CURR_DCLK1: - *value = metrics->CurrClock[PPCLK_DCLK_1]; - break; - case METRICS_CURR_DCEFCLK: - *value = metrics->CurrClock[PPCLK_DCEFCLK]; - break; - case METRICS_AVERAGE_GFXCLK: - if (metrics->AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) - *value = metrics->AverageGfxclkFrequencyPostDs; - else - *value = metrics->AverageGfxclkFrequencyPreDs; - break; - case METRICS_AVERAGE_FCLK: - *value = metrics->AverageFclkFrequencyPostDs; - break; - case METRICS_AVERAGE_UCLK: - *value = metrics->AverageUclkFrequencyPostDs; - break; - case METRICS_AVERAGE_GFXACTIVITY: - *value = metrics->AverageGfxActivity; - break; - case METRICS_AVERAGE_MEMACTIVITY: - *value = metrics->AverageUclkActivity; - break; - case METRICS_AVERAGE_SOCKETPOWER: - *value = metrics->AverageSocketPower << 8; - break; - case METRICS_TEMPERATURE_EDGE: - *value = metrics->TemperatureEdge * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_HOTSPOT: - *value = metrics->TemperatureHotspot * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_MEM: - *value = metrics->TemperatureMem * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRGFX: - *value = metrics->TemperatureVrGfx * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_TEMPERATURE_VRSOC: - *value = metrics->TemperatureVrSoc * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - break; - case METRICS_THROTTLER_STATUS: - *value = metrics->ThrottlerStatus; - break; - case METRICS_CURR_FANSPEED: - *value = metrics->CurrFanSpeed; - break; - default: - *value = UINT_MAX; - break; - } - - mutex_unlock(&smu->metrics_lock); - - return ret; - -} - -static int sienna_cichlid_allocate_dpm_context(struct smu_context *smu) -{ - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - - smu_dpm->dpm_context = kzalloc(sizeof(struct smu_11_0_dpm_context), - GFP_KERNEL); - if (!smu_dpm->dpm_context) - return -ENOMEM; - - smu_dpm->dpm_context_size = sizeof(struct smu_11_0_dpm_context); - - return 0; -} - -static int sienna_cichlid_init_smc_tables(struct smu_context *smu) -{ - int ret = 0; - - ret = sienna_cichlid_tables_init(smu); - if (ret) - return ret; - - ret = sienna_cichlid_allocate_dpm_context(smu); - if (ret) - return ret; - - return smu_v11_0_init_smc_tables(smu); -} - -static int sienna_cichlid_set_default_dpm_table(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - PPTable_t *driver_ppt = smu->smu_table.driver_pptable; - struct smu_11_0_dpm_table *dpm_table; - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - /* socclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.soc_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_SOCCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.socclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* gfxclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.gfx_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_GFXCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_GFXCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.gfxclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* uclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.uclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_UCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.uclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* fclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.fclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_FCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_FCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.fclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* vclk0 dpm table setup */ - dpm_table = &dpm_context->dpm_tables.vclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_VCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_VCLK_0].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.vclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* vclk1 dpm table setup */ - if (adev->vcn.num_vcn_inst > 1) { - dpm_table = &dpm_context->dpm_tables.vclk1_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_VCLK1, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_VCLK_1].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = - smu->smu_table.boot_values.vclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - } - - /* dclk0 dpm table setup */ - dpm_table = &dpm_context->dpm_tables.dclk_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DCLK_0].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* dclk1 dpm table setup */ - if (adev->vcn.num_vcn_inst > 1) { - dpm_table = &dpm_context->dpm_tables.dclk1_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DCLK1, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DCLK_1].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = - smu->smu_table.boot_values.dclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - } - - /* dcefclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.dcef_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DCEFCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DCEFCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* pixelclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.pixel_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_PIXCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_PIXCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* displayclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.display_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_DISPCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_DISPCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - /* phyclk dpm table setup */ - dpm_table = &dpm_context->dpm_tables.phy_table; - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_set_single_dpm_table(smu, - SMU_PHYCLK, - dpm_table); - if (ret) - return ret; - dpm_table->is_fine_grained = - !driver_ppt->DpmDescriptor[PPCLK_PHYCLK].SnapToDiscrete; - } else { - dpm_table->count = 1; - dpm_table->dpm_levels[0].value = smu->smu_table.boot_values.dcefclk / 100; - dpm_table->dpm_levels[0].enabled = true; - dpm_table->min = dpm_table->dpm_levels[0].value; - dpm_table->max = dpm_table->dpm_levels[0].value; - } - - return 0; -} - -static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enable) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - if (enable) { - /* vcn dpm on is a prerequisite for vcn power gate messages */ - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); - if (ret) - return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, - 0x10000, NULL); - if (ret) - return ret; - } - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); - if (ret) - return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, - 0x10000, NULL); - if (ret) - return ret; - } - } - } - - return ret; -} - -static int sienna_cichlid_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) -{ - int ret = 0; - - if (enable) { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpJpeg, 0, NULL); - if (ret) - return ret; - } - } else { - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_MM_DPM_PG_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownJpeg, 0, NULL); - if (ret) - return ret; - } - } - - return ret; -} - -static int sienna_cichlid_get_current_clk_freq_by_table(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - MetricsMember_t member_type; - int clk_id = 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - switch (clk_id) { - case PPCLK_GFXCLK: - member_type = METRICS_CURR_GFXCLK; - break; - case PPCLK_UCLK: - member_type = METRICS_CURR_UCLK; - break; - case PPCLK_SOCCLK: - member_type = METRICS_CURR_SOCCLK; - break; - case PPCLK_FCLK: - member_type = METRICS_CURR_FCLK; - break; - case PPCLK_VCLK_0: - member_type = METRICS_CURR_VCLK; - break; - case PPCLK_VCLK_1: - member_type = METRICS_CURR_VCLK1; - break; - case PPCLK_DCLK_0: - member_type = METRICS_CURR_DCLK; - break; - case PPCLK_DCLK_1: - member_type = METRICS_CURR_DCLK1; - break; - case PPCLK_DCEFCLK: - member_type = METRICS_CURR_DCEFCLK; - break; - default: - return -EINVAL; - } - - return sienna_cichlid_get_smu_metrics_data(smu, - member_type, - value); - -} - -static bool sienna_cichlid_is_support_fine_grained_dpm(struct smu_context *smu, enum smu_clk_type clk_type) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - DpmDescriptor_t *dpm_desc = NULL; - uint32_t clk_index = 0; - - clk_index = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - dpm_desc = &pptable->DpmDescriptor[clk_index]; - - /* 0 - Fine grained DPM, 1 - Discrete DPM */ - return dpm_desc->SnapToDiscrete == 0 ? true : false; -} - -static int sienna_cichlid_print_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, char *buf) -{ - struct amdgpu_device *adev = smu->adev; - struct smu_table_context *table_context = &smu->smu_table; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - struct smu_11_0_dpm_context *dpm_context = smu_dpm->dpm_context; - PPTable_t *pptable = (PPTable_t *)table_context->driver_pptable; - int i, size = 0, ret = 0; - uint32_t cur_value = 0, value = 0, count = 0; - uint32_t freq_values[3] = {0}; - uint32_t mark_index = 0; - uint32_t gen_speed, lane_width; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - case SMU_SOCCLK: - case SMU_MCLK: - case SMU_UCLK: - case SMU_FCLK: - case SMU_DCEFCLK: - ret = sienna_cichlid_get_current_clk_freq_by_table(smu, clk_type, &cur_value); - if (ret) - goto print_clk_out; - - /* no need to disable gfxoff when retrieving the current gfxclk */ - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, false); - - ret = smu_v11_0_get_dpm_level_count(smu, clk_type, &count); - if (ret) - goto print_clk_out; - - if (!sienna_cichlid_is_support_fine_grained_dpm(smu, clk_type)) { - for (i = 0; i < count; i++) { - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, i, &value); - if (ret) - goto print_clk_out; - - size += sprintf(buf + size, "%d: %uMhz %s\n", i, value, - cur_value == value ? "*" : ""); - } - } else { - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, 0, &freq_values[0]); - if (ret) - goto print_clk_out; - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, count - 1, &freq_values[2]); - if (ret) - goto print_clk_out; - - freq_values[1] = cur_value; - mark_index = cur_value == freq_values[0] ? 0 : - cur_value == freq_values[2] ? 2 : 1; - if (mark_index != 1) - freq_values[1] = (freq_values[0] + freq_values[2]) / 2; - - for (i = 0; i < 3; i++) { - size += sprintf(buf + size, "%d: %uMhz %s\n", i, freq_values[i], - i == mark_index ? "*" : ""); - } - - } - break; - case SMU_PCIE: - gen_speed = smu_v11_0_get_current_pcie_link_speed(smu); - lane_width = smu_v11_0_get_current_pcie_link_width(smu); - for (i = 0; i < NUM_LINK_LEVELS; i++) - size += sprintf(buf + size, "%d: %s %s %dMhz %s\n", i, - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 0) ? "2.5GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 1) ? "5.0GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 2) ? "8.0GT/s," : - (dpm_context->dpm_tables.pcie_table.pcie_gen[i] == 3) ? "16.0GT/s," : "", - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 1) ? "x1" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 2) ? "x2" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 3) ? "x4" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 4) ? "x8" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 5) ? "x12" : - (dpm_context->dpm_tables.pcie_table.pcie_lane[i] == 6) ? "x16" : "", - pptable->LclkFreq[i], - (gen_speed == dpm_context->dpm_tables.pcie_table.pcie_gen[i]) && - (lane_width == dpm_context->dpm_tables.pcie_table.pcie_lane[i]) ? - "*" : ""); - break; - default: - break; - } - -print_clk_out: - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, true); - - return size; -} - -static int sienna_cichlid_force_clk_levels(struct smu_context *smu, - enum smu_clk_type clk_type, uint32_t mask) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0, size = 0; - uint32_t soft_min_level = 0, soft_max_level = 0, min_freq = 0, max_freq = 0; - - soft_min_level = mask ? (ffs(mask) - 1) : 0; - soft_max_level = mask ? (fls(mask) - 1) : 0; - - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, false); - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - case SMU_SOCCLK: - case SMU_MCLK: - case SMU_UCLK: - case SMU_DCEFCLK: - case SMU_FCLK: - /* There is only 2 levels for fine grained DPM */ - if (sienna_cichlid_is_support_fine_grained_dpm(smu, clk_type)) { - soft_max_level = (soft_max_level >= 1 ? 1 : 0); - soft_min_level = (soft_min_level >= 1 ? 1 : 0); - } - - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_min_level, &min_freq); - if (ret) - goto forec_level_out; - - ret = smu_v11_0_get_dpm_freq_by_index(smu, clk_type, soft_max_level, &max_freq); - if (ret) - goto forec_level_out; - - ret = smu_v11_0_set_soft_freq_limited_range(smu, clk_type, min_freq, max_freq); - if (ret) - goto forec_level_out; - break; - default: - break; - } - -forec_level_out: - if ((clk_type == SMU_GFXCLK) || (clk_type == SMU_SCLK)) - amdgpu_gfx_off_ctrl(adev, true); - - return size; -} - -static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu) -{ - struct smu_11_0_dpm_context *dpm_context = - smu->smu_dpm.dpm_context; - struct smu_11_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_11_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_11_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_umd_pstate_table *pstate_table = - &smu->pstate_table; - - pstate_table->gfxclk_pstate.min = gfx_table->min; - pstate_table->gfxclk_pstate.peak = gfx_table->max; - - pstate_table->uclk_pstate.min = mem_table->min; - pstate_table->uclk_pstate.peak = mem_table->max; - - pstate_table->socclk_pstate.min = soc_table->min; - pstate_table->socclk_pstate.peak = soc_table->max; - - return 0; -} - -static int sienna_cichlid_pre_display_config_changed(struct smu_context *smu) -{ - int ret = 0; - uint32_t max_freq = 0; - - /* Sienna_Cichlid do not support to change display num currently */ - return 0; -#if 0 - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, 0, NULL); - if (ret) - return ret; -#endif - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_get_dpm_ultimate_freq(smu, SMU_UCLK, NULL, &max_freq); - if (ret) - return ret; - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, 0, max_freq); - if (ret) - return ret; - } - - return ret; -} - -static int sienna_cichlid_display_config_changed(struct smu_context *smu) -{ - int ret = 0; - - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) && - smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { -#if 0 - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, - smu->display_config->num_display, - NULL); -#endif - if (ret) - return ret; - } - - return ret; -} - -static int sienna_cichlid_get_gpu_power(struct smu_context *smu, uint32_t *value) -{ - if (!value) - return -EINVAL; - - return sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_SOCKETPOWER, - value); -} - -static int sienna_cichlid_get_current_activity_percent(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_GFXACTIVITY, - value); - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_AVERAGE_MEMACTIVITY, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving clock activity\n"); - return -EINVAL; - } - - return ret; -} - -static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) -{ - int ret = 0; - uint32_t feature_mask[2]; - unsigned long feature_enabled; - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); - return !!(feature_enabled & SMC_DPM_FEATURE); -} - -static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, - uint32_t *speed) -{ - if (!speed) - return -EINVAL; - - return sienna_cichlid_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); -} - -static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = sienna_cichlid_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - -static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *buf) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - uint32_t i, size = 0; - int16_t workload_type = 0; - static const char *profile_name[] = { - "BOOTUP_DEFAULT", - "3D_FULL_SCREEN", - "POWER_SAVING", - "VIDEO", - "VR", - "COMPUTE", - "CUSTOM"}; - static const char *title[] = { - "PROFILE_INDEX(NAME)", - "CLOCK_TYPE(NAME)", - "FPS", - "MinFreqType", - "MinActiveFreqType", - "MinActiveFreq", - "BoosterFreqType", - "BoosterFreq", - "PD_Data_limit_c", - "PD_Data_error_coeff", - "PD_Data_error_rate_coeff"}; - int result = 0; - - if (!buf) - return -EINVAL; - - size += sprintf(buf + size, "%16s %s %s %s %s %s %s %s %s %s %s\n", - title[0], title[1], title[2], title[3], title[4], title[5], - title[6], title[7], title[8], title[9], title[10]); - - for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) { - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - i); - if (workload_type < 0) - return -EINVAL; - - result = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, workload_type, - (void *)(&activity_monitor), false); - if (result) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return result; - } - - size += sprintf(buf + size, "%2d %14s%s:\n", - i, profile_name[i], (i == smu->power_profile_mode) ? "*" : " "); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 0, - "GFXCLK", - activity_monitor.Gfx_FPS, - activity_monitor.Gfx_MinFreqStep, - activity_monitor.Gfx_MinActiveFreqType, - activity_monitor.Gfx_MinActiveFreq, - activity_monitor.Gfx_BoosterFreqType, - activity_monitor.Gfx_BoosterFreq, - activity_monitor.Gfx_PD_Data_limit_c, - activity_monitor.Gfx_PD_Data_error_coeff, - activity_monitor.Gfx_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 1, - "SOCCLK", - activity_monitor.Fclk_FPS, - activity_monitor.Fclk_MinFreqStep, - activity_monitor.Fclk_MinActiveFreqType, - activity_monitor.Fclk_MinActiveFreq, - activity_monitor.Fclk_BoosterFreqType, - activity_monitor.Fclk_BoosterFreq, - activity_monitor.Fclk_PD_Data_limit_c, - activity_monitor.Fclk_PD_Data_error_coeff, - activity_monitor.Fclk_PD_Data_error_rate_coeff); - - size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n", - " ", - 2, - "MEMLK", - activity_monitor.Mem_FPS, - activity_monitor.Mem_MinFreqStep, - activity_monitor.Mem_MinActiveFreqType, - activity_monitor.Mem_MinActiveFreq, - activity_monitor.Mem_BoosterFreqType, - activity_monitor.Mem_BoosterFreq, - activity_monitor.Mem_PD_Data_limit_c, - activity_monitor.Mem_PD_Data_error_coeff, - activity_monitor.Mem_PD_Data_error_rate_coeff); - } - - return size; -} - -static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size) -{ - DpmActivityMonitorCoeffInt_t activity_monitor; - int workload_type, ret = 0; - - smu->power_profile_mode = input[size]; - - if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) { - dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode); - return -EINVAL; - } - - if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) { - - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), false); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__); - return ret; - } - - switch (input[0]) { - case 0: /* Gfxclk */ - activity_monitor.Gfx_FPS = input[1]; - activity_monitor.Gfx_MinFreqStep = input[2]; - activity_monitor.Gfx_MinActiveFreqType = input[3]; - activity_monitor.Gfx_MinActiveFreq = input[4]; - activity_monitor.Gfx_BoosterFreqType = input[5]; - activity_monitor.Gfx_BoosterFreq = input[6]; - activity_monitor.Gfx_PD_Data_limit_c = input[7]; - activity_monitor.Gfx_PD_Data_error_coeff = input[8]; - activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9]; - break; - case 1: /* Socclk */ - activity_monitor.Fclk_FPS = input[1]; - activity_monitor.Fclk_MinFreqStep = input[2]; - activity_monitor.Fclk_MinActiveFreqType = input[3]; - activity_monitor.Fclk_MinActiveFreq = input[4]; - activity_monitor.Fclk_BoosterFreqType = input[5]; - activity_monitor.Fclk_BoosterFreq = input[6]; - activity_monitor.Fclk_PD_Data_limit_c = input[7]; - activity_monitor.Fclk_PD_Data_error_coeff = input[8]; - activity_monitor.Fclk_PD_Data_error_rate_coeff = input[9]; - break; - case 2: /* Memlk */ - activity_monitor.Mem_FPS = input[1]; - activity_monitor.Mem_MinFreqStep = input[2]; - activity_monitor.Mem_MinActiveFreqType = input[3]; - activity_monitor.Mem_MinActiveFreq = input[4]; - activity_monitor.Mem_BoosterFreqType = input[5]; - activity_monitor.Mem_BoosterFreq = input[6]; - activity_monitor.Mem_PD_Data_limit_c = input[7]; - activity_monitor.Mem_PD_Data_error_coeff = input[8]; - activity_monitor.Mem_PD_Data_error_rate_coeff = input[9]; - break; - } - - ret = smu_cmn_update_table(smu, - SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT, - (void *)(&activity_monitor), true); - if (ret) { - dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__); - return ret; - } - } - - /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */ - workload_type = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_WORKLOAD, - smu->power_profile_mode); - if (workload_type < 0) - return -EINVAL; - smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask, - 1 << workload_type, NULL); - - return ret; -} - -static int sienna_cichlid_notify_smc_display_config(struct smu_context *smu) -{ - struct smu_clocks min_clocks = {0}; - struct pp_display_clock_request clock_req; - int ret = 0; - - min_clocks.dcef_clock = smu->display_config->min_dcef_set_clk; - min_clocks.dcef_clock_in_sr = smu->display_config->min_dcef_deep_sleep_set_clk; - min_clocks.memory_clock = smu->display_config->min_mem_set_clock; - - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - clock_req.clock_type = amd_pp_dcef_clock; - clock_req.clock_freq_in_khz = min_clocks.dcef_clock * 10; - - ret = smu_v11_0_display_clock_voltage_request(smu, &clock_req); - if (!ret) { - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_DCEFCLK_BIT)) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetMinDeepSleepDcefclk, - min_clocks.dcef_clock_in_sr/100, - NULL); - if (ret) { - dev_err(smu->adev->dev, "Attempt to set divider for DCEFCLK Failed!"); - return ret; - } - } - } else { - dev_info(smu->adev->dev, "Attempt to set Hard Min for DCEFCLK Failed!"); - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_clocks.memory_clock/100, 0); - if (ret) { - dev_err(smu->adev->dev, "[%s] Set hard min uclk failed!", __func__); - return ret; - } - } - - return 0; -} - -static int sienna_cichlid_set_watermarks_table(struct smu_context *smu, - struct dm_pp_wm_sets_with_clock_ranges_soc15 - *clock_ranges) -{ - Watermarks_t *table = smu->smu_table.watermarks_table; - int ret = 0; - int i; - - if (clock_ranges) { - if (clock_ranges->num_wm_dmif_sets > 4 || - clock_ranges->num_wm_mcif_sets > 4) - return -EINVAL; - - for (i = 0; i < clock_ranges->num_wm_dmif_sets; i++) { - table->WatermarkRow[1][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[1][i].WmSetting = (uint8_t) - clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id; - } - - for (i = 0; i < clock_ranges->num_wm_mcif_sets; i++) { - table->WatermarkRow[0][i].MinClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxClock = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MinUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].MaxUclk = - cpu_to_le16((uint16_t) - (clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / - 1000)); - table->WatermarkRow[0][i].WmSetting = (uint8_t) - clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id; - } - - smu->watermarks_bitmap |= WATERMARKS_EXIST; - } - - if ((smu->watermarks_bitmap & WATERMARKS_EXIST) && - !(smu->watermarks_bitmap & WATERMARKS_LOADED)) { - ret = smu_cmn_write_watermarks_table(smu); - if (ret) { - dev_err(smu->adev->dev, "Failed to update WMTABLE!"); - return ret; - } - smu->watermarks_bitmap |= WATERMARKS_LOADED; - } - - return 0; -} - -static int sienna_cichlid_thermal_get_temperature(struct smu_context *smu, - enum amd_pp_sensors sensor, - uint32_t *value) -{ - int ret = 0; - - if (!value) - return -EINVAL; - - switch (sensor) { - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_HOTSPOT, - value); - break; - case AMDGPU_PP_SENSOR_EDGE_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_EDGE, - value); - break; - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = sienna_cichlid_get_smu_metrics_data(smu, - METRICS_TEMPERATURE_MEM, - value); - break; - default: - dev_err(smu->adev->dev, "Invalid sensor for retrieving temp\n"); - return -EINVAL; - } - - return ret; -} - -static int sienna_cichlid_read_sensor(struct smu_context *smu, - enum amd_pp_sensors sensor, - void *data, uint32_t *size) -{ - int ret = 0; - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *pptable = table_context->driver_pptable; - - if(!data || !size) - return -EINVAL; - - mutex_lock(&smu->sensor_lock); - switch (sensor) { - case AMDGPU_PP_SENSOR_MAX_FAN_RPM: - *(uint32_t *)data = pptable->FanMaximumRpm; - *size = 4; - break; - case AMDGPU_PP_SENSOR_MEM_LOAD: - case AMDGPU_PP_SENSOR_GPU_LOAD: - ret = sienna_cichlid_get_current_activity_percent(smu, sensor, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GPU_POWER: - ret = sienna_cichlid_get_gpu_power(smu, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_HOTSPOT_TEMP: - case AMDGPU_PP_SENSOR_EDGE_TEMP: - case AMDGPU_PP_SENSOR_MEM_TEMP: - ret = sienna_cichlid_thermal_get_temperature(smu, sensor, (uint32_t *)data); - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_MCLK: - ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_GFX_SCLK: - ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data); - *(uint32_t *)data *= 100; - *size = 4; - break; - case AMDGPU_PP_SENSOR_VDDGFX: - ret = smu_v11_0_get_gfx_vdd(smu, (uint32_t *)data); - *size = 4; - break; - default: - ret = -EOPNOTSUPP; - break; - } - mutex_unlock(&smu->sensor_lock); - - return ret; -} - -static int sienna_cichlid_get_uclk_dpm_states(struct smu_context *smu, uint32_t *clocks_in_khz, uint32_t *num_states) -{ - uint32_t num_discrete_levels = 0; - uint16_t *dpm_levels = NULL; - uint16_t i = 0; - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *driver_ppt = NULL; - - if (!clocks_in_khz || !num_states || !table_context->driver_pptable) - return -EINVAL; - - driver_ppt = table_context->driver_pptable; - num_discrete_levels = driver_ppt->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels; - dpm_levels = driver_ppt->FreqTableUclk; - - if (num_discrete_levels == 0 || dpm_levels == NULL) - return -EINVAL; - - *num_states = num_discrete_levels; - for (i = 0; i < num_discrete_levels; i++) { - /* convert to khz */ - *clocks_in_khz = (*dpm_levels) * 1000; - clocks_in_khz++; - dpm_levels++; - } - - return 0; -} - -static int sienna_cichlid_get_thermal_temperature_range(struct smu_context *smu, - struct smu_temperature_range *range) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_7_powerplay_table *powerplay_table = - table_context->power_play_table; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - if (!range) - return -EINVAL; - - memcpy(range, &smu11_thermal_policy[0], sizeof(struct smu_temperature_range)); - - range->max = pptable->TemperatureLimit[TEMP_EDGE] * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->edge_emergency_max = (pptable->TemperatureLimit[TEMP_EDGE] + CTF_OFFSET_EDGE) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_crit_max = pptable->TemperatureLimit[TEMP_HOTSPOT] * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->hotspot_emergency_max = (pptable->TemperatureLimit[TEMP_HOTSPOT] + CTF_OFFSET_HOTSPOT) * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_crit_max = pptable->TemperatureLimit[TEMP_MEM] * - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->mem_emergency_max = (pptable->TemperatureLimit[TEMP_MEM] + CTF_OFFSET_MEM)* - SMU_TEMPERATURE_UNITS_PER_CENTIGRADES; - range->software_shutdown_temp = powerplay_table->software_shutdown_temp; - - return 0; -} - -static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context *smu, - bool disable_memory_clock_switch) -{ - int ret = 0; - struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = - (struct smu_11_0_max_sustainable_clocks *) - smu->smu_table.max_sustainable_clocks; - uint32_t min_memory_clock = smu->hard_min_uclk_req_from_dal; - uint32_t max_memory_clock = max_sustainable_clocks->uclock; - - if(smu->disable_uclk_switch == disable_memory_clock_switch) - return 0; - - if(disable_memory_clock_switch) - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, max_memory_clock, 0); - else - ret = smu_v11_0_set_hard_freq_limited_range(smu, SMU_UCLK, min_memory_clock, 0); - - if(!ret) - smu->disable_uclk_switch = disable_memory_clock_switch; - - return ret; -} - -static int sienna_cichlid_get_power_limit(struct smu_context *smu) -{ - struct smu_11_0_7_powerplay_table *powerplay_table = - (struct smu_11_0_7_powerplay_table *)smu->smu_table.power_play_table; - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t power_limit, od_percent; - - if (smu_v11_0_get_current_power_limit(smu, &power_limit)) { - /* the last hope to figure out the ppt limit */ - if (!pptable) { - dev_err(smu->adev->dev, "Cannot get PPT limit due to pptable missing!"); - return -EINVAL; - } - power_limit = - pptable->SocketPowerLimitAc[PPT_THROTTLER_PPT0]; - } - smu->current_power_limit = power_limit; - - if (smu->od_enabled) { - od_percent = le32_to_cpu(powerplay_table->overdrive_table.max[SMU_11_0_7_ODSETTING_POWERPERCENTAGE]); - - dev_dbg(smu->adev->dev, "ODSETTING_POWERPERCENTAGE: %d (default: %d)\n", od_percent, power_limit); - - power_limit *= (100 + od_percent); - power_limit /= 100; - } - smu->max_power_limit = power_limit; - - return 0; -} - -static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu, - uint32_t pcie_gen_cap, - uint32_t pcie_width_cap) -{ - struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context; - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t smu_pcie_arg; - int ret, i; - - /* lclk dpm table setup */ - for (i = 0; i < MAX_PCIE_CONF; i++) { - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pptable->PcieGenSpeed[i]; - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pptable->PcieLaneCount[i]; - } - - for (i = 0; i < NUM_LINK_LEVELS; i++) { - smu_pcie_arg = (i << 16) | - ((pptable->PcieGenSpeed[i] <= pcie_gen_cap) ? - (pptable->PcieGenSpeed[i] << 8) : - (pcie_gen_cap << 8)) | - ((pptable->PcieLaneCount[i] <= pcie_width_cap) ? - pptable->PcieLaneCount[i] : - pcie_width_cap); - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_OverridePcieParameters, - smu_pcie_arg, - NULL); - - if (ret) - return ret; - - if (pptable->PcieGenSpeed[i] > pcie_gen_cap) - dpm_context->dpm_tables.pcie_table.pcie_gen[i] = pcie_gen_cap; - if (pptable->PcieLaneCount[i] > pcie_width_cap) - dpm_context->dpm_tables.pcie_table.pcie_lane[i] = pcie_width_cap; - } - - return 0; -} - -static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max) -{ - struct amdgpu_device *adev = smu->adev; - int ret; - - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - ret = smu_v11_0_get_dpm_ultimate_freq(smu, clk_type, min, max); - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - - return ret; -} - -static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t val; - - if (amdgpu_sriov_vf(adev) || (!smu_v11_0_baco_is_support(smu))) - return false; - - val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0); - return (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true : false; -} - -static bool sienna_cichlid_is_mode1_reset_supported(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t val; - u32 smu_version; - - /** - * SRIOV env will not support SMU mode1 reset - * PM FW support mode1 reset from 58.26 - */ - smu_cmn_get_smc_version(smu, NULL, &smu_version); - if (amdgpu_sriov_vf(adev) || (smu_version < 0x003a1a00)) - return false; - - /** - * mode1 reset relies on PSP, so we should check if - * PSP is alive. - */ - val = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81); - return val != 0x0; -} - -static void sienna_cichlid_dump_pptable(struct smu_context *smu) -{ - struct smu_table_context *table_context = &smu->smu_table; - PPTable_t *pptable = table_context->driver_pptable; - int i; - - dev_info(smu->adev->dev, "Dumped PPTable:\n"); - - dev_info(smu->adev->dev, "Version = 0x%08x\n", pptable->Version); - dev_info(smu->adev->dev, "FeaturesToRun[0] = 0x%08x\n", pptable->FeaturesToRun[0]); - dev_info(smu->adev->dev, "FeaturesToRun[1] = 0x%08x\n", pptable->FeaturesToRun[1]); - - for (i = 0; i < PPT_THROTTLER_COUNT; i++) { - dev_info(smu->adev->dev, "SocketPowerLimitAc[%d] = 0x%x\n", i, pptable->SocketPowerLimitAc[i]); - dev_info(smu->adev->dev, "SocketPowerLimitAcTau[%d] = 0x%x\n", i, pptable->SocketPowerLimitAcTau[i]); - dev_info(smu->adev->dev, "SocketPowerLimitDc[%d] = 0x%x\n", i, pptable->SocketPowerLimitDc[i]); - dev_info(smu->adev->dev, "SocketPowerLimitDcTau[%d] = 0x%x\n", i, pptable->SocketPowerLimitDcTau[i]); - } - - for (i = 0; i < TDC_THROTTLER_COUNT; i++) { - dev_info(smu->adev->dev, "TdcLimit[%d] = 0x%x\n", i, pptable->TdcLimit[i]); - dev_info(smu->adev->dev, "TdcLimitTau[%d] = 0x%x\n", i, pptable->TdcLimitTau[i]); - } - - for (i = 0; i < TEMP_COUNT; i++) { - dev_info(smu->adev->dev, "TemperatureLimit[%d] = 0x%x\n", i, pptable->TemperatureLimit[i]); - } - - dev_info(smu->adev->dev, "FitLimit = 0x%x\n", pptable->FitLimit); - dev_info(smu->adev->dev, "TotalPowerConfig = 0x%x\n", pptable->TotalPowerConfig); - dev_info(smu->adev->dev, "TotalPowerPadding[0] = 0x%x\n", pptable->TotalPowerPadding[0]); - dev_info(smu->adev->dev, "TotalPowerPadding[1] = 0x%x\n", pptable->TotalPowerPadding[1]); - dev_info(smu->adev->dev, "TotalPowerPadding[2] = 0x%x\n", pptable->TotalPowerPadding[2]); - - dev_info(smu->adev->dev, "ApccPlusResidencyLimit = 0x%x\n", pptable->ApccPlusResidencyLimit); - for (i = 0; i < NUM_SMNCLK_DPM_LEVELS; i++) { - dev_info(smu->adev->dev, "SmnclkDpmFreq[%d] = 0x%x\n", i, pptable->SmnclkDpmFreq[i]); - dev_info(smu->adev->dev, "SmnclkDpmVoltage[%d] = 0x%x\n", i, pptable->SmnclkDpmVoltage[i]); - } - dev_info(smu->adev->dev, "PaddingAPCC[0] = 0x%x\n", pptable->PaddingAPCC[0]); - dev_info(smu->adev->dev, "PaddingAPCC[1] = 0x%x\n", pptable->PaddingAPCC[1]); - dev_info(smu->adev->dev, "PaddingAPCC[2] = 0x%x\n", pptable->PaddingAPCC[2]); - dev_info(smu->adev->dev, "PaddingAPCC[3] = 0x%x\n", pptable->PaddingAPCC[3]); - - dev_info(smu->adev->dev, "ThrottlerControlMask = 0x%x\n", pptable->ThrottlerControlMask); - - dev_info(smu->adev->dev, "FwDStateMask = 0x%x\n", pptable->FwDStateMask); - - dev_info(smu->adev->dev, "UlvVoltageOffsetSoc = 0x%x\n", pptable->UlvVoltageOffsetSoc); - dev_info(smu->adev->dev, "UlvVoltageOffsetGfx = 0x%x\n", pptable->UlvVoltageOffsetGfx); - dev_info(smu->adev->dev, "MinVoltageUlvGfx = 0x%x\n", pptable->MinVoltageUlvGfx); - dev_info(smu->adev->dev, "MinVoltageUlvSoc = 0x%x\n", pptable->MinVoltageUlvSoc); - - dev_info(smu->adev->dev, "SocLIVmin = 0x%x\n", pptable->SocLIVmin); - dev_info(smu->adev->dev, "PaddingLIVmin = 0x%x\n", pptable->PaddingLIVmin); - - dev_info(smu->adev->dev, "GceaLinkMgrIdleThreshold = 0x%x\n", pptable->GceaLinkMgrIdleThreshold); - dev_info(smu->adev->dev, "paddingRlcUlvParams[0] = 0x%x\n", pptable->paddingRlcUlvParams[0]); - dev_info(smu->adev->dev, "paddingRlcUlvParams[1] = 0x%x\n", pptable->paddingRlcUlvParams[1]); - dev_info(smu->adev->dev, "paddingRlcUlvParams[2] = 0x%x\n", pptable->paddingRlcUlvParams[2]); - - dev_info(smu->adev->dev, "MinVoltageGfx = 0x%x\n", pptable->MinVoltageGfx); - dev_info(smu->adev->dev, "MinVoltageSoc = 0x%x\n", pptable->MinVoltageSoc); - dev_info(smu->adev->dev, "MaxVoltageGfx = 0x%x\n", pptable->MaxVoltageGfx); - dev_info(smu->adev->dev, "MaxVoltageSoc = 0x%x\n", pptable->MaxVoltageSoc); - - dev_info(smu->adev->dev, "LoadLineResistanceGfx = 0x%x\n", pptable->LoadLineResistanceGfx); - dev_info(smu->adev->dev, "LoadLineResistanceSoc = 0x%x\n", pptable->LoadLineResistanceSoc); - - dev_info(smu->adev->dev, "VDDGFX_TVmin = 0x%x\n", pptable->VDDGFX_TVmin); - dev_info(smu->adev->dev, "VDDSOC_TVmin = 0x%x\n", pptable->VDDSOC_TVmin); - dev_info(smu->adev->dev, "VDDGFX_Vmin_HiTemp = 0x%x\n", pptable->VDDGFX_Vmin_HiTemp); - dev_info(smu->adev->dev, "VDDGFX_Vmin_LoTemp = 0x%x\n", pptable->VDDGFX_Vmin_LoTemp); - dev_info(smu->adev->dev, "VDDSOC_Vmin_HiTemp = 0x%x\n", pptable->VDDSOC_Vmin_HiTemp); - dev_info(smu->adev->dev, "VDDSOC_Vmin_LoTemp = 0x%x\n", pptable->VDDSOC_Vmin_LoTemp); - dev_info(smu->adev->dev, "VDDGFX_TVminHystersis = 0x%x\n", pptable->VDDGFX_TVminHystersis); - dev_info(smu->adev->dev, "VDDSOC_TVminHystersis = 0x%x\n", pptable->VDDSOC_TVminHystersis); - - dev_info(smu->adev->dev, "[PPCLK_GFXCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_GFXCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_GFXCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_GFXCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_GFXCLK].Padding, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_GFXCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_GFXCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_GFXCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_SOCCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_SOCCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_SOCCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_SOCCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_SOCCLK].Padding, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_SOCCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_SOCCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_SOCCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_UCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_UCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_UCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_UCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_UCLK].Padding, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_UCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_UCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_UCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_UCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_FCLK]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_FCLK].VoltageMode, - pptable->DpmDescriptor[PPCLK_FCLK].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_FCLK].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_FCLK].Padding, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_FCLK].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.a, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.b, - pptable->DpmDescriptor[PPCLK_FCLK].SsCurve.c, - pptable->DpmDescriptor[PPCLK_FCLK].SsFmin, - pptable->DpmDescriptor[PPCLK_FCLK].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_DCLK_0]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_DCLK_0].VoltageMode, - pptable->DpmDescriptor[PPCLK_DCLK_0].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DCLK_0].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DCLK_0].Padding, - pptable->DpmDescriptor[PPCLK_DCLK_0].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DCLK_0].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DCLK_0].SsCurve.c, - pptable->DpmDescriptor[PPCLK_DCLK_0].SsFmin, - pptable->DpmDescriptor[PPCLK_DCLK_0].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_VCLK_0]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_VCLK_0].VoltageMode, - pptable->DpmDescriptor[PPCLK_VCLK_0].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_VCLK_0].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_VCLK_0].Padding, - pptable->DpmDescriptor[PPCLK_VCLK_0].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_VCLK_0].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.a, - pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.b, - pptable->DpmDescriptor[PPCLK_VCLK_0].SsCurve.c, - pptable->DpmDescriptor[PPCLK_VCLK_0].SsFmin, - pptable->DpmDescriptor[PPCLK_VCLK_0].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_DCLK_1]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_DCLK_1].VoltageMode, - pptable->DpmDescriptor[PPCLK_DCLK_1].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_DCLK_1].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_DCLK_1].Padding, - pptable->DpmDescriptor[PPCLK_DCLK_1].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_DCLK_1].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.a, - pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.b, - pptable->DpmDescriptor[PPCLK_DCLK_1].SsCurve.c, - pptable->DpmDescriptor[PPCLK_DCLK_1].SsFmin, - pptable->DpmDescriptor[PPCLK_DCLK_1].Padding16); - - dev_info(smu->adev->dev, "[PPCLK_VCLK_1]\n" - " .VoltageMode = 0x%02x\n" - " .SnapToDiscrete = 0x%02x\n" - " .NumDiscreteLevels = 0x%02x\n" - " .padding = 0x%02x\n" - " .ConversionToAvfsClk{m = 0x%08x b = 0x%08x}\n" - " .SsCurve {a = 0x%08x b = 0x%08x c = 0x%08x}\n" - " .SsFmin = 0x%04x\n" - " .Padding_16 = 0x%04x\n", - pptable->DpmDescriptor[PPCLK_VCLK_1].VoltageMode, - pptable->DpmDescriptor[PPCLK_VCLK_1].SnapToDiscrete, - pptable->DpmDescriptor[PPCLK_VCLK_1].NumDiscreteLevels, - pptable->DpmDescriptor[PPCLK_VCLK_1].Padding, - pptable->DpmDescriptor[PPCLK_VCLK_1].ConversionToAvfsClk.m, - pptable->DpmDescriptor[PPCLK_VCLK_1].ConversionToAvfsClk.b, - pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.a, - pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.b, - pptable->DpmDescriptor[PPCLK_VCLK_1].SsCurve.c, - pptable->DpmDescriptor[PPCLK_VCLK_1].SsFmin, - pptable->DpmDescriptor[PPCLK_VCLK_1].Padding16); - - dev_info(smu->adev->dev, "FreqTableGfx\n"); - for (i = 0; i < NUM_GFXCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableGfx[i]); - - dev_info(smu->adev->dev, "FreqTableVclk\n"); - for (i = 0; i < NUM_VCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableVclk[i]); - - dev_info(smu->adev->dev, "FreqTableDclk\n"); - for (i = 0; i < NUM_DCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableDclk[i]); - - dev_info(smu->adev->dev, "FreqTableSocclk\n"); - for (i = 0; i < NUM_SOCCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableSocclk[i]); - - dev_info(smu->adev->dev, "FreqTableUclk\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableUclk[i]); - - dev_info(smu->adev->dev, "FreqTableFclk\n"); - for (i = 0; i < NUM_FCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%02d] = 0x%x\n", i, pptable->FreqTableFclk[i]); - - dev_info(smu->adev->dev, "Paddingclks[0] = 0x%x\n", pptable->Paddingclks[0]); - dev_info(smu->adev->dev, "Paddingclks[1] = 0x%x\n", pptable->Paddingclks[1]); - dev_info(smu->adev->dev, "Paddingclks[2] = 0x%x\n", pptable->Paddingclks[2]); - dev_info(smu->adev->dev, "Paddingclks[3] = 0x%x\n", pptable->Paddingclks[3]); - dev_info(smu->adev->dev, "Paddingclks[4] = 0x%x\n", pptable->Paddingclks[4]); - dev_info(smu->adev->dev, "Paddingclks[5] = 0x%x\n", pptable->Paddingclks[5]); - dev_info(smu->adev->dev, "Paddingclks[6] = 0x%x\n", pptable->Paddingclks[6]); - dev_info(smu->adev->dev, "Paddingclks[7] = 0x%x\n", pptable->Paddingclks[7]); - dev_info(smu->adev->dev, "Paddingclks[8] = 0x%x\n", pptable->Paddingclks[8]); - dev_info(smu->adev->dev, "Paddingclks[9] = 0x%x\n", pptable->Paddingclks[9]); - dev_info(smu->adev->dev, "Paddingclks[10] = 0x%x\n", pptable->Paddingclks[10]); - dev_info(smu->adev->dev, "Paddingclks[11] = 0x%x\n", pptable->Paddingclks[11]); - dev_info(smu->adev->dev, "Paddingclks[12] = 0x%x\n", pptable->Paddingclks[12]); - dev_info(smu->adev->dev, "Paddingclks[13] = 0x%x\n", pptable->Paddingclks[13]); - dev_info(smu->adev->dev, "Paddingclks[14] = 0x%x\n", pptable->Paddingclks[14]); - dev_info(smu->adev->dev, "Paddingclks[15] = 0x%x\n", pptable->Paddingclks[15]); - - dev_info(smu->adev->dev, "DcModeMaxFreq\n"); - dev_info(smu->adev->dev, " .PPCLK_GFXCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_GFXCLK]); - dev_info(smu->adev->dev, " .PPCLK_SOCCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_SOCCLK]); - dev_info(smu->adev->dev, " .PPCLK_UCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_UCLK]); - dev_info(smu->adev->dev, " .PPCLK_FCLK = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_FCLK]); - dev_info(smu->adev->dev, " .PPCLK_DCLK_0 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_DCLK_0]); - dev_info(smu->adev->dev, " .PPCLK_VCLK_0 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_VCLK_0]); - dev_info(smu->adev->dev, " .PPCLK_DCLK_1 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_DCLK_1]); - dev_info(smu->adev->dev, " .PPCLK_VCLK_1 = 0x%x\n", pptable->DcModeMaxFreq[PPCLK_VCLK_1]); - - dev_info(smu->adev->dev, "FreqTableUclkDiv\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FreqTableUclkDiv[i]); - - dev_info(smu->adev->dev, "FclkBoostFreq = 0x%x\n", pptable->FclkBoostFreq); - dev_info(smu->adev->dev, "FclkParamPadding = 0x%x\n", pptable->FclkParamPadding); - - dev_info(smu->adev->dev, "Mp0clkFreq\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->Mp0clkFreq[i]); - - dev_info(smu->adev->dev, "Mp0DpmVoltage\n"); - for (i = 0; i < NUM_MP0CLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->Mp0DpmVoltage[i]); - - dev_info(smu->adev->dev, "MemVddciVoltage\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->MemVddciVoltage[i]); - - dev_info(smu->adev->dev, "MemMvddVoltage\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->MemMvddVoltage[i]); - - dev_info(smu->adev->dev, "GfxclkFgfxoffEntry = 0x%x\n", pptable->GfxclkFgfxoffEntry); - dev_info(smu->adev->dev, "GfxclkFinit = 0x%x\n", pptable->GfxclkFinit); - dev_info(smu->adev->dev, "GfxclkFidle = 0x%x\n", pptable->GfxclkFidle); - dev_info(smu->adev->dev, "GfxclkSource = 0x%x\n", pptable->GfxclkSource); - dev_info(smu->adev->dev, "GfxclkPadding = 0x%x\n", pptable->GfxclkPadding); - - dev_info(smu->adev->dev, "GfxGpoSubFeatureMask = 0x%x\n", pptable->GfxGpoSubFeatureMask); - - dev_info(smu->adev->dev, "GfxGpoEnabledWorkPolicyMask = 0x%x\n", pptable->GfxGpoEnabledWorkPolicyMask); - dev_info(smu->adev->dev, "GfxGpoDisabledWorkPolicyMask = 0x%x\n", pptable->GfxGpoDisabledWorkPolicyMask); - dev_info(smu->adev->dev, "GfxGpoPadding[0] = 0x%x\n", pptable->GfxGpoPadding[0]); - dev_info(smu->adev->dev, "GfxGpoVotingAllow = 0x%x\n", pptable->GfxGpoVotingAllow); - dev_info(smu->adev->dev, "GfxGpoPadding32[0] = 0x%x\n", pptable->GfxGpoPadding32[0]); - dev_info(smu->adev->dev, "GfxGpoPadding32[1] = 0x%x\n", pptable->GfxGpoPadding32[1]); - dev_info(smu->adev->dev, "GfxGpoPadding32[2] = 0x%x\n", pptable->GfxGpoPadding32[2]); - dev_info(smu->adev->dev, "GfxGpoPadding32[3] = 0x%x\n", pptable->GfxGpoPadding32[3]); - dev_info(smu->adev->dev, "GfxDcsFopt = 0x%x\n", pptable->GfxDcsFopt); - dev_info(smu->adev->dev, "GfxDcsFclkFopt = 0x%x\n", pptable->GfxDcsFclkFopt); - dev_info(smu->adev->dev, "GfxDcsUclkFopt = 0x%x\n", pptable->GfxDcsUclkFopt); - - dev_info(smu->adev->dev, "DcsGfxOffVoltage = 0x%x\n", pptable->DcsGfxOffVoltage); - dev_info(smu->adev->dev, "DcsMinGfxOffTime = 0x%x\n", pptable->DcsMinGfxOffTime); - dev_info(smu->adev->dev, "DcsMaxGfxOffTime = 0x%x\n", pptable->DcsMaxGfxOffTime); - dev_info(smu->adev->dev, "DcsMinCreditAccum = 0x%x\n", pptable->DcsMinCreditAccum); - dev_info(smu->adev->dev, "DcsExitHysteresis = 0x%x\n", pptable->DcsExitHysteresis); - dev_info(smu->adev->dev, "DcsTimeout = 0x%x\n", pptable->DcsTimeout); - - dev_info(smu->adev->dev, "DcsParamPadding[0] = 0x%x\n", pptable->DcsParamPadding[0]); - dev_info(smu->adev->dev, "DcsParamPadding[1] = 0x%x\n", pptable->DcsParamPadding[1]); - dev_info(smu->adev->dev, "DcsParamPadding[2] = 0x%x\n", pptable->DcsParamPadding[2]); - dev_info(smu->adev->dev, "DcsParamPadding[3] = 0x%x\n", pptable->DcsParamPadding[3]); - dev_info(smu->adev->dev, "DcsParamPadding[4] = 0x%x\n", pptable->DcsParamPadding[4]); - - dev_info(smu->adev->dev, "FlopsPerByteTable\n"); - for (i = 0; i < RLC_PACE_TABLE_NUM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FlopsPerByteTable[i]); - - dev_info(smu->adev->dev, "LowestUclkReservedForUlv = 0x%x\n", pptable->LowestUclkReservedForUlv); - dev_info(smu->adev->dev, "vddingMem[0] = 0x%x\n", pptable->PaddingMem[0]); - dev_info(smu->adev->dev, "vddingMem[1] = 0x%x\n", pptable->PaddingMem[1]); - dev_info(smu->adev->dev, "vddingMem[2] = 0x%x\n", pptable->PaddingMem[2]); - - dev_info(smu->adev->dev, "UclkDpmPstates\n"); - for (i = 0; i < NUM_UCLK_DPM_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->UclkDpmPstates[i]); - - dev_info(smu->adev->dev, "UclkDpmSrcFreqRange\n"); - dev_info(smu->adev->dev, " .Fmin = 0x%x\n", - pptable->UclkDpmSrcFreqRange.Fmin); - dev_info(smu->adev->dev, " .Fmax = 0x%x\n", - pptable->UclkDpmSrcFreqRange.Fmax); - dev_info(smu->adev->dev, "UclkDpmTargFreqRange\n"); - dev_info(smu->adev->dev, " .Fmin = 0x%x\n", - pptable->UclkDpmTargFreqRange.Fmin); - dev_info(smu->adev->dev, " .Fmax = 0x%x\n", - pptable->UclkDpmTargFreqRange.Fmax); - dev_info(smu->adev->dev, "UclkDpmMidstepFreq = 0x%x\n", pptable->UclkDpmMidstepFreq); - dev_info(smu->adev->dev, "UclkMidstepPadding = 0x%x\n", pptable->UclkMidstepPadding); - - dev_info(smu->adev->dev, "PcieGenSpeed\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->PcieGenSpeed[i]); - - dev_info(smu->adev->dev, "PcieLaneCount\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->PcieLaneCount[i]); - - dev_info(smu->adev->dev, "LclkFreq\n"); - for (i = 0; i < NUM_LINK_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->LclkFreq[i]); - - dev_info(smu->adev->dev, "FanStopTemp = 0x%x\n", pptable->FanStopTemp); - dev_info(smu->adev->dev, "FanStartTemp = 0x%x\n", pptable->FanStartTemp); - - dev_info(smu->adev->dev, "FanGain\n"); - for (i = 0; i < TEMP_COUNT; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->FanGain[i]); - - dev_info(smu->adev->dev, "FanPwmMin = 0x%x\n", pptable->FanPwmMin); - dev_info(smu->adev->dev, "FanAcousticLimitRpm = 0x%x\n", pptable->FanAcousticLimitRpm); - dev_info(smu->adev->dev, "FanThrottlingRpm = 0x%x\n", pptable->FanThrottlingRpm); - dev_info(smu->adev->dev, "FanMaximumRpm = 0x%x\n", pptable->FanMaximumRpm); - dev_info(smu->adev->dev, "MGpuFanBoostLimitRpm = 0x%x\n", pptable->MGpuFanBoostLimitRpm); - dev_info(smu->adev->dev, "FanTargetTemperature = 0x%x\n", pptable->FanTargetTemperature); - dev_info(smu->adev->dev, "FanTargetGfxclk = 0x%x\n", pptable->FanTargetGfxclk); - dev_info(smu->adev->dev, "FanPadding16 = 0x%x\n", pptable->FanPadding16); - dev_info(smu->adev->dev, "FanTempInputSelect = 0x%x\n", pptable->FanTempInputSelect); - dev_info(smu->adev->dev, "FanPadding = 0x%x\n", pptable->FanPadding); - dev_info(smu->adev->dev, "FanZeroRpmEnable = 0x%x\n", pptable->FanZeroRpmEnable); - dev_info(smu->adev->dev, "FanTachEdgePerRev = 0x%x\n", pptable->FanTachEdgePerRev); - - dev_info(smu->adev->dev, "FuzzyFan_ErrorSetDelta = 0x%x\n", pptable->FuzzyFan_ErrorSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_ErrorRateSetDelta = 0x%x\n", pptable->FuzzyFan_ErrorRateSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_PwmSetDelta = 0x%x\n", pptable->FuzzyFan_PwmSetDelta); - dev_info(smu->adev->dev, "FuzzyFan_Reserved = 0x%x\n", pptable->FuzzyFan_Reserved); - - dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "OverrideAvfsGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->OverrideAvfsGb[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "dBtcGbGfxDfllModelSelect = 0x%x\n", pptable->dBtcGbGfxDfllModelSelect); - dev_info(smu->adev->dev, "Padding8_Avfs = 0x%x\n", pptable->Padding8_Avfs); - - dev_info(smu->adev->dev, "qAvfsGb[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].a, - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].b, - pptable->qAvfsGb[AVFS_VOLTAGE_GFX].c); - dev_info(smu->adev->dev, "qAvfsGb[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].a, - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].b, - pptable->qAvfsGb[AVFS_VOLTAGE_SOC].c); - dev_info(smu->adev->dev, "dBtcGbGfxPll{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxPll.a, - pptable->dBtcGbGfxPll.b, - pptable->dBtcGbGfxPll.c); - dev_info(smu->adev->dev, "dBtcGbGfxAfll{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbGfxDfll.a, - pptable->dBtcGbGfxDfll.b, - pptable->dBtcGbGfxDfll.c); - dev_info(smu->adev->dev, "dBtcGbSoc{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->dBtcGbSoc.a, - pptable->dBtcGbSoc.b, - pptable->dBtcGbSoc.c); - dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_GFX]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_GFX].m, - pptable->qAgingGb[AVFS_VOLTAGE_GFX].b); - dev_info(smu->adev->dev, "qAgingGb[AVFS_VOLTAGE_SOC]{m = 0x%x b = 0x%x}\n", - pptable->qAgingGb[AVFS_VOLTAGE_SOC].m, - pptable->qAgingGb[AVFS_VOLTAGE_SOC].b); - - dev_info(smu->adev->dev, "PiecewiseLinearDroopIntGfxDfll\n"); - for (i = 0; i < NUM_PIECE_WISE_LINEAR_DROOP_MODEL_VF_POINTS; i++) { - dev_info(smu->adev->dev, " Fset[%d] = 0x%x\n", - i, pptable->PiecewiseLinearDroopIntGfxDfll.Fset[i]); - dev_info(smu->adev->dev, " Vdroop[%d] = 0x%x\n", - i, pptable->PiecewiseLinearDroopIntGfxDfll.Vdroop[i]); - } - - dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_GFX]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_GFX].c); - dev_info(smu->adev->dev, "qStaticVoltageOffset[AVFS_VOLTAGE_SOC]{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].a, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].b, - pptable->qStaticVoltageOffset[AVFS_VOLTAGE_SOC].c); - - dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcTol[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcTol[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcEnabled[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcEnabled[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "Padding8_GfxBtc[0] = 0x%x\n", pptable->Padding8_GfxBtc[0]); - dev_info(smu->adev->dev, "Padding8_GfxBtc[1] = 0x%x\n", pptable->Padding8_GfxBtc[1]); - - dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcMin[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMin[AVFS_VOLTAGE_SOC]); - dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcMax[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcMax[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_GFX] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_GFX]); - dev_info(smu->adev->dev, "DcBtcGb[AVFS_VOLTAGE_SOC] = 0x%x\n", pptable->DcBtcGb[AVFS_VOLTAGE_SOC]); - - dev_info(smu->adev->dev, "XgmiDpmPstates\n"); - for (i = 0; i < NUM_XGMI_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiDpmPstates[i]); - dev_info(smu->adev->dev, "XgmiDpmSpare[0] = 0x%02x\n", pptable->XgmiDpmSpare[0]); - dev_info(smu->adev->dev, "XgmiDpmSpare[1] = 0x%02x\n", pptable->XgmiDpmSpare[1]); - - dev_info(smu->adev->dev, "DebugOverrides = 0x%x\n", pptable->DebugOverrides); - dev_info(smu->adev->dev, "ReservedEquation0{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation0.a, - pptable->ReservedEquation0.b, - pptable->ReservedEquation0.c); - dev_info(smu->adev->dev, "ReservedEquation1{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation1.a, - pptable->ReservedEquation1.b, - pptable->ReservedEquation1.c); - dev_info(smu->adev->dev, "ReservedEquation2{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation2.a, - pptable->ReservedEquation2.b, - pptable->ReservedEquation2.c); - dev_info(smu->adev->dev, "ReservedEquation3{a = 0x%x b = 0x%x c = 0x%x}\n", - pptable->ReservedEquation3.a, - pptable->ReservedEquation3.b, - pptable->ReservedEquation3.c); - - dev_info(smu->adev->dev, "SkuReserved[0] = 0x%x\n", pptable->SkuReserved[0]); - dev_info(smu->adev->dev, "SkuReserved[1] = 0x%x\n", pptable->SkuReserved[1]); - dev_info(smu->adev->dev, "SkuReserved[2] = 0x%x\n", pptable->SkuReserved[2]); - dev_info(smu->adev->dev, "SkuReserved[3] = 0x%x\n", pptable->SkuReserved[3]); - dev_info(smu->adev->dev, "SkuReserved[4] = 0x%x\n", pptable->SkuReserved[4]); - dev_info(smu->adev->dev, "SkuReserved[5] = 0x%x\n", pptable->SkuReserved[5]); - dev_info(smu->adev->dev, "SkuReserved[6] = 0x%x\n", pptable->SkuReserved[6]); - dev_info(smu->adev->dev, "SkuReserved[7] = 0x%x\n", pptable->SkuReserved[7]); - dev_info(smu->adev->dev, "SkuReserved[8] = 0x%x\n", pptable->SkuReserved[8]); - dev_info(smu->adev->dev, "SkuReserved[9] = 0x%x\n", pptable->SkuReserved[9]); - dev_info(smu->adev->dev, "SkuReserved[10] = 0x%x\n", pptable->SkuReserved[10]); - dev_info(smu->adev->dev, "SkuReserved[11] = 0x%x\n", pptable->SkuReserved[11]); - dev_info(smu->adev->dev, "SkuReserved[12] = 0x%x\n", pptable->SkuReserved[12]); - dev_info(smu->adev->dev, "SkuReserved[13] = 0x%x\n", pptable->SkuReserved[13]); - - dev_info(smu->adev->dev, "GamingClk[0] = 0x%x\n", pptable->GamingClk[0]); - dev_info(smu->adev->dev, "GamingClk[1] = 0x%x\n", pptable->GamingClk[1]); - dev_info(smu->adev->dev, "GamingClk[2] = 0x%x\n", pptable->GamingClk[2]); - dev_info(smu->adev->dev, "GamingClk[3] = 0x%x\n", pptable->GamingClk[3]); - dev_info(smu->adev->dev, "GamingClk[4] = 0x%x\n", pptable->GamingClk[4]); - dev_info(smu->adev->dev, "GamingClk[5] = 0x%x\n", pptable->GamingClk[5]); - - for (i = 0; i < NUM_I2C_CONTROLLERS; i++) { - dev_info(smu->adev->dev, "I2cControllers[%d]:\n", i); - dev_info(smu->adev->dev, " .Enabled = 0x%x\n", - pptable->I2cControllers[i].Enabled); - dev_info(smu->adev->dev, " .Speed = 0x%x\n", - pptable->I2cControllers[i].Speed); - dev_info(smu->adev->dev, " .SlaveAddress = 0x%x\n", - pptable->I2cControllers[i].SlaveAddress); - dev_info(smu->adev->dev, " .ControllerPort = 0x%x\n", - pptable->I2cControllers[i].ControllerPort); - dev_info(smu->adev->dev, " .ControllerName = 0x%x\n", - pptable->I2cControllers[i].ControllerName); - dev_info(smu->adev->dev, " .ThermalThrottler = 0x%x\n", - pptable->I2cControllers[i].ThermalThrotter); - dev_info(smu->adev->dev, " .I2cProtocol = 0x%x\n", - pptable->I2cControllers[i].I2cProtocol); - dev_info(smu->adev->dev, " .PaddingConfig = 0x%x\n", - pptable->I2cControllers[i].PaddingConfig); - } - - dev_info(smu->adev->dev, "GpioScl = 0x%x\n", pptable->GpioScl); - dev_info(smu->adev->dev, "GpioSda = 0x%x\n", pptable->GpioSda); - dev_info(smu->adev->dev, "FchUsbPdSlaveAddr = 0x%x\n", pptable->FchUsbPdSlaveAddr); - dev_info(smu->adev->dev, "I2cSpare[0] = 0x%x\n", pptable->I2cSpare[0]); - - dev_info(smu->adev->dev, "Board Parameters:\n"); - dev_info(smu->adev->dev, "VddGfxVrMapping = 0x%x\n", pptable->VddGfxVrMapping); - dev_info(smu->adev->dev, "VddSocVrMapping = 0x%x\n", pptable->VddSocVrMapping); - dev_info(smu->adev->dev, "VddMem0VrMapping = 0x%x\n", pptable->VddMem0VrMapping); - dev_info(smu->adev->dev, "VddMem1VrMapping = 0x%x\n", pptable->VddMem1VrMapping); - dev_info(smu->adev->dev, "GfxUlvPhaseSheddingMask = 0x%x\n", pptable->GfxUlvPhaseSheddingMask); - dev_info(smu->adev->dev, "SocUlvPhaseSheddingMask = 0x%x\n", pptable->SocUlvPhaseSheddingMask); - dev_info(smu->adev->dev, "VddciUlvPhaseSheddingMask = 0x%x\n", pptable->VddciUlvPhaseSheddingMask); - dev_info(smu->adev->dev, "MvddUlvPhaseSheddingMask = 0x%x\n", pptable->MvddUlvPhaseSheddingMask); - - dev_info(smu->adev->dev, "GfxMaxCurrent = 0x%x\n", pptable->GfxMaxCurrent); - dev_info(smu->adev->dev, "GfxOffset = 0x%x\n", pptable->GfxOffset); - dev_info(smu->adev->dev, "Padding_TelemetryGfx = 0x%x\n", pptable->Padding_TelemetryGfx); - - dev_info(smu->adev->dev, "SocMaxCurrent = 0x%x\n", pptable->SocMaxCurrent); - dev_info(smu->adev->dev, "SocOffset = 0x%x\n", pptable->SocOffset); - dev_info(smu->adev->dev, "Padding_TelemetrySoc = 0x%x\n", pptable->Padding_TelemetrySoc); - - dev_info(smu->adev->dev, "Mem0MaxCurrent = 0x%x\n", pptable->Mem0MaxCurrent); - dev_info(smu->adev->dev, "Mem0Offset = 0x%x\n", pptable->Mem0Offset); - dev_info(smu->adev->dev, "Padding_TelemetryMem0 = 0x%x\n", pptable->Padding_TelemetryMem0); - - dev_info(smu->adev->dev, "Mem1MaxCurrent = 0x%x\n", pptable->Mem1MaxCurrent); - dev_info(smu->adev->dev, "Mem1Offset = 0x%x\n", pptable->Mem1Offset); - dev_info(smu->adev->dev, "Padding_TelemetryMem1 = 0x%x\n", pptable->Padding_TelemetryMem1); - - dev_info(smu->adev->dev, "MvddRatio = 0x%x\n", pptable->MvddRatio); - - dev_info(smu->adev->dev, "AcDcGpio = 0x%x\n", pptable->AcDcGpio); - dev_info(smu->adev->dev, "AcDcPolarity = 0x%x\n", pptable->AcDcPolarity); - dev_info(smu->adev->dev, "VR0HotGpio = 0x%x\n", pptable->VR0HotGpio); - dev_info(smu->adev->dev, "VR0HotPolarity = 0x%x\n", pptable->VR0HotPolarity); - dev_info(smu->adev->dev, "VR1HotGpio = 0x%x\n", pptable->VR1HotGpio); - dev_info(smu->adev->dev, "VR1HotPolarity = 0x%x\n", pptable->VR1HotPolarity); - dev_info(smu->adev->dev, "GthrGpio = 0x%x\n", pptable->GthrGpio); - dev_info(smu->adev->dev, "GthrPolarity = 0x%x\n", pptable->GthrPolarity); - dev_info(smu->adev->dev, "LedPin0 = 0x%x\n", pptable->LedPin0); - dev_info(smu->adev->dev, "LedPin1 = 0x%x\n", pptable->LedPin1); - dev_info(smu->adev->dev, "LedPin2 = 0x%x\n", pptable->LedPin2); - dev_info(smu->adev->dev, "LedEnableMask = 0x%x\n", pptable->LedEnableMask); - dev_info(smu->adev->dev, "LedPcie = 0x%x\n", pptable->LedPcie); - dev_info(smu->adev->dev, "LedError = 0x%x\n", pptable->LedError); - dev_info(smu->adev->dev, "LedSpare1[0] = 0x%x\n", pptable->LedSpare1[0]); - dev_info(smu->adev->dev, "LedSpare1[1] = 0x%x\n", pptable->LedSpare1[1]); - - dev_info(smu->adev->dev, "PllGfxclkSpreadEnabled = 0x%x\n", pptable->PllGfxclkSpreadEnabled); - dev_info(smu->adev->dev, "PllGfxclkSpreadPercent = 0x%x\n", pptable->PllGfxclkSpreadPercent); - dev_info(smu->adev->dev, "PllGfxclkSpreadFreq = 0x%x\n", pptable->PllGfxclkSpreadFreq); - - dev_info(smu->adev->dev, "DfllGfxclkSpreadEnabled = 0x%x\n", pptable->DfllGfxclkSpreadEnabled); - dev_info(smu->adev->dev, "DfllGfxclkSpreadPercent = 0x%x\n", pptable->DfllGfxclkSpreadPercent); - dev_info(smu->adev->dev, "DfllGfxclkSpreadFreq = 0x%x\n", pptable->DfllGfxclkSpreadFreq); - - dev_info(smu->adev->dev, "UclkSpreadPadding = 0x%x\n", pptable->UclkSpreadPadding); - dev_info(smu->adev->dev, "UclkSpreadFreq = 0x%x\n", pptable->UclkSpreadFreq); - - dev_info(smu->adev->dev, "FclkSpreadEnabled = 0x%x\n", pptable->FclkSpreadEnabled); - dev_info(smu->adev->dev, "FclkSpreadPercent = 0x%x\n", pptable->FclkSpreadPercent); - dev_info(smu->adev->dev, "FclkSpreadFreq = 0x%x\n", pptable->FclkSpreadFreq); - - dev_info(smu->adev->dev, "MemoryChannelEnabled = 0x%x\n", pptable->MemoryChannelEnabled); - dev_info(smu->adev->dev, "DramBitWidth = 0x%x\n", pptable->DramBitWidth); - dev_info(smu->adev->dev, "PaddingMem1[0] = 0x%x\n", pptable->PaddingMem1[0]); - dev_info(smu->adev->dev, "PaddingMem1[1] = 0x%x\n", pptable->PaddingMem1[1]); - dev_info(smu->adev->dev, "PaddingMem1[2] = 0x%x\n", pptable->PaddingMem1[2]); - - dev_info(smu->adev->dev, "TotalBoardPower = 0x%x\n", pptable->TotalBoardPower); - dev_info(smu->adev->dev, "BoardPowerPadding = 0x%x\n", pptable->BoardPowerPadding); - - dev_info(smu->adev->dev, "XgmiLinkSpeed\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiLinkSpeed[i]); - dev_info(smu->adev->dev, "XgmiLinkWidth\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiLinkWidth[i]); - dev_info(smu->adev->dev, "XgmiFclkFreq\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiFclkFreq[i]); - dev_info(smu->adev->dev, "XgmiSocVoltage\n"); - for (i = 0; i < NUM_XGMI_PSTATE_LEVELS; i++) - dev_info(smu->adev->dev, " .[%d] = 0x%x\n", i, pptable->XgmiSocVoltage[i]); - - dev_info(smu->adev->dev, "HsrEnabled = 0x%x\n", pptable->HsrEnabled); - dev_info(smu->adev->dev, "VddqOffEnabled = 0x%x\n", pptable->VddqOffEnabled); - dev_info(smu->adev->dev, "PaddingUmcFlags[0] = 0x%x\n", pptable->PaddingUmcFlags[0]); - dev_info(smu->adev->dev, "PaddingUmcFlags[1] = 0x%x\n", pptable->PaddingUmcFlags[1]); - - dev_info(smu->adev->dev, "BoardReserved[0] = 0x%x\n", pptable->BoardReserved[0]); - dev_info(smu->adev->dev, "BoardReserved[1] = 0x%x\n", pptable->BoardReserved[1]); - dev_info(smu->adev->dev, "BoardReserved[2] = 0x%x\n", pptable->BoardReserved[2]); - dev_info(smu->adev->dev, "BoardReserved[3] = 0x%x\n", pptable->BoardReserved[3]); - dev_info(smu->adev->dev, "BoardReserved[4] = 0x%x\n", pptable->BoardReserved[4]); - dev_info(smu->adev->dev, "BoardReserved[5] = 0x%x\n", pptable->BoardReserved[5]); - dev_info(smu->adev->dev, "BoardReserved[6] = 0x%x\n", pptable->BoardReserved[6]); - dev_info(smu->adev->dev, "BoardReserved[7] = 0x%x\n", pptable->BoardReserved[7]); - dev_info(smu->adev->dev, "BoardReserved[8] = 0x%x\n", pptable->BoardReserved[8]); - dev_info(smu->adev->dev, "BoardReserved[9] = 0x%x\n", pptable->BoardReserved[9]); - dev_info(smu->adev->dev, "BoardReserved[10] = 0x%x\n", pptable->BoardReserved[10]); - - dev_info(smu->adev->dev, "MmHubPadding[0] = 0x%x\n", pptable->MmHubPadding[0]); - dev_info(smu->adev->dev, "MmHubPadding[1] = 0x%x\n", pptable->MmHubPadding[1]); - dev_info(smu->adev->dev, "MmHubPadding[2] = 0x%x\n", pptable->MmHubPadding[2]); - dev_info(smu->adev->dev, "MmHubPadding[3] = 0x%x\n", pptable->MmHubPadding[3]); - dev_info(smu->adev->dev, "MmHubPadding[4] = 0x%x\n", pptable->MmHubPadding[4]); - dev_info(smu->adev->dev, "MmHubPadding[5] = 0x%x\n", pptable->MmHubPadding[5]); - dev_info(smu->adev->dev, "MmHubPadding[6] = 0x%x\n", pptable->MmHubPadding[6]); - dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]); -} - -static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t *req, bool write, - uint8_t address, uint32_t numbytes, - uint8_t *data) -{ - int i; - - BUG_ON(numbytes > MAX_SW_I2C_COMMANDS); - - req->I2CcontrollerPort = 0; - req->I2CSpeed = 2; - req->SlaveAddress = address; - req->NumCmds = numbytes; - - for (i = 0; i < numbytes; i++) { - SwI2cCmd_t *cmd = &req->SwI2cCmds[i]; - - /* First 2 bytes are always write for lower 2b EEPROM address */ - if (i < 2) - cmd->CmdConfig = CMDCONFIG_READWRITE_MASK; - else - cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0; - - - /* Add RESTART for read after address filled */ - cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0; - - /* Add STOP in the end */ - cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0; - - /* Fill with data regardless if read or write to simplify code */ - cmd->ReadWriteData = data[i]; - } -} - -static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t i, ret = 0; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - struct smu_table_context *smu_table = &adev->smu.smu_table; - struct smu_table *table = &smu_table->driver_table; - - memset(&req, 0, sizeof(req)); - sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - /* Now read data starting with that address */ - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, - true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr; - - /* Assume SMU fills res.SwI2cCmds[i].Data with read bytes */ - for (i = 0; i < numbytes; i++) - data[i] = res->SwI2cCmds[i].ReadWriteData; - - dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - } else - dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret); - - return ret; -} - -static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control, - uint8_t address, - uint8_t *data, - uint32_t numbytes) -{ - uint32_t ret; - SwI2cRequest_t req; - struct amdgpu_device *adev = to_amdgpu_device(control); - - memset(&req, 0, sizeof(req)); - sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data); - - mutex_lock(&adev->smu.mutex); - ret = smu_cmn_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true); - mutex_unlock(&adev->smu.mutex); - - if (!ret) { - dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ", - (uint16_t)address, numbytes); - - print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE, - 8, 1, data, numbytes, false); - /* - * According to EEPROM spec there is a MAX of 10 ms required for - * EEPROM to flush internal RX buffer after STOP was issued at the - * end of write transaction. During this time the EEPROM will not be - * responsive to any more commands - so wait a bit more. - */ - msleep(10); - - } else - dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret); - - return ret; -} - -static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, int num) -{ - uint32_t i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0; - uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 }; - - for (i = 0; i < num; i++) { - /* - * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at - * once and hence the data needs to be spliced into chunks and sent each - * chunk separately - */ - data_size = msgs[i].len - 2; - data_chunk_size = MAX_SW_I2C_COMMANDS - 2; - next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff); - data_ptr = msgs[i].buf + 2; - - for (j = 0; j < data_size / data_chunk_size; j++) { - /* Insert the EEPROM dest addess, bits 0-15 */ - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = sienna_cichlid_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - - memcpy(data_ptr, data_chunk + 2, data_chunk_size); - } else { - - memcpy(data_chunk + 2, data_ptr, data_chunk_size); - - ret = sienna_cichlid_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, MAX_SW_I2C_COMMANDS); - } - - if (ret) { - num = -EIO; - goto fail; - } - - next_eeprom_addr += data_chunk_size; - data_ptr += data_chunk_size; - } - - if (data_size % data_chunk_size) { - data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff); - data_chunk[1] = (next_eeprom_addr & 0xff); - - if (msgs[i].flags & I2C_M_RD) { - ret = sienna_cichlid_i2c_read_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - - memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size); - } else { - memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size); - - ret = sienna_cichlid_i2c_write_data(i2c_adap, - (uint8_t)msgs[i].addr, - data_chunk, (data_size % data_chunk_size) + 2); - } - - if (ret) { - num = -EIO; - goto fail; - } - } - } - -fail: - return num; -} - -static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - - -static const struct i2c_algorithm sienna_cichlid_i2c_algo = { - .master_xfer = sienna_cichlid_i2c_xfer, - .functionality = sienna_cichlid_i2c_func, -}; - -static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control) -{ - struct amdgpu_device *adev = to_amdgpu_device(control); - int res; - - control->owner = THIS_MODULE; - control->class = I2C_CLASS_SPD; - control->dev.parent = &adev->pdev->dev; - control->algo = &sienna_cichlid_i2c_algo; - snprintf(control->name, sizeof(control->name), "AMDGPU SMU"); - - res = i2c_add_adapter(control); - if (res) - DRM_ERROR("Failed to register hw i2c, err: %d\n", res); - - return res; -} - -static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control) -{ - i2c_del_adapter(control); -} - -static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu, - void **table) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct gpu_metrics_v1_0 *gpu_metrics = - (struct gpu_metrics_v1_0 *)smu_table->gpu_metrics_table; - SmuMetrics_t metrics; - int ret = 0; - - ret = smu_cmn_get_metrics_table(smu, - &metrics, - true); - if (ret) - return ret; - - smu_v11_0_init_gpu_metrics_v1_0(gpu_metrics); - - gpu_metrics->temperature_edge = metrics.TemperatureEdge; - gpu_metrics->temperature_hotspot = metrics.TemperatureHotspot; - gpu_metrics->temperature_mem = metrics.TemperatureMem; - gpu_metrics->temperature_vrgfx = metrics.TemperatureVrGfx; - gpu_metrics->temperature_vrsoc = metrics.TemperatureVrSoc; - gpu_metrics->temperature_vrmem = metrics.TemperatureVrMem0; - - gpu_metrics->average_gfx_activity = metrics.AverageGfxActivity; - gpu_metrics->average_umc_activity = metrics.AverageUclkActivity; - gpu_metrics->average_mm_activity = metrics.VcnActivityPercentage; - - gpu_metrics->average_socket_power = metrics.AverageSocketPower; - gpu_metrics->energy_accumulator = metrics.EnergyAccumulator; - - if (metrics.AverageGfxActivity <= SMU_11_0_7_GFX_BUSY_THRESHOLD) - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPostDs; - else - gpu_metrics->average_gfxclk_frequency = metrics.AverageGfxclkFrequencyPreDs; - gpu_metrics->average_uclk_frequency = metrics.AverageUclkFrequencyPostDs; - gpu_metrics->average_vclk0_frequency = metrics.AverageVclk0Frequency; - gpu_metrics->average_dclk0_frequency = metrics.AverageDclk0Frequency; - gpu_metrics->average_vclk1_frequency = metrics.AverageVclk1Frequency; - gpu_metrics->average_dclk1_frequency = metrics.AverageDclk1Frequency; - - gpu_metrics->current_gfxclk = metrics.CurrClock[PPCLK_GFXCLK]; - gpu_metrics->current_socclk = metrics.CurrClock[PPCLK_SOCCLK]; - gpu_metrics->current_uclk = metrics.CurrClock[PPCLK_UCLK]; - gpu_metrics->current_vclk0 = metrics.CurrClock[PPCLK_VCLK_0]; - gpu_metrics->current_dclk0 = metrics.CurrClock[PPCLK_DCLK_0]; - gpu_metrics->current_vclk1 = metrics.CurrClock[PPCLK_VCLK_1]; - gpu_metrics->current_dclk1 = metrics.CurrClock[PPCLK_DCLK_1]; - - gpu_metrics->throttle_status = metrics.ThrottlerStatus; - - gpu_metrics->current_fan_speed = metrics.CurrFanSpeed; - - gpu_metrics->pcie_link_width = - smu_v11_0_get_current_pcie_link_width(smu); - gpu_metrics->pcie_link_speed = - smu_v11_0_get_current_pcie_link_speed(smu); - - *table = (void *)gpu_metrics; - - return sizeof(struct gpu_metrics_v1_0); -} - -static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu) -{ - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetMGpuFanBoostLimitRpm, - 0, - NULL); -} - -static const struct pptable_funcs sienna_cichlid_ppt_funcs = { - .get_allowed_feature_mask = sienna_cichlid_get_allowed_feature_mask, - .set_default_dpm_table = sienna_cichlid_set_default_dpm_table, - .dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable, - .dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable, - .i2c_init = sienna_cichlid_i2c_control_init, - .i2c_fini = sienna_cichlid_i2c_control_fini, - .print_clk_levels = sienna_cichlid_print_clk_levels, - .force_clk_levels = sienna_cichlid_force_clk_levels, - .populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk, - .pre_display_config_changed = sienna_cichlid_pre_display_config_changed, - .display_config_changed = sienna_cichlid_display_config_changed, - .notify_smc_display_config = sienna_cichlid_notify_smc_display_config, - .is_dpm_running = sienna_cichlid_is_dpm_running, - .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent, - .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm, - .get_power_profile_mode = sienna_cichlid_get_power_profile_mode, - .set_power_profile_mode = sienna_cichlid_set_power_profile_mode, - .set_watermarks_table = sienna_cichlid_set_watermarks_table, - .read_sensor = sienna_cichlid_read_sensor, - .get_uclk_dpm_states = sienna_cichlid_get_uclk_dpm_states, - .set_performance_level = smu_v11_0_set_performance_level, - .get_thermal_temperature_range = sienna_cichlid_get_thermal_temperature_range, - .display_disable_memory_clock_switch = sienna_cichlid_display_disable_memory_clock_switch, - .get_power_limit = sienna_cichlid_get_power_limit, - .update_pcie_parameters = sienna_cichlid_update_pcie_parameters, - .dump_pptable = sienna_cichlid_dump_pptable, - .init_microcode = smu_v11_0_init_microcode, - .load_microcode = smu_v11_0_load_microcode, - .init_smc_tables = sienna_cichlid_init_smc_tables, - .fini_smc_tables = smu_v11_0_fini_smc_tables, - .init_power = smu_v11_0_init_power, - .fini_power = smu_v11_0_fini_power, - .check_fw_status = smu_v11_0_check_fw_status, - .setup_pptable = sienna_cichlid_setup_pptable, - .get_vbios_bootup_values = smu_v11_0_get_vbios_bootup_values, - .check_fw_version = smu_v11_0_check_fw_version, - .write_pptable = smu_cmn_write_pptable, - .set_driver_table_location = smu_v11_0_set_driver_table_location, - .set_tool_table_location = smu_v11_0_set_tool_table_location, - .notify_memory_pool_location = smu_v11_0_notify_memory_pool_location, - .system_features_control = smu_v11_0_system_features_control, - .send_smc_msg_with_param = smu_cmn_send_smc_msg_with_param, - .send_smc_msg = smu_cmn_send_smc_msg, - .init_display_count = NULL, - .set_allowed_mask = smu_v11_0_set_allowed_mask, - .get_enabled_mask = smu_cmn_get_enabled_mask, - .feature_is_enabled = smu_cmn_feature_is_enabled, - .disable_all_features_with_exception = smu_cmn_disable_all_features_with_exception, - .notify_display_change = NULL, - .set_power_limit = smu_v11_0_set_power_limit, - .init_max_sustainable_clocks = smu_v11_0_init_max_sustainable_clocks, - .enable_thermal_alert = smu_v11_0_enable_thermal_alert, - .disable_thermal_alert = smu_v11_0_disable_thermal_alert, - .set_min_dcef_deep_sleep = NULL, - .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, - .get_fan_control_mode = smu_v11_0_get_fan_control_mode, - .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, - .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, - .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, - .gfx_off_control = smu_v11_0_gfx_off_control, - .register_irq_handler = smu_v11_0_register_irq_handler, - .set_azalia_d3_pme = smu_v11_0_set_azalia_d3_pme, - .get_max_sustainable_clocks_by_dc = smu_v11_0_get_max_sustainable_clocks_by_dc, - .baco_is_support= sienna_cichlid_is_baco_supported, - .baco_get_state = smu_v11_0_baco_get_state, - .baco_set_state = smu_v11_0_baco_set_state, - .baco_enter = smu_v11_0_baco_enter, - .baco_exit = smu_v11_0_baco_exit, - .mode1_reset_is_support = sienna_cichlid_is_mode1_reset_supported, - .mode1_reset = smu_v11_0_mode1_reset, - .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, - .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, - .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, - .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, - .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, - .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, -}; - -void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -{ - smu->ppt_funcs = &sienna_cichlid_ppt_funcs; - smu->message_map = sienna_cichlid_message_map; - smu->clock_map = sienna_cichlid_clk_map; - smu->feature_map = sienna_cichlid_feature_mask_map; - smu->table_map = sienna_cichlid_table_map; - smu->pwr_src_map = sienna_cichlid_pwr_src_map; - smu->workload_map = sienna_cichlid_workload_map; -} diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h deleted file mode 100644 index 57e120c440ea..000000000000 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef __SIENNA_CICHLID_PPT_H__ -#define __SIENNA_CICHLID_PPT_H__ - -typedef enum { - POWER_SOURCE_AC, - POWER_SOURCE_DC, - POWER_SOURCE_COUNT, -} POWER_SOURCE_e; - -extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.c b/drivers/gpu/drm/amd/powerplay/smu_cmn.c deleted file mode 100644 index a58ea08cd115..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - * 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. - */ - -#define SWSMU_CODE_LAYER_L4 - -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "smu_cmn.h" -#include "soc15_common.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -/* - * Although these are defined in each ASIC's specific header file. - * They share the same definitions and values. That makes common - * APIs for SMC messages issuing for all ASICs possible. - */ -#define mmMP1_SMN_C2PMSG_66 0x0282 -#define mmMP1_SMN_C2PMSG_66_BASE_IDX 0 - -#define mmMP1_SMN_C2PMSG_82 0x0292 -#define mmMP1_SMN_C2PMSG_82_BASE_IDX 0 - -#define mmMP1_SMN_C2PMSG_90 0x029a -#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0 - -#define MP1_C2PMSG_90__CONTENT_MASK 0xFFFFFFFFL - -#undef __SMU_DUMMY_MAP -#define __SMU_DUMMY_MAP(type) #type -static const char* __smu_message_names[] = { - SMU_MESSAGE_TYPES -}; - -static const char *smu_get_message_name(struct smu_context *smu, - enum smu_message_type type) -{ - if (type < 0 || type >= SMU_MSG_MAX_COUNT) - return "unknown smu message"; - - return __smu_message_names[type]; -} - -static void smu_cmn_send_msg_without_waiting(struct smu_context *smu, - uint16_t msg) -{ - struct amdgpu_device *adev = smu->adev; - - WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); -} - -static void smu_cmn_read_arg(struct smu_context *smu, - uint32_t *arg) -{ - struct amdgpu_device *adev = smu->adev; - - *arg = RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_82); -} - -static int smu_cmn_wait_for_response(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t cur_value, i, timeout = adev->usec_timeout * 10; - - for (i = 0; i < timeout; i++) { - cur_value = RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90); - if ((cur_value & MP1_C2PMSG_90__CONTENT_MASK) != 0) - return cur_value == 0x1 ? 0 : -EIO; - - udelay(1); - } - - /* timeout means wrong logic */ - if (i == timeout) - return -ETIME; - - return RREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90) == 0x1 ? 0 : -EIO; -} - -int smu_cmn_send_smc_msg_with_param(struct smu_context *smu, - enum smu_message_type msg, - uint32_t param, - uint32_t *read_arg) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0, index = 0; - - index = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_MSG, - msg); - if (index < 0) - return index == -EACCES ? 0 : index; - - mutex_lock(&smu->message_lock); - ret = smu_cmn_wait_for_response(smu); - if (ret) { - dev_err(adev->dev, "Msg issuing pre-check failed and " - "SMU may be not in the right state!\n"); - goto out; - } - - WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - WREG32_SOC15_NO_KIQ(MP1, 0, mmMP1_SMN_C2PMSG_82, param); - - smu_cmn_send_msg_without_waiting(smu, (uint16_t)index); - - ret = smu_cmn_wait_for_response(smu); - if (ret) { - dev_err(adev->dev, "failed send message: %10s (%d) \tparam: 0x%08x response %#x\n", - smu_get_message_name(smu, msg), index, param, ret); - goto out; - } - - if (read_arg) - smu_cmn_read_arg(smu, read_arg); - -out: - mutex_unlock(&smu->message_lock); - return ret; -} - -int smu_cmn_send_smc_msg(struct smu_context *smu, - enum smu_message_type msg, - uint32_t *read_arg) -{ - return smu_cmn_send_smc_msg_with_param(smu, - msg, - 0, - read_arg); -} - -int smu_cmn_to_asic_specific_index(struct smu_context *smu, - enum smu_cmn2asic_mapping_type type, - uint32_t index) -{ - struct cmn2asic_msg_mapping msg_mapping; - struct cmn2asic_mapping mapping; - - switch (type) { - case CMN2ASIC_MAPPING_MSG: - if (index >= SMU_MSG_MAX_COUNT || - !smu->message_map) - return -EINVAL; - - msg_mapping = smu->message_map[index]; - if (!msg_mapping.valid_mapping) - return -EINVAL; - - if (amdgpu_sriov_vf(smu->adev) && - !msg_mapping.valid_in_vf) - return -EACCES; - - return msg_mapping.map_to; - - case CMN2ASIC_MAPPING_CLK: - if (index >= SMU_CLK_COUNT || - !smu->clock_map) - return -EINVAL; - - mapping = smu->clock_map[index]; - if (!mapping.valid_mapping) - return -EINVAL; - - return mapping.map_to; - - case CMN2ASIC_MAPPING_FEATURE: - if (index >= SMU_FEATURE_COUNT || - !smu->feature_map) - return -EINVAL; - - mapping = smu->feature_map[index]; - if (!mapping.valid_mapping) - return -EINVAL; - - return mapping.map_to; - - case CMN2ASIC_MAPPING_TABLE: - if (index >= SMU_TABLE_COUNT || - !smu->table_map) - return -EINVAL; - - mapping = smu->table_map[index]; - if (!mapping.valid_mapping) - return -EINVAL; - - return mapping.map_to; - - case CMN2ASIC_MAPPING_PWR: - if (index >= SMU_POWER_SOURCE_COUNT || - !smu->pwr_src_map) - return -EINVAL; - - mapping = smu->pwr_src_map[index]; - if (!mapping.valid_mapping) - return -EINVAL; - - return mapping.map_to; - - case CMN2ASIC_MAPPING_WORKLOAD: - if (index > PP_SMC_POWER_PROFILE_CUSTOM || - !smu->workload_map) - return -EINVAL; - - mapping = smu->workload_map[index]; - if (!mapping.valid_mapping) - return -EINVAL; - - return mapping.map_to; - - default: - return -EINVAL; - } -} - -int smu_cmn_feature_is_supported(struct smu_context *smu, - enum smu_feature_mask mask) -{ - struct smu_feature *feature = &smu->smu_feature; - int feature_id; - int ret = 0; - - feature_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_FEATURE, - mask); - if (feature_id < 0) - return 0; - - WARN_ON(feature_id > feature->feature_num); - - mutex_lock(&feature->mutex); - ret = test_bit(feature_id, feature->supported); - mutex_unlock(&feature->mutex); - - return ret; -} - -int smu_cmn_feature_is_enabled(struct smu_context *smu, - enum smu_feature_mask mask) -{ - struct smu_feature *feature = &smu->smu_feature; - int feature_id; - int ret = 0; - - if (smu->is_apu) - return 1; - feature_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_FEATURE, - mask); - if (feature_id < 0) - return 0; - - WARN_ON(feature_id > feature->feature_num); - - mutex_lock(&feature->mutex); - ret = test_bit(feature_id, feature->enabled); - mutex_unlock(&feature->mutex); - - return ret; -} - -bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, - enum smu_clk_type clk_type) -{ - enum smu_feature_mask feature_id = 0; - - switch (clk_type) { - case SMU_MCLK: - case SMU_UCLK: - feature_id = SMU_FEATURE_DPM_UCLK_BIT; - break; - case SMU_GFXCLK: - case SMU_SCLK: - feature_id = SMU_FEATURE_DPM_GFXCLK_BIT; - break; - case SMU_SOCCLK: - feature_id = SMU_FEATURE_DPM_SOCCLK_BIT; - break; - default: - return true; - } - - if (!smu_cmn_feature_is_enabled(smu, feature_id)) - return false; - - return true; -} - -int smu_cmn_get_enabled_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num) -{ - uint32_t feature_mask_high = 0, feature_mask_low = 0; - struct smu_feature *feature = &smu->smu_feature; - int ret = 0; - - if (!feature_mask || num < 2) - return -EINVAL; - - if (bitmap_empty(feature->enabled, feature->feature_num)) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesHigh, &feature_mask_high); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetEnabledSmuFeaturesLow, &feature_mask_low); - if (ret) - return ret; - - feature_mask[0] = feature_mask_low; - feature_mask[1] = feature_mask_high; - } else { - bitmap_copy((unsigned long *)feature_mask, feature->enabled, - feature->feature_num); - } - - return ret; -} - -static int smu_cmn_feature_update_enable_state(struct smu_context *smu, - uint64_t feature_mask, - bool enabled) -{ - struct smu_feature *feature = &smu->smu_feature; - int ret = 0; - - if (enabled) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_EnableSmuFeaturesLow, - lower_32_bits(feature_mask), - NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_EnableSmuFeaturesHigh, - upper_32_bits(feature_mask), - NULL); - if (ret) - return ret; - } else { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_DisableSmuFeaturesLow, - lower_32_bits(feature_mask), - NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_DisableSmuFeaturesHigh, - upper_32_bits(feature_mask), - NULL); - if (ret) - return ret; - } - - mutex_lock(&feature->mutex); - if (enabled) - bitmap_or(feature->enabled, feature->enabled, - (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - else - bitmap_andnot(feature->enabled, feature->enabled, - (unsigned long *)(&feature_mask), SMU_FEATURE_MAX); - mutex_unlock(&feature->mutex); - - return ret; -} - -int smu_cmn_feature_set_enabled(struct smu_context *smu, - enum smu_feature_mask mask, - bool enable) -{ - struct smu_feature *feature = &smu->smu_feature; - int feature_id; - - feature_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_FEATURE, - mask); - if (feature_id < 0) - return -EINVAL; - - WARN_ON(feature_id > feature->feature_num); - - return smu_cmn_feature_update_enable_state(smu, - 1ULL << feature_id, - enable); -} - -#undef __SMU_DUMMY_MAP -#define __SMU_DUMMY_MAP(fea) #fea -static const char* __smu_feature_names[] = { - SMU_FEATURE_MASKS -}; - -static const char *smu_get_feature_name(struct smu_context *smu, - enum smu_feature_mask feature) -{ - if (feature < 0 || feature >= SMU_FEATURE_COUNT) - return "unknown smu feature"; - return __smu_feature_names[feature]; -} - -size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, - char *buf) -{ - uint32_t feature_mask[2] = { 0 }; - int32_t feature_index = 0; - uint32_t count = 0; - uint32_t sort_feature[SMU_FEATURE_COUNT]; - uint64_t hw_feature_count = 0; - size_t size = 0; - int ret = 0, i; - - ret = smu_cmn_get_enabled_mask(smu, - feature_mask, - 2); - if (ret) - return 0; - - size = sprintf(buf + size, "features high: 0x%08x low: 0x%08x\n", - feature_mask[1], feature_mask[0]); - - for (i = 0; i < SMU_FEATURE_COUNT; i++) { - feature_index = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_FEATURE, - i); - if (feature_index < 0) - continue; - sort_feature[feature_index] = i; - hw_feature_count++; - } - - for (i = 0; i < hw_feature_count; i++) { - size += sprintf(buf + size, "%02d. %-20s (%2d) : %s\n", - count++, - smu_get_feature_name(smu, sort_feature[i]), - i, - !!smu_cmn_feature_is_enabled(smu, sort_feature[i]) ? - "enabled" : "disabled"); - } - - return size; -} - -int smu_cmn_set_pp_feature_mask(struct smu_context *smu, - uint64_t new_mask) -{ - int ret = 0; - uint32_t feature_mask[2] = { 0 }; - uint64_t feature_2_enabled = 0; - uint64_t feature_2_disabled = 0; - uint64_t feature_enables = 0; - - ret = smu_cmn_get_enabled_mask(smu, - feature_mask, - 2); - if (ret) - return ret; - - feature_enables = ((uint64_t)feature_mask[1] << 32 | - (uint64_t)feature_mask[0]); - - feature_2_enabled = ~feature_enables & new_mask; - feature_2_disabled = feature_enables & ~new_mask; - - if (feature_2_enabled) { - ret = smu_cmn_feature_update_enable_state(smu, - feature_2_enabled, - true); - if (ret) - return ret; - } - if (feature_2_disabled) { - ret = smu_cmn_feature_update_enable_state(smu, - feature_2_disabled, - false); - if (ret) - return ret; - } - - return ret; -} - -int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, - enum smu_feature_mask mask) -{ - uint64_t features_to_disable = U64_MAX; - int skipped_feature_id; - - skipped_feature_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_FEATURE, - mask); - if (skipped_feature_id < 0) - return -EINVAL; - - features_to_disable &= ~(1ULL << skipped_feature_id); - - return smu_cmn_feature_update_enable_state(smu, - features_to_disable, - 0); -} - -int smu_cmn_get_smc_version(struct smu_context *smu, - uint32_t *if_version, - uint32_t *smu_version) -{ - int ret = 0; - - if (!if_version && !smu_version) - return -EINVAL; - - if (smu->smc_fw_if_version && smu->smc_fw_version) - { - if (if_version) - *if_version = smu->smc_fw_if_version; - - if (smu_version) - *smu_version = smu->smc_fw_version; - - return 0; - } - - if (if_version) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetDriverIfVersion, if_version); - if (ret) - return ret; - - smu->smc_fw_if_version = *if_version; - } - - if (smu_version) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_GetSmuVersion, smu_version); - if (ret) - return ret; - - smu->smc_fw_version = *smu_version; - } - - return ret; -} - -int smu_cmn_update_table(struct smu_context *smu, - enum smu_table_id table_index, - int argument, - void *table_data, - bool drv2smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct amdgpu_device *adev = smu->adev; - struct smu_table *table = &smu_table->driver_table; - int table_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_TABLE, - table_index); - uint32_t table_size; - int ret = 0; - if (!table_data || table_id >= SMU_TABLE_COUNT || table_id < 0) - return -EINVAL; - - table_size = smu_table->tables[table_index].size; - - if (drv2smu) { - memcpy(table->cpu_addr, table_data, table_size); - /* - * Flush hdp cache: to guard the content seen by - * GPU is consitent with CPU. - */ - amdgpu_asic_flush_hdp(adev, NULL); - } - - ret = smu_cmn_send_smc_msg_with_param(smu, drv2smu ? - SMU_MSG_TransferTableDram2Smu : - SMU_MSG_TransferTableSmu2Dram, - table_id | ((argument & 0xFFFF) << 16), - NULL); - if (ret) - return ret; - - if (!drv2smu) { - amdgpu_asic_flush_hdp(adev, NULL); - memcpy(table_data, table->cpu_addr, table_size); - } - - return 0; -} - -int smu_cmn_write_watermarks_table(struct smu_context *smu) -{ - void *watermarks_table = smu->smu_table.watermarks_table; - - if (!watermarks_table) - return -EINVAL; - - return smu_cmn_update_table(smu, - SMU_TABLE_WATERMARKS, - 0, - watermarks_table, - true); -} - -int smu_cmn_write_pptable(struct smu_context *smu) -{ - void *pptable = smu->smu_table.driver_pptable; - - return smu_cmn_update_table(smu, - SMU_TABLE_PPTABLE, - 0, - pptable, - true); -} - -int smu_cmn_get_metrics_table_locked(struct smu_context *smu, - void *metrics_table, - bool bypass_cache) -{ - struct smu_table_context *smu_table= &smu->smu_table; - uint32_t table_size = - smu_table->tables[SMU_TABLE_SMU_METRICS].size; - int ret = 0; - - if (bypass_cache || - !smu_table->metrics_time || - time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(1))) { - ret = smu_cmn_update_table(smu, - SMU_TABLE_SMU_METRICS, - 0, - smu_table->metrics_table, - false); - if (ret) { - dev_info(smu->adev->dev, "Failed to export SMU metrics table!\n"); - return ret; - } - smu_table->metrics_time = jiffies; - } - - if (metrics_table) - memcpy(metrics_table, smu_table->metrics_table, table_size); - - return 0; -} - -int smu_cmn_get_metrics_table(struct smu_context *smu, - void *metrics_table, - bool bypass_cache) -{ - int ret = 0; - - mutex_lock(&smu->metrics_lock); - ret = smu_cmn_get_metrics_table_locked(smu, - metrics_table, - bypass_cache); - mutex_unlock(&smu->metrics_lock); - - return ret; -} diff --git a/drivers/gpu/drm/amd/powerplay/smu_cmn.h b/drivers/gpu/drm/amd/powerplay/smu_cmn.h deleted file mode 100644 index 6d00ad740c27..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smu_cmn.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2020 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SMU_CMN_H__ -#define __SMU_CMN_H__ - -#include "amdgpu_smu.h" - -#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, - uint32_t *read_arg); - -int smu_cmn_send_smc_msg(struct smu_context *smu, - enum smu_message_type msg, - uint32_t *read_arg); - -int smu_cmn_to_asic_specific_index(struct smu_context *smu, - enum smu_cmn2asic_mapping_type type, - uint32_t index); - -int smu_cmn_feature_is_supported(struct smu_context *smu, - enum smu_feature_mask mask); - -int smu_cmn_feature_is_enabled(struct smu_context *smu, - enum smu_feature_mask mask); - -bool smu_cmn_clk_dpm_is_enabled(struct smu_context *smu, - enum smu_clk_type clk_type); - -int smu_cmn_get_enabled_mask(struct smu_context *smu, - uint32_t *feature_mask, - uint32_t num); - -int smu_cmn_feature_set_enabled(struct smu_context *smu, - enum smu_feature_mask mask, - bool enable); - -size_t smu_cmn_get_pp_feature_mask(struct smu_context *smu, - char *buf); - -int smu_cmn_set_pp_feature_mask(struct smu_context *smu, - uint64_t new_mask); - -int smu_cmn_disable_all_features_with_exception(struct smu_context *smu, - enum smu_feature_mask mask); - -int smu_cmn_get_smc_version(struct smu_context *smu, - uint32_t *if_version, - uint32_t *smu_version); - -int smu_cmn_update_table(struct smu_context *smu, - enum smu_table_id table_index, - int argument, - void *table_data, - bool drv2smu); - -int smu_cmn_write_watermarks_table(struct smu_context *smu); - -int smu_cmn_write_pptable(struct smu_context *smu); - -int smu_cmn_get_metrics_table_locked(struct smu_context *smu, - void *metrics_table, - bool bypass_cache); - -int smu_cmn_get_metrics_table(struct smu_context *smu, - void *metrics_table, - bool bypass_cache); - -#endif -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_internal.h b/drivers/gpu/drm/amd/powerplay/smu_internal.h deleted file mode 100644 index 264073d4e263..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smu_internal.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SMU_INTERNAL_H__ -#define __SMU_INTERNAL_H__ - -#include "amdgpu_smu.h" - -#if defined(SWSMU_CODE_LAYER_L1) - -#define smu_ppt_funcs(intf, ret, smu, args...) \ - ((smu)->ppt_funcs ? ((smu)->ppt_funcs->intf ? (smu)->ppt_funcs->intf(smu, ##args) : ret) : -EINVAL) - -#define smu_init_microcode(smu) smu_ppt_funcs(init_microcode, 0, smu) -#define smu_fini_microcode(smu) smu_ppt_funcs(fini_microcode, 0, smu) -#define smu_init_smc_tables(smu) smu_ppt_funcs(init_smc_tables, 0, smu) -#define smu_fini_smc_tables(smu) smu_ppt_funcs(fini_smc_tables, 0, smu) -#define smu_init_power(smu) smu_ppt_funcs(init_power, 0, smu) -#define smu_fini_power(smu) smu_ppt_funcs(fini_power, 0, smu) -#define smu_setup_pptable(smu) smu_ppt_funcs(setup_pptable, 0, smu) -#define smu_powergate_sdma(smu, gate) smu_ppt_funcs(powergate_sdma, 0, smu, gate) -#define smu_get_vbios_bootup_values(smu) smu_ppt_funcs(get_vbios_bootup_values, 0, smu) -#define smu_check_fw_version(smu) smu_ppt_funcs(check_fw_version, 0, smu) -#define smu_write_pptable(smu) smu_ppt_funcs(write_pptable, 0, smu) -#define smu_set_min_dcef_deep_sleep(smu, clk) smu_ppt_funcs(set_min_dcef_deep_sleep, 0, smu, clk) -#define smu_set_driver_table_location(smu) smu_ppt_funcs(set_driver_table_location, 0, smu) -#define smu_set_tool_table_location(smu) smu_ppt_funcs(set_tool_table_location, 0, smu) -#define smu_notify_memory_pool_location(smu) smu_ppt_funcs(notify_memory_pool_location, 0, smu) -#define smu_gfx_off_control(smu, enable) smu_ppt_funcs(gfx_off_control, 0, smu, enable) -#define smu_get_gfx_off_status(smu) smu_ppt_funcs(get_gfx_off_status, 0, smu) -#define smu_set_last_dcef_min_deep_sleep_clk(smu) smu_ppt_funcs(set_last_dcef_min_deep_sleep_clk, 0, smu) -#define smu_system_features_control(smu, en) smu_ppt_funcs(system_features_control, 0, smu, en) -#define smu_init_max_sustainable_clocks(smu) smu_ppt_funcs(init_max_sustainable_clocks, 0, smu) -#define smu_set_default_od_settings(smu) smu_ppt_funcs(set_default_od_settings, 0, smu) -#define smu_send_smc_msg_with_param(smu, msg, param, read_arg) smu_ppt_funcs(send_smc_msg_with_param, 0, smu, msg, param, read_arg) -#define smu_send_smc_msg(smu, msg, read_arg) smu_ppt_funcs(send_smc_msg, 0, smu, msg, read_arg) -#define smu_init_display_count(smu, count) smu_ppt_funcs(init_display_count, 0, smu, count) -#define smu_feature_set_allowed_mask(smu) smu_ppt_funcs(set_allowed_mask, 0, smu) -#define smu_feature_get_enabled_mask(smu, mask, num) smu_ppt_funcs(get_enabled_mask, 0, smu, mask, num) -#define smu_feature_is_enabled(smu, mask) smu_ppt_funcs(feature_is_enabled, 0, smu, mask) -#define smu_disable_all_features_with_exception(smu, mask) smu_ppt_funcs(disable_all_features_with_exception, 0, smu, mask) -#define smu_is_dpm_running(smu) smu_ppt_funcs(is_dpm_running, 0 , smu) -#define smu_notify_display_change(smu) smu_ppt_funcs(notify_display_change, 0, smu) -#define smu_populate_umd_state_clk(smu) smu_ppt_funcs(populate_umd_state_clk, 0, smu) -#define smu_set_default_od8_settings(smu) smu_ppt_funcs(set_default_od8_settings, 0, smu) -#define smu_enable_thermal_alert(smu) smu_ppt_funcs(enable_thermal_alert, 0, smu) -#define smu_disable_thermal_alert(smu) smu_ppt_funcs(disable_thermal_alert, 0, smu) -#define smu_smc_read_sensor(smu, sensor, data, size) smu_ppt_funcs(read_sensor, -EINVAL, smu, sensor, data, size) -#define smu_pre_display_config_changed(smu) smu_ppt_funcs(pre_display_config_changed, 0, smu) -#define smu_display_config_changed(smu) smu_ppt_funcs(display_config_changed, 0 , smu) -#define smu_apply_clocks_adjust_rules(smu) smu_ppt_funcs(apply_clocks_adjust_rules, 0, smu) -#define smu_notify_smc_display_config(smu) smu_ppt_funcs(notify_smc_display_config, 0, smu) -#define smu_set_cpu_power_state(smu) smu_ppt_funcs(set_cpu_power_state, 0, smu) -#define smu_run_btc(smu) smu_ppt_funcs(run_btc, 0, smu) -#define smu_get_allowed_feature_mask(smu, feature_mask, num) smu_ppt_funcs(get_allowed_feature_mask, 0, smu, feature_mask, num) -#define smu_store_cc6_data(smu, st, cc6_dis, pst_dis, pst_sw_dis) smu_ppt_funcs(store_cc6_data, 0, smu, st, cc6_dis, pst_dis, pst_sw_dis) -#define smu_get_dal_power_level(smu, clocks) smu_ppt_funcs(get_dal_power_level, 0, smu, clocks) -#define smu_get_perf_level(smu, designation, level) smu_ppt_funcs(get_perf_level, 0, smu, designation, level) -#define smu_get_current_shallow_sleep_clocks(smu, clocks) smu_ppt_funcs(get_current_shallow_sleep_clocks, 0, smu, clocks) -#define smu_set_watermarks_table(smu, clock_ranges) smu_ppt_funcs(set_watermarks_table, 0, smu, clock_ranges) -#define smu_thermal_temperature_range_update(smu, range, rw) smu_ppt_funcs(thermal_temperature_range_update, 0, smu, range, rw) -#define smu_register_irq_handler(smu) smu_ppt_funcs(register_irq_handler, 0, smu) -#define smu_get_dpm_ultimate_freq(smu, param, min, max) smu_ppt_funcs(get_dpm_ultimate_freq, 0, smu, param, min, max) -#define smu_asic_set_performance_level(smu, level) smu_ppt_funcs(set_performance_level, -EINVAL, smu, level) -#define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu) -#define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap) -#define smu_disable_umc_cdr_12gbps_workaround(smu) smu_ppt_funcs(disable_umc_cdr_12gbps_workaround, 0, smu) -#define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src) -#define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control) -#define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control) -#define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu) -#define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu) -#define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) -#define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) -#define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) - -#endif -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c b/drivers/gpu/drm/amd/powerplay/smu_v11_0.c deleted file mode 100644 index ff574ebc179e..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smu_v11_0.c +++ /dev/null @@ -1,1987 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#define SMU_11_0_PARTIAL_PPTABLE -#define SWSMU_CODE_LAYER_L3 - -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "atomfirmware.h" -#include "amdgpu_atomfirmware.h" -#include "amdgpu_atombios.h" -#include "smu_v11_0.h" -#include "soc15_common.h" -#include "atom.h" -#include "amdgpu_ras.h" -#include "smu_cmn.h" - -#include "asic_reg/thm/thm_11_0_2_offset.h" -#include "asic_reg/thm/thm_11_0_2_sh_mask.h" -#include "asic_reg/mp/mp_11_0_offset.h" -#include "asic_reg/mp/mp_11_0_sh_mask.h" -#include "asic_reg/smuio/smuio_11_0_0_offset.h" -#include "asic_reg/smuio/smuio_11_0_0_sh_mask.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -MODULE_FIRMWARE("amdgpu/arcturus_smc.bin"); -MODULE_FIRMWARE("amdgpu/navi10_smc.bin"); -MODULE_FIRMWARE("amdgpu/navi14_smc.bin"); -MODULE_FIRMWARE("amdgpu/navi12_smc.bin"); -MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin"); -MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin"); - -#define SMU11_VOLTAGE_SCALE 4 - -#define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500 //500ms - -#define LINK_WIDTH_MAX 6 -#define LINK_SPEED_MAX 3 - -#define smnPCIE_LC_LINK_WIDTH_CNTL 0x11140288 -#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L -#define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4 -#define smnPCIE_LC_SPEED_CNTL 0x11140290 -#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000 -#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE - -static int link_width[] = {0, 1, 2, 4, 8, 12, 16}; -static int link_speed[] = {25, 50, 80, 160}; - -int smu_v11_0_init_microcode(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - const char *chip_name; - char fw_name[30]; - int err = 0; - const struct smc_firmware_header_v1_0 *hdr; - const struct common_firmware_header *header; - struct amdgpu_firmware_info *ucode = NULL; - - switch (adev->asic_type) { - case CHIP_ARCTURUS: - chip_name = "arcturus"; - break; - case CHIP_NAVI10: - chip_name = "navi10"; - break; - case CHIP_NAVI14: - chip_name = "navi14"; - break; - case CHIP_NAVI12: - chip_name = "navi12"; - break; - case CHIP_SIENNA_CICHLID: - chip_name = "sienna_cichlid"; - break; - case CHIP_NAVY_FLOUNDER: - chip_name = "navy_flounder"; - break; - default: - dev_err(adev->dev, "Unsupported ASIC type %d\n", adev->asic_type); - return -EINVAL; - } - - snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name); - - err = request_firmware(&adev->pm.fw, fw_name, adev->dev); - if (err) - goto out; - err = amdgpu_ucode_validate(adev->pm.fw); - if (err) - goto out; - - hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; - amdgpu_ucode_print_smc_hdr(&hdr->header); - adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version); - - if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) { - ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC]; - ucode->ucode_id = AMDGPU_UCODE_ID_SMC; - ucode->fw = adev->pm.fw; - header = (const struct common_firmware_header *)ucode->fw->data; - adev->firmware.fw_size += - ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE); - } - -out: - if (err) { - DRM_ERROR("smu_v11_0: Failed to load firmware \"%s\"\n", - fw_name); - release_firmware(adev->pm.fw); - adev->pm.fw = NULL; - } - return err; -} - -void smu_v11_0_fini_microcode(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - - release_firmware(adev->pm.fw); - adev->pm.fw = NULL; - adev->pm.fw_version = 0; -} - -int smu_v11_0_load_microcode(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - const uint32_t *src; - const struct smc_firmware_header_v1_0 *hdr; - uint32_t addr_start = MP1_SRAM; - uint32_t i; - uint32_t smc_fw_size; - uint32_t mp1_fw_flags; - - hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; - src = (const uint32_t *)(adev->pm.fw->data + - le32_to_cpu(hdr->header.ucode_array_offset_bytes)); - smc_fw_size = hdr->header.ucode_size_bytes; - - for (i = 1; i < smc_fw_size/4 - 1; i++) { - WREG32_PCIE(addr_start, src[i]); - addr_start += 4; - } - - WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff), - 1 & MP1_SMN_PUB_CTRL__RESET_MASK); - WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff), - 1 & ~MP1_SMN_PUB_CTRL__RESET_MASK); - - for (i = 0; i < adev->usec_timeout; i++) { - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); - if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> - MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) - break; - udelay(1); - } - - if (i == adev->usec_timeout) - return -ETIME; - - return 0; -} - -int smu_v11_0_check_fw_status(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t mp1_fw_flags; - - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); - - if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> - MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) - return 0; - - return -EIO; -} - -int smu_v11_0_check_fw_version(struct smu_context *smu) -{ - uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; - int ret = 0; - - ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); - if (ret) - return ret; - - smu_major = (smu_version >> 16) & 0xffff; - smu_minor = (smu_version >> 8) & 0xff; - smu_debug = (smu_version >> 0) & 0xff; - - switch (smu->adev->asic_type) { - case CHIP_ARCTURUS: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT; - break; - case CHIP_NAVI10: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10; - break; - case CHIP_NAVI12: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12; - break; - case CHIP_NAVI14: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14; - break; - case CHIP_SIENNA_CICHLID: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid; - break; - case CHIP_NAVY_FLOUNDER: - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder; - break; - default: - dev_err(smu->adev->dev, "smu unsupported asic type:%d.\n", smu->adev->asic_type); - smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV; - break; - } - - /* - * 1. if_version mismatch is not critical as our fw is designed - * to be backward compatible. - * 2. New fw usually brings some optimizations. But that's visible - * only on the paired driver. - * Considering above, we just leave user a warning message instead - * of halt driver loading. - */ - if (if_version != smu->smc_driver_if_version) { - dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " - "smu fw version = 0x%08x (%d.%d.%d)\n", - smu->smc_driver_if_version, if_version, - smu_version, smu_major, smu_minor, smu_debug); - dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); - } - - return ret; -} - -static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t ppt_offset_bytes; - const struct smc_firmware_header_v2_0 *v2; - - v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data; - - ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes); - *size = le32_to_cpu(v2->ppt_size_bytes); - *table = (uint8_t *)v2 + ppt_offset_bytes; - - return 0; -} - -static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table, - uint32_t *size, uint32_t pptable_id) -{ - struct amdgpu_device *adev = smu->adev; - const struct smc_firmware_header_v2_1 *v2_1; - struct smc_soft_pptable_entry *entries; - uint32_t pptable_count = 0; - int i = 0; - - v2_1 = (const struct smc_firmware_header_v2_1 *) adev->pm.fw->data; - entries = (struct smc_soft_pptable_entry *) - ((uint8_t *)v2_1 + le32_to_cpu(v2_1->pptable_entry_offset)); - pptable_count = le32_to_cpu(v2_1->pptable_count); - for (i = 0; i < pptable_count; i++) { - if (le32_to_cpu(entries[i].id) == pptable_id) { - *table = ((uint8_t *)v2_1 + le32_to_cpu(entries[i].ppt_offset_bytes)); - *size = le32_to_cpu(entries[i].ppt_size_bytes); - break; - } - } - - if (i == pptable_count) - return -EINVAL; - - return 0; -} - -int smu_v11_0_setup_pptable(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - const struct smc_firmware_header_v1_0 *hdr; - int ret, index; - uint32_t size = 0; - uint16_t atom_table_size; - uint8_t frev, crev; - void *table; - uint16_t version_major, version_minor; - - hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data; - version_major = le16_to_cpu(hdr->header.header_version_major); - version_minor = le16_to_cpu(hdr->header.header_version_minor); - if ((version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) || - adev->asic_type == CHIP_NAVY_FLOUNDER) { - dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id); - switch (version_minor) { - case 0: - ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size); - break; - case 1: - ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size, - smu->smu_table.boot_values.pp_table_id); - break; - default: - ret = -EINVAL; - break; - } - if (ret) - return ret; - - } else { - dev_info(adev->dev, "use vbios provided pptable\n"); - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - powerplayinfo); - - ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev, - (uint8_t **)&table); - if (ret) - return ret; - size = atom_table_size; - } - - if (!smu->smu_table.power_play_table) - smu->smu_table.power_play_table = table; - if (!smu->smu_table.power_play_table_size) - smu->smu_table.power_play_table_size = size; - - return 0; -} - -int smu_v11_0_init_smc_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *tables = smu_table->tables; - int ret = 0; - - smu_table->driver_pptable = - kzalloc(tables[SMU_TABLE_PPTABLE].size, GFP_KERNEL); - if (!smu_table->driver_pptable) { - ret = -ENOMEM; - goto err0_out; - } - - smu_table->max_sustainable_clocks = - kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), GFP_KERNEL); - if (!smu_table->max_sustainable_clocks) { - ret = -ENOMEM; - goto err1_out; - } - - /* Arcturus does not support OVERDRIVE */ - if (tables[SMU_TABLE_OVERDRIVE].size) { - smu_table->overdrive_table = - kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL); - if (!smu_table->overdrive_table) { - ret = -ENOMEM; - goto err2_out; - } - - smu_table->boot_overdrive_table = - kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL); - if (!smu_table->boot_overdrive_table) { - ret = -ENOMEM; - goto err3_out; - } - } - - return 0; - -err3_out: - kfree(smu_table->overdrive_table); -err2_out: - kfree(smu_table->max_sustainable_clocks); -err1_out: - kfree(smu_table->driver_pptable); -err0_out: - return ret; -} - -int smu_v11_0_fini_smc_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_dpm_context *smu_dpm = &smu->smu_dpm; - - kfree(smu_table->gpu_metrics_table); - kfree(smu_table->boot_overdrive_table); - kfree(smu_table->overdrive_table); - kfree(smu_table->max_sustainable_clocks); - kfree(smu_table->driver_pptable); - smu_table->gpu_metrics_table = NULL; - smu_table->boot_overdrive_table = NULL; - smu_table->overdrive_table = NULL; - smu_table->max_sustainable_clocks = NULL; - smu_table->driver_pptable = NULL; - kfree(smu_table->hardcode_pptable); - smu_table->hardcode_pptable = NULL; - - kfree(smu_table->metrics_table); - kfree(smu_table->watermarks_table); - smu_table->metrics_table = NULL; - smu_table->watermarks_table = NULL; - smu_table->metrics_time = 0; - - kfree(smu_dpm->dpm_context); - kfree(smu_dpm->golden_dpm_context); - kfree(smu_dpm->dpm_current_power_state); - kfree(smu_dpm->dpm_request_power_state); - smu_dpm->dpm_context = NULL; - smu_dpm->golden_dpm_context = NULL; - smu_dpm->dpm_context_size = 0; - smu_dpm->dpm_current_power_state = NULL; - smu_dpm->dpm_request_power_state = NULL; - - return 0; -} - -int smu_v11_0_init_power(struct smu_context *smu) -{ - struct smu_power_context *smu_power = &smu->smu_power; - - if (smu_power->power_context || smu_power->power_context_size != 0) - return -EINVAL; - - smu_power->power_context = kzalloc(sizeof(struct smu_11_0_dpm_context), - GFP_KERNEL); - if (!smu_power->power_context) - return -ENOMEM; - smu_power->power_context_size = sizeof(struct smu_11_0_dpm_context); - - return 0; -} - -int smu_v11_0_fini_power(struct smu_context *smu) -{ - struct smu_power_context *smu_power = &smu->smu_power; - - if (!smu_power->power_context || smu_power->power_context_size == 0) - return -EINVAL; - - kfree(smu_power->power_context); - smu_power->power_context = NULL; - smu_power->power_context_size = 0; - - return 0; -} - -static int smu_v11_0_atom_get_smu_clockinfo(struct amdgpu_device *adev, - uint8_t clk_id, - uint8_t syspll_id, - uint32_t *clk_freq) -{ - struct atom_get_smu_clock_info_parameters_v3_1 input = {0}; - struct atom_get_smu_clock_info_output_parameters_v3_1 *output; - int ret, index; - - input.clk_id = clk_id; - input.syspll_id = syspll_id; - input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ; - index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1, - getsmuclockinfo); - - ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index, - (uint32_t *)&input); - if (ret) - return -EINVAL; - - output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input; - *clk_freq = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000; - - return 0; -} - -int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu) -{ - int ret, index; - uint16_t size; - uint8_t frev, crev; - struct atom_common_table_header *header; - struct atom_firmware_info_v3_3 *v_3_3; - struct atom_firmware_info_v3_1 *v_3_1; - - index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, - firmwareinfo); - - ret = amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev, - (uint8_t **)&header); - if (ret) - return ret; - - if (header->format_revision != 3) { - dev_err(smu->adev->dev, "unknown atom_firmware_info version! for smu11\n"); - return -EINVAL; - } - - switch (header->content_revision) { - case 0: - case 1: - case 2: - v_3_1 = (struct atom_firmware_info_v3_1 *)header; - smu->smu_table.boot_values.revision = v_3_1->firmware_revision; - smu->smu_table.boot_values.gfxclk = v_3_1->bootup_sclk_in10khz; - smu->smu_table.boot_values.uclk = v_3_1->bootup_mclk_in10khz; - smu->smu_table.boot_values.socclk = 0; - smu->smu_table.boot_values.dcefclk = 0; - smu->smu_table.boot_values.vddc = v_3_1->bootup_vddc_mv; - smu->smu_table.boot_values.vddci = v_3_1->bootup_vddci_mv; - smu->smu_table.boot_values.mvddc = v_3_1->bootup_mvddc_mv; - smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv; - smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id; - smu->smu_table.boot_values.pp_table_id = 0; - break; - case 3: - default: - v_3_3 = (struct atom_firmware_info_v3_3 *)header; - smu->smu_table.boot_values.revision = v_3_3->firmware_revision; - smu->smu_table.boot_values.gfxclk = v_3_3->bootup_sclk_in10khz; - smu->smu_table.boot_values.uclk = v_3_3->bootup_mclk_in10khz; - smu->smu_table.boot_values.socclk = 0; - smu->smu_table.boot_values.dcefclk = 0; - smu->smu_table.boot_values.vddc = v_3_3->bootup_vddc_mv; - smu->smu_table.boot_values.vddci = v_3_3->bootup_vddci_mv; - smu->smu_table.boot_values.mvddc = v_3_3->bootup_mvddc_mv; - smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv; - smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id; - smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id; - } - - smu->smu_table.boot_values.format_revision = header->format_revision; - smu->smu_table.boot_values.content_revision = header->content_revision; - - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL0_SOCCLK_ID, - (uint8_t)0, - &smu->smu_table.boot_values.socclk); - - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL0_DCEFCLK_ID, - (uint8_t)0, - &smu->smu_table.boot_values.dcefclk); - - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL0_ECLK_ID, - (uint8_t)0, - &smu->smu_table.boot_values.eclk); - - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL0_VCLK_ID, - (uint8_t)0, - &smu->smu_table.boot_values.vclk); - - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL0_DCLK_ID, - (uint8_t)0, - &smu->smu_table.boot_values.dclk); - - if ((smu->smu_table.boot_values.format_revision == 3) && - (smu->smu_table.boot_values.content_revision >= 2)) - smu_v11_0_atom_get_smu_clockinfo(smu->adev, - (uint8_t)SMU11_SYSPLL1_0_FCLK_ID, - (uint8_t)SMU11_SYSPLL1_2_ID, - &smu->smu_table.boot_values.fclk); - - return 0; -} - -int smu_v11_0_notify_memory_pool_location(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - struct smu_table *memory_pool = &smu_table->memory_pool; - int ret = 0; - uint64_t address; - uint32_t address_low, address_high; - - if (memory_pool->size == 0 || memory_pool->cpu_addr == NULL) - return ret; - - address = (uintptr_t)memory_pool->cpu_addr; - address_high = (uint32_t)upper_32_bits(address); - address_low = (uint32_t)lower_32_bits(address); - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetSystemVirtualDramAddrHigh, - address_high, - NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetSystemVirtualDramAddrLow, - address_low, - NULL); - if (ret) - return ret; - - address = memory_pool->mc_address; - address_high = (uint32_t)upper_32_bits(address); - address_low = (uint32_t)lower_32_bits(address); - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh, - address_high, NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow, - address_low, NULL); - if (ret) - return ret; - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize, - (uint32_t)memory_pool->size, NULL); - if (ret) - return ret; - - return ret; -} - -int smu_v11_0_set_min_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk) -{ - int ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetMinDeepSleepDcefclk, clk, NULL); - if (ret) - dev_err(smu->adev->dev, "SMU11 attempt to set divider for DCEFCLK Failed!"); - - return ret; -} - -int smu_v11_0_set_driver_table_location(struct smu_context *smu) -{ - struct smu_table *driver_table = &smu->smu_table.driver_table; - int ret = 0; - - if (driver_table->mc_address) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetDriverDramAddrHigh, - upper_32_bits(driver_table->mc_address), - NULL); - if (!ret) - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetDriverDramAddrLow, - lower_32_bits(driver_table->mc_address), - NULL); - } - - return ret; -} - -int smu_v11_0_set_tool_table_location(struct smu_context *smu) -{ - int ret = 0; - struct smu_table *tool_table = &smu->smu_table.tables[SMU_TABLE_PMSTATUSLOG]; - - if (tool_table->mc_address) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetToolsDramAddrHigh, - upper_32_bits(tool_table->mc_address), - NULL); - if (!ret) - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetToolsDramAddrLow, - lower_32_bits(tool_table->mc_address), - NULL); - } - - return ret; -} - -int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count) -{ - int ret = 0; - struct amdgpu_device *adev = smu->adev; - - /* Navy_Flounder do not support to change display num currently */ - if (adev->asic_type == CHIP_NAVY_FLOUNDER) - return 0; - - if (!smu->pm_enabled) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_NumOfDisplays, count, NULL); - return ret; -} - - -int smu_v11_0_set_allowed_mask(struct smu_context *smu) -{ - struct smu_feature *feature = &smu->smu_feature; - int ret = 0; - uint32_t feature_mask[2]; - - mutex_lock(&feature->mutex); - if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || feature->feature_num < 64) - goto failed; - - bitmap_copy((unsigned long *)feature_mask, feature->allowed, 64); - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskHigh, - feature_mask[1], NULL); - if (ret) - goto failed; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskLow, - feature_mask[0], NULL); - if (ret) - goto failed; - -failed: - mutex_unlock(&feature->mutex); - return ret; -} - -int smu_v11_0_system_features_control(struct smu_context *smu, - bool en) -{ - struct smu_feature *feature = &smu->smu_feature; - uint32_t feature_mask[2]; - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures : - SMU_MSG_DisableAllSmuFeatures), NULL); - if (ret) - return ret; - - bitmap_zero(feature->enabled, feature->feature_num); - bitmap_zero(feature->supported, feature->feature_num); - - if (en) { - ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - if (ret) - return ret; - - bitmap_copy(feature->enabled, (unsigned long *)&feature_mask, - feature->feature_num); - bitmap_copy(feature->supported, (unsigned long *)&feature_mask, - feature->feature_num); - } - - return ret; -} - -int smu_v11_0_notify_display_change(struct smu_context *smu) -{ - int ret = 0; - - if (!smu->pm_enabled) - return ret; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) && - smu->adev->gmc.vram_type == AMDGPU_VRAM_TYPE_HBM) - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1, NULL); - - return ret; -} - -static int -smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock, - enum smu_clk_type clock_select) -{ - int ret = 0; - int clk_id; - - if ((smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetDcModeMaxDpmFreq) < 0) || - (smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetMaxDpmFreq) < 0)) - return 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clock_select); - if (clk_id < 0) - return -EINVAL; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq, - clk_id << 16, clock); - if (ret) { - dev_err(smu->adev->dev, "[GetMaxSustainableClock] Failed to get max DC clock from SMC!"); - return ret; - } - - if (*clock != 0) - return 0; - - /* if DC limit is zero, return AC limit */ - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, - clk_id << 16, clock); - if (ret) { - dev_err(smu->adev->dev, "[GetMaxSustainableClock] failed to get max AC clock from SMC!"); - return ret; - } - - return 0; -} - -int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu) -{ - struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks = - smu->smu_table.max_sustainable_clocks; - int ret = 0; - - max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100; - max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100; - max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100; - max_sustainable_clocks->display_clock = 0xFFFFFFFF; - max_sustainable_clocks->phy_clock = 0xFFFFFFFF; - max_sustainable_clocks->pixel_clock = 0xFFFFFFFF; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->uclock), - SMU_UCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max UCLK from SMC!", - __func__); - return ret; - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) { - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->soc_clock), - SMU_SOCCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max SOCCLK from SMC!", - __func__); - return ret; - } - } - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) { - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->dcef_clock), - SMU_DCEFCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max DCEFCLK from SMC!", - __func__); - return ret; - } - - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->display_clock), - SMU_DISPCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max DISPCLK from SMC!", - __func__); - return ret; - } - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->phy_clock), - SMU_PHYCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max PHYCLK from SMC!", - __func__); - return ret; - } - ret = smu_v11_0_get_max_sustainable_clock(smu, - &(max_sustainable_clocks->pixel_clock), - SMU_PIXCLK); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get max PIXCLK from SMC!", - __func__); - return ret; - } - } - - if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock) - max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock; - - return 0; -} - -int smu_v11_0_get_current_power_limit(struct smu_context *smu, - uint32_t *power_limit) -{ - int power_src; - int ret = 0; - - if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) - return -EINVAL; - - power_src = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_PWR, - smu->adev->pm.ac_power ? - SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (power_src < 0) - return -EINVAL; - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetPptLimit, - power_src << 16, - power_limit); - if (ret) - dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__); - - return ret; -} - -int smu_v11_0_set_power_limit(struct smu_context *smu, uint32_t n) -{ - int ret = 0; - - if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) { - dev_err(smu->adev->dev, "Setting new power limit is not supported!\n"); - return -EOPNOTSUPP; - } - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, n, NULL); - if (ret) { - dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__); - return ret; - } - - smu->current_power_limit = n; - - return 0; -} - -int smu_v11_0_enable_thermal_alert(struct smu_context *smu) -{ - if (smu->smu_table.thermal_controller_type) - return amdgpu_irq_get(smu->adev, &smu->irq_source, 0); - - return 0; -} - -int smu_v11_0_disable_thermal_alert(struct smu_context *smu) -{ - return amdgpu_irq_put(smu->adev, &smu->irq_source, 0); -} - -static uint16_t convert_to_vddc(uint8_t vid) -{ - return (uint16_t) ((6200 - (vid * 25)) / SMU11_VOLTAGE_SCALE); -} - -int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t vdd = 0, val_vid = 0; - - if (!value) - return -EINVAL; - val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) & - SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >> - SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT; - - vdd = (uint32_t)convert_to_vddc((uint8_t)val_vid); - - *value = vdd; - - return 0; - -} - -int -smu_v11_0_display_clock_voltage_request(struct smu_context *smu, - struct pp_display_clock_request - *clock_req) -{ - enum amd_pp_clock_type clk_type = clock_req->clock_type; - int ret = 0; - enum smu_clk_type clk_select = 0; - uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000; - - if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) || - smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) { - switch (clk_type) { - case amd_pp_dcef_clock: - clk_select = SMU_DCEFCLK; - break; - case amd_pp_disp_clock: - clk_select = SMU_DISPCLK; - break; - case amd_pp_pixel_clock: - clk_select = SMU_PIXCLK; - break; - case amd_pp_phy_clock: - clk_select = SMU_PHYCLK; - break; - case amd_pp_mem_clock: - clk_select = SMU_UCLK; - break; - default: - dev_info(smu->adev->dev, "[%s] Invalid Clock Type!", __func__); - ret = -EINVAL; - break; - } - - if (ret) - goto failed; - - if (clk_select == SMU_UCLK && smu->disable_uclk_switch) - return 0; - - ret = smu_v11_0_set_hard_freq_limited_range(smu, clk_select, clk_freq, 0); - - if(clk_select == SMU_UCLK) - smu->hard_min_uclk_req_from_dal = clk_freq; - } - -failed: - return ret; -} - -int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable) -{ - int ret = 0; - struct amdgpu_device *adev = smu->adev; - - switch (adev->asic_type) { - case CHIP_NAVI10: - case CHIP_NAVI14: - case CHIP_NAVI12: - case CHIP_SIENNA_CICHLID: - case CHIP_NAVY_FLOUNDER: - if (!(adev->pm.pp_feature & PP_GFXOFF_MASK)) - return 0; - if (enable) - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); - else - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); - break; - default: - break; - } - - return ret; -} - -uint32_t -smu_v11_0_get_fan_control_mode(struct smu_context *smu) -{ - if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT)) - return AMD_FAN_CTRL_MANUAL; - else - return AMD_FAN_CTRL_AUTO; -} - -static int -smu_v11_0_auto_fan_control(struct smu_context *smu, bool auto_fan_control) -{ - int ret = 0; - - if (!smu_cmn_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT)) - return 0; - - ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, auto_fan_control); - if (ret) - dev_err(smu->adev->dev, "[%s]%s smc FAN CONTROL feature failed!", - __func__, (auto_fan_control ? "Start" : "Stop")); - - return ret; -} - -static int -smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode) -{ - struct amdgpu_device *adev = smu->adev; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, TMIN, 0)); - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2), - CG_FDO_CTRL2, FDO_PWM_MODE, mode)); - - return 0; -} - -int -smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t duty100, duty; - uint64_t tmp64; - - if (speed > 100) - speed = 100; - - if (smu_v11_0_auto_fan_control(smu, 0)) - return -EINVAL; - - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - if (!duty100) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); - - return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC); -} - -int -smu_v11_0_set_fan_control_mode(struct smu_context *smu, - uint32_t mode) -{ - int ret = 0; - - switch (mode) { - case AMD_FAN_CTRL_NONE: - ret = smu_v11_0_set_fan_speed_percent(smu, 100); - break; - case AMD_FAN_CTRL_MANUAL: - ret = smu_v11_0_auto_fan_control(smu, 0); - break; - case AMD_FAN_CTRL_AUTO: - ret = smu_v11_0_auto_fan_control(smu, 1); - break; - default: - break; - } - - if (ret) { - dev_err(smu->adev->dev, "[%s]Set fan control mode failed!", __func__); - return -EINVAL; - } - - return ret; -} - -int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, - uint32_t speed) -{ - struct amdgpu_device *adev = smu->adev; - int ret; - uint32_t tach_period, crystal_clock_freq; - - if (!speed) - return -EINVAL; - - ret = smu_v11_0_auto_fan_control(smu, 0); - if (ret) - return ret; - - crystal_clock_freq = amdgpu_asic_get_xclk(adev); - tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); - WREG32_SOC15(THM, 0, mmCG_TACH_CTRL, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), - CG_TACH_CTRL, TARGET_PERIOD, - tach_period)); - - ret = smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM); - - return ret; -} - -int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, - uint32_t pstate) -{ - int ret = 0; - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetXgmiMode, - pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3, - NULL); - return ret; -} - -static int smu_v11_0_set_irq_state(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - unsigned tyep, - enum amdgpu_interrupt_state state) -{ - struct smu_context *smu = &adev->smu; - uint32_t low, high; - uint32_t val = 0; - - switch (state) { - case AMDGPU_IRQ_STATE_DISABLE: - /* For THM irqs */ - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 1); - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0); - - /* For MP1 SW irqs */ - val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1); - WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val); - - break; - case AMDGPU_IRQ_STATE_ENABLE: - /* For THM irqs */ - low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP, - smu->thermal_range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES); - high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP, - smu->thermal_range.software_shutdown_temp); - - val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff)); - val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); - - val = (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT); - val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT); - WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val); - - /* For MP1 SW irqs */ - val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0); - WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT, val); - - val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); - val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0); - WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val); - - break; - default: - break; - } - - return 0; -} - -static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu) -{ - return smu_cmn_send_smc_msg(smu, - SMU_MSG_ReenableAcDcInterrupt, - NULL); -} - -#define THM_11_0__SRCID__THM_DIG_THERM_L2H 0 /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH */ -#define THM_11_0__SRCID__THM_DIG_THERM_H2L 1 /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL */ - -#define SMUIO_11_0__SRCID__SMUIO_GPIO19 83 - -static int smu_v11_0_irq_process(struct amdgpu_device *adev, - struct amdgpu_irq_src *source, - struct amdgpu_iv_entry *entry) -{ - struct smu_context *smu = &adev->smu; - uint32_t client_id = entry->client_id; - uint32_t src_id = entry->src_id; - /* - * ctxid is used to distinguish different - * events for SMCToHost interrupt. - */ - uint32_t ctxid = entry->src_data[0]; - uint32_t data; - - if (client_id == SOC15_IH_CLIENTID_THM) { - switch (src_id) { - case THM_11_0__SRCID__THM_DIG_THERM_L2H: - dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n"); - /* - * SW CTF just occurred. - * Try to do a graceful shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n"); - orderly_poweroff(true); - break; - case THM_11_0__SRCID__THM_DIG_THERM_H2L: - dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n"); - break; - default: - dev_emerg(adev->dev, "ERROR: GPU under temperature range unknown src id (%d)\n", - src_id); - break; - } - } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) { - dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n"); - /* - * HW CTF just occurred. Shutdown to prevent further damage. - */ - dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n"); - orderly_poweroff(true); - } else if (client_id == SOC15_IH_CLIENTID_MP1) { - if (src_id == 0xfe) { - /* ACK SMUToHost interrupt */ - data = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL); - data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1); - WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, data); - - switch (ctxid) { - case 0x3: - dev_dbg(adev->dev, "Switched to AC mode!\n"); - smu_v11_0_ack_ac_dc_interrupt(&adev->smu); - break; - case 0x4: - dev_dbg(adev->dev, "Switched to DC mode!\n"); - 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; - - if (__ratelimit(&adev->throttling_logging_rs)) - schedule_work(&smu->throttling_logging_work); - - break; - } - } - } - - return 0; -} - -static const struct amdgpu_irq_src_funcs smu_v11_0_irq_funcs = -{ - .set = smu_v11_0_set_irq_state, - .process = smu_v11_0_irq_process, -}; - -int smu_v11_0_register_irq_handler(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - struct amdgpu_irq_src *irq_src = &smu->irq_source; - int ret = 0; - - irq_src->num_types = 1; - irq_src->funcs = &smu_v11_0_irq_funcs; - - ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, - THM_11_0__SRCID__THM_DIG_THERM_L2H, - irq_src); - if (ret) - return ret; - - ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM, - THM_11_0__SRCID__THM_DIG_THERM_H2L, - irq_src); - if (ret) - return ret; - - /* Register CTF(GPIO_19) interrupt */ - ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_ROM_SMUIO, - SMUIO_11_0__SRCID__SMUIO_GPIO19, - irq_src); - if (ret) - return ret; - - ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1, - 0xfe, - irq_src); - if (ret) - return ret; - - return ret; -} - -int smu_v11_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu, - struct pp_smu_nv_clock_table *max_clocks) -{ - struct smu_table_context *table_context = &smu->smu_table; - struct smu_11_0_max_sustainable_clocks *sustainable_clocks = NULL; - - if (!max_clocks || !table_context->max_sustainable_clocks) - return -EINVAL; - - sustainable_clocks = table_context->max_sustainable_clocks; - - max_clocks->dcfClockInKhz = - (unsigned int) sustainable_clocks->dcef_clock * 1000; - max_clocks->displayClockInKhz = - (unsigned int) sustainable_clocks->display_clock * 1000; - max_clocks->phyClockInKhz = - (unsigned int) sustainable_clocks->phy_clock * 1000; - max_clocks->pixelClockInKhz = - (unsigned int) sustainable_clocks->pixel_clock * 1000; - max_clocks->uClockInKhz = - (unsigned int) sustainable_clocks->uclock * 1000; - max_clocks->socClockInKhz = - (unsigned int) sustainable_clocks->soc_clock * 1000; - max_clocks->dscClockInKhz = 0; - max_clocks->dppClockInKhz = 0; - max_clocks->fabricClockInKhz = 0; - - return 0; -} - -int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL); - - return ret; -} - -static int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu, enum smu_v11_0_baco_seq baco_seq) -{ - return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL); -} - -bool smu_v11_0_baco_is_support(struct smu_context *smu) -{ - struct smu_baco_context *smu_baco = &smu->smu_baco; - bool baco_support; - - mutex_lock(&smu_baco->mutex); - baco_support = smu_baco->platform_support; - mutex_unlock(&smu_baco->mutex); - - if (!baco_support) - return false; - - /* Arcturus does not support this bit mask */ - if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) && - !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT)) - return false; - - return true; -} - -enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu) -{ - struct smu_baco_context *smu_baco = &smu->smu_baco; - enum smu_baco_state baco_state; - - mutex_lock(&smu_baco->mutex); - baco_state = smu_baco->state; - mutex_unlock(&smu_baco->mutex); - - return baco_state; -} - -int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state) -{ - struct smu_baco_context *smu_baco = &smu->smu_baco; - struct amdgpu_device *adev = smu->adev; - struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - uint32_t data; - int ret = 0; - - if (smu_v11_0_baco_get_state(smu) == state) - return 0; - - mutex_lock(&smu_baco->mutex); - - if (state == SMU_BACO_STATE_ENTER) { - if (!ras || !ras->supported) { - data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL); - data |= 0x80000000; - WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data); - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL); - } else { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL); - } - } else { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL); - if (ret) - goto out; - - /* clear vbios scratch 6 and 7 for coming asic reinit */ - WREG32(adev->bios_scratch_reg_offset + 6, 0); - WREG32(adev->bios_scratch_reg_offset + 7, 0); - } - if (ret) - goto out; - - smu_baco->state = state; -out: - mutex_unlock(&smu_baco->mutex); - return ret; -} - -int smu_v11_0_baco_enter(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0; - - /* Arcturus does not need this audio workaround */ - if (adev->asic_type != CHIP_ARCTURUS) { - ret = smu_v11_0_baco_set_armd3_sequence(smu, BACO_SEQ_BACO); - if (ret) - return ret; - } - - ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER); - if (ret) - return ret; - - msleep(10); - - return ret; -} - -int smu_v11_0_baco_exit(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT); - if (ret) - return ret; - - return ret; -} - -int smu_v11_0_mode1_reset(struct smu_context *smu) -{ - int ret = 0; - - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL); - if (!ret) - msleep(SMU11_MODE1_RESET_WAIT_TIME_IN_MS); - - return ret; -} - -int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t *min, uint32_t *max) -{ - int ret = 0, clk_id = 0; - uint32_t param = 0; - uint32_t clock_limit; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) { - switch (clk_type) { - case SMU_MCLK: - case SMU_UCLK: - clock_limit = smu->smu_table.boot_values.uclk; - break; - case SMU_GFXCLK: - case SMU_SCLK: - clock_limit = smu->smu_table.boot_values.gfxclk; - break; - case SMU_SOCCLK: - clock_limit = smu->smu_table.boot_values.socclk; - break; - default: - clock_limit = 0; - break; - } - - /* clock in Mhz unit */ - if (min) - *min = clock_limit / 100; - if (max) - *max = clock_limit / 100; - - return 0; - } - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) { - ret = -EINVAL; - goto failed; - } - param = (clk_id & 0xffff) << 16; - - if (max) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max); - if (ret) - goto failed; - } - - if (min) { - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param, min); - if (ret) - goto failed; - } - -failed: - return ret; -} - -int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t min, - uint32_t max) -{ - struct amdgpu_device *adev = smu->adev; - int ret = 0, clk_id = 0; - uint32_t param; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, false); - - if (max > 0) { - param = (uint32_t)((clk_id << 16) | (max & 0xffff)); - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq, - param, NULL); - if (ret) - goto out; - } - - if (min > 0) { - param = (uint32_t)((clk_id << 16) | (min & 0xffff)); - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq, - param, NULL); - if (ret) - goto out; - } - -out: - if (clk_type == SMU_GFXCLK) - amdgpu_gfx_off_ctrl(adev, true); - - return ret; -} - -int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t min, - uint32_t max) -{ - int ret = 0, clk_id = 0; - uint32_t param; - - if (min <= 0 && max <= 0) - return -EINVAL; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - if (max > 0) { - param = (uint32_t)((clk_id << 16) | (max & 0xffff)); - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq, - param, NULL); - if (ret) - return ret; - } - - if (min > 0) { - param = (uint32_t)((clk_id << 16) | (min & 0xffff)); - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq, - param, NULL); - if (ret) - return ret; - } - - return ret; -} - -int smu_v11_0_set_performance_level(struct smu_context *smu, - enum amd_dpm_forced_level level) -{ - struct smu_11_0_dpm_context *dpm_context = - smu->smu_dpm.dpm_context; - struct smu_11_0_dpm_table *gfx_table = - &dpm_context->dpm_tables.gfx_table; - struct smu_11_0_dpm_table *mem_table = - &dpm_context->dpm_tables.uclk_table; - struct smu_11_0_dpm_table *soc_table = - &dpm_context->dpm_tables.soc_table; - struct smu_umd_pstate_table *pstate_table = - &smu->pstate_table; - struct amdgpu_device *adev = smu->adev; - uint32_t sclk_min = 0, sclk_max = 0; - uint32_t mclk_min = 0, mclk_max = 0; - uint32_t socclk_min = 0, socclk_max = 0; - int ret = 0; - - switch (level) { - case AMD_DPM_FORCED_LEVEL_HIGH: - sclk_min = sclk_max = gfx_table->max; - mclk_min = mclk_max = mem_table->max; - socclk_min = socclk_max = soc_table->max; - break; - case AMD_DPM_FORCED_LEVEL_LOW: - sclk_min = sclk_max = gfx_table->min; - mclk_min = mclk_max = mem_table->min; - socclk_min = socclk_max = soc_table->min; - break; - case AMD_DPM_FORCED_LEVEL_AUTO: - sclk_min = gfx_table->min; - sclk_max = gfx_table->max; - mclk_min = mem_table->min; - mclk_max = mem_table->max; - socclk_min = soc_table->min; - socclk_max = soc_table->max; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD: - sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard; - mclk_min = mclk_max = pstate_table->uclk_pstate.standard; - socclk_min = socclk_max = pstate_table->socclk_pstate.standard; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK: - sclk_min = sclk_max = pstate_table->gfxclk_pstate.min; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK: - mclk_min = mclk_max = pstate_table->uclk_pstate.min; - break; - case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK: - sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak; - mclk_min = mclk_max = pstate_table->uclk_pstate.peak; - socclk_min = socclk_max = pstate_table->socclk_pstate.peak; - break; - case AMD_DPM_FORCED_LEVEL_MANUAL: - case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT: - return 0; - default: - dev_err(adev->dev, "Invalid performance level %d\n", level); - return -EINVAL; - } - - /* - * Separate MCLK and SOCCLK soft min/max settings are not allowed - * on Arcturus. - */ - if (adev->asic_type == CHIP_ARCTURUS) { - mclk_min = mclk_max = 0; - socclk_min = socclk_max = 0; - } - - if (sclk_min && sclk_max) { - ret = smu_v11_0_set_soft_freq_limited_range(smu, - SMU_GFXCLK, - sclk_min, - sclk_max); - if (ret) - return ret; - } - - if (mclk_min && mclk_max) { - ret = smu_v11_0_set_soft_freq_limited_range(smu, - SMU_MCLK, - mclk_min, - mclk_max); - if (ret) - return ret; - } - - if (socclk_min && socclk_max) { - ret = smu_v11_0_set_soft_freq_limited_range(smu, - SMU_SOCCLK, - socclk_min, - socclk_max); - if (ret) - return ret; - } - - return ret; -} - -int smu_v11_0_set_power_source(struct smu_context *smu, - enum smu_power_src_type power_src) -{ - int pwr_source; - - pwr_source = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_PWR, - (uint32_t)power_src); - if (pwr_source < 0) - return -EINVAL; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_NotifyPowerSource, - pwr_source, - NULL); -} - -int smu_v11_0_get_dpm_freq_by_index(struct smu_context *smu, - enum smu_clk_type clk_type, - uint16_t level, - uint32_t *value) -{ - int ret = 0, clk_id = 0; - uint32_t param; - - if (!value) - return -EINVAL; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - clk_id = smu_cmn_to_asic_specific_index(smu, - CMN2ASIC_MAPPING_CLK, - clk_type); - if (clk_id < 0) - return clk_id; - - param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff)); - - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_GetDpmFreqByIndex, - param, - value); - if (ret) - return ret; - - /* - * BIT31: 0 - Fine grained DPM, 1 - Dicrete DPM - * now, we un-support it - */ - *value = *value & 0x7fffffff; - - return ret; -} - -int smu_v11_0_get_dpm_level_count(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *value) -{ - return smu_v11_0_get_dpm_freq_by_index(smu, - clk_type, - 0xff, - value); -} - -int smu_v11_0_set_single_dpm_table(struct smu_context *smu, - enum smu_clk_type clk_type, - struct smu_11_0_dpm_table *single_dpm_table) -{ - int ret = 0; - uint32_t clk; - int i; - - ret = smu_v11_0_get_dpm_level_count(smu, - clk_type, - &single_dpm_table->count); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get dpm levels!\n", __func__); - return ret; - } - - for (i = 0; i < single_dpm_table->count; i++) { - ret = smu_v11_0_get_dpm_freq_by_index(smu, - clk_type, - i, - &clk); - if (ret) { - dev_err(smu->adev->dev, "[%s] failed to get dpm freq by index!\n", __func__); - return ret; - } - - single_dpm_table->dpm_levels[i].value = clk; - single_dpm_table->dpm_levels[i].enabled = true; - - if (i == 0) - single_dpm_table->min = clk; - else if (i == single_dpm_table->count - 1) - single_dpm_table->max = clk; - } - - return 0; -} - -int smu_v11_0_get_dpm_level_range(struct smu_context *smu, - enum smu_clk_type clk_type, - uint32_t *min_value, - uint32_t *max_value) -{ - uint32_t level_count = 0; - int ret = 0; - - if (!min_value && !max_value) - return -EINVAL; - - if (min_value) { - /* by default, level 0 clock value as min value */ - ret = smu_v11_0_get_dpm_freq_by_index(smu, - clk_type, - 0, - min_value); - if (ret) - return ret; - } - - if (max_value) { - ret = smu_v11_0_get_dpm_level_count(smu, - clk_type, - &level_count); - if (ret) - return ret; - - ret = smu_v11_0_get_dpm_freq_by_index(smu, - clk_type, - level_count - 1, - max_value); - if (ret) - return ret; - } - - return ret; -} - -int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - - return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) & - PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK) - >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT; -} - -int smu_v11_0_get_current_pcie_link_width(struct smu_context *smu) -{ - uint32_t width_level; - - width_level = smu_v11_0_get_current_pcie_link_width_level(smu); - if (width_level > LINK_WIDTH_MAX) - width_level = 0; - - return link_width[width_level]; -} - -int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - - return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) & - PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) - >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; -} - -int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu) -{ - uint32_t speed_level; - - speed_level = smu_v11_0_get_current_pcie_link_speed_level(smu); - if (speed_level > LINK_SPEED_MAX) - speed_level = 0; - - return link_speed[speed_level]; -} - -void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) -{ - memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v1_0)); - - gpu_metrics->common_header.structure_size = - sizeof(struct gpu_metrics_v1_0); - gpu_metrics->common_header.format_revision = 1; - gpu_metrics->common_header.content_revision = 0; - - gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); -} diff --git a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c b/drivers/gpu/drm/amd/powerplay/smu_v12_0.c deleted file mode 100644 index 660f403d5770..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smu_v12_0.c +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright 2019 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#define SWSMU_CODE_LAYER_L3 - -#include -#include "amdgpu.h" -#include "amdgpu_smu.h" -#include "atomfirmware.h" -#include "amdgpu_atomfirmware.h" -#include "smu_v12_0.h" -#include "soc15_common.h" -#include "atom.h" -#include "smu_cmn.h" - -#include "asic_reg/mp/mp_12_0_0_offset.h" -#include "asic_reg/mp/mp_12_0_0_sh_mask.h" -#include "asic_reg/smuio/smuio_12_0_0_offset.h" -#include "asic_reg/smuio/smuio_12_0_0_sh_mask.h" - -/* - * DO NOT use these for err/warn/info/debug messages. - * Use dev_err, dev_warn, dev_info and dev_dbg instead. - * They are more MGPU friendly. - */ -#undef pr_err -#undef pr_warn -#undef pr_info -#undef pr_debug - -// because some SMU12 based ASICs use older ip offset tables -// we should undefine this register from the smuio12 header -// to prevent confusion down the road -#undef mmPWR_MISC_CNTL_STATUS - -#define smnMP1_FIRMWARE_FLAGS 0x3010024 - -int smu_v12_0_check_fw_status(struct smu_context *smu) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t mp1_fw_flags; - - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); - - if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> - MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) - return 0; - - return -EIO; -} - -int smu_v12_0_check_fw_version(struct smu_context *smu) -{ - uint32_t if_version = 0xff, smu_version = 0xff; - uint16_t smu_major; - uint8_t smu_minor, smu_debug; - int ret = 0; - - ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version); - if (ret) - return ret; - - smu_major = (smu_version >> 16) & 0xffff; - smu_minor = (smu_version >> 8) & 0xff; - smu_debug = (smu_version >> 0) & 0xff; - - /* - * 1. if_version mismatch is not critical as our fw is designed - * to be backward compatible. - * 2. New fw usually brings some optimizations. But that's visible - * only on the paired driver. - * Considering above, we just leave user a warning message instead - * of halt driver loading. - */ - if (if_version != smu->smc_driver_if_version) { - dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, " - "smu fw version = 0x%08x (%d.%d.%d)\n", - smu->smc_driver_if_version, if_version, - smu_version, smu_major, smu_minor, smu_debug); - dev_warn(smu->adev->dev, "SMU driver if version not matched\n"); - } - - return ret; -} - -int smu_v12_0_powergate_sdma(struct smu_context *smu, bool gate) -{ - if (!smu->is_apu) - return 0; - - if (gate) - return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerDownSdma, NULL); - else - return smu_cmn_send_smc_msg(smu, SMU_MSG_PowerUpSdma, NULL); -} - -int smu_v12_0_set_gfx_cgpg(struct smu_context *smu, bool enable) -{ - if (!(smu->adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) - return 0; - - return smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetGfxCGPG, - enable ? 1 : 0, - NULL); -} - -/** - * smu_v12_0_get_gfxoff_status - get gfxoff status - * - * @smu: amdgpu_device pointer - * - * This function will be used to get gfxoff status - * - * Returns 0=GFXOFF(default). - * Returns 1=Transition out of GFX State. - * Returns 2=Not in GFXOFF. - * Returns 3=Transition into GFXOFF. - */ -uint32_t smu_v12_0_get_gfxoff_status(struct smu_context *smu) -{ - uint32_t reg; - uint32_t gfxOff_Status = 0; - struct amdgpu_device *adev = smu->adev; - - reg = RREG32_SOC15(SMUIO, 0, mmSMUIO_GFX_MISC_CNTL); - gfxOff_Status = (reg & SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS_MASK) - >> SMUIO_GFX_MISC_CNTL__PWR_GFXOFF_STATUS__SHIFT; - - return gfxOff_Status; -} - -int smu_v12_0_gfx_off_control(struct smu_context *smu, bool enable) -{ - int ret = 0, timeout = 500; - - if (enable) { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL); - - } else { - ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL); - - /* confirm gfx is back to "on" state, timeout is 0.5 second */ - while (!(smu_v12_0_get_gfxoff_status(smu) == 2)) { - msleep(1); - timeout--; - if (timeout == 0) { - DRM_ERROR("disable gfxoff timeout and failed!\n"); - break; - } - } - } - - return ret; -} - -int smu_v12_0_fini_smc_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - - kfree(smu_table->clocks_table); - smu_table->clocks_table = NULL; - - kfree(smu_table->metrics_table); - smu_table->metrics_table = NULL; - - kfree(smu_table->watermarks_table); - smu_table->watermarks_table = NULL; - - return 0; -} - -int smu_v12_0_set_default_dpm_tables(struct smu_context *smu) -{ - struct smu_table_context *smu_table = &smu->smu_table; - - return smu_cmn_update_table(smu, SMU_TABLE_DPMCLOCKS, 0, smu_table->clocks_table, false); -} - -int smu_v12_0_mode2_reset(struct smu_context *smu){ - return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GfxDeviceDriverReset, SMU_RESET_MODE_2, NULL); -} - -int smu_v12_0_set_soft_freq_limited_range(struct smu_context *smu, enum smu_clk_type clk_type, - uint32_t min, uint32_t max) -{ - int ret = 0; - - if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) - return 0; - - switch (clk_type) { - case SMU_GFXCLK: - case SMU_SCLK: - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinGfxClk, min, NULL); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxGfxClk, max, NULL); - if (ret) - return ret; - break; - case SMU_FCLK: - case SMU_MCLK: - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinFclkByFreq, min, NULL); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxFclkByFreq, max, NULL); - if (ret) - return ret; - break; - case SMU_SOCCLK: - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinSocclkByFreq, min, NULL); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxSocclkByFreq, max, NULL); - if (ret) - return ret; - break; - case SMU_VCLK: - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinVcn, min, NULL); - if (ret) - return ret; - - ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxVcn, max, NULL); - if (ret) - return ret; - break; - default: - return -EINVAL; - } - - return ret; -} - -int smu_v12_0_set_driver_table_location(struct smu_context *smu) -{ - struct smu_table *driver_table = &smu->smu_table.driver_table; - int ret = 0; - - if (driver_table->mc_address) { - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetDriverDramAddrHigh, - upper_32_bits(driver_table->mc_address), - NULL); - if (!ret) - ret = smu_cmn_send_smc_msg_with_param(smu, - SMU_MSG_SetDriverDramAddrLow, - lower_32_bits(driver_table->mc_address), - NULL); - } - - return ret; -} - -void smu_v12_0_init_gpu_metrics_v2_0(struct gpu_metrics_v2_0 *gpu_metrics) -{ - memset(gpu_metrics, 0xFF, sizeof(struct gpu_metrics_v2_0)); - - gpu_metrics->common_header.structure_size = - sizeof(struct gpu_metrics_v2_0); - gpu_metrics->common_header.format_revision = 2; - gpu_metrics->common_header.content_revision = 0; - - gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile deleted file mode 100644 index 6c59c61a0d81..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2017 Advanced Micro Devices, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# the rights to use, copy, modify, merge, publish, distribute, sublicense, -# and/or sell copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -# THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# -# Makefile for the 'smu manager' sub-component of powerplay. -# It provides the smu management services for the driver. - -SMU_MGR = smumgr.o smu8_smumgr.o tonga_smumgr.o fiji_smumgr.o \ - polaris10_smumgr.o iceland_smumgr.o \ - smu7_smumgr.o vega10_smumgr.o smu10_smumgr.o ci_smumgr.o \ - vega12_smumgr.o vegam_smumgr.o smu9_smumgr.o vega20_smumgr.o - -AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) - -AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c deleted file mode 100644 index c18169aa59ce..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ /dev/null @@ -1,2965 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include -#include -#include -#include "linux/delay.h" -#include -#include - -#include "smumgr.h" -#include "pp_debug.h" -#include "ci_smumgr.h" -#include "ppsmc.h" -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "pppcielanes.h" - -#include "smu/smu_7_0_1_d.h" -#include "smu/smu_7_0_1_sh_mask.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "bif/bif_4_1_d.h" -#include "bif/bif_4_1_sh_mask.h" - -#include "gca/gfx_7_2_d.h" -#include "gca/gfx_7_2_sh_mask.h" - -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -#include "processpptables.h" - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -#define SMC_RAM_END 0x40000 - -#define CISLAND_MINIMUM_ENGINE_CLOCK 800 -#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 - -static const struct ci_pt_defaults defaults_hawaii_xt = { - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_hawaii_pro = { - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_bonaire_xt = { - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } -}; - - -static const struct ci_pt_defaults defaults_saturn_xt = { - 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, - { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, - { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } -}; - - -static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr, - uint32_t smc_addr, uint32_t limit) -{ - if ((0 != (3 & smc_addr)) - || ((smc_addr + 3) >= limit)) { - pr_err("smc_addr invalid \n"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - return 0; -} - -static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, - const uint8_t *src, uint32_t byte_count, uint32_t limit) -{ - int result; - uint32_t data = 0; - uint32_t original_data; - uint32_t addr = 0; - uint32_t extra_shift; - - if ((3 & smc_start_address) - || ((smc_start_address + byte_count) >= limit)) { - pr_err("smc_start_address invalid \n"); - return -EINVAL; - } - - addr = smc_start_address; - - while (byte_count >= 4) { - /* Bytes are written into the SMC address space with the MSB first. */ - data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - - src += 4; - byte_count -= 4; - addr += 4; - } - - if (0 != byte_count) { - - data = 0; - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - - original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); - - extra_shift = 8 * (4 - byte_count); - - while (byte_count > 0) { - /* Bytes are written into the SMC addres space with the MSB first. */ - data = (0x100 * data) + *src++; - byte_count--; - } - - data <<= extra_shift; - - data |= (original_data & ~((~0UL) << extra_shift)); - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - } - - return 0; -} - - -static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr) -{ - static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; - - ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); - - return 0; -} - -static bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr) -{ - return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) - && (0x20100 <= cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, ixSMC_PC_C))); -} - -static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, - uint32_t *value, uint32_t limit) -{ - int result; - - result = ci_set_smc_sram_address(hwmgr, smc_addr, limit); - - if (result) - return result; - - *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); - return 0; -} - -static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - int ret; - - cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); - cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); - - PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - - ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); - - if (ret != 1) - pr_info("\n failed to send message %x ret is %d\n", msg, ret); - - return 0; -} - -static int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); - return ci_send_msg_to_smc(hwmgr, msg); -} - -static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - uint32_t dev_id; - - dev_id = adev->pdev->device; - - switch (dev_id) { - case 0x67BA: - case 0x67B1: - smu_data->power_tune_defaults = &defaults_hawaii_pro; - break; - case 0x67B8: - case 0x66B0: - smu_data->power_tune_defaults = &defaults_hawaii_xt; - break; - case 0x6640: - case 0x6641: - case 0x6646: - case 0x6647: - smu_data->power_tune_defaults = &defaults_saturn_xt; - break; - case 0x6649: - case 0x6650: - case 0x6651: - case 0x6658: - case 0x665C: - case 0x665D: - case 0x67A0: - case 0x67A1: - case 0x67A2: - case 0x67A8: - case 0x67A9: - case 0x67AA: - case 0x67B9: - case 0x67BE: - default: - smu_data->power_tune_defaults = &defaults_bonaire_xt; - break; - } -} - -static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, uint32_t *vol) -{ - uint32_t i = 0; - - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - *vol = allowed_clock_voltage_table->entries[i].v; - return 0; - } - } - - *vol = allowed_clock_voltage_table->entries[i - 1].v; - return 0; -} - -static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t ref_clock; - uint32_t ref_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ - ref_clock = atomctrl_get_reference_clock(hwmgr); - ref_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider */ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup */ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - struct pp_atomctrl_internal_ss_info ss_info; - uint32_t vco_freq = clock * dividers.uc_pll_post_div; - - if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, - vco_freq, &ss_info)) { - uint32_t clk_s = ref_clock * 5 / - (ref_divider * ss_info.speed_spectrum_rate); - uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage * - fbdiv / (clk_s * 10000); - - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, - CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); - } - } - - sclk->SclkFrequency = clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, - const struct phm_phase_shedding_limits_table *pl, - uint32_t sclk, uint32_t *p_shed) -{ - unsigned int i; - - /* use the minimum phase shedding */ - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (sclk < pl->entries[i].Sclk) { - *p_shed = i; - break; - } - } -} - -static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock, - uint32_t clock_insr) -{ - uint8_t i; - uint32_t temp; - uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK); - - if (clock < min) { - pr_info("Engine clock can't satisfy stutter requirement!\n"); - return 0; - } - for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { - temp = clock >> i; - - if (temp >= min || i == 0) - break; - } - return i; -} - -static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU7_Discrete_GraphicsLevel *level) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - - result = ci_calculate_sclk_params(hwmgr, clock, level); - - /* populate graphics levels */ - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_sclk, clock, - (uint32_t *)(&level->MinVddc)); - if (result) { - pr_err("vdd_dep_on_sclk table is NULL\n"); - return result; - } - - level->SclkFrequency = clock; - level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) - ci_populate_phase_value_based_on_sclk(hwmgr, - hwmgr->dyn_state.vddc_phase_shed_limits_table, - clock, - &level->MinVddcPhases); - - level->ActivityLevel = data->current_profile_setting.sclk_activity; - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - level->EnabledForThrottle = 1; - level->UpH = data->current_profile_setting.sclk_up_hyst; - level->DownH = data->current_profile_setting.sclk_down_hyst; - level->VoltageDownH = 0; - level->PowerThrottle = 0; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = - ci_get_sleep_divider_id_from_clock(clock, - CISLAND_MINIMUM_ENGINE_CLOCK); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (0 == result) { - level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - } - - return result; -} - -static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result = 0; - uint32_t array = smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * - SMU7_MAX_LEVELS_GRAPHICS; - struct SMU7_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i; - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = ci_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &levels[i]); - if (result) - return result; - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - if (i == (dpm_table->sclk_table.count - 1)) - smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - } - - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - result = ci_copy_bytes_to_smc(hwmgr, array, - (u8 *)levels, array_size, - SMC_RAM_END); - - return result; - -} - -static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (ci_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - uint16_t tmp; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) - || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) - tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity; - else - tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp); - - return 0; -} - -static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) -{ - int i; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, - "The CAC Leakage table does not exist!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, - "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, - "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); - - for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); - hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3); - } else { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage); - } - } - - return 0; -} - -static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr) -{ - int i; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t *vid = smu_data->power_tune_table.VddCVid; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, - "There should never be more than 8 entries for VddcVid!!!", - return -EINVAL); - - for (i = 0; i < (int)data->vddc_voltage_table.count; i++) - vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); - - return 0; -} - -static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - int i, min, max; - - min = max = hi_vid[0]; - for (i = 0; i < 8; i++) { - if (0 != hi_vid[i]) { - if (min > hi_vid[i]) - min = hi_vid[i]; - if (max < hi_vid[i]) - max = hi_vid[i]; - } - - if (0 != lo_vid[i]) { - if (min > lo_vid[i]) - min = lo_vid[i]; - if (max < lo_vid[i]) - max = lo_vid[i]; - } - } - - if ((min == 0) || (max == 0)) - return -EINVAL; - smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max; - smu_data->power_tune_table.GnbLPMLMinVid = (u8)min; - - return 0; -} - -static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint16_t HiSidd; - uint16_t LoSidd; - struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - int ret = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) { - pr_err("Attempt to get pm_fuse_table_offset Failed!\n"); - return -EINVAL; - } - - /* DW0 - DW3 */ - ret = ci_populate_bapm_vddc_vid_sidd(hwmgr); - /* DW4 - DW5 */ - ret |= ci_populate_vddc_vid(hwmgr); - /* DW6 */ - ret |= ci_populate_svi_load_line(hwmgr); - /* DW7 */ - ret |= ci_populate_tdc_limit(hwmgr); - /* DW8 */ - ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset); - - ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset); - - ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr); - - ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr); - if (ret) - return ret; - - ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END); - } - return ret; -} - -static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; - struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; - const uint16_t *def1, *def2; - int i, j, k; - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - dpm_table->DTETjOffset = 0; - dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - if (ppm) { - dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; - dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; - } else { - dpm_table->PPM_PkgPwrLimit = 0; - dpm_table->PPM_TemperatureLimit = 0; - } - - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); - - dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - def1 = defaults->bapmti_r; - def2 = defaults->bapmti_rc; - - for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU7_DTE_SOURCES; j++) { - for (k = 0; k < SMU7_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); - dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); - def1++; - def2++; - } - } - } - - return 0; -} - -static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, - uint16_t *lo) -{ - uint16_t v_index; - bool vol_found = false; - *hi = tab->value * VOLTAGE_SCALE; - *lo = tab->value * VOLTAGE_SCALE; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, - "The SCLK/VDDC Dependency Table does not exist.\n", - return -EINVAL); - - if (NULL == hwmgr->dyn_state.cac_leakage_table) { - pr_warn("CAC Leakage Table does not exist, using vddc.\n"); - return 0; - } - - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) { - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) - pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); - } - - return 0; -} - -static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, - SMU7_Discrete_VoltageLevel *smc_voltage_tab) -{ - int result; - - result = ci_get_std_voltage_value_sidd(hwmgr, tab, - &smc_voltage_tab->StdVoltageHiSidd, - &smc_voltage_tab->StdVoltageLoSidd); - if (result) { - smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; - smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; - } - - smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd); - - return 0; -} - -static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - unsigned int count; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->vddc_voltage_table.entries[count]), - &(table->VddcLevel[count])); - PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); - - /* GPIO voltage control */ - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) { - table->VddcLevel[count].Smio = (uint8_t) count; - table->Smio[count] |= data->vddc_voltage_table.entries[count].smio_low; - table->SmioMaskVddcVid |= data->vddc_voltage_table.entries[count].smio_low; - } else { - table->VddcLevel[count].Smio = 0; - } - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - - return 0; -} - -static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->VddciLevelCount = data->vddci_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->vddci_voltage_table.entries[count]), - &(table->VddciLevel[count])); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - table->VddciLevel[count].Smio = (uint8_t) count; - table->Smio[count] |= data->vddci_voltage_table.entries[count].smio_low; - table->SmioMaskVddciVid |= data->vddci_voltage_table.entries[count].smio_low; - } else { - table->VddciLevel[count].Smio = 0; - } - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->MvddLevelCount = data->mvdd_voltage_table.count; - - for (count = 0; count < table->MvddLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->mvdd_voltage_table.entries[count]), - &table->MvddLevel[count]); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - table->MvddLevel[count].Smio = (uint8_t) count; - table->Smio[count] |= data->mvdd_voltage_table.entries[count].smio_low; - table->SmioMaskMvddVid |= data->mvdd_voltage_table.entries[count].smio_low; - } else { - table->MvddLevel[count].Smio = 0; - } - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - - return 0; -} - - -static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result; - - result = ci_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDC voltage table to SMC", return -EINVAL); - - result = ci_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDCI voltage table to SMC", return -EINVAL); - - result = ci_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate MVDD voltage table to SMC", return -EINVAL); - - return 0; -} - -static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU7_Discrete_Ulv *state) -{ - uint32_t voltage_response_time, ulv_voltage; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); - PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); - - if (ulv_voltage == 0) { - data->ulv_supported = false; - return 0; - } - - if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffset = 0; - else - /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ - state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); - } else { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffsetVid = 0; - else /* used in SVI2 Mode */ - state->VddcOffsetVid = (uint8_t)( - (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) - * VOLTAGE_VID_OFFSET_SCALE2 - / VOLTAGE_VID_OFFSET_SCALE1); - } - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr, - SMU7_Discrete_Ulv *ulv_level) -{ - return ci_populate_ulv_level(hwmgr, ulv_level); -} - -static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t i; - -/* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int ci_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU7_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE(0 == result, - "Error retrieving Memory Clock Parameters from VBIOS.", return result); - - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); - - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); - - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - - return mc_para_index; -} - -static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - - return mc_para_index; -} - -static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, - uint32_t memory_clock, uint32_t *p_shed) -{ - unsigned int i; - - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (memory_clock < pl->entries[i].Mclk) { - *p_shed = i; - break; - } - } - - return 0; -} - -static int ci_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU7_Discrete_MemoryLevel *memory_level - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - bool dll_state_on; - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - - if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); - } - - if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddci_dependency_on_mclk, - memory_clock, - &memory_level->MinVddci); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); - } - - if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.mvdd_dependency_on_mclk, - memory_clock, - &memory_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result); - } - - memory_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) { - ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, - memory_clock, &memory_level->MinVddcPhases); - } - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 1; - memory_level->UpH = data->current_profile_setting.mclk_up_hyst; - memory_level->DownH = data->current_profile_setting.mclk_down_hyst; - memory_level->VoltageDownH = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - /* stutter mode not support on ci */ - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (ci_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - else - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } else - dll_state_on = data->dll_default_on; - } else { - memory_level->StrobeRatio = - ci_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = ci_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (0 == result) { - memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); - memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); - memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - struct amdgpu_device *adev = hwmgr->adev; - uint32_t dev_id; - - uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY; - SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", return -EINVAL); - result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (0 != result) - return result; - } - - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - dev_id = adev->pdev->device; - - if ((dpm_table->mclk_table.count >= 2) - && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { - smu_data->smc_state_table.MemoryLevel[1].MinVddci = - smu_data->smc_state_table.MemoryLevel[0].MinVddci; - smu_data->smc_state_table.MemoryLevel[1].MinMvdd = - smu_data->smc_state_table.MemoryLevel[0].MinMvdd; - } - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - result = ci_copy_bytes_to_smc(hwmgr, - level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, - SMU7_Discrete_VoltageLevel *voltage) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { - if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - voltage->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, - "MVDD Voltage is outside the supported range.", return -EINVAL); - - } else { - return -EINVAL; - } - - return 0; -} - -static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - - SMU7_Discrete_VoltageLevel voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (data->acpi_vddc) - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); - else - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); - - table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1; - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, - CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; - table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; - else { - if (data->acpi_vddci != 0) - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); - } - - if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpH = 0; - table->MemoryACPILevel.DownH = 100; - table->MemoryACPILevel.VoltageDownH = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_uvd_clock_voltage_dependency_table *uvd_table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - - table->UvdLevelCount = (uint8_t)(uvd_table->count); - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].VclkFrequency = - uvd_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = - uvd_table->entries[count].dclk; - table->UvdLevel[count].MinVddc = - uvd_table->entries[count].v * VOLTAGE_SCALE; - table->UvdLevel[count].MinVddcPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc); - } - - return result; -} - -static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_vce_clock_voltage_dependency_table *vce_table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - table->VceLevelCount = (uint8_t)(vce_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = vce_table->entries[count].evclk; - table->VceLevel[count].MinVoltage = - vce_table->entries[count].v * VOLTAGE_SCALE; - table->VceLevel[count].MinPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_acp_clock_voltage_dependency_table *acp_table = - hwmgr->dyn_state.acp_clock_voltage_dependency_table; - - table->AcpLevelCount = (uint8_t)(acp_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk; - table->AcpLevel[count].MinVoltage = acp_table->entries[count].v; - table->AcpLevel[count].MinPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage); - } - return result; -} - -static int ci_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU7_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = ci_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (0 != result) - break; - } - } - - if (0 == result) { - result = ci_copy_bytes_to_smc( - hwmgr, - smu_data->arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU7_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n"); - result = 0; - } - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - return result; -} - -static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU7_Discrete_MCRegisters *mc_reg_table) -{ - const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<address[] array out of boundary", return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -static void ci_convert_mc_registers( - const struct ci_mc_reg_entry *entry, - SMU7_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int ci_convert_mc_reg_table_entry_to_smc( - struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU7_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU7_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = ci_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters)); - - result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]); - - return ci_copy_bytes_to_smc(hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters)); - result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for the MC register addresses!", return result;); - - result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for driver state!", return result;); - - return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END); -} - -static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t count, level; - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk - >= data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk - >= data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - table->SVI2Enable = 1; - else - table->SVI2Enable = 0; - return 0; -} - -static int ci_start_smc(struct pp_hwmgr *hwmgr) -{ - /* set smc instruct start point at 0x0 */ - ci_program_jump_on_start(hwmgr); - - /* enable smc clock */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, - INTERRUPTS_ENABLED, 1); - - return 0; -} - -static int ci_populate_vr_config(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t config; - - config = VR_SVI2_PLANE_1; - table->VRConfig |= (config<voltage_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= config; - } else { - pr_info("VDDCshould be on SVI2 controller!"); - } - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config<vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config<mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config<backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - u32 i; - - ci_initialize_power_tune_defaults(hwmgr); - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - ci_populate_smc_voltage_tables(hwmgr, table); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (data->ulv_supported) { - result = ci_populate_ulv_state(hwmgr, &(table->Ulv)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = ci_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = ci_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = ci_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = ci_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = ci_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - result = ci_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result); - - /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ - /* need to populate the ARB settings for the initial state. */ - result = ci_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = ci_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - table->UvdBootLevel = 0; - table->VceBootLevel = 0; - table->AcpBootLevel = 0; - table->SamuBootLevel = 0; - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - result = ci_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = ci_populate_smc_initial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); - - result = ci_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); - - table->UVDInterval = 1; - table->VCEInterval = 1; - table->ACPInterval = 1; - table->SAMUInterval = 1; - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - - table->TemperatureLimitHigh = - (data->thermal_temp_setting.temperature_high * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - table->TemperatureLimitLow = - (data->thermal_temp_setting.temperature_low * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->VddcVddciDelta = 4000; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - - PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - - table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count; - table->PCIeGenInterval = 1; - - result = ci_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate VRConfig setting!", return result); - data->vr_config = table->VRConfig; - - ci_populate_smc_svi2_config(hwmgr, table); - - for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++) - CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); - table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); - table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result;); - - result = ci_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate initialize MC Reg table!", return result); - - result = ci_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - ci_start_smc(hwmgr); - - return 0; -} - -static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); - SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == ci_data->fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - - return 0; -} - -static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return ci_program_memory_timing_parameters(hwmgr); - - return 0; -} - -static int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = ci_copy_bytes_to_smc( - hwmgr, - smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, - LowSclkInterruptT), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = ci_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); - - result = ci_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -static uint32_t ci_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU7_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU7_SoftRegisters, AverageGraphicsA); - case AverageMemoryActivity: - return offsetof(SMU7_SoftRegisters, AverageMemoryA); - case PreVBlankGap: - return offsetof(SMU7_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU7_SoftRegisters, VBlankTimeout); - case DRAM_LOG_ADDR_H: - return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU7_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case LowSclkInterruptThreshold: - return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT); - } - break; - } - pr_debug("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static uint32_t ci_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU7_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU7_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU7_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU7_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU7_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDCI: - return SMU7_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU7_MAX_LEVELS_MVDD; - } - - pr_debug("can't get the mac of %x\n", value); - return 0; -} - -static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr) -{ - uint32_t byte_count, start_addr; - uint8_t *src; - uint32_t data; - - struct cgs_firmware_info info = {0}; - - cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info); - - hwmgr->is_kicker = info.is_kicker; - hwmgr->smu_version = info.version; - byte_count = info.image_size; - src = (uint8_t *)info.kptr; - start_addr = info.ucode_start_address; - - if (byte_count > SMC_RAM_END) { - pr_err("SMC address is beyond the SMC RAM area.\n"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); - - for (; byte_count >= 4; byte_count -= 4) { - data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - src += 4; - } - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - - if (0 != byte_count) { - pr_err("SMC size must be divisible by 4\n"); - return -EINVAL; - } - - return 0; -} - -static int ci_upload_firmware(struct pp_hwmgr *hwmgr) -{ - if (ci_is_smc_ram_running(hwmgr)) { - pr_info("smc is running, no need to load smc firmware\n"); - return 0; - } - PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, - boot_seq_done, 1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL, - pre_fetcher_en, 1); - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - return ci_load_smc_ucode(hwmgr); -} - -static int ci_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp = 0; - int result; - bool error = false; - - if (ci_upload_firmware(hwmgr)) - return -EINVAL; - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->dpm_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (0 == result) { - data->soft_regs_start = tmp; - ci_data->soft_regs_start = tmp; - } - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->mc_reg_table_start = tmp; - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->fan_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->arb_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (0 == result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? 1 : 0; -} - -static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) - ? address : table->mc_reg_address[i].s1; - } - return 0; -} - -static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct ci_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct ci_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - - PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - j++; - - if (!data->is_memory_gddr5) { - PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - } - j++; - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int ci_set_valid_flag(struct ci_mc_reg_table *table) -{ - uint8_t i, j; - - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1 << i); - break; - } - } - } - - return 0; -} - -static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - pp_atomctrl_mc_reg_table *table; - struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = ci_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (0 == result) - result = ci_copy_vbios_smc_reg_table(table, ni_table); - - if (0 == result) { - ci_set_s0_mc_reg_index(ni_table); - result = ci_set_mc_special_registers(hwmgr, ni_table); - } - - if (0 == result) - ci_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, - VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -static int ci_smu_init(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *ci_priv = NULL; - - ci_priv = kzalloc(sizeof(struct ci_smumgr), GFP_KERNEL); - - if (ci_priv == NULL) - return -ENOMEM; - - hwmgr->smu_backend = ci_priv; - - return 0; -} - -static int ci_smu_fini(struct pp_hwmgr *hwmgr) -{ - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - return 0; -} - -static int ci_start_smu(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int ci_update_dpm_settings(struct pp_hwmgr *hwmgr, - void *profile_setting) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *) - (hwmgr->smu_backend); - struct profile_mode_setting *setting; - struct SMU7_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); - - uint32_t mclk_array = smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, MemoryLevel); - struct SMU7_Discrete_MemoryLevel *mclk_levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; - - if (profile_setting == NULL) - return -EINVAL; - - setting = (struct profile_mode_setting *)profile_setting; - - if (setting->bupdate_sclk) { - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - if (levels[i].ActivityLevel != - cpu_to_be16(setting->sclk_activity)) { - levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); - - clk_activity_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) - + offsetof(SMU7_Discrete_GraphicsLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (levels[i].UpH != setting->sclk_up_hyst || - levels[i].DownH != setting->sclk_down_hyst) { - levels[i].UpH = setting->sclk_up_hyst; - levels[i].DownH = setting->sclk_down_hyst; - up_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) - + offsetof(SMU7_Discrete_GraphicsLevel, UpH); - down_hyst_offset = array + (sizeof(SMU7_Discrete_GraphicsLevel) * i) - + offsetof(SMU7_Discrete_GraphicsLevel, DownH); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpH, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownH, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); - } - - if (setting->bupdate_mclk) { - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { - if (mclk_levels[i].ActivityLevel != - cpu_to_be16(setting->mclk_activity)) { - mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); - - clk_activity_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) - + offsetof(SMU7_Discrete_MemoryLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (mclk_levels[i].UpH != setting->mclk_up_hyst || - mclk_levels[i].DownH != setting->mclk_down_hyst) { - mclk_levels[i].UpH = setting->mclk_up_hyst; - mclk_levels[i].DownH = setting->mclk_down_hyst; - up_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) - + offsetof(SMU7_Discrete_MemoryLevel, UpH); - down_hyst_offset = mclk_array + (sizeof(SMU7_Discrete_MemoryLevel) * i) - + offsetof(SMU7_Discrete_MemoryLevel, DownH); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpH, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownH, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); - } - return 0; -} - -static int ci_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct smu7_hwmgr *data = hwmgr->backend; - struct ci_smumgr *smu_data = hwmgr->smu_backend; - struct phm_uvd_clock_voltage_dependency_table *uvd_table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; - int32_t i; - - if (PP_CAP(PHM_PlatformCaps_UVDDPM) || uvd_table->count <= 0) - smu_data->smc_state_table.UvdBootLevel = 0; - else - smu_data->smc_state_table.UvdBootLevel = uvd_table->count - 1; - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, - UvdBootLevel, smu_data->smc_state_table.UvdBootLevel); - - data->dpm_level_enable_mask.uvd_dpm_enable_mask = 0; - - for (i = uvd_table->count - 1; i >= 0; i--) { - if (uvd_table->entries[i].v <= max_vddc) - data->dpm_level_enable_mask.uvd_dpm_enable_mask |= 1 << i; - if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_UVDDPM)) - break; - } - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_UVDDPM_SetEnabledMask, - data->dpm_level_enable_mask.uvd_dpm_enable_mask, - NULL); - - return 0; -} - -static int ci_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - struct smu7_hwmgr *data = hwmgr->backend; - struct phm_vce_clock_voltage_dependency_table *vce_table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | - AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; - uint32_t max_vddc = adev->pm.ac_power ? hwmgr->dyn_state.max_clock_voltage_on_ac.vddc : - hwmgr->dyn_state.max_clock_voltage_on_dc.vddc; - int32_t i; - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, DPM_TABLE_475, - VceBootLevel, 0); /* temp hard code to level 0, vce can set min evclk*/ - - data->dpm_level_enable_mask.vce_dpm_enable_mask = 0; - - for (i = vce_table->count - 1; i >= 0; i--) { - if (vce_table->entries[i].v <= max_vddc) - data->dpm_level_enable_mask.vce_dpm_enable_mask |= 1 << i; - if (hwmgr->dpm_level & profile_mode_mask || !PP_CAP(PHM_PlatformCaps_VCEDPM)) - break; - } - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_VCEDPM_SetEnabledMask, - data->dpm_level_enable_mask.vce_dpm_enable_mask, - NULL); - - return 0; -} - -static int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - ci_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - ci_update_vce_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - -const struct pp_smumgr_func ci_smu_funcs = { - .name = "ci_smu", - .smu_init = ci_smu_init, - .smu_fini = ci_smu_fini, - .start_smu = ci_start_smu, - .check_fw_load_finish = NULL, - .request_smu_load_fw = NULL, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = ci_send_msg_to_smc, - .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .get_offsetof = ci_get_offsetof, - .process_firmware_header = ci_process_firmware_header, - .init_smc_table = ci_init_smc_table, - .update_sclk_threshold = ci_update_sclk_threshold, - .thermal_setup_fan_table = ci_thermal_setup_fan_table, - .populate_all_graphic_levels = ci_populate_all_graphic_levels, - .populate_all_memory_levels = ci_populate_all_memory_levels, - .get_mac_definition = ci_get_mac_definition, - .initialize_mc_reg_table = ci_initialize_mc_reg_table, - .is_dpm_running = ci_is_dpm_running, - .update_dpm_settings = ci_update_dpm_settings, - .update_smc_table = ci_update_smc_table, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h deleted file mode 100644 index a8282705c569..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _CI_SMUMANAGER_H_ -#define _CI_SMUMANAGER_H_ - -#define SMU__NUM_SCLK_DPM_STATE 8 -#define SMU__NUM_MCLK_DPM_LEVELS 6 -#define SMU__NUM_LCLK_DPM_LEVELS 8 -#define SMU__NUM_PCIE_DPM_LEVELS 8 - -#include "smu7_discrete.h" -#include -#include "ppatomctrl.h" - -struct ci_pt_defaults { - u8 svi_load_line_en; - u8 svi_load_line_vddc; - u8 tdc_vddc_throttle_release_limit_perc; - u8 tdc_mawt; - u8 tdc_waterfall_ctl; - u8 dte_ambient_temp_base; - u32 display_cac; - u32 bapm_temp_gradient; - u16 bapmti_r[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; - u16 bapmti_rc[SMU7_DTE_ITERATIONS * SMU7_DTE_SOURCES * SMU7_DTE_SINKS]; -}; - -struct ci_mc_reg_entry { - uint32_t mclk_max; - uint32_t mc_data[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - -struct ci_mc_reg_table { - uint8_t last; - uint8_t num_entries; - uint16_t validflag; - struct ci_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMU7_Discrete_MCRegisterAddress mc_reg_address[SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - -struct ci_smumgr { - uint32_t soft_regs_start; - uint32_t dpm_table_start; - uint32_t mc_reg_table_start; - uint32_t fan_table_start; - uint32_t arb_table_start; - uint32_t ulv_setting_starts; - struct SMU7_Discrete_DpmTable smc_state_table; - struct SMU7_Discrete_PmFuses power_tune_table; - const struct ci_pt_defaults *power_tune_defaults; - SMU7_Discrete_MCRegisters mc_regs; - struct ci_mc_reg_table mc_reg_table; -}; - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c deleted file mode 100644 index ecb9ee46d6b3..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ /dev/null @@ -1,2673 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include "smumgr.h" -#include "smu7_dyn_defaults.h" -#include "smu73.h" -#include "smu_ucode_xfer_vi.h" -#include "fiji_smumgr.h" -#include "fiji_ppsmc.h" -#include "smu73_discrete.h" -#include "ppatomctrl.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "oss/oss_3_0_d.h" -#include "gca/gfx_8_0_d.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" -#include "hardwaremanager.h" -#include "cgs_common.h" -#include "atombios.h" -#include "pppcielanes.h" -#include "hwmgr.h" -#include "smu7_hwmgr.h" - - -#define AVFS_EN_MSB 1568 -#define AVFS_EN_LSB 1568 - -#define FIJI_SMC_SIZE 0x20000 - -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VDDC_VDDCI_DELTA 300 -#define MC_CG_ARB_FREQ_F1 0x0b - -/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs - * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] - */ -static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = { - {600, 1050, 3, 0}, {600, 1050, 6, 1} }; - -/* [FF, SS] type, [] 4 voltage ranges, and - * [Floor Freq, Boundary Freq, VID min , VID max] - */ -static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = { - { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, - { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; - -/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] - * (coming from PWR_CKS_CNTL.stretch_amount reg spec) - */ -static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = { - {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} }; - -static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { - /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ - {1, 0xF, 0xFD, - /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ - 0x19, 5, 45} -}; - -static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { - /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */ - /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ - { 0x3c0fd047, 0x30750000, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0xa00fd047, 0x409c0000, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0x0410d047, 0x50c30000, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000, 0, 0, 0x0e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0x6810d047, 0x60ea0000, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0xcc10d047, 0xe8fd0000, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0x3011d047, 0x70110100, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0x9411d047, 0xf8240100, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, - { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } -}; - -static int fiji_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* Wait for smc boot up */ - /* PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - RCU_UC_EVENTS, boot_seq_done, 0); */ - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result) - return result; - - /* Clear status */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_STATUS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /* De-assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for ROM firmware to initialize interrupt hendler */ - /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, SMC_IND, - SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */ - - /* Set SMU Auto Start */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_INPUT_DATA, AUTO_START, 1); - - /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, - INTERRUPTS_ENABLED, 1); - - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL); - - /* Wait for done bit to be set */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - SMU_STATUS, SMU_DONE, 0); - - /* Check pass/failed indicator */ - if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_STATUS, SMU_PASS) != 1) { - PP_ASSERT_WITH_CODE(false, - "SMU Firmware start failed!", return -1); - } - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* wait for smc boot up */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - RCU_UC_EVENTS, boot_seq_done, 0); - - /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - /* Assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result) - return result; - - /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(hwmgr); - - /* Enable clock */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /* De-assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - if (0 != smu_data->avfs_btc_param) { - if (0 != smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param, - NULL)) { - pr_info("[AVFS][Fiji_PerformBtc] PerformBTC SMU msg failed"); - result = -EINVAL; - } - } - /* Soft-Reset to reset the engine before loading uCode */ - /* halt */ - cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); - /* reset everything */ - cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); - /* clear reset */ - cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); - - return result; -} - -static int fiji_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) -{ - int32_t vr_config; - uint32_t table_start; - uint32_t level_addr, vr_config_addr; - uint32_t level_size = sizeof(avfs_graphics_level); - - PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, DpmTable), - &table_start, 0x40000), - "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not " - "communicate starting address of DPM table", - return -1;); - - /* Default value for vr_config = - * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ - vr_config = 0x01000500; /* Real value:0x50001 */ - - vr_config_addr = table_start + - offsetof(SMU73_Discrete_DpmTable, VRConfig); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_addr, - (uint8_t *)&vr_config, sizeof(int32_t), 0x40000), - "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying " - "vr_config value over to SMC", - return -1;); - - level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, level_addr, - (uint8_t *)(&avfs_graphics_level), level_size, 0x40000), - "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!", - return -1;); - - return 0; -} - -static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->avfs_supported) - return 0; - - PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(hwmgr), - "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" - " table over to SMU", - return -EINVAL); - PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), - "[AVFS][fiji_avfs_event_mgr] Could not setup " - "Pwr Virus for AVFS ", - return -EINVAL); - PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(hwmgr), - "[AVFS][fiji_avfs_event_mgr] Failure at " - "fiji_start_avfs_btc. AVFS Disabled", - return -EINVAL); - - return 0; -} - -static int fiji_start_smu(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct fiji_smumgr *priv = (struct fiji_smumgr *)(hwmgr->smu_backend); - - /* Only start SMC if SMC RAM is not running */ - if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { - /* Check if SMU is running in protected mode */ - if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, - SMU_FIRMWARE, SMU_MODE)) { - result = fiji_start_smu_in_non_protection_mode(hwmgr); - if (result) - return result; - } else { - result = fiji_start_smu_in_protection_mode(hwmgr); - if (result) - return result; - } - if (fiji_avfs_event_mgr(hwmgr)) - hwmgr->avfs_supported = false; - } - - /* Setup SoftRegsStart here for register lookup in case - * DummyBackEnd is used and ProcessFirmwareHeader is not executed - */ - smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, SoftRegisters), - &(priv->smu7_data.soft_regs_start), 0x40000); - - result = smu7_request_smu_load_fw(hwmgr); - - return result; -} - -static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) -{ - - uint32_t efuse = 0; - uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; - - if (!hwmgr->not_vf) - return false; - - if (!atomctrl_read_efuse(hwmgr, AVFS_EN_LSB, AVFS_EN_MSB, - mask, &efuse)) { - if (efuse) - return true; - } - return false; -} - -static int fiji_smu_init(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *fiji_priv = NULL; - - fiji_priv = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL); - - if (fiji_priv == NULL) - return -ENOMEM; - - hwmgr->smu_backend = fiji_priv; - - if (smu7_init(hwmgr)) { - kfree(fiji_priv); - return -EINVAL; - } - - return 0; -} - -static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, - uint32_t clock, uint32_t *voltage, uint32_t *mvdd) -{ - uint32_t i; - uint16_t vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - *voltage = *mvdd = 0; - - - /* clock - voltage dependency table is empty table */ - if (dep_table->count == 0) - return -EINVAL; - - for (i = 0; i < dep_table->count; i++) { - /* find first sclk bigger than request */ - if (dep_table->entries[i].clk >= clock) { - *voltage |= (dep_table->entries[i].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i].vddci) - *voltage |= (dep_table->entries[i].vddci * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i].mvdd * - VOLTAGE_SCALE; - - *voltage |= 1 << PHASES_SHIFT; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i-1].vddci) { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; - - return 0; -} - - -static uint16_t scale_fan_gain_settings(uint16_t raw_setting) -{ - uint32_t tmp; - tmp = raw_setting * 4096 / 100; - return (uint16_t)tmp; -} - -static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) -{ - switch (line) { - case SMU7_I2CLineID_DDC1: - *scl = SMU7_I2C_DDC1CLK; - *sda = SMU7_I2C_DDC1DATA; - break; - case SMU7_I2CLineID_DDC2: - *scl = SMU7_I2C_DDC2CLK; - *sda = SMU7_I2C_DDC2DATA; - break; - case SMU7_I2CLineID_DDC3: - *scl = SMU7_I2C_DDC3CLK; - *sda = SMU7_I2C_DDC3DATA; - break; - case SMU7_I2CLineID_DDC4: - *scl = SMU7_I2C_DDC4CLK; - *sda = SMU7_I2C_DDC4DATA; - break; - case SMU7_I2CLineID_DDC5: - *scl = SMU7_I2C_DDC5CLK; - *sda = SMU7_I2C_DDC5DATA; - break; - case SMU7_I2CLineID_DDC6: - *scl = SMU7_I2C_DDC6CLK; - *sda = SMU7_I2C_DDC6DATA; - break; - case SMU7_I2CLineID_SCLSDA: - *scl = SMU7_I2C_SCL; - *sda = SMU7_I2C_SDA; - break; - case SMU7_I2CLineID_DDCVGA: - *scl = SMU7_I2C_DDCVGACLK; - *sda = SMU7_I2C_DDCVGADATA; - break; - default: - *scl = 0; - *sda = 0; - break; - } -} - -static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &fiji_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0]; - -} - -static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - struct pp_advance_fan_control_parameters *fan_table = - &hwmgr->thermal_controller.advanceFanControlParameters; - uint8_t uc_scl, uc_sda; - - /* TDP number of fraction bits are changed from 8 to 7 for Fiji - * as requested by SMC team - */ - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 128)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 128)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range!", - ); - - dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; - - /* The following are for new Fiji Multi-input fan/thermal control */ - dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( - cac_dtp_table->usTargetOperatingTemp * 256); - dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitHotspot * 256); - dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitLiquid1 * 256); - dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitLiquid2 * 256); - dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitVrVddc * 256); - dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitVrMvdd * 256); - dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitPlx * 256); - - dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainEdge)); - dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHotspot)); - dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainLiquid)); - dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainVrVddc)); - dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); - dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainPlx)); - dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHbm)); - - dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; - dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; - dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; - dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; - - get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Liquid_I2C_LineSCL = uc_scl; - dpm_table->Liquid_I2C_LineSDA = uc_sda; - - get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Vr_I2C_LineSCL = uc_scl; - dpm_table->Vr_I2C_LineSDA = uc_sda; - - get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Plx_I2C_LineSCL = uc_scl; - dpm_table->Plx_I2C_LineSDA = uc_sda; - - return 0; -} - - -static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; - smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - - -static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - /* TDC number of fraction bits are changed from 8 to 7 - * for Fiji as requested by SMC team - */ - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->TDC_VDDC_ThrottleReleaseLimitPerc; - smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; - - return 0; -} - -static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else { - smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; - smu_data->power_tune_table.LPMLTemperatureMin = - (uint8_t)((temp >> 16) & 0xff); - smu_data->power_tune_table.LPMLTemperatureMax = - (uint8_t)((temp >> 8) & 0xff); - smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); - } - return 0; -} - -static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity & (1 << 15)) || - 0 == hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity) - hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity = hwmgr->thermal_controller. - advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = - PP_HOST_TO_SMC_US(hwmgr->thermal_controller. - advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - uint32_t pm_fuse_table_offset; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - /* DW6 */ - if (fiji_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - /* DW7 */ - if (fiji_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - /* DW8 */ - if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - /* DW9-DW12 */ - if (0 != fiji_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - /* DW13-DW14 */ - if (fiji_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan Control parameters Failed!", - return -EINVAL); - - /* DW15-DW18 */ - if (fiji_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - /* DW20 */ - if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo " - "Sidd Failed!", return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *lookup_table = - table_info->vddc_lookup_table; - /* tables is already swapped, so in order to use the value from it, - * we need to swap it back. - * We are populating vddc CAC data to BapmVddc table - * in split and merged mode - */ - - for (count = 0; count < lookup_table->count; count++) { - index = phm_get_voltage_index(lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_high); - } - - return 0; -} - -static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result; - - result = fiji_populate_cac_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate CAC voltage tables to SMC", - return -EINVAL); - - return 0; -} - -static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_Ulv *state) -{ - int result = 0; - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - state->VddcPhase = 1; - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - } - return result; -} - -static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - return fiji_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - int i; - - /* Index (dpm_table->pcie_speed_table.count) - * is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( - dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t ref_clock; - uint32_t ref_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ - ref_clock = atomctrl_get_reference_clock(hwmgr); - ref_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider */ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup */ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - struct pp_atomctrl_internal_ss_info ssInfo; - - uint32_t vco_freq = clock * dividers.uc_pll_post_div; - if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, - vco_freq, &ssInfo)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - * - * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 - */ - uint32_t clk_s = ref_clock * 5 / - (ref_divider * ssInfo.speed_spectrum_rate); - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * - fbdiv / (clk_s * 10000); - - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, - CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); - } - } - - sclk->SclkFrequency = clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_GraphicsLevel *level) -{ - int result; - /* PP_Clocks minClocks; */ - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - - result = fiji_calculate_sclk_params(hwmgr, clock, level); - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; - else - vdd_dep_table = table_info->vdd_dep_on_sclk; - - /* populate graphics levels */ - result = fiji_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, clock, - (uint32_t *)(&level->MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for " - "VDDC engine clock dependency table", - return result); - - level->SclkFrequency = clock; - level->ActivityLevel = data->current_profile_setting.sclk_activity; - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - level->EnabledForThrottle = 1; - level->UpHyst = data->current_profile_setting.sclk_up_hyst; - level->DownHyst = data->current_profile_setting.sclk_down_hyst; - level->VoltageDownHyst = 0; - level->PowerThrottle = 0; - - data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, - hwmgr->display_config->min_core_set_clock_in_sr); - - - /* Default to slow, highest DPM level will be - * set to PPSMC_DISPLAY_WATERMARK_LOW later. - */ - level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - - return 0; -} - -static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; - int result = 0; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * - SMU73_MAX_LEVELS_GRAPHICS; - struct SMU73_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i, max_entry; - uint8_t hightest_pcie_level_enabled = 0, - lowest_pcie_level_enabled = 0, - mid_pcie_level_enabled = 0, - count = 0; - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = fiji_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &levels[i]); - if (result) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - levels[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now.*/ - levels[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - levels[dpm_table->sclk_table.count - 1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_cnt - 1; - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } else { - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (hightest_pcie_level_enabled + 1))) != 0)) - hightest_pcie_level_enabled++; - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0)) - lowest_pcie_level_enabled++; - - while ((count < hightest_pcie_level_enabled) && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) - count++; - - mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < - hightest_pcie_level_enabled ? - (lowest_pcie_level_enabled + 1 + count) : - hightest_pcie_level_enabled; - - /* set pcieDpmLevel to hightest_pcie_level_enabled */ - for (i = 2; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = hightest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled */ - levels[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled */ - levels[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - - -/** - * MCLK Frequency Ratio - * SEQ_CG_RESP Bit[31:24] - 0x0 - * Bit[27:24] \96 DDR3 Frequency ratio - * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz - * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz - * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz - * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz - * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz - * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz - * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz - * 400 < 0x7 <= 450MHz, 800 < 0xF - */ -static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) -{ - if (mem_clock <= 10000) - return 0x0; - if (mem_clock <= 15000) - return 0x1; - if (mem_clock <= 20000) - return 0x2; - if (mem_clock <= 25000) - return 0x3; - if (mem_clock <= 30000) - return 0x4; - if (mem_clock <= 35000) - return 0x5; - if (mem_clock <= 40000) - return 0x6; - if (mem_clock <= 45000) - return 0x7; - if (mem_clock <= 50000) - return 0x8; - if (mem_clock <= 55000) - return 0x9; - if (mem_clock <= 60000) - return 0xa; - if (mem_clock <= 65000) - return 0xb; - if (mem_clock <= 70000) - return 0xc; - if (mem_clock <= 75000) - return 0xd; - if (mem_clock <= 80000) - return 0xe; - /* mem_clock > 800MHz */ - return 0xf; -} - -static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) -{ - struct pp_atomctrl_memory_clock_param mem_param; - int result; - - result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to get Memory PLL Dividers.", - ); - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = clock; - mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; - mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); - - return result; -} - -static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - uint32_t mclk_stutter_mode_threshold = 60000; - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; - else - vdd_dep_table = table_info->vdd_dep_on_mclk; - - if (vdd_dep_table) { - result = fiji_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, clock, - (uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory " - "VDDC voltage dependency table", return result); - } - - mem_level->EnabledForThrottle = 1; - mem_level->EnabledForActivity = 0; - mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst; - mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst; - mem_level->VoltageDownHyst = 0; - mem_level->ActivityLevel = data->current_profile_setting.mclk_activity; - mem_level->StutterEnable = false; - - mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - /* enable stutter mode if all the follow condition applied - * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, - * &(data->DisplayTiming.numExistingDisplays)); - */ - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - if (mclk_stutter_mode_threshold && - (clock <= mclk_stutter_mode_threshold) && - (!data->is_uvd_enabled) && - (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) - mem_level->StutterEnable = true; - - result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); - } - return result; -} - -static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - /* populate MCLK dpm table to SMU7 */ - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, MemoryLevel); - uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * - SMU73_MAX_LEVELS_MEMORY; - struct SMU73_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = fiji_populate_single_memory_level(hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &levels[i]); - if (result) - return result; - } - - /* Only enable level 0 for now. */ - levels[0].EnabledForActivity = 1; - - /* in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not effected by - * up threshold or and MCLK DPM latency. - */ - levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; - CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = - (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high */ - levels[dpm_table->mclk_table.count - 1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - -static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pat) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else - return -EINVAL; - - return 0; -} - -static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct pp_atomctrl_clock_dividers_vi dividers; - SMIO_Pattern vol_level; - uint32_t mvdd; - uint16_t us_mvdd; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (!data->sclk_dpm_key_disabled) { - /* Get MinVoltage and Frequency from DPM0, - * already converted to SMC_UL */ - table->ACPILevel.SclkFrequency = - data->dpm_table.sclk_table.dpm_levels[0].value; - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, - table->ACPILevel.SclkFrequency, - (uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDC voltage value " \ - "in Clock Dependency Table", - ); - } else { - table->ACPILevel.SclkFrequency = - data->vbios_boot_state.sclk_bootup_value; - table->ACPILevel.MinVoltage = - data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; - } - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, - SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - if (!data->mclk_dpm_key_disabled) { - /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ - table->MemoryACPILevel.MclkFrequency = - data->dpm_table.mclk_table.dpm_levels[0].value; - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, - table->MemoryACPILevel.MclkFrequency, - (uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDCI voltage value in Clock Dependency Table", - ); - } else { - table->MemoryACPILevel.MclkFrequency = - data->vbios_boot_state.mclk_bootup_value; - table->MemoryACPILevel.MinVoltage = - data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; - } - - us_mvdd = 0; - if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || - (data->mclk_dpm_key_disabled)) - us_mvdd = data->vbios_boot_state.mvdd_bootup_value; - else { - if (!fiji_populate_mvdd_value(hwmgr, - data->dpm_table.mclk_table.dpm_levels[0].value, - &vol_level)) - us_mvdd = vol_level.Voltage; - } - - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - table->MemoryACPILevel.StutterEnable = false; - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); - - return result; -} - -static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->VceLevelCount = (uint8_t)(mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage = 0; - table->VceLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - table->VceLevel[count].MinVoltage |= - ((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) * - VOLTAGE_SCALE) << VDDCI_SHIFT; - table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /*retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->AcpLevelCount = (uint8_t)(mm_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; - table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - - VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); - } - return result; -} - -static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, - int32_t eng_clock, int32_t mem_clock, - struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) -{ - uint32_t dram_timing; - uint32_t dram_timing2; - uint32_t burstTime; - ULONG trrds, trrdl; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - eng_clock, mem_clock); - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); - - trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); - trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - arb_regs->TRRDS = (uint8_t)trrds; - arb_regs->TRRDL = (uint8_t)trrdl; - - return 0; -} - -static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct SMU73_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - int result = 0; - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = fiji_populate_memory_timing_parameters(hwmgr, - data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - if (result) - break; - } - } - - if (!result) - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU73_Discrete_MCArbDramTimingTable), - SMC_RAM_END); - return result; -} - -static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->UvdLevelCount = (uint8_t)(mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].MinVoltage = 0; - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - - VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); - - } - return result; -} - -static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value * - VOLTAGE_SCALE; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return 0; -} - -static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint8_t count, level; - - count = (uint8_t)(table_info->vdd_dep_on_sclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_sclk->entries[level].clk >= - data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(table_info->vdd_dep_on_mclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_mclk->entries[level].clk >= - data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, - volt_with_cks, value; - uint16_t clock_freq_u16; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, - volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (146 * 4)); - efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (148 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - efuse2 &= 0xF; - - if (efuse2 == 1) - ro = (2300 - 1350) * efuse / 255 + 1350; - else - ro = (2500 - 1000) * efuse / 255 + 1000; - - if (ro >= 1660) - type = 0; - else - type = 1; - - /* Populate Stretch amount */ - smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - volt_without_cks = (uint32_t)((14041 * - (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / - (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); - volt_with_cks = (uint32_t)((13946 * - (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / - (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - STRETCH_ENABLE, 0x0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - staticEnable, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x0); - - /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFC2FF87; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = - fiji_clock_stretcher_lookup_table[stretch_amount2][0]; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = - fiji_clock_stretcher_lookup_table[stretch_amount2][1]; - clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. - GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. - SclkFrequency) / 100); - if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < - clock_freq_u16 && - fiji_clock_stretcher_lookup_table[stretch_amount2][1] > - clock_freq_u16) { - /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ - value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; - /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ - value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; - /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ - value |= (fiji_clock_stretch_amount_conversion - [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] - [stretch_amount]) << 3; - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].minFreq); - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].maxFreq); - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = - fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= - (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - /* Populate DDT Lookup Table */ - for (i = 0; i < 4; i++) { - /* Assign the minimum and maximum VID stored - * in the last row of Clock Stretcher Voltage Table. - */ - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].minVID = - (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].maxVID = - (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; - /* Loop through each SCLK and check the frequency - * to see if it lies within the frequency for clock stretcher. - */ - for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { - cks_setting = 0; - clock_freq = PP_SMC_TO_HOST_UL( - smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); - /* Check the allowed frequency against the sclk level[j]. - * Sclk's endianness has already been converted, - * and it's in 10Khz unit, - * as opposed to Data table, which is in Mhz unit. - */ - if (clock_freq >= - (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { - cks_setting |= 0x2; - if (clock_freq < - (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) - cks_setting |= 0x1; - } - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. - ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); - - return 0; -} - -static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t config; - - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - PP_ASSERT_WITH_CODE(false, - "VDDC should be on SVI2 control in merged mode!", - ); - } - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } - - return 0; -} - -static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - -static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) -{ - pp_atomctrl_voltage_table param_led_dpm; - int result = 0; - u32 mask = 0; - - result = atomctrl_get_voltage_table_v3(hwmgr, - VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT, - ¶m_led_dpm); - if (result == 0) { - int i, j; - u32 tmp = param_led_dpm.mask_low; - - for (i = 0, j = 0; i < 32; i++) { - if (tmp & 1) { - mask |= (i << (8 * j)); - if (++j >= 3) - break; - } - tmp >>= 1; - } - } - if (mask) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_LedConfig, - mask, - NULL); - return 0; -} - -static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); - uint8_t i; - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - - fiji_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - fiji_populate_smc_voltage_tables(hwmgr, table); - - table->SystemFlags = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = fiji_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = fiji_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = fiji_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = fiji_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = fiji_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = fiji_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - result = fiji_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result); - - /* Since only the initial state is completely set up at this point - * (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = fiji_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = fiji_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - result = fiji_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = fiji_populate_smc_initailial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot State!", return result); - - result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate BAPM Parameters!", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = fiji_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate Clock Stretcher Data Table!", - return result); - } - - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ - table->PCIeGenInterval = 1; - table->VRConfig = 0; - - result = fiji_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate VRConfig setting!", return result); - data->vr_config = table->VRConfig; - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin)) { - table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - /* Thermal Output GPIO */ - if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, - &gpio_pin)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; - - /* For porlarity read GPIOPAD_A with assigned Gpio pin - * since VBIOS will program this register to set 'inactive state', - * driver can then determine 'active state' from this and - * program SMU with correct polarity - */ - table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & - (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CombinePCCWithThermalSignal)) - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), - SMC_RAM_END); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result); - - result = fiji_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload arb data to SMC memory!", return result); - - result = fiji_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - result = fiji_setup_dpm_led_config(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to setup dpm led config", return result); - - return 0; -} - -static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (smu_data->smu7_data.fan_table_start == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. - usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr-> - thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> - thermal_controller.advanceFanControlParameters.ulCycleDelay * - reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( - hwmgr->device, CGS_IND_REG__SMC, - CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanMinPwm, - hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit, - NULL); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanSclkTarget, - hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit, - NULL); - - if (res) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - return 0; -} - - -static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - if (!hwmgr->avfs_supported) - return 0; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); - - return 0; -} - -static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return fiji_program_memory_timing_parameters(hwmgr); - - return 0; -} - -static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - result = fiji_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - return result; -} - -static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU73_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); - case AverageMemoryActivity: - return offsetof(SMU73_SoftRegisters, AverageMemoryActivity); - case PreVBlankGap: - return offsetof(SMU73_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU73_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU73_SoftRegisters, UcodeLoadStatus); - case DRAM_LOG_ADDR_H: - return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU73_Discrete_DpmTable, VceBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); - } - break; - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static uint32_t fiji_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU73_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU73_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU73_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU73_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU73_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU73_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU73_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU73_MAX_LEVELS_MVDD; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - - -static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, - UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), - NULL); - return 0; -} - -static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - else - smu_data->smc_state_table.VceBootLevel = 0; - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, - NULL); - return 0; -} - -static int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - fiji_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - fiji_update_vce_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - -static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? -1 : 0; -} - -static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - - /* Program additional LP registers - * that are no longer programmed by VBIOS - */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - - return 0; -} - -static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -static int fiji_update_dpm_settings(struct pp_hwmgr *hwmgr, - void *profile_setting) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *) - (hwmgr->smu_backend); - struct profile_mode_setting *setting; - struct SMU73_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - - uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, MemoryLevel); - struct SMU73_Discrete_MemoryLevel *mclk_levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; - - if (profile_setting == NULL) - return -EINVAL; - - setting = (struct profile_mode_setting *)profile_setting; - - if (setting->bupdate_sclk) { - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - if (levels[i].ActivityLevel != - cpu_to_be16(setting->sclk_activity)) { - levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); - - clk_activity_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) - + offsetof(SMU73_Discrete_GraphicsLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (levels[i].UpHyst != setting->sclk_up_hyst || - levels[i].DownHyst != setting->sclk_down_hyst) { - levels[i].UpHyst = setting->sclk_up_hyst; - levels[i].DownHyst = setting->sclk_down_hyst; - up_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) - + offsetof(SMU73_Discrete_GraphicsLevel, UpHyst); - down_hyst_offset = array + (sizeof(SMU73_Discrete_GraphicsLevel) * i) - + offsetof(SMU73_Discrete_GraphicsLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); - } - - if (setting->bupdate_mclk) { - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { - if (mclk_levels[i].ActivityLevel != - cpu_to_be16(setting->mclk_activity)) { - mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); - - clk_activity_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) - + offsetof(SMU73_Discrete_MemoryLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || - mclk_levels[i].DownHyst != setting->mclk_down_hyst) { - mclk_levels[i].UpHyst = setting->mclk_up_hyst; - mclk_levels[i].DownHyst = setting->mclk_down_hyst; - up_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) - + offsetof(SMU73_Discrete_MemoryLevel, UpHyst); - down_hyst_offset = mclk_array + (sizeof(SMU73_Discrete_MemoryLevel) * i) - + offsetof(SMU73_Discrete_MemoryLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); - } - return 0; -} - -const struct pp_smumgr_func fiji_smu_funcs = { - .name = "fiji_smu", - .smu_init = &fiji_smu_init, - .smu_fini = &smu7_smu_fini, - .start_smu = &fiji_start_smu, - .check_fw_load_finish = &smu7_check_fw_load_finish, - .request_smu_load_fw = &smu7_reload_firmware, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &smu7_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, - .get_argument = smu7_get_argument, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .update_smc_table = fiji_update_smc_table, - .get_offsetof = fiji_get_offsetof, - .process_firmware_header = fiji_process_firmware_header, - .init_smc_table = fiji_init_smc_table, - .update_sclk_threshold = fiji_update_sclk_threshold, - .thermal_setup_fan_table = fiji_thermal_setup_fan_table, - .thermal_avfs_enable = fiji_thermal_avfs_enable, - .populate_all_graphic_levels = fiji_populate_all_graphic_levels, - .populate_all_memory_levels = fiji_populate_all_memory_levels, - .get_mac_definition = fiji_get_mac_definition, - .initialize_mc_reg_table = fiji_initialize_mc_reg_table, - .is_dpm_running = fiji_is_dpm_running, - .is_hw_avfs_present = fiji_is_hw_avfs_present, - .update_dpm_settings = fiji_update_dpm_settings, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h deleted file mode 100644 index 6d3746268ccf..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2015 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 _FIJI_SMUMANAGER_H_ -#define _FIJI_SMUMANAGER_H_ - -#include "smu73_discrete.h" -#include -#include "smu7_smumgr.h" - - -struct fiji_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; -}; - -struct fiji_smumgr { - struct smu7_smumgr smu7_data; - struct SMU73_Discrete_DpmTable smc_state_table; - struct SMU73_Discrete_Ulv ulv_setting; - struct SMU73_Discrete_PmFuses power_tune_table; - const struct fiji_pt_defaults *power_tune_defaults; -}; - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c deleted file mode 100644 index 431ad2fd38df..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c +++ /dev/null @@ -1,2686 +0,0 @@ -/* - * Copyright 2016 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. - * - * Author: Huang Rui - * - */ -#include "pp_debug.h" -#include -#include -#include -#include -#include - -#include "smumgr.h" -#include "iceland_smumgr.h" - -#include "ppsmc.h" - -#include "cgs_common.h" - -#include "smu7_dyn_defaults.h" -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "atombios.h" -#include "pppcielanes.h" -#include "pp_endian.h" -#include "processpptables.h" - - -#include "smu/smu_7_1_1_d.h" -#include "smu/smu_7_1_1_sh_mask.h" -#include "smu71_discrete.h" - -#include "smu_ucode_xfer_vi.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - - -#define ICELAND_SMC_SIZE 0x20000 - -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define MC_CG_ARB_FREQ_F1 0x0b -#define VDDC_VDDCI_DELTA 200 - -#define DEVICE_ID_VI_ICELAND_M_6900 0x6900 -#define DEVICE_ID_VI_ICELAND_M_6901 0x6901 -#define DEVICE_ID_VI_ICELAND_M_6902 0x6902 -#define DEVICE_ID_VI_ICELAND_M_6903 0x6903 - -static const struct iceland_pt_defaults defaults_iceland = { - /* - * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, - * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } -}; - -/* 35W - XT, XTL */ -static const struct iceland_pt_defaults defaults_icelandxt = { - /* - * sviLoadLIneEn, SviLoadLineVddC, - * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, - * BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, - { 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0}, - { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} -}; - -/* 25W - PRO, LE */ -static const struct iceland_pt_defaults defaults_icelandpro = { - /* - * sviLoadLIneEn, SviLoadLineVddC, - * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, - * BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, - { 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0}, - { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} -}; - -static int iceland_start_smc(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - return 0; -} - -static void iceland_reset_smc(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, - rst_reg, 1); -} - - -static void iceland_stop_smc_clock(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, - ck_disable, 1); -} - -static void iceland_start_smc_clock(struct pp_hwmgr *hwmgr) -{ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, - ck_disable, 0); -} - -static int iceland_smu_start_smc(struct pp_hwmgr *hwmgr) -{ - /* set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(hwmgr); - - /* enable smc clock */ - iceland_start_smc_clock(hwmgr); - - /* de-assert reset */ - iceland_start_smc(hwmgr); - - PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, - INTERRUPTS_ENABLED, 1); - - return 0; -} - - -static int iceland_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, - uint32_t length, const uint8_t *src, - uint32_t limit, uint32_t start_addr) -{ - uint32_t byte_count = length; - uint32_t data; - - PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); - - while (byte_count >= 4) { - data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - src += 4; - byte_count -= 4; - } - - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - - PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); - - return 0; -} - - -static int iceland_smu_upload_firmware_image(struct pp_hwmgr *hwmgr) -{ - uint32_t val; - struct cgs_firmware_info info = {0}; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - /* load SMC firmware */ - cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); - - if (info.image_size & 3) { - pr_err("[ powerplay ] SMC ucode is not 4 bytes aligned\n"); - return -EINVAL; - } - - if (info.image_size > ICELAND_SMC_SIZE) { - pr_err("[ powerplay ] SMC address is beyond the SMC RAM area\n"); - return -EINVAL; - } - hwmgr->smu_version = info.version; - /* wait for smc boot up */ - PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - RCU_UC_EVENTS, boot_seq_done, 0); - - /* clear firmware interrupt enable flag */ - val = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMC_SYSCON_MISC_CNTL); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMC_SYSCON_MISC_CNTL, val | 1); - - /* stop smc clock */ - iceland_stop_smc_clock(hwmgr); - - /* reset smc */ - iceland_reset_smc(hwmgr); - iceland_upload_smc_firmware_data(hwmgr, info.image_size, - (uint8_t *)info.kptr, ICELAND_SMC_SIZE, - info.ucode_start_address); - - return 0; -} - -static int iceland_request_smu_load_specific_fw(struct pp_hwmgr *hwmgr, - uint32_t firmwareType) -{ - return 0; -} - -static int iceland_start_smu(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *priv = hwmgr->smu_backend; - int result; - - if (!smu7_is_smc_ram_running(hwmgr)) { - result = iceland_smu_upload_firmware_image(hwmgr); - if (result) - return result; - - iceland_smu_start_smc(hwmgr); - } - - /* Setup SoftRegsStart here to visit the register UcodeLoadStatus - * to check fw loading state - */ - smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, SoftRegisters), - &(priv->smu7_data.soft_regs_start), 0x40000); - - result = smu7_request_smu_load_fw(hwmgr); - - return result; -} - -static int iceland_smu_init(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *iceland_priv = NULL; - - iceland_priv = kzalloc(sizeof(struct iceland_smumgr), GFP_KERNEL); - - if (iceland_priv == NULL) - return -ENOMEM; - - hwmgr->smu_backend = iceland_priv; - - if (smu7_init(hwmgr)) { - kfree(iceland_priv); - return -EINVAL; - } - - return 0; -} - - -static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - uint32_t dev_id; - - dev_id = adev->pdev->device; - - switch (dev_id) { - case DEVICE_ID_VI_ICELAND_M_6900: - case DEVICE_ID_VI_ICELAND_M_6903: - smu_data->power_tune_defaults = &defaults_icelandxt; - break; - - case DEVICE_ID_VI_ICELAND_M_6901: - case DEVICE_ID_VI_ICELAND_M_6902: - smu_data->power_tune_defaults = &defaults_icelandpro; - break; - default: - smu_data->power_tune_defaults = &defaults_iceland; - pr_warn("Unknown V.I. Device ID.\n"); - break; - } - return; -} - -static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 8; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, - "The CAC Leakage table does not exist!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, - "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, - "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { - for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); - } - } else { - PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL); - } - - return 0; -} - -static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t *vid = smu_data->power_tune_table.VddCVid; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, - "There should never be more than 8 entries for VddcVid!!!", - return -EINVAL); - - for (i = 0; i < (int)data->vddc_voltage_table.count; i++) { - vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); - } - - return 0; -} - - - -static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - /* DW0 - DW3 */ - if (iceland_populate_bapm_vddc_vid_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate bapm vddc vid Failed!", - return -EINVAL); - - /* DW4 - DW5 */ - if (iceland_populate_vddc_vid(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate vddc vid Failed!", - return -EINVAL); - - /* DW6 */ - if (iceland_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - /* DW7 */ - if (iceland_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - /* DW8 */ - if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - /* DW9-DW12 */ - if (0 != iceland_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - /* DW13-DW16 */ - if (iceland_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - /* DW18 */ - if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!", - return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, uint32_t *vol) -{ - uint32_t i = 0; - - /* clock - voltage dependency table is empty table */ - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - /* find first sclk bigger than request */ - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - *vol = allowed_clock_voltage_table->entries[i].v; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *vol = allowed_clock_voltage_table->entries[i - 1].v; - - return 0; -} - -static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, - uint16_t *lo) -{ - uint16_t v_index; - bool vol_found = false; - *hi = tab->value * VOLTAGE_SCALE; - *lo = tab->value * VOLTAGE_SCALE; - - /* SCLK/VDDC Dependency Table has to exist. */ - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, - "The SCLK/VDDC Dependency Table does not exist.", - return -EINVAL); - - if (NULL == hwmgr->dyn_state.cac_leakage_table) { - pr_warn("CAC Leakage Table does not exist, using vddc.\n"); - return 0; - } - - /* - * Since voltage in the sclk/vddc dependency table is not - * necessarily in ascending order because of ELB voltage - * patching, loop through entire list to find exact voltage. - */ - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - /* - * If voltage is not found in the first pass, loop again to - * find the best match, equal or higher value. - */ - if (!vol_found) { - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) - pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); - } - - return 0; -} - -static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, - SMU71_Discrete_VoltageLevel *smc_voltage_tab) -{ - int result; - - result = iceland_get_std_voltage_value_sidd(hwmgr, tab, - &smc_voltage_tab->StdVoltageHiSidd, - &smc_voltage_tab->StdVoltageLoSidd); - if (0 != result) { - smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; - smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; - } - - smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - - return 0; -} - -static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - unsigned int count; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->vddc_voltage_table.entries[count]), - &(table->VddcLevel[count])); - PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); - - /* GPIO voltage control */ - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) - table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - table->VddcLevel[count].Smio = 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - - return 0; -} - -static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->VddciLevelCount = data->vddci_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->vddci_voltage_table.entries[count]), - &(table->VddciLevel[count])); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; - else - table->VddciLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->MvddLevelCount = data->mvdd_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->mvdd_voltage_table.entries[count]), - &table->MvddLevel[count]); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) - table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; - else - table->MvddLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - - return 0; -} - - -static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result; - - result = iceland_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDC voltage table to SMC", return -EINVAL); - - result = iceland_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDCI voltage table to SMC", return -EINVAL); - - result = iceland_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate MVDD voltage table to SMC", return -EINVAL); - - return 0; -} - -static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU71_Discrete_Ulv *state) -{ - uint32_t voltage_response_time, ulv_voltage; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); - PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); - - if (ulv_voltage == 0) { - data->ulv_supported = false; - return 0; - } - - if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffset = 0; - else - /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ - state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); - } else { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffsetVid = 0; - else /* used in SVI2 Mode */ - state->VddcOffsetVid = (uint8_t)( - (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) - * VOLTAGE_VID_OFFSET_SCALE2 - / VOLTAGE_VID_OFFSET_SCALE1); - } - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr, - SMU71_Discrete_Ulv *ulv_level) -{ - return iceland_populate_ulv_level(hwmgr, ulv_level); -} - -static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t i; - - /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = - 1; - table->LinkLevel[i].SPC = - (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = - PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = - PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t reference_clock; - uint32_t reference_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ - reference_clock = atomctrl_get_reference_clock(hwmgr); - - reference_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider*/ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup*/ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - - uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; - if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - */ - /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ - uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); - - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); - - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = - PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); - } - } - - sclk->SclkFrequency = engine_clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, - const struct phm_phase_shedding_limits_table *pl, - uint32_t sclk, uint32_t *p_shed) -{ - unsigned int i; - - /* use the minimum phase shedding */ - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (sclk < pl->entries[i].Sclk) { - *p_shed = i; - break; - } - } - return 0; -} - -static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - SMU71_Discrete_GraphicsLevel *graphic_level) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level); - - /* populate graphics levels*/ - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock, - &graphic_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for VDDC engine clock dependency table", return result); - - /* SCLK frequency in units of 10KHz*/ - graphic_level->SclkFrequency = engine_clock; - graphic_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) - iceland_populate_phase_value_based_on_sclk(hwmgr, - hwmgr->dyn_state.vddc_phase_shed_limits_table, - engine_clock, - &graphic_level->MinVddcPhases); - - /* Indicates maximum activity level for this performance level. 50% for now*/ - graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity; - - graphic_level->CcPwrDynRm = 0; - graphic_level->CcPwrDynRm1 = 0; - /* this level can be used if activity is high enough.*/ - graphic_level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - graphic_level->EnabledForThrottle = 1; - graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst; - graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst; - graphic_level->VoltageDownHyst = 0; - graphic_level->PowerThrottle = 0; - - data->display_timing.min_clock_in_sr = - hwmgr->display_config->min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - graphic_level->DeepSleepDivId = - smu7_get_sleep_divider_id_from_clock(engine_clock, - data->display_timing.min_clock_in_sr); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (0 == result) { - graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); - } - - return result; -} - -static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, GraphicsLevel); - - uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) * - SMU71_MAX_LEVELS_GRAPHICS; - - SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; - - uint32_t i; - uint8_t highest_pcie_level_enabled = 0; - uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; - uint8_t count = 0; - int result = 0; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = iceland_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result != 0) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now. */ - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - if (dpm_table->sclk_table.count > 1) - smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (highest_pcie_level_enabled + 1))) != 0) { - highest_pcie_level_enabled++; - } - - while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0) { - lowest_pcie_level_enabled++; - } - - while ((count < highest_pcie_level_enabled) && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) { - count++; - } - - mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? - (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; - - - /* set pcieDpmLevel to highest_pcie_level_enabled*/ - for (i = 2; i < dpm_table->sclk_table.count; i++) { - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; - } - - /* set pcieDpmLevel to lowest_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, - (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int iceland_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU71_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE(0 == result, - "Error retrieving Memory Clock Parameters from VBIOS.", return result); - - /* MPLL_FUNC_CNTL setup*/ - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); - - /* MPLL_FUNC_CNTL_1 setup*/ - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); - - /* MPLL_AD_FUNC_CNTL setup*/ - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - /* MPLL_DQ_FUNC_CNTL setup*/ - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - /* - ************************************ - Fref = Reference Frequency - NF = Feedback divider ratio - NR = Reference divider ratio - Fnom = Nominal VCO output frequency = Fref * NF / NR - Fs = Spreading Rate - D = Percentage down-spread / 2 - Fint = Reference input frequency to PFD = Fref / NR - NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) - CLKS = NS - 1 = ISS_STEP_NUM[11:0] - NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) - CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] - ************************************* - */ - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ - /* ss.Info.speed_spectrum_rate -- in unit of khz */ - /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ - /* = reference_clock * 5 / speed_spectrum_rate */ - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - - /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ - /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - /* MCLK_PWRMGT_CNTL setup */ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) { - mc_para_index = 0x00; - } else if (memory_clock > 47500) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } - } else { - if (memory_clock < 65000) { - mc_para_index = 0x00; - } else if (memory_clock > 135000) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - } - - return mc_para_index; -} - -static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) { - mc_para_index = 0; - } else if (memory_clock >= 80000) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - } - - return mc_para_index; -} - -static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, - uint32_t memory_clock, uint32_t *p_shed) -{ - unsigned int i; - - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (memory_clock < pl->entries[i].Mclk) { - *p_shed = i; - break; - } - } - - return 0; -} - -static int iceland_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU71_Discrete_MemoryLevel *memory_level - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - bool dll_state_on; - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - - if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); - } - - if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) { - memory_level->MinVddci = memory_level->MinVddc; - } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddci_dependency_on_mclk, - memory_clock, - &memory_level->MinVddci); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); - } - - memory_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) { - iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, - memory_clock, &memory_level->MinVddcPhases); - } - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 0; - memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst; - memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst; - memory_level->VoltageDownHyst = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - /* stutter mode not support on iceland */ - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - else - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } else - dll_state_on = data->dll_default_on; - } else { - memory_level->StrobeRatio = - iceland_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = iceland_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (0 == result) { - memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); - memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); - memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -static int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - - /* populate MCLK dpm table to SMU7 */ - uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY; - SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", return -EINVAL); - result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (0 != result) { - return result; - } - } - - /* Only enable level 0 for now.*/ - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - /* - * in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in a higher state - * by default such that we are not effected by up threshold or and MCLK DPM latency. - */ - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high*/ - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, - level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, - SMU71_Discrete_VoltageLevel *voltage) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { - if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - voltage->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, - "MVDD Voltage is outside the supported range.", return -EINVAL); - - } else { - return -EINVAL; - } - - return 0; -} - -static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t vddc_phase_shed_control = 0; - - SMU71_Discrete_VoltageLevel voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (data->acpi_vddc) - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); - else - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); - - table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1; - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, - CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; - table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; - else { - if (data->acpi_vddci != 0) - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); - } - - if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU71_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = iceland_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (0 != result) { - break; - } - } - } - - if (0 == result) { - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU71_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value in dependency table. Using Graphics DPM level 0!\n"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value in dependency table. Using Memory DPM level 0!\n"); - result = 0; - } - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->BootVddci = table->BootVddc; - else - table->BootVddci = data->vbios_boot_state.vddci_bootup_value; - - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - return result; -} - -static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU71_Discrete_MCRegisters *mc_reg_table) -{ - const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<address[] array out of boundary", return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -/*convert register values from driver to SMC format */ -static void iceland_convert_mc_registers( - const struct iceland_mc_reg_entry *entry, - SMU71_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU71_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU71_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = iceland_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters)); - - result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - - address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]); - - return smu7_copy_bytes_to_smc(hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters)); - result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for the MC register addresses!", return result;); - - result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for driver state!", return result;); - - return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END); -} - -static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t count, level; - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk - >= data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk - >= data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU71_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; - struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; - const uint16_t *def1, *def2; - int i, j, k; - - - /* - * TDP number of fraction bits are changed from 8 to 7 for Iceland - * as requested by SMC team - */ - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - - dpm_table->DTETjOffset = 0; - - dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - /* The following are for new Iceland Multi-input fan/thermal control */ - if (NULL != ppm) { - dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; - dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; - } else { - dpm_table->PPM_PkgPwrLimit = 0; - dpm_table->PPM_TemperatureLimit = 0; - } - - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); - - dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - def1 = defaults->bapmti_r; - def2 = defaults->bapmti_rc; - - for (i = 0; i < SMU71_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU71_DTE_SOURCES; j++) { - for (k = 0; k < SMU71_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); - dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); - def1++; - def2++; - } - } - } - - return 0; -} - -static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *tab) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - tab->SVI2Enable |= VDDC_ON_SVI2; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - tab->SVI2Enable |= VDDCI_ON_SVI2; - else - tab->MergedVddci = 1; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) - tab->SVI2Enable |= MVDD_ON_SVI2; - - PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) && - (tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL); - - return 0; -} - -static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - SMU71_Discrete_DpmTable *table = &(smu_data->smc_state_table); - - - iceland_initialize_power_tune_defaults(hwmgr); - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) { - iceland_populate_smc_voltage_tables(hwmgr, table); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - - if (data->ulv_supported) { - result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result;); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = iceland_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result;); - - result = iceland_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result;); - - result = iceland_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result;); - - result = iceland_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result;); - - result = iceland_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result;); - - result = iceland_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result;); - - /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ - /* need to populate the ARB settings for the initial state. */ - result = iceland_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result;); - - result = iceland_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result;); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - result = iceland_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result;); - - result = iceland_populate_smc_initial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); - - result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); - - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - - table->TemperatureLimitHigh = - (data->thermal_temp_setting.temperature_high * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - table->TemperatureLimitLow = - (data->thermal_temp_setting.temperature_low * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; - table->PCIeGenInterval = 1; - - result = iceland_populate_smc_svi2_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate SVI2 setting!", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); - table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); - table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result;); - - /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.ulv_setting_starts, - (uint8_t *)&(smu_data->ulv_setting), - sizeof(SMU71_Discrete_Ulv), - SMC_RAM_END); - - - result = iceland_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate initialize MC Reg table!", return result); - - result = iceland_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - return 0; -} - -int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == smu7_data->fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - /* fan_table.FanControl_GL_Flag = 1; */ - - res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - - return 0; -} - - -static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return iceland_program_memory_timing_parameters(hwmgr); - - return 0; -} - -static int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = iceland_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); - - result = iceland_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -static uint32_t iceland_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU71_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity); - case AverageMemoryActivity: - return offsetof(SMU71_SoftRegisters, AverageMemoryActivity); - case PreVBlankGap: - return offsetof(SMU71_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU71_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU71_SoftRegisters, UcodeLoadStatus); - case DRAM_LOG_ADDR_H: - return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU71_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case LowSclkInterruptThreshold: - return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold); - } - break; - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static uint32_t iceland_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU71_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU71_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU71_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU71_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU71_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDCI: - return SMU71_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU71_MAX_LEVELS_MVDD; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - -static int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->dpm_table_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (0 == result) { - data->soft_regs_start = tmp; - smu7_data->soft_regs_start = tmp; - } - - error |= (0 != result); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->mc_reg_table_start = tmp; - } - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->fan_table_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->arb_table_start = tmp; - } - - error |= (0 != result); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (0 == result) { - hwmgr->microcode_version_info.SMC = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, UlvSettings), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->ulv_setting_starts = tmp; - } - - error |= (0 != result); - - return error ? 1 : 0; -} - -/*---------------------------MC----------------------------*/ - -static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) - ? address : table->mc_reg_address[i].s1; - } - return 0; -} - -static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct iceland_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) { - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - } - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct iceland_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - - PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) { - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - } - j++; - - if (!data->is_memory_gddr5) { - PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - } - j++; - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int iceland_set_valid_flag(struct iceland_mc_reg_table *table) -{ - uint8_t i, j; - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1<smu_backend); - pp_atomctrl_mc_reg_table *table; - struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = iceland_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (0 == result) - result = iceland_copy_vbios_smc_reg_table(table, ni_table); - - if (0 == result) { - iceland_set_s0_mc_reg_index(ni_table); - result = iceland_set_mc_special_registers(hwmgr, ni_table); - } - - if (0 == result) - iceland_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -static bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -const struct pp_smumgr_func iceland_smu_funcs = { - .name = "iceland_smu", - .smu_init = &iceland_smu_init, - .smu_fini = &smu7_smu_fini, - .start_smu = &iceland_start_smu, - .check_fw_load_finish = &smu7_check_fw_load_finish, - .request_smu_load_fw = &smu7_request_smu_load_fw, - .request_smu_load_specific_fw = &iceland_request_smu_load_specific_fw, - .send_msg_to_smc = &smu7_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, - .get_argument = smu7_get_argument, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .get_offsetof = iceland_get_offsetof, - .process_firmware_header = iceland_process_firmware_header, - .init_smc_table = iceland_init_smc_table, - .update_sclk_threshold = iceland_update_sclk_threshold, - .thermal_setup_fan_table = iceland_thermal_setup_fan_table, - .populate_all_graphic_levels = iceland_populate_all_graphic_levels, - .populate_all_memory_levels = iceland_populate_all_memory_levels, - .get_mac_definition = iceland_get_mac_definition, - .initialize_mc_reg_table = iceland_initialize_mc_reg_table, - .is_dpm_running = iceland_is_dpm_running, -}; - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h deleted file mode 100644 index f32c506779c9..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 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. - * - * Author: Huang Rui - * - */ - -#ifndef _ICELAND_SMUMGR_H_ -#define _ICELAND_SMUMGR_H_ - - -#include "smu7_smumgr.h" -#include "pp_endian.h" -#include "smu71_discrete.h" - -struct iceland_pt_defaults { - uint8_t svi_load_line_en; - uint8_t svi_load_line_vddc; - uint8_t tdc_vddc_throttle_release_limit_perc; - uint8_t tdc_mawt; - uint8_t tdc_waterfall_ctl; - uint8_t dte_ambient_temp_base; - uint32_t display_cac; - uint32_t bapm_temp_gradient; - uint16_t bapmti_r[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; - uint16_t bapmti_rc[SMU71_DTE_ITERATIONS * SMU71_DTE_SOURCES * SMU71_DTE_SINKS]; -}; - -struct iceland_mc_reg_entry { - uint32_t mclk_max; - uint32_t mc_data[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - -struct iceland_mc_reg_table { - uint8_t last; /* number of registers*/ - uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/ - uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/ - struct iceland_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMU71_Discrete_MCRegisterAddress mc_reg_address[SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - -struct iceland_smumgr { - struct smu7_smumgr smu7_data; - struct SMU71_Discrete_DpmTable smc_state_table; - struct SMU71_Discrete_PmFuses power_tune_table; - struct SMU71_Discrete_Ulv ulv_setting; - const struct iceland_pt_defaults *power_tune_defaults; - SMU71_Discrete_MCRegisters mc_regs; - struct iceland_mc_reg_table mc_reg_table; -}; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c deleted file mode 100644 index c3d2e6dcf62a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ /dev/null @@ -1,2590 +0,0 @@ -/* - * Copyright 2015 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 - -#include "pp_debug.h" -#include "smumgr.h" -#include "smu74.h" -#include "smu_ucode_xfer_vi.h" -#include "polaris10_smumgr.h" -#include "smu74_discrete.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "oss/oss_3_0_d.h" -#include "gca/gfx_8_0_d.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "smu7_ppsmc.h" -#include "smu7_smumgr.h" - -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "atombios.h" -#include "pppcielanes.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -#define POLARIS10_SMC_SIZE 0x20000 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VDDC_VDDCI_DELTA 200 -#define MC_CG_ARB_FREQ_F1 0x0b - -static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { - /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ - { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, -}; - -static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { - {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, - {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, - {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; - -#define PPPOLARIS10_TARGETACTIVITY_DFLT 50 - -static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { - /* Min pcie DeepSleep Activity CgSpll CgSpll CcPwr CcPwr Sclk Enabled Enabled Voltage Power */ - /* Voltage, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, DynRm, DynRm1 Did, Padding,ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ - { 0x100ea446, 0x00, 0x03, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x30750000, 0x3000, 0, 0x2600, 0, 0, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } }, - { 0x400ea446, 0x01, 0x04, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x409c0000, 0x2000, 0, 0x1e00, 1, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } }, - { 0x740ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x50c30000, 0x2800, 0, 0x2000, 1, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } }, - { 0xa40ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x60ea0000, 0x3000, 0, 0x2600, 1, 1, 0x0004, 0x8f02, 0xffff, 0x2f00, 0x300e, 0x2700 } }, - { 0xd80ea446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x70110100, 0x3800, 0, 0x2c00, 1, 1, 0x0004, 0x1203, 0xffff, 0x3600, 0xc9e2, 0x2e00 } }, - { 0x3c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x80380100, 0x2000, 0, 0x1e00, 2, 1, 0x0004, 0x8300, 0xffff, 0x1f00, 0xcb5e, 0x1a00 } }, - { 0x6c0fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0x905f0100, 0x2400, 0, 0x1e00, 2, 1, 0x0004, 0x8901, 0xffff, 0x2300, 0x314c, 0x1d00 } }, - { 0xa00fa446, 0x01, 0x00, 0x3200, 0, 0, 0, 0, 0, 0, 0x01, 0x01, 0x0a, 0x00, 0x00, 0x00, { 0xa0860100, 0x2800, 0, 0x2000, 2, 1, 0x0004, 0x0c02, 0xffff, 0x2700, 0x6433, 0x2100 } } -}; - -static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = { - 0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00}; - -static int polaris10_perform_btc(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - if (0 != smu_data->avfs_btc_param) { - if (0 != smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_PerformBtc, smu_data->avfs_btc_param, - NULL)) { - pr_info("[AVFS][SmuPolaris10_PerformBtc] PerformBTC SMU msg failed"); - result = -1; - } - } - if (smu_data->avfs_btc_param > 1) { - /* Soft-Reset to reset the engine before loading uCode */ - /* halt */ - cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, 0x50000000); - /* reset everything */ - cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0xffffffff); - cgs_write_register(hwmgr->device, mmGRBM_SOFT_RESET, 0); - } - return result; -} - - -static int polaris10_setup_graphics_level_structure(struct pp_hwmgr *hwmgr) -{ - uint32_t vr_config; - uint32_t dpm_table_start; - - uint16_t u16_boot_mvdd; - uint32_t graphics_level_address, vr_config_address, graphics_level_size; - - graphics_level_size = sizeof(avfs_graphics_level_polaris10); - u16_boot_mvdd = PP_HOST_TO_SMC_US(1300 * VOLTAGE_SCALE); - - PP_ASSERT_WITH_CODE(0 == smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, DpmTable), - &dpm_table_start, 0x40000), - "[AVFS][Polaris10_SetupGfxLvlStruct] SMU could not communicate starting address of DPM table", - return -1); - - /* Default value for VRConfig = VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ - vr_config = 0x01000500; /* Real value:0x50001 */ - - vr_config_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, VRConfig); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, vr_config_address, - (uint8_t *)&vr_config, sizeof(uint32_t), 0x40000), - "[AVFS][Polaris10_SetupGfxLvlStruct] Problems copying VRConfig value over to SMC", - return -1); - - graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, - (uint8_t *)(&avfs_graphics_level_polaris10), - graphics_level_size, 0x40000), - "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of SCLK DPM table failed!", - return -1); - - graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, - (uint8_t *)(&avfs_memory_level_polaris10), sizeof(avfs_memory_level_polaris10), 0x40000), - "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of MCLK DPM table failed!", - return -1); - - /* MVDD Boot value - neccessary for getting rid of the hang that occurs during Mclk DPM enablement */ - - graphics_level_address = dpm_table_start + offsetof(SMU74_Discrete_DpmTable, BootMVdd); - - PP_ASSERT_WITH_CODE(0 == smu7_copy_bytes_to_smc(hwmgr, graphics_level_address, - (uint8_t *)(&u16_boot_mvdd), sizeof(u16_boot_mvdd), 0x40000), - "[AVFS][Polaris10_SetupGfxLvlStruct] Copying of DPM table failed!", - return -1); - - return 0; -} - - -static int polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - if (!hwmgr->avfs_supported) - return 0; - - PP_ASSERT_WITH_CODE(0 == polaris10_setup_graphics_level_structure(hwmgr), - "[AVFS][Polaris10_AVFSEventMgr] Could not Copy Graphics Level table over to SMU", - return -EINVAL); - - if (smu_data->avfs_btc_param > 1) { - pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting."); - PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), - "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ", - return -EINVAL); - } - - PP_ASSERT_WITH_CODE(0 == polaris10_perform_btc(hwmgr), - "[AVFS][Polaris10_AVFSEventMgr] Failure at SmuPolaris10_PerformBTC. AVFS Disabled", - return -EINVAL); - - return 0; -} - -static int polaris10_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* Wait for smc boot up */ - /* PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ - - /* Assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result != 0) - return result; - - /* Clear status */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /* De-assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); - - - /* Call Test SMU message with 0x20000 offset to trigger SMU start */ - smu7_send_msg_to_smc_offset(hwmgr); - - /* Wait done bit to be set */ - /* Check pass/failed indicator */ - - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); - - if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_STATUS, SMU_PASS)) - PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int polaris10_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* wait for smc boot up */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); - - /* Clear firmware interrupt enable flag */ - /* PHM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, - rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result != 0) - return result; - - /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(hwmgr); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int polaris10_start_smu(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - /* Only start SMC if SMC RAM is not running */ - if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { - smu_data->protected_mode = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); - smu_data->smu7_data.security_hard_key = (uint8_t) (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); - - /* Check if SMU is running in protected mode */ - if (smu_data->protected_mode == 0) - result = polaris10_start_smu_in_non_protection_mode(hwmgr); - else - result = polaris10_start_smu_in_protection_mode(hwmgr); - - if (result != 0) - PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); - - polaris10_avfs_event_mgr(hwmgr); - } - - /* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */ - smu7_read_smc_sram_dword(hwmgr, SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, SoftRegisters), - &(smu_data->smu7_data.soft_regs_start), 0x40000); - - result = smu7_request_smu_load_fw(hwmgr); - - return result; -} - -static bool polaris10_is_hw_avfs_present(struct pp_hwmgr *hwmgr) -{ - uint32_t efuse; - - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_EFUSE_0 + (49*4)); - efuse &= 0x00000001; - if (efuse) - return true; - - return false; -} - -static int polaris10_smu_init(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data; - - smu_data = kzalloc(sizeof(struct polaris10_smumgr), GFP_KERNEL); - if (smu_data == NULL) - return -ENOMEM; - - hwmgr->smu_backend = smu_data; - - if (smu7_init(hwmgr)) { - kfree(smu_data); - return -EINVAL; - } - - return 0; -} - -static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, - uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) -{ - uint32_t i; - uint16_t vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - *voltage = *mvdd = 0; - - /* clock - voltage dependency table is empty table */ - if (dep_table->count == 0) - return -EINVAL; - - for (i = 0; i < dep_table->count; i++) { - /* find first sclk bigger than request */ - if (dep_table->entries[i].clk >= clock) { - *voltage |= (dep_table->entries[i].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i].vddci) - *voltage |= (dep_table->entries[i].vddci * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i].mvdd * - VOLTAGE_SCALE; - - *voltage |= 1 << PHASES_SHIFT; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i-1].vddci) { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; - - return 0; -} - -static uint16_t scale_fan_gain_settings(uint16_t raw_setting) -{ - uint32_t tmp; - tmp = raw_setting * 4096 / 100; - return (uint16_t)tmp; -} - -static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - struct pp_advance_fan_control_parameters *fan_table = - &hwmgr->thermal_controller.advanceFanControlParameters; - int i, j, k; - const uint16_t *pdef1; - const uint16_t *pdef2; - - table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range!", - ); - - table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( - cac_dtp_table->usTargetOperatingTemp * 256); - table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitHotspot * 256); - table->FanGainEdge = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainEdge)); - table->FanGainHotspot = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHotspot)); - - pdef1 = defaults->BAPMTI_R; - pdef2 = defaults->BAPMTI_RC; - - for (i = 0; i < SMU74_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU74_DTE_SOURCES; j++) { - for (k = 0; k < SMU74_DTE_SINKS; k++) { - table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); - table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); - pdef1++; - pdef2++; - } - } - } - - return 0; -} - -static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; - smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->TDC_VDDC_ThrottleReleaseLimitPerc; - smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; - - return 0; -} - -static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else { - smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; - smu_data->power_tune_table.LPMLTemperatureMin = - (uint8_t)((temp >> 16) & 0xff); - smu_data->power_tune_table.LPMLTemperatureMax = - (uint8_t)((temp >> 8) & 0xff); - smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); - } - return 0; -} - -static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - -/* TO DO move to hwmgr */ - if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) - || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); - - return 0; -} - -static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - if (polaris10_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - - if (polaris10_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - - if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - if (0 != polaris10_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - if (polaris10_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan Control parameters Failed!", - return -EINVAL); - - if (polaris10_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo " - "Sidd Failed!", return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count, level; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - count = data->mvdd_voltage_table.count; - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; level++) { - table->SmioTable2.Pattern[level].Voltage = - PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ - table->SmioTable2.Pattern[level].Smio = - (uint8_t) level; - table->Smio[level] |= - data->mvdd_voltage_table.entries[level].smio_low; - } - table->SmioMask2 = data->mvdd_voltage_table.mask_low; - - table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); - } - - return 0; -} - -static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - uint32_t count, level; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - count = data->vddci_voltage_table.count; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; ++level) { - table->SmioTable1.Pattern[level].Voltage = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); - table->SmioTable1.Pattern[level].Smio = (uint8_t) level; - - table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; - } - } - - table->SmioMask1 = data->vddci_voltage_table.mask_low; - - return 0; -} - -static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *lookup_table = - table_info->vddc_lookup_table; - /* tables is already swapped, so in order to use the value from it, - * we need to swap it back. - * We are populating vddc CAC data to BapmVddc table - * in split and merged mode - */ - for (count = 0; count < lookup_table->count; count++) { - index = phm_get_voltage_index(lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid); - table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high); - } - - return 0; -} - -static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - polaris10_populate_smc_vddci_table(hwmgr, table); - polaris10_populate_smc_mvdd_table(hwmgr, table); - polaris10_populate_cac_table(hwmgr, table); - - return 0; -} - -static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_Ulv *state) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) - state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; - else - state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - return polaris10_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int i; - - /* Index (dpm_table->pcie_speed_table.count) - * is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( - dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - -/* To Do move to hwmgr */ - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - - -static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t i, ref_clk; - - struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; - - ref_clk = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { - for (i = 0; i < NUM_SCLK_RANGE; i++) { - table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting; - table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv; - table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } - return; - } - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; - smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; - - table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; - table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; - table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } -} - -static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, SMU_SclkSetting *sclk_setting) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct pp_atomctrl_clock_dividers_ai dividers; - uint32_t ref_clock; - uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; - uint8_t i; - int result; - uint64_t temp; - - sclk_setting->SclkFrequency = clock; - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); - if (result == 0) { - sclk_setting->Fcw_int = dividers.usSclk_fcw_int; - sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; - sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; - sclk_setting->PllRange = dividers.ucSclkPllRange; - sclk_setting->Sclk_slew_rate = 0x400; - sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; - sclk_setting->Pcc_down_slew_rate = 0xffff; - sclk_setting->SSc_En = dividers.ucSscEnable; - sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; - sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; - sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; - return result; - } - - ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - if (clock > smu_data->range_table[i].trans_lower_frequency - && clock <= smu_data->range_table[i].trans_upper_frequency) { - sclk_setting->PllRange = i; - break; - } - } - - sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw_frac = temp & 0xffff; - - pcc_target_percent = 10; /* Hardcode 10% for now. */ - pcc_target_freq = clock - (clock * pcc_target_percent / 100); - sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - - ss_target_percent = 2; /* Hardcode 2% for now. */ - sclk_setting->SSc_En = 0; - if (ss_target_percent) { - sclk_setting->SSc_En = 1; - ss_target_freq = clock - (clock * ss_target_percent / 100); - sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw1_frac = temp & 0xffff; - } - - return 0; -} - -static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU74_Discrete_GraphicsLevel *level) -{ - int result; - /* PP_Clocks minClocks; */ - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMU_SclkSetting curr_sclk_setting = { 0 }; - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - - result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; - else - vdd_dep_table = table_info->vdd_dep_on_sclk; - - /* populate graphics levels */ - result = polaris10_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, clock, - &level->MinVoltage, &mvdd); - - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for " - "VDDC engine clock dependency table", - return result); - level->ActivityLevel = data->current_profile_setting.sclk_activity; - - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - level->EnabledForThrottle = 1; - level->UpHyst = data->current_profile_setting.sclk_up_hyst; - level->DownHyst = data->current_profile_setting.sclk_down_hyst; - level->VoltageDownHyst = 0; - level->PowerThrottle = 0; - data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, - hwmgr->display_config->min_core_set_clock_in_sr); - - /* Default to slow, highest DPM level will be - * set to PPSMC_DISPLAY_WATERMARK_LOW later. - */ - if (data->update_up_hyst) - level->UpHyst = (uint8_t)data->up_hyst; - if (data->update_down_hyst) - level->DownHyst = (uint8_t)data->down_hyst; - - level->SclkSetting = curr_sclk_setting; - - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); - return 0; -} - -static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; - int result = 0; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * - SMU74_MAX_LEVELS_GRAPHICS; - struct SMU74_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i, max_entry; - uint8_t hightest_pcie_level_enabled = 0, - lowest_pcie_level_enabled = 0, - mid_pcie_level_enabled = 0, - count = 0; - - polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - - result = polaris10_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - levels[i].DeepSleepDivId = 0; - } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport)) - smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; - - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_cnt - 1; - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } else { - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (hightest_pcie_level_enabled + 1))) != 0)) - hightest_pcie_level_enabled++; - - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0)) - lowest_pcie_level_enabled++; - - while ((count < hightest_pcie_level_enabled) && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) - count++; - - mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < - hightest_pcie_level_enabled ? - (lowest_pcie_level_enabled + 1 + count) : - hightest_pcie_level_enabled; - - /* set pcieDpmLevel to hightest_pcie_level_enabled */ - for (i = 2; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = hightest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled */ - levels[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled */ - levels[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - - -static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - uint32_t mclk_stutter_mode_threshold = 40000; - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; - else - vdd_dep_table = table_info->vdd_dep_on_mclk; - - if (vdd_dep_table) { - result = polaris10_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, clock, - &mem_level->MinVoltage, &mem_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory " - "VDDC voltage dependency table", return result); - } - - mem_level->MclkFrequency = clock; - mem_level->EnabledForThrottle = 1; - mem_level->EnabledForActivity = 0; - mem_level->UpHyst = data->current_profile_setting.mclk_up_hyst; - mem_level->DownHyst = data->current_profile_setting.mclk_down_hyst; - mem_level->VoltageDownHyst = 0; - mem_level->ActivityLevel = data->current_profile_setting.mclk_activity; - mem_level->StutterEnable = false; - mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - if (mclk_stutter_mode_threshold && - (clock <= mclk_stutter_mode_threshold) && - (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) - mem_level->StutterEnable = true; - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); - } - return result; -} - -static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - int result; - /* populate MCLK dpm table to SMU7 */ - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, MemoryLevel); - uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) * - SMU74_MAX_LEVELS_MEMORY; - struct SMU74_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = polaris10_populate_single_memory_level(hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &levels[i]); - if (i == dpm_table->mclk_table.count - 1) { - levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - levels[i].EnabledForActivity = 1; - } - if (result) - return result; - } - - /* In order to prevent MC activity from stutter mode to push DPM up, - * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not affected by - * up threshold or and MCLK DPM latency. - */ - levels[0].ActivityLevel = 0x1f; - CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = - (uint8_t)dpm_table->mclk_table.count; - hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - -static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pat) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else - return -EINVAL; - - return 0; -} - -static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - int result = 0; - uint32_t sclk_frequency; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMIO_Pattern vol_level; - uint32_t mvdd; - - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - /* Get MinVoltage and Frequency from DPM0, - * already converted to SMC_UL */ - sclk_frequency = data->vbios_boot_state.sclk_bootup_value; - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, - sclk_frequency, - &table->ACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDC voltage value " - "in Clock Dependency Table", - ); - - result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency, &(table->ACPILevel.SclkSetting)); - PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result); - - table->ACPILevel.DeepSleepDivId = 0; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); - - - /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ - table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, - table->MemoryACPILevel.MclkFrequency, - &table->MemoryACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDCI voltage value " - "in Clock Dependency Table", - ); - - if (!((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || - (data->mclk_dpm_key_disabled))) - polaris10_populate_mvdd_value(hwmgr, - data->dpm_table.mclk_table.dpm_levels[0].value, - &vol_level); - - if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level)) - table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); - else - table->MemoryACPILevel.MinMvdd = 0; - - table->MemoryACPILevel.StutterEnable = false; - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); - - return result; -} - -static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->VceLevelCount = (uint8_t)(mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage = 0; - table->VceLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - - table->VceLevel[count].MinVoltage |= - (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /*retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, - int32_t eng_clock, int32_t mem_clock, - SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs) -{ - uint32_t dram_timing; - uint32_t dram_timing2; - uint32_t burst_time; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - eng_clock, mem_clock); - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); - arb_regs->McArbBurstTime = (uint8_t)burst_time; - - return 0; -} - -static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct SMU74_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - int result = 0; - - for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { - result = polaris10_populate_memory_timing_parameters(hwmgr, - hw_data->dpm_table.sclk_table.dpm_levels[i].value, - hw_data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - if (result == 0) - result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j); - if (result != 0) - return result; - } - } - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU74_Discrete_MCArbDramTimingTable), - SMC_RAM_END); - return result; -} - -static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->UvdLevelCount = (uint8_t)(mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].MinVoltage = 0; - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); - } - - return result; -} - -static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value * - VOLTAGE_SCALE; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return 0; -} - -static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint8_t count, level; - - count = (uint8_t)(table_info->vdd_dep_on_sclk->count); - - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_sclk->entries[level].clk >= - hw_data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(table_info->vdd_dep_on_mclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_mclk->entries[level].clk >= - hw_data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - uint8_t i, stretch_amount, volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (67 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - - if (hwmgr->chip_id == CHIP_POLARIS10) { - if (hwmgr->is_kicker) { - min = 1200; - max = 2500; - } else { - min = 1000; - max = 2300; - } - } else if (hwmgr->chip_id == CHIP_POLARIS11) { - if (hwmgr->is_kicker) { - min = 900; - max = 2100; - } else { - min = 1100; - max = 2100; - } - } else { - min = 1100; - max = 2100; - } - - ro = efuse * (max - min) / 255 + min; - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - if (hwmgr->chip_id == CHIP_POLARIS10) { - volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \ - (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); - volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \ - (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); - } else { - volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \ - (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000))); - volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \ - (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000))); - } - - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); - - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; - /* Populate CKS Lookup Table */ - if (stretch_amount == 0 || stretch_amount > 5) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); - - return 0; -} - -static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint16_t config; - - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - PP_ASSERT_WITH_CODE(false, - "VDDC should be on SVI2 control in merged mode!", - ); - } - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + - offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } - - return 0; -} - - -static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - int result = 0; - struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; - AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; - AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; - uint32_t tmp, i; - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - - if (!hwmgr->avfs_supported) - return 0; - - result = atomctrl_get_avfs_information(hwmgr, &avfs_params); - - if (0 == result) { - if (((adev->pdev->device == 0x67ef) && - ((adev->pdev->revision == 0xe0) || - (adev->pdev->revision == 0xe5))) || - ((adev->pdev->device == 0x67ff) && - ((adev->pdev->revision == 0xcf) || - (adev->pdev->revision == 0xef) || - (adev->pdev->revision == 0xff)))) { - avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; - if ((adev->pdev->device == 0x67ef && adev->pdev->revision == 0xe5) || - (adev->pdev->device == 0x67ff && adev->pdev->revision == 0xef)) { - if ((avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 == 0xEA522DD3) && - (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 == 0x5645A) && - (avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 == 0x33F9E) && - (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 == 0xFFFFC5CC) && - (avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 == 0x1B1A) && - (avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b == 0xFFFFFCED)) { - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF718F1D4; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x323FD; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x1E455; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; - avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x23; - } - } - } else if (hwmgr->chip_id == CHIP_POLARIS12 && !hwmgr->is_kicker) { - avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF6B024DD; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x3005E; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0x18A5F; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0x315; - avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFED1; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x3B; - } else if (((adev->pdev->device == 0x67df) && - ((adev->pdev->revision == 0xe0) || - (adev->pdev->revision == 0xe3) || - (adev->pdev->revision == 0xe4) || - (adev->pdev->revision == 0xe5) || - (adev->pdev->revision == 0xe7) || - (adev->pdev->revision == 0xef))) || - ((adev->pdev->device == 0x6fdf) && - ((adev->pdev->revision == 0xef) || - (adev->pdev->revision == 0xff)))) { - avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage = 1; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0 = 0xF843B66B; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1 = 0x59CB5; - avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2 = 0xFFFF287F; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1 = 0; - avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2 = 0xFF23; - avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b = 0x58; - } - } - - if (0 == result) { - table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); - table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); - table->BTCGB_VDROOP_TABLE[0].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); - table->BTCGB_VDROOP_TABLE[1].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); - table->BTCGB_VDROOP_TABLE[1].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); - table->BTCGB_VDROOP_TABLE[1].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); - table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); - table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); - table->AVFSGB_VDROOP_TABLE[0].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); - table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24; - table->AVFSGB_VDROOP_TABLE[0].m2_shift = 12; - table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); - table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); - table->AVFSGB_VDROOP_TABLE[1].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); - table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24; - table->AVFSGB_VDROOP_TABLE[1].m2_shift = 12; - table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); - AVFS_meanNsigma.Aconstant[0] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); - AVFS_meanNsigma.Aconstant[1] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); - AVFS_meanNsigma.Aconstant[2] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); - AVFS_meanNsigma.DC_tol_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); - AVFS_meanNsigma.Platform_mean = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); - AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); - AVFS_meanNsigma.Platform_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); - - for (i = 0; i < NUM_VFT_COLUMNS; i++) { - AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); - AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100); - } - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma), - &tmp, SMC_RAM_END); - - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_meanNsigma, - sizeof(AVFS_meanNsigma_t), - SMC_RAM_END); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable), - &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_SclkOffset, - sizeof(AVFS_Sclk_Offset_t), - SMC_RAM_END); - - data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); - data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; - } - return result; -} - -static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - -static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &polaris10_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0]; - -} - -static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - uint8_t i; - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - pp_atomctrl_clock_dividers_vi dividers; - - polaris10_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) - polaris10_populate_smc_voltage_tables(hwmgr, table); - - table->SystemFlags = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (hw_data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = polaris10_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); - } - - result = polaris10_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = polaris10_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = polaris10_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = polaris10_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = polaris10_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - /* Since only the initial state is completely set up at this point - * (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = polaris10_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = polaris10_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - result = polaris10_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = polaris10_populate_smc_initailial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot State!", return result); - - result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate BAPM Parameters!", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = polaris10_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate Clock Stretcher Data Table!", - return result); - } - - result = polaris10_populate_avfs_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;); - - table->CurrSclkPllRange = 0xff; - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; - table->PCIeGenInterval = 1; - table->VRConfig = 0; - - result = polaris10_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate VRConfig setting!", return result); - hw_data->vr_config = table->VRConfig; - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin)) { - table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - /* Thermal Output GPIO */ - if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, - &gpio_pin)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; - - /* For porlarity read GPIOPAD_A with assigned Gpio pin - * since VBIOS will program this register to set 'inactive state', - * driver can then determine 'active state' from this and - * program SMU with correct polarity - */ - table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) - & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot) - && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal)) - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } else { - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - /* Populate BIF_SCLK levels into SMC DPM table */ - for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], ÷rs); - PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result); - - if (i == 0) - table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); - else - table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); - } - - for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController), - SMC_RAM_END); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result); - - result = polaris10_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload arb data to SMC memory!", return result); - - result = polaris10_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - return 0; -} - -static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return polaris10_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (!hwmgr->avfs_supported) - return 0; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting, - NULL); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); - - /* Apply avfs cks-off voltages to avoid the overshoot - * when switching to the highest sclk frequency - */ - if (data->apply_avfs_cks_off_voltage) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ApplyAvfsCksOffVoltage, NULL); - - return 0; -} - -static int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (smu_data->smu7_data.fan_table_start == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - /* use hardware fan control */ - if (hwmgr->thermal_controller.use_hw_fan_control) - return 0; - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. - usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr-> - thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> - thermal_controller.advanceFanControlParameters.ulCycleDelay * - reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( - hwmgr->device, CGS_IND_REG__SMC, - CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanMinPwm, - hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit, - NULL); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanSclkTarget, - hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit, - NULL); - - if (res) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - return 0; -} - -static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, - UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), - NULL); - return 0; -} - -static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - else - smu_data->smc_state_table.VceBootLevel = 0; - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, - NULL); - return 0; -} - -static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - int max_entry, i; - - max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ? - SMU74_MAX_LEVELS_LINK : - pcie_table->count; - /* Setup BIF_SCLK levels */ - for (i = 0; i < max_entry; i++) - smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; - return 0; -} - -static int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - polaris10_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - polaris10_update_vce_smc_table(hwmgr); - break; - case SMU_BIF_TABLE: - polaris10_update_bif_smc_table(hwmgr); - default: - break; - } - return 0; -} - -static int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - PP_ASSERT_WITH_CODE((result == 0), - "Failed to update SCLK threshold!", return result); - - result = polaris10_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -static uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU74_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity); - case AverageMemoryActivity: - return offsetof(SMU74_SoftRegisters, AverageMemoryActivity); - case PreVBlankGap: - return offsetof(SMU74_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU74_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU74_SoftRegisters, UcodeLoadStatus); - case DRAM_LOG_ADDR_H: - return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU74_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU74_Discrete_DpmTable, VceBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold); - } - break; - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static uint32_t polaris10_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU74_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU74_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU74_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU74_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU74_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU74_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU74_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU74_MAX_LEVELS_MVDD; - case SMU_UVD_MCLK_HANDSHAKE_DISABLE: - return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - -static int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? -1 : 0; -} - -static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -static int polaris10_update_dpm_settings(struct pp_hwmgr *hwmgr, - void *profile_setting) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) - (hwmgr->smu_backend); - struct profile_mode_setting *setting; - struct SMU74_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - - uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, MemoryLevel); - struct SMU74_Discrete_MemoryLevel *mclk_levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; - - if (profile_setting == NULL) - return -EINVAL; - - setting = (struct profile_mode_setting *)profile_setting; - - if (setting->bupdate_sclk) { - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - if (levels[i].ActivityLevel != - cpu_to_be16(setting->sclk_activity)) { - levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); - - clk_activity_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) - + offsetof(SMU74_Discrete_GraphicsLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (levels[i].UpHyst != setting->sclk_up_hyst || - levels[i].DownHyst != setting->sclk_down_hyst) { - levels[i].UpHyst = setting->sclk_up_hyst; - levels[i].DownHyst = setting->sclk_down_hyst; - up_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) - + offsetof(SMU74_Discrete_GraphicsLevel, UpHyst); - down_hyst_offset = array + (sizeof(SMU74_Discrete_GraphicsLevel) * i) - + offsetof(SMU74_Discrete_GraphicsLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); - } - - if (setting->bupdate_mclk) { - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { - if (mclk_levels[i].ActivityLevel != - cpu_to_be16(setting->mclk_activity)) { - mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); - - clk_activity_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) - + offsetof(SMU74_Discrete_MemoryLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || - mclk_levels[i].DownHyst != setting->mclk_down_hyst) { - mclk_levels[i].UpHyst = setting->mclk_up_hyst; - mclk_levels[i].DownHyst = setting->mclk_down_hyst; - up_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) - + offsetof(SMU74_Discrete_MemoryLevel, UpHyst); - down_hyst_offset = mclk_array + (sizeof(SMU74_Discrete_MemoryLevel) * i) - + offsetof(SMU74_Discrete_MemoryLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); - } - return 0; -} - -const struct pp_smumgr_func polaris10_smu_funcs = { - .name = "polaris10_smu", - .smu_init = polaris10_smu_init, - .smu_fini = smu7_smu_fini, - .start_smu = polaris10_start_smu, - .check_fw_load_finish = smu7_check_fw_load_finish, - .request_smu_load_fw = smu7_reload_firmware, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = smu7_send_msg_to_smc, - .send_msg_to_smc_with_parameter = smu7_send_msg_to_smc_with_parameter, - .get_argument = smu7_get_argument, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .update_smc_table = polaris10_update_smc_table, - .get_offsetof = polaris10_get_offsetof, - .process_firmware_header = polaris10_process_firmware_header, - .init_smc_table = polaris10_init_smc_table, - .update_sclk_threshold = polaris10_update_sclk_threshold, - .thermal_avfs_enable = polaris10_thermal_avfs_enable, - .thermal_setup_fan_table = polaris10_thermal_setup_fan_table, - .populate_all_graphic_levels = polaris10_populate_all_graphic_levels, - .populate_all_memory_levels = polaris10_populate_all_memory_levels, - .get_mac_definition = polaris10_get_mac_definition, - .is_dpm_running = polaris10_is_dpm_running, - .is_hw_avfs_present = polaris10_is_hw_avfs_present, - .update_dpm_settings = polaris10_update_dpm_settings, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h deleted file mode 100644 index 1ec425df9eda..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2015 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 _POLARIS10_SMUMANAGER_H -#define _POLARIS10_SMUMANAGER_H - - -#include -#include "smu74.h" -#include "smu74_discrete.h" -#include "smu7_smumgr.h" - -#define SMC_RAM_END 0x40000 - -struct polaris10_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; - - uint32_t DisplayCac; - uint32_t BAPM_TEMP_GRADIENT; - uint16_t BAPMTI_R[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; - uint16_t BAPMTI_RC[SMU74_DTE_ITERATIONS * SMU74_DTE_SOURCES * SMU74_DTE_SINKS]; -}; - -struct polaris10_range_table { - uint32_t trans_lower_frequency; /* in 10khz */ - uint32_t trans_upper_frequency; -}; - -struct polaris10_smumgr { - struct smu7_smumgr smu7_data; - uint8_t protected_mode; - SMU74_Discrete_DpmTable smc_state_table; - struct SMU74_Discrete_Ulv ulv_setting; - struct SMU74_Discrete_PmFuses power_tune_table; - struct polaris10_range_table range_table[NUM_SCLK_RANGE]; - const struct polaris10_pt_defaults *power_tune_defaults; - uint32_t bif_sclk_table[SMU74_MAX_LEVELS_LINK]; -}; - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c deleted file mode 100644 index ea2279bb8cbf..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright 2016 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 - -#include "smumgr.h" -#include "smu10_inc.h" -#include "soc15_common.h" -#include "smu10_smumgr.h" -#include "ppatomctrl.h" -#include "rv_ppsmc.h" -#include "smu10_driver_if.h" -#include "smu10.h" -#include "pp_debug.h" - - -#define BUFFER_SIZE 80000 -#define MAX_STRING_SIZE 15 -#define BUFFER_SIZETWO 131072 - -#define MP0_Public 0x03800000 -#define MP0_SRAM 0x03900000 -#define MP1_Public 0x03b00000 -#define MP1_SRAM 0x03c00004 - -#define smnMP1_FIRMWARE_FLAGS 0x3010028 - - -static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t reg; - - reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); - - phm_wait_for_register_unequal(hwmgr, reg, - 0, MP1_C2PMSG_90__CONTENT_MASK); - - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); -} - -static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, - uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); - - return 0; -} - -static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); -} - -static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - - smu10_wait_for_response(hwmgr); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - smu10_send_msg_to_smc_without_waiting(hwmgr, msg); - - if (smu10_wait_for_response(hwmgr) == 0) - printk("Failed to send Message %x.\n", msg); - - return 0; -} - - -static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - struct amdgpu_device *adev = hwmgr->adev; - - smu10_wait_for_response(hwmgr); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); - - smu10_send_msg_to_smc_without_waiting(hwmgr, msg); - - - if (smu10_wait_for_response(hwmgr) == 0) - printk("Failed to send Message %x.\n", msg); - - return 0; -} - -static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct smu10_smumgr *priv = - (struct smu10_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -EINVAL;); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL;); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL;); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableSmu2Dram, - priv->smu_tables.entry[table_id].table_id, - NULL); - - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); - - memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table, - priv->smu_tables.entry[table_id].size); - - return 0; -} - -static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct smu10_smumgr *priv = - (struct smu10_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -EINVAL;); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL;); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL;); - - memcpy(priv->smu_tables.entry[table_id].table, table, - priv->smu_tables.entry[table_id].size); - - amdgpu_asic_flush_hdp(adev, NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableDram2Smu, - priv->smu_tables.entry[table_id].table_id, - NULL); - - return 0; -} - -static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr) -{ - uint32_t smc_driver_if_version; - - smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetDriverIfVersion, - &smc_driver_if_version); - - if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) && - (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) { - pr_err("Attempt to read SMC IF Version Number Failed!\n"); - return -EINVAL; - } - - return 0; -} - -static int smu10_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct smu10_smumgr *priv = - (struct smu10_smumgr *)(hwmgr->smu_backend); - - if (priv) { - amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, - &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, - &priv->smu_tables.entry[SMU10_WMTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, - &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, - &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - } - - return 0; -} - -static int smu10_start_smu(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion, &hwmgr->smu_version); - adev->pm.fw_version = hwmgr->smu_version >> 8; - - if (!(adev->apu_flags & AMD_APU_IS_RAVEN2) && - (adev->apu_flags & AMD_APU_IS_RAVEN) && - adev->pm.fw_version < 0x1e45) - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - - if (smu10_verify_smc_interface(hwmgr)) - return -EINVAL; - - return 0; -} - -static int smu10_smu_init(struct pp_hwmgr *hwmgr) -{ - struct smu10_smumgr *priv; - int r; - - priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL); - - if (!priv) - return -ENOMEM; - - hwmgr->smu_backend = priv; - - /* allocate space for watermarks table */ - r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(Watermarks_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[SMU10_WMTABLE].handle, - &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, - &priv->smu_tables.entry[SMU10_WMTABLE].table); - - if (r) - goto err0; - - priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01; - priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t); - priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS; - - /* allocate space for watermarks table */ - r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(DpmClocks_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, - &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, - &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); - - if (r) - goto err1; - - priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01; - priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t); - priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS; - - return 0; - -err1: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, - &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, - &priv->smu_tables.entry[SMU10_WMTABLE].table); -err0: - kfree(priv); - return -EINVAL; -} - -static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) -{ - int ret; - - if (rw) - ret = smu10_copy_table_from_smc(hwmgr, table, table_id); - else - ret = smu10_copy_table_to_smc(hwmgr, table, table_id); - - return ret; -} - - -const struct pp_smumgr_func smu10_smu_funcs = { - .name = "smu10_smu", - .smu_init = &smu10_smu_init, - .smu_fini = &smu10_smu_fini, - .start_smu = &smu10_start_smu, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &smu10_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .get_argument = smu10_read_arg_from_smc, - .smc_table_manager = smu10_smc_table_manager, -}; - - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h deleted file mode 100644 index 9c2be74a2b2f..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef PP_SMU10_SMUMANAGER_H -#define PP_SMU10_SMUMANAGER_H - -#include "rv_ppsmc.h" -#include "smu10_driver_if.h" - -#define MAX_SMU_TABLE 2 - -struct smu_table_entry { - uint32_t version; - uint32_t size; - uint32_t table_id; - uint64_t mc_addr; - void *table; - struct amdgpu_bo *handle; -}; - -struct smu_table_array { - struct smu_table_entry entry[MAX_SMU_TABLE]; -}; - -struct smu10_smumgr { - struct smu_table_array smu_tables; -}; - - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c deleted file mode 100644 index aae25243eb10..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include "smumgr.h" -#include "smu_ucode_xfer_vi.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "smu7_ppsmc.h" -#include "smu7_smumgr.h" -#include "smu7_common.h" - -#include "polaris10_pwrvirus.h" - -#define SMU7_SMC_SIZE 0x20000 - -static int smu7_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t limit) -{ - PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL); - PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL); - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, smc_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */ - return 0; -} - - -int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit) -{ - uint32_t data; - uint32_t addr; - uint8_t *dest_byte; - uint8_t i, data_byte[4] = {0}; - uint32_t *pdata = (uint32_t *)&data_byte; - - PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL); - PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL); - - addr = smc_start_address; - - while (byte_count >= 4) { - smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); - - *dest = PP_SMC_TO_HOST_UL(data); - - dest += 1; - byte_count -= 4; - addr += 4; - } - - if (byte_count) { - smu7_read_smc_sram_dword(hwmgr, addr, &data, limit); - *pdata = PP_SMC_TO_HOST_UL(data); - /* Cast dest into byte type in dest_byte. This way, we don't overflow if the allocated memory is not 4-byte aligned. */ - dest_byte = (uint8_t *)dest; - for (i = 0; i < byte_count; i++) - dest_byte[i] = data_byte[i]; - } - - return 0; -} - - -int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, - const uint8_t *src, uint32_t byte_count, uint32_t limit) -{ - int result; - uint32_t data = 0; - uint32_t original_data; - uint32_t addr = 0; - uint32_t extra_shift; - - PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL); - PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL); - - addr = smc_start_address; - - while (byte_count >= 4) { - /* Bytes are written into the SMC addres space with the MSB first. */ - data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - - result = smu7_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); - - src += 4; - byte_count -= 4; - addr += 4; - } - - if (0 != byte_count) { - - data = 0; - - result = smu7_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - - original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); - - extra_shift = 8 * (4 - byte_count); - - while (byte_count > 0) { - /* Bytes are written into the SMC addres space with the MSB first. */ - data = (0x100 * data) + *src++; - byte_count--; - } - - data <<= extra_shift; - - data |= (original_data & ~((~0UL) << extra_shift)); - - result = smu7_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data); - } - - return 0; -} - - -int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr) -{ - static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; - - smu7_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); - - return 0; -} - -bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr) -{ - return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) - && (0x20100 <= cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_PC_C))); -} - -int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - int ret; - - PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - - ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); - - if (ret == 0xFE) - pr_debug("last message was not supported\n"); - else if (ret != 1) - pr_info("\n last message was failed ret is %d\n", ret); - - cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0); - cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); - - PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - - ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); - - if (ret == 0xFE) - pr_debug("message %x was not supported\n", msg); - else if (ret != 1) - pr_info("\n failed to send message %x ret is %d \n", msg, ret); - - return 0; -} - -int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter) -{ - PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - - cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); - - return smu7_send_msg_to_smc(hwmgr, msg); -} - -uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr) -{ - return cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); -} - -int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr) -{ - return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL); -} - -enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type) -{ - enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; - - switch (fw_type) { - case UCODE_ID_SMU: - result = CGS_UCODE_ID_SMU; - break; - case UCODE_ID_SMU_SK: - result = CGS_UCODE_ID_SMU_SK; - break; - case UCODE_ID_SDMA0: - result = CGS_UCODE_ID_SDMA0; - break; - case UCODE_ID_SDMA1: - result = CGS_UCODE_ID_SDMA1; - break; - case UCODE_ID_CP_CE: - result = CGS_UCODE_ID_CP_CE; - break; - case UCODE_ID_CP_PFP: - result = CGS_UCODE_ID_CP_PFP; - break; - case UCODE_ID_CP_ME: - result = CGS_UCODE_ID_CP_ME; - break; - case UCODE_ID_CP_MEC: - result = CGS_UCODE_ID_CP_MEC; - break; - case UCODE_ID_CP_MEC_JT1: - result = CGS_UCODE_ID_CP_MEC_JT1; - break; - case UCODE_ID_CP_MEC_JT2: - result = CGS_UCODE_ID_CP_MEC_JT2; - break; - case UCODE_ID_RLC_G: - result = CGS_UCODE_ID_RLC_G; - break; - case UCODE_ID_MEC_STORAGE: - result = CGS_UCODE_ID_STORAGE; - break; - default: - break; - } - - return result; -} - - -int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit) -{ - int result; - - result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); - - *value = result ? 0 : cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11); - - return result; -} - -int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit) -{ - int result; - - result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit); - - if (result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value); - - return 0; -} - -static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr, - uint32_t fw_type, - struct SMU_Entry *entry) -{ - int result = 0; - struct cgs_firmware_info info = {0}; - - result = cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(fw_type), - &info); - - if (!result) { - entry->version = info.fw_version; - entry->id = (uint16_t)fw_type; - entry->image_addr_high = upper_32_bits(info.mc_addr); - entry->image_addr_low = lower_32_bits(info.mc_addr); - entry->meta_data_addr_high = 0; - entry->meta_data_addr_low = 0; - - /* digest need be excluded out */ - if (!hwmgr->not_vf) - info.image_size -= 20; - entry->data_size_byte = info.image_size; - entry->num_register_entries = 0; - } - - if ((fw_type == UCODE_ID_RLC_G) - || (fw_type == UCODE_ID_CP_MEC)) - entry->flags = 1; - else - entry->flags = 0; - - return 0; -} - -int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - uint32_t fw_to_load; - int r = 0; - - amdgpu_ucode_init_bo(hwmgr->adev); - - if (smu_data->soft_regs_start) - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - smu_data->soft_regs_start + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, UcodeLoadStatus), - 0x0); - - if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */ - if (hwmgr->not_vf) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SMU_DRAM_ADDR_HI, - upper_32_bits(smu_data->smu_buffer.mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SMU_DRAM_ADDR_LO, - lower_32_bits(smu_data->smu_buffer.mc_addr), - NULL); - } - fw_to_load = UCODE_ID_RLC_G_MASK - + UCODE_ID_SDMA0_MASK - + UCODE_ID_SDMA1_MASK - + UCODE_ID_CP_CE_MASK - + UCODE_ID_CP_ME_MASK - + UCODE_ID_CP_PFP_MASK - + UCODE_ID_CP_MEC_MASK; - } else { - fw_to_load = UCODE_ID_RLC_G_MASK - + UCODE_ID_SDMA0_MASK - + UCODE_ID_SDMA1_MASK - + UCODE_ID_CP_CE_MASK - + UCODE_ID_CP_ME_MASK - + UCODE_ID_CP_PFP_MASK - + UCODE_ID_CP_MEC_MASK - + UCODE_ID_CP_MEC_JT1_MASK - + UCODE_ID_CP_MEC_JT2_MASK; - } - - if (!smu_data->toc) { - struct SMU_DRAMData_TOC *toc; - - smu_data->toc = kzalloc(sizeof(struct SMU_DRAMData_TOC), GFP_KERNEL); - if (!smu_data->toc) - return -ENOMEM; - toc = smu_data->toc; - toc->num_entries = 0; - toc->structure_version = 1; - - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - if (!hwmgr->not_vf) - PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr, - UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]), - "Failed to Get Firmware Entry.", r = -EINVAL; goto failed); - } - memcpy_toio(smu_data->header_buffer.kaddr, smu_data->toc, - sizeof(struct SMU_DRAMData_TOC)); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DRV_DRAM_ADDR_HI, - upper_32_bits(smu_data->header_buffer.mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DRV_DRAM_ADDR_LO, - lower_32_bits(smu_data->header_buffer.mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load, NULL); - - r = smu7_check_fw_load_finish(hwmgr, fw_to_load); - if (!r) - return 0; - - pr_err("SMU load firmware failed\n"); - -failed: - kfree(smu_data->toc); - smu_data->toc = NULL; - return r; -} - -/* Check if the FW has been loaded, SMU will not return if loading has not finished. */ -int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type) -{ - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - uint32_t ret; - - ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11, - smu_data->soft_regs_start + smum_get_offsetof(hwmgr, - SMU_SoftRegisters, UcodeLoadStatus), - fw_type, fw_type); - return ret; -} - -int smu7_reload_firmware(struct pp_hwmgr *hwmgr) -{ - return hwmgr->smumgr_funcs->start_smu(hwmgr); -} - -static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit) -{ - uint32_t byte_count = length; - - PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL); - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1); - - for (; byte_count >= 4; byte_count -= 4) - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++); - - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); - - PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); - - return 0; -} - - -int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - struct cgs_firmware_info info = {0}; - - if (smu_data->security_hard_key == 1) - cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); - else - cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info); - - hwmgr->is_kicker = info.is_kicker; - hwmgr->smu_version = info.version; - result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE); - - return result; -} - -static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size) -{ - int i; - uint32_t reg, data; - - for (i = 0; i < size; i++) { - reg = pvirus->reg; - data = pvirus->data; - if (reg != 0xffffffff) - cgs_write_register(hwmgr->device, reg, data); - else - break; - pvirus++; - } -} - -static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section) -{ - int i; - - cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl); - cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi); - cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo); - for (i = 0; i < section->dfy_size; i++) - cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]); -} - -int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr) -{ - execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre)); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section1); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section2); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section3); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section4); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section5); - execute_pwr_dfy_table(hwmgr, &pwr_virus_section6); - execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post)); - - return 0; -} - -int smu7_init(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu_data; - int r; - /* Allocate memory for backend private data */ - smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - smu_data->header_buffer.data_size = - ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; - -/* Allocate FW image data structure and header buffer and - * send the header buffer address to SMU */ - r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - smu_data->header_buffer.data_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &smu_data->header_buffer.handle, - &smu_data->header_buffer.mc_addr, - &smu_data->header_buffer.kaddr); - - if (r) - return -EINVAL; - - if (!hwmgr->not_vf) - return 0; - - smu_data->smu_buffer.data_size = 200*4096; - r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - smu_data->smu_buffer.data_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &smu_data->smu_buffer.handle, - &smu_data->smu_buffer.mc_addr, - &smu_data->smu_buffer.kaddr); - - if (r) { - amdgpu_bo_free_kernel(&smu_data->header_buffer.handle, - &smu_data->header_buffer.mc_addr, - &smu_data->header_buffer.kaddr); - return -EINVAL; - } - - if (smum_is_hw_avfs_present(hwmgr) && - (hwmgr->feature_mask & PP_AVFS_MASK)) - hwmgr->avfs_supported = true; - - return 0; -} - - -int smu7_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - amdgpu_bo_free_kernel(&smu_data->header_buffer.handle, - &smu_data->header_buffer.mc_addr, - &smu_data->header_buffer.kaddr); - - if (hwmgr->not_vf) - amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle, - &smu_data->smu_buffer.mc_addr, - &smu_data->smu_buffer.kaddr); - - - kfree(smu_data->toc); - smu_data->toc = NULL; - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - return 0; -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h deleted file mode 100644 index e7303dc8c260..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2015 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 _SMU7_SMUMANAGER_H -#define _SMU7_SMUMANAGER_H - - -#include - -#define SMC_RAM_END 0x40000 - -struct smu7_buffer_entry { - uint32_t data_size; - uint64_t mc_addr; - void *kaddr; - struct amdgpu_bo *handle; -}; - -struct smu7_smumgr { - struct smu7_buffer_entry smu_buffer; - struct smu7_buffer_entry header_buffer; - struct SMU_DRAMData_TOC *toc; - - uint32_t soft_regs_start; - uint32_t dpm_table_start; - uint32_t mc_reg_table_start; - uint32_t fan_table_start; - uint32_t arb_table_start; - uint32_t ulv_setting_starts; - uint8_t security_hard_key; - uint32_t acpi_optimization; - uint32_t avfs_btc_param; -}; - - -int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, - uint32_t *dest, uint32_t byte_count, uint32_t limit); -int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, - const uint8_t *src, uint32_t byte_count, uint32_t limit); -int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr); -bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr); -int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); -int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, - uint32_t parameter); -uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr); -int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr); - -enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type); -int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, - uint32_t *value, uint32_t limit); -int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, - uint32_t value, uint32_t limit); - -int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr); -int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type); -int smu7_reload_firmware(struct pp_hwmgr *hwmgr); -int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr); -int smu7_init(struct pp_hwmgr *hwmgr); -int smu7_smu_fini(struct pp_hwmgr *hwmgr); - -int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c deleted file mode 100644 index 76d4f12ceedf..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Copyright 2015 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 -#include -#include -#include -#include -#include - -#include "cgs_common.h" -#include "smu/smu_8_0_d.h" -#include "smu/smu_8_0_sh_mask.h" -#include "smu8.h" -#include "smu8_fusion.h" -#include "smu8_smumgr.h" -#include "cz_ppsmc.h" -#include "smu_ucode_xfer_cz.h" -#include "gca/gfx_8_0_d.h" -#include "gca/gfx_8_0_sh_mask.h" -#include "smumgr.h" - -#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32) - -static const enum smu8_scratch_entry firmware_list[] = { - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, -}; - -static uint32_t smu8_get_argument(struct pp_hwmgr *hwmgr) -{ - if (hwmgr == NULL || hwmgr->device == NULL) - return 0; - - return cgs_read_register(hwmgr->device, - mmSMU_MP1_SRBM2P_ARG_0); -} - -/* Send a message to the SMC, and wait for its response.*/ -static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - int result = 0; - ktime_t t_start; - s64 elapsed_us; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, - SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); - if (result != 0) { - /* Read the last message to SMU, to report actual cause */ - uint32_t val = cgs_read_register(hwmgr->device, - mmSMU_MP1_SRBM2P_MSG_0); - pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n", - __func__, msg, val); - return result; - } - t_start = ktime_get(); - - cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); - - cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); - cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); - - result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, - SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); - - elapsed_us = ktime_us_delta(ktime_get(), t_start); - - WARN(result, "%s(0x%04x, %#x) timed out after %lld us\n", - __func__, msg, parameter, elapsed_us); - - return result; -} - -static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - return smu8_send_msg_to_smc_with_parameter(hwmgr, msg, 0); -} - -static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr, - uint32_t smc_address, uint32_t limit) -{ - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - if (0 != (3 & smc_address)) { - pr_err("SMC address must be 4 byte aligned\n"); - return -EINVAL; - } - - if (limit <= (smc_address + 3)) { - pr_err("SMC address beyond the SMC RAM area\n"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0, - SMN_MP1_SRAM_START_ADDR + smc_address); - - return 0; -} - -static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr, - uint32_t smc_address, uint32_t value, uint32_t limit) -{ - int result; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - result = smu8_set_smc_sram_address(hwmgr, smc_address, limit); - if (!result) - cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value); - - return result; -} - -static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr, - uint32_t firmware) -{ - int i; - uint32_t index = SMN_MP1_SRAM_START_ADDR + - SMU8_FIRMWARE_HEADER_LOCATION + - offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); - - for (i = 0; i < hwmgr->usec_timeout; i++) { - if (firmware == - (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware)) - break; - udelay(1); - } - - if (i >= hwmgr->usec_timeout) { - pr_err("SMU check loaded firmware failed.\n"); - return -EINVAL; - } - - return 0; -} - -static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr) -{ - uint32_t reg_data; - uint32_t tmp; - int ret = 0; - struct cgs_firmware_info info = {0}; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - ret = cgs_get_firmware_info(hwmgr->device, - CGS_UCODE_ID_CP_MEC, &info); - - if (ret) - return -EINVAL; - - /* Disable MEC parsing/prefetching */ - tmp = cgs_read_register(hwmgr->device, - mmCP_MEC_CNTL); - tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); - tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); - cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp); - - tmp = cgs_read_register(hwmgr->device, - mmCP_CPC_IC_BASE_CNTL); - - tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); - tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); - tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); - tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); - cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); - - reg_data = lower_32_bits(info.mc_addr) & - PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); - cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data); - - reg_data = upper_32_bits(info.mc_addr) & - PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); - cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data); - - return 0; -} - -static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr, - enum smu8_scratch_entry firmware_enum) -{ - uint8_t ret = 0; - - switch (firmware_enum) { - case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0: - ret = UCODE_ID_SDMA0; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1: - if (hwmgr->chip_id == CHIP_STONEY) - ret = UCODE_ID_SDMA0; - else - ret = UCODE_ID_SDMA1; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE: - ret = UCODE_ID_CP_CE; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP: - ret = UCODE_ID_CP_PFP; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME: - ret = UCODE_ID_CP_ME; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1: - ret = UCODE_ID_CP_MEC_JT1; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: - if (hwmgr->chip_id == CHIP_STONEY) - ret = UCODE_ID_CP_MEC_JT1; - else - ret = UCODE_ID_CP_MEC_JT2; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: - ret = UCODE_ID_GMCON_RENG; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G: - ret = UCODE_ID_RLC_G; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH: - ret = UCODE_ID_RLC_SCRATCH; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM: - ret = UCODE_ID_RLC_SRM_ARAM; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM: - ret = UCODE_ID_RLC_SRM_DRAM; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM: - ret = UCODE_ID_DMCU_ERAM; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM: - ret = UCODE_ID_DMCU_IRAM; - break; - case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING: - ret = TASK_ARG_INIT_MM_PWR_LOG; - break; - case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT: - case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING: - case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS: - case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT: - case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START: - case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS: - ret = TASK_ARG_REG_MMIO; - break; - case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE: - ret = TASK_ARG_INIT_CLK_TABLE; - break; - } - - return ret; -} - -static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type) -{ - enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; - - switch (fw_type) { - case UCODE_ID_SDMA0: - result = CGS_UCODE_ID_SDMA0; - break; - case UCODE_ID_SDMA1: - result = CGS_UCODE_ID_SDMA1; - break; - case UCODE_ID_CP_CE: - result = CGS_UCODE_ID_CP_CE; - break; - case UCODE_ID_CP_PFP: - result = CGS_UCODE_ID_CP_PFP; - break; - case UCODE_ID_CP_ME: - result = CGS_UCODE_ID_CP_ME; - break; - case UCODE_ID_CP_MEC_JT1: - result = CGS_UCODE_ID_CP_MEC_JT1; - break; - case UCODE_ID_CP_MEC_JT2: - result = CGS_UCODE_ID_CP_MEC_JT2; - break; - case UCODE_ID_RLC_G: - result = CGS_UCODE_ID_RLC_G; - break; - default: - break; - } - - return result; -} - -static int smu8_smu_populate_single_scratch_task( - struct pp_hwmgr *hwmgr, - enum smu8_scratch_entry fw_enum, - uint8_t type, bool is_last) -{ - uint8_t i; - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; - struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; - - task->type = type; - task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); - task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; - - for (i = 0; i < smu8_smu->scratch_buffer_length; i++) - if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum) - break; - - if (i >= smu8_smu->scratch_buffer_length) { - pr_err("Invalid Firmware Type\n"); - return -EINVAL; - } - - task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr); - task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr); - task->size_bytes = smu8_smu->scratch_buffer[i].data_size; - - if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) { - struct smu8_ih_meta_data *pIHReg_restore = - (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr; - pIHReg_restore->command = - METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD; - } - - return 0; -} - -static int smu8_smu_populate_single_ucode_load_task( - struct pp_hwmgr *hwmgr, - enum smu8_scratch_entry fw_enum, - bool is_last) -{ - uint8_t i; - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; - struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++]; - - task->type = TASK_TYPE_UCODE_LOAD; - task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum); - task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count; - - for (i = 0; i < smu8_smu->driver_buffer_length; i++) - if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum) - break; - - if (i >= smu8_smu->driver_buffer_length) { - pr_err("Invalid Firmware Type\n"); - return -EINVAL; - } - - task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr); - task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr); - task->size_bytes = smu8_smu->driver_buffer[i].data_size; - - return 0; -} - -static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - - smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count; - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, - TASK_TYPE_UCODE_SAVE, true); - - return 0; -} - -static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr) -{ - int i; - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; - - for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) - toc->JobList[i] = (uint8_t)IGNORE_JOB; - - return 0; -} - -static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; - - toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count; - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, - TASK_TYPE_UCODE_SAVE, false); - - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, - TASK_TYPE_UCODE_SAVE, true); - - return 0; -} - - -static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr; - - toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count; - - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - - if (hwmgr->chip_id == CHIP_STONEY) - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - else - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); - - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); - - /* populate scratch */ - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, - TASK_TYPE_UCODE_LOAD, false); - - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, - TASK_TYPE_UCODE_LOAD, false); - - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, - TASK_TYPE_UCODE_LOAD, true); - - return 0; -} - -static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - - smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count; - - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, - TASK_TYPE_INITIALIZE, true); - return 0; -} - -static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - - smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count; - - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); - if (hwmgr->chip_id != CHIP_STONEY) - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); - if (hwmgr->chip_id != CHIP_STONEY) - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); - smu8_smu_populate_single_ucode_load_task(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); - - return 0; -} - -static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - - smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count; - - smu8_smu_populate_single_scratch_task(hwmgr, - SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, - TASK_TYPE_INITIALIZE, true); - - return 0; -} - -static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - - smu8_smu->toc_entry_used_count = 0; - smu8_smu_initialize_toc_empty_job_list(hwmgr); - smu8_smu_construct_toc_for_rlc_aram_save(hwmgr); - smu8_smu_construct_toc_for_vddgfx_enter(hwmgr); - smu8_smu_construct_toc_for_vddgfx_exit(hwmgr); - smu8_smu_construct_toc_for_power_profiling(hwmgr); - smu8_smu_construct_toc_for_bootup(hwmgr); - smu8_smu_construct_toc_for_clock_table(hwmgr); - - return 0; -} - -static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - uint32_t firmware_type; - uint32_t i; - int ret; - enum cgs_ucode_id ucode_id; - struct cgs_firmware_info info = {0}; - - smu8_smu->driver_buffer_length = 0; - - for (i = 0; i < ARRAY_SIZE(firmware_list); i++) { - - firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr, - firmware_list[i]); - - ucode_id = smu8_convert_fw_type_to_cgs(firmware_type); - - ret = cgs_get_firmware_info(hwmgr->device, - ucode_id, &info); - - if (ret == 0) { - smu8_smu->driver_buffer[i].mc_addr = info.mc_addr; - - smu8_smu->driver_buffer[i].data_size = info.image_size; - - smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i]; - smu8_smu->driver_buffer_length++; - } - } - - return 0; -} - -static int smu8_smu_populate_single_scratch_entry( - struct pp_hwmgr *hwmgr, - enum smu8_scratch_entry scratch_type, - uint32_t ulsize_byte, - struct smu8_buffer_entry *entry) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte); - - entry->data_size = ulsize_byte; - entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr + - smu8_smu->smu_buffer_used_bytes; - entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes; - entry->firmware_ID = scratch_type; - - smu8_smu->smu_buffer_used_bytes += ulsize_aligned; - - return 0; -} - -static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - unsigned long i; - - for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { - if (smu8_smu->scratch_buffer[i].firmware_ID - == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) - break; - } - - *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetClkTableAddrHi, - upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetClkTableAddrLo, - lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, - smu8_smu->toc_entry_clock_table, - NULL); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram, NULL); - - return 0; -} - -static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - unsigned long i; - - for (i = 0; i < smu8_smu->scratch_buffer_length; i++) { - if (smu8_smu->scratch_buffer[i].firmware_ID - == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) - break; - } - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetClkTableAddrHi, - upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetClkTableAddrLo, - lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, - smu8_smu->toc_entry_clock_table, - NULL); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu, NULL); - - return 0; -} - -static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu = hwmgr->smu_backend; - uint32_t smc_address; - uint32_t fw_to_check = 0; - int ret; - - amdgpu_ucode_init_bo(hwmgr->adev); - - smu8_smu_populate_firmware_entries(hwmgr); - - smu8_smu_construct_toc(hwmgr); - - smc_address = SMU8_FIRMWARE_HEADER_LOCATION + - offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); - - smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DriverDramAddrHi, - upper_32_bits(smu8_smu->toc_buffer.mc_addr), - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DriverDramAddrLo, - lower_32_bits(smu8_smu->toc_buffer.mc_addr), - NULL); - - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs, NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_ExecuteJob, - smu8_smu->toc_entry_aram, - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob, - smu8_smu->toc_entry_power_profiling_index, - NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_ExecuteJob, - smu8_smu->toc_entry_initialize_index, - NULL); - - fw_to_check = UCODE_ID_RLC_G_MASK | - UCODE_ID_SDMA0_MASK | - UCODE_ID_SDMA1_MASK | - UCODE_ID_CP_CE_MASK | - UCODE_ID_CP_ME_MASK | - UCODE_ID_CP_PFP_MASK | - UCODE_ID_CP_MEC_JT1_MASK | - UCODE_ID_CP_MEC_JT2_MASK; - - if (hwmgr->chip_id == CHIP_STONEY) - fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK); - - ret = smu8_check_fw_load_finish(hwmgr, fw_to_check); - if (ret) { - pr_err("SMU firmware load failed\n"); - return ret; - } - - ret = smu8_load_mec_firmware(hwmgr); - if (ret) { - pr_err("Mec Firmware load failed\n"); - return ret; - } - - return 0; -} - -static int smu8_start_smu(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev; - - uint32_t index = SMN_MP1_SRAM_START_ADDR + - SMU8_FIRMWARE_HEADER_LOCATION + - offsetof(struct SMU8_Firmware_Header, Version); - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - adev = hwmgr->adev; - - cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index); - hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA); - pr_info("smu version %02d.%02d.%02d\n", - ((hwmgr->smu_version >> 16) & 0xFF), - ((hwmgr->smu_version >> 8) & 0xFF), - (hwmgr->smu_version & 0xFF)); - adev->pm.fw_version = hwmgr->smu_version >> 8; - - return smu8_request_smu_load_fw(hwmgr); -} - -static int smu8_smu_init(struct pp_hwmgr *hwmgr) -{ - int ret = 0; - struct smu8_smumgr *smu8_smu; - - smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL); - if (smu8_smu == NULL) - return -ENOMEM; - - hwmgr->smu_backend = smu8_smu; - - smu8_smu->toc_buffer.data_size = 4096; - smu8_smu->smu_buffer.data_size = - ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) + - ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) + - ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) + - ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + - ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); - - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - smu8_smu->toc_buffer.data_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &smu8_smu->toc_buffer.handle, - &smu8_smu->toc_buffer.mc_addr, - &smu8_smu->toc_buffer.kaddr); - if (ret) - goto err2; - - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - smu8_smu->smu_buffer.data_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &smu8_smu->smu_buffer.handle, - &smu8_smu->smu_buffer.mc_addr, - &smu8_smu->smu_buffer.kaddr); - if (ret) - goto err1; - - if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, - UCODE_ID_RLC_SCRATCH_SIZE_BYTE, - &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { - pr_err("Error when Populate Firmware Entry.\n"); - goto err0; - } - - if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, - UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, - &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { - pr_err("Error when Populate Firmware Entry.\n"); - goto err0; - } - if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, - UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, - &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { - pr_err("Error when Populate Firmware Entry.\n"); - goto err0; - } - - if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, - SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, - sizeof(struct SMU8_MultimediaPowerLogData), - &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { - pr_err("Error when Populate Firmware Entry.\n"); - goto err0; - } - - if (0 != smu8_smu_populate_single_scratch_entry(hwmgr, - SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, - sizeof(struct SMU8_Fusion_ClkTable), - &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) { - pr_err("Error when Populate Firmware Entry.\n"); - goto err0; - } - - return 0; - -err0: - amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, - &smu8_smu->smu_buffer.mc_addr, - &smu8_smu->smu_buffer.kaddr); -err1: - amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, - &smu8_smu->toc_buffer.mc_addr, - &smu8_smu->toc_buffer.kaddr); -err2: - kfree(smu8_smu); - return -EINVAL; -} - -static int smu8_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct smu8_smumgr *smu8_smu; - - if (hwmgr == NULL || hwmgr->device == NULL) - return -EINVAL; - - smu8_smu = hwmgr->smu_backend; - if (smu8_smu) { - amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle, - &smu8_smu->toc_buffer.mc_addr, - &smu8_smu->toc_buffer.kaddr); - amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle, - &smu8_smu->smu_buffer.mc_addr, - &smu8_smu->smu_buffer.kaddr); - kfree(smu8_smu); - } - - return 0; -} - -static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr, - unsigned long check_feature) -{ - int result; - uint32_t features; - - result = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_GetFeatureStatus, - 0, - &features); - if (result == 0) { - if (features & check_feature) - return true; - } - - return false; -} - -static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn)) - return true; - return false; -} - -const struct pp_smumgr_func smu8_smu_funcs = { - .name = "smu8_smu", - .smu_init = smu8_smu_init, - .smu_fini = smu8_smu_fini, - .start_smu = smu8_start_smu, - .check_fw_load_finish = smu8_check_fw_load_finish, - .request_smu_load_fw = NULL, - .request_smu_load_specific_fw = NULL, - .get_argument = smu8_get_argument, - .send_msg_to_smc = smu8_send_msg_to_smc, - .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter, - .download_pptable_settings = smu8_download_pptable_settings, - .upload_pptable_settings = smu8_upload_pptable_settings, - .is_dpm_running = smu8_is_dpm_running, -}; - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h deleted file mode 100644 index c7b61222d258..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2015 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 _SMU8_SMUMGR_H_ -#define _SMU8_SMUMGR_H_ - - -#define MAX_NUM_FIRMWARE 8 -#define MAX_NUM_SCRATCH 11 -#define SMU8_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024 -#define SMU8_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048 -#define SMU8_SCRATCH_SIZE_SDMA_METADATA 1024 -#define SMU8_SCRATCH_SIZE_IH ((2*256+1)*4) - -#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000 - -enum smu8_scratch_entry { - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0, - SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, - SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, - SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, - SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, - SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM, - SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM, - SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, - SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT, - SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING, - SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS, - SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT, - SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START, - SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS, - SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE -}; - -struct smu8_buffer_entry { - uint32_t data_size; - uint64_t mc_addr; - void *kaddr; - enum smu8_scratch_entry firmware_ID; - struct amdgpu_bo *handle; /* as bo handle used when release bo */ -}; - -struct smu8_register_index_data_pair { - uint32_t offset; - uint32_t value; -}; - -struct smu8_ih_meta_data { - uint32_t command; - struct smu8_register_index_data_pair register_index_value_pair[1]; -}; - -struct smu8_smumgr { - uint8_t driver_buffer_length; - uint8_t scratch_buffer_length; - uint16_t toc_entry_used_count; - uint16_t toc_entry_initialize_index; - uint16_t toc_entry_power_profiling_index; - uint16_t toc_entry_aram; - uint16_t toc_entry_ih_register_restore_task_index; - uint16_t toc_entry_clock_table; - uint16_t ih_register_restore_task_size; - uint16_t smu_buffer_used_bytes; - - struct smu8_buffer_entry toc_buffer; - struct smu8_buffer_entry smu_buffer; - struct smu8_buffer_entry firmware_buffer; - struct smu8_buffer_entry driver_buffer[MAX_NUM_FIRMWARE]; - struct smu8_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE]; - struct smu8_buffer_entry scratch_buffer[MAX_NUM_SCRATCH]; -}; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c deleted file mode 100644 index adfbcbe5d113..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2018 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 "smumgr.h" -#include "vega10_inc.h" -#include "soc15_common.h" -#include "pp_debug.h" - - -/* MP Apertures */ -#define MP0_Public 0x03800000 -#define MP0_SRAM 0x03900000 -#define MP1_Public 0x03b00000 -#define MP1_SRAM 0x03c00004 - -#define smnMP1_FIRMWARE_FLAGS 0x3010028 - -bool smu9_is_smc_ram_running(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t mp1_fw_flags; - - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); - - if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) - return true; - - return false; -} - -/* - * Check if SMC has responded to previous message. - * - * @param smumgr the address of the powerplay hardware manager. - * @return TRUE SMC has responded, FALSE otherwise. - */ -static uint32_t smu9_wait_for_response(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t reg; - uint32_t ret; - - /* Due to the L1 policy problem under SRIOV, we have to use - * mmMP1_SMN_C2PMSG_103 as the driver response register - */ - if (hwmgr->pp_one_vf) { - reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_103); - - ret = phm_wait_for_register_unequal(hwmgr, reg, - 0, MP1_C2PMSG_103__CONTENT_MASK); - - if (ret) - pr_err("No response from smu\n"); - - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103); - } else { - reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); - - ret = phm_wait_for_register_unequal(hwmgr, reg, - 0, MP1_C2PMSG_90__CONTENT_MASK); - - if (ret) - pr_err("No response from smu\n"); - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); - } -} - -/* - * Send a message to the SMC, and do not wait for its response. - * @param smumgr the address of the powerplay hardware manager. - * @param msg the message to send. - * @return Always return 0. - */ -static int smu9_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, - uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (hwmgr->pp_one_vf) { - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_101, msg); - } else { - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); - } - - return 0; -} - -/* - * Send a message to the SMC, and wait for its response. - * @param hwmgr the address of the powerplay hardware manager. - * @param msg the message to send. - * @return Always return 0. - */ -int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t ret; - - smu9_wait_for_response(hwmgr); - - if (hwmgr->pp_one_vf) - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0); - else - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - smu9_send_msg_to_smc_without_waiting(hwmgr, msg); - - ret = smu9_wait_for_response(hwmgr); - if (ret != 1) - pr_err("Failed to send message: 0x%x, ret value: 0x%x\n", msg, ret); - - return 0; -} - -/* - * Send a message to the SMC with parameter - * @param hwmgr: the address of the powerplay hardware manager. - * @param msg: the message to send. - * @param parameter: the parameter to send - * @return Always return 0. - */ -int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t ret; - - smu9_wait_for_response(hwmgr); - - /* Due to the L1 policy problem under SRIOV, we have to use - * mmMP1_SMN_C2PMSG_101 as the driver message register and - * mmMP1_SMN_C2PMSG_102 as the driver parameter register. - */ - if (hwmgr->pp_one_vf) { - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_103, 0); - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102, parameter); - } else { - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); - } - - smu9_send_msg_to_smc_without_waiting(hwmgr, msg); - - ret = smu9_wait_for_response(hwmgr); - if (ret != 1) - pr_err("Failed message: 0x%x, input parameter: 0x%x, error code: 0x%x\n", msg, parameter, ret); - - return 0; -} - -uint32_t smu9_get_argument(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - if (hwmgr->pp_one_vf) - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_102); - else - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h deleted file mode 100644 index 1462279ca128..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu9_smumgr.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2018 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 _SMU9_SMUMANAGER_H_ -#define _SMU9_SMUMANAGER_H_ - -bool smu9_is_smc_ram_running(struct pp_hwmgr *hwmgr); -int smu9_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); -int smu9_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter); -uint32_t smu9_get_argument(struct pp_hwmgr *hwmgr); - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c deleted file mode 100644 index b6fb48066841..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright 2015 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 -#include -#include -#include -#include -#include -#include "smumgr.h" - -MODULE_FIRMWARE("amdgpu/bonaire_smc.bin"); -MODULE_FIRMWARE("amdgpu/bonaire_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/hawaii_smc.bin"); -MODULE_FIRMWARE("amdgpu/hawaii_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/topaz_smc.bin"); -MODULE_FIRMWARE("amdgpu/topaz_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/tonga_smc.bin"); -MODULE_FIRMWARE("amdgpu/tonga_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/fiji_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris10_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin"); -MODULE_FIRMWARE("amdgpu/polaris10_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris10_k2_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris11_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin"); -MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris11_k2_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris12_smc.bin"); -MODULE_FIRMWARE("amdgpu/polaris12_k_smc.bin"); -MODULE_FIRMWARE("amdgpu/vegam_smc.bin"); -MODULE_FIRMWARE("amdgpu/vega10_smc.bin"); -MODULE_FIRMWARE("amdgpu/vega10_acg_smc.bin"); -MODULE_FIRMWARE("amdgpu/vega12_smc.bin"); -MODULE_FIRMWARE("amdgpu/vega20_smc.bin"); - -int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->thermal_avfs_enable) - return hwmgr->smumgr_funcs->thermal_avfs_enable(hwmgr); - - return 0; -} - -int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->thermal_setup_fan_table) - return hwmgr->smumgr_funcs->thermal_setup_fan_table(hwmgr); - - return 0; -} - -int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - - if (NULL != hwmgr->smumgr_funcs->update_sclk_threshold) - return hwmgr->smumgr_funcs->update_sclk_threshold(hwmgr); - - return 0; -} - -int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - - if (NULL != hwmgr->smumgr_funcs->update_smc_table) - return hwmgr->smumgr_funcs->update_smc_table(hwmgr, type); - - return 0; -} - -uint32_t smum_get_offsetof(struct pp_hwmgr *hwmgr, uint32_t type, uint32_t member) -{ - if (NULL != hwmgr->smumgr_funcs->get_offsetof) - return hwmgr->smumgr_funcs->get_offsetof(type, member); - - return 0; -} - -int smum_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->process_firmware_header) - return hwmgr->smumgr_funcs->process_firmware_header(hwmgr); - return 0; -} - -uint32_t smum_get_mac_definition(struct pp_hwmgr *hwmgr, uint32_t value) -{ - if (NULL != hwmgr->smumgr_funcs->get_mac_definition) - return hwmgr->smumgr_funcs->get_mac_definition(value); - - return 0; -} - -int smum_download_powerplay_table(struct pp_hwmgr *hwmgr, void **table) -{ - if (NULL != hwmgr->smumgr_funcs->download_pptable_settings) - return hwmgr->smumgr_funcs->download_pptable_settings(hwmgr, - table); - return 0; -} - -int smum_upload_powerplay_table(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->upload_pptable_settings) - return hwmgr->smumgr_funcs->upload_pptable_settings(hwmgr); - - return 0; -} - -int smum_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t *resp) -{ - int ret = 0; - - if (hwmgr == NULL || - hwmgr->smumgr_funcs->send_msg_to_smc == NULL || - (resp && !hwmgr->smumgr_funcs->get_argument)) - return -EINVAL; - - mutex_lock(&hwmgr->msg_lock); - - ret = hwmgr->smumgr_funcs->send_msg_to_smc(hwmgr, msg); - if (ret) { - mutex_unlock(&hwmgr->msg_lock); - return ret; - } - - if (resp) - *resp = hwmgr->smumgr_funcs->get_argument(hwmgr); - - mutex_unlock(&hwmgr->msg_lock); - - return ret; -} - -int smum_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, - uint32_t parameter, - uint32_t *resp) -{ - int ret = 0; - - if (hwmgr == NULL || - hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL || - (resp && !hwmgr->smumgr_funcs->get_argument)) - return -EINVAL; - - mutex_lock(&hwmgr->msg_lock); - - ret = hwmgr->smumgr_funcs->send_msg_to_smc_with_parameter( - hwmgr, msg, parameter); - if (ret) { - mutex_unlock(&hwmgr->msg_lock); - return ret; - } - - if (resp) - *resp = hwmgr->smumgr_funcs->get_argument(hwmgr); - - mutex_unlock(&hwmgr->msg_lock); - - return ret; -} - -int smum_init_smc_table(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->init_smc_table) - return hwmgr->smumgr_funcs->init_smc_table(hwmgr); - - return 0; -} - -int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->populate_all_graphic_levels) - return hwmgr->smumgr_funcs->populate_all_graphic_levels(hwmgr); - - return 0; -} - -int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->populate_all_memory_levels) - return hwmgr->smumgr_funcs->populate_all_memory_levels(hwmgr); - - return 0; -} - -/*this interface is needed by island ci/vi */ -int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->initialize_mc_reg_table) - return hwmgr->smumgr_funcs->initialize_mc_reg_table(hwmgr); - - return 0; -} - -bool smum_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - if (NULL != hwmgr->smumgr_funcs->is_dpm_running) - return hwmgr->smumgr_funcs->is_dpm_running(hwmgr); - - return true; -} - -bool smum_is_hw_avfs_present(struct pp_hwmgr *hwmgr) -{ - if (hwmgr->smumgr_funcs->is_hw_avfs_present) - return hwmgr->smumgr_funcs->is_hw_avfs_present(hwmgr); - - return false; -} - -int smum_update_dpm_settings(struct pp_hwmgr *hwmgr, void *profile_setting) -{ - if (hwmgr->smumgr_funcs->update_dpm_settings) - return hwmgr->smumgr_funcs->update_dpm_settings(hwmgr, profile_setting); - - return -EINVAL; -} - -int smum_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) -{ - if (hwmgr->smumgr_funcs->smc_table_manager) - return hwmgr->smumgr_funcs->smc_table_manager(hwmgr, table, table_id, rw); - - return -EINVAL; -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c deleted file mode 100644 index 4bfadb49521b..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c +++ /dev/null @@ -1,3268 +0,0 @@ -/* - * Copyright 2015 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 "pp_debug.h" -#include -#include -#include -#include -#include - -#include "smumgr.h" -#include "tonga_smumgr.h" -#include "smu_ucode_xfer_vi.h" -#include "tonga_ppsmc.h" -#include "smu/smu_7_1_2_d.h" -#include "smu/smu_7_1_2_sh_mask.h" -#include "cgs_common.h" -#include "smu7_smumgr.h" - -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" - -#include "atombios.h" - -#include "pppcielanes.h" -#include "pp_endian.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define MC_CG_ARB_FREQ_F1 0x0b -#define VDDC_VDDCI_DELTA 200 - - -static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { -/* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT - */ - {1, 0xF, 0xFD, 0x19, - 5, 45, 0, 0xB0000, - {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, - 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, - {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, - 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4} - }, -}; - -/* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */ -static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = { - {600, 1050, 3, 0}, - {600, 1050, 6, 1} -}; - -/* [FF, SS] type, [] 4 voltage ranges, - * and [Floor Freq, Boundary Freq, VID min , VID max] - */ -static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = { - { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, - { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } -}; - -/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */ -static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = { - {0, 1, 3, 2, 4, 5}, - {0, 2, 4, 5, 6, 5} -}; - -static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result; - - /* Assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result) - return result; - - /* Clear status */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_STATUS, 0); - - /* Enable clock */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /* De-assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Set SMU Auto Start */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_INPUT_DATA, AUTO_START, 1); - - /* Clear firmware interrupt enable flag */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); - - /** - * Call Test SMU message with 0x20000 offset to trigger SMU start - */ - smu7_send_msg_to_smc_offset(hwmgr); - - /* Wait for done bit to be set */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - SMU_STATUS, SMU_DONE, 0); - - /* Check pass/failed indicator */ - if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) { - pr_err("SMU Firmware start failed\n"); - return -EINVAL; - } - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return 0; -} - -static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* wait for smc boot up */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, - RCU_UC_EVENTS, boot_seq_done, 0); - - /*Clear firmware interrupt enable flag*/ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - - if (result != 0) - return result; - - /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(hwmgr); - - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /*De-assert reset*/ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int tonga_start_smu(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *priv = hwmgr->smu_backend; - int result; - - /* Only start SMC if SMC RAM is not running */ - if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { - /*Check if SMU is running in protected mode*/ - if (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_FIRMWARE, SMU_MODE)) { - result = tonga_start_in_non_protection_mode(hwmgr); - if (result) - return result; - } else { - result = tonga_start_in_protection_mode(hwmgr); - if (result) - return result; - } - } - - /* Setup SoftRegsStart here to visit the register UcodeLoadStatus - * to check fw loading state - */ - smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, SoftRegisters), - &(priv->smu7_data.soft_regs_start), 0x40000); - - result = smu7_request_smu_load_fw(hwmgr); - - return result; -} - -static int tonga_smu_init(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *tonga_priv = NULL; - - tonga_priv = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL); - if (tonga_priv == NULL) - return -ENOMEM; - - hwmgr->smu_backend = tonga_priv; - - if (smu7_init(hwmgr)) { - kfree(tonga_priv); - return -EINVAL; - } - - return 0; -} - - -static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) -{ - uint32_t i = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - /* clock - voltage dependency table is empty table */ - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - /* find first sclk bigger than request */ - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - voltage->VddGfx = phm_get_voltage_index( - pptable_info->vddgfx_lookup_table, - allowed_clock_voltage_table->entries[i].vddgfx); - voltage->Vddc = phm_get_voltage_index( - pptable_info->vddc_lookup_table, - allowed_clock_voltage_table->entries[i].vddc); - - if (allowed_clock_voltage_table->entries[i].vddci) - voltage->Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci); - else - voltage->Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA); - - - if (allowed_clock_voltage_table->entries[i].mvdd) - *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd; - - voltage->Phases = 1; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - allowed_clock_voltage_table->entries[i-1].vddgfx); - voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table, - allowed_clock_voltage_table->entries[i-1].vddc); - - if (allowed_clock_voltage_table->entries[i-1].vddci) - voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table, - allowed_clock_voltage_table->entries[i-1].vddci); - - if (allowed_clock_voltage_table->entries[i-1].mvdd) - *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd; - - return 0; -} - -static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - unsigned int count; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - table->VddcTable[count] = - PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - } - return 0; -} - -static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - unsigned int count; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { - table->VddGfxLevelCount = data->vddgfx_voltage_table.count; - for (count = 0; count < data->vddgfx_voltage_table.count; count++) { - table->VddGfxTable[count] = - PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount); - } - return 0; -} - -static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - - table->VddciLevelCount = data->vddci_voltage_table.count; - for (count = 0; count < table->VddciLevelCount; count++) { - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - table->VddciTable[count] = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - table->SmioTable1.Pattern[count].Voltage = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */ - table->SmioTable1.Pattern[count].Smio = - (uint8_t) count; - table->Smio[count] |= - data->vddci_voltage_table.entries[count].smio_low; - table->VddciTable[count] = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - } - - table->SmioMask1 = data->vddci_voltage_table.mask_low; - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - table->MvddLevelCount = data->mvdd_voltage_table.count; - for (count = 0; count < table->MvddLevelCount; count++) { - table->SmioTable2.Pattern[count].Voltage = - PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ - table->SmioTable2.Pattern[count].Smio = - (uint8_t) count; - table->Smio[count] |= - data->mvdd_voltage_table.entries[count].smio_low; - } - table->SmioMask2 = data->mvdd_voltage_table.mask_low; - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - } - - return 0; -} - -static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = - pptable_info->vddgfx_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = - pptable_info->vddc_lookup_table; - - /* table is already swapped, so in order to use the value from it - * we need to swap it back. - */ - uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount); - uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount); - - for (count = 0; count < vddc_level_count; count++) { - /* We are populating vddc CAC data to BapmVddc table in split and merged mode */ - index = phm_get_voltage_index(vddc_lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); - table->BapmVddcVidHiSidd2[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); - } - - if (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) { - /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */ - for (count = 0; count < vddgfx_level_count; count++) { - index = phm_get_voltage_index(vddgfx_lookup_table, - convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid)); - table->BapmVddGfxVidHiSidd2[count] = - convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high); - } - } else { - for (count = 0; count < vddc_level_count; count++) { - index = phm_get_voltage_index(vddc_lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddGfxVidLoSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); - table->BapmVddGfxVidHiSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); - table->BapmVddGfxVidHiSidd2[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); - } - } - - return 0; -} - -static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result; - - result = tonga_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDC voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDCI voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_vdd_gfx_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDGFX voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate MVDD voltage table to SMC", - return -EINVAL); - - result = tonga_populate_cac_tables(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate CAC voltage tables to SMC", - return -EINVAL); - - return 0; -} - -static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU72_Discrete_Ulv *state) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU72_Discrete_DpmTable *table) -{ - return tonga_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t i; - - /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = - 1; - table->LinkLevel[i].SPC = - (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = - PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = - PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t reference_clock; - uint32_t reference_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ - reference_clock = atomctrl_get_reference_clock(hwmgr); - - reference_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider*/ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup*/ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - - uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; - if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - */ - /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ - uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); - - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); - - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = - PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); - } - } - - sclk->SclkFrequency = engine_clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - SMU72_Discrete_GraphicsLevel *graphic_level) -{ - int result; - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - - result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_sclk; - else - vdd_dep_table = pptable_info->vdd_dep_on_sclk; - - /* populate graphics levels*/ - result = tonga_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, engine_clock, - &graphic_level->MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((!result), - "can not find VDDC voltage value for VDDC " - "engine clock dependency table", return result); - - /* SCLK frequency in units of 10KHz*/ - graphic_level->SclkFrequency = engine_clock; - /* Indicates maximum activity level for this performance level. 50% for now*/ - graphic_level->ActivityLevel = data->current_profile_setting.sclk_activity; - - graphic_level->CcPwrDynRm = 0; - graphic_level->CcPwrDynRm1 = 0; - /* this level can be used if activity is high enough.*/ - graphic_level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - graphic_level->EnabledForThrottle = 1; - graphic_level->UpHyst = data->current_profile_setting.sclk_up_hyst; - graphic_level->DownHyst = data->current_profile_setting.sclk_down_hyst; - graphic_level->VoltageDownHyst = 0; - graphic_level->PowerThrottle = 0; - - data->display_timing.min_clock_in_sr = - hwmgr->display_config->min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - graphic_level->DeepSleepDivId = - smu7_get_sleep_divider_id_from_clock(engine_clock, - data->display_timing.min_clock_in_sr); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (!result) { - /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/ - /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/ - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); - } - - return result; -} - -static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; - uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count; - uint32_t level_array_address = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); - - uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) * - SMU72_MAX_LEVELS_GRAPHICS; - - SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; - - uint32_t i, max_entry; - uint8_t highest_pcie_level_enabled = 0; - uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; - uint8_t count = 0; - int result = 0; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = tonga_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result != 0) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now. */ - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - if (dpm_table->sclk_table.count > 1) - smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((pcie_entry_count >= 1), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/ - for (i = 0; i < dpm_table->sclk_table.count; i++) { - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } - } else { - if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask) - pr_err("Pcie Dpm Enablemask is 0 !"); - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<<(highest_pcie_level_enabled+1))) != 0)) { - highest_pcie_level_enabled++; - } - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<<(lowest_pcie_level_enabled+1+count))) == 0)) { - count++; - } - mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? - (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; - - - /* set pcieDpmLevel to highest_pcie_level_enabled*/ - for (i = 2; i < dpm_table->sclk_table.count; i++) - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, - (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int tonga_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU72_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE( - !result, - "Error retrieving Memory Clock Parameters from VBIOS.", - return result); - - /* MPLL_FUNC_CNTL setup*/ - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, - mpll_param.bw_ctrl); - - /* MPLL_FUNC_CNTL_1 setup*/ - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, - mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, - mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, - mpll_param.vco_mode); - - /* MPLL_AD_FUNC_CNTL setup*/ - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, - mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - /* MPLL_DQ_FUNC_CNTL setup*/ - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, - mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, - mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - /* - ************************************ - Fref = Reference Frequency - NF = Feedback divider ratio - NR = Reference divider ratio - Fnom = Nominal VCO output frequency = Fref * NF / NR - Fs = Spreading Rate - D = Percentage down-spread / 2 - Fint = Reference input frequency to PFD = Fref / NR - NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) - CLKS = NS - 1 = ISS_STEP_NUM[11:0] - NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) - CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] - ************************************* - */ - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ - /* ss.Info.speed_spectrum_rate -- in unit of khz */ - /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ - /* = reference_clock * 5 / speed_spectrum_rate */ - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - - /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ - /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - /* MCLK_PWRMGT_CNTL setup */ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - - return mc_para_index; -} - -static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - - return mc_para_index; -} - - -static int tonga_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU72_Discrete_MemoryLevel *memory_level - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_stutter_mode_threshold = 30000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_table = NULL; - int result = 0; - bool dll_state_on; - uint32_t mvdd = 0; - - if (hwmgr->od_enabled) - vdd_dep_table = (phm_ppt_v1_clock_voltage_dependency_table *)&data->odn_dpm_table.vdd_dependency_on_mclk; - else - vdd_dep_table = pptable_info->vdd_dep_on_mclk; - - if (NULL != vdd_dep_table) { - result = tonga_get_dependency_volt_by_clk(hwmgr, - vdd_dep_table, - memory_clock, - &memory_level->MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE( - !result, - "can not find MinVddc voltage value from memory VDDC " - "voltage dependency table", - return result); - } - - if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) - memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value; - else - memory_level->MinMvdd = mvdd; - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 0; - memory_level->UpHyst = data->current_profile_setting.mclk_up_hyst; - memory_level->DownHyst = data->current_profile_setting.mclk_down_hyst; - memory_level->VoltageDownHyst = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = data->current_profile_setting.mclk_activity; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - if ((mclk_stutter_mode_threshold != 0) && - (memory_clock <= mclk_stutter_mode_threshold) && - (!data->is_uvd_enabled) - && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1) - && (data->display_timing.num_existing_displays <= 2) - && (data->display_timing.num_existing_displays != 0)) - memory_level->StutterEnable = 1; - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) { - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } else { - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } - - } else { - dll_state_on = data->dll_default_on; - } - } else { - memory_level->StrobeRatio = - tonga_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = tonga_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -static int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - - /* populate MCLK dpm table to SMU7 */ - uint32_t level_array_address = - smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = - sizeof(SMU72_Discrete_MemoryLevel) * - SMU72_MAX_LEVELS_MEMORY; - SMU72_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = tonga_populate_single_memory_level( - hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (result) - return result; - } - - /* Only enable level 0 for now.*/ - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - /* - * in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in a higher state - * by default such that we are not effected by up threshold or and MCLK DPM latency. - */ - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high*/ - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, - level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pattern) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - smio_pattern->Voltage = - data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else { - return -EINVAL; - } - - return 0; -} - - -static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - - SMIO_Pattern voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - table->ACPILevel.MinVoltage = - smu_data->smc_state_table.GraphicsLevel[0].MinVoltage; - - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, - SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVoltage = - smu_data->smc_state_table.MemoryLevel[0].MinVoltage; - - /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/ - - if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->UvdLevelCount = (uint8_t) (mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->UvdLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->UvdLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->UvdLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi( - hwmgr, - table->UvdLevel[count].VclkFrequency, - ÷rs); - - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for Vclk clock", - return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for Dclk clock", - return result); - - table->UvdLevel[count].DclkDivider = - (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - } - - return result; - -} - -static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->VceLevelCount = (uint8_t) (mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = - mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->VceLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->VceLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->VceLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - } - - return result; -} - -static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->AcpLevelCount = (uint8_t) (mm_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = - pptable_info->mm_dep_table->entries[count].aclk; - table->AcpLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->AcpLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->AcpLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->AcpLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - } - - return result; -} - -static int tonga_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU72_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = tonga_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (result) - break; - } - } - - if (!result) { - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU72_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (result != 0) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("[powerplay] VBIOS did not find boot engine " - "clock value in dependency table. " - "Using Graphics DPM level 0 !"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (result != 0) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("[powerplay] VBIOS did not find boot " - "engine clock value in dependency table." - "Using Memory DPM level 0 !"); - result = 0; - } - - table->BootVoltage.Vddc = - phm_get_voltage_id(&(data->vddc_voltage_table), - data->vbios_boot_state.vddc_bootup_value); - table->BootVoltage.VddGfx = - phm_get_voltage_id(&(data->vddgfx_voltage_table), - data->vbios_boot_state.vddgfx_bootup_value); - table->BootVoltage.Vddci = - phm_get_voltage_id(&(data->vddci_voltage_table), - data->vbios_boot_state.vddci_bootup_value); - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return result; -} - -static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, - volt_with_cks, value; - uint16_t clock_freq_u16; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, - volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - uint32_t hw_revision, dev_id; - struct amdgpu_device *adev = hwmgr->adev; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - hw_revision = adev->pdev->revision; - dev_id = adev->pdev->device; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (146 * 4)); - efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (148 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - efuse2 &= 0xF; - - if (efuse2 == 1) - ro = (2300 - 1350) * efuse / 255 + 1350; - else - ro = (2500 - 1000) * efuse / 255 + 1000; - - if (ro >= 1660) - type = 0; - else - type = 1; - - /* Populate Stretch amount */ - smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; - - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - if (ASICID_IS_TONGA_P(dev_id, hw_revision)) { - volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 * - (sclk_table->entries[i].clk/100) / 10000) * 1000 / - (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000))); - volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 * - (sclk_table->entries[i].clk/100) / 100000) * 1000 / - (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000))); - } else { - volt_without_cks = (uint32_t)((14041 * - (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / - (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); - volt_with_cks = (uint32_t)((13946 * - (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / - (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); - } - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - STRETCH_ENABLE, 0x0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - staticEnable, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x0); - - /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFC2FF87; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = - tonga_clock_stretcher_lookup_table[stretch_amount2][0]; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = - tonga_clock_stretcher_lookup_table[stretch_amount2][1]; - clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. - GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. - SclkFrequency) / 100); - if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] < - clock_freq_u16 && - tonga_clock_stretcher_lookup_table[stretch_amount2][1] > - clock_freq_u16) { - /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ - value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; - /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ - value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; - /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ - value |= (tonga_clock_stretch_amount_conversion - [tonga_clock_stretcher_lookup_table[stretch_amount2][3]] - [stretch_amount]) << 3; - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].minFreq); - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].maxFreq); - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = - tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= - (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - /* Populate DDT Lookup Table */ - for (i = 0; i < 4; i++) { - /* Assign the minimum and maximum VID stored - * in the last row of Clock Stretcher Voltage Table. - */ - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].minVID = - (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2]; - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].maxVID = - (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3]; - /* Loop through each SCLK and check the frequency - * to see if it lies within the frequency for clock stretcher. - */ - for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { - cks_setting = 0; - clock_freq = PP_SMC_TO_HOST_UL( - smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); - /* Check the allowed frequency against the sclk level[j]. - * Sclk's endianness has already been converted, - * and it's in 10Khz unit, - * as opposed to Data table, which is in Mhz unit. - */ - if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) { - cks_setting |= 0x2; - if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100) - cks_setting |= 0x1; - } - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. - ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - return 0; -} - -static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t config; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { - /* Splitted mode */ - config = VR_SVI2_PLANE_1; - table->VRConfig |= (config<voltage_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= config; - } else { - pr_err("VDDC and VDDGFX should " - "be both on SVI2 control in splitted mode !\n"); - } - } else { - /* Merged mode */ - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config<voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - pr_err("VDDC should be on " - "SVI2 control in merged mode !\n"); - } - } - - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config<vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config<mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config<smu_backend); - uint32_t tmp; - int result; - - /* - * This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result != 0) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - - -static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - int i, j, k; - const uint16_t *pdef1, *pdef2; - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range !", - ); - - dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - dpm_table->BAPM_TEMP_GRADIENT = - PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - pdef1 = defaults->bapmti_r; - pdef2 = defaults->bapmti_rc; - - for (i = 0; i < SMU72_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU72_DTE_SOURCES; j++) { - for (k = 0; k < SMU72_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = - PP_HOST_TO_SMC_US(*pdef1); - dpm_table->BAPMTI_RC[i][j][k] = - PP_HOST_TO_SMC_US(*pdef2); - pdef1++; - pdef2++; - } - } - } - - return 0; -} - -static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - /* TDC number of fraction bits are changed from 8 to 7 - * for Fiji as requested by SMC team - */ - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 " - "(SviLoadLineEn) from SMC Failed !", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity & (1 << 15)) || - (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0)) - hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity = hwmgr->thermal_controller. - advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = - PP_HOST_TO_SMC_US(hwmgr->thermal_controller. - advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); - - return 0; -} - -static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed !", - return -EINVAL); - - /* DW6 */ - if (tonga_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed !", - return -EINVAL); - /* DW7 */ - if (tonga_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed !", - return -EINVAL); - /* DW8 */ - if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl Failed !", - return -EINVAL); - - /* DW9-DW12 */ - if (tonga_populate_temperature_scaler(hwmgr) != 0) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed !", - return -EINVAL); - - /* DW13-DW14 */ - if (tonga_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan " - "Control parameters Failed !", - return -EINVAL); - - /* DW15-DW18 */ - if (tonga_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed !", - return -EINVAL); - - /* DW20 */ - if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE( - false, - "Attempt to populate BapmVddCBaseLeakage " - "Hi and Lo Sidd Failed !", - return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed !", - return -EINVAL); - } - return 0; -} - -static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU72_Discrete_MCRegisters *mc_reg_table) -{ - const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<address[] array " - "out of boundary", - return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -/*convert register values from driver to SMC format */ -static void tonga_convert_mc_registers( - const struct tonga_mc_reg_entry *entry, - SMU72_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int tonga_convert_mc_reg_table_entry_to_smc( - struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU72_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU72_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = tonga_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters)); - - result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - - address = smu_data->smu7_data.mc_reg_table_start + - (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); - - return smu7_copy_bytes_to_smc( - hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU72_Discrete_MCRegisterSet) * - data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters)); - result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize MCRegTable for the MC register addresses !", - return result;); - - result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize MCRegTable for driver state !", - return result;); - - return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END); -} - -static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &tonga_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0]; -} - -static int tonga_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - uint8_t i; - pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; - - - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - tonga_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - tonga_populate_smc_voltage_tables(hwmgr, table); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN); - - if (i == 1 || i == 0) - table->SystemFlags |= 0x40; - - if (data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = tonga_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ULV state !", - return result;); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = tonga_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Link Level !", return result); - - result = tonga_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Graphics Level !", return result); - - result = tonga_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Memory Level !", return result); - - result = tonga_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ACPI Level !", return result); - - result = tonga_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize VCE Level !", return result); - - result = tonga_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ACP Level !", return result); - - /* Since only the initial state is completely set up at this - * point (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = tonga_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to Write ARB settings for the initial state.", - return result;); - - result = tonga_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize UVD Level !", return result); - - result = tonga_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Boot Level !", return result); - - tonga_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate BAPM Parameters !", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = tonga_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate Clock Stretcher Data Table !", - return result;); - } - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - - /* - * Cail reads current link status and reports it as cap (we cannot - * change this due to some previous issues we had) - * SMC drops the link status to lowest level after enabling - * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again - * but this time Cail reads current link status which was set to low by - * SMC and reports it as cap to powerplay - * To avoid it, we set PCIeBootLinkLevel to highest dpm level - */ - PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - - table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); - - table->PCIeGenInterval = 1; - - result = tonga_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate VRConfig setting !", return result); - data->vr_config = table->VRConfig; - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, - &gpio_pin_assignment)) { - table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin_assignment)) { - table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - - if (0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, - THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - - table->ThermOutPolarity = - (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & - (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0; - - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO*/ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CombinePCCWithThermalSignal)){ - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } - } else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(!result, - "Failed to upload dpm data to SMC memory !", return result;); - - result = tonga_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload arb data to SMC memory !", return result); - - tonga_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE((!result), - "Failed to populate initialize pm fuses !", return result); - - result = tonga_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((!result), - "Failed to populate initialize MC Reg table !", return result); - - return 0; -} - -static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == smu_data->smu7_data.fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - fan_table.FanControl_GL_Flag = 1; - - res = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, - (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - return 0; -} - - -static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return tonga_program_memory_timing_parameters(hwmgr); - - return 0; -} - -static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = tonga_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((!result), - "Failed to upload MC reg table !", - return result); - - result = tonga_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters !", - ); - - return result; -} - -static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU72_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); - case AverageMemoryActivity: - return offsetof(SMU72_SoftRegisters, AverageMemoryActivity); - case PreVBlankGap: - return offsetof(SMU72_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU72_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU72_SoftRegisters, UcodeLoadStatus); - case DRAM_LOG_ADDR_H: - return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU72_Discrete_DpmTable, VceBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold); - } - break; - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static uint32_t tonga_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU72_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU72_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU72_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU72_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU72_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU72_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU72_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU72_MAX_LEVELS_MVDD; - } - pr_warn("can't get the mac value %x\n", value); - - return 0; -} - -static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), - NULL); - return 0; -} - -static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, - NULL); - return 0; -} - -static int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - tonga_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - tonga_update_vce_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - -static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (result != 0); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (result != 0); - - return error ? 1 : 0; -} - -/*---------------------------MC----------------------------*/ - -static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, - &address) ? - address : - table->mc_reg_address[i].s1; - } - return 0; -} - -static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct tonga_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct tonga_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, - mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - - PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - j++; - - if (!data->is_memory_gddr5) { - PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - j++; - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int tonga_set_valid_flag(struct tonga_mc_reg_table *table) -{ - uint8_t i, j; - - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1<smu_backend); - pp_atomctrl_mc_reg_table *table; - struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = tonga_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (table == NULL) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (!result) - result = tonga_copy_vbios_smc_reg_table(table, ni_table); - - if (!result) { - tonga_set_s0_mc_reg_index(ni_table); - result = tonga_set_mc_special_registers(hwmgr, ni_table); - } - - if (!result) - tonga_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -static int tonga_update_dpm_settings(struct pp_hwmgr *hwmgr, - void *profile_setting) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *) - (hwmgr->smu_backend); - struct profile_mode_setting *setting; - struct SMU72_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); - - uint32_t mclk_array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, MemoryLevel); - struct SMU72_Discrete_MemoryLevel *mclk_levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - uint32_t offset, up_hyst_offset, down_hyst_offset, clk_activity_offset, tmp; - - if (profile_setting == NULL) - return -EINVAL; - - setting = (struct profile_mode_setting *)profile_setting; - - if (setting->bupdate_sclk) { - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - if (levels[i].ActivityLevel != - cpu_to_be16(setting->sclk_activity)) { - levels[i].ActivityLevel = cpu_to_be16(setting->sclk_activity); - - clk_activity_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) - + offsetof(SMU72_Discrete_GraphicsLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (levels[i].UpHyst != setting->sclk_up_hyst || - levels[i].DownHyst != setting->sclk_down_hyst) { - levels[i].UpHyst = setting->sclk_up_hyst; - levels[i].DownHyst = setting->sclk_down_hyst; - up_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) - + offsetof(SMU72_Discrete_GraphicsLevel, UpHyst); - down_hyst_offset = array + (sizeof(SMU72_Discrete_GraphicsLevel) * i) - + offsetof(SMU72_Discrete_GraphicsLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->sclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_SCLKDPM_UnfreezeLevel, NULL); - } - - if (setting->bupdate_mclk) { - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_FreezeLevel, NULL); - for (i = 0; i < smu_data->smc_state_table.MemoryDpmLevelCount; i++) { - if (mclk_levels[i].ActivityLevel != - cpu_to_be16(setting->mclk_activity)) { - mclk_levels[i].ActivityLevel = cpu_to_be16(setting->mclk_activity); - - clk_activity_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) - + offsetof(SMU72_Discrete_MemoryLevel, ActivityLevel); - offset = clk_activity_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(clk_activity_offset, tmp, mclk_levels[i].ActivityLevel, sizeof(uint16_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - - } - if (mclk_levels[i].UpHyst != setting->mclk_up_hyst || - mclk_levels[i].DownHyst != setting->mclk_down_hyst) { - mclk_levels[i].UpHyst = setting->mclk_up_hyst; - mclk_levels[i].DownHyst = setting->mclk_down_hyst; - up_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) - + offsetof(SMU72_Discrete_MemoryLevel, UpHyst); - down_hyst_offset = mclk_array + (sizeof(SMU72_Discrete_MemoryLevel) * i) - + offsetof(SMU72_Discrete_MemoryLevel, DownHyst); - offset = up_hyst_offset & ~0x3; - tmp = PP_HOST_TO_SMC_UL(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset)); - tmp = phm_set_field_to_u32(up_hyst_offset, tmp, mclk_levels[i].UpHyst, sizeof(uint8_t)); - tmp = phm_set_field_to_u32(down_hyst_offset, tmp, mclk_levels[i].DownHyst, sizeof(uint8_t)); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset, PP_HOST_TO_SMC_UL(tmp)); - } - } - if (!data->mclk_dpm_key_disabled) - smum_send_msg_to_smc(hwmgr, PPSMC_MSG_MCLKDPM_UnfreezeLevel, NULL); - } - return 0; -} - -const struct pp_smumgr_func tonga_smu_funcs = { - .name = "tonga_smu", - .smu_init = &tonga_smu_init, - .smu_fini = &smu7_smu_fini, - .start_smu = &tonga_start_smu, - .check_fw_load_finish = &smu7_check_fw_load_finish, - .request_smu_load_fw = &smu7_request_smu_load_fw, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &smu7_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter, - .get_argument = smu7_get_argument, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .update_smc_table = tonga_update_smc_table, - .get_offsetof = tonga_get_offsetof, - .process_firmware_header = tonga_process_firmware_header, - .init_smc_table = tonga_init_smc_table, - .update_sclk_threshold = tonga_update_sclk_threshold, - .thermal_setup_fan_table = tonga_thermal_setup_fan_table, - .populate_all_graphic_levels = tonga_populate_all_graphic_levels, - .populate_all_memory_levels = tonga_populate_all_memory_levels, - .get_mac_definition = tonga_get_mac_definition, - .initialize_mc_reg_table = tonga_initialize_mc_reg_table, - .is_dpm_running = tonga_is_dpm_running, - .update_dpm_settings = tonga_update_dpm_settings, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h deleted file mode 100644 index d664fedd3d85..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2015 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 _TONGA_SMUMGR_H_ -#define _TONGA_SMUMGR_H_ - -#include "smu72_discrete.h" -#include "smu7_smumgr.h" -#include "smu72.h" - - -#define ASICID_IS_TONGA_P(wDID, bRID) \ - (((wDID == 0x6930) && ((bRID == 0xF0) || (bRID == 0xF1) || (bRID == 0xFF))) \ - || ((wDID == 0x6920) && ((bRID == 0) || (bRID == 1)))) - -struct tonga_pt_defaults { - uint8_t svi_load_line_en; - uint8_t svi_load_line_vddC; - uint8_t tdc_vddc_throttle_release_limit_perc; - uint8_t tdc_mawt; - uint8_t tdc_waterfall_ctl; - uint8_t dte_ambient_temp_base; - uint32_t display_cac; - uint32_t bapm_temp_gradient; - uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; - uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; -}; - -struct tonga_mc_reg_entry { - uint32_t mclk_max; - uint32_t mc_data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - -struct tonga_mc_reg_table { - uint8_t last; /* number of registers*/ - uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/ - uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/ - struct tonga_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; - SMU72_Discrete_MCRegisterAddress mc_reg_address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; -}; - - -struct tonga_smumgr { - - struct smu7_smumgr smu7_data; - struct SMU72_Discrete_DpmTable smc_state_table; - struct SMU72_Discrete_Ulv ulv_setting; - struct SMU72_Discrete_PmFuses power_tune_table; - const struct tonga_pt_defaults *power_tune_defaults; - SMU72_Discrete_MCRegisters mc_regs; - struct tonga_mc_reg_table mc_reg_table; -}; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c deleted file mode 100644 index 1e222c5d91a4..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c +++ /dev/null @@ -1,396 +0,0 @@ -/* - * Copyright 2016 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 - -#include "smumgr.h" -#include "vega10_inc.h" -#include "soc15_common.h" -#include "vega10_smumgr.h" -#include "vega10_hwmgr.h" -#include "vega10_ppsmc.h" -#include "smu9_driver_if.h" -#include "smu9_smumgr.h" -#include "ppatomctrl.h" -#include "pp_debug.h" - - -static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega10_smumgr *priv = hwmgr->smu_backend; - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableSmu2Dram, - priv->smu_tables.entry[table_id].table_id, - NULL); - - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); - - memcpy(table, priv->smu_tables.entry[table_id].table, - priv->smu_tables.entry[table_id].size); - - return 0; -} - -static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega10_smumgr *priv = hwmgr->smu_backend; - struct amdgpu_device *adev = hwmgr->adev; - - /* under sriov, vbios or hypervisor driver - * has already copy table to smc so here only skip it - */ - if (!hwmgr->not_vf) - return 0; - - PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - - memcpy(priv->smu_tables.entry[table_id].table, table, - priv->smu_tables.entry[table_id].size); - - amdgpu_asic_flush_hdp(adev, NULL); - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableDram2Smu, - priv->smu_tables.entry[table_id].table_id, - NULL); - - return 0; -} - -int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint32_t feature_mask) -{ - int msg = enable ? PPSMC_MSG_EnableSmuFeatures : - PPSMC_MSG_DisableSmuFeatures; - - /* VF has no permission to change smu feature due - * to security concern even under pp one vf mode - * it still can't do it. For vega10, the smu in - * vbios will enable the appropriate features. - * */ - if (!hwmgr->not_vf) - return 0; - - return smum_send_msg_to_smc_with_parameter(hwmgr, - msg, feature_mask, NULL); -} - -int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled) -{ - uint32_t enabled_features; - - if (features_enabled == NULL) - return -EINVAL; - - smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetEnabledSmuFeatures, - &enabled_features); - *features_enabled = enabled_features; - - return 0; -} - -static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - uint64_t features_enabled = 0; - - vega10_get_enabled_smc_features(hwmgr, &features_enabled); - - if (features_enabled & SMC_DPM_FEATURES) - return true; - else - return false; -} - -static int vega10_set_tools_address(struct pp_hwmgr *hwmgr) -{ - struct vega10_smumgr *priv = hwmgr->smu_backend; - - if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) { - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr), - NULL); - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr), - NULL); - } - return 0; -} - -static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr) -{ - uint32_t smc_driver_if_version; - struct amdgpu_device *adev = hwmgr->adev; - uint32_t dev_id; - uint32_t rev_id; - - PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetDriverIfVersion, - &smc_driver_if_version), - "Attempt to get SMC IF Version Number Failed!", - return -EINVAL); - - dev_id = adev->pdev->device; - rev_id = adev->pdev->revision; - - if (!((dev_id == 0x687f) && - ((rev_id == 0xc0) || - (rev_id == 0xc1) || - (rev_id == 0xc3)))) { - if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) { - pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n", - smc_driver_if_version, SMU9_DRIVER_IF_VERSION); - return -EINVAL; - } - } - - return 0; -} - -static int vega10_smu_init(struct pp_hwmgr *hwmgr) -{ - struct vega10_smumgr *priv; - unsigned long tools_size; - int ret; - struct cgs_firmware_info info = {0}; - - ret = cgs_get_firmware_info(hwmgr->device, - CGS_UCODE_ID_SMU, - &info); - if (ret || !info.kptr) - return -EINVAL; - - priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL); - - if (!priv) - return -ENOMEM; - - hwmgr->smu_backend = priv; - - /* allocate space for pptable */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(PPTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[PPTABLE].handle, - &priv->smu_tables.entry[PPTABLE].mc_addr, - &priv->smu_tables.entry[PPTABLE].table); - if (ret) - goto free_backend; - - priv->smu_tables.entry[PPTABLE].version = 0x01; - priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t); - priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE; - - /* allocate space for watermarks table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(Watermarks_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[WMTABLE].handle, - &priv->smu_tables.entry[WMTABLE].mc_addr, - &priv->smu_tables.entry[WMTABLE].table); - - if (ret) - goto err0; - - priv->smu_tables.entry[WMTABLE].version = 0x01; - priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t); - priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS; - - /* allocate space for AVFS table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(AvfsTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[AVFSTABLE].handle, - &priv->smu_tables.entry[AVFSTABLE].mc_addr, - &priv->smu_tables.entry[AVFSTABLE].table); - - if (ret) - goto err1; - - priv->smu_tables.entry[AVFSTABLE].version = 0x01; - priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t); - priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS; - - tools_size = 0x19000; - if (tools_size) { - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - tools_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TOOLSTABLE].handle, - &priv->smu_tables.entry[TOOLSTABLE].mc_addr, - &priv->smu_tables.entry[TOOLSTABLE].table); - if (ret) - goto err2; - priv->smu_tables.entry[TOOLSTABLE].version = 0x01; - priv->smu_tables.entry[TOOLSTABLE].size = tools_size; - priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG; - } - - /* allocate space for AVFS Fuse table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(AvfsFuseOverride_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[AVFSFUSETABLE].handle, - &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr, - &priv->smu_tables.entry[AVFSFUSETABLE].table); - if (ret) - goto err3; - - priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01; - priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t); - priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE; - - - return 0; - -err3: - if (priv->smu_tables.entry[TOOLSTABLE].table) - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle, - &priv->smu_tables.entry[TOOLSTABLE].mc_addr, - &priv->smu_tables.entry[TOOLSTABLE].table); -err2: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle, - &priv->smu_tables.entry[AVFSTABLE].mc_addr, - &priv->smu_tables.entry[AVFSTABLE].table); -err1: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle, - &priv->smu_tables.entry[WMTABLE].mc_addr, - &priv->smu_tables.entry[WMTABLE].table); -err0: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle, - &priv->smu_tables.entry[PPTABLE].mc_addr, - &priv->smu_tables.entry[PPTABLE].table); -free_backend: - kfree(hwmgr->smu_backend); - - return -EINVAL; -} - -static int vega10_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct vega10_smumgr *priv = hwmgr->smu_backend; - - if (priv) { - amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle, - &priv->smu_tables.entry[PPTABLE].mc_addr, - &priv->smu_tables.entry[PPTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle, - &priv->smu_tables.entry[WMTABLE].mc_addr, - &priv->smu_tables.entry[WMTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle, - &priv->smu_tables.entry[AVFSTABLE].mc_addr, - &priv->smu_tables.entry[AVFSTABLE].table); - if (priv->smu_tables.entry[TOOLSTABLE].table) - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle, - &priv->smu_tables.entry[TOOLSTABLE].mc_addr, - &priv->smu_tables.entry[TOOLSTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle, - &priv->smu_tables.entry[AVFSFUSETABLE].mc_addr, - &priv->smu_tables.entry[AVFSFUSETABLE].table); - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - } - return 0; -} - -static int vega10_start_smu(struct pp_hwmgr *hwmgr) -{ - if (!smu9_is_smc_ram_running(hwmgr)) - return -EINVAL; - - PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr), - "Failed to verify SMC interface!", - return -EINVAL); - - vega10_set_tools_address(hwmgr); - - return 0; -} - -static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, - uint16_t table_id, bool rw) -{ - int ret; - - if (rw) - ret = vega10_copy_table_from_smc(hwmgr, table, table_id); - else - ret = vega10_copy_table_to_smc(hwmgr, table, table_id); - - return ret; -} - -const struct pp_smumgr_func vega10_smu_funcs = { - .name = "vega10_smu", - .smu_init = &vega10_smu_init, - .smu_fini = &vega10_smu_fini, - .start_smu = &vega10_start_smu, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &smu9_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .is_dpm_running = vega10_is_dpm_running, - .get_argument = smu9_get_argument, - .smc_table_manager = vega10_smc_table_manager, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h deleted file mode 100644 index bad760f22624..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2016 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 _VEGA10_SMUMANAGER_H_ -#define _VEGA10_SMUMANAGER_H_ - -#define MAX_SMU_TABLE 5 - -struct smu_table_entry { - uint32_t version; - uint32_t size; - uint32_t table_id; - uint64_t mc_addr; - void *table; - struct amdgpu_bo *handle; -}; - -struct smu_table_array { - struct smu_table_entry entry[MAX_SMU_TABLE]; -}; - -struct vega10_smumgr { - struct smu_table_array smu_tables; -}; - -int vega10_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint32_t feature_mask); -int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c deleted file mode 100644 index f54df76537e4..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.c +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "smumgr.h" -#include "vega12_inc.h" -#include "soc15_common.h" -#include "smu9_smumgr.h" -#include "vega12_smumgr.h" -#include "vega12_ppsmc.h" -#include "vega12/smu9_driver_if.h" -#include "ppatomctrl.h" -#include "pp_debug.h" - - -/* - * Copy table from SMC into driver FB - * @param hwmgr the address of the HW manager - * @param table_id the driver's table ID to copy from - */ -static int vega12_copy_table_from_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega12_smumgr *priv = - (struct vega12_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL) == 0, - "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL) == 0, - "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", - return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableSmu2Dram, - table_id, - NULL) == 0, - "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", - return -EINVAL); - - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); - - memcpy(table, priv->smu_tables.entry[table_id].table, - priv->smu_tables.entry[table_id].size); - - return 0; -} - -/* - * Copy table from Driver FB into SMC - * @param hwmgr the address of the HW manager - * @param table_id the table to copy from - */ -static int vega12_copy_table_to_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega12_smumgr *priv = - (struct vega12_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - - memcpy(priv->smu_tables.entry[table_id].table, table, - priv->smu_tables.entry[table_id].size); - - amdgpu_asic_flush_hdp(adev, NULL); - - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL) == 0, - "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", - return -EINVAL;); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL) == 0, - "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", - return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableDram2Smu, - table_id, - NULL) == 0, - "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", - return -EINVAL); - - return 0; -} - -int vega12_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint64_t feature_mask) -{ - uint32_t smu_features_low, smu_features_high; - - smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); - smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); - - if (enable) { - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL) == 0, - "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!", - return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL) == 0, - "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!", - return -EINVAL); - } else { - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL) == 0, - "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!", - return -EINVAL); - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL) == 0, - "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!", - return -EINVAL); - } - - return 0; -} - -int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled) -{ - uint32_t smc_features_low, smc_features_high; - - if (features_enabled == NULL) - return -EINVAL; - - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetEnabledSmuFeaturesLow, - &smc_features_low) == 0, - "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!", - return -EINVAL); - - PP_ASSERT_WITH_CODE(smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetEnabledSmuFeaturesHigh, - &smc_features_high) == 0, - "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!", - return -EINVAL); - - *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | - (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); - - return 0; -} - -static bool vega12_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - uint64_t features_enabled = 0; - - vega12_get_enabled_smc_features(hwmgr, &features_enabled); - - if (features_enabled & SMC_DPM_FEATURES) - return true; - else - return false; -} - -static int vega12_set_tools_address(struct pp_hwmgr *hwmgr) -{ - struct vega12_smumgr *priv = - (struct vega12_smumgr *)(hwmgr->smu_backend); - - if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) { - if (!smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), - NULL)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), - NULL); - } - return 0; -} - -static int vega12_smu_init(struct pp_hwmgr *hwmgr) -{ - struct vega12_smumgr *priv; - unsigned long tools_size; - struct cgs_firmware_info info = {0}; - int ret; - - ret = cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, - &info); - if (ret || !info.kptr) - return -EINVAL; - - priv = kzalloc(sizeof(struct vega12_smumgr), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - hwmgr->smu_backend = priv; - - /* allocate space for pptable */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(PPTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); - if (ret) - goto free_backend; - - priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01; - priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t); - - /* allocate space for watermarks table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(Watermarks_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); - - if (ret) - goto err0; - - priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01; - priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t); - - tools_size = 0x19000; - if (tools_size) { - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - tools_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); - if (ret) - goto err1; - - priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01; - priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size; - } - - /* allocate space for AVFS Fuse table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(AvfsFuseOverride_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); - - if (ret) - goto err2; - - priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].version = 0x01; - priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].size = sizeof(AvfsFuseOverride_t); - - /* allocate space for OverDrive table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(OverDriveTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); - if (ret) - goto err3; - - priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01; - priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t); - - /* allocate space for SMU_METRICS table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(SmuMetrics_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_SMU_METRICS].handle, - &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, - &priv->smu_tables.entry[TABLE_SMU_METRICS].table); - if (ret) - goto err4; - - priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01; - priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t); - - return 0; - -err4: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); -err3: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); -err2: - if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table) - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); -err1: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); -err0: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); -free_backend: - kfree(hwmgr->smu_backend); - - return -EINVAL; -} - -static int vega12_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct vega12_smumgr *priv = - (struct vega12_smumgr *)(hwmgr->smu_backend); - - if (priv) { - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); - if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].table) - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].handle, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].mc_addr, - &priv->smu_tables.entry[TABLE_AVFS_FUSE_OVERRIDE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, - &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, - &priv->smu_tables.entry[TABLE_SMU_METRICS].table); - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - } - return 0; -} - -static int vega12_start_smu(struct pp_hwmgr *hwmgr) -{ - PP_ASSERT_WITH_CODE(smu9_is_smc_ram_running(hwmgr), - "SMC is not running!", - return -EINVAL); - - vega12_set_tools_address(hwmgr); - - return 0; -} - -static int vega12_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, - uint16_t table_id, bool rw) -{ - int ret; - - if (rw) - ret = vega12_copy_table_from_smc(hwmgr, table, table_id); - else - ret = vega12_copy_table_to_smc(hwmgr, table, table_id); - - return ret; -} - -const struct pp_smumgr_func vega12_smu_funcs = { - .name = "vega12_smu", - .smu_init = &vega12_smu_init, - .smu_fini = &vega12_smu_fini, - .start_smu = &vega12_start_smu, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &smu9_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .is_dpm_running = vega12_is_dpm_running, - .get_argument = smu9_get_argument, - .smc_table_manager = vega12_smc_table_manager, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h deleted file mode 100644 index aeec965ce81f..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega12_smumgr.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _VEGA12_SMUMANAGER_H_ -#define _VEGA12_SMUMANAGER_H_ - -#include "hwmgr.h" -#include "vega12/smu9_driver_if.h" -#include "vega12_hwmgr.h" - -struct smu_table_entry { - uint32_t version; - uint32_t size; - uint64_t mc_addr; - void *table; - struct amdgpu_bo *handle; -}; - -struct smu_table_array { - struct smu_table_entry entry[TABLE_COUNT]; -}; - -struct vega12_smumgr { - struct smu_table_array smu_tables; -}; - -#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF -#define SMU_FEATURES_LOW_SHIFT 0 -#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 -#define SMU_FEATURES_HIGH_SHIFT 32 - -int vega12_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint64_t feature_mask); -int vega12_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c deleted file mode 100644 index cf43629d29d2..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Copyright 2018 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 "smumgr.h" -#include "vega20_inc.h" -#include "soc15_common.h" -#include "vega20_smumgr.h" -#include "vega20_ppsmc.h" -#include "smu11_driver_if.h" -#include "ppatomctrl.h" -#include "pp_debug.h" -#include "smu_ucode_xfer_vi.h" -#include "smu7_smumgr.h" -#include "vega20_hwmgr.h" - -#include "smu_v11_0_i2c.h" - -/* MP Apertures */ -#define MP0_Public 0x03800000 -#define MP0_SRAM 0x03900000 -#define MP1_Public 0x03b00000 -#define MP1_SRAM 0x03c00004 - -/* address block */ -#define smnMP1_FIRMWARE_FLAGS 0x3010024 -#define smnMP0_FW_INTF 0x30101c0 -#define smnMP1_PUB_CTRL 0x3010b14 - -bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t mp1_fw_flags; - - mp1_fw_flags = RREG32_PCIE(MP1_Public | - (smnMP1_FIRMWARE_FLAGS & 0xffffffff)); - - if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >> - MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT) - return true; - - return false; -} - -/* - * Check if SMC has responded to previous message. - * - * @param smumgr the address of the powerplay hardware manager. - * @return TRUE SMC has responded, FALSE otherwise. - */ -static uint32_t vega20_wait_for_response(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - uint32_t reg; - - reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); - - phm_wait_for_register_unequal(hwmgr, reg, - 0, MP1_C2PMSG_90__CONTENT_MASK); - - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); -} - -/* - * Send a message to the SMC, and do not wait for its response. - * @param smumgr the address of the powerplay hardware manager. - * @param msg the message to send. - * @return Always return 0. - */ -static int vega20_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, - uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); - - return 0; -} - -/* - * Send a message to the SMC, and wait for its response. - * @param hwmgr the address of the powerplay hardware manager. - * @param msg the message to send. - * @return Always return 0. - */ -static int vega20_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - vega20_wait_for_response(hwmgr); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - vega20_send_msg_to_smc_without_waiting(hwmgr, msg); - - ret = vega20_wait_for_response(hwmgr); - if (ret != PPSMC_Result_OK) - pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); - - return (ret == PPSMC_Result_OK) ? 0 : -EIO; -} - -/* - * Send a message to the SMC with parameter - * @param hwmgr: the address of the powerplay hardware manager. - * @param msg: the message to send. - * @param parameter: the parameter to send - * @return Always return 0. - */ -static int vega20_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - vega20_wait_for_response(hwmgr); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); - - WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); - - vega20_send_msg_to_smc_without_waiting(hwmgr, msg); - - ret = vega20_wait_for_response(hwmgr); - if (ret != PPSMC_Result_OK) - pr_err("Failed to send message 0x%x, response 0x%x\n", msg, ret); - - return (ret == PPSMC_Result_OK) ? 0 : -EIO; -} - -static uint32_t vega20_get_argument(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); -} - -/* - * Copy table from SMC into driver FB - * @param hwmgr the address of the HW manager - * @param table_id the driver's table ID to copy from - */ -static int vega20_copy_table_from_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL)) == 0, - "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL)) == 0, - "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableSmu2Dram, table_id, NULL)) == 0, - "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!", - return ret); - - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); - - memcpy(table, priv->smu_tables.entry[table_id].table, - priv->smu_tables.entry[table_id].size); - - return 0; -} - -/* - * Copy table from Driver FB into SMC - * @param hwmgr the address of the HW manager - * @param table_id the table to copy from - */ -static int vega20_copy_table_to_smc(struct pp_hwmgr *hwmgr, - uint8_t *table, int16_t table_id) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - PP_ASSERT_WITH_CODE(table_id < TABLE_COUNT, - "Invalid SMU Table ID!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, - "Invalid SMU Table version!", return -EINVAL); - PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, - "Invalid SMU Table Length!", return -EINVAL); - - memcpy(priv->smu_tables.entry[table_id].table, table, - priv->smu_tables.entry[table_id].size); - - amdgpu_asic_flush_hdp(adev, NULL); - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL)) == 0, - "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[table_id].mc_addr), - NULL)) == 0, - "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableDram2Smu, table_id, NULL)) == 0, - "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!", - return ret); - - return 0; -} - -int vega20_set_activity_monitor_coeff(struct pp_hwmgr *hwmgr, - uint8_t *table, uint16_t workload_type) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - memcpy(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, table, - priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size); - - amdgpu_asic_flush_hdp(adev, NULL); - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), - NULL)) == 0, - "[SetActivityMonitor] Attempt to Set Dram Addr High Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), - NULL)) == 0, - "[SetActivityMonitor] Attempt to Set Dram Addr Low Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableDram2Smu, - TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16), - NULL)) == 0, - "[SetActivityMonitor] Attempt to Transfer Table To SMU Failed!", - return ret); - - return 0; -} - -int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr, - uint8_t *table, uint16_t workload_type) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - int ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), - NULL)) == 0, - "[GetActivityMonitor] Attempt to Set Dram Addr High Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr), - NULL)) == 0, - "[GetActivityMonitor] Attempt to Set Dram Addr Low Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_TransferTableSmu2Dram, - TABLE_ACTIVITY_MONITOR_COEFF | (workload_type << 16), NULL)) == 0, - "[GetActivityMonitor] Attempt to Transfer Table From SMU Failed!", - return ret); - - /* flush hdp cache */ - amdgpu_asic_flush_hdp(adev, NULL); - - memcpy(table, priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table, - priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size); - - return 0; -} - -int vega20_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint64_t feature_mask) -{ - uint32_t smu_features_low, smu_features_high; - int ret = 0; - - smu_features_low = (uint32_t)((feature_mask & SMU_FEATURES_LOW_MASK) >> SMU_FEATURES_LOW_SHIFT); - smu_features_high = (uint32_t)((feature_mask & SMU_FEATURES_HIGH_MASK) >> SMU_FEATURES_HIGH_SHIFT); - - if (enable) { - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableSmuFeaturesLow, smu_features_low, NULL)) == 0, - "[EnableDisableSMCFeatures] Attempt to enable SMU features Low failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableSmuFeaturesHigh, smu_features_high, NULL)) == 0, - "[EnableDisableSMCFeatures] Attempt to enable SMU features High failed!", - return ret); - } else { - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableSmuFeaturesLow, smu_features_low, NULL)) == 0, - "[EnableDisableSMCFeatures] Attempt to disable SMU features Low failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_DisableSmuFeaturesHigh, smu_features_high, NULL)) == 0, - "[EnableDisableSMCFeatures] Attempt to disable SMU features High failed!", - return ret); - } - - return 0; -} - -int vega20_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled) -{ - uint32_t smc_features_low, smc_features_high; - int ret = 0; - - if (features_enabled == NULL) - return -EINVAL; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetEnabledSmuFeaturesLow, - &smc_features_low)) == 0, - "[GetEnabledSMCFeatures] Attempt to get SMU features Low failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_GetEnabledSmuFeaturesHigh, - &smc_features_high)) == 0, - "[GetEnabledSMCFeatures] Attempt to get SMU features High failed!", - return ret); - - *features_enabled = ((((uint64_t)smc_features_low << SMU_FEATURES_LOW_SHIFT) & SMU_FEATURES_LOW_MASK) | - (((uint64_t)smc_features_high << SMU_FEATURES_HIGH_SHIFT) & SMU_FEATURES_HIGH_MASK)); - - return 0; -} - -static int vega20_set_tools_address(struct pp_hwmgr *hwmgr) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - int ret = 0; - - if (priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr) { - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), - NULL); - if (!ret) - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetToolsDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr), - NULL); - } - - return ret; -} - -int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - int ret = 0; - - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrHigh, - upper_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr), - NULL)) == 0, - "[SetPPtabeDriverAddress] Attempt to Set Dram Addr High Failed!", - return ret); - PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetDriverDramAddrLow, - lower_32_bits(priv->smu_tables.entry[TABLE_PPTABLE].mc_addr), - NULL)) == 0, - "[SetPPtabeDriverAddress] Attempt to Set Dram Addr Low Failed!", - return ret); - - return ret; -} - -static int vega20_smu_init(struct pp_hwmgr *hwmgr) -{ - struct vega20_smumgr *priv; - unsigned long tools_size = 0x19000; - int ret = 0; - struct amdgpu_device *adev = hwmgr->adev; - - struct cgs_firmware_info info = {0}; - - ret = cgs_get_firmware_info(hwmgr->device, - smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), - &info); - if (ret || !info.kptr) - return -EINVAL; - - priv = kzalloc(sizeof(struct vega20_smumgr), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - hwmgr->smu_backend = priv; - - /* allocate space for pptable */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(PPTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); - if (ret) - goto free_backend; - - priv->smu_tables.entry[TABLE_PPTABLE].version = 0x01; - priv->smu_tables.entry[TABLE_PPTABLE].size = sizeof(PPTable_t); - - /* allocate space for watermarks table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(Watermarks_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); - if (ret) - goto err0; - - priv->smu_tables.entry[TABLE_WATERMARKS].version = 0x01; - priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t); - - /* allocate space for pmstatuslog table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - tools_size, - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); - if (ret) - goto err1; - - priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01; - priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size; - - /* allocate space for OverDrive table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(OverDriveTable_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); - if (ret) - goto err2; - - priv->smu_tables.entry[TABLE_OVERDRIVE].version = 0x01; - priv->smu_tables.entry[TABLE_OVERDRIVE].size = sizeof(OverDriveTable_t); - - /* allocate space for SmuMetrics table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(SmuMetrics_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_SMU_METRICS].handle, - &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, - &priv->smu_tables.entry[TABLE_SMU_METRICS].table); - if (ret) - goto err3; - - priv->smu_tables.entry[TABLE_SMU_METRICS].version = 0x01; - priv->smu_tables.entry[TABLE_SMU_METRICS].size = sizeof(SmuMetrics_t); - - /* allocate space for ActivityMonitor table */ - ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, - sizeof(DpmActivityMonitorCoeffInt_t), - PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, - &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle, - &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr, - &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table); - if (ret) - goto err4; - - priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01; - priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t); - - ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c); - if (ret) - goto err4; - - return 0; - -err4: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, - &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, - &priv->smu_tables.entry[TABLE_SMU_METRICS].table); -err3: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); -err2: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); -err1: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); -err0: - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); -free_backend: - kfree(hwmgr->smu_backend); - - return -EINVAL; -} - -static int vega20_smu_fini(struct pp_hwmgr *hwmgr) -{ - struct vega20_smumgr *priv = - (struct vega20_smumgr *)(hwmgr->smu_backend); - struct amdgpu_device *adev = hwmgr->adev; - - smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c); - - if (priv) { - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle, - &priv->smu_tables.entry[TABLE_PPTABLE].mc_addr, - &priv->smu_tables.entry[TABLE_PPTABLE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_WATERMARKS].handle, - &priv->smu_tables.entry[TABLE_WATERMARKS].mc_addr, - &priv->smu_tables.entry[TABLE_WATERMARKS].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr, - &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_OVERDRIVE].handle, - &priv->smu_tables.entry[TABLE_OVERDRIVE].mc_addr, - &priv->smu_tables.entry[TABLE_OVERDRIVE].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_SMU_METRICS].handle, - &priv->smu_tables.entry[TABLE_SMU_METRICS].mc_addr, - &priv->smu_tables.entry[TABLE_SMU_METRICS].table); - amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].handle, - &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].mc_addr, - &priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].table); - kfree(hwmgr->smu_backend); - hwmgr->smu_backend = NULL; - } - - return 0; -} - -static int vega20_start_smu(struct pp_hwmgr *hwmgr) -{ - int ret; - - ret = vega20_is_smc_ram_running(hwmgr); - PP_ASSERT_WITH_CODE(ret, - "[Vega20StartSmu] SMC is not running!", - return -EINVAL); - - ret = vega20_set_tools_address(hwmgr); - PP_ASSERT_WITH_CODE(!ret, - "[Vega20StartSmu] Failed to set tools address!", - return ret); - - return 0; -} - -static bool vega20_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - uint64_t features_enabled = 0; - - vega20_get_enabled_smc_features(hwmgr, &features_enabled); - - if (features_enabled & SMC_DPM_FEATURES) - return true; - else - return false; -} - -static int vega20_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, - uint16_t table_id, bool rw) -{ - int ret; - - if (rw) - ret = vega20_copy_table_from_smc(hwmgr, table, table_id); - else - ret = vega20_copy_table_to_smc(hwmgr, table, table_id); - - return ret; -} - -const struct pp_smumgr_func vega20_smu_funcs = { - .name = "vega20_smu", - .smu_init = &vega20_smu_init, - .smu_fini = &vega20_smu_fini, - .start_smu = &vega20_start_smu, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = &vega20_send_msg_to_smc, - .send_msg_to_smc_with_parameter = &vega20_send_msg_to_smc_with_parameter, - .download_pptable_settings = NULL, - .upload_pptable_settings = NULL, - .is_dpm_running = vega20_is_dpm_running, - .get_argument = vega20_get_argument, - .smc_table_manager = vega20_smc_table_manager, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h deleted file mode 100644 index 62ebbfd6068f..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2018 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 _VEGA20_SMUMANAGER_H_ -#define _VEGA20_SMUMANAGER_H_ - -#include "hwmgr.h" -#include "smu11_driver_if.h" - -struct smu_table_entry { - uint32_t version; - uint32_t size; - uint64_t mc_addr; - void *table; - struct amdgpu_bo *handle; -}; - -struct smu_table_array { - struct smu_table_entry entry[TABLE_COUNT]; -}; - -struct vega20_smumgr { - struct smu_table_array smu_tables; -}; - -#define SMU_FEATURES_LOW_MASK 0x00000000FFFFFFFF -#define SMU_FEATURES_LOW_SHIFT 0 -#define SMU_FEATURES_HIGH_MASK 0xFFFFFFFF00000000 -#define SMU_FEATURES_HIGH_SHIFT 32 - -int vega20_enable_smc_features(struct pp_hwmgr *hwmgr, - bool enable, uint64_t feature_mask); -int vega20_get_enabled_smc_features(struct pp_hwmgr *hwmgr, - uint64_t *features_enabled); -int vega20_set_activity_monitor_coeff(struct pp_hwmgr *hwmgr, - uint8_t *table, uint16_t workload_type); -int vega20_get_activity_monitor_coeff(struct pp_hwmgr *hwmgr, - uint8_t *table, uint16_t workload_type); -int vega20_set_pptable_driver_address(struct pp_hwmgr *hwmgr); - -bool vega20_is_smc_ram_running(struct pp_hwmgr *hwmgr); - -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c deleted file mode 100644 index 0ecc18b55ffb..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c +++ /dev/null @@ -1,2302 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include "pp_debug.h" -#include "smumgr.h" -#include "smu_ucode_xfer_vi.h" -#include "vegam_smumgr.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "oss/oss_3_0_d.h" -#include "gca/gfx_8_0_d.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "smu7_ppsmc.h" - -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "atombios.h" -#include "pppcielanes.h" - -#include "dce/dce_11_2_d.h" -#include "dce/dce_11_2_sh_mask.h" - -#define PPVEGAM_TARGETACTIVITY_DFLT 50 - -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VDDC_VDDCI_DELTA 200 -#define MC_CG_ARB_FREQ_F1 0x0b - -#define STRAP_ASIC_RO_LSB 2168 -#define STRAP_ASIC_RO_MSB 2175 - -#define PPSMC_MSG_ApplyAvfsCksOffVoltage ((uint16_t) 0x415) -#define PPSMC_MSG_EnableModeSwitchRLCNotification ((uint16_t) 0x305) - -static const struct vegam_pt_defaults -vegam_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { - /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ - { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, -}; - -static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { - {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, - {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, - {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; - -static int vegam_smu_init(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data; - - smu_data = kzalloc(sizeof(struct vegam_smumgr), GFP_KERNEL); - if (smu_data == NULL) - return -ENOMEM; - - hwmgr->smu_backend = smu_data; - - if (smu7_init(hwmgr)) { - kfree(smu_data); - return -EINVAL; - } - - return 0; -} - -static int vegam_start_smu_in_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* Wait for smc boot up */ - /* PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0) */ - - /* Assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result != 0) - return result; - - /* Clear status */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMU_STATUS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - /* De-assert reset */ - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); - - - /* Call Test SMU message with 0x20000 offset to trigger SMU start */ - smu7_send_msg_to_smc_offset(hwmgr); - - /* Wait done bit to be set */ - /* Check pass/failed indicator */ - - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, SMU_STATUS, SMU_DONE, 0); - - if (1 != PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMU_STATUS, SMU_PASS)) - PP_ASSERT_WITH_CODE(false, "SMU Firmware start failed!", return -1); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixFIRMWARE_FLAGS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 1); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int vegam_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) -{ - int result = 0; - - /* wait for smc boot up */ - PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, SMC_IND, RCU_UC_EVENTS, boot_seq_done, 0); - - /* Clear firmware interrupt enable flag */ - /* PHM_WRITE_VFPF_INDIRECT_FIELD(pSmuMgr, SMC_IND, SMC_SYSCON_MISC_CNTL, pre_fetcher_en, 1); */ - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixFIRMWARE_FLAGS, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, - rst_reg, 1); - - result = smu7_upload_smu_firmware_image(hwmgr); - if (result != 0) - return result; - - /* Set smc instruct start point at 0x0 */ - smu7_program_jump_on_start(hwmgr); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - /* Wait for firmware to initialize */ - - PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, SMC_IND, - FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); - - return result; -} - -static int vegam_start_smu(struct pp_hwmgr *hwmgr) -{ - int result = 0; - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - /* Only start SMC if SMC RAM is not running */ - if (!smu7_is_smc_ram_running(hwmgr) && hwmgr->not_vf) { - smu_data->protected_mode = (uint8_t)(PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_MODE)); - smu_data->smu7_data.security_hard_key = (uint8_t)(PHM_READ_VFPF_INDIRECT_FIELD( - hwmgr->device, CGS_IND_REG__SMC, SMU_FIRMWARE, SMU_SEL)); - - /* Check if SMU is running in protected mode */ - if (smu_data->protected_mode == 0) - result = vegam_start_smu_in_non_protection_mode(hwmgr); - else - result = vegam_start_smu_in_protection_mode(hwmgr); - - if (result != 0) - PP_ASSERT_WITH_CODE(0, "Failed to load SMU ucode.", return result); - } - - /* Setup SoftRegsStart here for register lookup in case DummyBackEnd is used and ProcessFirmwareHeader is not executed */ - smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU75_Firmware_Header, SoftRegisters), - &(smu_data->smu7_data.soft_regs_start), - 0x40000); - - result = smu7_request_smu_load_fw(hwmgr); - - return result; -} - -static int vegam_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? -1 : 0; -} - -static bool vegam_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -static uint32_t vegam_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU75_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU75_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU75_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU75_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU75_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU75_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU75_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU75_MAX_LEVELS_MVDD; - case SMU_UVD_MCLK_HANDSHAKE_DISABLE: - return SMU7_UVD_MCLK_HANDSHAKE_DISABLE | - SMU7_VCE_MCLK_HANDSHAKE_DISABLE; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - -static int vegam_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU75_Discrete_DpmTable, - UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel), - NULL); - return 0; -} - -static int vegam_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - else - smu_data->smc_state_table.VceBootLevel = 0; - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU75_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel, - NULL); - return 0; -} - -static int vegam_update_bif_smc_table(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - int max_entry, i; - - max_entry = (SMU75_MAX_LEVELS_LINK < pcie_table->count) ? - SMU75_MAX_LEVELS_LINK : - pcie_table->count; - /* Setup BIF_SCLK levels */ - for (i = 0; i < max_entry; i++) - smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; - return 0; -} - -static int vegam_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - vegam_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - vegam_update_vce_smc_table(hwmgr); - break; - case SMU_BIF_TABLE: - vegam_update_bif_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - -static void vegam_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &vegam_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &vegam_power_tune_data_set_array[0]; - -} - -static int vegam_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU75_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count, level; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - count = data->mvdd_voltage_table.count; - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; level++) { - table->SmioTable2.Pattern[level].Voltage = PP_HOST_TO_SMC_US( - data->mvdd_voltage_table.entries[level].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ - table->SmioTable2.Pattern[level].Smio = - (uint8_t) level; - table->Smio[level] |= - data->mvdd_voltage_table.entries[level].smio_low; - } - table->SmioMask2 = data->mvdd_voltage_table.mask_low; - - table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); - } - - return 0; -} - -static int vegam_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - uint32_t count, level; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - count = data->vddci_voltage_table.count; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; ++level) { - table->SmioTable1.Pattern[level].Voltage = PP_HOST_TO_SMC_US( - data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); - table->SmioTable1.Pattern[level].Smio = (uint8_t) level; - - table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; - } - } - - table->SmioMask1 = data->vddci_voltage_table.mask_low; - - return 0; -} - -static int vegam_populate_cac_table(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *lookup_table = - table_info->vddc_lookup_table; - /* tables is already swapped, so in order to use the value from it, - * we need to swap it back. - * We are populating vddc CAC data to BapmVddc table - * in split and merged mode - */ - for (count = 0; count < lookup_table->count; count++) { - index = phm_get_voltage_index(lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_mid); - table->BapmVddcVidHiSidd2[count] = - convert_to_vid(lookup_table->entries[index].us_cac_high); - } - - return 0; -} - -static int vegam_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - vegam_populate_smc_vddci_table(hwmgr, table); - vegam_populate_smc_mvdd_table(hwmgr, table); - vegam_populate_cac_table(hwmgr, table); - - return 0; -} - -static int vegam_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_Ulv *state) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int vegam_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - return vegam_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int vegam_populate_smc_link_level(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = - (struct vegam_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int i; - - /* Index (dpm_table->pcie_speed_table.count) - * is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( - dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - -/* To Do move to hwmgr */ - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, - uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) -{ - uint32_t i; - uint16_t vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - *voltage = *mvdd = 0; - - /* clock - voltage dependency table is empty table */ - if (dep_table->count == 0) - return -EINVAL; - - for (i = 0; i < dep_table->count; i++) { - /* find first sclk bigger than request */ - if (dep_table->entries[i].clk >= clock) { - *voltage |= (dep_table->entries[i].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i].vddci) - *voltage |= (dep_table->entries[i].vddci * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i].mvdd * - VOLTAGE_SCALE; - - *voltage |= 1 << PHASES_SHIFT; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i - 1].vddci) - *voltage |= (dep_table->entries[i - 1].vddci * - VOLTAGE_SCALE) << VDDC_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i - 1].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; - - return 0; -} - -static void vegam_get_sclk_range_table(struct pp_hwmgr *hwmgr, - SMU75_Discrete_DpmTable *table) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - uint32_t i, ref_clk; - - struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; - - ref_clk = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { - for (i = 0; i < NUM_SCLK_RANGE; i++) { - table->SclkFcwRangeTable[i].vco_setting = - range_table_from_vbios.entry[i].ucVco_setting; - table->SclkFcwRangeTable[i].postdiv = - range_table_from_vbios.entry[i].ucPostdiv; - table->SclkFcwRangeTable[i].fcw_pcc = - range_table_from_vbios.entry[i].usFcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = - range_table_from_vbios.entry[i].usFcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = - range_table_from_vbios.entry[i].usRcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } - return; - } - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - smu_data->range_table[i].trans_lower_frequency = - (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; - smu_data->range_table[i].trans_upper_frequency = - (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; - - table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; - table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; - table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } -} - -static int vegam_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, SMU_SclkSetting *sclk_setting) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - const SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct pp_atomctrl_clock_dividers_ai dividers; - uint32_t ref_clock; - uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; - uint8_t i; - int result; - uint64_t temp; - - sclk_setting->SclkFrequency = clock; - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); - if (result == 0) { - sclk_setting->Fcw_int = dividers.usSclk_fcw_int; - sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; - sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; - sclk_setting->PllRange = dividers.ucSclkPllRange; - sclk_setting->Sclk_slew_rate = 0x400; - sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; - sclk_setting->Pcc_down_slew_rate = 0xffff; - sclk_setting->SSc_En = dividers.ucSscEnable; - sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; - sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; - sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; - return result; - } - - ref_clock = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev); - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - if (clock > smu_data->range_table[i].trans_lower_frequency - && clock <= smu_data->range_table[i].trans_upper_frequency) { - sclk_setting->PllRange = i; - break; - } - } - - sclk_setting->Fcw_int = (uint16_t) - ((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / - ref_clock); - temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw_frac = temp & 0xffff; - - pcc_target_percent = 10; /* Hardcode 10% for now. */ - pcc_target_freq = clock - (clock * pcc_target_percent / 100); - sclk_setting->Pcc_fcw_int = (uint16_t) - ((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / - ref_clock); - - ss_target_percent = 2; /* Hardcode 2% for now. */ - sclk_setting->SSc_En = 0; - if (ss_target_percent) { - sclk_setting->SSc_En = 1; - ss_target_freq = clock - (clock * ss_target_percent / 100); - sclk_setting->Fcw1_int = (uint16_t) - ((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / - ref_clock); - temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw1_frac = temp & 0xffff; - } - - return 0; -} - -static uint8_t vegam_get_sleep_divider_id_from_clock(uint32_t clock, - uint32_t clock_insr) -{ - uint8_t i; - uint32_t temp; - uint32_t min = max(clock_insr, (uint32_t)SMU7_MINIMUM_ENGINE_CLOCK); - - PP_ASSERT_WITH_CODE((clock >= min), - "Engine clock can't satisfy stutter requirement!", - return 0); - for (i = 31; ; i--) { - temp = clock / (i + 1); - - if (temp >= min || i == 0) - break; - } - return i; -} - -static int vegam_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU75_Discrete_GraphicsLevel *level) -{ - int result; - /* PP_Clocks minClocks; */ - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMU_SclkSetting curr_sclk_setting = { 0 }; - - result = vegam_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); - - /* populate graphics levels */ - result = vegam_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, clock, - &level->MinVoltage, &mvdd); - - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for " - "VDDC engine clock dependency table", - return result); - level->ActivityLevel = (uint16_t)(SclkDPMTuning_VEGAM >> DPMTuning_Activity_Shift); - - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - level->EnabledForThrottle = 1; - level->VoltageDownHyst = 0; - level->PowerThrottle = 0; - data->display_timing.min_clock_in_sr = hwmgr->display_config->min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = vegam_get_sleep_divider_id_from_clock(clock, - hwmgr->display_config->min_core_set_clock_in_sr); - - level->SclkSetting = curr_sclk_setting; - - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); - return 0; -} - -static int vegam_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; - int result = 0; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU75_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU75_Discrete_GraphicsLevel) * - SMU75_MAX_LEVELS_GRAPHICS; - struct SMU75_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i, max_entry; - uint8_t hightest_pcie_level_enabled = 0, - lowest_pcie_level_enabled = 0, - mid_pcie_level_enabled = 0, - count = 0; - - vegam_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - - result = vegam_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result) - return result; - - levels[i].UpHyst = (uint8_t) - (SclkDPMTuning_VEGAM >> DPMTuning_Uphyst_Shift); - levels[i].DownHyst = (uint8_t) - (SclkDPMTuning_VEGAM >> DPMTuning_Downhyst_Shift); - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - levels[i].DeepSleepDivId = 0; - } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport)) - smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].EnabledForActivity = - (hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask >> i) & 0x1; - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_cnt - 1; - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } else { - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (hightest_pcie_level_enabled + 1))) != 0)) - hightest_pcie_level_enabled++; - - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0)) - lowest_pcie_level_enabled++; - - while ((count < hightest_pcie_level_enabled) && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) - count++; - - mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < - hightest_pcie_level_enabled ? - (lowest_pcie_level_enabled + 1 + count) : - hightest_pcie_level_enabled; - - /* set pcieDpmLevel to hightest_pcie_level_enabled */ - for (i = 2; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = hightest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled */ - levels[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled */ - levels[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - -static int vegam_calculate_mclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU75_Discrete_MemoryLevel *mem_level) -{ - struct pp_atomctrl_memory_clock_param_ai mpll_param; - - PP_ASSERT_WITH_CODE(!atomctrl_get_memory_pll_dividers_ai(hwmgr, - clock, &mpll_param), - "Failed to retrieve memory pll parameter.", - return -EINVAL); - - mem_level->MclkFrequency = (uint32_t)mpll_param.ulClock; - mem_level->Fcw_int = (uint16_t)mpll_param.ulMclk_fcw_int; - mem_level->Fcw_frac = (uint16_t)mpll_param.ulMclk_fcw_frac; - mem_level->Postdiv = (uint8_t)mpll_param.ulPostDiv; - - return 0; -} - -static int vegam_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU75_Discrete_MemoryLevel *mem_level) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - uint32_t mclk_stutter_mode_threshold = 60000; - - - if (table_info->vdd_dep_on_mclk) { - result = vegam_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, clock, - &mem_level->MinVoltage, &mem_level->MinMvdd); - PP_ASSERT_WITH_CODE(!result, - "can not find MinVddc voltage value from memory " - "VDDC voltage dependency table", return result); - } - - result = vegam_calculate_mclk_params(hwmgr, clock, mem_level); - PP_ASSERT_WITH_CODE(!result, - "Failed to calculate mclk params.", - return -EINVAL); - - mem_level->EnabledForThrottle = 1; - mem_level->EnabledForActivity = 0; - mem_level->VoltageDownHyst = 0; - mem_level->ActivityLevel = (uint16_t) - (MemoryDPMTuning_VEGAM >> DPMTuning_Activity_Shift); - mem_level->StutterEnable = false; - mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = hwmgr->display_config->num_display; - data->display_timing.vrefresh = hwmgr->display_config->vrefresh; - - if (mclk_stutter_mode_threshold && - (clock <= mclk_stutter_mode_threshold) && - (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) - mem_level->StutterEnable = true; - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); - } - - return result; -} - -static int vegam_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - int result; - /* populate MCLK dpm table to SMU7 */ - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU75_Discrete_DpmTable, MemoryLevel); - uint32_t array_size = sizeof(SMU75_Discrete_MemoryLevel) * - SMU75_MAX_LEVELS_MEMORY; - struct SMU75_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = vegam_populate_single_memory_level(hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &levels[i]); - - if (result) - return result; - - levels[i].UpHyst = (uint8_t) - (MemoryDPMTuning_VEGAM >> DPMTuning_Uphyst_Shift); - levels[i].DownHyst = (uint8_t) - (MemoryDPMTuning_VEGAM >> DPMTuning_Downhyst_Shift); - } - - smu_data->smc_state_table.MemoryDpmLevelCount = - (uint8_t)dpm_table->mclk_table.count; - hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - - for (i = 0; i < dpm_table->mclk_table.count; i++) - levels[i].EnabledForActivity = - (hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask >> i) & 0x1; - - levels[dpm_table->mclk_table.count - 1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - -static int vegam_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pat) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else - return -EINVAL; - - return 0; -} - -static int vegam_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU75_Discrete_DpmTable *table) -{ - int result = 0; - uint32_t sclk_frequency; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMIO_Pattern vol_level; - uint32_t mvdd; - - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - /* Get MinVoltage and Frequency from DPM0, - * already converted to SMC_UL */ - sclk_frequency = data->vbios_boot_state.sclk_bootup_value; - result = vegam_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, - sclk_frequency, - &table->ACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE(!result, - "Cannot find ACPI VDDC voltage value " - "in Clock Dependency Table", - ); - - result = vegam_calculate_sclk_params(hwmgr, sclk_frequency, - &(table->ACPILevel.SclkSetting)); - PP_ASSERT_WITH_CODE(!result, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - table->ACPILevel.DeepSleepDivId = 0; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); - - - /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ - table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; - result = vegam_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, - table->MemoryACPILevel.MclkFrequency, - &table->MemoryACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDCI voltage value " - "in Clock Dependency Table", - ); - - if (!vegam_populate_mvdd_value(hwmgr, 0, &vol_level)) - table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); - else - table->MemoryACPILevel.MinMvdd = 0; - - table->MemoryACPILevel.StutterEnable = false; - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US(data->current_profile_setting.mclk_activity); - - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); - - return result; -} - -static int vegam_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU75_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->VceLevelCount = (uint8_t)(mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage = 0; - table->VceLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - - table->VceLevel[count].MinVoltage |= - (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /*retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int vegam_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, - int32_t eng_clock, int32_t mem_clock, - SMU75_Discrete_MCArbDramTimingTableEntry *arb_regs) -{ - uint32_t dram_timing; - uint32_t dram_timing2; - uint32_t burst_time; - uint32_t rfsh_rate; - uint32_t misc3; - - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - eng_clock, mem_clock); - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", - return result); - - dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burst_time = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); - rfsh_rate = cgs_read_register(hwmgr->device, mmMC_ARB_RFSH_RATE); - misc3 = cgs_read_register(hwmgr->device, mmMC_ARB_MISC3); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); - arb_regs->McArbBurstTime = PP_HOST_TO_SMC_UL(burst_time); - arb_regs->McArbRfshRate = PP_HOST_TO_SMC_UL(rfsh_rate); - arb_regs->McArbMisc3 = PP_HOST_TO_SMC_UL(misc3); - - return 0; -} - -static int vegam_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct SMU75_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - int result = 0; - - memset(&arb_regs, 0, sizeof(SMU75_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { - result = vegam_populate_memory_timing_parameters(hwmgr, - hw_data->dpm_table.sclk_table.dpm_levels[i].value, - hw_data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - if (result) - return result; - } - } - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU75_Discrete_MCArbDramTimingTable), - SMC_RAM_END); - return result; -} - -static int vegam_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->UvdLevelCount = (uint8_t)(mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].MinVoltage = 0; - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); - } - - return result; -} - -static int vegam_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); - if (result) - return result; - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); - - if (result) - return result; - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value * - VOLTAGE_SCALE; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return 0; -} - -static int vegam_populate_smc_initial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint8_t count, level; - - count = (uint8_t)(table_info->vdd_dep_on_sclk->count); - - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_sclk->entries[level].clk >= - hw_data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(table_info->vdd_dep_on_mclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_mclk->entries[level].clk >= - hw_data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static uint16_t scale_fan_gain_settings(uint16_t raw_setting) -{ - uint32_t tmp; - tmp = raw_setting * 4096 / 100; - return (uint16_t)tmp; -} - -static int vegam_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - struct pp_advance_fan_control_parameters *fan_table = - &hwmgr->thermal_controller.advanceFanControlParameters; - int i, j, k; - const uint16_t *pdef1; - const uint16_t *pdef2; - - table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range!", - ); - - table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( - cac_dtp_table->usTargetOperatingTemp * 256); - table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitHotspot * 256); - table->FanGainEdge = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainEdge)); - table->FanGainHotspot = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHotspot)); - - pdef1 = defaults->BAPMTI_R; - pdef2 = defaults->BAPMTI_RC; - - for (i = 0; i < SMU75_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU75_DTE_SOURCES; j++) { - for (k = 0; k < SMU75_DTE_SINKS; k++) { - table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); - table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); - pdef1++; - pdef2++; - } - } - } - - return 0; -} - -static int vegam_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; - struct vegam_smumgr *smu_data = - (struct vegam_smumgr *)(hwmgr->smu_backend); - - uint8_t i, stretch_amount, volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - uint32_t mask = (1 << ((STRAP_ASIC_RO_MSB - STRAP_ASIC_RO_LSB) + 1)) - 1; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - atomctrl_read_efuse(hwmgr, STRAP_ASIC_RO_LSB, STRAP_ASIC_RO_MSB, - mask, &efuse); - - min = 1200; - max = 2500; - - ro = efuse * (max - min) / 255 + min; - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * - 136418 - (ro - 70) * 1000000) / - (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); - volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * - 3232 - (ro - 65) * 1000000) / - (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); - - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); - - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - smu_data->smc_state_table.LdoRefSel = - (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? - table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 5; - /* Populate CKS Lookup Table */ - if (!(stretch_amount == 1 || stretch_amount == 2 || - stretch_amount == 5 || stretch_amount == 3 || - stretch_amount == 4)) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported\n", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); - - return 0; -} - -static bool vegam_is_hw_avfs_present(struct pp_hwmgr *hwmgr) -{ - uint32_t efuse; - - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (49 * 4)); - efuse &= 0x00000001; - - if (efuse) - return true; - - return false; -} - -static int vegam_populate_avfs_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); - int result = 0; - struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; - AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; - AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; - uint32_t tmp, i; - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - if (!hwmgr->avfs_supported) - return 0; - - result = atomctrl_get_avfs_information(hwmgr, &avfs_params); - - if (0 == result) { - table->BTCGB_VDROOP_TABLE[0].a0 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); - table->BTCGB_VDROOP_TABLE[0].a1 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); - table->BTCGB_VDROOP_TABLE[0].a2 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); - table->BTCGB_VDROOP_TABLE[1].a0 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); - table->BTCGB_VDROOP_TABLE[1].a1 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); - table->BTCGB_VDROOP_TABLE[1].a2 = - PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); - table->AVFSGB_FUSE_TABLE[0].m1 = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); - table->AVFSGB_FUSE_TABLE[0].m2 = - PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); - table->AVFSGB_FUSE_TABLE[0].b = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); - table->AVFSGB_FUSE_TABLE[0].m1_shift = 24; - table->AVFSGB_FUSE_TABLE[0].m2_shift = 12; - table->AVFSGB_FUSE_TABLE[1].m1 = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); - table->AVFSGB_FUSE_TABLE[1].m2 = - PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); - table->AVFSGB_FUSE_TABLE[1].b = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); - table->AVFSGB_FUSE_TABLE[1].m1_shift = 24; - table->AVFSGB_FUSE_TABLE[1].m2_shift = 12; - table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); - AVFS_meanNsigma.Aconstant[0] = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); - AVFS_meanNsigma.Aconstant[1] = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); - AVFS_meanNsigma.Aconstant[2] = - PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); - AVFS_meanNsigma.DC_tol_sigma = - PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); - AVFS_meanNsigma.Platform_mean = - PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); - AVFS_meanNsigma.PSM_Age_CompFactor = - PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); - AVFS_meanNsigma.Platform_sigma = - PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); - - for (i = 0; i < sclk_table->count; i++) { - AVFS_meanNsigma.Static_Voltage_Offset[i] = - (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); - AVFS_SclkOffset.Sclk_Offset[i] = - PP_HOST_TO_SMC_US((uint16_t) - (sclk_table->entries[i].sclk_offset) / 100); - } - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, AvfsMeanNSigma), - &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_meanNsigma, - sizeof(AVFS_meanNsigma_t), - SMC_RAM_END); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, AvfsSclkOffsetTable), - &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_SclkOffset, - sizeof(AVFS_Sclk_Offset_t), - SMC_RAM_END); - - data->avfs_vdroop_override_setting = - (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); - data->apply_avfs_cks_off_voltage = - (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; - } - return result; -} - -static int vegam_populate_vr_config(struct pp_hwmgr *hwmgr, - struct SMU75_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = - (struct vegam_smumgr *)(hwmgr->smu_backend); - uint16_t config; - - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - PP_ASSERT_WITH_CODE(false, - "VDDC should be on SVI2 control in merged mode!", - ); - } - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - if (config != VR_SVI2_PLANE_2) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - smu_data->smu7_data.soft_regs_start + - offsetof(SMU75_SoftRegisters, AllowMvddSwitch), - 0x1); - } else { - PP_ASSERT_WITH_CODE(false, - "SVI2 Plane 2 is already taken, set MVDD as Static",); - config = VR_STATIC_VOLTAGE; - table->VRConfig = (config << VRCONF_MVDD_SHIFT); - } - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig = (config << VRCONF_MVDD_SHIFT); - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - smu_data->smu7_data.soft_regs_start + - offsetof(SMU75_SoftRegisters, AllowMvddSwitch), - 0x1); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } - - return 0; -} - -static int vegam_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; - smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int vegam_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->TDC_VDDC_ThrottleReleaseLimitPerc; - smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; - - return 0; -} - -static int vegam_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - const struct vegam_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU75_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else { - smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; - smu_data->power_tune_table.LPMLTemperatureMin = - (uint8_t)((temp >> 16) & 0xff); - smu_data->power_tune_table.LPMLTemperatureMax = - (uint8_t)((temp >> 8) & 0xff); - smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); - } - return 0; -} - -static int vegam_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int vegam_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - -/* TO DO move to hwmgr */ - if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) - || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int vegam_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int vegam_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); - - return 0; -} - -static int vegam_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU75_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - if (vegam_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - - if (vegam_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - - if (vegam_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - if (0 != vegam_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - if (vegam_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan Control parameters Failed!", - return -EINVAL); - - if (vegam_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - if (vegam_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo " - "Sidd Failed!", return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - (sizeof(struct SMU75_Discrete_PmFuses) - PMFUSES_AVFSSIZE), - SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -static int vegam_enable_reconfig_cus(struct pp_hwmgr *hwmgr) -{ - struct amdgpu_device *adev = hwmgr->adev; - - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_EnableModeSwitchRLCNotification, - adev->gfx.cu_info.number, - NULL); - - return 0; -} - -static int vegam_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = (struct vegam_smumgr *)(hwmgr->smu_backend); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct SMU75_Discrete_DpmTable *table = &(smu_data->smc_state_table); - uint8_t i; - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - struct phm_ppt_v1_gpio_table *gpio_table = - (struct phm_ppt_v1_gpio_table *)table_info->gpio_table; - pp_atomctrl_clock_dividers_vi dividers; - - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - - vegam_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) - vegam_populate_smc_voltage_tables(hwmgr, table); - - table->SystemFlags = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (hw_data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = vegam_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ULV state!", return result); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); - } - - result = vegam_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Link Level!", return result); - - result = vegam_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Graphics Level!", return result); - - result = vegam_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Memory Level!", return result); - - result = vegam_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ACPI Level!", return result); - - result = vegam_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize VCE Level!", return result); - - /* Since only the initial state is completely set up at this point - * (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = vegam_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to Write ARB settings for the initial state.", return result); - - result = vegam_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize UVD Level!", return result); - - result = vegam_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Boot Level!", return result); - - result = vegam_populate_smc_initial_state(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Boot State!", return result); - - result = vegam_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate BAPM Parameters!", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = vegam_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate Clock Stretcher Data Table!", - return result); - } - - result = vegam_populate_avfs_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate AVFS Parameters!", return result;); - - table->CurrSclkPllRange = 0xff; - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - - PP_ASSERT_WITH_CODE(hw_data->dpm_table.pcie_speed_table.count >= 1, - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - table->PCIeBootLinkLevel = - hw_data->dpm_table.pcie_speed_table.count; - table->PCIeGenInterval = 1; - table->VRConfig = 0; - - result = vegam_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate VRConfig setting!", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, - VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - if (gpio_table) - table->VRHotLevel = - table_info->gpio_table->vrhot_triggered_sclk_dpm_index; - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, - PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin)) { - table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition) && - !smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UseNewGPIOScheme, NULL)) - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SMCtoPPLIBAcdcGpioScheme); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - /* Thermal Output GPIO */ - if (atomctrl_get_pp_assign_pin(hwmgr, - THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin)) { - table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; - - /* For porlarity read GPIOPAD_A with assigned Gpio pin - * since VBIOS will program this register to set 'inactive state', - * driver can then determine 'active state' from this and - * program SMU with correct polarity - */ - table->ThermOutPolarity = - (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & - (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CombinePCCWithThermalSignal)) - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } else { - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - /* Populate BIF_SCLK levels into SMC DPM table */ - for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - smu_data->bif_sclk_table[i], ÷rs); - PP_ASSERT_WITH_CODE(!result, - "Can not find DFS divide id for Sclk", - return result); - - if (i == 0) - table->Ulv.BifSclkDfs = - PP_HOST_TO_SMC_US((uint16_t)(dividers.pll_post_divider)); - else - table->LinkLevel[i - 1].BifSclkDfs = - PP_HOST_TO_SMC_US((uint16_t)(dividers.pll_post_divider)); - } - - for (i = 0; i < SMU75_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU75_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU75_Discrete_DpmTable) - 3 * sizeof(SMU75_PIDController), - SMC_RAM_END); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload dpm data to SMC memory!", return result); - - result = vegam_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate PM fuses to SMC memory!", return result); - - result = vegam_enable_reconfig_cus(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to enable reconfigurable CUs!", return result); - - return 0; -} - -static uint32_t vegam_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU75_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU75_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU75_SoftRegisters, AverageGraphicsActivity); - case AverageMemoryActivity: - return offsetof(SMU75_SoftRegisters, AverageMemoryActivity); - case PreVBlankGap: - return offsetof(SMU75_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU75_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU75_SoftRegisters, UcodeLoadStatus); - case DRAM_LOG_ADDR_H: - return offsetof(SMU75_SoftRegisters, DRAM_LOG_ADDR_H); - case DRAM_LOG_ADDR_L: - return offsetof(SMU75_SoftRegisters, DRAM_LOG_ADDR_L); - case DRAM_LOG_PHY_ADDR_H: - return offsetof(SMU75_SoftRegisters, DRAM_LOG_PHY_ADDR_H); - case DRAM_LOG_PHY_ADDR_L: - return offsetof(SMU75_SoftRegisters, DRAM_LOG_PHY_ADDR_L); - case DRAM_LOG_BUFF_SIZE: - return offsetof(SMU75_SoftRegisters, DRAM_LOG_BUFF_SIZE); - } - break; - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU75_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU75_Discrete_DpmTable, VceBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU75_Discrete_DpmTable, LowSclkInterruptThreshold); - } - break; - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -static int vegam_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + - DPMTABLE_UPDATE_SCLK + - DPMTABLE_UPDATE_MCLK)) - return vegam_program_memory_timing_parameters(hwmgr); - - return 0; -} - -static int vegam_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct vegam_smumgr *smu_data = - (struct vegam_smumgr *)(hwmgr->smu_backend); - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (data->low_sclk_interrupt_threshold != 0)) { - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU75_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - PP_ASSERT_WITH_CODE((result == 0), - "Failed to update SCLK threshold!", return result); - - result = vegam_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -int vegam_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int ret; - - if (!hwmgr->avfs_supported) - return 0; - - ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs, NULL); - if (!ret) { - if (data->apply_avfs_cks_off_voltage) - ret = smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_ApplyAvfsCksOffVoltage, - NULL); - } - - return ret; -} - -static int vegam_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - PP_ASSERT_WITH_CODE(hwmgr->thermal_controller.fanInfo.bNoFan, - "VBIOS fan info is not correct!", - ); - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; -} - -const struct pp_smumgr_func vegam_smu_funcs = { - .name = "vegam_smu", - .smu_init = vegam_smu_init, - .smu_fini = smu7_smu_fini, - .start_smu = vegam_start_smu, - .check_fw_load_finish = smu7_check_fw_load_finish, - .request_smu_load_fw = smu7_reload_firmware, - .request_smu_load_specific_fw = NULL, - .send_msg_to_smc = smu7_send_msg_to_smc, - .send_msg_to_smc_with_parameter = smu7_send_msg_to_smc_with_parameter, - .get_argument = smu7_get_argument, - .process_firmware_header = vegam_process_firmware_header, - .is_dpm_running = vegam_is_dpm_running, - .get_mac_definition = vegam_get_mac_definition, - .update_smc_table = vegam_update_smc_table, - .init_smc_table = vegam_init_smc_table, - .get_offsetof = vegam_get_offsetof, - .populate_all_graphic_levels = vegam_populate_all_graphic_levels, - .populate_all_memory_levels = vegam_populate_all_memory_levels, - .update_sclk_threshold = vegam_update_sclk_threshold, - .is_hw_avfs_present = vegam_is_hw_avfs_present, - .thermal_avfs_enable = vegam_thermal_avfs_enable, - .thermal_setup_fan_table = vegam_thermal_setup_fan_table, -}; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h deleted file mode 100644 index 2b6558238500..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _VEGAM_SMUMANAGER_H -#define _VEGAM_SMUMANAGER_H - - -#include -#include "smu75_discrete.h" -#include "smu7_smumgr.h" - -#define SMC_RAM_END 0x40000 - -#define DPMTuning_Uphyst_Shift 0 -#define DPMTuning_Downhyst_Shift 8 -#define DPMTuning_Activity_Shift 16 - -#define GraphicsDPMTuning_VEGAM 0x001e6400 -#define MemoryDPMTuning_VEGAM 0x000f3c0a -#define SclkDPMTuning_VEGAM 0x002d000a -#define MclkDPMTuning_VEGAM 0x001f100a - - -struct vegam_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; - - uint32_t DisplayCac; - uint32_t BAPM_TEMP_GRADIENT; - uint16_t BAPMTI_R[SMU75_DTE_ITERATIONS * SMU75_DTE_SOURCES * SMU75_DTE_SINKS]; - uint16_t BAPMTI_RC[SMU75_DTE_ITERATIONS * SMU75_DTE_SOURCES * SMU75_DTE_SINKS]; -}; - -struct vegam_range_table { - uint32_t trans_lower_frequency; /* in 10khz */ - uint32_t trans_upper_frequency; -}; - -struct vegam_smumgr { - struct smu7_smumgr smu7_data; - uint8_t protected_mode; - SMU75_Discrete_DpmTable smc_state_table; - struct SMU75_Discrete_Ulv ulv_setting; - struct SMU75_Discrete_PmFuses power_tune_table; - struct vegam_range_table range_table[NUM_SCLK_RANGE]; - const struct vegam_pt_defaults *power_tune_defaults; - uint32_t bif_sclk_table[SMU75_MAX_LEVELS_LINK]; -}; - - -#endif -- cgit v1.2.3 From ac1128c99620ba8057fa82f2ca1264d0d54544d6 Mon Sep 17 00:00:00 2001 From: James Zhu Date: Thu, 13 Aug 2020 09:57:31 -0400 Subject: drm/amdgpu/vcn3.0: only SIENNA_CICHLID need specify instance for dec/enc Only SIENNA_CICHLID(VCN3) has 2 unsymmetrical instances, there're less codecs on instance 1, we use 0 for decode and 1 for encode. Signed-off-by: James Zhu Reviewed-by: Leo Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 63e5547cfb16..589d6cd8adec 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -198,7 +198,7 @@ static int vcn_v3_0_sw_init(void *handle) } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 8 * i; } - if (i != 0) + if (adev->asic_type == CHIP_SIENNA_CICHLID && i != 0) ring->no_scheduler = true; sprintf(ring->name, "vcn_dec_%d", i); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, @@ -222,7 +222,7 @@ static int vcn_v3_0_sw_init(void *handle) } else { ring->doorbell_index = (adev->doorbell_index.vcn.vcn_ring0_1 << 1) + 2 + j + 8 * i; } - if (i != 1) + if (adev->asic_type == CHIP_SIENNA_CICHLID && i != 1) ring->no_scheduler = true; sprintf(ring->name, "vcn_enc_%d.%d", i, j); r = amdgpu_ring_init(adev, ring, 512, &adev->vcn.inst[i].irq, 0, -- cgit v1.2.3 From 31e726ca3da9b126f162b51bb55647b1ffccbd48 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 28 Jul 2020 11:35:54 -0400 Subject: drm/amdgpu: parse ta firmware for navy_flounder Use the same case as sienna_cichlid Signed-off-by: Bhawanpreet Lakha Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index d488d250805d..e16874f30d5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -179,12 +179,11 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) } break; case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: err = psp_init_ta_microcode(&adev->psp, chip_name); if (err) return err; break; - case CHIP_NAVY_FLOUNDER: - break; default: BUG(); } -- cgit v1.2.3 From bddbacc9e0373fc1f1f7963fa2a7838dd06e4b1b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 10 Aug 2020 17:09:17 -0400 Subject: drm/amdgpu: print where we get the vbios image from ACPI, ROM, PCI BAR, etc. Acked-by: Nirmoy Das Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index b1172d93c99c..6333cada1e09 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -417,26 +417,40 @@ static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) bool amdgpu_get_bios(struct amdgpu_device *adev) { - if (amdgpu_atrm_get_bios(adev)) + if (amdgpu_atrm_get_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ATRM\n"); goto success; + } - if (amdgpu_acpi_vfct_bios(adev)) + if (amdgpu_acpi_vfct_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from VFCT\n"); goto success; + } - if (igp_read_bios_from_vram(adev)) + if (igp_read_bios_from_vram(adev)) { + dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n"); goto success; + } - if (amdgpu_read_bios(adev)) + if (amdgpu_read_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); goto success; + } - if (amdgpu_read_bios_from_rom(adev)) + if (amdgpu_read_bios_from_rom(adev)) { + dev_info(adev->dev, "Fetched VBIOS from ROM\n"); goto success; + } - if (amdgpu_read_disabled_bios(adev)) + if (amdgpu_read_disabled_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n"); goto success; + } - if (amdgpu_read_platform_bios(adev)) + if (amdgpu_read_platform_bios(adev)) { + dev_info(adev->dev, "Fetched VBIOS from platform\n"); goto success; + } DRM_ERROR("Unable to locate a BIOS ROM\n"); return false; -- cgit v1.2.3 From 11043b7a995c18ea725c956825d1dfcbbdd8e78b Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 11 Aug 2020 12:02:21 -0400 Subject: drm/amdgpu: note what type of reset we are using When we reset the GPU, note what type of reset will be used. This makes debugging different reset scenarios more clear as the driver may use different reset methods depending on conditions on the system. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 2 ++ drivers/gpu/drm/amd/amdgpu/nv.c | 6 ++++-- drivers/gpu/drm/amd/amdgpu/si.c | 2 ++ drivers/gpu/drm/amd/amdgpu/soc15.c | 3 +++ drivers/gpu/drm/amd/amdgpu/vi.c | 2 ++ 5 files changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index c2c67ab68a43..7e71ffbca93d 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1366,8 +1366,10 @@ static int cik_asic_reset(struct amdgpu_device *adev) int r; if (cik_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); } else { + dev_info(adev->dev, "PCI CONFIG reset\n"); r = cik_asic_pci_config_reset(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index da8024c2826e..54e941e0db60 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -379,7 +379,7 @@ static int nv_asic_reset(struct amdgpu_device *adev) struct smu_context *smu = &adev->smu; if (nv_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { - dev_info(adev->dev, "GPU BACO reset\n"); + dev_info(adev->dev, "BACO reset\n"); ret = smu_baco_enter(smu); if (ret) @@ -387,8 +387,10 @@ static int nv_asic_reset(struct amdgpu_device *adev) ret = smu_baco_exit(smu); if (ret) return ret; - } else + } else { + dev_info(adev->dev, "MODE1 reset\n"); ret = nv_asic_mode1_reset(adev); + } return ret; } diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index e330884edd19..eaa2f071b139 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1302,6 +1302,8 @@ static int si_asic_reset(struct amdgpu_device *adev) { int r; + dev_info(adev->dev, "PCI CONFIG reset\n"); + amdgpu_atombios_scratch_regs_engine_hung(adev, true); r = si_gpu_pci_config_reset(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 84d811b6e48b..3cd98c144bc6 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -580,10 +580,13 @@ static int soc15_asic_reset(struct amdgpu_device *adev) switch (soc15_asic_reset_method(adev)) { case AMD_RESET_METHOD_BACO: + dev_info(adev->dev, "BACO reset\n"); return soc15_asic_baco_reset(adev); case AMD_RESET_METHOD_MODE2: + dev_info(adev->dev, "MODE2 reset\n"); return amdgpu_dpm_mode2_reset(adev); default: + dev_info(adev->dev, "MODE1 reset\n"); return soc15_asic_mode1_reset(adev); } } diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index b4e4a7a19d19..a92880c67841 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -752,8 +752,10 @@ static int vi_asic_reset(struct amdgpu_device *adev) int r; if (vi_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { + dev_info(adev->dev, "BACO reset\n"); r = amdgpu_dpm_baco_reset(adev); } else { + dev_info(adev->dev, "PCI CONFIG reset\n"); r = vi_asic_pci_config_reset(adev); } -- cgit v1.2.3 From 2a25ba97879f809e79642fca05178d4ee77f9f52 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 13 Aug 2020 00:23:22 -0400 Subject: drm/amdgpu: drop log message in amdgpu_dpm_baco_reset() The caller does this now for all reset types. This is now a duplicate call. Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index e480b54f6545..ca3fb32979d4 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -1115,8 +1115,6 @@ int amdgpu_dpm_baco_reset(struct amdgpu_device *adev) struct smu_context *smu = &adev->smu; int ret = 0; - dev_info(adev->dev, "GPU BACO reset\n"); - if (is_support_sw_smu(adev)) { ret = smu_baco_enter(smu); if (ret) -- cgit v1.2.3 From 88fee1c9007a38c19f2c558dc0ab1ddb4c323dc5 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 14 Aug 2020 13:01:40 -0400 Subject: drm/dp_mst: Don't return error code when crtc is null [Why] In certain cases the crtc can be NULL and returning -EINVAL causes atomic check to fail when it shouln't. This leads to valid configurations failing because atomic check fails. [How] Don't early return if crtc is null Signed-off-by: Bhawanpreet Lakha Reviewed-by: Lyude Paul [added stable cc] Signed-off-by: Lyude Paul Fixes: 8ec046716ca8 ("drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs") Cc: # v5.6+ Link: https://patchwork.freedesktop.org/patch/msgid/20200814170140.24917-1-Bhawanpreet.Lakha@amd.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 1e26b89628f9..0a2f0b5c7a44 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4990,8 +4990,8 @@ int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm crtc = conn_state->crtc; - if (WARN_ON(!crtc)) - return -EINVAL; + if (!crtc) + continue; if (!drm_dp_mst_dsc_aux_for_port(pos->port)) continue; -- cgit v1.2.3 From 77ef38574beb3e0b414db48e9c0f04633df68ba6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 14 Aug 2020 11:38:42 +0200 Subject: drm/modeset-lock: Take the modeset BKL for legacy drivers This fell off in the conversion in commit 9bcaa3fe58ab7559e71df798bcff6e0795158695 Author: Michal Orzel Date: Tue Apr 28 19:10:04 2020 +0200 drm: Replace drm_modeset_lock/unlock_all with DRM_MODESET_LOCK_ALL_* helpers but it's caught by the drm_warn_on_modeset_not_all_locked() that the legacy modeset code uses. Since this is the bkl and it's unclear what's all protected, play it safe and grab it again for legacy drivers. Unfortunately this means we need to sprinkle a few more #includes around. Also we need to add the drm_device as a parameter to the _END macro. Finally remove the mute_lock() from setcrtc, since that's now done by the macro. Cc: Alex Deucher References: https://gitlab.freedesktop.org/drm/amd/-/issues/1224 Fixes: 9bcaa3fe58ab ("drm: Replace drm_modeset_lock/unlock_all with DRM_MODESET_LOCK_ALL_* helpers") Cc: Michal Orzel Cc: Daniel Vetter Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: # v5.8+ Signed-off-by: Daniel Vetter Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20200814093842.3048472-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/drm_atomic_helper.c | 7 ++++--- drivers/gpu/drm/drm_color_mgmt.c | 2 +- drivers/gpu/drm/drm_crtc.c | 4 +--- drivers/gpu/drm/drm_mode_object.c | 4 ++-- drivers/gpu/drm/drm_plane.c | 2 +- include/drm/drm_modeset_lock.h | 9 +++++++-- 6 files changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 85d163f16801..b78e142a5620 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -3105,7 +3106,7 @@ void drm_atomic_helper_shutdown(struct drm_device *dev) if (ret) DRM_ERROR("Disabling all crtc's during unload failed with %i\n", ret); - DRM_MODESET_LOCK_ALL_END(ctx, ret); + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); } EXPORT_SYMBOL(drm_atomic_helper_shutdown); @@ -3245,7 +3246,7 @@ struct drm_atomic_state *drm_atomic_helper_suspend(struct drm_device *dev) } unlock: - DRM_MODESET_LOCK_ALL_END(ctx, err); + DRM_MODESET_LOCK_ALL_END(dev, ctx, err); if (err) return ERR_PTR(err); @@ -3326,7 +3327,7 @@ int drm_atomic_helper_resume(struct drm_device *dev, err = drm_atomic_helper_commit_duplicated_state(state, &ctx); - DRM_MODESET_LOCK_ALL_END(ctx, err); + DRM_MODESET_LOCK_ALL_END(dev, ctx, err); drm_atomic_state_put(state); return err; diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index c93123ff7c21..138ff34b31db 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -294,7 +294,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, crtc->gamma_size, &ctx); out: - DRM_MODESET_LOCK_ALL_END(ctx, ret); + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); return ret; } diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4936e1080e41..eb1c33e5d0f4 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -561,7 +561,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, if (crtc_req->mode_valid && !drm_lease_held(file_priv, plane->base.id)) return -EACCES; - mutex_lock(&crtc->dev->mode_config.mutex); DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE, ret); @@ -728,8 +727,7 @@ out: fb = NULL; mode = NULL; - DRM_MODESET_LOCK_ALL_END(ctx, ret); - mutex_unlock(&crtc->dev->mode_config.mutex); + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); return ret; } diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 901b078abf40..db05f386a709 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -428,7 +428,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, out_unref: drm_mode_object_put(obj); out: - DRM_MODESET_LOCK_ALL_END(ctx, ret); + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); return ret; } @@ -470,7 +470,7 @@ static int set_property_legacy(struct drm_mode_object *obj, break; } drm_property_change_valid_put(prop, ref); - DRM_MODESET_LOCK_ALL_END(ctx, ret); + DRM_MODESET_LOCK_ALL_END(dev, ctx, ret); return ret; } diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 4af173ced327..fdbafc2b8199 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -791,7 +791,7 @@ static int setplane_internal(struct drm_plane *plane, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, &ctx); - DRM_MODESET_LOCK_ALL_END(ctx, ret); + DRM_MODESET_LOCK_ALL_END(plane->dev, ctx, ret); return ret; } diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h index 4fc9a43ac45a..aafd07388eb7 100644 --- a/include/drm/drm_modeset_lock.h +++ b/include/drm/drm_modeset_lock.h @@ -164,6 +164,8 @@ int drm_modeset_lock_all_ctx(struct drm_device *dev, * is 0, so no error checking is necessary */ #define DRM_MODESET_LOCK_ALL_BEGIN(dev, ctx, flags, ret) \ + if (!drm_drv_uses_atomic_modeset(dev)) \ + mutex_lock(&dev->mode_config.mutex); \ drm_modeset_acquire_init(&ctx, flags); \ modeset_lock_retry: \ ret = drm_modeset_lock_all_ctx(dev, &ctx); \ @@ -172,6 +174,7 @@ modeset_lock_retry: \ /** * DRM_MODESET_LOCK_ALL_END - Helper to release and cleanup modeset locks + * @dev: drm device * @ctx: local modeset acquire context, will be dereferenced * @ret: local ret/err/etc variable to track error status * @@ -188,7 +191,7 @@ modeset_lock_retry: \ * to that failure. In both of these cases the code between BEGIN/END will not * be run, so the failure will reflect the inability to grab the locks. */ -#define DRM_MODESET_LOCK_ALL_END(ctx, ret) \ +#define DRM_MODESET_LOCK_ALL_END(dev, ctx, ret) \ modeset_lock_fail: \ if (ret == -EDEADLK) { \ ret = drm_modeset_backoff(&ctx); \ @@ -196,6 +199,8 @@ modeset_lock_fail: \ goto modeset_lock_retry; \ } \ drm_modeset_drop_locks(&ctx); \ - drm_modeset_acquire_fini(&ctx); + drm_modeset_acquire_fini(&ctx); \ + if (!drm_drv_uses_atomic_modeset(dev)) \ + mutex_unlock(&dev->mode_config.mutex); #endif /* DRM_MODESET_LOCK_H_ */ -- cgit v1.2.3 From d95c42a150d01e28830e0f597bc126a20db8fd0b Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 11 Aug 2020 13:54:56 +0800 Subject: drm/amdkfd: fix the wrong sdma instance query for renoir Renoir only has one sdma instance, it will get failed once query the sdma1 registers. So use switch-case instead of static register array. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') 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 e4c274bd35c8..a755f63514e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -195,19 +195,32 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, unsigned int engine_id, unsigned int queue_id) { - uint32_t sdma_engine_reg_base[2] = { - SOC15_REG_OFFSET(SDMA0, 0, - mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL, - SOC15_REG_OFFSET(SDMA1, 0, - mmSDMA1_RLC0_RB_CNTL) - mmSDMA1_RLC0_RB_CNTL - }; - uint32_t retval = sdma_engine_reg_base[engine_id] + uint32_t sdma_engine_reg_base = 0; + uint32_t sdma_rlc_reg_offset; + + switch (engine_id) { + default: + dev_warn(adev->dev, + "Invalid sdma engine id (%d), using engine id 0\n", + engine_id); + fallthrough; + case 0: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0, + mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + case 1: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA1, 0, + mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + } + + sdma_rlc_reg_offset = sdma_engine_reg_base + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL); pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id, - queue_id, retval); + queue_id, sdma_rlc_reg_offset); - return retval; + return sdma_rlc_reg_offset; } static inline struct v9_mqd *get_mqd(void *mqd) -- cgit v1.2.3 From 736b17297857cf533649a4161d1369e3cde0d922 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 17 Aug 2020 14:55:11 +0800 Subject: drm/amdgpu: fix amdgpu_bo_release_notify() comment error fix amdgpu_bo_release_notify() comment error. Signed-off-by: Kevin Wang Reviewed-by: Christian König Reviewed-by: Dennis Li Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index a3cf38d25fc1..3080b5644121 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -1302,7 +1302,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, } /** - * amdgpu_bo_move_notify - notification about a BO being released + * amdgpu_bo_release_notify - notification about a BO being released * @bo: pointer to a buffer object * * Wipes VRAM buffers whose contents should not be leaked before the -- cgit v1.2.3 From 4444457450fa66860fca856c6dd20f7acde80efa Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 17 Aug 2020 16:57:20 +0800 Subject: drm/amdgpu: add condition check for trace_amdgpu_cs() v1: add trace event enabled check to avoid nop loop when submit multi ibs in amdgpu_cs_ioctl() function. v2: add a new wrapper function to trace all amdgpu cs ibs. Signed-off-by: Kevin Wang Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index a512ccbc4dea..10c0779aba73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1275,13 +1275,24 @@ error_unlock: return r; } +static void trace_amdgpu_cs_ibs(struct amdgpu_cs_parser *parser) +{ + int i; + + if (!trace_amdgpu_cs_enabled()) + return; + + for (i = 0; i < parser->job->num_ibs; i++) + trace_amdgpu_cs(parser, i); +} + int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser parser = {}; bool reserved_buffers = false; - int i, r; + int r; if (amdgpu_ras_intr_triggered()) return -EHWPOISON; @@ -1319,8 +1330,7 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) reserved_buffers = true; - for (i = 0; i < parser.job->num_ibs; i++) - trace_amdgpu_cs(&parser, i); + trace_amdgpu_cs_ibs(&parser); r = amdgpu_cs_vm_handling(&parser); if (r) -- cgit v1.2.3 From 45083ed24b8df3b43ce17c5598b6304a044659e6 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 3 Aug 2020 16:11:44 -0400 Subject: drm/amd/display: [FW Promotion] Release 0.0.28 Signed-off-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 55717ae4724d..b58ed6538eab 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0xd7f4bb6ee +#define DMUB_FW_VERSION_GIT_HASH 0x3f7e3738b #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 27 +#define DMUB_FW_VERSION_REVISION 28 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 -- cgit v1.2.3 From 1ffe92021e6cd27ee9ccc30012a57d8a4868e28f Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Mon, 3 Aug 2020 16:12:58 -0400 Subject: drm/amd/display: 3.2.98 Signed-off-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 6d4cab948607..772b3a647700 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.97" +#define DC_VER "3.2.98" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From 8a0e210c048e97f950c674840e281e378de08373 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Wed, 5 Aug 2020 13:46:40 -0400 Subject: drm/amd/display: Call DMUB for eDP power control [Why] If DMUB is used, LVTMA VBIOS call can be used to control eDP instead of tranditional transmitter control. Interface is agreed with VBIOS for eDP to use this new path to program LVTMA registers. [How] Create DAL interface to send DMUB command for LVTMA as currently implemented in VBIOS. Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 16 ++++++++++++- .../gpu/drm/amd/display/dc/bios/command_table2.c | 28 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/bios/command_table2.h | 3 ++- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 4 ++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 24 +++++++++++++++++++ .../drm/amd/display/include/bios_parser_types.h | 7 ++++++ 6 files changed, 80 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 078b7e344185..2d5c7daaee23 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1108,6 +1108,18 @@ static enum bp_result bios_parser_enable_disp_power_gating( action); } +static enum bp_result bios_parser_enable_lvtma_control( + struct dc_bios *dcb, + uint8_t uc_pwr_on) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_lvtma_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on); +} + static bool bios_parser_is_accelerated_mode( struct dc_bios *dcb) { @@ -2208,7 +2220,9 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_board_layout_info = bios_get_board_layout_info, .pack_data_tables = bios_parser_pack_data_tables, - .get_atom_dc_golden_table = bios_get_atom_dc_golden_table + .get_atom_dc_golden_table = bios_get_atom_dc_golden_table, + + .enable_lvtma_control = bios_parser_enable_lvtma_control }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index e8f52eb8ef0d..a91d7be5d86e 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -901,6 +901,33 @@ static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id) return 0; } +/****************************************************************************** + ****************************************************************************** + ** + ** LVTMA CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on); + +static void init_enable_lvtma_control(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control; + +} + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on) +{ + enum bp_result result = BP_RESULT_FAILURE; + return result; +} + void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) { init_dig_encoder_control(bp); @@ -916,4 +943,5 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_set_dce_clock(bp); init_get_smu_clock_info(bp); + init_enable_lvtma_control(bp); } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h index 7a2af24dfe60..7bdce013cde5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -94,7 +94,8 @@ struct cmd_tbl { struct bp_set_dce_clock_parameters *bp_params); unsigned int (*get_smu_clock_info)( struct bios_parser *bp, uint8_t id); - + enum bp_result (*enable_lvtma_control)(struct bios_parser *bp, + uint8_t uc_pwr_on); }; void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index d06d07042a12..0811f941f430 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -136,6 +136,10 @@ struct dc_vbios_funcs { enum bp_result (*get_atom_dc_golden_table)( struct dc_bios *dcb); + + enum bp_result (*enable_lvtma_control)( + struct dc_bios *bios, + uint8_t uc_pwr_on); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 49380ed3aeae..45c9e9027886 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -842,6 +842,17 @@ void dce110_edp_power_control( cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; cntl.hpd_sel = link->link_enc->hpd_source; + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_POWER_ON) + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_ON); + else + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_OFF); + } + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); if (!power_up) @@ -919,8 +930,21 @@ void dce110_edp_backlight_control( /*edp 1.2*/ if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) edp_receiver_ready_T7(link); + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLON); + else + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLOFF); + } + link_transmitter_control(ctx->dc_bios, &cntl); + + if (enable && link->dpcd_sink_ext_caps.bits.oled) msleep(OLED_POST_T7_DELAY); diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index c30437ae8395..21011edea337 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -101,6 +101,13 @@ enum bp_pipe_control_action { ASIC_PIPE_INIT }; +enum bp_lvtma_control_action { + LVTMA_CONTROL_LCD_BLOFF = 2, + LVTMA_CONTROL_LCD_BLON = 3, + LVTMA_CONTROL_POWER_ON = 12, + LVTMA_CONTROL_POWER_OFF = 13 +}; + struct bp_encoder_control { enum bp_encoder_control_action action; enum engine_id engine_id; -- cgit v1.2.3 From 5a7c86e168b4b3229945f792ba0ea04c5236521f Mon Sep 17 00:00:00 2001 From: Chris Park Date: Wed, 5 Aug 2020 16:59:28 -0400 Subject: drm/amd/display: Assign correct left shift [Why] Reading for DP alt registers return incorrect values due to LE_SF definition missing. [How] Define correct LE_SF or DP alt registers. Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 4 +++- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index bf0044f7417e..dcbf28dd72d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -167,7 +167,9 @@ LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh) + LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) #define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 8e9fd59ccde8..2fbf879cd327 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -61,7 +61,10 @@ DPCS_DCN2_MASK_SH_LIST(mask_sh),\ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh) + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + void dcn30_link_encoder_construct( struct dcn20_link_encoder *enc20, -- cgit v1.2.3 From c08321cb181d5677dedec276f9a11990f27c8d99 Mon Sep 17 00:00:00 2001 From: Wenjing Liu Date: Thu, 9 Jul 2020 17:08:50 -0400 Subject: drm/amd/display: create a function to decide mst link settings [why] create a dedicated function to make mst link settings decision, so that the policy's decision is made in a unified place. Signed-off-by: Wenjing Liu Reviewed-by: Tony Cheng Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') 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 9bc03f26efda..231929932516 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -2431,6 +2431,12 @@ static bool decide_edp_link_settings(struct dc_link *link, struct dc_link_settin return false; } +static bool decide_mst_link_settings(const struct dc_link *link, struct dc_link_settings *link_setting) +{ + *link_setting = link->verified_link_cap; + return true; +} + void decide_link_settings(struct dc_stream_state *stream, struct dc_link_settings *link_setting) { @@ -2456,11 +2462,9 @@ void decide_link_settings(struct dc_stream_state *stream, * TODO: add MST specific link training routine */ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { - *link_setting = link->verified_link_cap; - return; - } - - if (link->connector_signal == SIGNAL_TYPE_EDP) { + if (decide_mst_link_settings(link, link_setting)) + return; + } else if (link->connector_signal == SIGNAL_TYPE_EDP) { if (decide_edp_link_settings(link, link_setting, req_bw)) return; } else if (decide_dp_link_settings(link, link_setting, req_bw)) -- cgit v1.2.3 From ecfe7569a512852eb35fe0edf73089e6451152e4 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Fri, 31 Jul 2020 13:57:05 -0400 Subject: drm/amd/display: Change ABM config init interface [Why & How] change abm config init interface to support multiple ABMs. Signed-off-by: Yongqiang Sun Reviewed-by: Chris Park Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- .../gpu/drm/amd/display/modules/power/power_helpers.c | 19 +++++++++++++++---- .../gpu/drm/amd/display/modules/power/power_helpers.h | 4 +++- 3 files changed, 19 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 653b4a0d51d8..a9b34462f5e1 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1415,7 +1415,7 @@ static int dm_late_init(void *handle) if (dmcu) ret = dmcu_load_iram(dmcu, params); else if (adev->dm.dc->ctx->dmub_srv) - ret = dmub_init_abm_config(adev->dm.dc->res_pool->abm, params); + ret = dmub_init_abm_config(adev->dm.dc->res_pool, params); if (!ret) return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c index 859724771a75..61497954e67e 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c @@ -657,7 +657,7 @@ void fill_iram_v_2_3(struct iram_table_v_2_2 *ram_table, struct dmcu_iram_parame params, ram_table, big_endian); } -bool dmub_init_abm_config(struct abm *abm, +bool dmub_init_abm_config(struct resource_pool *res_pool, struct dmcu_iram_parameters params) { struct iram_table_v_2_2 ram_table; @@ -665,8 +665,13 @@ bool dmub_init_abm_config(struct abm *abm, bool result = false; uint32_t i, j = 0; - if (abm == NULL) +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (res_pool->abm == NULL && res_pool->multiple_abms[0] == NULL) return false; +#else + if (res_pool->abm == NULL) + return false; +#endif memset(&ram_table, 0, sizeof(ram_table)); memset(&config, 0, sizeof(config)); @@ -707,8 +712,14 @@ bool dmub_init_abm_config(struct abm *abm, config.min_abm_backlight = ram_table.min_abm_backlight; - result = abm->funcs->init_abm_config( - abm, (char *)(&config), sizeof(struct abm_config_table)); +#if defined(CONFIG_DRM_AMD_DC_DCN3_0) + if (res_pool->multiple_abms[0]) { + result = res_pool->multiple_abms[0]->funcs->init_abm_config( + res_pool->multiple_abms[0], (char *)(&config), sizeof(struct abm_config_table)); + } else +#endif + result = res_pool->abm->funcs->init_abm_config( + res_pool->abm, (char *)(&config), sizeof(struct abm_config_table)); return result; } diff --git a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h index 46fbca2e2cd1..fa4728d88092 100644 --- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.h +++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.h @@ -28,6 +28,8 @@ #include "dc/inc/hw/dmcu.h" #include "dc/inc/hw/abm.h" +struct resource_pool; + enum abm_defines { abm_defines_max_level = 4, @@ -45,7 +47,7 @@ struct dmcu_iram_parameters { bool dmcu_load_iram(struct dmcu *dmcu, struct dmcu_iram_parameters params); -bool dmub_init_abm_config(struct abm *abm, +bool dmub_init_abm_config(struct resource_pool *res_pool, struct dmcu_iram_parameters params); #endif /* MODULES_POWER_POWER_HELPERS_H_ */ -- cgit v1.2.3 From 9804ecbba8f73916101ac36929bc647c3cb17155 Mon Sep 17 00:00:00 2001 From: Paul Hsieh Date: Wed, 5 Aug 2020 17:28:37 +0800 Subject: drm/amd/display: Fix DFPstate hang due to view port changed [Why] Place the cursor in the center of screen between two pipes then adjusting the viewport but cursour doesn't update cause DFPstate hang. [How] If viewport changed, update cursor as well. Cc: stable@vger.kernel.org Signed-off-by: Paul Hsieh Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1..c8cfd3ba1c15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1457,8 +1457,8 @@ static void dcn20_update_dchubp_dpp( /* Any updates are handled in dc interface, just need to apply existing for plane enable */ if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || - pipe_ctx->update_flags.bits.scaler || pipe_ctx->update_flags.bits.viewport) - && pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { + pipe_ctx->update_flags.bits.scaler || viewport_changed == true) && + pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { dc->hwss.set_cursor_position(pipe_ctx); dc->hwss.set_cursor_attribute(pipe_ctx); -- cgit v1.2.3 From 6ee90e88b976743835d4f34f3234d775c733ef12 Mon Sep 17 00:00:00 2001 From: hersen wu Date: Wed, 8 Jul 2020 22:14:41 -0400 Subject: drm/amd/display: PSR eDP p-state warning occurs intermittently after unplug DP [Why] with eDP + DP, each display use one pipe. after DP unplugged, eDP switch from one pipe to two pipes -- pipe split. dpp1_cm_set_regamma_pwl will be executed too. The duration from switch single pipe to dual pipes is a little long which could let eDP enter PSR mode. upon two pipes for eDP are setup, eDP PHY is disabled. front pipe is not really running to fetch data from frame buffer. i.e., dchubp is not in normal working status. execution of hubbub1_wm_change_req_wa may cause p-state warning. [How] disable eDP PSR before dc_commit_state. psr is disabled when execute hubbub1_wm_change_req_wa. Signed-off-by: Hersen Wu Reviewed-by: Roman Li Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 27 ++++++++++++++++++----- drivers/gpu/drm/amd/display/dc/core/dc.c | 24 ++++++++++++++++++++ drivers/gpu/drm/amd/display/dc/dc.h | 3 +++ 3 files changed, 48 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') 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 a9b34462f5e1..0d121a3f2103 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -171,7 +171,7 @@ static void amdgpu_dm_set_psr_caps(struct dc_link *link); static bool amdgpu_dm_psr_enable(struct dc_stream_state *stream); static bool amdgpu_dm_link_setup_psr(struct dc_stream_state *stream); static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream); - +static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm); /* * dm_vblank_get_counter @@ -7445,6 +7445,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) struct drm_connector_state *old_con_state, *new_con_state; struct dm_crtc_state *dm_old_crtc_state, *dm_new_crtc_state; int crtc_disable_count = 0; + bool mode_set_reset_required = false; drm_atomic_helper_update_legacy_modeset_state(dev, state); @@ -7521,19 +7522,21 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) acrtc->enabled = true; acrtc->hw_mode = new_crtc_state->mode; crtc->hwmode = new_crtc_state->mode; + mode_set_reset_required = true; } else if (modereset_required(new_crtc_state)) { DRM_DEBUG_DRIVER("Atomic commit: RESET. crtc id %d:[%p]\n", acrtc->crtc_id, acrtc); /* i.e. reset mode */ - if (dm_old_crtc_state->stream) { - if (dm_old_crtc_state->stream->link->psr_settings.psr_allow_active) - amdgpu_dm_psr_disable(dm_old_crtc_state->stream); - + if (dm_old_crtc_state->stream) remove_stream(adev, acrtc, dm_old_crtc_state->stream); - } + mode_set_reset_required = true; } } /* for_each_crtc_in_state() */ if (dc_state) { + /* if there mode set or reset, disable eDP PSR */ + if (mode_set_reset_required) + amdgpu_dm_psr_disable_all(dm); + dm_enable_per_frame_crtc_master_sync(dc_state); mutex_lock(&dm->dc_lock); WARN_ON(!dc_commit_state(dm->dc, dc_state)); @@ -9054,6 +9057,18 @@ static bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) return dc_link_set_psr_allow_active(stream->link, false, true); } +/* + * amdgpu_dm_psr_disable() - disable psr f/w + * if psr is enabled on any stream + * + * Return: true if success + */ +static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) +{ + DRM_DEBUG_DRIVER("Disabling psr if psr is enabled on any stream\n"); + return dc_set_psr_allow_active(dm->dc, false); +} + void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { struct amdgpu_device *adev = dev->dev_private; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ebbb8182228d..a2084f279e7b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2948,6 +2948,30 @@ void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_ dc->hwss.get_clock(dc, clock_type, clock_cfg); } +/* enable/disable eDP PSR without specify stream for eDP */ +bool dc_set_psr_allow_active(struct dc *dc, bool enable) +{ + int i; + + for (i = 0; i < dc->current_state->stream_count ; i++) { + struct dc_link *link; + struct dc_stream_state *stream = dc->current_state->streams[i]; + + link = stream->link; + if (!link) + continue; + + if (link->psr_settings.psr_feature_enabled) { + if (enable && !link->psr_settings.psr_allow_active) + return dc_link_set_psr_allow_active(link, true, false); + else if (!enable && link->psr_settings.psr_allow_active) + return dc_link_set_psr_allow_active(link, false, false); + } + } + + return true; +} + #if defined(CONFIG_DRM_AMD_DC_DCN3_0) void dc_allow_idle_optimizations(struct dc *dc, bool allow) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 772b3a647700..f3ac9e3df760 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1265,6 +1265,9 @@ void dc_unlock_memory_clock_frequency(struct dc *dc); void dc_lock_memory_clock_frequency(struct dc *dc); #endif + +bool dc_set_psr_allow_active(struct dc *dc, bool enable); + /******************************************************************************* * DSC Interfaces ******************************************************************************/ -- cgit v1.2.3 From ccc875052f829a03d1c9f67fc3a8709fe6c67c31 Mon Sep 17 00:00:00 2001 From: Yongqiang Sun Date: Wed, 5 Aug 2020 11:34:53 -0400 Subject: drm/amd/display: Add read backlight interface [Why & How] Add read backlight interface to get ABM data. Signed-off-by: Yongqiang Sun Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 1 + drivers/gpu/drm/amd/display/dc/dce/dce_abm.h | 12 +++++++++++- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 6 ++++-- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +- drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h | 1 + 5 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 0257a900fe2b..f42a17d765e3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -708,3 +708,4 @@ void dc_stream_log(const struct dc *dc, const struct dc_stream_state *stream) "\tlink: %d\n", stream->link->link_index); } + diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h index a44effcda49f..e84d21605854 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_abm.h @@ -46,6 +46,8 @@ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \ + SR(DC_ABM1_ACE_THRES_12), \ SR(BIOS_SCRATCH_2) #define ABM_DCN10_REG_LIST(id)\ @@ -60,6 +62,8 @@ SRI(BL1_PWM_USER_LEVEL, ABM, id), \ SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI(DC_ABM1_ACE_THRES_12, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) #define ABM_DCN20_REG_LIST() \ @@ -74,10 +78,12 @@ SR(BL1_PWM_USER_LEVEL), \ SR(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES), \ SR(DC_ABM1_HGLS_REG_READ_PROGRESS), \ + SR(DC_ABM1_ACE_OFFSET_SLOPE_0), \ + SR(DC_ABM1_ACE_THRES_12), \ NBIO_SR(BIOS_SCRATCH_2) #if defined(CONFIG_DRM_AMD_DC_DCN3_0) -#define ABM_DCN301_REG_LIST(id)\ +#define ABM_DCN30_REG_LIST(id)\ ABM_COMMON_REG_LIST_DCE_BASE(), \ SRI(DC_ABM1_HG_SAMPLE_RATE, ABM, id), \ SRI(DC_ABM1_LS_SAMPLE_RATE, ABM, id), \ @@ -89,6 +95,8 @@ SRI(BL1_PWM_USER_LEVEL, ABM, id), \ SRI(DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES, ABM, id), \ SRI(DC_ABM1_HGLS_REG_READ_PROGRESS, ABM, id), \ + SRI(DC_ABM1_ACE_OFFSET_SLOPE_0, ABM, id), \ + SRI(DC_ABM1_ACE_THRES_12, ABM, id), \ NBIO_SR(BIOS_SCRATCH_2) #endif @@ -208,6 +216,8 @@ struct dce_abm_registers { uint32_t BL1_PWM_USER_LEVEL; uint32_t DC_ABM1_LS_MIN_MAX_PIXEL_VALUE_THRES; uint32_t DC_ABM1_HGLS_REG_READ_PROGRESS; + uint32_t DC_ABM1_ACE_OFFSET_SLOPE_0; + uint32_t DC_ABM1_ACE_THRES_12; uint32_t MASTER_COMM_CNTL_REG; uint32_t MASTER_COMM_CMD_REG; uint32_t MASTER_COMM_DATA_REG1; diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index 43781e77be43..a6d73d30837c 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -46,13 +46,14 @@ #define FN(reg_name, field_name) \ dce_panel_cntl->shift->field_name, dce_panel_cntl->mask->field_name -static unsigned int calculate_16_bit_backlight_from_pwm(struct dce_panel_cntl *dce_panel_cntl) +static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_cntl) { uint64_t current_backlight; uint32_t round_result; uint32_t pwm_period_cntl, bl_period, bl_int_count; uint32_t bl_pwm_cntl, bl_pwm, fractional_duty_cycle_en; uint32_t bl_period_mask, bl_pwm_mask; + struct dce_panel_cntl *dce_panel_cntl = TO_DCE_PANEL_CNTL(panel_cntl); pwm_period_cntl = REG_READ(BL_PWM_PERIOD_CNTL); REG_GET(BL_PWM_PERIOD_CNTL, BL_PWM_PERIOD, &bl_period); @@ -150,7 +151,7 @@ static uint32_t dce_panel_cntl_hw_init(struct panel_cntl *panel_cntl) REG_UPDATE(BL_PWM_GRP1_REG_LOCK, BL_PWM_GRP1_REG_LOCK, 0); - current_backlight = calculate_16_bit_backlight_from_pwm(dce_panel_cntl); + current_backlight = dce_get_16_bit_backlight_from_pwm(panel_cntl); return current_backlight; } @@ -273,6 +274,7 @@ static const struct panel_cntl_funcs dce_link_panel_cntl_funcs = { .is_panel_powered_on = dce_is_panel_powered_on, .store_backlight_level = dce_store_backlight_level, .driver_set_backlight = dce_driver_set_backlight, + .get_current_backlight = dce_get_16_bit_backlight_from_pwm, }; void dce_panel_cntl_construct( diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index aa3ea6c79c27..3b4c356c5ba6 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -340,7 +340,7 @@ static const struct dce110_clk_src_mask cs_mask = { #define abm_regs(id)\ [id] = {\ - ABM_DCN301_REG_LIST(id)\ + ABM_DCN30_REG_LIST(id)\ } static const struct dce_abm_registers abm_regs[] = { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h index f9ab5abb6462..48eac622c6a0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/panel_cntl.h @@ -49,6 +49,7 @@ struct panel_cntl_funcs { void (*store_backlight_level)(struct panel_cntl *panel_cntl); void (*driver_set_backlight)(struct panel_cntl *panel_cntl, uint32_t backlight_pwm_u16_16); + uint32_t (*get_current_backlight)(struct panel_cntl *panel_cntl); }; struct panel_cntl_init_data { -- cgit v1.2.3 From ce271b40a91f781af3dee985c39e841ac5148766 Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Thu, 30 Jul 2020 15:35:41 -0400 Subject: drm/amd/display: Screen corruption on dual displays (DP+USB-C) [why] Current pipe merge and split logic only supports cases where new dc_state is allocated and relies on dc->current_state to gather information from previous dc_state. Calls to validate_bandwidth on UPDATE_TYPE_MED would cause an issue because there is no new dc_state allocated, and data in dc->current_state would be overwritten during pipe merge. [how] Only allow validate_bandwidth when new dc_state space is created. Signed-off-by: Qingqing Zhuo Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index a2084f279e7b..dc463d99ef50 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2636,7 +2636,7 @@ void dc_commit_updates_for_stream(struct dc *dc, copy_stream_update_to_stream(dc, context, stream, stream_update); - if (update_type > UPDATE_TYPE_FAST) { + if (update_type >= UPDATE_TYPE_FULL) { if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) { DC_ERROR("Mode validation failed for stream update!\n"); dc_release_state(context); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c index c31d1f30e505..1b9874445134 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c @@ -3209,6 +3209,9 @@ static noinline bool dcn20_validate_bandwidth_fp(struct dc *dc, context->bw_ctx.dml.soc.allow_dram_clock_one_display_vactive = dc->debug.enable_dram_clock_change_one_display_vactive; + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + if (fast_validate) { return dcn20_validate_bandwidth_internal(dc, context, true); } diff --git a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c index a828696668bf..78743ae37851 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c @@ -1184,6 +1184,9 @@ bool dcn21_validate_bandwidth(struct dc *dc, struct dc_state *context, BW_VAL_TRACE_COUNT(); + /*Unsafe due to current pipe merge and split logic*/ + ASSERT(context != dc->current_state); + out = dcn20_fast_validate_bw(dc, context, pipes, &pipe_cnt, pipe_split_from, &vlevel); if (pipe_cnt == 0) -- cgit v1.2.3 From 4bb23a544667a5c9f6dd158abf5158c120e1707f Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Aug 2020 13:57:08 -0400 Subject: drm/amd/display: fix dcn3 wide timing dsc validation Wide timing DSC requires odm. Since spreadsheet is missing this dsc validation we have to modify DML vba code ourselves. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Wesley Chalmers Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index b54814f11b74..2beb284f89b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -63,6 +63,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff +#define DCN30_MAX_DSC_IMAGE_WIDTH 5184 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -3984,6 +3985,9 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; -- cgit v1.2.3 From bcc6aa61c82d4f12df3ecc884a9eef9d566edae9 Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Fri, 19 Jun 2020 14:42:09 -0400 Subject: drm/amd/display: Fix DSC force enable on SST [why] Previously when force enabling DSC on SST display we unknowingly supressed lane count, which caused DSC to be enabled automatically. [how] By adding an additional flag to force enable DSC in dc_dsc.c DSC can always be enabled with debugfs dsc_clock_en forced to 1 Cc: stable@vger.kernel.org Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ drivers/gpu/drm/amd/display/dc/dc_dsc.h | 3 +++ drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 16 +++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 0d121a3f2103..ad6b95d65f7b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4646,6 +4646,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, #if defined(CONFIG_DRM_AMD_DC_DCN) if (dsc_caps.is_dsc_supported) { + /* Set DSC policy according to dsc_clock_en */ + dc_dsc_policy_set_enable_dsc_when_not_needed(aconnector->dsc_settings.dsc_clock_en); + if (dc_dsc_compute_config(aconnector->dc_link->ctx->dc->res_pool->dscs[0], &dsc_caps, aconnector->dc_link->ctx->dc->debug.dsc_min_slice_height_override, diff --git a/drivers/gpu/drm/amd/display/dc/dc_dsc.h b/drivers/gpu/drm/amd/display/dc/dc_dsc.h index 3800340a5b4f..768ab38d41cf 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dsc.h @@ -51,6 +51,7 @@ struct dc_dsc_policy { int min_slice_height; // Must not be less than 8 uint32_t max_target_bpp; uint32_t min_target_bpp; + bool enable_dsc_when_not_needed; }; bool dc_dsc_parse_dsc_dpcd(const struct dc *dc, @@ -80,4 +81,6 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit); +void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable); + #endif diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index 8cdaa6eef5d3..da1b654833d5 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -34,6 +34,9 @@ /* default DSC policy target bitrate limit is 16bpp */ static uint32_t dsc_policy_max_target_bpp_limit = 16; +/* default DSC policy enables DSC only when needed */ +static bool dsc_policy_enable_dsc_when_not_needed; + static uint32_t dc_dsc_bandwidth_in_kbps_from_timing( const struct dc_crtc_timing *timing) { @@ -360,7 +363,7 @@ static bool decide_dsc_target_bpp_x16( get_dsc_bandwidth_range(policy->min_target_bpp, policy->max_target_bpp, dsc_common_caps, timing, &range); - if (target_bandwidth_kbps >= range.stream_kbps) { + if (!policy->enable_dsc_when_not_needed && target_bandwidth_kbps >= range.stream_kbps) { /* enough bandwidth without dsc */ *target_bpp_x16 = 0; should_use_dsc = false; @@ -961,9 +964,20 @@ void dc_dsc_get_policy_for_timing(const struct dc_crtc_timing *timing, struct dc /* internal upper limit, default 16 bpp */ if (policy->max_target_bpp > dsc_policy_max_target_bpp_limit) policy->max_target_bpp = dsc_policy_max_target_bpp_limit; + + /* enable DSC when not needed, default false */ + if (dsc_policy_enable_dsc_when_not_needed) + policy->enable_dsc_when_not_needed = dsc_policy_enable_dsc_when_not_needed; + else + policy->enable_dsc_when_not_needed = false; } void dc_dsc_policy_set_max_target_bpp_limit(uint32_t limit) { dsc_policy_max_target_bpp_limit = limit; } + +void dc_dsc_policy_set_enable_dsc_when_not_needed(bool enable) +{ + dsc_policy_enable_dsc_when_not_needed = enable; +} -- cgit v1.2.3 From 6798d04205d171df94b016163b13094179878d67 Mon Sep 17 00:00:00 2001 From: Lewis Huang Date: Thu, 30 Jul 2020 18:00:23 +0800 Subject: drm/amd/display: Add extra T3 delay [Why] For some special panel, it will have an invalid HPD high cause driver DPCD read/write fail. [How] Add extra T3 delay as a monitor patch in dce110_edp_wait_for_hpd_ready Signed-off-by: Lewis Huang Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 946ba929c6f6..aa8e0955db48 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -233,6 +233,7 @@ struct dc_panel_patch { unsigned int skip_scdc_overwrite; unsigned int delay_ignore_msa; unsigned int disable_fec; + unsigned int extra_t3_ms; }; struct dc_edid_caps { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 45c9e9027886..0603ddca7bd0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -720,6 +720,7 @@ void dce110_edp_wait_for_hpd_ready( struct dc_context *ctx = link->ctx; struct graphics_object_id connector = link->link_enc->connector; struct gpio *hpd; + struct dc_sink *sink = link->local_sink; bool edp_hpd_high = false; uint32_t time_elapsed = 0; uint32_t timeout = power_up ? @@ -752,6 +753,14 @@ void dce110_edp_wait_for_hpd_ready( return; } + if (sink != NULL) { + if (sink->edid_caps.panel_patch.extra_t3_ms > 0) { + int extra_t3_in_ms = sink->edid_caps.panel_patch.extra_t3_ms; + + msleep(extra_t3_in_ms); + } + } + dal_gpio_open(hpd, GPIO_MODE_INTERRUPT); /* wait until timeout or panel detected */ -- cgit v1.2.3 From 8cfc40cd97475fcddb2ca4671eaea2eb26b31e0a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 6 Aug 2020 15:40:01 -0400 Subject: drm/amd/display: Reset scrambling on Test Pattern [Why] Programming is missing the sequence where for eDP the scrambling is reset when testing for eye diagram test pattern. [How] Include the required register in the definition Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 3b4c356c5ba6..1ee9087eec76 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } static const struct dce110_aux_registers_shift aux_shift = { -- cgit v1.2.3 From 5ab7943187f22b572fd12d517bd699771b88ce91 Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac Date: Thu, 6 Aug 2020 17:54:47 -0400 Subject: drm/amd/display: fix pow() crashing when given base 0 [Why&How] pow(a,x) is implemented as exp(x*log(a)). log(0) will crash. So return 0^x = 0, unless x=0, convention seems to be 0^0 = 1. Cc: stable@vger.kernel.org Signed-off-by: Krunoslav Kovac Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/fixed31_32.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 89ef9f6860e5..16df2a485dd0 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -431,6 +431,9 @@ struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg); */ static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2) { + if (arg1.value == 0) + return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero; + return dc_fixpt_exp( dc_fixpt_mul( dc_fixpt_log(arg1), -- cgit v1.2.3 From e0f7ff99c92ff5e033e169c30cff607ff7c17192 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Wed, 5 Aug 2020 17:28:53 -0400 Subject: drm/amd/display: Mask DPCD field to avoid reading unsupported field value [Why] DSC will be disabled if DPCD 0006F[6:3] is set to a non-zero value because bits 6:3 are not currently supported. When 6:3 is populated, an unsupported INCREMENT OF bits_per_pixel value is read (DPCD 0006F[2:0]) [How] Mask the INCREMENT OF bits_per_pixel field so that values in the unsupported field are ignored. Signed-off-by: Jaehyun Chung Reviewed-by: Wenjing Liu Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c index da1b654833d5..4c844cfaa956 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c @@ -192,8 +192,10 @@ static bool dsc_throughput_from_dpcd(int dpcd_throughput, int *throughput) } -static bool dsc_bpp_increment_div_from_dpcd(int bpp_increment_dpcd, uint32_t *bpp_increment_div) +static bool dsc_bpp_increment_div_from_dpcd(uint8_t bpp_increment_dpcd, uint32_t *bpp_increment_div) { + // Mask bpp increment dpcd field to avoid reading other fields + bpp_increment_dpcd &= 0x7; switch (bpp_increment_dpcd) { case 0: -- cgit v1.2.3 From 2ac685bfca27dd692b772fdd66b59ef1d83453be Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Fri, 7 Aug 2020 21:06:11 -0400 Subject: drm/amd/display: [FW Promotion] Release 0.0.29 [Header Changes] - Add command for panel power seq control Signed-off-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index b58ed6538eab..d7e7f2eda92f 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -36,10 +36,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x3f7e3738b +#define DMUB_FW_VERSION_GIT_HASH 0x4e5b2f46f #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 28 +#define DMUB_FW_VERSION_REVISION 29 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 @@ -213,6 +213,7 @@ enum dmub_cmd_vbios_type { DMUB_CMD__VBIOS_DIG1_TRANSMITTER_CONTROL = 1, DMUB_CMD__VBIOS_SET_PIXEL_CLOCK = 2, DMUB_CMD__VBIOS_ENABLE_DISP_POWER_GATING = 3, + DMUB_CMD__VBIOS_LVTMA_CONTROL = 15, }; //============================================================================== -- cgit v1.2.3 From 6fecfc82529d3cac41bb1f36b9b825926c1657e7 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Thu, 13 Aug 2020 16:51:09 -0400 Subject: drm/amd/display: Add DSC_DBG_EN shift/mask for dcn3 This field is not defined for DCN3 Signed-off-by: Bhawanpreet Lakha Reviewed-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h | 1 + .../amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h index 667640c4b288..1118e33aaa2c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.h @@ -94,6 +94,7 @@ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_CLOCK_EN, mask_sh), \ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DISPCLK_R_GATE_DIS, mask_sh), \ DSC_SF(DSC_TOP0_DSC_TOP_CONTROL, DSC_DSCCLK_R_GATE_DIS, mask_sh), \ + DSC_SF(DSC_TOP0_DSC_DEBUG_CONTROL, DSC_DBG_EN, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, ICH_RESET_AT_END_OF_LINE, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, NUMBER_OF_SLICES_PER_LINE, mask_sh), \ DSC_SF(DSCC0_DSCC_CONFIG0, ALTERNATE_ICH_ENCODING_EN, mask_sh), \ diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h index 0e0319e98c07..ea683f452bb3 100755 --- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h @@ -50271,6 +50271,10 @@ #define DSC_TOP0_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP0_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP0_DSC_DEBUG_CONTROL +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP0_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc0_dispdec_dsccif_dispdec //DSCCIF0_DSCCIF_CONFIG0 @@ -50789,6 +50793,9 @@ #define DSC_TOP1_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP1_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP1_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP1_DSC_DEBUG_CONTROL +#define DSC_TOP1_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP1_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L // addressBlock: dce_dc_dsc1_dispdec_dsccif_dispdec @@ -51308,6 +51315,10 @@ #define DSC_TOP2_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP2_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP2_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP2_DSC_DEBUG_CONTROL +#define DSC_TOP2_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP2_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc2_dispdec_dsccif_dispdec //DSCCIF2_DSCCIF_CONFIG0 @@ -51826,6 +51837,9 @@ #define DSC_TOP3_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP3_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP3_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP3_DSC_DEBUG_CONTROL +#define DSC_TOP3_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP3_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L // addressBlock: dce_dc_dsc3_dispdec_dsccif_dispdec @@ -52346,6 +52360,10 @@ #define DSC_TOP4_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP4_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP4_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP4_DSC_DEBUG_CONTROL +#define DSC_TOP4_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP4_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc4_dispdec_dsccif_dispdec //DSCCIF4_DSCCIF_CONFIG0 @@ -52864,6 +52882,10 @@ #define DSC_TOP5_DSC_TOP_CONTROL__DSC_CLOCK_EN_MASK 0x00000001L #define DSC_TOP5_DSC_TOP_CONTROL__DSC_DISPCLK_R_GATE_DIS_MASK 0x00000010L #define DSC_TOP5_DSC_TOP_CONTROL__DSC_DSCCLK_R_GATE_DIS_MASK 0x00000100L +//DSC_TOP5_DSC_DEBUG_CONTROL +#define DSC_TOP5_DSC_DEBUG_CONTROL__DSC_DBG_EN__SHIFT 0x0 +#define DSC_TOP5_DSC_DEBUG_CONTROL__DSC_DBG_EN_MASK 0x00000001L + // addressBlock: dce_dc_dsc5_dispdec_dsccif_dispdec //DSCCIF5_DSCCIF_CONFIG0 -- cgit v1.2.3 From ccc862b957c6413b008fbe458034372847992d7f Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Mon, 10 Aug 2020 18:19:18 +0530 Subject: drm/msm/dpu: Fix reservation failures in modeset In TEST_ONLY commit, rm global_state will duplicate the object and request for new reservations, once they pass then the new state will be swapped with the old and will be available for the Atomic Commit. This patch fixes some of missing links in the resource reservation sequence mentioned above. 1) Creation of duplicate state in test_only commit (Rob) 2) Allocate and release the resources on every modeset. 3) Avoid allocation only when active is false. In a modeset operation, swap state happens well before disable. Hence clearing reservations in disable will cause failures in modeset enable. Allow reservations to be cleared/allocated before swap, such that only newly committed resources are pushed to HW. Changes in v1: - Move the rm release to atomic_check. - Ensure resource allocation and free happens when active is not changed i.e only when mode is changed.(Rob) Changes in v2: - Handle dpu_kms_get_global_state API failure as it may return EDEADLK (swboyd). Signed-off-by: Kalyan Thota Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index a97f6d2e5a08..bd6def436c65 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -599,7 +599,10 @@ static int dpu_encoder_virt_atomic_check( dpu_kms = to_dpu_kms(priv->kms); mode = &crtc_state->mode; adj_mode = &crtc_state->adjusted_mode; - global_state = dpu_kms_get_existing_global_state(dpu_kms); + global_state = dpu_kms_get_global_state(crtc_state->state); + if (IS_ERR(global_state)) + return PTR_ERR(global_state); + trace_dpu_enc_atomic_check(DRMID(drm_enc)); /* perform atomic check on the first physical encoder (master) */ @@ -625,12 +628,15 @@ static int dpu_encoder_virt_atomic_check( /* Reserve dynamic resources now. */ if (!ret) { /* - * Avoid reserving resources when mode set is pending. Topology - * info may not be available to complete reservation. + * Release and Allocate resources on every modeset + * Dont allocate when active is false. */ if (drm_atomic_crtc_needs_modeset(crtc_state)) { - ret = dpu_rm_reserve(&dpu_kms->rm, global_state, - drm_enc, crtc_state, topology); + dpu_rm_release(global_state, drm_enc); + + if (!crtc_state->active_changed || crtc_state->active) + ret = dpu_rm_reserve(&dpu_kms->rm, global_state, + drm_enc, crtc_state, topology); } } @@ -1181,7 +1187,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) struct dpu_encoder_virt *dpu_enc = NULL; struct msm_drm_private *priv; struct dpu_kms *dpu_kms; - struct dpu_global_state *global_state; int i = 0; if (!drm_enc) { @@ -1200,7 +1205,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) priv = drm_enc->dev->dev_private; dpu_kms = to_dpu_kms(priv->kms); - global_state = dpu_kms_get_existing_global_state(dpu_kms); trace_dpu_enc_disable(DRMID(drm_enc)); @@ -1230,8 +1234,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); - dpu_rm_release(global_state, drm_enc); - mutex_unlock(&dpu_enc->enc_lock); } -- cgit v1.2.3 From 4c978caf08aa155bdeadd9e2d4b026d4ce97ebd0 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Thu, 30 Jul 2020 19:08:56 +0530 Subject: drm/msm/dpu: Fix scale params in plane validation Plane validation uses an API drm_calc_scale which will return src/dst value as a scale ratio. when viewing the range on a scale the values should fall in as Upscale ratio < Unity scale < Downscale ratio for src/dst formula Fix the min and max scale ratios to suit the API accordingly. Signed-off-by: Kalyan Thota Tested-by: Kristian H. Kristensen Reviewed-by: Kristian H. Kristensen Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 33f6c56f01ed..29e373d2e7b5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -866,9 +866,9 @@ static int dpu_plane_atomic_check(struct drm_plane *plane, crtc_state = drm_atomic_get_new_crtc_state(state->state, state->crtc); - min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxdwnscale); + min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxupscale); ret = drm_atomic_helper_check_plane_state(state, crtc_state, min_scale, - pdpu->pipe_sblk->maxupscale << 16, + pdpu->pipe_sblk->maxdwnscale << 16, true, true); if (ret) { DPU_DEBUG_PLANE(pdpu, "Check plane state failed (%d)\n", ret); -- cgit v1.2.3 From 35c719da95c0d28560bff7bafeaf07ebb212665e Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 11 Aug 2020 14:09:35 -0700 Subject: drm/msm/dpu: fix unitialized variable error drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c:817 dpu_crtc_enable() error: uninitialized symbol 'request_bandwidth'. Reported-by: kernel test robot Signed-off-by: Rob Clark Reviewed-by: Sean Paul Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index f272a8d0f95b..c2729f71e2fa 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -827,7 +827,7 @@ static void dpu_crtc_enable(struct drm_crtc *crtc, { struct dpu_crtc *dpu_crtc; struct drm_encoder *encoder; - bool request_bandwidth; + bool request_bandwidth = false; if (!crtc) { DPU_ERROR("invalid crtc\n"); -- cgit v1.2.3 From f228af11dfa1d1616bc67f3a4119ab77c36181f1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 12 Aug 2020 17:03:09 -0700 Subject: drm/msm/adreno: fix updating ring fence We need to set it to the most recent completed fence, not the most recent submitted. Otherwise we have races where we think we can retire submits that the GPU is not finished with, if the GPU doesn't manage to overwrite the seqno before we look at it. This can show up with hang recovery if one of the submits after the crashing submit also hangs after it is replayed. Fixes: f97decac5f4c ("drm/msm: Support multiple ringbuffers") Signed-off-by: Rob Clark Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index e23641a5ec84..d2dbb6968cba 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -396,7 +396,7 @@ int adreno_hw_init(struct msm_gpu *gpu) ring->next = ring->start; /* reset completed fence seqno: */ - ring->memptrs->fence = ring->seqno; + ring->memptrs->fence = ring->fctx->completed_fence; ring->memptrs->rptr = 0; } -- cgit v1.2.3 From 352c83fb39cae3eff95a8e1ed23006291abb6196 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 17 Aug 2020 09:23:09 -0700 Subject: drm/msm/gpu: make ringbuffer readonly The GPU has no business writing into the ringbuffer, let's make it readonly to the GPU. Fixes: 7198e6b03155 ("drm/msm: add a3xx gpu support") Signed-off-by: Rob Clark Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_ringbuffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index e397c44cc011..39ecb5a18431 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -27,7 +27,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->id = id; ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ, - MSM_BO_WC, gpu->aspace, &ring->bo, &ring->iova); + MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &ring->bo, + &ring->iova); if (IS_ERR(ring->start)) { ret = PTR_ERR(ring->start); -- cgit v1.2.3 From 20925fe84463ef87a01b0b536768c39544eae89b Mon Sep 17 00:00:00 2001 From: Sharat Masetty Date: Mon, 13 Jul 2020 18:11:43 +0530 Subject: drm: msm: a6xx: use dev_pm_opp_set_bw to scale DDR This patches replaces the previously used static DDR vote and uses dev_pm_opp_set_bw() to scale GPU->DDR bandwidth along with scaling GPU frequency. Also since the icc path voting is handled completely in the opp driver, remove the icc_path handle and its usage in the drm driver. Signed-off-by: Sharat Masetty Signed-off-by: Akhil P Oommen Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index b67b38c8fadf..5b2df7d48138 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -133,7 +133,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) if (!gmu->legacy) { a6xx_hfi_set_freq(gmu, perf_index); - icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216)); + dev_pm_opp_set_bw(&gpu->pdev->dev, opp); pm_runtime_put(gmu->dev); return; } @@ -157,11 +157,7 @@ void a6xx_gmu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) if (ret) dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret); - /* - * Eventually we will want to scale the path vote with the frequency but - * for now leave it at max so that the performance is nominal. - */ - icc_set_bw(gpu->icc_path, 0, MBps_to_icc(7216)); + dev_pm_opp_set_bw(&gpu->pdev->dev, opp); pm_runtime_put(gmu->dev); } @@ -849,6 +845,19 @@ static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu) dev_pm_opp_put(gpu_opp); } +static void a6xx_gmu_set_initial_bw(struct msm_gpu *gpu, struct a6xx_gmu *gmu) +{ + struct dev_pm_opp *gpu_opp; + unsigned long gpu_freq = gmu->gpu_freqs[gmu->current_perf_index]; + + gpu_opp = dev_pm_opp_find_freq_exact(&gpu->pdev->dev, gpu_freq, true); + if (IS_ERR_OR_NULL(gpu_opp)) + return; + + dev_pm_opp_set_bw(&gpu->pdev->dev, gpu_opp); + dev_pm_opp_put(gpu_opp); +} + int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) { struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; @@ -882,7 +891,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu) } /* Set the bus quota to a reasonable value for boot */ - icc_set_bw(gpu->icc_path, 0, MBps_to_icc(3072)); + a6xx_gmu_set_initial_bw(gpu, gmu); /* Enable the GMU interrupt */ gmu_write(gmu, REG_A6XX_GMU_AO_HOST_INTERRUPT_CLR, ~0); @@ -1051,7 +1060,7 @@ int a6xx_gmu_stop(struct a6xx_gpu *a6xx_gpu) a6xx_gmu_shutdown(gmu); /* Remove the bus vote */ - icc_set_bw(gpu->icc_path, 0, 0); + dev_pm_opp_set_bw(&gpu->pdev->dev, NULL); /* * Make sure the GX domain is off before turning off the GMU (CX) -- cgit v1.2.3 From 83c0926f3e189e91137c5311f2d187eafc6091a0 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 14 Jul 2020 23:19:45 +0300 Subject: drm/i915/fbc: Limit cfb to the first 256MiB of stolen on g4x+ Since g4x the CFB base only takes a 28bit offset into stolen. Not sure if the CFB is allowed to start below that limit but then extend beyond it. Let's assume not and just restrict the allocation to the first 256MiB (in the unlikely case we have more stolen than that). v2: s/BIT/BIT_ULL/ (Chris) Cc: Chris Wilson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714201945.18959-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 85723fba6002..3a4f980788a6 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -424,6 +424,14 @@ static void intel_fbc_deactivate(struct drm_i915_private *dev_priv, fbc->no_fbc_reason = reason; } +static u64 intel_fbc_cfb_base_max(struct drm_i915_private *i915) +{ + if (INTEL_GEN(i915) >= 5 || IS_G4X(i915)) + return BIT_ULL(28); + else + return BIT_ULL(32); +} + static int find_compression_threshold(struct drm_i915_private *dev_priv, struct drm_mm_node *node, unsigned int size, @@ -442,6 +450,8 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv, else end = U64_MAX; + end = min(end, intel_fbc_cfb_base_max(dev_priv)); + /* HACK: This code depends on what we will do in *_enable_fbc. If that * code changes, this code needs to change as well. * -- cgit v1.2.3 From 124c7088b87fdf97530fe96d7c025fce9198ed9c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 14 Jul 2020 18:26:23 +0300 Subject: drm/i915: Pack struct intel_cdclk_vals There's a pointless hole in struct intel_cdclk_vals, get rid of it. Fortunately we already use named initializers so the order does not matter. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-1-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index 5731806e4cee..6b31fde4be16 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -17,8 +17,8 @@ struct intel_atomic_state; struct intel_crtc_state; struct intel_cdclk_vals { - u16 refclk; u32 cdclk; + u16 refclk; u8 divider; /* CD2X divider * 2 */ u8 ratio; }; -- cgit v1.2.3 From 0e954383ff575d42095eeb8a8083ada693053e5e Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 14 Jul 2020 18:26:24 +0300 Subject: drm/i915: Fix some whitespace Some spaces have snuck in where we want tabs. Fix it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-2-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index bb91dace304a..72095ef14426 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2677,7 +2677,7 @@ void intel_update_cdclk(struct drm_i915_private *dev_priv) */ if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) intel_de_write(dev_priv, GMBUSFREQ_VLV, - DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000)); + DIV_ROUND_UP(dev_priv->cdclk.hw.cdclk, 1000)); } static int cnp_rawclk(struct drm_i915_private *dev_priv) -- cgit v1.2.3 From 366ec167ea73c36ec2a2ccd144306623e8e49b9c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Tue, 14 Jul 2020 18:26:25 +0300 Subject: drm/i915: Make i830 .get_cdclk() assignment less confusing Explicitly check for i830 when assigning the .get_cdclk() vfunc, and then deal with the case of not having assigned the vfunc separately. Less confusing, and gets rid of the checkpatch complaint about using {} on one branch but not the others. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714152626.380-3-ville.syrjala@linux.intel.com Reviewed-by: Chris Wilson Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_cdclk.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 72095ef14426..9d6cacbdb691 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2903,9 +2903,10 @@ void intel_init_cdclk_hooks(struct drm_i915_private *dev_priv) dev_priv->display.get_cdclk = i85x_get_cdclk; else if (IS_I845G(dev_priv)) dev_priv->display.get_cdclk = fixed_200mhz_get_cdclk; - else { /* 830 */ - drm_WARN(&dev_priv->drm, !IS_I830(dev_priv), - "Unknown platform. Assuming 133 MHz CDCLK\n"); + else if (IS_I830(dev_priv)) + dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk; + + if (drm_WARN(&dev_priv->drm, !dev_priv->display.get_cdclk, + "Unknown platform. Assuming 133 MHz CDCLK\n")) dev_priv->display.get_cdclk = fixed_133mhz_get_cdclk; - } } -- cgit v1.2.3 From 963501bdd094acb4a382d185a9754cd30b8903ba Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 14 Jul 2020 18:31:40 +0300 Subject: drm/i915/ddi: Don't frob the DP link scramble disabling flag According to BSpec this flag should not be changed while the DDI function is enabled. On BDW+ the DP_TP_CTL register spec also states it explicitly that the HW takes care of enabling/disabling the scrambling for training patterns (and it must stay enabled for normal pixel output). Assume that this HW automatic handling of scrambling is also true for HSW. BSpec: 8013, 7557, 50484 Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714153141.10280-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 2c484b55bcdf..c467f18d5e1b 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4037,8 +4037,7 @@ static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) intel_wait_ddi_buf_idle(dev_priv, port); } - dp_tp_ctl = DP_TP_CTL_ENABLE | - DP_TP_CTL_LINK_TRAIN_PAT1 | DP_TP_CTL_SCRAMBLE_DISABLE; + dp_tp_ctl = DP_TP_CTL_ENABLE | DP_TP_CTL_LINK_TRAIN_PAT1; if (intel_dp->link_mst) dp_tp_ctl |= DP_TP_CTL_MODE_MST; else { @@ -4066,11 +4065,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_ctl); - if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) - temp |= DP_TP_CTL_SCRAMBLE_DISABLE; - else - temp &= ~DP_TP_CTL_SCRAMBLE_DISABLE; - temp &= ~DP_TP_CTL_LINK_TRAIN_MASK; switch (dp_train_pat & train_pat_mask) { case DP_TRAINING_PATTERN_DISABLE: -- cgit v1.2.3 From a5bcf8dde63142f36ae8ce720265d4c41a634d5c Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 14 Jul 2020 18:31:41 +0300 Subject: drm/i915/ddi: Don't rewrite DDI_BUF_CTL reg during DP link training The value we program to DDI_BUF_CTL changes at the following places: - At enabling/disabling the output to configure the port width etc, and to enable/disable the DDI BUF function. - At the beginning/end of link re-training to disable/re-enable the DDI BUF function. - On HSW/BDW/SKL to change the voltage swing/pre-emph levels. Except of the above the value we program to the DDI_BUF_CTL register (intel_dp->DP) doesn't change, so no need to reprogram the register when changing the link training patterns (which is programmed via the DP_TP_CTL register on DDI platforms). v2: - Fix the commit message wrt. voltage/pre-emph level values in intel_dp->DP. (Ville) Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200714153141.10280-2-imre.deak@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c467f18d5e1b..424d59671561 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4060,7 +4060,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); u8 train_pat_mask = drm_dp_training_pattern_mask(intel_dp->dpcd); - enum port port = dp_to_dig_port(intel_dp)->base.port; u32 temp; temp = intel_de_read(dev_priv, intel_dp->regs.dp_tp_ctl); @@ -4085,9 +4084,6 @@ static void intel_ddi_set_link_train(struct intel_dp *intel_dp, } intel_de_write(dev_priv, intel_dp->regs.dp_tp_ctl, temp); - - intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP); - intel_de_posting_read(dev_priv, DDI_BUF_CTL(port)); } static void intel_ddi_set_idle_link_train(struct intel_dp *intel_dp) -- cgit v1.2.3 From 27e897beec1c59861f15d4d3562c39ad1143620f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2020 10:46:43 +0100 Subject: drm/i915: Provide the perf pmu.module Rather than manually implement our own module reference counting for perf pmu events, finally realise that there is a module parameter to struct pmu for this very purpose. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200716094643.31410-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pmu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 28bc5f13ae52..056994224c6b 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -445,8 +445,6 @@ static void i915_pmu_event_destroy(struct perf_event *event) container_of(event->pmu, typeof(*i915), pmu.base); drm_WARN_ON(&i915->drm, event->parent); - - module_put(THIS_MODULE); } static int @@ -538,10 +536,8 @@ static int i915_pmu_event_init(struct perf_event *event) if (ret) return ret; - if (!event->parent) { - __module_get(THIS_MODULE); + if (!event->parent) event->destroy = i915_pmu_event_destroy; - } return 0; } @@ -1130,6 +1126,7 @@ void i915_pmu_register(struct drm_i915_private *i915) if (!pmu->base.attr_groups) goto err_attr; + pmu->base.module = THIS_MODULE; pmu->base.task_ctx_nr = perf_invalid_context; pmu->base.event_init = i915_pmu_event_init; pmu->base.add = i915_pmu_event_add; -- cgit v1.2.3 From 81619f4a75ed75823d52f46e167fa82d72c1eeef Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Wed, 15 Jul 2020 10:56:37 -0700 Subject: drm/i915/display: Implement HOBL Hours Of Battery Life is a new GEN12+ power-saving feature that allows supported motherboards to use a special voltage swing table for eDP panels that uses less power. So here if supported by HW, OEM will set it in VBT and i915 will try to train link with HOBL vswing table if link training fails it fall back to the original table. intel_ddi_dp_preemph_max() was optimized to only check the HOBL flag instead of do something like is done in intel_ddi_dp_voltage_max() because it is only called after the first entry of the voltage swing table was loaded so the HOBL flag is valid at that point. v3: - removed a few parameters of icl_ddi_combo_vswing_program() that can be taken from encoder v4: - using the HOBL vswing table until training fails completely (Ville) v5: - not reducing lane or link rate when link training fails with HOBL active - duplicated the HOBL voltage swing entry to match DP spec requirement v6: - removed the optional VS 3 & pre-emp 0 from HOBL table - changed from u8:1 to bool to store hobl_failed/active BSpec: 49291 BSpec: 49399 Reviewed-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Animesh Manna Cc: Manasi Navare Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200715175637.33763-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 43 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_display_types.h | 3 ++ .../gpu/drm/i915/display/intel_dp_link_training.c | 19 +++++++--- drivers/gpu/drm/i915/i915_reg.h | 2 + 4 files changed, 61 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 424d59671561..c52ad5ecb645 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -706,6 +706,28 @@ static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; +/* + * Cloned the HOBL entry to comply with the voltage and pre-emphasis entries + * that DisplayPort specification requires + */ +static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_edp_hbr2_hobl[] = { + /* VS pre-emp */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 1 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 2 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 0 3 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 1 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 1 2 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 0 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 2 1 */ +}; + +static bool is_hobl_buf_trans(const struct cnl_ddi_buf_trans *table) +{ + return table == tgl_combo_phy_ddi_translations_edp_hbr2_hobl; +} + static const struct ddi_buf_trans * bdw_get_buf_trans_edp(struct intel_encoder *encoder, int *n_entries) { @@ -1050,6 +1072,18 @@ static const struct cnl_ddi_buf_trans * tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, int *n_entries) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + + if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.hobl) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + if (!intel_dp->hobl_failed && rate <= 540000) { + /* Same table applies to TGL, RKL and DG1 */ + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_edp_hbr2_hobl); + return tgl_combo_phy_ddi_translations_edp_hbr2_hobl; + } + } + if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } else if (rate > 270000) { @@ -2392,6 +2426,15 @@ static void icl_ddi_combo_vswing_program(struct intel_encoder *encoder, level = n_entries - 1; } + if (type == INTEL_OUTPUT_EDP) { + struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + val = EDP4K2K_MODE_OVRD_EN | EDP4K2K_MODE_OVRD_OPTIMIZED; + intel_dp->hobl_active = is_hobl_buf_trans(ddi_translations); + intel_de_rmw(dev_priv, ICL_PORT_CL_DW10(phy), val, + intel_dp->hobl_active ? val : 0); + } + /* Set PORT_TX_DW5 */ val = intel_de_read(dev_priv, ICL_PORT_TX_DW5_LN0(phy)); val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e8f809161c75..f581260e8dbf 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1375,6 +1375,9 @@ struct intel_dp { /* Display stream compression testing */ bool force_dsc_en; + + bool hobl_failed; + bool hobl_active; }; enum lspcon_vendor { diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index a23ed7290843..f2c8b56be9ea 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -410,10 +410,17 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) intel_connector->base.base.id, intel_connector->base.name, intel_dp->link_rate, intel_dp->lane_count); - if (!intel_dp_get_link_train_fallback_values(intel_dp, - intel_dp->link_rate, - intel_dp->lane_count)) - /* Schedule a Hotplug Uevent to userspace to start modeset */ - schedule_work(&intel_connector->modeset_retry_work); - return; + + if (intel_dp->hobl_active) { + drm_dbg_kms(&dp_to_i915(intel_dp)->drm, + "Link Training failed with HOBL active, not enabling it from now on"); + intel_dp->hobl_failed = true; + } else if (intel_dp_get_link_train_fallback_values(intel_dp, + intel_dp->link_rate, + intel_dp->lane_count)) { + return; + } + + /* Schedule a Hotplug Uevent to userspace to start modeset */ + schedule_work(&intel_connector->modeset_retry_work); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4e796ff4d7d0..b9607ac3620d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1898,6 +1898,8 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define PWR_DOWN_LN_3_1_0 (0xb << 4) #define PWR_DOWN_LN_MASK (0xf << 4) #define PWR_DOWN_LN_SHIFT 4 +#define EDP4K2K_MODE_OVRD_EN (1 << 3) +#define EDP4K2K_MODE_OVRD_OPTIMIZED (1 << 2) #define ICL_PORT_CL_DW12(phy) _MMIO(_ICL_PORT_CL_DW(12, phy)) #define ICL_LANE_ENABLE_AUX (1 << 0) -- cgit v1.2.3 From f1421190d0abf55c34525cc88ab8c00ada9fbb9c Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 16 Jul 2020 22:04:25 +0300 Subject: drm/i915: Move WaDisableDopClockGating:skl to skl_init_clock_gating() It's silly to have if(SKL) checks in gen9_init_clock_gating() when we can just move those bits into skl_init_clock_gating(). I'm not entirely convinced we even need this w/a, or if we do then maybe we want it for kbl/cfl as well. IIRC it was only listed in the wadb, but that is now dead so can't double check anymore. Bspec doesn't seem to have any purely skl specific DOP clock gating workarounds listed. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200716190426.17047-1-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index cfabbe0481ab..0a1a95060f38 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -100,12 +100,6 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) */ I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | DISP_FBC_MEMORY_WAKE); - - if (IS_SKYLAKE(dev_priv)) { - /* WaDisableDopClockGating */ - I915_WRITE(GEN7_MISCCPCTL, I915_READ(GEN7_MISCCPCTL) - & ~GEN7_DOP_CLOCK_GATE_ENABLE); - } } static void bxt_init_clock_gating(struct drm_i915_private *dev_priv) @@ -7251,6 +7245,10 @@ static void skl_init_clock_gating(struct drm_i915_private *dev_priv) { gen9_init_clock_gating(dev_priv); + /* WaDisableDopClockGating:skl */ + I915_WRITE(GEN7_MISCCPCTL, I915_READ(GEN7_MISCCPCTL) & + ~GEN7_DOP_CLOCK_GATE_ENABLE); + /* WAC6entrylatency:skl */ I915_WRITE(FBC_LLC_READ_CTRL, I915_READ(FBC_LLC_READ_CTRL) | FBC_LLC_FULLY_OPEN); -- cgit v1.2.3 From cd803bb4f8a8d7b2c27c464ae32af14005cce7a1 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Jul 2020 15:05:47 -0700 Subject: drm/i915/rkl: Handle new DPCLKA_CFGCR0 layout RKL uses a slightly different bit layout for the DPCLKA_CFGCR0 register. v2: - Fix inverted mask application when updating ICL_DPCLKA_CFGCR0 - Checkpatch style fixes Bspec: 50287 Cc: Aditya Swarup Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-2-matthew.d.roper@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 18 +++++++++++++++--- drivers/gpu/drm/i915/display/intel_display.c | 15 ++++++++++++--- drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c52ad5ecb645..1ca70f9abc8d 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2845,7 +2845,9 @@ hsw_set_signal_levels(struct intel_dp *intel_dp) static u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv, enum phy phy) { - if (intel_phy_is_combo(dev_priv, phy)) { + if (IS_ROCKETLAKE(dev_priv)) { + return RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); + } else if (intel_phy_is_combo(dev_priv, phy)) { return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy); } else if (intel_phy_is_tc(dev_priv, phy)) { enum tc_port tc_port = intel_port_to_tc(dev_priv, @@ -2872,6 +2874,16 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder, (val & icl_dpclka_cfgcr0_clk_off(dev_priv, phy)) == 0); if (intel_phy_is_combo(dev_priv, phy)) { + u32 mask, sel; + + if (IS_ROCKETLAKE(dev_priv)) { + mask = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + sel = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + } else { + mask = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + sel = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + } + /* * Even though this register references DDIs, note that we * want to pass the PHY rather than the port (DDI). For @@ -2882,8 +2894,8 @@ static void icl_map_plls_to_ports(struct intel_encoder *encoder, * Clock Select chooses the PLL for both DDIA and DDID and * drives port A in all cases." */ - val &= ~ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); - val |= ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, phy); + val &= ~mask; + val |= sel; intel_de_write(dev_priv, ICL_DPCLKA_CFGCR0, val); intel_de_posting_read(dev_priv, ICL_DPCLKA_CFGCR0); } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 729ec6e0d43a..6cb66580ad2c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10802,9 +10802,18 @@ static void icl_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, u32 temp; if (intel_phy_is_combo(dev_priv, phy)) { - temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) & - ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); - id = temp >> ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + u32 mask, shift; + + if (IS_ROCKETLAKE(dev_priv)) { + mask = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + shift = RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + } else { + mask = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy); + shift = ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy); + } + + temp = intel_de_read(dev_priv, ICL_DPCLKA_CFGCR0) & mask; + id = temp >> shift; port_dpll_id = ICL_PORT_DPLL_DEFAULT; } else if (intel_phy_is_tc(dev_priv, phy)) { u32 clk_sel = intel_de_read(dev_priv, DDI_CLK_SEL(port)) & DDI_CLK_SEL_MASK; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b9607ac3620d..00414c457941 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10279,12 +10279,18 @@ enum skl_power_gate { #define ICL_DPCLKA_CFGCR0 _MMIO(0x164280) #define ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) (1 << _PICK(phy, 10, 11, 24)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_OFF(phy) REG_BIT((phy) + 10) #define ICL_DPCLKA_CFGCR0_TC_CLK_OFF(tc_port) (1 << ((tc_port) < PORT_TC4 ? \ (tc_port) + 12 : \ (tc_port) - PORT_TC4 + 21)) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) ((phy) * 2) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) (3 << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) #define ICL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) ((pll) << ICL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy) _PICK(phy, 0, 2, 4, 27) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(phy) \ + (3 << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) +#define RKL_DPCLKA_CFGCR0_DDI_CLK_SEL(pll, phy) \ + ((pll) << RKL_DPCLKA_CFGCR0_DDI_CLK_SEL_SHIFT(phy)) /* CNL PLL */ #define DPLL0_ENABLE 0x46010 -- cgit v1.2.3 From f52fa57ae70e2e411c0d72396d526d76bf8d3eda Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Jul 2020 15:05:48 -0700 Subject: drm/i915/rkl: Add initial workarounds RKL and TGL share some general gen12 workarounds, but each platform also has its own platform-specific workarounds. v2: - Add Wa_1604555607 for RKL. This makes RKL's ctx WA list identical to TGL's, so we'll have both functions call the tgl_ function for now; this workaround isn't listed for DG1 so we don't want to add it to the general gen12_ function. Cc: Matt Atwood Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-3-matthew.d.roper@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_sprite.c | 5 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 89 ++++++++++++++++++----------- 2 files changed, 60 insertions(+), 34 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index d03860fef2d7..c26ca029fc0a 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2843,8 +2843,9 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, static bool gen12_plane_supports_mc_ccs(struct drm_i915_private *dev_priv, enum plane_id plane_id) { - /* Wa_14010477008:tgl[a0..c0] */ - if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) + /* Wa_14010477008:tgl[a0..c0],rkl[all] */ + if (IS_ROCKETLAKE(dev_priv) || + IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_C0)) return false; return plane_id < PLANE_SPRITE4; diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 5726cd0a37e0..cef1c122696f 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -596,8 +596,8 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine, wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU); } -static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, - struct i915_wa_list *wal) +static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine, + struct i915_wa_list *wal) { /* * Wa_1409142259:tgl @@ -607,12 +607,28 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, * Wa_1409207793:tgl * Wa_1409178076:tgl * Wa_1408979724:tgl + * Wa_14010443199:rkl + * Wa_14010698770:rkl */ WA_SET_BIT_MASKED(GEN11_COMMON_SLICE_CHICKEN3, GEN12_DISABLE_CPS_AWARE_COLOR_PIPE); + /* WaDisableGPGPUMidThreadPreemption:gen12 */ + WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, + GEN9_PREEMPT_GPGPU_LEVEL_MASK, + GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL); +} + +static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, + struct i915_wa_list *wal) +{ + gen12_ctx_workarounds_init(engine, wal); + /* - * Wa_1604555607:gen12 and Wa_1608008084:gen12 + * Wa_1604555607:tgl,rkl + * + * Note that the implementation of this workaround is further modified + * according to the FF_MODE2 guidance given by Wa_1608008084:gen12. * FF_MODE2 register will return the wrong value when read. The default * value for this register is zero for all fields and there are no bit * masks. So instead of doing a RMW we should just write the GS Timer @@ -623,11 +639,6 @@ static void tgl_ctx_workarounds_init(struct intel_engine_cs *engine, FF_MODE2_GS_TIMER_MASK | FF_MODE2_TDS_TIMER_MASK, FF_MODE2_GS_TIMER_224 | FF_MODE2_TDS_TIMER_128, 0); - - /* WaDisableGPGPUMidThreadPreemption:tgl */ - WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, - GEN9_PREEMPT_GPGPU_LEVEL_MASK, - GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL); } static void @@ -642,8 +653,10 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine, wa_init_start(wal, name, engine->name); - if (IS_GEN(i915, 12)) + if (IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) tgl_ctx_workarounds_init(engine, wal); + else if (IS_GEN(i915, 12)) + gen12_ctx_workarounds_init(engine, wal); else if (IS_GEN(i915, 11)) icl_ctx_workarounds_init(engine, wal); else if (IS_CANNONLAKE(i915)) @@ -1176,9 +1189,16 @@ icl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) } static void -tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) +gen12_gt_workarounds_init(struct drm_i915_private *i915, + struct i915_wa_list *wal) { wa_init_mcr(i915, wal); +} + +static void +tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) +{ + gen12_gt_workarounds_init(i915, wal); /* Wa_1409420604:tgl */ if (IS_TGL_REVID(i915, TGL_REVID_A0, TGL_REVID_A0)) @@ -1196,8 +1216,10 @@ tgl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) static void gt_init_workarounds(struct drm_i915_private *i915, struct i915_wa_list *wal) { - if (IS_GEN(i915, 12)) + if (IS_TIGERLAKE(i915)) tgl_gt_workarounds_init(i915, wal); + else if (IS_GEN(i915, 12)) + gen12_gt_workarounds_init(i915, wal); else if (IS_GEN(i915, 11)) icl_gt_workarounds_init(i915, wal); else if (IS_CANNONLAKE(i915)) @@ -1629,18 +1651,6 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) GEN9_CTX_PREEMPT_REG, GEN12_DISABLE_POSH_BUSY_FF_DOP_CG); - /* - * Wa_1607030317:tgl - * Wa_1607186500:tgl - * Wa_1607297627:tgl there is 3 entries for this WA on BSpec, 2 - * of then says it is fixed on B0 the other one says it is - * permanent - */ - wa_masked_en(wal, - GEN6_RC_SLEEP_PSMI_CONTROL, - GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | - GEN8_RC_SEMA_IDLE_MSG_DISABLE); - /* * Wa_1606679103:tgl * (see also Wa_1606682166:icl) @@ -1654,22 +1664,17 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) VSUNIT_CLKGATE_DIS_TGL); } - if (IS_TIGERLAKE(i915)) { - /* Wa_1606931601:tgl */ + if (IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) { + /* Wa_1606931601:tgl,rkl */ wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ); - /* Wa_1409804808:tgl */ + /* Wa_1409804808:tgl,rkl */ wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_PUSH_CONST_DEREF_HOLD_DIS); - /* Wa_1606700617:tgl */ - wa_masked_en(wal, - GEN9_CS_DEBUG_MODE1, - FF_DOP_CLOCK_GATE_DISABLE); - /* * Wa_1409085225:tgl - * Wa_14010229206:tgl + * Wa_14010229206:tgl,rkl */ wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH); @@ -1677,9 +1682,29 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) * Wa_1407928979:tgl A* * Wa_18011464164:tgl B0+ * Wa_22010931296:tgl B0+ + * Wa_14010919138:rkl */ wa_write_or(wal, GEN7_FF_THREAD_MODE, GEN12_FF_TESSELATION_DOP_GATE_DISABLE); + + /* + * Wa_1607030317:tgl + * Wa_1607186500:tgl + * Wa_1607297627:tgl,rkl there are multiple entries for this + * WA in the BSpec; some indicate this is an A0-only WA, + * others indicate it applies to all steppings. + */ + wa_masked_en(wal, + GEN6_RC_SLEEP_PSMI_CONTROL, + GEN12_WAIT_FOR_EVENT_POWER_DOWN_DISABLE | + GEN8_RC_SEMA_IDLE_MSG_DISABLE); + } + + if (IS_TIGERLAKE(i915)) { + /* Wa_1606700617:tgl */ + wa_masked_en(wal, + GEN9_CS_DEBUG_MODE1, + FF_DOP_CLOCK_GATE_DISABLE); } if (IS_GEN(i915, 11)) { -- cgit v1.2.3 From e66f609baeee0d8354d3e1aa7d171a54ce72cb34 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Jul 2020 15:05:49 -0700 Subject: drm/i915/rkl: Add DPLL4 support Rocket Lake has a third DPLL (called 'DPLL4') that must be used to enable a third display. Unlike EHL's variant of DPLL4, the RKL variant behaves the same as DPLL0/1. And despite its name, the DPLL4 registers are offset as if it were DPLL2. v2: - Add new .update_ref_clks() hook. v3: - Renumber TBT PLL to '3' and switch _MMIO_PLL3 to _MMIO_PLL (Lucas) v4: - Don't drop _MMIO_PLL3; although it's now unused, we're going to need it very soon again for upcoming DG1 patches. (Lucas) v5: - Don't re-number TBT PLL and beyond, just use new RKL_DPLL_CFGCR macros to lookup the proper registers instead. Although renumbering the PLLs might be something we want to consider down the road, it opens a big can of worms right now since a bunch of places in the code have an assumption that the PLL table has idx==id and no holes. Renumbering creates a hole for TGL, so we'd either need to allow holes in the table or break the idx==id invariant, both of which are somewhat invasive changes to the design. Bspec: 49202 Bspec: 49443 Bspec: 50288 Bspec: 50289 Cc: Lucas De Marchi Cc: José Roberto de Souza Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-4-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 41 +++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 6 ++-- 2 files changed, 40 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index aeb6ee395cce..134c2ecf4c80 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3504,13 +3504,19 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); - if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) + if (IS_ROCKETLAKE(dev_priv)) { dpll_mask = BIT(DPLL_ID_EHL_DPLL4) | BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); - else + } else if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A) { + dpll_mask = + BIT(DPLL_ID_EHL_DPLL4) | + BIT(DPLL_ID_ICL_DPLL1) | + BIT(DPLL_ID_ICL_DPLL0); + } else { dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); + } port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, @@ -3791,7 +3797,12 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv, if (!(val & PLL_ENABLE)) goto out; - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + hw_state->cfgcr0 = intel_de_read(dev_priv, + RKL_DPLL_CFGCR0(id)); + hw_state->cfgcr1 = intel_de_read(dev_priv, + RKL_DPLL_CFGCR1(id)); + } else if (INTEL_GEN(dev_priv) >= 12) { hw_state->cfgcr0 = intel_de_read(dev_priv, TGL_DPLL_CFGCR0(id)); hw_state->cfgcr1 = intel_de_read(dev_priv, @@ -3844,7 +3855,10 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv, const enum intel_dpll_id id = pll->info->id; i915_reg_t cfgcr0_reg, cfgcr1_reg; - if (INTEL_GEN(dev_priv) >= 12) { + if (IS_ROCKETLAKE(dev_priv)) { + cfgcr0_reg = RKL_DPLL_CFGCR0(id); + cfgcr1_reg = RKL_DPLL_CFGCR1(id); + } else if (INTEL_GEN(dev_priv) >= 12) { cfgcr0_reg = TGL_DPLL_CFGCR0(id); cfgcr1_reg = TGL_DPLL_CFGCR1(id); } else { @@ -4276,6 +4290,21 @@ static const struct intel_dpll_mgr tgl_pll_mgr = { .dump_hw_state = icl_dump_hw_state, }; +static const struct dpll_info rkl_plls[] = { + { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, + { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, + { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 }, + { }, +}; + +static const struct intel_dpll_mgr rkl_pll_mgr = { + .dpll_info = rkl_plls, + .get_dplls = icl_get_dplls, + .put_dplls = icl_put_dplls, + .update_ref_clks = icl_update_dpll_ref_clks, + .dump_hw_state = icl_dump_hw_state, +}; + /** * intel_shared_dpll_init - Initialize shared DPLLs * @dev: drm device @@ -4289,7 +4318,9 @@ void intel_shared_dpll_init(struct drm_device *dev) const struct dpll_info *dpll_info; int i; - if (INTEL_GEN(dev_priv) >= 12) + if (IS_ROCKETLAKE(dev_priv)) + dpll_mgr = &rkl_pll_mgr; + else if (INTEL_GEN(dev_priv) >= 12) dpll_mgr = &tgl_pll_mgr; else if (IS_ELKHARTLAKE(dev_priv)) dpll_mgr = &ehl_pll_mgr; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 00414c457941..bfdb6d23b5d8 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -10511,19 +10511,21 @@ enum skl_power_gate { #define _TGL_DPLL0_CFGCR0 0x164284 #define _TGL_DPLL1_CFGCR0 0x16428C -/* TODO: add DPLL4 */ #define _TGL_TBTPLL_CFGCR0 0x16429C #define TGL_DPLL_CFGCR0(pll) _MMIO_PLL3(pll, _TGL_DPLL0_CFGCR0, \ _TGL_DPLL1_CFGCR0, \ _TGL_TBTPLL_CFGCR0) +#define RKL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR0, \ + _TGL_DPLL1_CFGCR0) #define _TGL_DPLL0_CFGCR1 0x164288 #define _TGL_DPLL1_CFGCR1 0x164290 -/* TODO: add DPLL4 */ #define _TGL_TBTPLL_CFGCR1 0x1642A0 #define TGL_DPLL_CFGCR1(pll) _MMIO_PLL3(pll, _TGL_DPLL0_CFGCR1, \ _TGL_DPLL1_CFGCR1, \ _TGL_TBTPLL_CFGCR1) +#define RKL_DPLL_CFGCR1(pll) _MMIO_PLL(pll, _TGL_DPLL0_CFGCR1, \ + _TGL_DPLL1_CFGCR1) #define _DKL_PHY1_BASE 0x168000 #define _DKL_PHY2_BASE 0x169000 -- cgit v1.2.3 From ddff9a602e5e65e99ca6516151ee775560156697 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Jul 2020 15:05:50 -0700 Subject: drm/i915/rkl: Handle HTI If HTI (also sometimes called HDPORT) is enabled at startup, it may be using some of the PHYs and DPLLs making them unavailable for general usage. Let's read out the HDPORT_STATE register and avoid making use of resources that HTI is already using. v2: - Fix minor checkpatch warnings v3: - Just readout HDPORT_STATE register once during init and then parse it later as needed. - Add a 'has_hti' device info flag to track whether we should readout HDPORT_STATE or not. We can skip the platform/flag tests later since the hti_state in dev_priv will remain 0 for platforms it does not apply to. - Move PLL masking into icl_get_combo_phy_dpll() since at the moment RKL is the only platform that has HTI. (Jose) Bspec: 49189 Bspec: 53707 Cc: Lucas De Marchi Cc: José Roberto de Souza Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-5-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 11 +++++++++++ drivers/gpu/drm/i915/i915_drv.h | 8 ++++++++ drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_device_info.h | 1 + 7 files changed, 54 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1ca70f9abc8d..714b2bc96f23 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4923,6 +4923,13 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port) return max_lanes; } +static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy) +{ + return i915->hti_state & HDPORT_ENABLED && + (i915->hti_state & HDPORT_PHY_USED_DP(phy) || + i915->hti_state & HDPORT_PHY_USED_HDMI(phy)); +} + void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) { struct intel_digital_port *dig_port; @@ -4930,6 +4937,18 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) bool init_hdmi, init_dp, init_lspcon = false; enum phy phy = intel_port_to_phy(dev_priv, port); + /* + * On platforms with HTI (aka HDPORT), if it's enabled at boot it may + * have taken over some of the PHYs and made them unavailable to the + * driver. In that case we should skip initializing the corresponding + * outputs. + */ + if (hti_uses_phy(dev_priv, phy)) { + drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n", + port_name(port), phy_name(phy)); + return; + } + init_hdmi = intel_bios_port_supports_dvi(dev_priv, port) || intel_bios_port_supports_hdmi(dev_priv, port); init_dp = intel_bios_port_supports_dp(dev_priv, port); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6cb66580ad2c..db2a5a1a9b35 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -47,6 +47,7 @@ #include "display/intel_ddi.h" #include "display/intel_dp.h" #include "display/intel_dp_mst.h" +#include "display/intel_dpll_mgr.h" #include "display/intel_dsi.h" #include "display/intel_dvo.h" #include "display/intel_gmbus.h" @@ -17903,6 +17904,13 @@ int intel_modeset_init(struct drm_i915_private *i915) if (i915->max_cdclk_freq == 0) intel_update_max_cdclk(i915); + /* + * If the platform has HTI, we need to find out whether it has reserved + * any display resources before we create our display outputs. + */ + if (INTEL_INFO(i915)->display.has_hti) + i915->hti_state = intel_de_read(i915, HDPORT_STATE); + /* Just disable it once at startup */ intel_vga_disable(i915); intel_setup_outputs(i915); diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 134c2ecf4c80..81ab975fe4f0 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -3475,6 +3475,14 @@ static void icl_update_active_dpll(struct intel_atomic_state *state, icl_set_active_port_dpll(crtc_state, port_dpll_id); } +static u32 intel_get_hti_plls(struct drm_i915_private *i915) +{ + if (!(i915->hti_state & HDPORT_ENABLED)) + return 0; + + return REG_FIELD_GET(HDPORT_DPLL_USED_MASK, i915->hti_state); +} + static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, struct intel_crtc *crtc, struct intel_encoder *encoder) @@ -3518,6 +3526,9 @@ static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state, dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); } + /* Eliminate DPLLs from consideration if reserved by HTI */ + dpll_mask &= ~intel_get_hti_plls(dev_priv); + port_dpll->pll = intel_find_shared_dpll(state, crtc, &port_dpll->hw_state, dpll_mask); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e4f7f6518945..56dfc6d98caa 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1044,6 +1044,14 @@ struct drm_i915_private { struct intel_l3_parity l3_parity; + /* + * HTI (aka HDPORT) state read during initial hw readout. Most + * platforms don't have HTI, so this will just stay 0. Those that do + * will use this later to figure out which PLLs and PHYs are unavailable + * for driver usage. + */ + u32 hti_state; + /* * edram size in MB. * Cannot be determined by PCIID. You must always read a register. diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 2338f92ce490..366ddfc8df6b 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -890,6 +890,7 @@ static const struct intel_device_info rkl_info = { .cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C), .require_force_probe = 1, + .display.has_hti = 1, .display.has_psr_hw_tracking = 0, .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(VECS0) | BIT(VCS0), diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index bfdb6d23b5d8..89a9f2d8110e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2921,6 +2921,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define MBUS_BBOX_CTL_S1 _MMIO(0x45040) #define MBUS_BBOX_CTL_S2 _MMIO(0x45044) +#define HDPORT_STATE _MMIO(0x45050) +#define HDPORT_DPLL_USED_MASK REG_GENMASK(14, 12) +#define HDPORT_PHY_USED_DP(phy) REG_BIT(2 * (phy) + 2) +#define HDPORT_PHY_USED_HDMI(phy) REG_BIT(2 * (phy) + 1) +#define HDPORT_ENABLED REG_BIT(0) + /* Make render/texture TLB fetches lower priorty than associated data * fetches. This is not turned on by default */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index fd2385457ab6..6a3d607218aa 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -146,6 +146,7 @@ enum intel_ppgtt_type { func(has_gmch); \ func(has_hdcp); \ func(has_hotplug); \ + func(has_hti); \ func(has_ipc); \ func(has_modular_fia); \ func(has_overlay); \ -- cgit v1.2.3 From a3db3f8496bfa138cb7ddabde6baaf3d1beb01e2 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 16 Jul 2020 15:05:51 -0700 Subject: drm/i915/rkl: Add Wa_14011224835 for PHY B initialization After doing normal PHY-B initialization on Rocket Lake, we need to manually copy some additional PHY-A register values into PHY-B registers. Note that the bspec's combo phy page doesn't specify that this workaround is restricted to specific platform steppings (and doesn't even do a very good job of specifying that RKL is the only platform this is needed on), but the RKL workaround page lists this as relevant only for A and B steppings, so I'm trusting that information for now. v2: Make rkl_combo_phy_b_init_wa() static v3: - Minimize variables in WA function. (Jose) - Fix timeout duration (usec vs msec). (Jose) - Add verification of workaround. (Jose) - Fix stepping bounds in comment. Bspec: 49291 Bspec: 53273 Cc: José Roberto de Souza Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200716220551.2730644-6-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_combo_phy.c | 50 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 13 ++++++- 2 files changed, 62 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index eccaa79cb4a9..d88f91038428 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -255,6 +255,26 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) return phy == PHY_A; } +static bool verify_wa14011224835(struct drm_i915_private *i915) +{ + u32 grccode, val; + bool ret = true; + + grccode = REG_FIELD_GET(GRCCODE, + intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); + val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); + ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), + IREF_RCAL_ORD, val); + + grccode = REG_FIELD_GET(GRCCODE_LDO, + intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); + val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); + ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), + IREF_RCAL_ORD, val); + + return ret; +} + static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { @@ -295,6 +315,11 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy), CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE); + /* Wa_14011224835:rkl[a0..b0] */ + if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && + phy == PHY_B) + ret &= verify_wa14011224835(dev_priv); + return ret; } @@ -350,6 +375,26 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val); } +static void rkl_combo_phy_b_init_wa(struct drm_i915_private *i915) +{ + u32 grccode, val; + + wait_for_us(intel_de_read(i915, ICL_PORT_COMP_DW3(PHY_A)) & + FIRST_COMP_DONE, 100); + + grccode = REG_FIELD_GET(GRCCODE, + intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); + val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); + intel_de_rmw(i915, ICL_PORT_COMP_DW2(PHY_B), IREF_RCAL_ORD, + val | IREF_RCAL_ORD_EN); + + grccode = REG_FIELD_GET(GRCCODE_LDO, + intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); + val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); + intel_de_rmw(i915, ICL_PORT_COMP_DW6(PHY_B), RCOMPCODE_LD_CAP_OV, + val | RCOMPCODEOVEN_LDO_SYNC); +} + static void icl_combo_phys_init(struct drm_i915_private *dev_priv) { enum phy phy; @@ -415,6 +460,11 @@ skip_phy_misc: val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)); val |= CL_POWER_DOWN_ENABLE; intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy), val); + + if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && + phy == PHY_B) + /* Wa_14011224835:rkl[a0..b0] */ + rkl_combo_phy_b_init_wa(dev_priv); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 89a9f2d8110e..a0d31f3bf634 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1911,11 +1911,16 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define CNL_PORT_COMP_DW0 _MMIO(0x162100) #define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy)) -#define COMP_INIT (1 << 31) +#define COMP_INIT REG_BIT(31) +#define GRCCODE_LDO REG_GENMASK(7, 0) #define CNL_PORT_COMP_DW1 _MMIO(0x162104) #define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy)) +#define ICL_PORT_COMP_DW2(phy) _MMIO(_ICL_PORT_COMP_DW(2, phy)) +#define IREF_RCAL_ORD_EN REG_BIT(7) +#define IREF_RCAL_ORD REG_GENMASK(6, 0) + #define CNL_PORT_COMP_DW3 _MMIO(0x16210c) #define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy)) #define PROCESS_INFO_DOT_0 (0 << 26) @@ -1928,6 +1933,12 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VOLTAGE_INFO_1_05V (2 << 24) #define VOLTAGE_INFO_MASK (3 << 24) #define VOLTAGE_INFO_SHIFT 24 +#define FIRST_COMP_DONE REG_BIT(22) + +#define ICL_PORT_COMP_DW6(phy) _MMIO(_ICL_PORT_COMP_DW(6, phy)) +#define GRCCODE REG_GENMASK(30, 24) +#define RCOMPCODEOVEN_LDO_SYNC REG_BIT(23) +#define RCOMPCODE_LD_CAP_OV REG_GENMASK(22, 16) #define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy)) #define IREFGEN (1 << 24) -- cgit v1.2.3 From 90e1329296fda234669ff97c12e39816b948de72 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 23 Jul 2020 16:38:05 +0100 Subject: drm/i915/selftests: Downgrade severity of CS/SRM frequency scaling tests Gracefully skip over the failures in the frequency scaling for the moment, the results are under review. References: https://gitlab.freedesktop.org/drm/intel/-/issues/1754 Signed-off-by: Chris Wilson Cc: "Sundaresan, Sujaritha" Cc: "Ewins, Jon" Reviewed-by: Sujaritha Sundaresan Link: https://patchwork.freedesktop.org/patch/msgid/20200723153805.8076-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/selftest_rps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 8624f5d2a1f3..34b403d47840 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -700,7 +700,7 @@ int live_rps_frequency_cs(void *arg) f = act; /* may skip ahead [pcu granularity] */ } - err = -EINVAL; + err = -EINTR; /* ignore error, continue on with test */ } err_vma: @@ -841,7 +841,7 @@ int live_rps_frequency_srm(void *arg) f = act; /* may skip ahead [pcu granularity] */ } - err = -EINVAL; + err = -EINTR; /* ignore error, continue on with test */ } err_vma: -- cgit v1.2.3 From c746063ab14644592abfb61be3486989ff990cea Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 27 Jul 2020 09:47:29 -0700 Subject: drm/i915: Implement WA 14011294188 Although the WA description targets the platforms it is a workaround for the affected PCHs, that is why it is being checked. v2: excluding DG1 fake PCH from WA BSpec: 52890 BSpec: 53273 BSpec: 52888 Reviewed-by: Matt Roper Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200727164729.28836-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_power.c | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0c713e83274d..788bd4516365 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5302,6 +5302,12 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, gen9_set_dc_state(dev_priv, DC_STATE_DISABLE); + /* Wa_14011294188:ehl,jsl,tgl,rkl */ + if (INTEL_PCH_TYPE(dev_priv) >= PCH_JSP && + INTEL_PCH_TYPE(dev_priv) < PCH_DG1) + intel_de_rmw(dev_priv, SOUTH_DSPCLK_GATE_D, 0, + PCH_DPMGUNIT_CLOCK_GATE_DISABLE); + /* 1. Enable PCH reset handshake. */ intel_pch_reset_handshake(dev_priv, !HAS_PCH_NOP(dev_priv)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index a0d31f3bf634..5eae593ee784 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8730,6 +8730,7 @@ enum { #define PCH_GMBUSUNIT_CLOCK_GATE_DISABLE (1 << 31) #define PCH_DPLUNIT_CLOCK_GATE_DISABLE (1 << 30) #define PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1 << 29) +#define PCH_DPMGUNIT_CLOCK_GATE_DISABLE (1 << 15) #define PCH_CPUNIT_CLOCK_GATE_DISABLE (1 << 14) #define CNP_PWM_CGE_GATING_DISABLE (1 << 13) #define PCH_LP_PARTITION_LEVEL_DISABLE (1 << 12) -- cgit v1.2.3 From 2982ded2ff5ce0cf1a49bc39a526da182782b664 Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Thu, 16 Jul 2020 20:28:57 +0530 Subject: drm/i915/display/fbc: Disable fbc by default on TGL Fbc is causing random underruns in CI execution on TGL platforms. Disabling the same while the problem is being debugged and analyzed. v2: Moved the check below the module param check (Ville) Cc: Stanislav Lisovskiy Cc: Ville Syrjälä Signed-off-by: Uma Shankar Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200716145857.6911-1-uma.shankar@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_fbc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 3a4f980788a6..195b8be4532a 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1426,6 +1426,13 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) if (!HAS_FBC(dev_priv)) return 0; + /* + * Fbc is causing random underruns in CI execution on TGL platforms. + * Disabling the same while the problem is being debugged and analyzed. + */ + if (IS_TIGERLAKE(dev_priv)) + return 0; + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) return 1; -- cgit v1.2.3 From 98ef067453709444a264939940f7b3a5dfdfa09e Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:06:00 +0100 Subject: drm/i915: Copy default modparams to mock i915_device Since we use the module parameters stored inside the drm_i915_device itself, we need to ensure the mock i915_device also sets up the right defaults. Fixes: 8a25c4be583d ("drm/i915/params: switch to device specific parameters") Signed-off-by: Chris Wilson Cc: Jani Nikula Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200728150600.4509-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 9a46be05425a..ce4d4303229c 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -77,6 +77,7 @@ static void mock_device_release(struct drm_device *dev) drm_mode_config_cleanup(&i915->drm); out: + i915_params_free(&i915->params); put_device(&i915->drm.pdev->dev); i915->drm.pdev = NULL; } @@ -159,6 +160,8 @@ struct drm_i915_private *mock_gem_device(void) i915->drm.pdev = pdev; drmm_add_final_kfree(&i915->drm, i915); + i915_params_copy(&i915->params, &i915_modparams); + intel_runtime_pm_init_early(&i915->runtime_pm); /* Using the global GTT may ask questions about KMS users, so prepare */ -- cgit v1.2.3 From e310b4352cf471ba73119ec31abb1ef72086824d Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:21:10 +0100 Subject: drm/i915/selftests: Add compiler paranoia for checking HWSP values Since we want to read the values from the HWSP as written to by the GPU, warn the compiler that the values are volatile. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200728152110.830-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/selftest_timeline.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index fb5b7d3498a6..6564c989dbee 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -491,7 +491,7 @@ checked_intel_timeline_create(struct intel_gt *gt) if (IS_ERR(tl)) return tl; - if (*tl->hwsp_seqno != tl->seqno) { + if (READ_ONCE(*tl->hwsp_seqno) != tl->seqno) { pr_err("Timeline created with incorrect breadcrumb, found %x, expected %x\n", *tl->hwsp_seqno, tl->seqno); intel_timeline_put(tl); @@ -561,9 +561,9 @@ static int live_hwsp_engine(void *arg) for (n = 0; n < count; n++) { struct intel_timeline *tl = timelines[n]; - if (!err && *tl->hwsp_seqno != n) { - pr_err("Invalid seqno stored in timeline %lu @ %x, found 0x%x\n", - n, tl->hwsp_offset, *tl->hwsp_seqno); + if (!err && READ_ONCE(*tl->hwsp_seqno) != n) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x, found 0x%x\n", + n, tl->fence_context, tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } @@ -633,9 +633,9 @@ out: for (n = 0; n < count; n++) { struct intel_timeline *tl = timelines[n]; - if (!err && *tl->hwsp_seqno != n) { - pr_err("Invalid seqno stored in timeline %lu @ %x, found 0x%x\n", - n, tl->hwsp_offset, *tl->hwsp_seqno); + if (!err && READ_ONCE(*tl->hwsp_seqno) != n) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x, found 0x%x\n", + n, tl->fence_context, tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } @@ -733,7 +733,8 @@ static int live_hwsp_wrap(void *arg) goto out; } - if (*hwsp_seqno[0] != seqno[0] || *hwsp_seqno[1] != seqno[1]) { + if (READ_ONCE(*hwsp_seqno[0]) != seqno[0] || + READ_ONCE(*hwsp_seqno[1]) != seqno[1]) { pr_err("Bad timeline values: found (%x, %x), expected (%x, %x)\n", *hwsp_seqno[0], *hwsp_seqno[1], seqno[0], seqno[1]); @@ -966,9 +967,10 @@ static int live_hwsp_recycle(void *arg) break; } - if (*tl->hwsp_seqno != count) { - pr_err("Invalid seqno stored in timeline %lu @ tl->hwsp_offset, found 0x%x\n", - count, *tl->hwsp_seqno); + if (READ_ONCE(*tl->hwsp_seqno) != count) { + GEM_TRACE_ERR("Invalid seqno:%lu stored in timeline %llu @ %x found 0x%x\n", + count, tl->fence_context, + tl->hwsp_offset, *tl->hwsp_seqno); GEM_TRACE_DUMP(); err = -EINVAL; } -- cgit v1.2.3 From 1840d40ac690e2ad60fa52fc3156249802e27aa9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:22:19 +0100 Subject: drm/i915: Remove gen check before calling intel_rps_boost It's been a while since gen6_rps_boost() [that only worked on gen6+] was replaced by intel_rps_boost() that understood itself when rps was active. Since the intel_rps_boost() is gen-agnostic, just call it. Signed-off-by: Chris Wilson Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200728152219.1387-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_request.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 0b2fe55e6194..7a05850ca931 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1783,11 +1783,8 @@ long i915_request_wait(struct i915_request *rq, * but at a cost of spending more power processing the workload * (bad for battery). */ - if (flags & I915_WAIT_PRIORITY) { - if (!i915_request_started(rq) && - INTEL_GEN(rq->engine->i915) >= 6) - intel_rps_boost(rq); - } + if (flags & I915_WAIT_PRIORITY && !i915_request_started(rq)) + intel_rps_boost(rq); wait.tsk = current; if (dma_fence_add_callback(&rq->fence, &wait.cb, request_wait_wake)) -- cgit v1.2.3 From a22b1a9bb0d72a58d5b836653f28d97ee8fea1c4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 14:09:12 +0100 Subject: drm/i915/display: Check for an LPSP encoder before dereferencing Avoid a GPF at <1>[ 20.177320] BUG: kernel NULL pointer dereference, address: 000000000000007c <1>[ 20.177322] #PF: supervisor read access in kernel mode <1>[ 20.177323] #PF: error_code(0x0000) - not-present page <6>[ 20.177324] PGD 0 P4D 0 <4>[ 20.177327] Oops: 0000 [#1] PREEMPT SMP PTI <4>[ 20.177328] CPU: 1 PID: 944 Comm: debugfs_test Not tainted 5.8.0-rc7-CI-CI_DRM_8814+ #1 <4>[ 20.177330] Hardware name: Dell Inc. XPS 13 9360/0823VW, BIOS 2.9.0 07/09/2018 <4>[ 20.177372] RIP: 0010:i915_lpsp_capability_show+0x44/0xc0 [i915] <4>[ 20.177374] Code: 0f b6 81 ca 0d 00 00 3c 0b 74 77 76 19 3c 0c 75 44 83 7e 7c 01 7e 2f 48 c7 c6 d7 b9 47 a0 e8 43 df 06 e1 31 c0 c3 3c 09 72 2b <8b> 46 7c 85 c0 75 e6 8b 82 e4 00 00 00 89 c2 83 e2 fb 83 fa 0a 74 <4>[ 20.177376] RSP: 0018:ffffc90000cebe38 EFLAGS: 00010246 <4>[ 20.177377] RAX: 0000000000000009 RBX: ffff888267fe6a58 RCX: ffff888252d10000 <4>[ 20.177378] RDX: ffff88824a9a4000 RSI: 0000000000000000 RDI: ffff888267fe6a30 <4>[ 20.177379] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001 <4>[ 20.177380] R10: 0000000000000001 R11: 0000000000000000 R12: ffffc90000cebf08 <4>[ 20.177381] R13: 00000000ffffffff R14: 0000000000000001 R15: ffff888267fe6a30 <4>[ 20.177383] FS: 00007f6f9c6b5e40(0000) GS:ffff888276480000(0000) knlGS:0000000000000000 <4>[ 20.177384] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 20.177385] CR2: 000000000000007c CR3: 0000000255f04006 CR4: 00000000003606e0 <4>[ 20.177386] Call Trace: <4>[ 20.177390] seq_read+0xcb/0x420 which is presumably from having no encoder attached at that time. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2175 Fixes: 8806211fe7b3 ("drm/i915: Add i915_lpsp_capability debugfs") Signed-off-by: Chris Wilson Cc: Animesh Manna Cc: Anshuman Gupta Cc: Uma Shankar Cc: "Ville Syrjälä" Reviewed-by: Anshuman Gupta Link: https://patchwork.freedesktop.org/patch/msgid/20200729130912.30093-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3644752cc5ec..5a5cfe25085b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -2044,9 +2044,12 @@ DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability); static int i915_lpsp_capability_show(struct seq_file *m, void *data) { struct drm_connector *connector = m->private; - struct intel_encoder *encoder = - intel_attached_encoder(to_intel_connector(connector)); struct drm_i915_private *i915 = to_i915(connector->dev); + struct intel_encoder *encoder; + + encoder = intel_attached_encoder(to_intel_connector(connector)); + if (!encoder) + return -ENODEV; if (connector->status != connector_status_connected) return -ENODEV; -- cgit v1.2.3 From 9a0a3bebb0c5885784a048a65f4661a2464cc920 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:09 +0100 Subject: drm/i915: Add a couple of missing i915_active_fini() We use i915_active_fini() as a debug check on the i915_active state before freeing. If we forget to call it, we may end up angering the debugobjects contained within. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_frontbuffer.c | 2 ++ drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c index 2979ed2588eb..d898b370d7a4 100644 --- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c +++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c @@ -232,6 +232,8 @@ static void frontbuffer_release(struct kref *ref) RCU_INIT_POINTER(obj->frontbuffer, NULL); spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock); + i915_active_fini(&front->write); + i915_gem_object_put(obj); kfree_rcu(front, rcu); } diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c index 73243ba59c7d..e73854dd2fe0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c +++ b/drivers/gpu/drm/i915/gt/selftest_engine_heartbeat.c @@ -47,7 +47,10 @@ static int pulse_active(struct i915_active *active) static void pulse_free(struct kref *kref) { - kfree(container_of(kref, struct pulse, kref)); + struct pulse *p = container_of(kref, typeof(*p), kref); + + i915_active_fini(&p->active); + kfree(p); } static void pulse_put(struct pulse *p) -- cgit v1.2.3 From ecb40d0826fda213ebb58d49e7d5b4752480e130 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 12 Jun 2020 13:47:34 -0700 Subject: drm/i915: Update bw_buddy pagemask table A recent bspec update removed the LPDDR4 single channel entry from the buddy register table, but added a new four-channel entry. Workaround 1409767108 hasn't been updated with any guidance for four channel configurations, so we leave that alternate table unchanged for now. Bspec 49218 Fixes: 3fa01d642fa7 ("drm/i915/tgl: Program BW_BUDDY registers during display init") Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200612204734.3674650-1-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 788bd4516365..9f0241a53a45 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5240,10 +5240,10 @@ struct buddy_page_mask { }; static const struct buddy_page_mask tgl_buddy_page_masks[] = { - { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0xE }, { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0xF }, { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1C }, { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x1F }, + { .num_channels = 4, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x38 }, {} }; -- cgit v1.2.3 From e714977eef8fb40ea8234527d1b0c9d238bf1661 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Sun, 2 Aug 2020 12:56:55 +0100 Subject: drm/i915: Fix wrong return value In function i915_active_acquire_preallocate_barrier(), not all paths have the return value set correctly, and in case of memory allocation failure, a negative error code should be returned. Cc: Chris Wilson Signed-off-by: Tianjia Zhang Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200802115655.25568-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_active.c | 7 ++----- drivers/gpu/drm/i915/selftests/i915_request.c | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index d960d0be5bd2..1e1253207425 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -758,7 +758,6 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, intel_engine_mask_t tmp, mask = engine->mask; struct llist_node *first = NULL, *last = NULL; struct intel_gt *gt = engine->gt; - int err; GEM_BUG_ON(i915_active_is_idle(ref)); @@ -781,10 +780,8 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, node = reuse_idle_barrier(ref, idx); if (!node) { node = kmem_cache_alloc(global.slab_cache, GFP_KERNEL); - if (!node) { - err = ENOMEM; + if (!node) goto unwind; - } RCU_INIT_POINTER(node->base.fence, NULL); node->base.cb.func = node_retire; @@ -832,7 +829,7 @@ unwind: kmem_cache_free(global.slab_cache, node); } - return err; + return -ENOMEM; } void i915_active_acquire_barrier(struct i915_active *ref) diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index 57dd6f5122ee..c1dcd4b91bda 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -331,7 +331,7 @@ static int __igt_breadcrumbs_smoketest(void *arg) if (!wait) { i915_sw_fence_commit(submit); heap_fence_put(submit); - err = ENOMEM; + err = -ENOMEM; break; } -- cgit v1.2.3 From 66b51b801d05ee54a0f23628cb8220189adb715e Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Sun, 2 Aug 2020 19:15:35 +0800 Subject: drm/i915: Fix wrong return value in intel_atomic_check() In the case of calling check_digital_port_conflicts() failed, a negative error code -EINVAL should be returned. Fixes: bf5da83e4bd80 ("drm/i915: Move check_digital_port_conflicts() earier") Cc: Ville Syrjälä Signed-off-by: Tianjia Zhang Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200802111535.5200-1-tianjia.zhang@linux.alibaba.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index db2a5a1a9b35..522c772a2111 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14940,7 +14940,7 @@ static int intel_atomic_check(struct drm_device *dev, if (any_ms && !check_digital_port_conflicts(state)) { drm_dbg_kms(&dev_priv->drm, "rejecting conflicting digital port configuration\n"); - ret = EINVAL; + ret = -EINVAL; goto fail; } -- cgit v1.2.3 From 3f8210fd22d0c02faa18b36974debf1ad25b7f92 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 3 Aug 2020 21:40:24 -0700 Subject: Revert "drm/i915/rkl: Add Wa_14011224835 for PHY B initialization" The hardware team has dropped this workaround from the bspec; it is no longer needed. This reverts commit 111822b21be995a3a4a731066db3d820523c57f7. Bspec: 49291 Cc: José Roberto de Souza Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200804044024.1931170-1-matthew.d.roper@intel.com Reviewed-by: José Roberto de Souza Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_combo_phy.c | 50 -------------------------- drivers/gpu/drm/i915/i915_reg.h | 13 +------ 2 files changed, 1 insertion(+), 62 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index d88f91038428..eccaa79cb4a9 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -255,26 +255,6 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) return phy == PHY_A; } -static bool verify_wa14011224835(struct drm_i915_private *i915) -{ - u32 grccode, val; - bool ret = true; - - grccode = REG_FIELD_GET(GRCCODE, - intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); - val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); - ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), - IREF_RCAL_ORD, val); - - grccode = REG_FIELD_GET(GRCCODE_LDO, - intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); - val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); - ret &= check_phy_reg(i915, PHY_B, ICL_PORT_COMP_DW2(PHY_B), - IREF_RCAL_ORD, val); - - return ret; -} - static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { @@ -315,11 +295,6 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, ret &= check_phy_reg(dev_priv, phy, ICL_PORT_CL_DW5(phy), CL_POWER_DOWN_ENABLE, CL_POWER_DOWN_ENABLE); - /* Wa_14011224835:rkl[a0..b0] */ - if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && - phy == PHY_B) - ret &= verify_wa14011224835(dev_priv); - return ret; } @@ -375,26 +350,6 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, intel_de_write(dev_priv, ICL_PORT_CL_DW10(phy), val); } -static void rkl_combo_phy_b_init_wa(struct drm_i915_private *i915) -{ - u32 grccode, val; - - wait_for_us(intel_de_read(i915, ICL_PORT_COMP_DW3(PHY_A)) & - FIRST_COMP_DONE, 100); - - grccode = REG_FIELD_GET(GRCCODE, - intel_de_read(i915, ICL_PORT_COMP_DW6(PHY_A))); - val = REG_FIELD_PREP(IREF_RCAL_ORD, grccode); - intel_de_rmw(i915, ICL_PORT_COMP_DW2(PHY_B), IREF_RCAL_ORD, - val | IREF_RCAL_ORD_EN); - - grccode = REG_FIELD_GET(GRCCODE_LDO, - intel_de_read(i915, ICL_PORT_COMP_DW0(PHY_A))); - val = REG_FIELD_PREP(RCOMPCODE_LD_CAP_OV, grccode); - intel_de_rmw(i915, ICL_PORT_COMP_DW6(PHY_B), RCOMPCODE_LD_CAP_OV, - val | RCOMPCODEOVEN_LDO_SYNC); -} - static void icl_combo_phys_init(struct drm_i915_private *dev_priv) { enum phy phy; @@ -460,11 +415,6 @@ skip_phy_misc: val = intel_de_read(dev_priv, ICL_PORT_CL_DW5(phy)); val |= CL_POWER_DOWN_ENABLE; intel_de_write(dev_priv, ICL_PORT_CL_DW5(phy), val); - - if (IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_B0) && - phy == PHY_B) - /* Wa_14011224835:rkl[a0..b0] */ - rkl_combo_phy_b_init_wa(dev_priv); } } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5eae593ee784..2b403df03404 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1911,16 +1911,11 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define CNL_PORT_COMP_DW0 _MMIO(0x162100) #define ICL_PORT_COMP_DW0(phy) _MMIO(_ICL_PORT_COMP_DW(0, phy)) -#define COMP_INIT REG_BIT(31) -#define GRCCODE_LDO REG_GENMASK(7, 0) +#define COMP_INIT (1 << 31) #define CNL_PORT_COMP_DW1 _MMIO(0x162104) #define ICL_PORT_COMP_DW1(phy) _MMIO(_ICL_PORT_COMP_DW(1, phy)) -#define ICL_PORT_COMP_DW2(phy) _MMIO(_ICL_PORT_COMP_DW(2, phy)) -#define IREF_RCAL_ORD_EN REG_BIT(7) -#define IREF_RCAL_ORD REG_GENMASK(6, 0) - #define CNL_PORT_COMP_DW3 _MMIO(0x16210c) #define ICL_PORT_COMP_DW3(phy) _MMIO(_ICL_PORT_COMP_DW(3, phy)) #define PROCESS_INFO_DOT_0 (0 << 26) @@ -1933,12 +1928,6 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VOLTAGE_INFO_1_05V (2 << 24) #define VOLTAGE_INFO_MASK (3 << 24) #define VOLTAGE_INFO_SHIFT 24 -#define FIRST_COMP_DONE REG_BIT(22) - -#define ICL_PORT_COMP_DW6(phy) _MMIO(_ICL_PORT_COMP_DW(6, phy)) -#define GRCCODE REG_GENMASK(30, 24) -#define RCOMPCODEOVEN_LDO_SYNC REG_BIT(23) -#define RCOMPCODE_LD_CAP_OV REG_GENMASK(22, 16) #define ICL_PORT_COMP_DW8(phy) _MMIO(_ICL_PORT_COMP_DW(8, phy)) #define IREFGEN (1 << 24) -- cgit v1.2.3 From cda9edd02425d7902714c60a6f6e31881d2f2741 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 4 Aug 2020 11:59:53 +0300 Subject: drm/i915: introduce a mechanism to extend execbuf2 We're planning to use this for a couple of new feature where we need to provide additional parameters to execbuf. v2: Check for invalid flags in execbuffer2 (Lionel) v3: Rename I915_EXEC_EXT -> I915_EXEC_USE_EXTENSIONS (Chris) v4: Rebase Move array fence parsing in i915_gem_do_execbuffer() Signed-off-by: Lionel Landwerlin Reviewed-by: Daniel Vetter Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200804085954.350343-2-lionel.g.landwerlin@intel.com Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2901 Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 131 +++++++++++++++---------- include/uapi/drm/i915_drm.h | 25 ++++- 2 files changed, 102 insertions(+), 54 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 6b4ec66cb558..09d2f955b11e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -26,6 +26,7 @@ #include "i915_gem_ioctls.h" #include "i915_sw_fence_work.h" #include "i915_trace.h" +#include "i915_user_extensions.h" struct eb_vma { struct i915_vma *vma; @@ -281,6 +282,13 @@ struct i915_execbuffer { int lut_size; struct hlist_head *buckets; /** ht for relocation handles */ struct eb_vma_array *array; + + struct i915_eb_fence { + struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ + } *fences; + u32 n_fences; + + u64 extension_flags; /** Available extensions parameters */ }; static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) @@ -1622,7 +1630,8 @@ static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec) return -EINVAL; /* Kernel clipping was a DRI1 misfeature */ - if (!(exec->flags & I915_EXEC_FENCE_ARRAY)) { + if (!(exec->flags & (I915_EXEC_FENCE_ARRAY | + I915_EXEC_USE_EXTENSIONS))) { if (exec->num_cliprects || exec->cliprects_ptr) return -EINVAL; } @@ -2201,41 +2210,41 @@ eb_pin_engine(struct i915_execbuffer *eb, } static void -__free_fence_array(struct drm_syncobj **fences, unsigned int n) +__free_fence_array(struct i915_eb_fence *fences, unsigned int n) { while (n--) - drm_syncobj_put(ptr_mask_bits(fences[n], 2)); + drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2)); kvfree(fences); } -static struct drm_syncobj ** +static int get_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct drm_file *file) + struct i915_execbuffer *eb) { const unsigned long nfences = args->num_cliprects; struct drm_i915_gem_exec_fence __user *user; - struct drm_syncobj **fences; + struct i915_eb_fence *fences; unsigned long n; int err; if (!(args->flags & I915_EXEC_FENCE_ARRAY)) - return NULL; + return 0; /* Check multiplication overflow for access_ok() and kvmalloc_array() */ BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); if (nfences > min_t(unsigned long, ULONG_MAX / sizeof(*user), SIZE_MAX / sizeof(*fences))) - return ERR_PTR(-EINVAL); + return -EINVAL; user = u64_to_user_ptr(args->cliprects_ptr); if (!access_ok(user, nfences * sizeof(*user))) - return ERR_PTR(-EFAULT); + return -EFAULT; fences = kvmalloc_array(nfences, sizeof(*fences), __GFP_NOWARN | GFP_KERNEL); if (!fences) - return ERR_PTR(-ENOMEM); + return -ENOMEM; for (n = 0; n < nfences; n++) { struct drm_i915_gem_exec_fence fence; @@ -2251,7 +2260,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args, goto err; } - syncobj = drm_syncobj_find(file, fence.handle); + syncobj = drm_syncobj_find(eb->file, fence.handle); if (!syncobj) { DRM_DEBUG("Invalid syncobj handle provided\n"); err = -ENOENT; @@ -2261,38 +2270,31 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args, BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); - fences[n] = ptr_pack_bits(syncobj, fence.flags, 2); + fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2); } - return fences; + eb->fences = fences; + eb->n_fences = nfences; + + return 0; err: __free_fence_array(fences, n); - return ERR_PTR(err); -} - -static void -put_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct drm_syncobj **fences) -{ - if (fences) - __free_fence_array(fences, args->num_cliprects); + return err; } static int -await_fence_array(struct i915_execbuffer *eb, - struct drm_syncobj **fences) +await_fence_array(struct i915_execbuffer *eb) { - const unsigned int nfences = eb->args->num_cliprects; unsigned int n; int err; - for (n = 0; n < nfences; n++) { + for (n = 0; n < eb->n_fences; n++) { struct drm_syncobj *syncobj; struct dma_fence *fence; unsigned int flags; - syncobj = ptr_unpack_bits(fences[n], &flags, 2); + syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); if (!(flags & I915_EXEC_FENCE_WAIT)) continue; @@ -2310,18 +2312,16 @@ await_fence_array(struct i915_execbuffer *eb, } static void -signal_fence_array(struct i915_execbuffer *eb, - struct drm_syncobj **fences) +signal_fence_array(struct i915_execbuffer *eb) { - const unsigned int nfences = eb->args->num_cliprects; struct dma_fence * const fence = &eb->request->fence; unsigned int n; - for (n = 0; n < nfences; n++) { + for (n = 0; n < eb->n_fences; n++) { struct drm_syncobj *syncobj; unsigned int flags; - syncobj = ptr_unpack_bits(fences[n], &flags, 2); + syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); if (!(flags & I915_EXEC_FENCE_SIGNAL)) continue; @@ -2370,12 +2370,38 @@ static void eb_request_add(struct i915_execbuffer *eb) mutex_unlock(&tl->mutex); } +static const i915_user_extension_fn execbuf_extensions[] = { +}; + +static int +parse_execbuf2_extensions(struct drm_i915_gem_execbuffer2 *args, + struct i915_execbuffer *eb) +{ + eb->extension_flags = 0; + + if (!(args->flags & I915_EXEC_USE_EXTENSIONS)) + return 0; + + /* The execbuf2 extension mechanism reuses cliprects_ptr. So we cannot + * have another flag also using it at the same time. + */ + if (eb->args->flags & I915_EXEC_FENCE_ARRAY) + return -EINVAL; + + if (args->num_cliprects != 0) + return -EINVAL; + + return i915_user_extensions(u64_to_user_ptr(args->cliprects_ptr), + execbuf_extensions, + ARRAY_SIZE(execbuf_extensions), + eb); +} + static int i915_gem_do_execbuffer(struct drm_device *dev, struct drm_file *file, struct drm_i915_gem_execbuffer2 *args, - struct drm_i915_gem_exec_object2 *exec, - struct drm_syncobj **fences) + struct drm_i915_gem_exec_object2 *exec) { struct drm_i915_private *i915 = to_i915(dev); struct i915_execbuffer eb; @@ -2405,6 +2431,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.batch_len = args->batch_len; eb.trampoline = NULL; + eb.fences = NULL; + eb.n_fences = 0; + eb.batch_flags = 0; if (args->flags & I915_EXEC_SECURE) { if (INTEL_GEN(i915) >= 11) @@ -2441,10 +2470,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, } } - err = eb_create(&eb); + err = parse_execbuf2_extensions(args, &eb); if (err) goto err_out_fence; + err = get_fence_array(args, &eb); + if (err) + goto err_arr_fence; + + err = eb_create(&eb); + if (err) + goto err_arr_fence; + GEM_BUG_ON(!eb.lut_size); err = eb_select_context(&eb); @@ -2539,8 +2576,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_request; } - if (fences) { - err = await_fence_array(&eb, fences); + if (eb.n_fences) { + err = await_fence_array(&eb); if (err) goto err_request; } @@ -2571,8 +2608,8 @@ err_request: i915_request_get(eb.request); eb_request_add(&eb); - if (fences) - signal_fence_array(&eb, fences); + if (eb.n_fences) + signal_fence_array(&eb); if (out_fence) { if (err == 0) { @@ -2600,6 +2637,8 @@ err_context: i915_gem_context_put(eb.gem_context); err_destroy: eb_destroy(&eb); +err_arr_fence: + __free_fence_array(eb.fences, eb.n_fences); err_out_fence: if (out_fence_fd != -1) put_unused_fd(out_fence_fd); @@ -2699,7 +2738,7 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, exec2_list[i].flags = 0; } - err = i915_gem_do_execbuffer(dev, file, &exec2, exec2_list, NULL); + err = i915_gem_do_execbuffer(dev, file, &exec2, exec2_list); if (exec2.flags & __EXEC_HAS_RELOC) { struct drm_i915_gem_exec_object __user *user_exec_list = u64_to_user_ptr(args->buffers_ptr); @@ -2731,7 +2770,6 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, struct drm_i915_private *i915 = to_i915(dev); struct drm_i915_gem_execbuffer2 *args = data; struct drm_i915_gem_exec_object2 *exec2_list; - struct drm_syncobj **fences = NULL; const size_t count = args->buffer_count; int err; @@ -2759,15 +2797,7 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, return -EFAULT; } - if (args->flags & I915_EXEC_FENCE_ARRAY) { - fences = get_fence_array(args, file); - if (IS_ERR(fences)) { - kvfree(exec2_list); - return PTR_ERR(fences); - } - } - - err = i915_gem_do_execbuffer(dev, file, args, exec2_list, fences); + err = i915_gem_do_execbuffer(dev, file, args, exec2_list); /* * Now that we have begun execution of the batchbuffer, we ignore @@ -2808,7 +2838,6 @@ end:; } args->flags &= ~__I915_EXEC_UNKNOWN_FLAGS; - put_fence_array(args, fences); kvfree(exec2_list); return err; } diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 00546062e023..dcada8c3a693 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -1046,6 +1046,10 @@ struct drm_i915_gem_exec_fence { __u32 flags; }; +enum drm_i915_gem_execbuffer_ext { + DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */ +}; + struct drm_i915_gem_execbuffer2 { /** * List of gem_exec_object2 structs @@ -1062,8 +1066,14 @@ struct drm_i915_gem_execbuffer2 { __u32 num_cliprects; /** * This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY - * is not set. If I915_EXEC_FENCE_ARRAY is set, then this is a - * struct drm_i915_gem_exec_fence *fences. + * & I915_EXEC_USE_EXTENSIONS are not set. + * + * If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array + * of struct drm_i915_gem_exec_fence and num_cliprects is the length + * of the array. + * + * If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a + * single struct i915_user_extension and num_cliprects is 0. */ __u64 cliprects_ptr; #define I915_EXEC_RING_MASK (0x3f) @@ -1181,7 +1191,16 @@ struct drm_i915_gem_execbuffer2 { */ #define I915_EXEC_FENCE_SUBMIT (1 << 20) -#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SUBMIT << 1)) +/* + * Setting I915_EXEC_USE_EXTENSIONS implies that + * drm_i915_gem_execbuffer2.cliprects_ptr is treated as a pointer to an linked + * list of i915_user_extension. Each i915_user_extension node is the base of a + * larger structure. The list of supported structures are listed in the + * drm_i915_gem_execbuffer_ext enum. + */ +#define I915_EXEC_USE_EXTENSIONS (1 << 21) + +#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1)) #define I915_EXEC_CONTEXT_ID_MASK (0xffffffff) #define i915_execbuffer2_set_context_id(eb2, context) \ -- cgit v1.2.3 From 13149e8bafc4657254831ba6c16ed8780aa64a06 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Tue, 4 Aug 2020 11:59:54 +0300 Subject: drm/i915: add syncobj timeline support Introduces a new parameters to execbuf so that we can specify syncobj handles as well as timeline points. v2: Reuse i915_user_extension_fn v3: Check that the chained extension is only present once (Chris) v4: Check that dma_fence_chain_find_seqno returns a non NULL fence (Lionel) v5: Use BIT_ULL (Chris) v6: Fix issue with already signaled timeline points, dma_fence_chain_find_seqno() setting fence to NULL (Chris) v7: Report ENOENT with invalid syncobj handle (Lionel) v8: Check for out of order timeline point insertion (Chris) v9: After explanations on https://lists.freedesktop.org/archives/dri-devel/2019-August/229287.html drop the ordering check from v8 (Lionel) v10: Set first extension enum item to 1 (Jason) v11: Rebase v12: Allow multiple extension nodes of timeline syncobj (Chris) Signed-off-by: Lionel Landwerlin Co-authored-by: Chris Wilson Reviewed-by: Daniel Vetter (v11) Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200804085954.350343-3-lionel.g.landwerlin@intel.com Link: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2901 Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 312 +++++++++++++++++++------ drivers/gpu/drm/i915/i915_drv.c | 3 +- drivers/gpu/drm/i915/i915_getparam.c | 1 + include/uapi/drm/i915_drm.h | 38 ++- 4 files changed, 279 insertions(+), 75 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 09d2f955b11e..02b1630f513e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -223,6 +223,13 @@ struct eb_vma_array { * the batchbuffer in trusted mode, otherwise the ioctl is rejected. */ +struct eb_fence { + struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ + struct dma_fence *dma_fence; + u64 value; + struct dma_fence_chain *chain_fence; +}; + struct i915_execbuffer { struct drm_i915_private *i915; /** i915 backpointer */ struct drm_file *file; /** per-file lookup tables and limits */ @@ -283,12 +290,8 @@ struct i915_execbuffer { struct hlist_head *buckets; /** ht for relocation handles */ struct eb_vma_array *array; - struct i915_eb_fence { - struct drm_syncobj *syncobj; /* Use with ptr_mask_bits() */ - } *fences; - u32 n_fences; - - u64 extension_flags; /** Available extensions parameters */ + struct eb_fence *fences; + unsigned long num_fences; }; static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) @@ -2210,77 +2213,222 @@ eb_pin_engine(struct i915_execbuffer *eb, } static void -__free_fence_array(struct i915_eb_fence *fences, unsigned int n) +__free_fence_array(struct eb_fence *fences, unsigned int n) { - while (n--) + while (n--) { drm_syncobj_put(ptr_mask_bits(fences[n].syncobj, 2)); + dma_fence_put(fences[n].dma_fence); + kfree(fences[n].chain_fence); + } kvfree(fences); } static int -get_fence_array(struct drm_i915_gem_execbuffer2 *args, - struct i915_execbuffer *eb) +add_timeline_fence_array(struct i915_execbuffer *eb, + const struct drm_i915_gem_execbuffer_ext_timeline_fences *timeline_fences) { - const unsigned long nfences = args->num_cliprects; - struct drm_i915_gem_exec_fence __user *user; - struct i915_eb_fence *fences; - unsigned long n; - int err; + struct drm_i915_gem_exec_fence __user *user_fences; + u64 __user *user_values; + struct eb_fence *f; + u64 nfences; + int err = 0; - if (!(args->flags & I915_EXEC_FENCE_ARRAY)) + nfences = timeline_fences->fence_count; + if (!nfences) return 0; /* Check multiplication overflow for access_ok() and kvmalloc_array() */ BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); if (nfences > min_t(unsigned long, - ULONG_MAX / sizeof(*user), - SIZE_MAX / sizeof(*fences))) + ULONG_MAX / sizeof(*user_fences), + SIZE_MAX / sizeof(*f)) - eb->num_fences) return -EINVAL; - user = u64_to_user_ptr(args->cliprects_ptr); - if (!access_ok(user, nfences * sizeof(*user))) + user_fences = u64_to_user_ptr(timeline_fences->handles_ptr); + if (!access_ok(user_fences, nfences * sizeof(*user_fences))) + return -EFAULT; + + user_values = u64_to_user_ptr(timeline_fences->values_ptr); + if (!access_ok(user_values, nfences * sizeof(*user_values))) return -EFAULT; - fences = kvmalloc_array(nfences, sizeof(*fences), - __GFP_NOWARN | GFP_KERNEL); - if (!fences) + f = krealloc(eb->fences, + (eb->num_fences + nfences) * sizeof(*f), + __GFP_NOWARN | GFP_KERNEL); + if (!f) return -ENOMEM; - for (n = 0; n < nfences; n++) { - struct drm_i915_gem_exec_fence fence; + eb->fences = f; + f += eb->num_fences; + + BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & + ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); + + while (nfences--) { + struct drm_i915_gem_exec_fence user_fence; struct drm_syncobj *syncobj; + struct dma_fence *fence = NULL; + u64 point; + + if (__copy_from_user(&user_fence, + user_fences++, + sizeof(user_fence))) + return -EFAULT; + + if (user_fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) + return -EINVAL; + + if (__get_user(point, user_values++)) + return -EFAULT; + + syncobj = drm_syncobj_find(eb->file, user_fence.handle); + if (!syncobj) { + DRM_DEBUG("Invalid syncobj handle provided\n"); + return -ENOENT; + } + + fence = drm_syncobj_fence_get(syncobj); - if (__copy_from_user(&fence, user++, sizeof(fence))) { - err = -EFAULT; - goto err; + if (!fence && user_fence.flags && + !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + DRM_DEBUG("Syncobj handle has no fence\n"); + drm_syncobj_put(syncobj); + return -EINVAL; } - if (fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) { - err = -EINVAL; - goto err; + if (fence) + err = dma_fence_chain_find_seqno(&fence, point); + + if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + DRM_DEBUG("Syncobj handle missing requested point %llu\n", point); + drm_syncobj_put(syncobj); + return err; + } + + /* + * A point might have been signaled already and + * garbage collected from the timeline. In this case + * just ignore the point and carry on. + */ + if (!fence && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { + drm_syncobj_put(syncobj); + continue; + } + + /* + * For timeline syncobjs we need to preallocate chains for + * later signaling. + */ + if (point != 0 && user_fence.flags & I915_EXEC_FENCE_SIGNAL) { + /* + * Waiting and signaling the same point (when point != + * 0) would break the timeline. + */ + if (user_fence.flags & I915_EXEC_FENCE_WAIT) { + DRM_DEBUG("Trying to wait & signal the same timeline point.\n"); + dma_fence_put(fence); + drm_syncobj_put(syncobj); + return -EINVAL; + } + + f->chain_fence = + kmalloc(sizeof(*f->chain_fence), + GFP_KERNEL); + if (!f->chain_fence) { + drm_syncobj_put(syncobj); + dma_fence_put(fence); + return -ENOMEM; + } + } else { + f->chain_fence = NULL; } - syncobj = drm_syncobj_find(eb->file, fence.handle); + f->syncobj = ptr_pack_bits(syncobj, user_fence.flags, 2); + f->dma_fence = fence; + f->value = point; + f++; + eb->num_fences++; + } + + return 0; +} + +static int add_fence_array(struct i915_execbuffer *eb) +{ + struct drm_i915_gem_execbuffer2 *args = eb->args; + struct drm_i915_gem_exec_fence __user *user; + unsigned long num_fences = args->num_cliprects; + struct eb_fence *f; + + if (!(args->flags & I915_EXEC_FENCE_ARRAY)) + return 0; + + if (!num_fences) + return 0; + + /* Check multiplication overflow for access_ok() and kvmalloc_array() */ + BUILD_BUG_ON(sizeof(size_t) > sizeof(unsigned long)); + if (num_fences > min_t(unsigned long, + ULONG_MAX / sizeof(*user), + SIZE_MAX / sizeof(*f) - eb->num_fences)) + return -EINVAL; + + user = u64_to_user_ptr(args->cliprects_ptr); + if (!access_ok(user, num_fences * sizeof(*user))) + return -EFAULT; + + f = krealloc(eb->fences, + (eb->num_fences + num_fences) * sizeof(*f), + __GFP_NOWARN | GFP_KERNEL); + if (!f) + return -ENOMEM; + + eb->fences = f; + f += eb->num_fences; + while (num_fences--) { + struct drm_i915_gem_exec_fence user_fence; + struct drm_syncobj *syncobj; + struct dma_fence *fence = NULL; + + if (__copy_from_user(&user_fence, user++, sizeof(user_fence))) + return -EFAULT; + + if (user_fence.flags & __I915_EXEC_FENCE_UNKNOWN_FLAGS) + return -EINVAL; + + syncobj = drm_syncobj_find(eb->file, user_fence.handle); if (!syncobj) { DRM_DEBUG("Invalid syncobj handle provided\n"); - err = -ENOENT; - goto err; + return -ENOENT; + } + + if (user_fence.flags & I915_EXEC_FENCE_WAIT) { + fence = drm_syncobj_fence_get(syncobj); + if (!fence) { + DRM_DEBUG("Syncobj handle has no fence\n"); + drm_syncobj_put(syncobj); + return -EINVAL; + } } BUILD_BUG_ON(~(ARCH_KMALLOC_MINALIGN - 1) & ~__I915_EXEC_FENCE_UNKNOWN_FLAGS); - fences[n].syncobj = ptr_pack_bits(syncobj, fence.flags, 2); + f->syncobj = ptr_pack_bits(syncobj, user_fence.flags, 2); + f->dma_fence = fence; + f->value = 0; + f->chain_fence = NULL; + f++; + eb->num_fences++; } - eb->fences = fences; - eb->n_fences = nfences; - return 0; +} -err: - __free_fence_array(fences, n); - return err; +static void put_fence_array(struct eb_fence *fences, int num_fences) +{ + if (fences) + __free_fence_array(fences, num_fences); } static int @@ -2289,21 +2437,17 @@ await_fence_array(struct i915_execbuffer *eb) unsigned int n; int err; - for (n = 0; n < eb->n_fences; n++) { + for (n = 0; n < eb->num_fences; n++) { struct drm_syncobj *syncobj; - struct dma_fence *fence; unsigned int flags; syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2); - if (!(flags & I915_EXEC_FENCE_WAIT)) - continue; - fence = drm_syncobj_fence_get(syncobj); - if (!fence) - return -EINVAL; + if (!eb->fences[n].dma_fence) + continue; - err = i915_request_await_dma_fence(eb->request, fence); - dma_fence_put(fence); + err = i915_request_await_dma_fence(eb->request, + eb->fences[n].dma_fence); if (err < 0) return err; } @@ -2311,13 +2455,12 @@ await_fence_array(struct i915_execbuffer *eb) return 0; } -static void -signal_fence_array(struct i915_execbuffer *eb) +static void signal_fence_array(const struct i915_execbuffer *eb) { struct dma_fence * const fence = &eb->request->fence; unsigned int n; - for (n = 0; n < eb->n_fences; n++) { + for (n = 0; n < eb->num_fences; n++) { struct drm_syncobj *syncobj; unsigned int flags; @@ -2325,10 +2468,34 @@ signal_fence_array(struct i915_execbuffer *eb) if (!(flags & I915_EXEC_FENCE_SIGNAL)) continue; - drm_syncobj_replace_fence(syncobj, fence); + if (eb->fences[n].chain_fence) { + drm_syncobj_add_point(syncobj, + eb->fences[n].chain_fence, + fence, + eb->fences[n].value); + /* + * The chain's ownership is transferred to the + * timeline. + */ + eb->fences[n].chain_fence = NULL; + } else { + drm_syncobj_replace_fence(syncobj, fence); + } } } +static int +parse_timeline_fences(struct i915_user_extension __user *ext, void *data) +{ + struct i915_execbuffer *eb = data; + struct drm_i915_gem_execbuffer_ext_timeline_fences timeline_fences; + + if (copy_from_user(&timeline_fences, ext, sizeof(timeline_fences))) + return -EFAULT; + + return add_timeline_fence_array(eb, &timeline_fences); +} + static void retire_requests(struct intel_timeline *tl, struct i915_request *end) { struct i915_request *rq, *rn; @@ -2371,14 +2538,13 @@ static void eb_request_add(struct i915_execbuffer *eb) } static const i915_user_extension_fn execbuf_extensions[] = { + [DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES] = parse_timeline_fences, }; static int parse_execbuf2_extensions(struct drm_i915_gem_execbuffer2 *args, struct i915_execbuffer *eb) { - eb->extension_flags = 0; - if (!(args->flags & I915_EXEC_USE_EXTENSIONS)) return 0; @@ -2432,7 +2598,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.trampoline = NULL; eb.fences = NULL; - eb.n_fences = 0; + eb.num_fences = 0; eb.batch_flags = 0; if (args->flags & I915_EXEC_SECURE) { @@ -2451,14 +2617,24 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (args->flags & I915_EXEC_IS_PINNED) eb.batch_flags |= I915_DISPATCH_PINNED; + err = parse_execbuf2_extensions(args, &eb); + if (err) + goto err_ext; + + err = add_fence_array(&eb); + if (err) + goto err_ext; + #define IN_FENCES (I915_EXEC_FENCE_IN | I915_EXEC_FENCE_SUBMIT) if (args->flags & IN_FENCES) { if ((args->flags & IN_FENCES) == IN_FENCES) return -EINVAL; in_fence = sync_file_get_fence(lower_32_bits(args->rsvd2)); - if (!in_fence) - return -EINVAL; + if (!in_fence) { + err = -EINVAL; + goto err_ext; + } } #undef IN_FENCES @@ -2470,17 +2646,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, } } - err = parse_execbuf2_extensions(args, &eb); - if (err) - goto err_out_fence; - - err = get_fence_array(args, &eb); - if (err) - goto err_arr_fence; - err = eb_create(&eb); if (err) - goto err_arr_fence; + goto err_out_fence; GEM_BUG_ON(!eb.lut_size); @@ -2576,7 +2744,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_request; } - if (eb.n_fences) { + if (eb.fences) { err = await_fence_array(&eb); if (err) goto err_request; @@ -2608,7 +2776,7 @@ err_request: i915_request_get(eb.request); eb_request_add(&eb); - if (eb.n_fences) + if (eb.fences) signal_fence_array(&eb); if (out_fence) { @@ -2637,13 +2805,13 @@ err_context: i915_gem_context_put(eb.gem_context); err_destroy: eb_destroy(&eb); -err_arr_fence: - __free_fence_array(eb.fences, eb.n_fences); err_out_fence: if (out_fence_fd != -1) put_unused_fd(out_fence_fd); err_in_fence: dma_fence_put(in_fence); +err_ext: + put_fence_array(eb.fences, eb.num_fences); return err; } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 5fd5af4bc855..2d10f6a2c042 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1846,7 +1846,8 @@ static struct drm_driver driver = { */ .driver_features = DRIVER_GEM | - DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ, + DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ | + DRIVER_SYNCOBJ_TIMELINE, .release = i915_driver_release, .open = i915_driver_open, .lastclose = i915_driver_lastclose, diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c index 421613219ae9..f96032c60a12 100644 --- a/drivers/gpu/drm/i915/i915_getparam.c +++ b/drivers/gpu/drm/i915/i915_getparam.c @@ -132,6 +132,7 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data, case I915_PARAM_HAS_EXEC_BATCH_FIRST: case I915_PARAM_HAS_EXEC_FENCE_ARRAY: case I915_PARAM_HAS_EXEC_SUBMIT_FENCE: + case I915_PARAM_HAS_EXEC_TIMELINE_FENCES: /* For the time being all of these are always true; * if some supported hardware does not have one of these * features this value needs to be provided from diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index dcada8c3a693..fa1f3d62f9a6 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -619,6 +619,12 @@ typedef struct drm_i915_irq_wait { */ #define I915_PARAM_PERF_REVISION 54 +/* Query whether DRM_I915_GEM_EXECBUFFER2 supports supplying an array of + * timeline syncobj through drm_i915_gem_execbuffer_ext_timeline_fences. See + * I915_EXEC_USE_EXTENSIONS. + */ +#define I915_PARAM_HAS_EXEC_TIMELINE_FENCES 55 + /* Must be kept compact -- no holes and well documented */ typedef struct drm_i915_getparam { @@ -1046,8 +1052,36 @@ struct drm_i915_gem_exec_fence { __u32 flags; }; -enum drm_i915_gem_execbuffer_ext { - DRM_I915_GEM_EXECBUFFER_EXT_MAX /* non-ABI */ +/** + * See drm_i915_gem_execbuffer_ext_timeline_fences. + */ +#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0 + +/** + * This structure describes an array of drm_syncobj and associated points for + * timeline variants of drm_syncobj. It is invalid to append this structure to + * the execbuf if I915_EXEC_FENCE_ARRAY is set. + */ +struct drm_i915_gem_execbuffer_ext_timeline_fences { + struct i915_user_extension base; + + /** + * Number of element in the handles_ptr & value_ptr arrays. + */ + __u64 fence_count; + + /** + * Pointer to an array of struct drm_i915_gem_exec_fence of length + * fence_count. + */ + __u64 handles_ptr; + + /** + * Pointer to an array of u64 values of length fence_count. Values + * must be 0 for a binary drm_syncobj. A Value of 0 for a timeline + * drm_syncobj is invalid as it turns a drm_syncobj into a binary one. + */ + __u64 values_ptr; }; struct drm_i915_gem_execbuffer2 { -- cgit v1.2.3 From 21118e8e56479ef33460fbd63a5ad0535843b666 Mon Sep 17 00:00:00 2001 From: George Spelvin Date: Wed, 25 Mar 2020 19:24:29 +0000 Subject: drm/i915/selftests: Avoid passing a random 0 into ilog2 igt_mm_config() calls ilog2() on the (pseudo)random 21-bit number s>>12. Once in 2 million seeds, this is zero and ilog2 summons the nasal demons. There was an attempt to handle this case with a max(), but that's too late; ms could already be something bizarre. Given that the low 12 bits of s and ms are always zero, it's a lot simpler just to divide them by 4096, then everything fits into 32 bits, and we can easily generate a random number 1 <= s <= 0x1fffff. Fixes: 14d1b9a6247c ("drm/i915: buddy allocator") Signed-off-by: George Spelvin Cc: Matthew Auld Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Matthew Auld Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200325192429.GA8865@SDF.ORG Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/selftests/i915_buddy.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c b/drivers/gpu/drm/i915/selftests/i915_buddy.c index 939a6caebb03..632b912b0bc9 100644 --- a/drivers/gpu/drm/i915/selftests/i915_buddy.c +++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c @@ -8,8 +8,6 @@ #include "../i915_selftest.h" #include "i915_random.h" -#define SZ_8G (1ULL << 33) - static void __igt_dump_block(struct i915_buddy_mm *mm, struct i915_buddy_block *block, bool buddy) @@ -281,18 +279,22 @@ static int igt_check_mm(struct i915_buddy_mm *mm) static void igt_mm_config(u64 *size, u64 *chunk_size) { I915_RND_STATE(prng); - u64 s, ms; + u32 s, ms; /* Nothing fancy, just try to get an interesting bit pattern */ prandom_seed_state(&prng, i915_selftest.random_seed); - s = i915_prandom_u64_state(&prng) & (SZ_8G - 1); - ms = BIT_ULL(12 + (prandom_u32_state(&prng) % ilog2(s >> 12))); - s = max(s & -ms, ms); + /* Let size be a random number of pages up to 8 GB (2M pages) */ + s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); + /* Let the chunk size be a random power of 2 less than size */ + ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng)); + /* Round size down to the chunk size */ + s &= -ms; - *chunk_size = ms; - *size = s; + /* Convert from pages to bytes */ + *chunk_size = (u64)ms << 12; + *size = (u64)s << 12; } static int igt_buddy_alloc_smoke(void *arg) -- cgit v1.2.3 From b302a2e68807604af2a5015816c1d117747989b6 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 21 Jul 2020 02:29:52 +0300 Subject: drm/i915/tgl: Make sure TC-cold is blocked before enabling TC AUX power wells The dependency between power wells is determined by the ordering of the power well list: when enabling the power wells for a domain, this happens walking the power well list forward, while disabling them happens in the reverse direction. Accordingly a power well on the list must follow any other power well it depends on. Since the TC AUX power wells depend on TC-cold being blocked, move the TC-cold off power well before all AUX power wells. Fixes: 3c02934b24e3 ("drm/i915/tc/tgl: Implement TC cold sequences") Cc: José Roberto de Souza Signed-off-by: Imre Deak Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200720232952.16228-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_power.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9f0241a53a45..3c800aa9cf3f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4146,6 +4146,12 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6, }, }, + { + .name = "TC cold off", + .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, + .ops = &tgl_tc_cold_off_ops, + .id = DISP_PW_ID_NONE, + }, { .name = "AUX A", .domains = TGL_AUX_A_IO_POWER_DOMAINS, @@ -4332,12 +4338,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.irq_pipe_mask = BIT(PIPE_D), }, }, - { - .name = "TC cold off", - .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, - .ops = &tgl_tc_cold_off_ops, - .id = DISP_PW_ID_NONE, - }, }; static const struct i915_power_well_desc rkl_power_wells[] = { -- cgit v1.2.3 From 05e31dd78e26d8c4d9d0dd68addead8d19c367c2 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Wed, 5 Aug 2020 18:00:56 +0300 Subject: drm/i915/tgl: Fix TC-cold block/unblock sequence The command register is the PCODE MBOX low register not the high one as described by the spec. This left the system with the TC-cold power state being blocked all the time. Fix things by using the correct register. Also to make sure we retry a request for at least 600usec, when the PCODE MBOX command itself succeeded, but the TC-cold block command failed, sleep for 1msec unconditionally after any fail. The change was tested with JTAG register read of the HW/FW's actual TC-cold state, which reported the expected states after this change. Tested-by: Nivedita Swaminathan Cc: José Roberto de Souza Signed-off-by: Imre Deak Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200805150056.24248-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display_power.c | 10 +++++----- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 3c800aa9cf3f..7946c6af4b1e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3927,12 +3927,13 @@ tgl_tc_cold_request(struct drm_i915_private *i915, bool block) int ret; while (1) { - u32 low_val = 0, high_val; + u32 low_val; + u32 high_val = 0; if (block) - high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ; + low_val = TGL_PCODE_EXIT_TCCOLD_DATA_L_BLOCK_REQ; else - high_val = TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ; + low_val = TGL_PCODE_EXIT_TCCOLD_DATA_L_UNBLOCK_REQ; /* * Spec states that we should timeout the request after 200us @@ -3951,8 +3952,7 @@ tgl_tc_cold_request(struct drm_i915_private *i915, bool block) if (++tries == 3) break; - if (ret == -EAGAIN) - msleep(1); + msleep(1); } if (ret) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2b403df03404..e85c6fc1f3cb 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -9226,8 +9226,8 @@ enum { #define DISPLAY_IPS_CONTROL 0x19 #define TGL_PCODE_TCCOLD 0x26 #define TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED REG_BIT(0) -#define TGL_PCODE_EXIT_TCCOLD_DATA_H_BLOCK_REQ 0 -#define TGL_PCODE_EXIT_TCCOLD_DATA_H_UNBLOCK_REQ REG_BIT(0) +#define TGL_PCODE_EXIT_TCCOLD_DATA_L_BLOCK_REQ 0 +#define TGL_PCODE_EXIT_TCCOLD_DATA_L_UNBLOCK_REQ REG_BIT(0) /* See also IPS_CTL */ #define IPS_PCODE_CONTROL (1 << 30) #define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A -- cgit v1.2.3 From 1d3cc7ab2b00f849c94bd7e5fcffc7899dc4039a Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Fri, 7 Aug 2020 12:26:28 -0700 Subject: drm/i915/tgl: Set subplatforms There is no way to differentiate TGL-U from TGL-Y by the PCI ids as some ids are available in both SKUs. So here using the root device id in the PCI bus that iGPU is in to differentiate between U and Y. BSpec: 44455 Reviewed-by: Swathi Dhanavanthri Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200807192629.64134-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ drivers/gpu/drm/i915/intel_device_info.c | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 56dfc6d98caa..a59f64821920 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1497,6 +1497,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_ICL_WITH_PORT_F(dev_priv) \ IS_SUBPLATFORM(dev_priv, INTEL_ICELAKE, INTEL_SUBPLATFORM_PORTF) +#define IS_TGL_U(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_ULT) + +#define IS_TGL_Y(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_TIGERLAKE, INTEL_SUBPLATFORM_ULX) + #define SKL_REVID_A0 0x0 #define SKL_REVID_B0 0x1 #define SKL_REVID_C0 0x2 diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e85c6fc1f3cb..14d8c3fbcc0d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -12353,4 +12353,10 @@ enum skl_power_gate { #define DSB_ENABLE (1 << 31) #define DSB_STATUS (1 << 0) +#define TGL_ROOT_DEVICE_ID 0x9A00 +#define TGL_ROOT_DEVICE_MASK 0xFF00 +#define TGL_ROOT_DEVICE_SKU_MASK 0xF +#define TGL_ROOT_DEVICE_SKU_ULX 0x2 +#define TGL_ROOT_DEVICE_SKU_ULT 0x4 + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 40c590db3c76..e2aa5bc3a6e0 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -346,6 +346,25 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915) mask = BIT(INTEL_SUBPLATFORM_PORTF); } + if (IS_TIGERLAKE(i915)) { + struct pci_dev *root, *pdev = i915->drm.pdev; + + root = list_first_entry(&pdev->bus->devices, typeof(*root), bus_list); + + drm_WARN_ON(&i915->drm, mask); + drm_WARN_ON(&i915->drm, (root->device & TGL_ROOT_DEVICE_MASK) != + TGL_ROOT_DEVICE_ID); + + switch (root->device & TGL_ROOT_DEVICE_SKU_MASK) { + case TGL_ROOT_DEVICE_SKU_ULX: + mask = BIT(INTEL_SUBPLATFORM_ULX); + break; + case TGL_ROOT_DEVICE_SKU_ULT: + mask = BIT(INTEL_SUBPLATFORM_ULT); + break; + } + } + GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_BITS); RUNTIME_INFO(i915)->platform_mask[pi] |= mask; -- cgit v1.2.3 From 04dfb1acbae6a70703183fc6c1366bb7d997d015 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Fri, 7 Aug 2020 12:26:29 -0700 Subject: drm/i915/tgl: Add new voltage swing table This new HBR2 table for TGL-U and TGL-Y is required to pass DisplayPort compliance. BSpec: 49291 Cc: Khaled Almahallawy Reviewed-by: Khaled Almahallawy Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200807192629.64134-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_ddi.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 714b2bc96f23..de5b216561d8 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -706,6 +706,20 @@ static const struct cnl_ddi_buf_trans tgl_combo_phy_ddi_translations_dp_hbr2[] = { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ }; +static const struct cnl_ddi_buf_trans tgl_uy_combo_phy_ddi_translations_dp_hbr2[] = { + /* NT mV Trans mV db */ + { 0xA, 0x35, 0x3F, 0x00, 0x00 }, /* 350 350 0.0 */ + { 0xA, 0x4F, 0x36, 0x00, 0x09 }, /* 350 500 3.1 */ + { 0xC, 0x60, 0x32, 0x00, 0x0D }, /* 350 700 6.0 */ + { 0xC, 0x7F, 0x2D, 0x00, 0x12 }, /* 350 900 8.2 */ + { 0xC, 0x47, 0x3F, 0x00, 0x00 }, /* 500 500 0.0 */ + { 0xC, 0x6F, 0x36, 0x00, 0x09 }, /* 500 700 2.9 */ + { 0x6, 0x7D, 0x32, 0x00, 0x0D }, /* 500 900 5.1 */ + { 0x6, 0x60, 0x3C, 0x00, 0x03 }, /* 650 700 0.6 */ + { 0x6, 0x7F, 0x34, 0x00, 0x0B }, /* 600 900 3.5 */ + { 0x6, 0x7F, 0x3F, 0x00, 0x00 }, /* 900 900 0.0 */ +}; + /* * Cloned the HOBL entry to comply with the voltage and pre-emphasis entries * that DisplayPort specification requires @@ -1087,6 +1101,11 @@ tgl_get_combo_buf_trans(struct intel_encoder *encoder, int type, int rate, if (type == INTEL_OUTPUT_HDMI || type == INTEL_OUTPUT_EDP) { return icl_get_combo_buf_trans(encoder, type, rate, n_entries); } else if (rate > 270000) { + if (IS_TGL_U(dev_priv) || IS_TGL_Y(dev_priv)) { + *n_entries = ARRAY_SIZE(tgl_uy_combo_phy_ddi_translations_dp_hbr2); + return tgl_uy_combo_phy_ddi_translations_dp_hbr2; + } + *n_entries = ARRAY_SIZE(tgl_combo_phy_ddi_translations_dp_hbr2); return tgl_combo_phy_ddi_translations_dp_hbr2; } -- cgit v1.2.3 From 96c5a15f9f3973aca11137671afa9d433639f8ce Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 10 Aug 2020 20:21:05 -0700 Subject: drm/i915/kbl: Fix revision ID checks We usually assume that increasing PCI device revision ID's translates to newer steppings; macros like IS_KBL_REVID() that we use rely on this behavior. Unfortunately this turns out to not be true on KBL; the newer device 2 revision ID's sometimes go backward to older steppings. The situation is further complicated by different GT and display steppings associated with each revision ID. Let's work around this by providing a table to map the revision ID to specific GT and display steppings, and then perform our comparisons on the mapped values. v2: - Move the kbl_revids[] array to intel_workarounds.c to avoid compiler warnings about an unused variable in files that don't call the macros (kernel test robot). Bspec: 18329 Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200811032105.2819370-1-matthew.d.roper@intel.com Reviewed-by: Swathi Dhanavanthri Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/intel_lrc.c | 2 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 24 ++++++++++++++++--- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 36 ++++++++++++++++++++++------- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 5 files changed, 53 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e0280a672f1d..94d8c9d76a26 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4555,7 +4555,7 @@ static int gen8_emit_flush_render(struct i915_request *request, vf_flush_wa = true; /* WaForGAMHang:kbl */ - if (IS_KBL_REVID(request->engine->i915, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(request->engine->i915, 0, KBL_REVID_B0)) dc_flush_wa = true; } diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index cef1c122696f..be5a4685c991 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -52,6 +52,24 @@ * - Public functions to init or apply the given workaround type. */ +/* + * KBL revision ID ordering is bizarre; higher revision ID's map to lower + * steppings in some cases. So rather than test against the revision ID + * directly, let's map that into our own range of increasing ID's that we + * can test against in a regular manner. + */ + +const struct i915_rev_steppings kbl_revids[] = { + [0] = { .gt_stepping = KBL_REVID_A0, .disp_stepping = KBL_REVID_A0 }, + [1] = { .gt_stepping = KBL_REVID_B0, .disp_stepping = KBL_REVID_B0 }, + [2] = { .gt_stepping = KBL_REVID_C0, .disp_stepping = KBL_REVID_B0 }, + [3] = { .gt_stepping = KBL_REVID_D0, .disp_stepping = KBL_REVID_B0 }, + [4] = { .gt_stepping = KBL_REVID_F0, .disp_stepping = KBL_REVID_C0 }, + [5] = { .gt_stepping = KBL_REVID_C0, .disp_stepping = KBL_REVID_B1 }, + [6] = { .gt_stepping = KBL_REVID_D1, .disp_stepping = KBL_REVID_B1 }, + [7] = { .gt_stepping = KBL_REVID_G0, .disp_stepping = KBL_REVID_C0 }, +}; + static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name) { wal->name = name; @@ -470,7 +488,7 @@ static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine, gen9_ctx_workarounds_init(engine, wal); /* WaToEnableHwFixForPushConstHWBug:kbl */ - if (IS_KBL_REVID(i915, KBL_REVID_C0, REVID_FOREVER)) + if (IS_KBL_GT_REVID(i915, KBL_REVID_C0, REVID_FOREVER)) WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); @@ -1008,7 +1026,7 @@ kbl_gt_workarounds_init(struct drm_i915_private *i915, struct i915_wa_list *wal) gen9_gt_workarounds_init(i915, wal); /* WaDisableDynamicCreditSharing:kbl */ - if (IS_KBL_REVID(i915, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(i915, 0, KBL_REVID_B0)) wa_write_or(wal, GAMT_CHKN_BIT_REG, GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); @@ -1923,7 +1941,7 @@ xcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) struct drm_i915_private *i915 = engine->i915; /* WaKBLVECSSemaphoreWaitPoll:kbl */ - if (IS_KBL_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) { + if (IS_KBL_GT_REVID(i915, KBL_REVID_A0, KBL_REVID_E0)) { wa_write(wal, RING_SEMA_WAIT_POLL(engine->mmio_base), 1); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2d10f6a2c042..e6918c7c0709 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -392,7 +392,7 @@ static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) pre |= IS_HSW_EARLY_SDV(dev_priv); pre |= IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0); pre |= IS_BXT_REVID(dev_priv, 0, BXT_REVID_B_LAST); - pre |= IS_KBL_REVID(dev_priv, 0, KBL_REVID_A0); + pre |= IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_A0); pre |= IS_GLK_REVID(dev_priv, 0, GLK_REVID_A2); if (pre) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a59f64821920..023eb28ea4ec 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1523,14 +1523,34 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_BXT_REVID(dev_priv, since, until) \ (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until)) -#define KBL_REVID_A0 0x0 -#define KBL_REVID_B0 0x1 -#define KBL_REVID_C0 0x2 -#define KBL_REVID_D0 0x3 -#define KBL_REVID_E0 0x4 - -#define IS_KBL_REVID(dev_priv, since, until) \ - (IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until)) +enum { + KBL_REVID_A0, + KBL_REVID_B0, + KBL_REVID_B1, + KBL_REVID_C0, + KBL_REVID_D0, + KBL_REVID_D1, + KBL_REVID_E0, + KBL_REVID_F0, + KBL_REVID_G0, +}; + +struct i915_rev_steppings { + u8 gt_stepping; + u8 disp_stepping; +}; + +/* Defined in intel_workarounds.c */ +extern const struct i915_rev_steppings kbl_revids[]; + +#define IS_KBL_GT_REVID(dev_priv, since, until) \ + (IS_KABYLAKE(dev_priv) && \ + kbl_revids[INTEL_REVID(dev_priv)].gt_stepping >= since && \ + kbl_revids[INTEL_REVID(dev_priv)].gt_stepping <= until) +#define IS_KBL_DISP_REVID(dev_priv, since, until) \ + (IS_KABYLAKE(dev_priv) && \ + kbl_revids[INTEL_REVID(dev_priv)].disp_stepping >= since && \ + kbl_revids[INTEL_REVID(dev_priv)].disp_stepping <= until) #define GLK_REVID_A0 0x0 #define GLK_REVID_A1 0x1 diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0a1a95060f38..b4bd19266b8c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -7217,12 +7217,12 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv) gen9_init_clock_gating(dev_priv); /* WaDisableSDEUnitClockGating:kbl */ - if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0)) I915_WRITE(GEN8_UCGCTL6, I915_READ(GEN8_UCGCTL6) | GEN8_SDEUNIT_CLOCK_GATE_DISABLE); /* WaDisableGamClockGating:kbl */ - if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) + if (IS_KBL_GT_REVID(dev_priv, 0, KBL_REVID_B0)) I915_WRITE(GEN6_UCGCTL1, I915_READ(GEN6_UCGCTL1) | GEN6_GAMUNIT_CLOCK_GATE_DISABLE); -- cgit v1.2.3 From 6e43e276b8c94ecfeebfcc32eabad2ba27e90299 Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 10 Aug 2020 10:41:43 -0700 Subject: drm/i915: Initial implementation of PSR2 selective fetch All GEN12 platforms supports PSR2 selective fetch but not all GEN12 platforms supports PSR2 hardware tracking(aka RKL). This feature consists in software programming registers with the damaged area of each plane this way hardware will only fetch from memory those areas and sent the PSR2 selective update blocks to panel, saving even more power. But as initial step it is only enabling the full frame fetch at every flip, the actual selective fetch part will come in a future patch. Also this is only handling the page flip side, it is still completely missing frontbuffer modifications, that is why the enable_psr2_sel_fetch parameter was added. v3: - calling intel_psr2_sel_fetch_update() during the atomic check phase (Ville) BSpec: 55229 Cc: Ville Syrjälä Cc: Imre Deak Cc: Gwan-gyeong Mun Cc: Rodrigo Vivi Cc: Dhinakaran Pandiyan Reviewed-by: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200810174144.76761-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++ .../gpu/drm/i915/display/intel_display_debugfs.c | 3 + drivers/gpu/drm/i915/display/intel_display_types.h | 3 + drivers/gpu/drm/i915/display/intel_psr.c | 95 ++++++++++++++++++---- drivers/gpu/drm/i915/display/intel_psr.h | 5 ++ drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_params.c | 5 ++ drivers/gpu/drm/i915/i915_params.h | 1 + 8 files changed, 105 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 522c772a2111..2ddabf92adde 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -12770,6 +12770,9 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state, } + if (!mode_changed) + intel_psr2_sel_fetch_update(state, crtc); + return 0; } @@ -15146,6 +15149,8 @@ static void commit_pipe_config(struct intel_atomic_state *state, if (new_crtc_state->update_pipe) intel_pipe_fastset(old_crtc_state, new_crtc_state); + + intel_psr2_program_trans_man_trk_ctl(new_crtc_state); } if (dev_priv->display.atomic_update_watermarks) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 5a5cfe25085b..f549381048b3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -417,6 +417,9 @@ static int i915_edp_psr_status(struct seq_file *m, void *data) su_blocks = su_blocks >> PSR2_SU_STATUS_SHIFT(frame); seq_printf(m, "%d\t%d\n", frame, su_blocks); } + + seq_printf(m, "PSR2 selective fetch: %s\n", + enableddisabled(psr->psr2_sel_fetch_enabled)); } unlock: diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index f581260e8dbf..9349b15afff6 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -931,6 +931,7 @@ struct intel_crtc_state { bool has_psr; bool has_psr2; + bool enable_psr2_sel_fetch; u32 dc3co_exitline; /* @@ -1073,6 +1074,8 @@ struct intel_crtc_state { /* For DSB related info */ struct intel_dsb *dsb; + + u32 psr2_man_track_ctl; }; enum intel_pipe_crc_source { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index bf9e320c547d..d30a3560b794 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -553,6 +553,14 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FAST_WAKE(7); } + if (dev_priv->psr.psr2_sel_fetch_enabled) + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), + PSR2_MAN_TRK_CTL_ENABLE); + else if (HAS_PSR2_SEL_FETCH(dev_priv)) + intel_de_write(dev_priv, + PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0); + /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is * recommending keep this bit unset while PSR2 is enabled. @@ -663,6 +671,38 @@ tgl_dc3co_exitline_compute_config(struct intel_dp *intel_dp, crtc_state->dc3co_exitline = crtc_vdisplay - exit_scanlines; } +static bool intel_psr2_sel_fetch_config_valid(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) +{ + struct intel_atomic_state *state = to_intel_atomic_state(crtc_state->uapi.state); + struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_plane_state *plane_state; + struct intel_plane *plane; + int i; + + if (!dev_priv->params.enable_psr2_sel_fetch) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, disabled by parameter\n"); + return false; + } + + if (crtc_state->uapi.async_flip) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, async flip enabled\n"); + return false; + } + + for_each_new_intel_plane_in_state(state, plane, plane_state, i) { + if (plane_state->uapi.rotation != DRM_MODE_ROTATE_0) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 sel fetch not enabled, plane rotated\n"); + return false; + } + } + + return crtc_state->enable_psr2_sel_fetch = true; +} + static bool intel_psr2_config_valid(struct intel_dp *intel_dp, struct intel_crtc_state *crtc_state) { @@ -732,22 +772,17 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp, return false; } - /* - * Some platforms lack PSR2 HW tracking and instead require manual - * tracking by software. In this case, the driver is required to track - * the areas that need updates and program hardware to send selective - * updates. - * - * So until the software tracking is implemented, PSR2 needs to be - * disabled for platforms without PSR2 HW tracking. - */ - if (!HAS_PSR_HW_TRACKING(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, - "No PSR2 HW tracking in the platform\n"); - return false; + if (HAS_PSR2_SEL_FETCH(dev_priv)) { + if (!intel_psr2_sel_fetch_config_valid(intel_dp, crtc_state) && + !HAS_PSR_HW_TRACKING(dev_priv)) { + drm_dbg_kms(&dev_priv->drm, + "PSR2 not enabled, selective fetch not valid and no HW tracking available\n"); + return false; + } } - if (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v) { + if (!crtc_state->enable_psr2_sel_fetch && + (crtc_hdisplay > psr_max_h || crtc_vdisplay > psr_max_v)) { drm_dbg_kms(&dev_priv->drm, "PSR2 not enabled, resolution %dx%d > max supported %dx%d\n", crtc_hdisplay, crtc_vdisplay, @@ -898,6 +933,11 @@ static void intel_psr_enable_source(struct intel_dp *intel_dp, val |= EXITLINE_ENABLE; intel_de_write(dev_priv, EXITLINE(cpu_transcoder), val); } + + if (HAS_PSR_HW_TRACKING(dev_priv)) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, IGNORE_PSR2_HW_TRACKING, + dev_priv->psr.psr2_sel_fetch_enabled ? + IGNORE_PSR2_HW_TRACKING : 0); } static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, @@ -919,6 +959,7 @@ static void intel_psr_enable_locked(struct drm_i915_private *dev_priv, /* DC5/DC6 requires at least 6 idle frames */ val = usecs_to_jiffies(intel_get_frame_time_us(crtc_state) * 6); dev_priv->psr.dc3co_exit_delay = val; + dev_priv->psr.psr2_sel_fetch_enabled = crtc_state->enable_psr2_sel_fetch; /* * If a PSR error happened and the driver is reloaded, the EDP_PSR_IIR @@ -1115,6 +1156,32 @@ static void psr_force_hw_tracking_exit(struct drm_i915_private *dev_priv) intel_psr_exit(dev_priv); } +void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct i915_psr *psr = &dev_priv->psr; + + if (!HAS_PSR2_SEL_FETCH(dev_priv) || + !crtc_state->enable_psr2_sel_fetch) + return; + + intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(psr->transcoder), + crtc_state->psr2_man_track_ctl); +} + +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + + if (!crtc_state->enable_psr2_sel_fetch) + return; + + crtc_state->psr2_man_track_ctl = PSR2_MAN_TRK_CTL_ENABLE | + PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME; +} + /** * intel_psr_update - Update PSR state * @intel_dp: Intel DP diff --git a/drivers/gpu/drm/i915/display/intel_psr.h b/drivers/gpu/drm/i915/display/intel_psr.h index b4515186d5f4..6a83c8e682e6 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.h +++ b/drivers/gpu/drm/i915/display/intel_psr.h @@ -13,6 +13,8 @@ struct drm_connector_state; struct drm_i915_private; struct intel_crtc_state; struct intel_dp; +struct intel_crtc; +struct intel_atomic_state; #define CAN_PSR(dev_priv) (HAS_PSR(dev_priv) && dev_priv->psr.sink_support) void intel_psr_init_dpcd(struct intel_dp *intel_dp); @@ -43,5 +45,8 @@ void intel_psr_atomic_check(struct drm_connector *connector, struct drm_connector_state *old_state, struct drm_connector_state *new_state); void intel_psr_set_force_mode_changed(struct intel_dp *intel_dp); +void intel_psr2_sel_fetch_update(struct intel_atomic_state *state, + struct intel_crtc *crtc); +void intel_psr2_program_trans_man_trk_ctl(const struct intel_crtc_state *crtc_state); #endif /* __INTEL_PSR_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 023eb28ea4ec..4b5c25a018b7 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -506,6 +506,7 @@ struct i915_psr { bool link_standby; bool colorimetry_support; bool psr2_enabled; + bool psr2_sel_fetch_enabled; u8 sink_sync_latency; ktime_t last_entry_attempt; ktime_t last_exit; @@ -1699,6 +1700,7 @@ extern const struct i915_rev_steppings kbl_revids[]; #define HAS_PSR(dev_priv) (INTEL_INFO(dev_priv)->display.has_psr) #define HAS_PSR_HW_TRACKING(dev_priv) \ (INTEL_INFO(dev_priv)->display.has_psr_hw_tracking) +#define HAS_PSR2_SEL_FETCH(dev_priv) (INTEL_GEN(dev_priv) >= 12) #define HAS_TRANSCODER(dev_priv, trans) ((INTEL_INFO(dev_priv)->cpu_transcoder_mask & BIT(trans)) != 0) #define HAS_RC6(dev_priv) (INTEL_INFO(dev_priv)->has_rc6) diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 8d8db9ff0a48..7f139ea4a90b 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -102,6 +102,11 @@ i915_param_named(psr_safest_params, bool, 0400, "is helpful to detect if PSR issues are related to bad values set in " " VBT. (0=use VBT parameters, 1=use safest parameters)"); +i915_param_named_unsafe(enable_psr2_sel_fetch, bool, 0400, + "Enable PSR2 selective fetch " + "(0=disabled, 1=enabled) " + "Default: 0"); + i915_param_named_unsafe(force_probe, charp, 0400, "Force probe the driver for specified devices. " "See CONFIG_DRM_I915_FORCE_PROBE for details."); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 53fb5ba8fbed..330c03e2b4f7 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -54,6 +54,7 @@ struct drm_printer; param(int, enable_fbc, -1, 0600) \ param(int, enable_psr, -1, 0600) \ param(bool, psr_safest_params, false, 0600) \ + param(bool, enable_psr2_sel_fetch, false, 0600) \ param(int, disable_power_well, -1, 0400) \ param(int, enable_ips, 1, 0600) \ param(int, invert_brightness, 0, 0600) \ -- cgit v1.2.3 From a170f4f1b128128d35b732cdc799dc5824f8e2ca Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Mon, 10 Aug 2020 10:41:44 -0700 Subject: drm/i915/display: Implement WA 1408330847 From the 3 WAs for PSR2 man track/selective fetch this is only one needed when doing single full frames at every flip. Reviewed-by: Gwan-gyeong Mun Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200810174144.76761-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_psr.c | 19 +++++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index d30a3560b794..2b004ee9619c 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -553,13 +553,21 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp) val |= EDP_PSR2_FAST_WAKE(7); } - if (dev_priv->psr.psr2_sel_fetch_enabled) + if (dev_priv->psr.psr2_sel_fetch_enabled) { + /* WA 1408330847 */ + if (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0)) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, + DIS_RAM_BYPASS_PSR2_MAN_TRACK, + DIS_RAM_BYPASS_PSR2_MAN_TRACK); + intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), PSR2_MAN_TRK_CTL_ENABLE); - else if (HAS_PSR2_SEL_FETCH(dev_priv)) + } else if (HAS_PSR2_SEL_FETCH(dev_priv)) { intel_de_write(dev_priv, PSR2_MAN_TRK_CTL(dev_priv->psr.transcoder), 0); + } /* * PSR2 HW is incorrectly using EDP_PSR_TP1_TP3_SEL and BSpec is @@ -1099,6 +1107,13 @@ static void intel_psr_disable_locked(struct intel_dp *intel_dp) psr_status_mask, 2000)) drm_err(&dev_priv->drm, "Timed out waiting PSR idle state\n"); + /* WA 1408330847 */ + if (dev_priv->psr.psr2_sel_fetch_enabled && + (IS_TGL_REVID(dev_priv, TGL_REVID_A0, TGL_REVID_A0) || + IS_RKL_REVID(dev_priv, RKL_REVID_A0, RKL_REVID_A0))) + intel_de_rmw(dev_priv, CHICKEN_PAR1_1, + DIS_RAM_BYPASS_PSR2_MAN_TRACK, 0); + /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 14d8c3fbcc0d..ac691927e29d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -7878,6 +7878,7 @@ enum { # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 _MMIO(0x42080) +#define DIS_RAM_BYPASS_PSR2_MAN_TRACK (1 << 16) #define SKL_DE_COMPRESSED_HASH_MODE (1 << 15) #define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) -- cgit v1.2.3 From 5bf7919d530a2e1456ae602fccf365c213a4db4f Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 13 Aug 2020 13:00:28 -0700 Subject: drm/i915: Update TGL and RKL DMC firmware versions Fixes around DC5, DC6 and DC3CO in those new firmwares. Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200813200029.25307-1-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_csr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_csr.c b/drivers/gpu/drm/i915/display/intel_csr.c index f22a7645c249..d5db16764619 100644 --- a/drivers/gpu/drm/i915/display/intel_csr.c +++ b/drivers/gpu/drm/i915/display/intel_csr.c @@ -40,12 +40,12 @@ #define GEN12_CSR_MAX_FW_SIZE ICL_CSR_MAX_FW_SIZE -#define RKL_CSR_PATH "i915/rkl_dmc_ver2_01.bin" -#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 1) +#define RKL_CSR_PATH "i915/rkl_dmc_ver2_02.bin" +#define RKL_CSR_VERSION_REQUIRED CSR_VERSION(2, 2) MODULE_FIRMWARE(RKL_CSR_PATH); -#define TGL_CSR_PATH "i915/tgl_dmc_ver2_06.bin" -#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 6) +#define TGL_CSR_PATH "i915/tgl_dmc_ver2_08.bin" +#define TGL_CSR_VERSION_REQUIRED CSR_VERSION(2, 8) #define TGL_CSR_MAX_FW_SIZE 0x6000 MODULE_FIRMWARE(TGL_CSR_PATH); -- cgit v1.2.3 From 25a322fde74f8ca3368f4ff28b452af7cb5fa0dc Mon Sep 17 00:00:00 2001 From: José Roberto de Souza Date: Thu, 13 Aug 2020 13:00:29 -0700 Subject: drm/i915: Update TGL and RKL HuC firmware versions Major upgrade of HuC firmware with fixes and new features. Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200813200029.25307-2-jose.souza@intel.com Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index 59b27aba15c6..80e8b6c3bc8c 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -51,8 +51,8 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, * Note that RKL uses the same firmware as TGL. */ #define INTEL_UC_FIRMWARE_DEFS(fw_def, guc_def, huc_def) \ - fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 0, 12)) \ - fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 0, 12)) \ + fw_def(ROCKETLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ + fw_def(TIGERLAKE, 0, guc_def(tgl, 35, 2, 0), huc_def(tgl, 7, 5, 0)) \ fw_def(ELKHARTLAKE, 0, guc_def(ehl, 33, 0, 4), huc_def(ehl, 9, 0, 0)) \ fw_def(ICELAKE, 0, guc_def(icl, 33, 0, 0), huc_def(icl, 9, 0, 0)) \ fw_def(COMETLAKE, 5, guc_def(cml, 33, 0, 0), huc_def(cml, 4, 0, 0)) \ -- cgit v1.2.3 From 9d5cbf5fe46e350715389d89d0c350d83289a102 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Mon, 1 Jun 2020 16:33:22 +0530 Subject: drm/msm: add shutdown support for display platform_driver Define shutdown callback for display drm driver, so as to disable all the CRTCS when shutdown notification is received by the driver. This change will turn off the timing engine so that no display transactions are requested while mmu translations are getting disabled during reboot sequence. Signed-off-by: Krishna Manikandan Changes in v2: - Remove NULL check from msm_pdev_shutdown (Stephen Boyd) - Change commit text to reflect when this issue was uncovered (Sai Prakash Ranjan) Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7d641c7e3514..79333842f70a 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1320,6 +1320,13 @@ static int msm_pdev_remove(struct platform_device *pdev) return 0; } +static void msm_pdev_shutdown(struct platform_device *pdev) +{ + struct drm_device *drm = platform_get_drvdata(pdev); + + drm_atomic_helper_shutdown(drm); +} + static const struct of_device_id dt_match[] = { { .compatible = "qcom,mdp4", .data = (void *)KMS_MDP4 }, { .compatible = "qcom,mdss", .data = (void *)KMS_MDP5 }, @@ -1332,6 +1339,7 @@ MODULE_DEVICE_TABLE(of, dt_match); static struct platform_driver msm_platform_driver = { .probe = msm_pdev_probe, .remove = msm_pdev_remove, + .shutdown = msm_pdev_shutdown, .driver = { .name = "msm", .of_match_table = dt_match, -- cgit v1.2.3 From 9c9b17a7d19a8e21db2e378784fff1128b46c9d3 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Wed, 12 Aug 2020 15:57:32 +0800 Subject: drm/amdgpu: disable gfxoff for navy_flounder gfxoff is temporarily disabled for navy_flounder, since at present the feature has broken some basic amdgpu test. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 65997ffaed45..142ffe2da758 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3595,6 +3595,9 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; + case CHIP_NAVY_FLOUNDER: + adev->pm.pp_feature &= ~PP_GFXOFF_MASK; + break; default: break; } -- cgit v1.2.3 From f5261bec20f4ed1795d7873ffcda649db686f195 Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Thu, 6 Aug 2020 23:41:47 +0800 Subject: drm/amdgpu: fix uninit-value in arcturus_log_thermal_throttling_event() when function arcturus_get_smu_metrics_data() call failed, it will cause the variable "throttler_status" isn't initialized before use. warning: powerplay/arcturus_ppt.c:2268:24: warning: ‘throttler_status’ may be used uninitialized in this function [-Wmaybe-uninitialized] 2268 | if (throttler_status & logging_label[throttler_idx].feature_mask) { Signed-off-by: Kevin Wang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index 6c991de8f371..fb962b9ceffb 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -2204,14 +2204,17 @@ static const struct throttling_logging_label { }; static void arcturus_log_thermal_throttling_event(struct smu_context *smu) { + int ret; int throttler_idx, throtting_events = 0, buf_idx = 0; struct amdgpu_device *adev = smu->adev; uint32_t throttler_status; char log_buf[256]; - arcturus_get_smu_metrics_data(smu, - METRICS_THROTTLER_STATUS, - &throttler_status); + ret = arcturus_get_smu_metrics_data(smu, + METRICS_THROTTLER_STATUS, + &throttler_status); + if (ret) + return; memset(log_buf, 0, sizeof(log_buf)); for (throttler_idx = 0; throttler_idx < ARRAY_SIZE(logging_label); -- cgit v1.2.3 From 1a68d96f81b8e7eb2a121fbf9abf9e5974e58832 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Thu, 13 Aug 2020 14:35:35 +0800 Subject: drm/amdgpu: fix NULL pointer access issue when unloading driver When unloading driver by "modprobe -r amdgpu", one NULL pointer dereference bug occurs in ras debugfs releasing. The cause is the duplicated debugfs_remove, as drm debugfs_root dir has been cleaned up already by drm_minor_unregister. BUG: kernel NULL pointer dereference, address: 00000000000000a0 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 11 PID: 1526 Comm: modprobe Tainted: G OE 5.6.0-guchchen #1 Hardware name: System manufacturer System Product Name/TUF Z370-PLUS GAMING II, BIOS 0411 09/21/2018 RIP: 0010:down_write+0x15/0x40 Code: eb de e8 7e 17 72 ff cc cc cc cc cc cc cc cc cc cc cc cc cc cc 0f 1f 44 00 00 53 48 89 fb e8 92 d8 ff ff 31 c0 ba 01 00 00 00 48 0f b1 13 75 0f 65 48 8b 04 25 c0 8b 01 00 48 89 43 08 5b c3 RSP: 0018:ffffb1590386fcd0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 00000000000000a0 RCX: 0000000000000000 RDX: 0000000000000001 RSI: ffffffff85b2fcc2 RDI: 00000000000000a0 RBP: ffffb1590386fd30 R08: ffffffff85b2fcc2 R09: 000000000002b3c0 R10: ffff97a330618c40 R11: 00000000000005f6 R12: ffff97a3481beb40 R13: 00000000000000a0 R14: ffff97a3481beb40 R15: 0000000000000000 FS: 00007fb11a717540(0000) GS:ffff97a376cc0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000a0 CR3: 00000004066d6006 CR4: 00000000003606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: simple_recursive_removal+0x63/0x370 ? debugfs_remove+0x60/0x60 debugfs_remove+0x40/0x60 amdgpu_ras_fini+0x82/0x230 [amdgpu] ? __kernfs_remove.part.17+0x101/0x1f0 ? kernfs_name_hash+0x12/0x80 amdgpu_device_fini+0x1c0/0x580 [amdgpu] amdgpu_driver_unload_kms+0x3e/0x70 [amdgpu] amdgpu_pci_remove+0x36/0x60 [amdgpu] pci_device_remove+0x3b/0xb0 device_release_driver_internal+0xe5/0x1c0 driver_detach+0x46/0x90 bus_remove_driver+0x58/0xd0 pci_unregister_driver+0x29/0x90 amdgpu_exit+0x11/0x25 [amdgpu] __x64_sys_delete_module+0x13d/0x210 do_syscall_64+0x5f/0x250 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: Guchun Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index bcce4c0be462..1bedb416eebd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1243,7 +1243,6 @@ void amdgpu_ras_debugfs_remove(struct amdgpu_device *adev, if (!obj || !obj->ent) return; - debugfs_remove(obj->ent); obj->ent = NULL; put_obj(obj); } @@ -1257,7 +1256,6 @@ static void amdgpu_ras_debugfs_remove_all(struct amdgpu_device *adev) amdgpu_ras_debugfs_remove(adev, &obj->head); } - debugfs_remove_recursive(con->dir); con->dir = NULL; } /* debugfs end */ -- cgit v1.2.3 From 0a668aee0ac288cf36a554eb7f270be2ca8ef476 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Tue, 28 Jul 2020 11:35:54 -0400 Subject: drm/amdgpu: parse ta firmware for navy_flounder Use the same case as sienna_cichlid Signed-off-by: Bhawanpreet Lakha Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v11_0.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c index d488d250805d..e16874f30d5d 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c @@ -179,12 +179,11 @@ static int psp_v11_0_init_microcode(struct psp_context *psp) } break; case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: err = psp_init_ta_microcode(&adev->psp, chip_name); if (err) return err; break; - case CHIP_NAVY_FLOUNDER: - break; default: BUG(); } -- cgit v1.2.3 From 34174b89bfa495bed9cddcc504fb38feca90fab7 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 11 Aug 2020 13:54:56 +0800 Subject: drm/amdkfd: fix the wrong sdma instance query for renoir Renoir only has one sdma instance, it will get failed once query the sdma1 registers. So use switch-case instead of static register array. Signed-off-by: Huang Rui Reviewed-by: Alex Deucher Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 31 ++++++++++++++++------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') 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..1102de76d876 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -195,19 +195,32 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, unsigned int engine_id, unsigned int queue_id) { - uint32_t sdma_engine_reg_base[2] = { - SOC15_REG_OFFSET(SDMA0, 0, - mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL, - SOC15_REG_OFFSET(SDMA1, 0, - mmSDMA1_RLC0_RB_CNTL) - mmSDMA1_RLC0_RB_CNTL - }; - uint32_t retval = sdma_engine_reg_base[engine_id] + uint32_t sdma_engine_reg_base = 0; + uint32_t sdma_rlc_reg_offset; + + switch (engine_id) { + default: + dev_warn(adev->dev, + "Invalid sdma engine id (%d), using engine id 0\n", + engine_id); + fallthrough; + case 0: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0, + mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + case 1: + sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA1, 0, + mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; + break; + } + + sdma_rlc_reg_offset = sdma_engine_reg_base + queue_id * (mmSDMA0_RLC1_RB_CNTL - mmSDMA0_RLC0_RB_CNTL); pr_debug("RLC register offset for SDMA%d RLC%d: 0x%x\n", engine_id, - queue_id, retval); + queue_id, sdma_rlc_reg_offset); - return retval; + return sdma_rlc_reg_offset; } static inline struct v9_mqd *get_mqd(void *mqd) -- cgit v1.2.3 From 5dea2142a86d9aafca07f1318851fb729577f03a Mon Sep 17 00:00:00 2001 From: Chris Park Date: Wed, 5 Aug 2020 13:46:40 -0400 Subject: drm/amd/display: Call DMUB for eDP power control [Why] If DMUB is used, LVTMA VBIOS call can be used to control eDP instead of tranditional transmitter control. Interface is agreed with VBIOS for eDP to use this new path to program LVTMA registers. [How] Create DAL interface to send DMUB command for LVTMA as currently implemented in VBIOS. Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 16 ++++++++++++- .../gpu/drm/amd/display/dc/bios/command_table2.c | 28 ++++++++++++++++++++++ .../gpu/drm/amd/display/dc/bios/command_table2.h | 3 ++- drivers/gpu/drm/amd/display/dc/dc_bios_types.h | 4 ++++ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 24 +++++++++++++++++++ .../drm/amd/display/include/bios_parser_types.h | 7 ++++++ 6 files changed, 80 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c index 078b7e344185..2d5c7daaee23 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c @@ -1108,6 +1108,18 @@ static enum bp_result bios_parser_enable_disp_power_gating( action); } +static enum bp_result bios_parser_enable_lvtma_control( + struct dc_bios *dcb, + uint8_t uc_pwr_on) +{ + struct bios_parser *bp = BP_FROM_DCB(dcb); + + if (!bp->cmd_tbl.enable_lvtma_control) + return BP_RESULT_FAILURE; + + return bp->cmd_tbl.enable_lvtma_control(bp, uc_pwr_on); +} + static bool bios_parser_is_accelerated_mode( struct dc_bios *dcb) { @@ -2208,7 +2220,9 @@ static const struct dc_vbios_funcs vbios_funcs = { .get_board_layout_info = bios_get_board_layout_info, .pack_data_tables = bios_parser_pack_data_tables, - .get_atom_dc_golden_table = bios_get_atom_dc_golden_table + .get_atom_dc_golden_table = bios_get_atom_dc_golden_table, + + .enable_lvtma_control = bios_parser_enable_lvtma_control }; static bool bios_parser2_construct( diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index bed91572f82a..eb3ae5c3677c 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -904,6 +904,33 @@ static unsigned int get_smu_clock_info_v3_1(struct bios_parser *bp, uint8_t id) return 0; } +/****************************************************************************** + ****************************************************************************** + ** + ** LVTMA CONTROL + ** + ****************************************************************************** + *****************************************************************************/ + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on); + +static void init_enable_lvtma_control(struct bios_parser *bp) +{ + /* TODO add switch for table vrsion */ + bp->cmd_tbl.enable_lvtma_control = enable_lvtma_control; + +} + +static enum bp_result enable_lvtma_control( + struct bios_parser *bp, + uint8_t uc_pwr_on) +{ + enum bp_result result = BP_RESULT_FAILURE; + return result; +} + void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) { init_dig_encoder_control(bp); @@ -919,4 +946,5 @@ void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp) init_set_dce_clock(bp); init_get_smu_clock_info(bp); + init_enable_lvtma_control(bp); } diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h index 7a2af24dfe60..7bdce013cde5 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.h +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.h @@ -94,7 +94,8 @@ struct cmd_tbl { struct bp_set_dce_clock_parameters *bp_params); unsigned int (*get_smu_clock_info)( struct bios_parser *bp, uint8_t id); - + enum bp_result (*enable_lvtma_control)(struct bios_parser *bp, + uint8_t uc_pwr_on); }; void dal_firmware_parser_init_cmd_tbl(struct bios_parser *bp); diff --git a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h index d06d07042a12..0811f941f430 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_bios_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_bios_types.h @@ -136,6 +136,10 @@ struct dc_vbios_funcs { enum bp_result (*get_atom_dc_golden_table)( struct dc_bios *dcb); + + enum bp_result (*enable_lvtma_control)( + struct dc_bios *bios, + uint8_t uc_pwr_on); }; struct bios_registers { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index 49380ed3aeae..45c9e9027886 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -842,6 +842,17 @@ void dce110_edp_power_control( cntl.coherent = false; cntl.lanes_number = LANE_COUNT_FOUR; cntl.hpd_sel = link->link_enc->hpd_source; + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_POWER_ON) + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_ON); + else + bp_result = ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_POWER_OFF); + } + bp_result = link_transmitter_control(ctx->dc_bios, &cntl); if (!power_up) @@ -919,8 +930,21 @@ void dce110_edp_backlight_control( /*edp 1.2*/ if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) edp_receiver_ready_T7(link); + + if (ctx->dc->ctx->dmub_srv && + ctx->dc->debug.dmub_command_table) { + if (cntl.action == TRANSMITTER_CONTROL_BACKLIGHT_ON) + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLON); + else + ctx->dc_bios->funcs->enable_lvtma_control(ctx->dc_bios, + LVTMA_CONTROL_LCD_BLOFF); + } + link_transmitter_control(ctx->dc_bios, &cntl); + + if (enable && link->dpcd_sink_ext_caps.bits.oled) msleep(OLED_POST_T7_DELAY); diff --git a/drivers/gpu/drm/amd/display/include/bios_parser_types.h b/drivers/gpu/drm/amd/display/include/bios_parser_types.h index c30437ae8395..21011edea337 100644 --- a/drivers/gpu/drm/amd/display/include/bios_parser_types.h +++ b/drivers/gpu/drm/amd/display/include/bios_parser_types.h @@ -101,6 +101,13 @@ enum bp_pipe_control_action { ASIC_PIPE_INIT }; +enum bp_lvtma_control_action { + LVTMA_CONTROL_LCD_BLOFF = 2, + LVTMA_CONTROL_LCD_BLON = 3, + LVTMA_CONTROL_POWER_ON = 12, + LVTMA_CONTROL_POWER_OFF = 13 +}; + struct bp_encoder_control { enum bp_encoder_control_action action; enum engine_id engine_id; -- cgit v1.2.3 From 42f8c416521aced2daba61e42d631cc3be2c452b Mon Sep 17 00:00:00 2001 From: Chris Park Date: Wed, 5 Aug 2020 16:59:28 -0400 Subject: drm/amd/display: Assign correct left shift [Why] Reading for DP alt registers return incorrect values due to LE_SF definition missing. [How] Define correct LE_SF or DP alt registers. Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 4 +++- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index bf0044f7417e..dcbf28dd72d4 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -167,7 +167,9 @@ LE_SF(DCIO_SOFT_RESET, UNIPHYB_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYC_SOFT_RESET, mask_sh),\ LE_SF(DCIO_SOFT_RESET, UNIPHYD_SOFT_RESET, mask_sh),\ - LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh) + LE_SF(DCIO_SOFT_RESET, UNIPHYE_SOFT_RESET, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) #define LINK_ENCODER_MASK_SH_LIST_DCN20(mask_sh)\ LINK_ENCODER_MASK_SH_LIST_DCN10(mask_sh),\ diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h index 8e9fd59ccde8..2fbf879cd327 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dio_link_encoder.h @@ -61,7 +61,10 @@ DPCS_DCN2_MASK_SH_LIST(mask_sh),\ LE_SF(DPCSTX0_DPCSTX_TX_CNTL, DPCS_TX_DATA_ORDER_INVERT_18_BIT, mask_sh),\ LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL0, RDPCS_PHY_TX_VBOOST_LVL, mask_sh),\ - LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh) + LE_SF(RDPCSTX0_RDPCSTX_CLOCK_CNTL, RDPCS_TX_CLK_EN, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DP4, mask_sh),\ + LE_SF(RDPCSTX0_RDPCSTX_PHY_CNTL6, RDPCS_PHY_DPALT_DISABLE, mask_sh) + void dcn30_link_encoder_construct( struct dcn20_link_encoder *enc20, -- cgit v1.2.3 From 8e80d482608a4e6a97c75272ef8b4bcfc5d0c490 Mon Sep 17 00:00:00 2001 From: Paul Hsieh Date: Wed, 5 Aug 2020 17:28:37 +0800 Subject: drm/amd/display: Fix DFPstate hang due to view port changed [Why] Place the cursor in the center of screen between two pipes then adjusting the viewport but cursour doesn't update cause DFPstate hang. [How] If viewport changed, update cursor as well. Cc: stable@vger.kernel.org Signed-off-by: Paul Hsieh Reviewed-by: Aric Cyr Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 66180b4332f1..c8cfd3ba1c15 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -1457,8 +1457,8 @@ static void dcn20_update_dchubp_dpp( /* Any updates are handled in dc interface, just need to apply existing for plane enable */ if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed || - pipe_ctx->update_flags.bits.scaler || pipe_ctx->update_flags.bits.viewport) - && pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { + pipe_ctx->update_flags.bits.scaler || viewport_changed == true) && + pipe_ctx->stream->cursor_attributes.address.quad_part != 0) { dc->hwss.set_cursor_position(pipe_ctx); dc->hwss.set_cursor_attribute(pipe_ctx); -- cgit v1.2.3 From 5ec37c089e7d02265b4e2ed9529bc7497fc1cf5a Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Thu, 6 Aug 2020 13:57:08 -0400 Subject: drm/amd/display: fix dcn3 wide timing dsc validation Wide timing DSC requires odm. Since spreadsheet is missing this dsc validation we have to modify DML vba code ourselves. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Wesley Chalmers Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index b54814f11b74..2beb284f89b0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -63,6 +63,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff +#define DCN30_MAX_DSC_IMAGE_WIDTH 5184 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -3984,6 +3985,9 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; -- cgit v1.2.3 From db0473f62438e075b6832fd1490fd06d03c59372 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Thu, 6 Aug 2020 15:40:01 -0400 Subject: drm/amd/display: Reset scrambling on Test Pattern [Why] Programming is missing the sequence where for eDP the scrambling is reset when testing for eye diagram test pattern. [How] Include the required register in the definition Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 653a571e366d..ebe0cc5b833b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } static const struct dce110_aux_registers_shift aux_shift = { -- cgit v1.2.3 From d2e59d0ff4c44d1f6f8ed884a5bea7d1bb7fd98c Mon Sep 17 00:00:00 2001 From: Krunoslav Kovac Date: Thu, 6 Aug 2020 17:54:47 -0400 Subject: drm/amd/display: fix pow() crashing when given base 0 [Why&How] pow(a,x) is implemented as exp(x*log(a)). log(0) will crash. So return 0^x = 0, unless x=0, convention seems to be 0^0 = 1. Cc: stable@vger.kernel.org Signed-off-by: Krunoslav Kovac Reviewed-by: Anthony Koo Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/include/fixed31_32.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h index 89ef9f6860e5..16df2a485dd0 100644 --- a/drivers/gpu/drm/amd/display/include/fixed31_32.h +++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h @@ -431,6 +431,9 @@ struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg); */ static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2) { + if (arg1.value == 0) + return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero; + return dc_fixpt_exp( dc_fixpt_mul( dc_fixpt_log(arg1), -- cgit v1.2.3 From 5960e02290357504b18f79fdda6de2f4d4812926 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Mon, 17 Aug 2020 13:46:56 -0400 Subject: drm/amdkfd: Initialize SDMA activity counter to 0 To prevent reporting erroneous SDMA usage, initialize SDMA activity counter to 0 before using. Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 40695d52e9a8..ddd192e3197c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -270,6 +270,7 @@ static ssize_t kfd_procfs_show(struct kobject *kobj, struct attribute *attr, kfd_sdma_activity_worker); sdma_activity_work_handler.pdd = pdd; + sdma_activity_work_handler.sdma_activity_counter = 0; schedule_work(&sdma_activity_work_handler.sdma_activity_work); -- cgit v1.2.3 From c80e966b54096e50264af62a350c621708a4fcd2 Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Mon, 17 Aug 2020 15:26:41 -0400 Subject: drm/amd/display: Add dsc_to_stream_resource for dcn3 Without this, enabling dsc will cause a nullptr Reviewed-by: Mikita Lipski Signed-off-by: Bhawanpreet Lakha Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 1ee9087eec76..957fc37b971e 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -2424,6 +2424,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = { .populate_dml_pipes = dcn30_populate_dml_pipes_from_context, .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer, .add_stream_to_ctx = dcn30_add_stream_to_ctx, + .add_dsc_to_stream_resource = dcn20_add_dsc_to_stream_resource, .remove_stream_from_ctx = dcn20_remove_stream_from_ctx, .populate_dml_writeback_from_context = dcn30_populate_dml_writeback_from_context, .set_mcif_arb_params = dcn30_set_mcif_arb_params, -- cgit v1.2.3 From e2d732fdb7a9e421720a644580cd6a9400f97f60 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Tue, 11 Aug 2020 19:59:58 -0400 Subject: drm/scheduler: Scheduler priority fixes (v2) Remove DRM_SCHED_PRIORITY_LOW, as it was used in only one place. Rename and separate by a line DRM_SCHED_PRIORITY_MAX to DRM_SCHED_PRIORITY_COUNT as it represents a (total) count of said priorities and it is used as such in loops throughout the code. (0-based indexing is the the count number.) Remove redundant word HIGH in priority names, and rename *KERNEL* to *HIGH*, as it really means that, high. v2: Add back KERNEL and remove SW and HW, in lieu of a single HIGH between NORMAL and KERNEL. Signed-off-by: Luben Tuikov Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/scheduler/sched_main.c | 4 ++-- include/drm/gpu_scheduler.h | 12 +++++++----- 8 files changed, 18 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 8842c55d4490..fc695126b6e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -46,7 +46,7 @@ const unsigned int amdgpu_ctx_num_entities[AMDGPU_HW_IP_NUM] = { static int amdgpu_ctx_priority_permit(struct drm_file *filp, enum drm_sched_priority priority) { - if (priority < 0 || priority >= DRM_SCHED_PRIORITY_MAX) + if (priority < 0 || priority >= DRM_SCHED_PRIORITY_COUNT) return -EINVAL; /* NORMAL and below are accessible by everyone */ @@ -65,7 +65,7 @@ static int amdgpu_ctx_priority_permit(struct drm_file *filp, static enum gfx_pipe_priority amdgpu_ctx_sched_prio_to_compute_prio(enum drm_sched_priority prio) { switch (prio) { - case DRM_SCHED_PRIORITY_HIGH_HW: + case DRM_SCHED_PRIORITY_HIGH: case DRM_SCHED_PRIORITY_KERNEL: return AMDGPU_GFX_PIPE_PRIO_HIGH; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 937029ad5271..dcfe8a3b03ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -251,7 +251,7 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched) int i; /* Signal all jobs not yet scheduled */ - for (i = DRM_SCHED_PRIORITY_MAX - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { struct drm_sched_rq *rq = &sched->sched_rq[i]; if (!rq) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 13ea8ebc421c..6d4fc79bf84a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -267,7 +267,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, &ring->sched; } - for (i = 0; i < DRM_SCHED_PRIORITY_MAX; ++i) + for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_COUNT; ++i) atomic_set(&ring->num_jobs[i], 0); return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index da871d84b742..7112137689db 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -243,7 +243,7 @@ struct amdgpu_ring { bool has_compute_vm_bug; bool no_scheduler; - atomic_t num_jobs[DRM_SCHED_PRIORITY_MAX]; + atomic_t num_jobs[DRM_SCHED_PRIORITY_COUNT]; struct mutex priority_mutex; /* protected by priority_mutex */ int priority; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index c799691dfa84..17661ede9488 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -36,14 +36,14 @@ enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority) { switch (amdgpu_priority) { case AMDGPU_CTX_PRIORITY_VERY_HIGH: - return DRM_SCHED_PRIORITY_HIGH_HW; + return DRM_SCHED_PRIORITY_HIGH; case AMDGPU_CTX_PRIORITY_HIGH: - return DRM_SCHED_PRIORITY_HIGH_SW; + return DRM_SCHED_PRIORITY_HIGH; case AMDGPU_CTX_PRIORITY_NORMAL: return DRM_SCHED_PRIORITY_NORMAL; case AMDGPU_CTX_PRIORITY_LOW: case AMDGPU_CTX_PRIORITY_VERY_LOW: - return DRM_SCHED_PRIORITY_LOW; + return DRM_SCHED_PRIORITY_MIN; case AMDGPU_CTX_PRIORITY_UNSET: return DRM_SCHED_PRIORITY_UNSET; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 2d502e98fad0..3d2712a4cf4d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2109,7 +2109,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) ring = adev->mman.buffer_funcs_ring; sched = &ring->sched; r = drm_sched_entity_init(&adev->mman.entity, - DRM_SCHED_PRIORITY_KERNEL, &sched, + DRM_SCHED_PRIORITY_KERNEL, &sched, 1, NULL); if (r) { DRM_ERROR("Failed setting up TTM BO move entity (%d)\n", diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 2f319102ae9f..19f381e5e661 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -623,7 +623,7 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched) return NULL; /* Kernel run queue has higher priority than normal run queue*/ - for (i = DRM_SCHED_PRIORITY_MAX - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { entity = drm_sched_rq_select_entity(&sched->sched_rq[i]); if (entity) break; @@ -851,7 +851,7 @@ int drm_sched_init(struct drm_gpu_scheduler *sched, sched->name = name; sched->timeout = timeout; sched->hang_limit = hang_limit; - for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_MAX; i++) + for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_COUNT; i++) drm_sched_rq_init(sched, &sched->sched_rq[i]); init_waitqueue_head(&sched->wake_up_worker); diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index a21b3b92135a..b30026ccd564 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -33,14 +33,16 @@ struct drm_gpu_scheduler; struct drm_sched_rq; +/* These are often used as an (initial) index + * to an array, and as such should start at 0. + */ enum drm_sched_priority { DRM_SCHED_PRIORITY_MIN, - DRM_SCHED_PRIORITY_LOW = DRM_SCHED_PRIORITY_MIN, DRM_SCHED_PRIORITY_NORMAL, - DRM_SCHED_PRIORITY_HIGH_SW, - DRM_SCHED_PRIORITY_HIGH_HW, + DRM_SCHED_PRIORITY_HIGH, DRM_SCHED_PRIORITY_KERNEL, - DRM_SCHED_PRIORITY_MAX, + + DRM_SCHED_PRIORITY_COUNT, DRM_SCHED_PRIORITY_INVALID = -1, DRM_SCHED_PRIORITY_UNSET = -2 }; @@ -274,7 +276,7 @@ struct drm_gpu_scheduler { uint32_t hw_submission_limit; long timeout; const char *name; - struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_MAX]; + struct drm_sched_rq sched_rq[DRM_SCHED_PRIORITY_COUNT]; wait_queue_head_t wake_up_worker; wait_queue_head_t job_scheduled; atomic_t hw_rq_count; -- cgit v1.2.3 From 9af5e21dace795891544042abda877ada39abacc Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Tue, 11 Aug 2020 20:56:58 -0400 Subject: drm/scheduler: Remove priority macro INVALID (v2) Remove DRM_SCHED_PRIORITY_INVALID. We no longer carry around an invalid priority and cut it off at the source. Backwards compatibility behaviour of AMDGPU CTX IOCTL passing in garbage for context priority from user space and then mapping that to DRM_SCHED_PRIORITY_NORMAL is preserved. v2: Revert "res" --> "r" and "prio" --> "priority". Signed-off-by: Luben Tuikov Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 5 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 40 +++++++++++++++++++++++-------- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h | 3 ++- include/drm/gpu_scheduler.h | 1 - 4 files changed, 34 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index fc695126b6e7..ba243cc8f585 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -388,13 +388,12 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct amdgpu_device *adev = dev->dev_private; struct amdgpu_fpriv *fpriv = filp->driver_priv; - r = 0; id = args->in.ctx_id; - priority = amdgpu_to_sched_priority(args->in.priority); + r = amdgpu_to_sched_priority(args->in.priority, &priority); /* For backwards compatibility reasons, we need to accept * ioctls with garbage in the priority field */ - if (priority == DRM_SCHED_PRIORITY_INVALID) + if (r == -EINVAL) priority = DRM_SCHED_PRIORITY_NORMAL; switch (args->in.op) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index 17661ede9488..9581283a4c78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -32,24 +32,32 @@ #include "amdgpu_vm.h" -enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority) +int amdgpu_to_sched_priority(int amdgpu_priority, + enum drm_sched_priority *prio) { switch (amdgpu_priority) { case AMDGPU_CTX_PRIORITY_VERY_HIGH: - return DRM_SCHED_PRIORITY_HIGH; + *prio = DRM_SCHED_PRIORITY_HIGH; + break; case AMDGPU_CTX_PRIORITY_HIGH: - return DRM_SCHED_PRIORITY_HIGH; + *prio = DRM_SCHED_PRIORITY_HIGH; + break; case AMDGPU_CTX_PRIORITY_NORMAL: - return DRM_SCHED_PRIORITY_NORMAL; + *prio = DRM_SCHED_PRIORITY_NORMAL; + break; case AMDGPU_CTX_PRIORITY_LOW: case AMDGPU_CTX_PRIORITY_VERY_LOW: - return DRM_SCHED_PRIORITY_MIN; + *prio = DRM_SCHED_PRIORITY_MIN; + break; case AMDGPU_CTX_PRIORITY_UNSET: - return DRM_SCHED_PRIORITY_UNSET; + *prio = DRM_SCHED_PRIORITY_UNSET; + break; default: WARN(1, "Invalid context priority %d\n", amdgpu_priority); - return DRM_SCHED_PRIORITY_INVALID; + return -EINVAL; } + + return 0; } static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev, @@ -119,9 +127,20 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, enum drm_sched_priority priority; int r; - priority = amdgpu_to_sched_priority(args->in.priority); - if (priority == DRM_SCHED_PRIORITY_INVALID) + /* First check the op, then the op's argument. + */ + switch (args->in.op) { + case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: + case AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE: + break; + default: + DRM_ERROR("Invalid sched op specified: %d\n", args->in.op); return -EINVAL; + } + + r = amdgpu_to_sched_priority(args->in.priority, &priority); + if (r) + return r; switch (args->in.op) { case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: @@ -136,7 +155,8 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, priority); break; default: - DRM_ERROR("Invalid sched op specified: %d\n", args->in.op); + /* Impossible. + */ r = -EINVAL; break; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h index 12299fd95691..67e5b2472f6a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h @@ -30,7 +30,8 @@ enum drm_sched_priority; struct drm_device; struct drm_file; -enum drm_sched_priority amdgpu_to_sched_priority(int amdgpu_priority); +int amdgpu_to_sched_priority(int amdgpu_priority, + enum drm_sched_priority *prio); int amdgpu_sched_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index b30026ccd564..a33590e62108 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -43,7 +43,6 @@ enum drm_sched_priority { DRM_SCHED_PRIORITY_KERNEL, DRM_SCHED_PRIORITY_COUNT, - DRM_SCHED_PRIORITY_INVALID = -1, DRM_SCHED_PRIORITY_UNSET = -2 }; -- cgit v1.2.3 From 332d790365dbf33a5babc2f31a33957f7633361b Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Mon, 17 Aug 2020 22:38:38 +0800 Subject: Revert "drm/amdgpu: disable gfxoff for navy_flounder" This reverts commit ba4e049e63b607ac2e0c070b1406826390d5047e. Newly released sdma fw (51.52) provides a fix for the issue. Signed-off-by: Jiansong Chen Reviewed-by: Kenneth Feng Reviewed-by: Tao Zhou Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index e87d43537013..e527be22a3d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3610,9 +3610,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; - case CHIP_NAVY_FLOUNDER: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - break; default: break; } -- cgit v1.2.3 From b109f61e7fe13109a2355f8cf087da0a448ee5de Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Tue, 18 Aug 2020 10:54:06 +0800 Subject: drm/amd/pm: update driver if version for navy_flounder It's in accordance with pmfw 65.7.0 for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 65363d56e3cc..77d0996f4ec2 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -31,7 +31,7 @@ #define SMU11_DRIVER_IF_VERSION_NV12 0x36 #define SMU11_DRIVER_IF_VERSION_NV14 0x36 #define SMU11_DRIVER_IF_VERSION_Sienna_Cichlid 0x35 -#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x3 +#define SMU11_DRIVER_IF_VERSION_Navy_Flounder 0x4 /* MP Apertures */ #define MP0_Public 0x03800000 -- cgit v1.2.3 From 588a4d5c6a9275ad3d2b74780c93c6e5a41fdf41 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 17 Aug 2020 14:52:06 +0800 Subject: drm/amd/pm: disable/enable gfx ulv on UMD pstate enter/exit Add gfx ulv disablement/enablement on UMD pstate entering/exiting. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index bbe4a343e9f1..7cc707ec21c3 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -596,6 +596,7 @@ struct pptable_funcs { int (*set_pp_feature_mask)(struct smu_context *smu, uint64_t new_mask); ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); int (*enable_mgpu_fan_boost)(struct smu_context *smu); + int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 7d17c4f1b489..221b5c923ce1 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1440,6 +1440,7 @@ static int smu_enable_umd_pstate(void *handle, amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_UNGATE); + smu_gfx_ulv_control(smu, false); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1447,6 +1448,7 @@ static int smu_enable_umd_pstate(void *handle, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; smu_dpm_ctx->enable_umd_pstate = false; + smu_gfx_ulv_control(smu, true); amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 264073d4e263..2fe29c6a00ce 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -92,6 +92,7 @@ #define smu_get_asic_power_limits(smu) smu_ppt_funcs(get_power_limit, 0, smu) #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) +#define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) #endif #endif -- cgit v1.2.3 From e988026fcf2694893c5f81aa0aa241c3c7891063 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 17 Aug 2020 15:08:16 +0800 Subject: drm/amd/pm: add SMU11 common gfx ulv control interface Considering the same logic can be applied to Arcturus, Navi1X and Sienna Cichlid. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 11 +++++++++++ 5 files changed, 17 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 77d0996f4ec2..c4743f8d0d23 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -274,5 +274,8 @@ int smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu); void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); +int smu_v11_0_gfx_ulv_control(struct smu_context *smu, + bool enablement); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 81f43fea4d52..aab83b957246 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2391,6 +2391,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = arcturus_get_gpu_metrics, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 4b4d461899df..c968f05533d9 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2660,6 +2660,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = navi10_get_gpu_metrics, .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 407a11c2826b..45b9defebd07 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2796,6 +2796,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, + .gfx_ulv_control = smu_v11_0_gfx_ulv_control, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index ff574ebc179e..3c98060e04b8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1985,3 +1985,14 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics) gpu_metrics->system_clock_counter = ktime_get_boottime_ns(); } + +int smu_v11_0_gfx_ulv_control(struct smu_context *smu, + bool enablement) +{ + int ret = 0; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_GFX_ULV_BIT)) + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_GFX_ULV_BIT, enablement); + + return ret; +} -- cgit v1.2.3 From f0d51d20d918b116571a243ef8c102b914fd5ad8 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 17 Aug 2020 15:52:42 +0800 Subject: drm/amd/pm: disable/enable deep sleep features on UMD pstate enter/exit Add deep sleep disablement/enablement on UMD pstate entering/exiting. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 + drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 7cc707ec21c3..4c5c041af4ee 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -597,6 +597,7 @@ struct pptable_funcs { ssize_t (*get_gpu_metrics)(struct smu_context *smu, void **table); int (*enable_mgpu_fan_boost)(struct smu_context *smu); int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); + int (*deep_sleep_control)(struct smu_context *smu, bool enablement); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 221b5c923ce1..8eb5b92903cd 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1441,6 +1441,7 @@ static int smu_enable_umd_pstate(void *handle, AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_UNGATE); smu_gfx_ulv_control(smu, false); + smu_deep_sleep_control(smu, false); } } else { /* exit umd pstate, restore level, enable gfx cg*/ @@ -1448,6 +1449,7 @@ static int smu_enable_umd_pstate(void *handle, if (*level == AMD_DPM_FORCED_LEVEL_PROFILE_EXIT) *level = smu_dpm_ctx->saved_dpm_level; smu_dpm_ctx->enable_umd_pstate = false; + smu_deep_sleep_control(smu, true); smu_gfx_ulv_control(smu, true); amdgpu_device_ip_set_clockgating_state(smu->adev, AMD_IP_BLOCK_TYPE_GFX, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index 2fe29c6a00ce..c88f8fab1bae 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -93,6 +93,7 @@ #define smu_get_pp_feature_mask(smu, buf) smu_ppt_funcs(get_pp_feature_mask, 0, smu, buf) #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) +#define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement) #endif #endif -- cgit v1.2.3 From 5ce99853a6fd94c729d4b50188f43300d6568898 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 17 Aug 2020 16:05:10 +0800 Subject: drm/amd/pm: add SMU11 common deep sleep control interface Considering the same logic can be applied to Arcturus, Navi1X and Sienna Cichlid. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 ++ drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 + .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 + drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 33 ++++++++++++++++++++++ 5 files changed, 39 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index c4743f8d0d23..2a3f1ee4a50b 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -277,5 +277,8 @@ void smu_v11_0_init_gpu_metrics_v1_0(struct gpu_metrics_v1_0 *gpu_metrics); int smu_v11_0_gfx_ulv_control(struct smu_context *smu, bool enablement); +int smu_v11_0_deep_sleep_control(struct smu_context *smu, + bool enablement); + #endif #endif diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index aab83b957246..8347b1f2509f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2392,6 +2392,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = arcturus_get_gpu_metrics, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index c968f05533d9..72f3d68691d8 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2661,6 +2661,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .get_gpu_metrics = navi10_get_gpu_metrics, .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 45b9defebd07..8ffa8b71b75f 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2797,6 +2797,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, + .deep_sleep_control = smu_v11_0_deep_sleep_control, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 3c98060e04b8..ec20e839f555 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1996,3 +1996,36 @@ int smu_v11_0_gfx_ulv_control(struct smu_context *smu, return ret; } + +int smu_v11_0_deep_sleep_control(struct smu_context *smu, + bool enablement) +{ + struct amdgpu_device *adev = smu->adev; + int ret = 0; + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_GFXCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_GFXCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s GFXCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s SOCCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_LCLK_BIT)) { + ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_LCLK_BIT, enablement); + if (ret) { + dev_err(adev->dev, "Failed to %s LCLK DS!\n", enablement ? "enable" : "disable"); + return ret; + } + } + + return ret; +} -- cgit v1.2.3 From 9a1cddd6374fb1eb166f40f10d5411e3699066d4 Mon Sep 17 00:00:00 2001 From: jqdeng Date: Fri, 7 Aug 2020 17:31:19 +0800 Subject: drm/amdgpu: Fix repeatly flr issue Only for no job running test case need to do recover in flr notification. For having job in mirror list, then let guest driver to hit job timeout, and then do recover. Signed-off-by: jqdeng Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 2 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 3 ++- 4 files changed, 32 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 08f80ca3b296..54666eea1863 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -1133,6 +1133,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); /* Common functions */ +bool amdgpu_device_has_job_running(struct amdgpu_device *adev); bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev); int amdgpu_device_gpu_recover(struct amdgpu_device *adev, struct amdgpu_job* job); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 415e1a32b98c..6573e1112462 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3922,6 +3922,34 @@ error: return r; } +/** + * amdgpu_device_has_job_running - check if there is any job in mirror list + * + * @adev: amdgpu device pointer + * + * check if there is any job in mirror list + */ +bool amdgpu_device_has_job_running(struct amdgpu_device *adev) +{ + int i; + struct drm_sched_job *job; + + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + struct amdgpu_ring *ring = adev->rings[i]; + + if (!ring || !ring->sched.thread) + continue; + + spin_lock(&ring->sched.job_list_lock); + job = list_first_entry_or_null(&ring->sched.ring_mirror_list, + struct drm_sched_job, node); + spin_unlock(&ring->sched.job_list_lock); + if (job) + return true; + } + return false; +} + /** * amdgpu_device_should_recover_gpu - check if we should try GPU recovery * diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 5fd67e1cc2a0..475ff5df8c87 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -268,7 +268,7 @@ flr_done: /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT) + && (amdgpu_device_has_job_running(adev) || adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT)) amdgpu_device_gpu_recover(adev, NULL); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index ce2bf1fb79ed..9cf695c05db3 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -289,7 +289,8 @@ flr_done: /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) - && (adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || + && (amdgpu_device_has_job_running(adev) || + adev->sdma_timeout == MAX_SCHEDULE_TIMEOUT || adev->gfx_timeout == MAX_SCHEDULE_TIMEOUT || adev->compute_timeout == MAX_SCHEDULE_TIMEOUT || adev->video_timeout == MAX_SCHEDULE_TIMEOUT)) -- cgit v1.2.3 From 8e1d88f948f33f2e34dbf13c3e9fc4228f1331af Mon Sep 17 00:00:00 2001 From: jqdeng Date: Thu, 30 Jul 2020 14:48:40 +0800 Subject: drm/amdgpu: Limit the error info print rate Use function printk_ratelimit to limit the print rate. Signed-off-by: jqdeng Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 10c0779aba73..e84a6e0bc784 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1305,7 +1305,8 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) r = amdgpu_cs_parser_init(&parser, data); if (r) { - DRM_ERROR("Failed to initialize parser %d!\n", r); + if (printk_ratelimit()) + DRM_ERROR("Failed to initialize parser %d!\n", r); goto out; } -- cgit v1.2.3 From cdab4211f66ec961a481e3b9d088e253b358cd1e Mon Sep 17 00:00:00 2001 From: Leo Liu Date: Fri, 14 Aug 2020 11:08:59 -0400 Subject: drm/amdgpu/jpeg: remove redundant check when it returns Fix warning from kernel test robot v2: remove the local variable as well Signed-off-by: Leo Liu Reviewed-by: Alex Deucher Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c index c41e5590a701..3a0dff53654d 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c @@ -460,15 +460,10 @@ static bool jpeg_v3_0_is_idle(void *handle) static int jpeg_v3_0_wait_for_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; - int ret; - ret = SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, + return SOC15_WAIT_ON_RREG(JPEG, 0, mmUVD_JRBC_STATUS, UVD_JRBC_STATUS__RB_JOB_DONE_MASK, UVD_JRBC_STATUS__RB_JOB_DONE_MASK); - if (ret) - return ret; - - return ret; } static int jpeg_v3_0_set_clockgating_state(void *handle, -- cgit v1.2.3 From d0eb1b5ceb2049dee32c469e4242ee7400504b48 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Aug 2020 15:04:44 -0400 Subject: drm/amdgpu/pm: remove duplicate check FAMILY_KV is APUs and we already check for APUs. Reviewed-by: Evan Quan Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 5fc6a9a13096..f2e70655e8d9 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3311,8 +3311,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, } if (((adev->flags & AMD_IS_APU) || - adev->family == AMDGPU_FAMILY_SI || /* not implemented yet */ - adev->family == AMDGPU_FAMILY_KV) && /* not implemented yet */ + adev->family == AMDGPU_FAMILY_SI) && /* not implemented yet */ (attr == &sensor_dev_attr_power1_average.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| -- cgit v1.2.3 From 61426114f246219e065b553d0d613f3b081a2683 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Aug 2020 15:37:54 -0400 Subject: drm/amdgpu/swsmu: implement voltage metrics for RENOIR Grab the data from the SMU metrics table. Reviewed-by: Evan Quan Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 29 +++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 186929c31e9e..ac81f2f605a2 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -616,6 +616,27 @@ static int renoir_get_current_activity_percent(struct smu_context *smu, return 0; } +static int renoir_get_vddc(struct smu_context *smu, uint32_t *value, + unsigned int index) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (index >= 2) + return -EINVAL; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + *value = metrics.Voltage[index]; + + return 0; +} + /** * This interface get dpm clock table for dc */ @@ -952,6 +973,14 @@ static int renoir_read_sensor(struct smu_context *smu, *(uint32_t *)data *= 100; *size = 4; break; + case AMDGPU_PP_SENSOR_VDDGFX: + ret = renoir_get_vddc(smu, (uint32_t *)data, 0); + *size = 4; + break; + case AMDGPU_PP_SENSOR_VDDNB: + ret = renoir_get_vddc(smu, (uint32_t *)data, 1); + *size = 4; + break; default: ret = -EOPNOTSUPP; break; -- cgit v1.2.3 From b49dc928f5a61d6a6dc8b73644bacfaf21b4ae64 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Aug 2020 15:47:31 -0400 Subject: drm/amdgpu/swsmu: implement power metrics for RENOIR Grab the data from the SMU metrics table. Reviewed-by: Evan Quan Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index ac81f2f605a2..3b9ac72c7571 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -637,6 +637,23 @@ static int renoir_get_vddc(struct smu_context *smu, uint32_t *value, return 0; } +static int renoir_get_power(struct smu_context *smu, uint32_t *value) +{ + int ret = 0; + SmuMetrics_t metrics; + + if (!value) + return -EINVAL; + + ret = smu_cmn_get_metrics_table(smu, &metrics, false); + if (ret) + return ret; + + *value = metrics.CurrentSocketPower << 8; + + return 0; +} + /** * This interface get dpm clock table for dc */ @@ -981,6 +998,10 @@ static int renoir_read_sensor(struct smu_context *smu, ret = renoir_get_vddc(smu, (uint32_t *)data, 1); *size = 4; break; + case AMDGPU_PP_SENSOR_GPU_POWER: + ret = renoir_get_power(smu, (uint32_t *)data); + *size = 4; + break; default: ret = -EOPNOTSUPP; break; -- cgit v1.2.3 From 367deb673c2f07e2071b0cfee31a366f6f353f96 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 17 Aug 2020 15:18:01 -0400 Subject: drm/amdgpu/pm: only hide average power on SI and pre-RENOIR APUs We can get this on RENOIR and newer via the SMU metrics table. Reviewed-by: Evan Quan Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index f2e70655e8d9..a77f7347fdfc 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -3312,12 +3312,17 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, if (((adev->flags & AMD_IS_APU) || adev->family == AMDGPU_FAMILY_SI) && /* not implemented yet */ - (attr == &sensor_dev_attr_power1_average.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || + (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| attr == &sensor_dev_attr_power1_cap.dev_attr.attr)) return 0; + if (((adev->family == AMDGPU_FAMILY_SI) || + ((adev->flags & AMD_IS_APU) && + (adev->asic_type < CHIP_RENOIR))) && /* not implemented yet */ + (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) + return 0; + if (!is_support_sw_smu(adev)) { /* hide max/min values if we can't both query and manage the fan */ if ((!adev->powerplay.pp_funcs->set_fan_speed_percent && -- cgit v1.2.3 From 1d5503331b12a76266049289747dfd94f1643fde Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 18 Aug 2020 13:09:14 +0100 Subject: drm/amd/display: fix potential integer overflow when shifting 32 bit variable bl_pwm The 32 bit unsigned integer bl_pwm is being shifted using 32 bit arithmetic and then being assigned to a 64 bit unsigned integer. There is a potential for a 32 bit overflow so cast bl_pwm to enforce a 64 bit shift operation to avoid this. Addresses-Coverity: ("unintentional integer overflow") Fixes: 3ba01817365c ("drm/amd/display: Move panel_cntl specific register from abm to panel_cntl.") Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c index a6d73d30837c..df7f826eebd8 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_panel_cntl.c @@ -76,7 +76,7 @@ static unsigned int dce_get_16_bit_backlight_from_pwm(struct panel_cntl *panel_c else bl_pwm &= 0xFFFF; - current_backlight = bl_pwm << (1 + bl_int_count); + current_backlight = (uint64_t)bl_pwm << (1 + bl_int_count); if (bl_period == 0) bl_period = 0xFFFF; -- cgit v1.2.3 From 16697cf39ed8c5948b44f786bf9bf749dc67692e Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sun, 16 Aug 2020 03:32:12 -0400 Subject: drm/amd/display: should check error using DC_OK core_link_read_dpcd returns only DC_OK(1) and DC_ERROR_UNEXPECTED(-1), the caller should check error using DC_OK instead of checking against 0 Signed-off-by: Tong Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 231929932516..d1d95d3e248a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -4413,9 +4413,9 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link, link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, dpcd_backlight_get.raw, - sizeof(union dpcd_source_backlight_get))) + sizeof(union dpcd_source_backlight_get)) != DC_OK) return false; *backlight_millinits_avg = @@ -4454,9 +4454,9 @@ bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_milli link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, (uint8_t *) backlight_millinits, - sizeof(uint32_t))) + sizeof(uint32_t)) != DC_OK) return false; return true; -- cgit v1.2.3 From 37d0474542850e6bb70b226487b4202d21bfe7cc Mon Sep 17 00:00:00 2001 From: Alexander Monakov Date: Tue, 4 Aug 2020 23:13:13 +0300 Subject: drm/amd/display: use correct scale for actual_brightness Documentation for sysfs backlight level interface requires that values in both 'brightness' and 'actual_brightness' files are interpreted to be in range from 0 to the value given in the 'max_brightness' file. With amdgpu, max_brightness gives 255, and values written by the user into 'brightness' are internally rescaled to a wider range. However, reading from 'actual_brightness' gives the raw register value without inverse rescaling. This causes issues for various userspace tools such as PowerTop and systemd that expect the value to be in the correct range. Introduce a helper to retrieve internal backlight range. Use it to reimplement 'convert_brightness' as 'convert_brightness_from_user' and introduce 'convert_brightness_to_user'. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=203905 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1242 Cc: Alex Deucher Cc: Nicholas Kazlauskas Reviewed-by: Alex Deucher Signed-off-by: Alexander Monakov Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 81 +++++++++++------------ 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') 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 ad6b95d65f7b..0a1e53fda08a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2965,51 +2965,50 @@ static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness) return rc ? 0 : 1; } -static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps, - const uint32_t user_brightness) +static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps, + unsigned *min, unsigned *max) { - u32 min, max, conversion_pace; - u32 brightness = user_brightness; - if (!caps) - goto out; + return 0; - if (!caps->aux_support) { - max = caps->max_input_signal; - min = caps->min_input_signal; - /* - * The brightness input is in the range 0-255 - * It needs to be rescaled to be between the - * requested min and max input signal - * It also needs to be scaled up by 0x101 to - * match the DC interface which has a range of - * 0 to 0xffff - */ - conversion_pace = 0x101; - brightness = - user_brightness - * conversion_pace - * (max - min) - / AMDGPU_MAX_BL_LEVEL - + min * conversion_pace; + if (caps->aux_support) { + // Firmware limits are in nits, DC API wants millinits. + *max = 1000 * caps->aux_max_input_signal; + *min = 1000 * caps->aux_min_input_signal; } else { - /* TODO - * We are doing a linear interpolation here, which is OK but - * does not provide the optimal result. We probably want - * something close to the Perceptual Quantizer (PQ) curve. - */ - max = caps->aux_max_input_signal; - min = caps->aux_min_input_signal; - - brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min - + user_brightness * max; - // Multiple the value by 1000 since we use millinits - brightness *= 1000; - brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL); + // Firmware limits are 8-bit, PWM control is 16-bit. + *max = 0x101 * caps->max_input_signal; + *min = 0x101 * caps->min_input_signal; } + return 1; +} + +static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; -out: - return brightness; + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + // Rescale 0..255 to min..max + return min + DIV_ROUND_CLOSEST((max - min) * brightness, + AMDGPU_MAX_BL_LEVEL); +} + +static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; + + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + if (brightness < min) + return 0; + // Rescale min..max to 0..255 + return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), + max - min); } static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) @@ -3025,7 +3024,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) link = (struct dc_link *)dm->backlight_link; - brightness = convert_brightness(&caps, bd->props.brightness); + brightness = convert_brightness_from_user(&caps, bd->props.brightness); // Change brightness based on AUX property if (caps.aux_support) return set_backlight_via_aux(link, brightness); @@ -3042,7 +3041,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) if (ret == DC_ERROR_UNEXPECTED) return bd->props.brightness; - return ret; + return convert_brightness_to_user(&dm->backlight_caps, ret); } static const struct backlight_ops amdgpu_dm_backlight_ops = { -- cgit v1.2.3 From df3ab3cb7eae63c6eb7c9aebcc196a75d59f65dd Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2020 10:46:43 +0100 Subject: drm/i915: Provide the perf pmu.module Rather than manually implement our own module reference counting for perf pmu events, finally realise that there is a module parameter to struct pmu for this very purpose. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: stable@vger.kernel.org Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200716094643.31410-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi (cherry picked from commit 27e897beec1c59861f15d4d3562c39ad1143620f) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_pmu.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 28bc5f13ae52..056994224c6b 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -445,8 +445,6 @@ static void i915_pmu_event_destroy(struct perf_event *event) container_of(event->pmu, typeof(*i915), pmu.base); drm_WARN_ON(&i915->drm, event->parent); - - module_put(THIS_MODULE); } static int @@ -538,10 +536,8 @@ static int i915_pmu_event_init(struct perf_event *event) if (ret) return ret; - if (!event->parent) { - __module_get(THIS_MODULE); + if (!event->parent) event->destroy = i915_pmu_event_destroy; - } return 0; } @@ -1130,6 +1126,7 @@ void i915_pmu_register(struct drm_i915_private *i915) if (!pmu->base.attr_groups) goto err_attr; + pmu->base.module = THIS_MODULE; pmu->base.task_ctx_nr = perf_invalid_context; pmu->base.event_init = i915_pmu_event_init; pmu->base.add = i915_pmu_event_add; -- cgit v1.2.3 From c499f6cb5ea4708c0c3d76a3c49917f8d905f4d4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:06:00 +0100 Subject: drm/i915: Copy default modparams to mock i915_device Since we use the module parameters stored inside the drm_i915_device itself, we need to ensure the mock i915_device also sets up the right defaults. Fixes: 8a25c4be583d ("drm/i915/params: switch to device specific parameters") Signed-off-by: Chris Wilson Cc: Jani Nikula Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200728150600.4509-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi (cherry picked from commit 98ef067453709444a264939940f7b3a5dfdfa09e) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/selftests/mock_gem_device.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index b9810bf156c3..f127e633f7ca 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -78,6 +78,7 @@ static void mock_device_release(struct drm_device *dev) drm_mode_config_cleanup(&i915->drm); out: + i915_params_free(&i915->params); put_device(&i915->drm.pdev->dev); i915->drm.pdev = NULL; } @@ -165,6 +166,8 @@ struct drm_i915_private *mock_gem_device(void) i915->drm.pdev = pdev; drmm_add_final_kfree(&i915->drm, i915); + i915_params_copy(&i915->params, &i915_modparams); + intel_runtime_pm_init_early(&i915->runtime_pm); /* Using the global GTT may ask questions about KMS users, so prepare */ -- cgit v1.2.3 From b7c664611789a96dd0bb32e0fd3e9bb405ba1179 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 14:09:12 +0100 Subject: drm/i915/display: Check for an LPSP encoder before dereferencing Avoid a GPF at <1>[ 20.177320] BUG: kernel NULL pointer dereference, address: 000000000000007c <1>[ 20.177322] #PF: supervisor read access in kernel mode <1>[ 20.177323] #PF: error_code(0x0000) - not-present page <6>[ 20.177324] PGD 0 P4D 0 <4>[ 20.177327] Oops: 0000 [#1] PREEMPT SMP PTI <4>[ 20.177328] CPU: 1 PID: 944 Comm: debugfs_test Not tainted 5.8.0-rc7-CI-CI_DRM_8814+ #1 <4>[ 20.177330] Hardware name: Dell Inc. XPS 13 9360/0823VW, BIOS 2.9.0 07/09/2018 <4>[ 20.177372] RIP: 0010:i915_lpsp_capability_show+0x44/0xc0 [i915] <4>[ 20.177374] Code: 0f b6 81 ca 0d 00 00 3c 0b 74 77 76 19 3c 0c 75 44 83 7e 7c 01 7e 2f 48 c7 c6 d7 b9 47 a0 e8 43 df 06 e1 31 c0 c3 3c 09 72 2b <8b> 46 7c 85 c0 75 e6 8b 82 e4 00 00 00 89 c2 83 e2 fb 83 fa 0a 74 <4>[ 20.177376] RSP: 0018:ffffc90000cebe38 EFLAGS: 00010246 <4>[ 20.177377] RAX: 0000000000000009 RBX: ffff888267fe6a58 RCX: ffff888252d10000 <4>[ 20.177378] RDX: ffff88824a9a4000 RSI: 0000000000000000 RDI: ffff888267fe6a30 <4>[ 20.177379] RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000001 <4>[ 20.177380] R10: 0000000000000001 R11: 0000000000000000 R12: ffffc90000cebf08 <4>[ 20.177381] R13: 00000000ffffffff R14: 0000000000000001 R15: ffff888267fe6a30 <4>[ 20.177383] FS: 00007f6f9c6b5e40(0000) GS:ffff888276480000(0000) knlGS:0000000000000000 <4>[ 20.177384] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 20.177385] CR2: 000000000000007c CR3: 0000000255f04006 CR4: 00000000003606e0 <4>[ 20.177386] Call Trace: <4>[ 20.177390] seq_read+0xcb/0x420 which is presumably from having no encoder attached at that time. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2175 Fixes: 8806211fe7b3 ("drm/i915: Add i915_lpsp_capability debugfs") Signed-off-by: Chris Wilson Cc: Animesh Manna Cc: Anshuman Gupta Cc: Uma Shankar Cc: "Ville Syrjälä" Reviewed-by: Anshuman Gupta Link: https://patchwork.freedesktop.org/patch/msgid/20200729130912.30093-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi (cherry picked from commit a22b1a9bb0d72a58d5b836653f28d97ee8fea1c4) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3644752cc5ec..5a5cfe25085b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -2044,9 +2044,12 @@ DEFINE_SHOW_ATTRIBUTE(i915_hdcp_sink_capability); static int i915_lpsp_capability_show(struct seq_file *m, void *data) { struct drm_connector *connector = m->private; - struct intel_encoder *encoder = - intel_attached_encoder(to_intel_connector(connector)); struct drm_i915_private *i915 = to_i915(connector->dev); + struct intel_encoder *encoder; + + encoder = intel_attached_encoder(to_intel_connector(connector)); + if (!encoder) + return -ENODEV; if (connector->status != connector_status_connected) return -ENODEV; -- cgit v1.2.3 From 5fd73c53701327e725cd4ca70decb5c9a61f3bac Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 12 Jun 2020 13:47:34 -0700 Subject: drm/i915: Update bw_buddy pagemask table A recent bspec update removed the LPDDR4 single channel entry from the buddy register table, but added a new four-channel entry. Workaround 1409767108 hasn't been updated with any guidance for four channel configurations, so we leave that alternate table unchanged for now. Bspec 49218 Fixes: 3fa01d642fa7 ("drm/i915/tgl: Program BW_BUDDY registers during display init") Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200612204734.3674650-1-matthew.d.roper@intel.com Reviewed-by: Lucas De Marchi Signed-off-by: Rodrigo Vivi (cherry picked from commit ecb40d0826fda213ebb58d49e7d5b4752480e130) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_power.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 0c713e83274d..4929d890bd1c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5240,10 +5240,10 @@ struct buddy_page_mask { }; static const struct buddy_page_mask tgl_buddy_page_masks[] = { - { .num_channels = 1, .type = INTEL_DRAM_LPDDR4, .page_mask = 0xE }, { .num_channels = 1, .type = INTEL_DRAM_DDR4, .page_mask = 0xF }, { .num_channels = 2, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x1C }, { .num_channels = 2, .type = INTEL_DRAM_DDR4, .page_mask = 0x1F }, + { .num_channels = 4, .type = INTEL_DRAM_LPDDR4, .page_mask = 0x38 }, {} }; -- cgit v1.2.3 From c67f0c28311c44597ecd8e14d152d1775c367cdf Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Sun, 2 Aug 2020 19:15:35 +0800 Subject: drm/i915: Fix wrong return value in intel_atomic_check() In the case of calling check_digital_port_conflicts() failed, a negative error code -EINVAL should be returned. Fixes: bf5da83e4bd80 ("drm/i915: Move check_digital_port_conflicts() earier") Cc: Ville Syrjälä Signed-off-by: Tianjia Zhang Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200802111535.5200-1-tianjia.zhang@linux.alibaba.com Signed-off-by: Rodrigo Vivi (cherry picked from commit 66b51b801d05ee54a0f23628cb8220189adb715e) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 729ec6e0d43a..b2ec3a5141cc 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14930,7 +14930,7 @@ static int intel_atomic_check(struct drm_device *dev, if (any_ms && !check_digital_port_conflicts(state)) { drm_dbg_kms(&dev_priv->drm, "rejecting conflicting digital port configuration\n"); - ret = EINVAL; + ret = -EINVAL; goto fail; } -- cgit v1.2.3 From c43a87f537d19499e51a6f013331f196d8f0ddbe Mon Sep 17 00:00:00 2001 From: George Spelvin Date: Wed, 25 Mar 2020 19:24:29 +0000 Subject: drm/i915/selftests: Avoid passing a random 0 into ilog2 igt_mm_config() calls ilog2() on the (pseudo)random 21-bit number s>>12. Once in 2 million seeds, this is zero and ilog2 summons the nasal demons. There was an attempt to handle this case with a max(), but that's too late; ms could already be something bizarre. Given that the low 12 bits of s and ms are always zero, it's a lot simpler just to divide them by 4096, then everything fits into 32 bits, and we can easily generate a random number 1 <= s <= 0x1fffff. Fixes: 14d1b9a6247c ("drm/i915: buddy allocator") Signed-off-by: George Spelvin Cc: Matthew Auld Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Reviewed-by: Matthew Auld Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200325192429.GA8865@SDF.ORG Signed-off-by: Rodrigo Vivi (cherry picked from commit 21118e8e56479ef33460fbd63a5ad0535843b666) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/selftests/i915_buddy.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c b/drivers/gpu/drm/i915/selftests/i915_buddy.c index 939a6caebb03..632b912b0bc9 100644 --- a/drivers/gpu/drm/i915/selftests/i915_buddy.c +++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c @@ -8,8 +8,6 @@ #include "../i915_selftest.h" #include "i915_random.h" -#define SZ_8G (1ULL << 33) - static void __igt_dump_block(struct i915_buddy_mm *mm, struct i915_buddy_block *block, bool buddy) @@ -281,18 +279,22 @@ static int igt_check_mm(struct i915_buddy_mm *mm) static void igt_mm_config(u64 *size, u64 *chunk_size) { I915_RND_STATE(prng); - u64 s, ms; + u32 s, ms; /* Nothing fancy, just try to get an interesting bit pattern */ prandom_seed_state(&prng, i915_selftest.random_seed); - s = i915_prandom_u64_state(&prng) & (SZ_8G - 1); - ms = BIT_ULL(12 + (prandom_u32_state(&prng) % ilog2(s >> 12))); - s = max(s & -ms, ms); + /* Let size be a random number of pages up to 8 GB (2M pages) */ + s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); + /* Let the chunk size be a random power of 2 less than size */ + ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng)); + /* Round size down to the chunk size */ + s &= -ms; - *chunk_size = ms; - *size = s; + /* Convert from pages to bytes */ + *chunk_size = (u64)ms << 12; + *size = (u64)s << 12; } static int igt_buddy_alloc_smoke(void *arg) -- cgit v1.2.3 From 4a4064ad79699ee41b74c12fa4f9f960a5bf9b2d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 21 Jul 2020 02:29:52 +0300 Subject: drm/i915/tgl: Make sure TC-cold is blocked before enabling TC AUX power wells The dependency between power wells is determined by the ordering of the power well list: when enabling the power wells for a domain, this happens walking the power well list forward, while disabling them happens in the reverse direction. Accordingly a power well on the list must follow any other power well it depends on. Since the TC AUX power wells depend on TC-cold being blocked, move the TC-cold off power well before all AUX power wells. Fixes: 3c02934b24e3 ("drm/i915/tc/tgl: Implement TC cold sequences") Cc: José Roberto de Souza Signed-off-by: Imre Deak Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200720232952.16228-1-imre.deak@intel.com Signed-off-by: Rodrigo Vivi (cherry picked from commit b302a2e68807604af2a5015816c1d117747989b6) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_power.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 4929d890bd1c..e0fcb89c736b 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -4146,6 +4146,12 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6, }, }, + { + .name = "TC cold off", + .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, + .ops = &tgl_tc_cold_off_ops, + .id = DISP_PW_ID_NONE, + }, { .name = "AUX A", .domains = TGL_AUX_A_IO_POWER_DOMAINS, @@ -4332,12 +4338,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .hsw.irq_pipe_mask = BIT(PIPE_D), }, }, - { - .name = "TC cold off", - .domains = TGL_TC_COLD_OFF_POWER_DOMAINS, - .ops = &tgl_tc_cold_off_ops, - .id = DISP_PW_ID_NONE, - }, }; static const struct i915_power_well_desc rkl_power_wells[] = { -- cgit v1.2.3 From d24f1341a63cebdff22454a6464810e6f34030c6 Mon Sep 17 00:00:00 2001 From: Matt Atwood Date: Wed, 12 Aug 2020 14:07:02 -0700 Subject: drm/i915: Apply Wa_14011264657:gen11+ Add minimum width to planes, variable with specific formats for gen11+ to reflect recent bspec changes. Signed-off-by: Matt Atwood Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20200812210702.7153-1-matthew.s.atwood@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 60 +++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2ddabf92adde..7d50b7177d40 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3762,6 +3762,44 @@ static int glk_max_plane_width(const struct drm_framebuffer *fb, } } +static int icl_min_plane_width(const struct drm_framebuffer *fb) +{ + /* Wa_14011264657, Wa_14011050563: gen11+ */ + switch (fb->format->format) { + case DRM_FORMAT_C8: + return 18; + case DRM_FORMAT_RGB565: + return 10; + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XRGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_XVYU2101010: + case DRM_FORMAT_Y212: + case DRM_FORMAT_Y216: + return 6; + case DRM_FORMAT_NV12: + return 20; + case DRM_FORMAT_P010: + case DRM_FORMAT_P012: + case DRM_FORMAT_P016: + return 12; + case DRM_FORMAT_XRGB16161616F: + case DRM_FORMAT_XBGR16161616F: + case DRM_FORMAT_ARGB16161616F: + case DRM_FORMAT_ABGR16161616F: + case DRM_FORMAT_XVYU12_16161616: + case DRM_FORMAT_XVYU16161616: + return 4; + default: + return 1; + } +} + static int icl_max_plane_width(const struct drm_framebuffer *fb, int color_plane, unsigned int rotation) @@ -3844,29 +3882,31 @@ static int skl_check_main_surface(struct intel_plane_state *plane_state) int y = plane_state->uapi.src.y1 >> 16; int w = drm_rect_width(&plane_state->uapi.src) >> 16; int h = drm_rect_height(&plane_state->uapi.src) >> 16; - int max_width; - int max_height; - u32 alignment; - u32 offset; + int max_width, min_width, max_height; + u32 alignment, offset; int aux_plane = intel_main_to_aux_plane(fb, 0); u32 aux_offset = plane_state->color_plane[aux_plane].offset; - if (INTEL_GEN(dev_priv) >= 11) + if (INTEL_GEN(dev_priv) >= 11) { max_width = icl_max_plane_width(fb, 0, rotation); - else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) + min_width = icl_min_plane_width(fb); + } else if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv)) { max_width = glk_max_plane_width(fb, 0, rotation); - else + min_width = 1; + } else { max_width = skl_max_plane_width(fb, 0, rotation); + min_width = 1; + } if (INTEL_GEN(dev_priv) >= 11) max_height = icl_max_plane_height(); else max_height = skl_max_plane_height(); - if (w > max_width || h > max_height) { + if (w > max_width || w < min_width || h > max_height) { drm_dbg_kms(&dev_priv->drm, - "requested Y/RGB source size %dx%d too big (limit %dx%d)\n", - w, h, max_width, max_height); + "requested Y/RGB source size %dx%d outside limits (min: %dx1 max: %dx%d)\n", + w, h, min_width, max_width, max_height); return -EINVAL; } -- cgit v1.2.3 From da2446b66b5e2c7f3ab63912c8d999810e35e8b3 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Mon, 17 Aug 2020 22:38:38 +0800 Subject: Revert "drm/amdgpu: disable gfxoff for navy_flounder" This reverts commit 9c9b17a7d19a8e21db2e378784fff1128b46c9d3. Newly released sdma fw (51.52) provides a fix for the issue. Signed-off-by: Jiansong Chen Reviewed-by: Kenneth Feng Reviewed-by: Tao Zhou Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 142ffe2da758..65997ffaed45 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -3595,9 +3595,6 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) if (!gfx_v10_0_navi10_gfxoff_should_enable(adev)) adev->pm.pp_feature &= ~PP_GFXOFF_MASK; break; - case CHIP_NAVY_FLOUNDER: - adev->pm.pp_feature &= ~PP_GFXOFF_MASK; - break; default: break; } -- cgit v1.2.3 From 3b4efa148da36f158cce3f662e831af2834b8e0f Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Mon, 17 Aug 2020 22:59:26 +0300 Subject: drm/i915: Fix cmd parser desc matching with masks Our variety of defined gpu commands have the actual command id field and possibly length and flags applied. We did start to apply the mask during initialization of the cmd descriptors but forgot to also apply it on comparisons. Fix comparisons in order to properly deny access with associated commands. v2: fix lri with correct mask (Chris) References: 926abff21a8f ("drm/i915/cmdparser: Ignore Length operands during command matching") Reported-by: Nicolai Stange Cc: stable@vger.kernel.org # v5.4+ Cc: Miroslav Benes Cc: Takashi Iwai Cc: Tyler Hicks Cc: Jon Bloomfield Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200817195926.12671-1-mika.kuoppala@linux.intel.com --- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 372354d33f55..5ac4a999f05a 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1204,6 +1204,12 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, return dst; } +static inline bool cmd_desc_is(const struct drm_i915_cmd_descriptor * const desc, + const u32 cmd) +{ + return desc->cmd.value == (cmd & desc->cmd.mask); +} + static bool check_cmd(const struct intel_engine_cs *engine, const struct drm_i915_cmd_descriptor *desc, const u32 *cmd, u32 length) @@ -1242,19 +1248,19 @@ static bool check_cmd(const struct intel_engine_cs *engine, * allowed mask/value pair given in the whitelist entry. */ if (reg->mask) { - if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_MEM)) { DRM_DEBUG("CMD: Rejected LRM to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_REG) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_REG)) { DRM_DEBUG("CMD: Rejected LRR to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) && + if (cmd_desc_is(desc, MI_LOAD_REGISTER_IMM(1)) && (offset + 2 > length || (cmd[offset + 1] & reg->mask) != reg->value)) { DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n", @@ -1478,7 +1484,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, break; } - if (desc->cmd.value == MI_BATCH_BUFFER_START) { + if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) { ret = check_bbstart(cmd, offset, length, batch_length, batch_addr, shadow_addr, jump_whitelist); -- cgit v1.2.3 From 43906812eaab06423f56af5cca9a9fcdbb4ac454 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 18 Aug 2020 09:31:19 -0700 Subject: drm/msm: enable vblank during atomic commits This has roughly the same effect as drm_atomic_helper_wait_for_vblanks(), basically just ensuring that vblank accounting is enabled so that we get valid timestamp/seqn on pageflip events. Signed-off-by: Rob Clark Tested-by: Stephen Boyd Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_atomic.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 5ccfad794c6a..561bfa48841c 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -27,6 +27,34 @@ int msm_atomic_prepare_fb(struct drm_plane *plane, return msm_framebuffer_prepare(new_state->fb, kms->aspace); } +/* + * Helpers to control vblanks while we flush.. basically just to ensure + * that vblank accounting is switched on, so we get valid seqn/timestamp + * on pageflip events (if requested) + */ + +static void vblank_get(struct msm_kms *kms, unsigned crtc_mask) +{ + struct drm_crtc *crtc; + + for_each_crtc_mask(kms->dev, crtc, crtc_mask) { + if (!crtc->state->active) + continue; + drm_crtc_vblank_get(crtc); + } +} + +static void vblank_put(struct msm_kms *kms, unsigned crtc_mask) +{ + struct drm_crtc *crtc; + + for_each_crtc_mask(kms->dev, crtc, crtc_mask) { + if (!crtc->state->active) + continue; + drm_crtc_vblank_put(crtc); + } +} + static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx) { unsigned crtc_mask = BIT(crtc_idx); @@ -44,6 +72,8 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx) kms->funcs->enable_commit(kms); + vblank_get(kms, crtc_mask); + /* * Flush hardware updates: */ @@ -58,6 +88,8 @@ static void msm_atomic_async_commit(struct msm_kms *kms, int crtc_idx) kms->funcs->wait_flush(kms, crtc_mask); trace_msm_atomic_wait_flush_finish(crtc_mask); + vblank_put(kms, crtc_mask); + mutex_lock(&kms->commit_lock); kms->funcs->complete_commit(kms, crtc_mask); mutex_unlock(&kms->commit_lock); @@ -221,6 +253,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state) */ kms->pending_crtc_mask &= ~crtc_mask; + vblank_get(kms, crtc_mask); + /* * Flush hardware updates: */ @@ -235,6 +269,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state *state) kms->funcs->wait_flush(kms, crtc_mask); trace_msm_atomic_wait_flush_finish(crtc_mask); + vblank_put(kms, crtc_mask); + mutex_lock(&kms->commit_lock); kms->funcs->complete_commit(kms, crtc_mask); mutex_unlock(&kms->commit_lock); -- cgit v1.2.3 From f5749d6181fa7df5ae741788e5d96f593d3a60b6 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Thu, 20 Aug 2020 12:36:22 +0300 Subject: drm/msm/a6xx: fix gmu start on newer firmware New Qualcomm firmware has changed a way it reports back the 'started' event. Support new register values. Signed-off-by: Dmitry Baryshkov Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index 5b2df7d48138..b3b5047bb7e7 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -200,6 +200,16 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) { int ret; u32 val; + u32 mask, reset_val; + + val = gmu_read(gmu, REG_A6XX_GMU_CM3_DTCM_START + 0xff8); + if (val <= 0x20010004) { + mask = 0xffffffff; + reset_val = 0xbabeface; + } else { + mask = 0x1ff; + reset_val = 0x100; + } gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 1); @@ -211,7 +221,7 @@ static int a6xx_gmu_start(struct a6xx_gmu *gmu) gmu_write(gmu, REG_A6XX_GMU_CM3_SYSRESET, 0); ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_CM3_FW_INIT_RESULT, val, - val == 0xbabeface, 100, 10000); + (val & mask) == reset_val, 100, 10000); if (ret) DRM_DEV_ERROR(gmu->dev, "GMU firmware initialization timed out\n"); -- cgit v1.2.3 From f74cacf5d2bf71c2b415dbb9f100f2c705ad5182 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 8 Aug 2020 10:29:11 -0700 Subject: drm/msm/a6xx: fix crashdec section name typo Backport note: maybe wait some time for the crashdec MR[1] to look for both the old typo'd name and the corrected name to land in mesa 20.2 [1] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6242 Fixes: 1707add81551 ("drm/msm/a6xx: Add a6xx gpu state") Signed-off-by: Rob Clark Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h index 846fd5b54c23..2fb58b7098e4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h @@ -372,7 +372,7 @@ static const struct a6xx_indexed_registers { u32 data; u32 count; } a6xx_indexed_reglist[] = { - { "CP_SEQ_STAT", REG_A6XX_CP_SQE_STAT_ADDR, + { "CP_SQE_STAT", REG_A6XX_CP_SQE_STAT_ADDR, REG_A6XX_CP_SQE_STAT_DATA, 0x33 }, { "CP_DRAW_STATE", REG_A6XX_CP_DRAW_STATE_ADDR, REG_A6XX_CP_DRAW_STATE_DATA, 0x100 }, -- cgit v1.2.3 From 6f7cd6e40b94d498049c1a8664c15bf5863ae578 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 11 Aug 2020 16:36:57 -0700 Subject: drm/msm/a6xx: add module param to enable debugbus snapshot For production devices, the debugbus sections will typically be fused off and empty in the gpu device coredump. But since this may contain data like cache contents, don't capture it by default. Signed-off-by: Rob Clark Reviewed-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 3 ++- drivers/gpu/drm/msm/adreno/adreno_device.c | 4 ++++ drivers/gpu/drm/msm/adreno/adreno_gpu.h | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 959656ad6987..b12f5b4a1bea 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -938,7 +938,8 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) msm_gem_kernel_put(dumper.bo, gpu->aspace, true); } - a6xx_get_debugbus(gpu, a6xx_state); + if (snapshot_debugbus) + a6xx_get_debugbus(gpu, a6xx_state); return &a6xx_state->base; } diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index 4e84f3c76f4f..9eeb46bf2a5d 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -14,6 +14,10 @@ bool hang_debug = false; MODULE_PARM_DESC(hang_debug, "Dump registers when hang is detected (can be slow!)"); module_param_named(hang_debug, hang_debug, bool, 0600); +bool snapshot_debugbus = false; +MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredump (if not fused off)"); +module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600); + static const struct adreno_info gpulist[] = { { .rev = ADRENO_REV(2, 0, 0, 0), diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 99bb468f5f24..e55abae365b5 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -21,6 +21,8 @@ #define REG_SKIP ~0 #define REG_ADRENO_SKIP(_offset) [_offset] = REG_SKIP +extern bool snapshot_debugbus; + /** * adreno_regs: List of registers that are used in across all * 3D devices. Each device type has different offset value for the same -- cgit v1.2.3 From 5e0c22d4a9ddae4e784a3e171b9d3d452b37aeb2 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 13 Aug 2020 14:54:48 -0400 Subject: drm/msm/a6xx: fix frequency not always being restored on GMU resume The patch reorganizing the set_freq function made it so the gmu resume doesn't always set the frequency, because a6xx_gmu_set_freq() exits early when the frequency hasn't been changed. Note this always happens when resuming GMU after recovering from a hang. Use a simple workaround to prevent this from happening. Fixes: 1f60d11423db ("drm: msm: a6xx: send opp instead of a frequency") Signed-off-by: Jonathan Marek Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index b3b5047bb7e7..46a29e383bfd 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -851,6 +851,7 @@ static void a6xx_gmu_set_initial_freq(struct msm_gpu *gpu, struct a6xx_gmu *gmu) if (IS_ERR_OR_NULL(gpu_opp)) return; + gmu->freq = 0; /* so a6xx_gmu_set_freq() doesn't exit early */ a6xx_gmu_set_freq(gpu, gpu_opp); dev_pm_opp_put(gpu_opp); } -- cgit v1.2.3 From df561f6688fef775baa341a0f5d960becd248b11 Mon Sep 17 00:00:00 2001 From: Gustavo A. R. Silva Date: Sun, 23 Aug 2020 17:36:59 -0500 Subject: treewide: Use fallthrough pseudo-keyword Replace the existing /* fall through */ comments and its variants with the new pseudo-keyword macro fallthrough[1]. Also, remove unnecessary fall-through markings when it is the case. [1] https://www.kernel.org/doc/html/v5.7/process/deprecated.html?highlight=fallthrough#implicit-switch-case-fall-through Signed-off-by: Gustavo A. R. Silva --- arch/alpha/kernel/module.c | 2 +- arch/alpha/kernel/signal.c | 2 +- arch/alpha/kernel/traps.c | 4 +- arch/arc/kernel/disasm.c | 2 +- arch/arc/kernel/signal.c | 2 +- arch/arc/kernel/unwind.c | 6 +- arch/arm/kernel/hw_breakpoint.c | 10 +- arch/arm/kernel/signal.c | 2 +- arch/arm/mach-ep93xx/crunch.c | 2 +- arch/arm/mach-mmp/pm-mmp2.c | 8 +- arch/arm/mach-mmp/pm-pxa910.c | 10 +- arch/arm/mach-omap2/id.c | 8 -- arch/arm/mach-omap2/omap_device.c | 2 +- arch/arm/mach-orion5x/dns323-setup.c | 2 +- arch/arm/mach-rpc/riscpc.c | 2 +- arch/arm/mach-tegra/reset.c | 2 +- arch/arm/mm/alignment.c | 4 +- arch/arm/mm/proc-v7-bugs.c | 2 +- arch/arm/plat-omap/dma.c | 6 +- arch/arm/probes/decode.c | 2 +- arch/arm/probes/kprobes/core.c | 2 +- arch/arm64/kernel/acpi.c | 2 +- arch/arm64/kernel/cpufeature.c | 2 +- arch/arm64/kernel/cpuinfo.c | 2 +- arch/arm64/kernel/hw_breakpoint.c | 6 +- arch/arm64/kernel/module.c | 8 +- arch/arm64/kernel/smp.c | 2 +- arch/arm64/kvm/handle_exit.c | 2 +- arch/arm64/kvm/hyp/include/hyp/debug-sr.h | 60 +++++------ arch/arm64/kvm/hyp/vgic-v3-sr.c | 16 +-- arch/arm64/mm/context.c | 2 +- arch/c6x/kernel/signal.c | 4 +- arch/csky/kernel/signal.c | 2 +- arch/h8300/kernel/signal.c | 2 +- arch/hexagon/kernel/module.c | 2 +- arch/hexagon/kernel/signal.c | 2 +- arch/ia64/kernel/crash.c | 2 +- arch/ia64/kernel/module.c | 2 +- arch/ia64/kernel/perfmon.c | 2 +- arch/ia64/kernel/signal.c | 2 +- arch/ia64/kernel/unaligned.c | 6 +- arch/ia64/kernel/unwind.c | 2 +- arch/m68k/atari/atakeyb.c | 2 +- arch/m68k/kernel/signal.c | 2 +- arch/m68k/mac/config.c | 2 +- arch/m68k/mac/via.c | 2 +- arch/m68k/mm/fault.c | 2 +- arch/microblaze/kernel/signal.c | 2 +- arch/mips/include/asm/unroll.h | 64 ++++++------ arch/nds32/kernel/fpu.c | 12 +-- arch/nds32/kernel/signal.c | 4 +- arch/openrisc/kernel/signal.c | 2 +- arch/parisc/kernel/signal.c | 2 +- arch/parisc/kernel/traps.c | 11 +- arch/parisc/mm/fault.c | 4 +- arch/powerpc/net/bpf_jit_comp.c | 2 +- arch/riscv/kernel/signal.c | 2 +- arch/riscv/net/bpf_jit_comp32.c | 4 +- arch/sh/drivers/platform_early.c | 2 +- arch/sh/kernel/disassemble.c | 4 +- arch/sh/kernel/kgdb.c | 2 +- arch/sh/kernel/signal_32.c | 2 +- arch/sparc/kernel/auxio_64.c | 1 - arch/sparc/kernel/central.c | 2 +- arch/sparc/kernel/kgdb_32.c | 2 +- arch/sparc/kernel/kgdb_64.c | 2 +- arch/sparc/kernel/pcr.c | 2 +- arch/sparc/kernel/prom_32.c | 2 +- arch/sparc/kernel/signal32.c | 4 +- arch/sparc/kernel/signal_32.c | 4 +- arch/sparc/kernel/signal_64.c | 4 +- arch/sparc/math-emu/math_32.c | 8 +- arch/sparc/net/bpf_jit_comp_32.c | 2 +- arch/um/kernel/signal.c | 2 +- arch/x86/boot/cmdline.c | 4 +- arch/x86/boot/compressed/kaslr.c | 2 +- arch/x86/events/intel/core.c | 6 +- arch/x86/events/intel/lbr.c | 2 +- arch/x86/kernel/alternative.c | 2 +- arch/x86/kernel/apic/io_apic.c | 4 +- arch/x86/kernel/apic/probe_32.c | 2 +- arch/x86/kernel/cpu/cacheinfo.c | 2 +- arch/x86/kernel/cpu/mce/inject.c | 2 +- arch/x86/kernel/cpu/mce/intel.c | 2 +- arch/x86/kernel/cpu/mtrr/cyrix.c | 2 +- arch/x86/kernel/hw_breakpoint.c | 2 +- arch/x86/kernel/kgdb.c | 4 +- arch/x86/kernel/mpparse.c | 4 +- arch/x86/kernel/ptrace.c | 2 +- arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/signal.c | 2 +- arch/x86/kernel/uprobes.c | 4 +- arch/x86/kvm/emulate.c | 2 +- arch/x86/kvm/hyperv.c | 2 +- arch/x86/kvm/irq_comm.c | 2 +- arch/x86/kvm/lapic.c | 6 +- arch/x86/kvm/mmu/mmu.c | 2 +- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/vmx/vmx.c | 12 +-- arch/x86/kvm/x86.c | 11 +- arch/x86/lib/cmdline.c | 8 +- arch/x86/lib/insn-eval.c | 6 +- arch/x86/math-emu/errors.c | 2 +- arch/x86/math-emu/fpu_trig.c | 2 +- arch/x86/mm/ioremap.c | 2 +- arch/xtensa/kernel/signal.c | 2 +- block/badblocks.c | 2 +- block/bfq-iosched.c | 4 +- block/blk-wbt.c | 2 +- block/ioprio.c | 2 +- crypto/drbg.c | 2 +- crypto/tcrypt.c | 114 ++++++++++----------- drivers/accessibility/braille/braille_console.c | 2 +- drivers/ata/ahci_brcm.c | 2 +- drivers/ata/libahci_platform.c | 2 +- drivers/ata/libata-core.c | 16 +-- drivers/ata/libata-eh.c | 6 +- drivers/ata/libata-scsi.c | 4 +- drivers/ata/pata_atp867x.c | 4 +- drivers/ata/pata_serverworks.c | 2 +- drivers/ata/sata_mv.c | 12 +-- drivers/ata/sata_promise.c | 8 +- drivers/ata/sata_sx4.c | 2 +- drivers/atm/firestream.c | 2 +- drivers/atm/fore200e.c | 16 +-- drivers/atm/he.c | 4 +- drivers/atm/idt77105.c | 2 +- drivers/atm/lanai.c | 2 +- drivers/atm/zatm.c | 2 +- drivers/auxdisplay/panel.c | 6 +- drivers/base/firmware_loader/fallback.c | 4 +- drivers/block/aoe/aoecmd.c | 2 +- drivers/block/ataflop.c | 2 +- drivers/block/drbd/drbd_int.h | 2 +- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_nl.c | 2 +- drivers/block/drbd/drbd_receiver.c | 12 +-- drivers/block/drbd/drbd_req.c | 4 +- drivers/block/floppy.c | 4 +- drivers/block/loop.c | 4 +- drivers/block/paride/pd.c | 4 +- drivers/block/pktcdvd.c | 2 +- drivers/block/rbd.c | 8 +- drivers/block/rsxx/core.c | 2 +- drivers/block/skd_main.c | 2 +- drivers/block/xen-blkback/blkback.c | 2 +- drivers/block/xen-blkback/xenbus.c | 2 +- drivers/block/xen-blkfront.c | 5 +- drivers/bus/ti-sysc.c | 2 +- drivers/char/agp/ali-agp.c | 2 +- drivers/char/ipmi/kcs_bmc.c | 2 +- drivers/char/lp.c | 4 +- drivers/char/mem.c | 2 +- drivers/char/nvram.c | 2 +- drivers/clocksource/timer-cadence-ttc.c | 4 +- drivers/cpufreq/p4-clockmod.c | 2 +- drivers/cpufreq/speedstep-lib.c | 2 +- drivers/cpufreq/ti-cpufreq.c | 4 +- drivers/crypto/axis/artpec6_crypto.c | 2 +- drivers/crypto/cavium/cpt/cptvf_reqmanager.c | 4 +- drivers/crypto/chelsio/chcr_ktls.c | 4 +- drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c | 4 +- drivers/crypto/qat/qat_common/adf_pf2vf_msg.c | 2 +- drivers/crypto/qat/qat_common/qat_uclo.c | 6 +- drivers/crypto/ux500/cryp/cryp.c | 12 +-- drivers/dma/amba-pl08x.c | 10 +- drivers/dma/fsldma.c | 2 +- drivers/dma/imx-dma.c | 2 +- drivers/dma/iop-adma.h | 12 +-- drivers/dma/nbpfaxi.c | 2 +- drivers/dma/pl330.c | 10 +- drivers/dma/sh/shdma-base.c | 2 +- drivers/edac/amd64_edac.c | 2 +- drivers/edac/pnd2_edac.c | 2 +- drivers/firewire/core-device.c | 2 +- drivers/firewire/core-iso.c | 2 +- drivers/firewire/core-topology.c | 2 +- drivers/firewire/core-transaction.c | 4 +- drivers/firewire/ohci.c | 4 +- drivers/gpio/gpio-aspeed-sgpio.c | 6 +- drivers/gpio/gpio-aspeed.c | 6 +- drivers/gpio/gpio-ath79.c | 2 +- drivers/gpio/gpio-eic-sprd.c | 4 +- drivers/gpio/gpio-stmpe.c | 4 +- drivers/gpio/gpiolib-acpi.c | 2 +- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 2 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/si_dpm.c | 2 +- drivers/gpu/drm/arm/malidp_hw.c | 6 +- drivers/gpu/drm/ast/ast_main.c | 2 +- drivers/gpu/drm/bridge/nwl-dsi.c | 2 - .../gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 4 +- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 6 +- drivers/gpu/drm/drm_bufs.c | 2 +- drivers/gpu/drm/drm_dp_helper.c | 2 +- drivers/gpu/drm/drm_modes.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_dsi.c | 10 +- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | 6 +- drivers/gpu/drm/i915/display/icl_dsi.c | 6 +- drivers/gpu/drm/i915/display/intel_bios.c | 6 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 10 +- drivers/gpu/drm/i915/display/intel_combo_phy.c | 6 +- drivers/gpu/drm/i915/display/intel_ddi.c | 4 +- drivers/gpu/drm/i915/display/intel_display.c | 20 ++-- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 8 +- drivers/gpu/drm/i915/display/intel_panel.c | 2 +- drivers/gpu/drm/i915/display/intel_sdvo.c | 12 +-- drivers/gpu/drm/i915/display/intel_sprite.c | 22 ++-- drivers/gpu/drm/i915/display/intel_tc.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_pages.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 6 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt.c | 2 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- drivers/gpu/drm/i915/gvt/handlers.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- drivers/gpu/drm/i915/i915_pmu.c | 2 +- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/drm/meson/meson_osd_afbcd.c | 2 +- drivers/gpu/drm/meson/meson_overlay.c | 4 +- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 +- drivers/gpu/drm/msm/adreno/adreno_gpu.c | 2 +- drivers/gpu/drm/omapdrm/dss/venc.c | 2 +- drivers/gpu/drm/radeon/ci_dpm.c | 2 +- drivers/gpu/drm/radeon/r300.c | 4 +- drivers/gpu/drm/radeon/r420.c | 2 +- drivers/gpu/drm/radeon/r600_cs.c | 4 +- drivers/gpu/drm/radeon/radeon_uvd.c | 2 +- drivers/gpu/drm/radeon/si_dpm.c | 2 +- drivers/gpu/drm/radeon/uvd_v1_0.c | 2 +- drivers/gpu/drm/savage/savage_state.c | 10 +- drivers/gpu/drm/sti/sti_hdmi.c | 6 +- drivers/gpu/drm/sun4i/sun4i_tcon.c | 4 +- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +- drivers/gpu/drm/tegra/dc.c | 2 +- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 2 +- drivers/gpu/drm/via/via_dmablit.c | 8 +- drivers/gpu/drm/xen/xen_drm_front.c | 3 - drivers/gpu/ipu-v3/ipu-dc.c | 2 +- drivers/hid/hid-lg-g15.c | 2 +- drivers/hid/hid-logitech-dj.c | 2 +- drivers/hid/hid-microsoft.c | 3 - drivers/hid/hid-rmi.c | 1 - drivers/hid/hid-roccat-kone.c | 2 +- drivers/hid/hid-uclogic-params.c | 2 +- drivers/hid/hid-wiimote-core.c | 2 - drivers/hid/usbhid/hiddev.c | 1 - drivers/hid/wacom_wac.c | 32 +++--- drivers/hsi/clients/ssi_protocol.c | 6 +- drivers/hsi/controllers/omap_ssi_core.c | 2 +- drivers/hv/hv_kvp.c | 2 +- drivers/hwmon/adt7462.c | 8 +- drivers/hwmon/emc1403.c | 4 +- drivers/hwmon/f71882fg.c | 4 +- drivers/hwmon/hwmon-vid.c | 4 +- drivers/hwmon/ina3221.c | 2 +- drivers/hwmon/nct6775.c | 2 +- drivers/hwmon/occ/common.c | 6 +- drivers/hwmon/w83627hf.c | 2 +- drivers/hwmon/w83781d.c | 2 +- drivers/hwmon/w83795.c | 2 +- drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 +- drivers/hwtracing/coresight/coresight-etm4x.c | 1 - drivers/hwtracing/coresight/coresight-tmc.c | 2 - drivers/hwtracing/intel_th/sth.c | 4 +- drivers/i2c/busses/i2c-omap.c | 1 - drivers/i2c/busses/i2c-opal.c | 2 +- drivers/i3c/master/dw-i3c-master.c | 2 +- drivers/ide/hpt366.c | 6 +- drivers/ide/ide-cd.c | 4 +- drivers/ide/ide-floppy.c | 2 +- drivers/ide/ide-probe.c | 2 +- drivers/ide/ide-taskfile.c | 12 +-- drivers/ide/sis5513.c | 2 +- drivers/iio/accel/mma8452.c | 2 +- drivers/iio/adc/ab8500-gpadc.c | 2 +- drivers/iio/adc/cpcap-adc.c | 2 +- drivers/iio/chemical/sps30.c | 2 +- drivers/iio/dac/ad5592r-base.c | 2 - drivers/iio/dac/dpot-dac.c | 2 +- drivers/iio/health/max30102.c | 4 +- drivers/iio/imu/adis.c | 6 +- drivers/iio/industrialio-core.c | 4 +- drivers/iio/light/si1145.c | 2 +- drivers/iio/magnetometer/ak8974.c | 2 +- drivers/infiniband/core/cm.c | 12 +-- drivers/infiniband/core/cma.c | 3 +- drivers/infiniband/core/rw.c | 1 - drivers/infiniband/core/ucma.c | 4 +- drivers/infiniband/core/uverbs_ioctl.c | 4 +- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 2 +- drivers/infiniband/hw/bnxt_re/qplib_fp.c | 2 +- drivers/infiniband/hw/cxgb4/cm.c | 4 +- drivers/infiniband/hw/cxgb4/qp.c | 2 +- drivers/infiniband/hw/hfi1/pio_copy.c | 1 - drivers/infiniband/hw/i40iw/i40iw_cm.c | 2 +- drivers/infiniband/hw/i40iw/i40iw_ctrl.c | 5 +- drivers/infiniband/hw/i40iw/i40iw_hw.c | 3 +- drivers/infiniband/hw/i40iw/i40iw_main.c | 22 ++-- drivers/infiniband/hw/i40iw/i40iw_puda.c | 4 +- drivers/infiniband/hw/i40iw/i40iw_utils.c | 8 +- drivers/infiniband/hw/i40iw/i40iw_verbs.c | 5 +- drivers/infiniband/hw/mlx4/cq.c | 4 +- drivers/infiniband/hw/mlx4/mcg.c | 2 +- drivers/infiniband/hw/mlx4/qp.c | 6 +- drivers/infiniband/hw/mlx5/cq.c | 4 +- drivers/infiniband/hw/mlx5/mad.c | 3 +- drivers/infiniband/hw/mlx5/main.c | 2 +- drivers/infiniband/hw/mlx5/qp.c | 4 +- drivers/infiniband/hw/mthca/mthca_av.c | 2 +- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 4 +- drivers/infiniband/hw/qedr/verbs.c | 2 +- drivers/infiniband/hw/qib/qib_iba6120.c | 4 +- drivers/infiniband/hw/qib/qib_iba7220.c | 4 +- drivers/infiniband/hw/qib/qib_iba7322.c | 6 +- drivers/infiniband/hw/qib/qib_mad.c | 12 +-- drivers/infiniband/hw/qib/qib_rc.c | 18 ++-- drivers/infiniband/hw/qib/qib_sdma.c | 2 +- drivers/infiniband/hw/qib/qib_uc.c | 8 +- drivers/infiniband/hw/qib/qib_verbs.c | 2 +- drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c | 2 +- drivers/infiniband/sw/rdmavt/qp.c | 2 +- drivers/infiniband/sw/rxe/rxe_comp.c | 2 +- drivers/infiniband/sw/rxe/rxe_task.c | 2 +- drivers/infiniband/sw/rxe/rxe_verbs.c | 2 +- drivers/infiniband/sw/siw/siw_cm.c | 2 - drivers/infiniband/sw/siw/siw_qp_rx.c | 4 +- drivers/infiniband/sw/siw/siw_qp_tx.c | 4 +- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 4 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- drivers/infiniband/ulp/iser/iser_verbs.c | 2 +- drivers/infiniband/ulp/isert/ib_isert.c | 10 +- drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c | 1 - drivers/input/joystick/fsia6b.c | 4 +- drivers/input/joystick/gamecon.c | 1 - drivers/input/tablet/wacom_serial4.c | 2 +- drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- drivers/input/touchscreen/wm831x-ts.c | 2 +- drivers/iommu/amd/init.c | 2 +- drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 11 +- drivers/iommu/intel/iommu.c | 1 - drivers/iommu/virtio-iommu.c | 2 +- drivers/irqchip/irq-gic-v3-its.c | 4 +- drivers/irqchip/irq-gic-v3.c | 8 +- drivers/irqchip/irq-imx-gpcv2.c | 2 +- drivers/irqchip/irq-mips-gic.c | 2 +- drivers/irqchip/irq-vic.c | 2 +- drivers/isdn/hardware/mISDN/avmfritz.c | 2 +- drivers/isdn/hardware/mISDN/hfc_multi_8xx.h | 1 - drivers/isdn/hardware/mISDN/hfcpci.c | 2 +- drivers/isdn/hardware/mISDN/hfcsusb.c | 2 +- drivers/isdn/hardware/mISDN/isdnhdlc.c | 2 +- drivers/isdn/hardware/mISDN/mISDNinfineon.c | 2 +- drivers/isdn/hardware/mISDN/mISDNisar.c | 8 +- drivers/isdn/mISDN/stack.c | 2 +- drivers/lightnvm/pblk-core.c | 2 +- drivers/macintosh/adbhid.c | 2 +- drivers/macintosh/smu.c | 2 +- drivers/md/bcache/journal.c | 2 +- drivers/md/bcache/util.c | 14 +-- drivers/md/dm-crypt.c | 2 +- drivers/md/dm-mpath.c | 2 +- drivers/md/dm.c | 2 +- drivers/md/md-autodetect.c | 4 +- drivers/md/md-bitmap.c | 2 +- drivers/md/raid5.c | 4 +- drivers/media/common/v4l2-tpg/v4l2-tpg-core.c | 36 +++---- drivers/media/dvb-core/dvb_net.c | 2 +- drivers/media/dvb-frontends/bcm3510.c | 2 +- drivers/media/dvb-frontends/dib0090.c | 2 +- drivers/media/dvb-frontends/dib3000mb.c | 2 +- drivers/media/dvb-frontends/dib7000p.c | 2 +- drivers/media/dvb-frontends/drx39xyj/drxj.c | 103 ++++++++++--------- drivers/media/dvb-frontends/drxd_hard.c | 12 +-- drivers/media/dvb-frontends/drxk_hard.c | 24 ++--- drivers/media/dvb-frontends/lgdt3306a.c | 2 +- drivers/media/dvb-frontends/mt352.c | 2 +- drivers/media/dvb-frontends/mxl5xx.c | 2 +- drivers/media/dvb-frontends/or51132.c | 2 +- drivers/media/dvb-frontends/s5h1411.c | 2 +- drivers/media/dvb-frontends/zl10353.c | 4 +- drivers/media/pci/cx23885/cx23885-cards.c | 4 +- drivers/media/pci/ddbridge/ddbridge-core.c | 23 +++-- drivers/media/pci/meye/meye.c | 2 +- drivers/media/pci/ttpci/av7110.c | 4 +- drivers/media/pci/ttpci/av7110_hw.c | 2 +- drivers/media/pci/ttpci/av7110_ipack.c | 2 +- drivers/media/pci/ttpci/budget-av.c | 2 +- drivers/media/pci/ttpci/budget.c | 4 +- drivers/media/platform/sh_vou.c | 4 +- drivers/media/radio/radio-si476x.c | 3 +- drivers/media/radio/tea575x.c | 2 +- drivers/media/rc/bpf-lirc.c | 2 +- drivers/media/rc/ir-rc6-decoder.c | 2 +- drivers/media/rc/ir-sony-decoder.c | 2 +- drivers/media/tuners/xc5000.c | 2 +- drivers/media/usb/b2c2/flexcop-usb.c | 2 +- drivers/media/usb/cpia2/cpia2_core.c | 36 +++---- drivers/media/usb/cx231xx/cx231xx-video.c | 2 +- drivers/media/usb/dvb-usb/dib0700_devices.c | 2 +- drivers/media/usb/dvb-usb/dw2102.c | 6 +- drivers/media/v4l2-core/v4l2-ctrls.c | 2 +- drivers/media/v4l2-core/v4l2-ioctl.c | 2 - drivers/media/v4l2-core/videobuf-core.c | 2 +- drivers/memory/omap-gpmc.c | 1 - drivers/memstick/core/ms_block.c | 12 +-- drivers/memstick/host/jmb38x_ms.c | 4 +- drivers/memstick/host/tifm_ms.c | 4 +- drivers/message/fusion/mptbase.c | 6 +- drivers/message/fusion/mptsas.c | 2 +- drivers/message/fusion/mptscsih.c | 4 +- drivers/mfd/db8500-prcmu.c | 4 +- drivers/mfd/iqs62x.c | 6 +- drivers/mfd/mxs-lradc.c | 2 +- drivers/mfd/omap-usb-host.c | 4 +- drivers/mfd/rave-sp.c | 4 +- drivers/mfd/syscon.c | 2 +- drivers/misc/eeprom/at25.c | 10 +- drivers/misc/mic/scif/scif_api.c | 4 +- drivers/misc/mic/scif/scif_rma.c | 2 +- drivers/misc/sgi-gru/grukservices.c | 4 +- drivers/misc/sgi-xp/xpc_main.c | 4 +- drivers/misc/sgi-xp/xpc_partition.c | 4 +- drivers/misc/sgi-xp/xpc_uv.c | 2 +- drivers/mmc/core/host.c | 2 +- drivers/mmc/host/atmel-mci.c | 8 +- drivers/mmc/host/davinci_mmc.c | 2 +- drivers/mmc/host/dw_mmc-k3.c | 2 +- drivers/mmc/host/dw_mmc.c | 6 +- drivers/mmc/host/jz4740_mmc.c | 4 +- drivers/mmc/host/meson-mx-sdio.c | 2 +- drivers/mmc/host/renesas_sdhi_core.c | 2 +- drivers/mmc/host/sdhci-esdhc-imx.c | 2 +- drivers/mmc/host/sdhci-s3c.c | 2 +- drivers/mmc/host/sdhci-sprd.c | 2 +- drivers/mmc/host/sdhci-xenon-phy.c | 2 +- drivers/mmc/host/sdhci.c | 2 +- drivers/mmc/host/tifm_sd.c | 2 +- drivers/mmc/host/usdhi6rol0.c | 6 +- drivers/mux/adgs1408.c | 2 +- drivers/net/appletalk/cops.c | 2 +- drivers/net/arcnet/arc-rimi.c | 6 +- drivers/net/arcnet/com20020-isa.c | 12 +-- drivers/net/arcnet/com90io.c | 4 +- drivers/net/arcnet/com90xx.c | 6 +- drivers/net/bonding/bond_3ad.c | 4 +- drivers/net/bonding/bond_main.c | 8 +- drivers/net/can/at91_can.c | 4 +- drivers/net/can/peak_canfd/peak_pciefd_main.c | 2 +- drivers/net/can/sja1000/sja1000_platform.c | 2 +- drivers/net/can/slcan.c | 4 +- drivers/net/can/spi/mcp251x.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 2 +- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 4 +- drivers/net/dsa/b53/b53_common.c | 2 +- drivers/net/dsa/b53/b53_serdes.c | 2 +- drivers/net/dsa/bcm_sf2.c | 2 +- drivers/net/dsa/microchip/ksz9477.c | 2 +- drivers/net/dsa/mt7530.c | 2 +- drivers/net/dsa/mv88e6xxx/chip.c | 2 +- drivers/net/ethernet/3com/3c509.c | 4 +- drivers/net/ethernet/3com/3c574_cs.c | 2 +- drivers/net/ethernet/8390/axnet_cs.c | 2 +- drivers/net/ethernet/8390/pcnet_cs.c | 2 +- drivers/net/ethernet/alacritech/slicoss.c | 12 +-- drivers/net/ethernet/alteon/acenic.c | 2 +- drivers/net/ethernet/amd/amd8111e.c | 2 +- drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 6 +- drivers/net/ethernet/broadcom/bgmac-bcma.c | 2 +- drivers/net/ethernet/broadcom/bgmac-platform.c | 2 +- drivers/net/ethernet/broadcom/bnx2.c | 14 +-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | 14 +-- drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 4 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 4 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c | 4 +- drivers/net/ethernet/broadcom/bnxt/bnxt.c | 16 +-- drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c | 4 +- drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 4 +- drivers/net/ethernet/broadcom/cnic.c | 4 +- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 4 +- drivers/net/ethernet/broadcom/genet/bcmmii.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 54 +++++----- drivers/net/ethernet/brocade/bna/bfa_ioc.c | 6 +- drivers/net/ethernet/brocade/bna/bna_enet.c | 2 +- drivers/net/ethernet/brocade/bna/bna_tx_rx.c | 2 +- drivers/net/ethernet/cadence/macb_ptp.c | 2 +- drivers/net/ethernet/cavium/liquidio/lio_main.c | 29 +++--- drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 25 +++-- .../net/ethernet/cavium/thunder/nicvf_ethtool.c | 2 +- drivers/net/ethernet/cavium/thunder/nicvf_main.c | 4 +- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 2 +- drivers/net/ethernet/chelsio/cxgb3/l2t.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/l2t.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 6 +- .../net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- drivers/net/ethernet/cisco/enic/enic_main.c | 2 +- drivers/net/ethernet/davicom/dm9000.c | 2 +- drivers/net/ethernet/dec/tulip/de4x5.c | 6 +- drivers/net/ethernet/dec/tulip/tulip_core.c | 2 +- drivers/net/ethernet/dec/tulip/winbond-840.c | 2 +- drivers/net/ethernet/emulex/benet/be_ethtool.c | 2 +- drivers/net/ethernet/freescale/dpaa/dpaa_eth.c | 2 +- drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c | 2 +- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 4 +- drivers/net/ethernet/freescale/fman/fman_memac.c | 2 +- drivers/net/ethernet/freescale/fman/fman_port.c | 4 +- drivers/net/ethernet/freescale/ucc_geth.c | 2 +- drivers/net/ethernet/hisilicon/hns/hns_ethtool.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 2 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 +- drivers/net/ethernet/ibm/ehea/ehea_main.c | 2 +- drivers/net/ethernet/ibm/emac/core.c | 2 +- drivers/net/ethernet/intel/e1000e/netdev.c | 1 - drivers/net/ethernet/intel/igb/igb_main.c | 1 - drivers/net/ethernet/marvell/mvneta.c | 4 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c | 2 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 4 +- .../net/ethernet/marvell/octeontx2/af/rvu_nix.c | 2 +- drivers/net/ethernet/marvell/skge.c | 2 +- drivers/net/ethernet/marvell/sky2.c | 4 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 6 +- drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c | 4 +- drivers/net/ethernet/mellanox/mlxsw/core.c | 18 ++-- drivers/net/ethernet/mellanox/mlxsw/core_env.c | 6 +- drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c | 4 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 4 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 10 +- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 32 +++--- .../net/ethernet/mellanox/mlxsw/spectrum_span.c | 6 +- .../ethernet/mellanox/mlxsw/spectrum_switchdev.c | 12 +-- drivers/net/ethernet/microchip/lan743x_ethtool.c | 2 +- drivers/net/ethernet/mscc/ocelot.c | 2 +- drivers/net/ethernet/natsemi/natsemi.c | 2 +- drivers/net/ethernet/neterion/vxge/vxge-config.c | 6 +- drivers/net/ethernet/netronome/nfp/crypto/tls.c | 2 +- drivers/net/ethernet/netronome/nfp/flower/action.c | 2 +- drivers/net/ethernet/netronome/nfp/flower/cmsg.c | 2 +- .../net/ethernet/netronome/nfp/flower/offload.c | 2 +- drivers/net/ethernet/netronome/nfp/nfp_asm.c | 2 +- .../net/ethernet/netronome/nfp/nfp_net_common.c | 4 +- .../ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c | 4 +- .../net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c | 2 +- .../net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c | 2 +- drivers/net/ethernet/packetengines/yellowfin.c | 2 +- .../ethernet/qlogic/netxen/netxen_nic_ethtool.c | 4 +- drivers/net/ethernet/qlogic/qed/qed_cxt.c | 2 +- drivers/net/ethernet/qlogic/qed/qed_dev.c | 4 +- drivers/net/ethernet/qlogic/qed/qed_main.c | 4 +- drivers/net/ethernet/qlogic/qed/qed_mcp.c | 10 +- drivers/net/ethernet/qlogic/qla3xxx.c | 2 +- .../net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | 4 +- drivers/net/ethernet/realtek/r8169_main.c | 4 +- drivers/net/ethernet/rocker/rocker_main.c | 8 +- drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c | 4 +- drivers/net/ethernet/sfc/falcon/ethtool.c | 2 +- drivers/net/ethernet/sfc/falcon/farch.c | 14 +-- drivers/net/ethernet/sfc/farch.c | 14 +-- drivers/net/ethernet/sfc/mcdi_filters.c | 2 +- drivers/net/ethernet/sfc/mcdi_port_common.c | 2 +- drivers/net/ethernet/sfc/rx.c | 2 +- drivers/net/ethernet/sis/sis900.c | 2 +- drivers/net/ethernet/smsc/smc911x.c | 2 +- drivers/net/ethernet/socionext/netsec.c | 4 +- .../net/ethernet/stmicro/stmmac/dwmac-anarion.c | 7 +- .../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 4 +- drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 2 +- drivers/net/ethernet/sun/cassini.c | 2 +- drivers/net/ethernet/sun/niu.c | 4 +- drivers/net/ethernet/sun/sungem.c | 2 +- drivers/net/ethernet/ti/cpsw-phy-sel.c | 4 +- drivers/net/ethernet/ti/cpsw_priv.c | 4 +- drivers/net/ethernet/ti/tlan.c | 2 +- drivers/net/ethernet/toshiba/ps3_gelic_wireless.c | 2 +- drivers/net/ethernet/toshiba/spider_net.c | 28 ++--- drivers/net/ethernet/xircom/xirc2ps_cs.c | 2 +- drivers/net/fddi/skfp/pcmplc.c | 4 +- drivers/net/fjes/fjes_main.c | 2 +- drivers/net/hamradio/baycom_epp.c | 2 +- drivers/net/hamradio/mkiss.c | 5 +- drivers/net/macvlan.c | 2 +- drivers/net/mii.c | 2 +- drivers/net/netdevsim/bus.c | 2 +- drivers/net/netdevsim/fib.c | 6 +- drivers/net/phy/adin.c | 4 +- drivers/net/phy/dp83640.c | 8 +- drivers/net/phy/fixed_phy.c | 4 +- drivers/net/phy/phy.c | 4 +- drivers/net/phy/phy_device.c | 2 +- drivers/net/phy/phylink.c | 4 +- drivers/net/phy/sfp-bus.c | 4 +- drivers/net/phy/sfp.c | 12 +-- drivers/net/plip/plip.c | 26 ++--- drivers/net/tun.c | 6 +- drivers/net/usb/aqc111.c | 6 +- drivers/net/usb/catc.c | 2 +- drivers/net/usb/cdc-phonet.c | 2 +- drivers/net/usb/lan78xx.c | 4 +- drivers/net/usb/pegasus.c | 4 +- drivers/net/usb/r8152.c | 6 +- drivers/net/usb/rtl8150.c | 2 +- drivers/net/usb/usbnet.c | 6 +- drivers/net/veth.c | 8 +- drivers/net/virtio_net.c | 6 +- drivers/net/vmxnet3/vmxnet3_ethtool.c | 2 +- drivers/net/wan/lapbether.c | 2 +- drivers/net/wan/sdla.c | 2 +- drivers/net/wan/x25_asy.c | 2 +- drivers/net/wimax/i2400m/control.c | 2 +- drivers/net/wimax/i2400m/usb-fw.c | 2 +- drivers/net/wimax/i2400m/usb-tx.c | 2 +- drivers/net/wimax/i2400m/usb.c | 2 +- drivers/net/xen-netback/hash.c | 2 +- drivers/net/xen-netback/xenbus.c | 2 +- drivers/net/xen-netfront.c | 2 +- drivers/nfc/pn533/pn533.c | 4 +- drivers/nfc/st21nfca/dep.c | 2 +- drivers/nfc/trf7970a.c | 4 +- drivers/ntb/ntb_transport.c | 4 +- drivers/nvme/host/core.c | 12 +-- drivers/nvme/host/pci.c | 2 +- drivers/nvme/host/rdma.c | 2 +- drivers/nvme/host/tcp.c | 1 - drivers/nvme/target/core.c | 2 +- drivers/nvme/target/fcloop.c | 2 +- drivers/nvme/target/io-cmd-bdev.c | 1 - drivers/nvme/target/rdma.c | 4 +- drivers/parport/ieee1284.c | 6 +- drivers/parport/parport_pc.c | 2 +- drivers/pci/controller/dwc/pci-imx6.c | 6 +- drivers/pci/controller/pci-rcar-gen2.c | 2 +- drivers/pci/hotplug/ibmphp_res.c | 2 +- drivers/pci/hotplug/pciehp_ctrl.c | 4 +- drivers/pci/hotplug/shpchp_ctrl.c | 4 +- drivers/pci/pci.c | 4 +- drivers/pci/proc.c | 2 +- drivers/pci/quirks.c | 4 +- drivers/pci/setup-bus.c | 2 +- drivers/pci/xen-pcifront.c | 2 +- drivers/pcmcia/db1xxx_ss.c | 8 +- drivers/perf/arm-ccn.c | 2 +- drivers/perf/arm_spe_pmu.c | 4 +- drivers/phy/qualcomm/phy-qcom-usb-hs.c | 2 +- drivers/phy/rockchip/phy-rockchip-inno-usb2.c | 8 +- drivers/platform/olpc/olpc-xo175-ec.c | 2 +- drivers/platform/x86/acer-wmi.c | 8 +- drivers/platform/x86/dell-laptop.c | 4 +- drivers/platform/x86/surfacepro3_button.c | 8 +- drivers/platform/x86/thinkpad_acpi.c | 6 +- drivers/platform/x86/toshiba_acpi.c | 2 +- drivers/power/supply/ab8500_charger.c | 4 +- drivers/power/supply/ab8500_fg.c | 4 +- drivers/power/supply/abx500_chargalg.c | 26 ++--- drivers/power/supply/axp20x_usb_power.c | 2 +- drivers/power/supply/cros_usbpd-charger.c | 2 +- drivers/power/supply/max8925_power.c | 2 +- drivers/power/supply/wm831x_power.c | 2 +- drivers/power/supply/wm8350_power.c | 2 +- drivers/ps3/ps3av.c | 2 +- drivers/ps3/ps3av_cmd.c | 4 +- drivers/rapidio/devices/rio_mport_cdev.c | 2 +- drivers/regulator/axp20x-regulator.c | 8 +- drivers/regulator/core.c | 2 +- drivers/regulator/slg51000-regulator.c | 2 +- drivers/regulator/twl6030-regulator.c | 2 +- drivers/remoteproc/omap_remoteproc.c | 1 - drivers/reset/reset-imx7.c | 14 +-- drivers/rpmsg/qcom_glink_native.c | 4 +- drivers/rtc/rtc-m41t80.c | 2 +- drivers/rtc/rtc-pcf85063.c | 2 +- drivers/rtc/rtc-pcf8523.c | 2 +- drivers/rtc/rtc-stmp3xxx.c | 2 +- drivers/s390/net/ctcm_fsms.c | 2 +- drivers/s390/net/ctcm_mpc.c | 6 +- drivers/s390/net/qeth_core_main.c | 4 +- drivers/s390/net/qeth_ethtool.c | 6 +- drivers/s390/net/qeth_l2_main.c | 2 +- drivers/s390/net/qeth_l3_main.c | 2 +- drivers/scsi/53c700.c | 2 +- drivers/scsi/BusLogic.c | 2 +- drivers/scsi/FlashPoint.c | 9 +- drivers/scsi/NCR5380.c | 2 +- drivers/scsi/aacraid/aachba.c | 8 +- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/linit.c | 2 +- drivers/scsi/aic7xxx/aic79xx_core.c | 40 ++++---- drivers/scsi/aic7xxx/aic79xx_osm.c | 2 +- drivers/scsi/aic7xxx/aic7xxx_core.c | 28 ++--- drivers/scsi/aic94xx/aic94xx_scb.c | 10 +- drivers/scsi/aic94xx/aic94xx_tmf.c | 2 +- drivers/scsi/arcmsr/arcmsr_hba.c | 2 +- drivers/scsi/arm/fas216.c | 12 +-- drivers/scsi/be2iscsi/be_iscsi.c | 2 +- drivers/scsi/be2iscsi/be_main.c | 2 +- drivers/scsi/bfa/bfa_fcpim.c | 6 +- drivers/scsi/bfa/bfa_fcs_lport.c | 4 +- drivers/scsi/bfa/bfa_fcs_rport.c | 14 +-- drivers/scsi/bfa/bfa_ioc.c | 6 +- drivers/scsi/bfa/bfa_svc.c | 2 +- drivers/scsi/bnx2fc/bnx2fc_hwi.c | 1 - drivers/scsi/csiostor/csio_hw.c | 2 +- drivers/scsi/csiostor/csio_lnode.c | 1 - drivers/scsi/csiostor/csio_wr.c | 2 +- drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 2 +- drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 2 +- drivers/scsi/cxlflash/main.c | 28 ++--- drivers/scsi/cxlflash/superpipe.c | 10 +- drivers/scsi/device_handler/scsi_dh_hp_sw.c | 4 +- drivers/scsi/esas2r/esas2r_flash.c | 2 +- drivers/scsi/esas2r/esas2r_init.c | 4 +- drivers/scsi/esp_scsi.c | 4 +- drivers/scsi/fcoe/fcoe_ctlr.c | 8 +- drivers/scsi/g_NCR5380.c | 2 +- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 +- drivers/scsi/hpsa.c | 10 +- drivers/scsi/ibmvscsi/ibmvfc.c | 6 +- drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c | 6 +- drivers/scsi/imm.c | 14 +-- drivers/scsi/isci/phy.c | 2 +- drivers/scsi/isci/remote_device.c | 4 +- drivers/scsi/isci/remote_node_context.c | 6 +- drivers/scsi/isci/request.c | 2 +- drivers/scsi/libfc/fc_exch.c | 4 +- drivers/scsi/libfc/fc_fcp.c | 8 +- drivers/scsi/libfc/fc_lport.c | 2 +- drivers/scsi/libfc/fc_rport.c | 2 +- drivers/scsi/libiscsi.c | 6 +- drivers/scsi/libiscsi_tcp.c | 2 +- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/scsi/libsas/sas_discover.c | 2 +- drivers/scsi/libsas/sas_expander.c | 2 +- drivers/scsi/libsas/sas_scsi_host.c | 2 +- drivers/scsi/lpfc/lpfc_ct.c | 4 +- drivers/scsi/lpfc/lpfc_els.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 7 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 2 +- drivers/scsi/lpfc/lpfc_nvme.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 8 +- drivers/scsi/lpfc/lpfc_sli.c | 28 ++--- drivers/scsi/megaraid.c | 12 +-- drivers/scsi/megaraid/megaraid_mbox.c | 2 +- drivers/scsi/megaraid/megaraid_sas_base.c | 2 +- drivers/scsi/megaraid/megaraid_sas_fusion.c | 2 +- drivers/scsi/mesh.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_base.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 8 +- drivers/scsi/myrb.c | 8 +- drivers/scsi/ncr53c8xx.c | 14 +-- drivers/scsi/pcmcia/nsp_cs.c | 2 +- drivers/scsi/ppa.c | 10 +- drivers/scsi/qla2xxx/qla_gs.c | 2 +- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 2 +- drivers/scsi/qla2xxx/qla_isr.c | 10 +- drivers/scsi/qla2xxx/qla_sup.c | 6 +- drivers/scsi/qla2xxx/qla_target.c | 6 +- drivers/scsi/qla4xxx/ql4_os.c | 2 +- drivers/scsi/qlogicpti.c | 20 ++-- drivers/scsi/scsi_error.c | 28 ++--- drivers/scsi/scsi_ioctl.c | 4 +- drivers/scsi/scsi_lib.c | 2 +- drivers/scsi/smartpqi/smartpqi_init.c | 17 ++- drivers/scsi/sr.c | 4 +- drivers/scsi/st.c | 8 +- drivers/scsi/sun3_scsi.c | 4 +- drivers/scsi/sym53c8xx_2/sym_fw.c | 2 +- drivers/scsi/sym53c8xx_2/sym_hipd.c | 4 +- drivers/scsi/sym53c8xx_2/sym_nvram.c | 2 +- drivers/scsi/ufs/ufs_bsg.c | 2 +- drivers/scsi/ufs/ufshcd.c | 8 +- drivers/scsi/virtio_scsi.c | 2 +- drivers/scsi/vmw_pvscsi.c | 2 +- drivers/scsi/wd33c93.c | 2 +- drivers/scsi/xen-scsifront.c | 2 +- drivers/soc/qcom/socinfo.c | 22 ++-- drivers/soc/tegra/pmc.c | 2 +- drivers/spi/spi-bcm2835aux.c | 4 +- drivers/spi/spi-fsl-cpm.c | 4 +- drivers/spi/spi-sprd-adi.c | 2 +- drivers/ssb/driver_chipcommon.c | 2 +- drivers/ssb/driver_mipscore.c | 2 +- drivers/ssb/scan.c | 2 +- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 2 +- .../media/atomisp/pci/atomisp_compat_css20.c | 8 +- drivers/staging/media/atomisp/pci/atomisp_ioctl.c | 1 - drivers/staging/media/atomisp/pci/atomisp_v4l2.c | 2 +- drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 2 +- drivers/staging/media/atomisp/pci/sh_css.c | 2 +- drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c | 2 +- .../staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c | 2 +- drivers/staging/media/imx/imx-media-csi.c | 2 +- drivers/staging/media/usbvision/usbvision-i2c.c | 6 +- drivers/target/iscsi/cxgbit/cxgbit_main.c | 2 +- drivers/target/iscsi/iscsi_target.c | 2 +- drivers/target/target_core_pr.c | 4 +- drivers/target/target_core_sbc.c | 2 +- drivers/target/target_core_transport.c | 4 +- drivers/target/tcm_fc/tfc_cmd.c | 2 +- drivers/thermal/qcom/tsens-v0_1.c | 8 +- drivers/thermal/qcom/tsens-v1.c | 4 +- drivers/thunderbolt/ctl.c | 2 +- drivers/thunderbolt/switch.c | 2 +- drivers/thunderbolt/tunnel.c | 4 +- drivers/tty/hvc/hvc_xen.c | 2 +- drivers/tty/mips_ejtag_fdc.c | 2 +- drivers/tty/n_gsm.c | 4 +- drivers/tty/n_hdlc.c | 2 +- drivers/tty/n_r3964.c | 1 - drivers/tty/serial/8250/8250_em.c | 2 +- drivers/tty/serial/8250/8250_fintek.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 2 +- drivers/tty/serial/8250/8250_port.c | 2 +- drivers/tty/serial/8250/8250_uniphier.c | 6 +- drivers/tty/serial/atmel_serial.c | 2 +- drivers/tty/serial/omap-serial.c | 2 - drivers/tty/serial/rda-uart.c | 2 +- drivers/tty/serial/serial-tegra.c | 2 +- drivers/tty/serial/serial_core.c | 2 +- drivers/tty/serial/sunsu.c | 2 +- drivers/tty/serial/sunzilog.c | 2 +- drivers/tty/serial/xilinx_uartps.c | 2 +- drivers/tty/tty_ioctl.c | 2 +- drivers/tty/vt/vt.c | 6 +- drivers/usb/c67x00/c67x00-sched.c | 3 +- drivers/usb/core/hub.c | 2 +- drivers/usb/dwc3/core.c | 5 +- drivers/usb/gadget/function/f_mass_storage.c | 1 - drivers/usb/gadget/udc/atmel_usba_udc.c | 2 +- drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- drivers/usb/gadget/udc/pxa25x_udc.c | 4 +- drivers/usb/host/isp116x-hcd.c | 6 +- drivers/usb/host/pci-quirks.c | 3 +- drivers/usb/host/xhci-dbgcap.c | 2 +- drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci-mem.c | 4 +- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/host/xhci.c | 2 +- drivers/usb/musb/cppi_dma.c | 2 +- drivers/usb/musb/musb_core.c | 13 ++- drivers/usb/musb/musb_dsps.c | 6 +- drivers/usb/musb/musb_gadget_ep0.c | 4 +- drivers/usb/musb/musb_host.c | 6 +- drivers/usb/musb/musb_virthub.c | 2 +- drivers/usb/musb/omap2430.c | 2 +- drivers/usb/musb/tusb6010.c | 2 +- drivers/usb/storage/sddr55.c | 2 +- drivers/usb/storage/uas.c | 2 +- drivers/usb/typec/tcpm/tcpci.c | 2 +- drivers/vfio/pci/vfio_pci.c | 2 +- drivers/vfio/vfio_iommu_type1.c | 2 +- drivers/video/backlight/adp8860_bl.c | 2 +- drivers/video/fbdev/acornfb.c | 2 +- drivers/video/fbdev/arcfb.c | 2 +- drivers/video/fbdev/atmel_lcdfb.c | 4 +- drivers/video/fbdev/aty/radeon_pm.c | 6 +- drivers/video/fbdev/cirrusfb.c | 4 +- drivers/video/fbdev/controlfb.c | 2 +- drivers/video/fbdev/core/fbmem.c | 2 +- drivers/video/fbdev/fsl-diu-fb.c | 4 +- drivers/video/fbdev/gxt4500.c | 2 +- drivers/video/fbdev/hyperv_fb.c | 4 +- drivers/video/fbdev/i740fb.c | 2 +- drivers/video/fbdev/mmp/fb/mmpfb.c | 2 - drivers/video/fbdev/nvidia/nv_hw.c | 2 +- drivers/video/fbdev/offb.c | 4 +- drivers/video/fbdev/omap/lcdc.c | 4 +- drivers/video/fbdev/omap/omapfb_main.c | 20 ++-- drivers/video/fbdev/omap2/omapfb/dss/dispc.c | 4 +- drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c | 2 +- drivers/video/fbdev/omap2/omapfb/omapfb-main.c | 2 +- drivers/video/fbdev/pm2fb.c | 4 +- drivers/video/fbdev/pxa168fb.c | 4 - drivers/video/fbdev/pxafb.c | 2 +- drivers/video/fbdev/riva/fbdev.c | 2 +- drivers/video/fbdev/s3c-fb.c | 6 +- drivers/video/fbdev/sa1100fb.c | 2 +- drivers/video/fbdev/savage/savagefb_driver.c | 2 +- drivers/video/fbdev/sh_mobile_lcdcfb.c | 4 +- drivers/video/fbdev/sis/sis_main.c | 8 +- drivers/video/fbdev/sm501fb.c | 2 +- drivers/video/fbdev/stifb.c | 4 +- drivers/video/fbdev/tdfxfb.c | 2 +- drivers/video/fbdev/via/lcd.c | 2 +- drivers/video/fbdev/xen-fbfront.c | 2 +- drivers/watchdog/sc1200wdt.c | 2 +- drivers/watchdog/wdrtas.c | 2 +- drivers/xen/pvcalls-front.c | 2 +- drivers/xen/xen-acpi-memhotplug.c | 2 +- drivers/xen/xen-pciback/xenbus.c | 2 +- drivers/xen/xen-scsiback.c | 2 +- drivers/xen/xenbus/xenbus_probe_frontend.c | 4 +- fs/9p/vfs_file.c | 2 +- fs/adfs/dir_f.c | 12 +-- fs/affs/inode.c | 2 +- fs/affs/super.c | 6 +- fs/afs/cmservice.c | 16 +-- fs/afs/file.c | 2 +- fs/afs/flock.c | 2 +- fs/afs/fsclient.c | 42 ++++---- fs/afs/misc.c | 18 ++-- fs/afs/rotate.c | 2 +- fs/afs/rxrpc.c | 6 +- fs/afs/vlclient.c | 24 ++--- fs/afs/write.c | 2 +- fs/afs/yfsclient.c | 50 ++++----- fs/aio.c | 2 +- fs/buffer.c | 2 +- fs/ceph/dir.c | 2 +- fs/ceph/file.c | 2 +- fs/cifs/cifssmb.c | 2 +- fs/cifs/connect.c | 10 +- fs/cifs/sess.c | 6 +- fs/cifs/smb2pdu.c | 2 +- fs/configfs/dir.c | 4 +- fs/dax.c | 2 +- fs/dlm/lock.c | 2 +- fs/erofs/zmap.c | 6 +- fs/ext2/inode.c | 4 +- fs/ext2/super.c | 2 +- fs/f2fs/f2fs.h | 2 +- fs/f2fs/node.c | 4 +- fs/fcntl.c | 4 +- fs/fs_context.c | 2 +- fs/fsopen.c | 2 +- fs/gfs2/bmap.c | 4 +- fs/gfs2/quota.c | 2 +- fs/hfsplus/wrapper.c | 2 +- fs/io_uring.c | 2 +- fs/iomap/seek.c | 4 +- fs/jffs2/fs.c | 2 +- fs/jffs2/readinode.c | 2 +- fs/libfs.c | 4 +- fs/locks.c | 6 +- fs/nfs/blocklayout/blocklayout.c | 2 +- fs/nfs/dir.c | 2 +- fs/nfs/filelayout/filelayout.c | 2 +- fs/nfs/flexfilelayout/flexfilelayout.c | 4 +- fs/nfs/fs_context.c | 22 ++-- fs/nfs/nfs3acl.c | 4 +- fs/nfs/nfs4file.c | 2 +- fs/nfs/nfs4idmap.c | 4 +- fs/nfs/nfs4proc.c | 32 +++--- fs/nfs/nfs4state.c | 14 +-- fs/nfs/pagelist.c | 2 +- fs/nfs/pnfs.c | 2 +- fs/nfs_common/nfsacl.c | 2 +- fs/nfsd/blocklayout.c | 4 +- fs/nfsd/nfs4callback.c | 2 +- fs/nfsd/nfs4layouts.c | 2 +- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4state.c | 12 +-- fs/nfsd/nfsfh.c | 4 +- fs/nfsd/nfsproc.c | 2 +- fs/nfsd/nfssvc.c | 2 +- fs/nfsd/vfs.c | 4 +- fs/nilfs2/bmap.c | 2 +- fs/nilfs2/recovery.c | 2 +- fs/nilfs2/segment.c | 19 ++-- fs/notify/fanotify/fanotify_user.c | 2 +- fs/ocfs2/cluster/quorum.c | 2 +- fs/pstore/zone.c | 1 - fs/quota/quota.c | 2 +- fs/seq_file.c | 2 +- fs/signalfd.c | 2 +- fs/ubifs/lprops.c | 4 +- fs/udf/symlink.c | 2 +- fs/ufs/util.h | 12 +-- fs/vboxsf/utils.c | 2 +- include/linux/compat.h | 6 +- include/linux/filter.h | 2 +- include/linux/jhash.h | 26 ++--- include/linux/mm.h | 9 +- include/linux/signal.h | 12 +-- include/linux/skbuff.h | 12 +-- include/math-emu/op-common.h | 10 +- ipc/sem.c | 4 +- ipc/shm.c | 4 +- kernel/auditfilter.c | 2 +- kernel/bpf/cgroup.c | 2 +- kernel/bpf/cpumap.c | 2 +- kernel/bpf/syscall.c | 2 +- kernel/bpf/verifier.c | 4 +- kernel/capability.c | 2 +- kernel/compat.c | 6 +- kernel/debug/gdbstub.c | 6 +- kernel/debug/kdb/kdb_keyboard.c | 4 +- kernel/debug/kdb/kdb_support.c | 6 +- kernel/events/core.c | 2 +- kernel/irq/handle.c | 2 +- kernel/irq/manage.c | 4 +- kernel/kallsyms.c | 4 +- kernel/power/hibernate.c | 2 +- kernel/power/qos.c | 4 +- kernel/sched/core.c | 2 +- kernel/sched/topology.c | 6 +- kernel/signal.c | 2 +- kernel/sys.c | 2 +- kernel/time/hrtimer.c | 2 +- kernel/time/posix-timers.c | 4 +- kernel/time/tick-broadcast.c | 2 +- kernel/time/timer.c | 2 +- kernel/trace/blktrace.c | 2 +- kernel/trace/trace_events_filter.c | 4 +- lib/asn1_decoder.c | 4 +- lib/assoc_array.c | 2 +- lib/bootconfig.c | 4 +- lib/cmdline.c | 10 +- lib/dim/net_dim.c | 2 +- lib/dim/rdma_dim.c | 4 +- lib/glob.c | 2 +- lib/siphash.c | 36 +++---- lib/ts_fsm.c | 2 +- lib/vsprintf.c | 15 +-- lib/xz/xz_dec_lzma2.c | 4 +- lib/xz/xz_dec_stream.c | 16 +-- lib/zstd/bitstream.h | 10 +- lib/zstd/compress.c | 2 +- lib/zstd/decompress.c | 12 +-- lib/zstd/huf_compress.c | 4 +- net/8021q/vlan_dev.c | 2 +- net/9p/trans_xen.c | 2 +- net/atm/common.c | 4 +- net/atm/lec.c | 2 +- net/atm/resources.c | 8 +- net/bpf/test_run.c | 2 +- net/can/j1939/socket.c | 2 +- net/can/j1939/transport.c | 20 ++-- net/ceph/ceph_hash.c | 20 ++-- net/ceph/crush/mapper.c | 2 +- net/ceph/messenger.c | 4 +- net/ceph/mon_client.c | 2 +- net/ceph/osd_client.c | 4 +- net/core/dev.c | 4 +- net/core/dev_ioctl.c | 6 +- net/core/devlink.c | 4 +- net/core/drop_monitor.c | 2 +- net/core/filter.c | 2 +- net/core/pktgen.c | 2 +- net/core/skmsg.c | 1 - net/core/sock.c | 2 +- net/dccp/ccids/ccid3.c | 2 +- net/dccp/feat.c | 3 +- net/dccp/input.c | 10 +- net/dccp/options.c | 2 +- net/dccp/output.c | 8 +- net/dccp/proto.c | 8 +- net/decnet/af_decnet.c | 6 +- net/decnet/dn_nsp_in.c | 2 +- net/decnet/dn_table.c | 2 +- net/decnet/sysctl_net_decnet.c | 2 +- net/dsa/slave.c | 2 +- net/ieee802154/6lowpan/reassembly.c | 2 +- net/ieee802154/6lowpan/rx.c | 4 +- net/iucv/af_iucv.c | 10 +- net/mpls/af_mpls.c | 2 +- net/mptcp/protocol.c | 3 +- net/ncsi/ncsi-manage.c | 4 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 2 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 2 +- net/netlink/policy.c | 2 +- net/netrom/nr_in.c | 2 +- net/netrom/nr_route.c | 8 +- net/openvswitch/conntrack.c | 4 +- net/openvswitch/flow.c | 2 +- net/packet/af_packet.c | 2 +- net/phonet/pep.c | 10 +- net/rds/send.c | 2 +- net/rose/rose_in.c | 2 +- net/rose/rose_route.c | 4 +- net/rxrpc/af_rxrpc.c | 6 +- net/rxrpc/call_accept.c | 2 +- net/rxrpc/conn_client.c | 2 +- net/rxrpc/input.c | 6 +- net/rxrpc/local_object.c | 2 +- net/rxrpc/peer_event.c | 2 +- net/rxrpc/recvmsg.c | 2 +- net/rxrpc/sendmsg.c | 6 +- net/sched/sch_cake.c | 2 +- net/sctp/ipv6.c | 2 +- net/sctp/outqueue.c | 6 +- net/sctp/sm_make_chunk.c | 2 +- net/sctp/sm_sideeffect.c | 2 +- net/sctp/sm_statefuns.c | 2 +- net/smc/smc_close.c | 2 +- net/sunrpc/auth_gss/gss_krb5_wrap.c | 2 +- net/sunrpc/clnt.c | 22 ++-- net/sunrpc/xprt.c | 2 +- net/sunrpc/xprtrdma/verbs.c | 2 +- net/sunrpc/xprtsock.c | 8 +- net/tipc/bearer.c | 2 +- net/tipc/group.c | 2 +- net/tipc/link.c | 2 +- net/tipc/socket.c | 4 +- net/unix/af_unix.c | 2 +- net/wireless/chan.c | 4 +- net/wireless/mlme.c | 2 +- net/wireless/nl80211.c | 20 ++-- net/wireless/scan.c | 2 +- net/wireless/sme.c | 4 +- net/wireless/util.c | 4 +- net/wireless/wext-compat.c | 4 +- net/x25/x25_facilities.c | 2 +- net/x25/x25_in.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- samples/bpf/hbm.c | 2 +- security/apparmor/domain.c | 2 +- security/apparmor/lib.c | 4 +- security/integrity/ima/ima_appraise.c | 4 +- security/integrity/ima/ima_policy.c | 8 +- security/integrity/ima/ima_template_lib.c | 2 +- security/keys/process_keys.c | 6 +- security/keys/request_key.c | 8 +- security/selinux/hooks.c | 8 +- security/selinux/ss/mls.c | 4 +- security/smack/smack_lsm.c | 2 +- security/tomoyo/common.c | 18 ++-- security/tomoyo/file.c | 2 +- sound/ppc/snd_ps3.c | 4 +- sound/soc/atmel/mchp-i2s-mcc.c | 2 +- sound/soc/codecs/jz4770.c | 2 +- sound/soc/codecs/pcm186x.c | 2 +- sound/soc/fsl/fsl_ssi.c | 2 +- sound/soc/hisilicon/hi6210-i2s.c | 4 +- sound/soc/intel/baytrail/sst-baytrail-pcm.c | 2 +- sound/soc/intel/boards/bytcht_es8316.c | 2 +- sound/soc/intel/boards/bytcr_rt5651.c | 4 +- sound/soc/intel/skylake/skl-pcm.c | 2 +- sound/soc/meson/axg-tdm-interface.c | 10 +- sound/soc/pxa/pxa-ssp.c | 2 +- sound/soc/rockchip/rockchip_pdm.c | 6 +- sound/soc/samsung/i2s.c | 2 +- sound/soc/soc-core.c | 2 +- sound/soc/soc-topology.c | 4 +- sound/soc/sof/intel/hda-dai.c | 4 +- sound/soc/sof/pcm.c | 4 +- sound/soc/ti/davinci-i2s.c | 2 +- sound/soc/ti/n810.c | 2 +- sound/soc/ti/omap-dmic.c | 4 +- sound/soc/ti/omap-mcpdm.c | 8 +- sound/soc/ti/rx51.c | 2 +- sound/soc/zte/zx-i2s.c | 4 +- sound/soc/zte/zx-spdif.c | 2 +- 1148 files changed, 2667 insertions(+), 2737 deletions(-) (limited to 'drivers/gpu') diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c index ac110ae8f978..5b60c248de9e 100644 --- a/arch/alpha/kernel/module.c +++ b/arch/alpha/kernel/module.c @@ -212,7 +212,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, STO_ALPHA_STD_GPLOAD) /* Omit the prologue. */ value += 8; - /* FALLTHRU */ + fallthrough; case R_ALPHA_BRADDR: value -= (u64)location + 4; if (value & 3) diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index a813020d2f11..15bc9d1e79f4 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c @@ -453,7 +453,7 @@ syscall_restart(unsigned long r0, unsigned long r19, regs->r0 = EINTR; break; } - /* fallthrough */ + fallthrough; case ERESTARTNOINTR: regs->r0 = r0; /* reset v0 and a3 and replay syscall */ regs->r19 = r19; diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 49754e07e04f..921d4b6e4d95 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -883,7 +883,7 @@ do_entUnaUser(void __user * va, unsigned long opcode, case 0x26: /* sts */ fake_reg = s_reg_to_mem(alpha_read_fp_reg(reg)); - /* FALLTHRU */ + fallthrough; case 0x2c: /* stl */ __asm__ __volatile__( @@ -911,7 +911,7 @@ do_entUnaUser(void __user * va, unsigned long opcode, case 0x27: /* stt */ fake_reg = alpha_read_fp_reg(reg); - /* FALLTHRU */ + fallthrough; case 0x2d: /* stq */ __asm__ __volatile__( diff --git a/arch/arc/kernel/disasm.c b/arch/arc/kernel/disasm.c index d04837d91b40..03f8b1be0c3a 100644 --- a/arch/arc/kernel/disasm.c +++ b/arch/arc/kernel/disasm.c @@ -339,7 +339,7 @@ void __kprobes disasm_instr(unsigned long addr, struct disasm_state *state, case op_LDWX_S: /* LDWX_S c, [b, u6] */ state->x = 1; - /* intentional fall-through */ + fallthrough; case op_LDW_S: /* LDW_S c, [b, u6] */ state->zz = 2; diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 3d57ed0d8535..8222f8c54690 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -321,7 +321,7 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs) regs->r0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: /* diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index f87758a6851b..74ad4256022e 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -572,7 +572,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, #else BUILD_BUG_ON(sizeof(u32) != sizeof(value)); #endif - /* Fall through */ + fallthrough; case DW_EH_PE_native: if (end < (const void *)(ptr.pul + 1)) return 0; @@ -827,7 +827,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, case DW_CFA_def_cfa: state->cfa.reg = get_uleb128(&ptr.p8, end); unw_debug("cfa_def_cfa: r%lu ", state->cfa.reg); - /* fall through */ + fallthrough; case DW_CFA_def_cfa_offset: state->cfa.offs = get_uleb128(&ptr.p8, end); unw_debug("cfa_def_cfa_offset: 0x%lx ", @@ -835,7 +835,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, break; case DW_CFA_def_cfa_sf: state->cfa.reg = get_uleb128(&ptr.p8, end); - /* fall through */ + fallthrough; case DW_CFA_def_cfa_offset_sf: state->cfa.offs = get_sleb128(&ptr.p8, end) * state->dataAlign; diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 7fff88e61252..7a4853b1213a 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -547,7 +547,7 @@ static int arch_build_bp_info(struct perf_event *bp, if ((hw->ctrl.type != ARM_BREAKPOINT_EXECUTE) && max_watchpoint_len >= 8) break; - /* Else, fall through */ + fallthrough; default: return -EINVAL; } @@ -612,12 +612,12 @@ int hw_breakpoint_arch_parse(struct perf_event *bp, /* Allow halfword watchpoints and breakpoints. */ if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2) break; - /* Else, fall through */ + fallthrough; case 3: /* Allow single byte watchpoint. */ if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1) break; - /* Else, fall through */ + fallthrough; default: ret = -EINVAL; goto out; @@ -884,7 +884,7 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, break; case ARM_ENTRY_ASYNC_WATCHPOINT: WARN(1, "Asynchronous watchpoint exception taken. Debugging results may be unreliable\n"); - /* Fall through */ + fallthrough; case ARM_ENTRY_SYNC_WATCHPOINT: watchpoint_handler(addr, fsr, regs); break; @@ -933,7 +933,7 @@ static bool core_has_os_save_restore(void) ARM_DBG_READ(c1, c1, 4, oslsr); if (oslsr & ARM_OSLSR_OSLM0) return true; - /* Else, fall through */ + fallthrough; default: return false; } diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index c9dc912b83f0..c1892f733f20 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -596,7 +596,7 @@ static int do_signal(struct pt_regs *regs, int syscall) switch (retval) { case -ERESTART_RESTARTBLOCK: restart -= 2; - /* Fall through */ + fallthrough; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: diff --git a/arch/arm/mach-ep93xx/crunch.c b/arch/arm/mach-ep93xx/crunch.c index 1c05c5bf7e5c..757032d82f63 100644 --- a/arch/arm/mach-ep93xx/crunch.c +++ b/arch/arm/mach-ep93xx/crunch.c @@ -49,7 +49,7 @@ static int crunch_do(struct notifier_block *self, unsigned long cmd, void *t) * FALLTHROUGH: Ensure we don't try to overwrite our newly * initialised state information on the first fault. */ - /* Fall through */ + fallthrough; case THREAD_NOTIFY_EXIT: crunch_task_release(thread); diff --git a/arch/arm/mach-mmp/pm-mmp2.c b/arch/arm/mach-mmp/pm-mmp2.c index 2d86381e152d..7a6f74c32d42 100644 --- a/arch/arm/mach-mmp/pm-mmp2.c +++ b/arch/arm/mach-mmp/pm-mmp2.c @@ -123,19 +123,19 @@ void mmp2_pm_enter_lowpower_mode(int state) case POWER_MODE_SYS_SLEEP: apcr |= MPMU_PCR_PJ_SLPEN; /* set the SLPEN bit */ apcr |= MPMU_PCR_PJ_VCTCXOSD; /* set VCTCXOSD */ - /* fall through */ + fallthrough; case POWER_MODE_CHIP_SLEEP: apcr |= MPMU_PCR_PJ_SLPEN; - /* fall through */ + fallthrough; case POWER_MODE_APPS_SLEEP: apcr |= MPMU_PCR_PJ_APBSD; /* set APBSD */ - /* fall through */ + fallthrough; case POWER_MODE_APPS_IDLE: apcr |= MPMU_PCR_PJ_AXISD; /* set AXISDD bit */ apcr |= MPMU_PCR_PJ_DDRCORSD; /* set DDRCORSD bit */ idle_cfg |= APMU_PJ_IDLE_CFG_PJ_PWRDWN; /* PJ power down */ apcr |= MPMU_PCR_PJ_SPSD; - /* fall through */ + fallthrough; case POWER_MODE_CORE_EXTIDLE: idle_cfg |= APMU_PJ_IDLE_CFG_PJ_IDLE; /* set the IDLE bit */ idle_cfg &= ~APMU_PJ_IDLE_CFG_ISO_MODE_CNTRL_MASK; diff --git a/arch/arm/mach-mmp/pm-pxa910.c b/arch/arm/mach-mmp/pm-pxa910.c index 69ebe18ff209..1d71d73c1862 100644 --- a/arch/arm/mach-mmp/pm-pxa910.c +++ b/arch/arm/mach-mmp/pm-pxa910.c @@ -145,23 +145,23 @@ void pxa910_pm_enter_lowpower_mode(int state) case POWER_MODE_UDR: /* only shutdown APB in UDR */ apcr |= MPMU_APCR_STBYEN | MPMU_APCR_APBSD; - /* fall through */ + fallthrough; case POWER_MODE_SYS_SLEEP: apcr |= MPMU_APCR_SLPEN; /* set the SLPEN bit */ apcr |= MPMU_APCR_VCTCXOSD; /* set VCTCXOSD */ - /* fall through */ + fallthrough; case POWER_MODE_APPS_SLEEP: apcr |= MPMU_APCR_DDRCORSD; /* set DDRCORSD */ - /* fall through */ + fallthrough; case POWER_MODE_APPS_IDLE: apcr |= MPMU_APCR_AXISD; /* set AXISDD bit */ - /* fall through */ + fallthrough; case POWER_MODE_CORE_EXTIDLE: idle_cfg |= APMU_MOH_IDLE_CFG_MOH_IDLE; idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWRDWN; idle_cfg |= APMU_MOH_IDLE_CFG_MOH_PWR_SW(3) | APMU_MOH_IDLE_CFG_MOH_L2_PWR_SW(3); - /* fall through */ + fallthrough; case POWER_MODE_CORE_INTIDLE: break; } diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 1d119b974f5f..59755b5a1ad7 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -396,7 +396,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "3.1"; break; case 7: - /* FALLTHROUGH */ default: /* Use the latest known revision as default */ omap_revision = OMAP3430_REV_ES3_1_2; @@ -416,7 +415,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "1.0"; break; case 1: - /* FALLTHROUGH */ default: omap_revision = AM35XX_REV_ES1_1; cpu_rev = "1.1"; @@ -435,7 +433,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "1.1"; break; case 2: - /* FALLTHROUGH */ default: omap_revision = OMAP3630_REV_ES1_2; cpu_rev = "1.2"; @@ -456,7 +453,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "2.0"; break; case 3: - /* FALLTHROUGH */ default: omap_revision = TI8168_REV_ES2_1; cpu_rev = "2.1"; @@ -473,7 +469,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "2.0"; break; case 2: - /* FALLTHROUGH */ default: omap_revision = AM335X_REV_ES2_1; cpu_rev = "2.1"; @@ -491,7 +486,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "1.1"; break; case 2: - /* FALLTHROUGH */ default: omap_revision = AM437X_REV_ES1_2; cpu_rev = "1.2"; @@ -502,7 +496,6 @@ void __init omap3xxx_check_revision(void) case 0xb968: switch (rev) { case 0: - /* FALLTHROUGH */ case 1: omap_revision = TI8148_REV_ES1_0; cpu_rev = "1.0"; @@ -512,7 +505,6 @@ void __init omap3xxx_check_revision(void) cpu_rev = "2.0"; break; case 3: - /* FALLTHROUGH */ default: omap_revision = TI8148_REV_ES2_1; cpu_rev = "2.1"; diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c index 6b4548f3b57f..fc7bb2ca1672 100644 --- a/arch/arm/mach-omap2/omap_device.c +++ b/arch/arm/mach-omap2/omap_device.c @@ -240,7 +240,7 @@ static int _omap_device_notifier_call(struct notifier_block *nb, if (pdev->dev.of_node) omap_device_build_from_dt(pdev); omap_auxdata_legacy_init(dev); - /* fall through */ + fallthrough; default: od = to_omap_device(pdev); if (od) diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c index d13344b2ddcd..87cb47220e82 100644 --- a/arch/arm/mach-orion5x/dns323-setup.c +++ b/arch/arm/mach-orion5x/dns323-setup.c @@ -624,7 +624,7 @@ static void __init dns323_init(void) dns323ab_leds[0].active_low = 1; gpio_request(DNS323_GPIO_LED_POWER1, "Power Led Enable"); gpio_direction_output(DNS323_GPIO_LED_POWER1, 0); - /* Fall through */ + fallthrough; case DNS323_REV_B1: i2c_register_board_info(0, dns323ab_i2c_devices, ARRAY_SIZE(dns323ab_i2c_devices)); diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index ea2c84214bac..d23970bd638d 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c @@ -46,7 +46,7 @@ static int __init parse_tag_acorn(const struct tag *tag) switch (tag->u.acorn.vram_pages) { case 512: vram_size += PAGE_SIZE * 256; - /* Fall through - ??? */ + fallthrough; /* ??? */ case 256: vram_size += PAGE_SIZE * 256; default: diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 76a65df42d10..d5c805adf7a8 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -70,7 +70,7 @@ static void __init tegra_cpu_reset_handler_enable(void) switch (err) { case -ENOSYS: tegra_cpu_reset_handler_set(reset_address); - /* fall through */ + fallthrough; case 0: is_enabled = true; break; diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index f4bfc1cac91a..ea81e89e7740 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -694,7 +694,7 @@ thumb2arm(u16 tinstr) return subset[(L<<1) | ((tinstr & (1<<8)) >> 8)] | (tinstr & 255); /* register_list */ } - /* Else, fall through - for illegal instruction case */ + fallthrough; /* for illegal instruction case */ default: return BAD_INSTR; @@ -750,7 +750,7 @@ do_alignment_t32_to_handler(u32 *pinstr, struct pt_regs *regs, case 0xe8e0: case 0xe9e0: poffset->un = (tinst2 & 0xff) << 2; - /* Fall through */ + fallthrough; case 0xe940: case 0xe9c0: diff --git a/arch/arm/mm/proc-v7-bugs.c b/arch/arm/mm/proc-v7-bugs.c index c0fbfca5da8b..114c05ab4dd9 100644 --- a/arch/arm/mm/proc-v7-bugs.c +++ b/arch/arm/mm/proc-v7-bugs.c @@ -71,7 +71,7 @@ static void cpu_v7_spectre_init(void) /* Other ARM CPUs require no workaround */ if (read_cpuid_implementor() == ARM_CPU_IMP_ARM) break; - /* fallthrough */ + fallthrough; /* Cortex A57/A72 require firmware workaround */ case ARM_CPU_PART_CORTEX_A57: case ARM_CPU_PART_CORTEX_A72: { diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index b2e9e822426f..1eb59003bdec 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -309,14 +309,14 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) * not supported by current hardware on OMAP1 * w |= (0x03 << 7); */ - /* fall through */ + fallthrough; case OMAP_DMA_DATA_BURST_16: if (dma_omap2plus()) { burst = 0x3; break; } /* OMAP1 don't support burst 16 */ - /* fall through */ + fallthrough; default: BUG(); } @@ -393,7 +393,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) break; } /* OMAP1 don't support burst 16 */ - /* fall through */ + fallthrough; default: printk(KERN_ERR "Invalid DMA burst mode\n"); BUG(); diff --git a/arch/arm/probes/decode.c b/arch/arm/probes/decode.c index fe81a9c21f2d..c84053a81358 100644 --- a/arch/arm/probes/decode.c +++ b/arch/arm/probes/decode.c @@ -307,7 +307,7 @@ static bool __kprobes decode_regs(probes_opcode_t *pinsn, u32 regs, bool modify) case REG_TYPE_NOPCWB: if (!is_writeback(insn)) break; /* No writeback, so any register is OK */ - /* fall through... */ + fallthrough; case REG_TYPE_NOPC: case REG_TYPE_NOPCX: /* Reject PC (R15) */ diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c index 90b5bc723c83..feefa2055eba 100644 --- a/arch/arm/probes/kprobes/core.c +++ b/arch/arm/probes/kprobes/core.c @@ -280,7 +280,7 @@ void __kprobes kprobe_handler(struct pt_regs *regs) /* A nested probe was hit in FIQ, it is a BUG */ pr_warn("Unrecoverable kprobe detected.\n"); dump_kprobe(p); - /* fall through */ + fallthrough; default: /* impossible cases */ BUG(); diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index 455966401102..a85174d05473 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -322,7 +322,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size) */ if (memblock_is_map_memory(phys)) return (void __iomem *)__phys_to_virt(phys); - /* fall through */ + fallthrough; default: if (region->attribute & EFI_MEMORY_WB) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index a389b999482e..6424584be01e 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -686,7 +686,7 @@ static s64 arm64_ftr_safe_value(const struct arm64_ftr_bits *ftrp, s64 new, case FTR_HIGHER_OR_ZERO_SAFE: if (!cur || !new) break; - /* Fallthrough */ + fallthrough; case FTR_HIGHER_SAFE: ret = new > cur ? new : cur; break; diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c index 393c6fb1f1cb..1886a02c3f50 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -327,7 +327,7 @@ static void cpuinfo_detect_icache_policy(struct cpuinfo_arm64 *info) set_bit(ICACHEF_VPIPT, &__icache_flags); break; default: - /* Fallthrough */ + fallthrough; case ICACHE_POLICY_VIPT: /* Assume aliasing */ set_bit(ICACHEF_ALIASING, &__icache_flags); diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index af234a1e08b7..712e97c03e54 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -257,7 +257,7 @@ static int hw_breakpoint_control(struct perf_event *bp, * level. */ enable_debug_monitors(dbg_el); - /* Fall through */ + fallthrough; case HW_BREAKPOINT_RESTORE: /* Setup the address register. */ write_wb_reg(val_reg, i, info->address); @@ -541,13 +541,13 @@ int hw_breakpoint_arch_parse(struct perf_event *bp, if (hw->ctrl.len == ARM_BREAKPOINT_LEN_2) break; - /* Fallthrough */ + fallthrough; case 3: /* Allow single byte watchpoint. */ if (hw->ctrl.len == ARM_BREAKPOINT_LEN_1) break; - /* Fallthrough */ + fallthrough; default: return -EINVAL; } diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 1cd1a4d0ed30..2a1ad95d9b2c 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -315,21 +315,21 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, /* MOVW instruction relocations. */ case R_AARCH64_MOVW_UABS_G0_NC: overflow_check = false; - /* Fall through */ + fallthrough; case R_AARCH64_MOVW_UABS_G0: ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0, AARCH64_INSN_IMM_MOVKZ); break; case R_AARCH64_MOVW_UABS_G1_NC: overflow_check = false; - /* Fall through */ + fallthrough; case R_AARCH64_MOVW_UABS_G1: ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16, AARCH64_INSN_IMM_MOVKZ); break; case R_AARCH64_MOVW_UABS_G2_NC: overflow_check = false; - /* Fall through */ + fallthrough; case R_AARCH64_MOVW_UABS_G2: ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32, AARCH64_INSN_IMM_MOVKZ); @@ -397,7 +397,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, break; case R_AARCH64_ADR_PREL_PG_HI21_NC: overflow_check = false; - /* Fall through */ + fallthrough; case R_AARCH64_ADR_PREL_PG_HI21: ovf = reloc_insn_adrp(me, sechdrs, loc, val); if (ovf && ovf != -ERANGE) diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 03957a1ae6c0..355ee9eed4dd 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -151,7 +151,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) break; } pr_crit("CPU%u: may not have shut down cleanly\n", cpu); - /* Fall through */ + fallthrough; case CPU_STUCK_IN_KERNEL: pr_crit("CPU%u: is stuck in kernel\n", cpu); if (status & CPU_STUCK_REASON_52_BIT_VA) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index fe6c7d79309d..5d690d60ccad 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -128,7 +128,7 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu) switch (ESR_ELx_EC(esr)) { case ESR_ELx_EC_WATCHPT_LOW: run->debug.arch.far = vcpu->arch.fault.far_el2; - /* fall through */ + fallthrough; case ESR_ELx_EC_SOFTSTP_LOW: case ESR_ELx_EC_BREAKPT_LOW: case ESR_ELx_EC_BKPT32: diff --git a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h index 0297dc63988c..5e28ea6aa097 100644 --- a/arch/arm64/kvm/hyp/include/hyp/debug-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/debug-sr.h @@ -21,70 +21,70 @@ #define save_debug(ptr,reg,nr) \ switch (nr) { \ case 15: ptr[15] = read_debug(reg, 15); \ - /* Fall through */ \ + fallthrough; \ case 14: ptr[14] = read_debug(reg, 14); \ - /* Fall through */ \ + fallthrough; \ case 13: ptr[13] = read_debug(reg, 13); \ - /* Fall through */ \ + fallthrough; \ case 12: ptr[12] = read_debug(reg, 12); \ - /* Fall through */ \ + fallthrough; \ case 11: ptr[11] = read_debug(reg, 11); \ - /* Fall through */ \ + fallthrough; \ case 10: ptr[10] = read_debug(reg, 10); \ - /* Fall through */ \ + fallthrough; \ case 9: ptr[9] = read_debug(reg, 9); \ - /* Fall through */ \ + fallthrough; \ case 8: ptr[8] = read_debug(reg, 8); \ - /* Fall through */ \ + fallthrough; \ case 7: ptr[7] = read_debug(reg, 7); \ - /* Fall through */ \ + fallthrough; \ case 6: ptr[6] = read_debug(reg, 6); \ - /* Fall through */ \ + fallthrough; \ case 5: ptr[5] = read_debug(reg, 5); \ - /* Fall through */ \ + fallthrough; \ case 4: ptr[4] = read_debug(reg, 4); \ - /* Fall through */ \ + fallthrough; \ case 3: ptr[3] = read_debug(reg, 3); \ - /* Fall through */ \ + fallthrough; \ case 2: ptr[2] = read_debug(reg, 2); \ - /* Fall through */ \ + fallthrough; \ case 1: ptr[1] = read_debug(reg, 1); \ - /* Fall through */ \ + fallthrough; \ default: ptr[0] = read_debug(reg, 0); \ } #define restore_debug(ptr,reg,nr) \ switch (nr) { \ case 15: write_debug(ptr[15], reg, 15); \ - /* Fall through */ \ + fallthrough; \ case 14: write_debug(ptr[14], reg, 14); \ - /* Fall through */ \ + fallthrough; \ case 13: write_debug(ptr[13], reg, 13); \ - /* Fall through */ \ + fallthrough; \ case 12: write_debug(ptr[12], reg, 12); \ - /* Fall through */ \ + fallthrough; \ case 11: write_debug(ptr[11], reg, 11); \ - /* Fall through */ \ + fallthrough; \ case 10: write_debug(ptr[10], reg, 10); \ - /* Fall through */ \ + fallthrough; \ case 9: write_debug(ptr[9], reg, 9); \ - /* Fall through */ \ + fallthrough; \ case 8: write_debug(ptr[8], reg, 8); \ - /* Fall through */ \ + fallthrough; \ case 7: write_debug(ptr[7], reg, 7); \ - /* Fall through */ \ + fallthrough; \ case 6: write_debug(ptr[6], reg, 6); \ - /* Fall through */ \ + fallthrough; \ case 5: write_debug(ptr[5], reg, 5); \ - /* Fall through */ \ + fallthrough; \ case 4: write_debug(ptr[4], reg, 4); \ - /* Fall through */ \ + fallthrough; \ case 3: write_debug(ptr[3], reg, 3); \ - /* Fall through */ \ + fallthrough; \ case 2: write_debug(ptr[2], reg, 2); \ - /* Fall through */ \ + fallthrough; \ case 1: write_debug(ptr[1], reg, 1); \ - /* Fall through */ \ + fallthrough; \ default: write_debug(ptr[0], reg, 0); \ } diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 5a0073511efb..452f4cacd674 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -340,10 +340,10 @@ void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if) case 7: cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3); cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2); - /* Fall through */ + fallthrough; case 6: cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1); - /* Fall through */ + fallthrough; default: cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0); } @@ -352,10 +352,10 @@ void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if) case 7: cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3); cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2); - /* Fall through */ + fallthrough; case 6: cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1); - /* Fall through */ + fallthrough; default: cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0); } @@ -373,10 +373,10 @@ void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if) case 7: __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3); __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2); - /* Fall through */ + fallthrough; case 6: __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1); - /* Fall through */ + fallthrough; default: __vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0); } @@ -385,10 +385,10 @@ void __vgic_v3_restore_aprs(struct vgic_v3_cpu_if *cpu_if) case 7: __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3); __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2); - /* Fall through */ + fallthrough; case 6: __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1); - /* Fall through */ + fallthrough; default: __vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0); } diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c index a206655a39a5..9b11c096a042 100644 --- a/arch/arm64/mm/context.c +++ b/arch/arm64/mm/context.c @@ -45,7 +45,7 @@ static u32 get_cpu_asid_bits(void) default: pr_warn("CPU%d: Unknown ASID size (%d); assuming 8-bit\n", smp_processor_id(), fld); - /* Fallthrough */ + fallthrough; case 0: asid = 8; break; diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c index e456652facce..d05c78eace1b 100644 --- a/arch/c6x/kernel/signal.c +++ b/arch/c6x/kernel/signal.c @@ -220,7 +220,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) regs->a4 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: do_restart: regs->a4 = regs->orig_a4; @@ -252,7 +252,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs, break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->a4 = regs->orig_a4; regs->pc -= 4; diff --git a/arch/csky/kernel/signal.c b/arch/csky/kernel/signal.c index 9452d6570b7e..970895df75ec 100644 --- a/arch/csky/kernel/signal.c +++ b/arch/csky/kernel/signal.c @@ -194,7 +194,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->a0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->a0 = regs->orig_a0; regs->pc -= TRAP0_SIZE; diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index 38d335488a54..69e68949787f 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c @@ -227,7 +227,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka) regs->er0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: do_restart: regs->er0 = regs->orig_er0; diff --git a/arch/hexagon/kernel/module.c b/arch/hexagon/kernel/module.c index cf99fb79a124..cb3bf19b0640 100644 --- a/arch/hexagon/kernel/module.c +++ b/arch/hexagon/kernel/module.c @@ -120,7 +120,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, } case R_HEXAGON_HI16: value = (value>>16) & 0xffff; - /* fallthrough */ + fallthrough; case R_HEXAGON_LO16: *location &= ~0x00c03fff; *location |= value & 0x3fff; diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c index d48864c48e5a..94cc7ff52dce 100644 --- a/arch/hexagon/kernel/signal.c +++ b/arch/hexagon/kernel/signal.c @@ -155,7 +155,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->r00 = -EINTR; break; } - /* Fall through */ + fallthrough; case -ERESTARTNOINTR: regs->r06 = regs->syscall_nr; pt_set_elr(regs, pt_elr(regs) - 4); diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c index bec762a9b418..fec70d662d0c 100644 --- a/arch/ia64/kernel/crash.c +++ b/arch/ia64/kernel/crash.c @@ -163,7 +163,7 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data) case DIE_INIT_MONARCH_LEAVE: if (!kdump_freeze_monarch) break; - /* fall through */ + fallthrough; case DIE_INIT_SLAVE_LEAVE: case DIE_INIT_MONARCH_ENTER: case DIE_MCA_RENDZVOUS_LEAVE: diff --git a/arch/ia64/kernel/module.c b/arch/ia64/kernel/module.c index 1a42ba885188..00a496cb346f 100644 --- a/arch/ia64/kernel/module.c +++ b/arch/ia64/kernel/module.c @@ -654,7 +654,7 @@ do_reloc (struct module *mod, uint8_t r_type, Elf64_Sym *sym, uint64_t addend, } } else if (!is_internal(mod, val)) val = get_plt(mod, location, val, &ok); - /* FALL THROUGH */ + fallthrough; default: val -= bundle(location); break; diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 971f166873aa..0dc3611e7971 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -3472,7 +3472,7 @@ pfm_restart(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs) break; case PFM_CTX_LOADED: if (CTX_HAS_SMPL(ctx) && fmt->fmt_restart_active) break; - /* fall through */ + fallthrough; case PFM_CTX_UNLOADED: case PFM_CTX_ZOMBIE: DPRINT(("invalid state=%d\n", state)); diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index d07ed65c9c6e..e67b22fc3c60 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c @@ -374,7 +374,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) /* note: scr->pt.r10 is already -1 */ break; } - /*FALLTHRU*/ + fallthrough; case ERESTARTNOINTR: ia64_decrement_ip(&scr->pt); restart = 0; /* don't restart twice if handle_signal() fails... */ diff --git a/arch/ia64/kernel/unaligned.c b/arch/ia64/kernel/unaligned.c index 2d4e65ba5c3e..6c1a8951dfbb 100644 --- a/arch/ia64/kernel/unaligned.c +++ b/arch/ia64/kernel/unaligned.c @@ -1431,7 +1431,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /*FALLTHRU*/ + fallthrough; case LDS_IMM_OP: case LDSA_IMM_OP: case LDFS_OP: @@ -1459,7 +1459,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /*FALLTHRU*/ + fallthrough; case LD_IMM_OP: case LDA_IMM_OP: case LDBIAS_IMM_OP: @@ -1475,7 +1475,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs) if (u.insn.x) /* oops, really a semaphore op (cmpxchg, etc) */ goto failure; - /*FALLTHRU*/ + fallthrough; case ST_IMM_OP: case STREL_IMM_OP: ret = emulate_store_int(ifa, u.insn, regs); diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c index 7601fe0622d2..6bd64c35e691 100644 --- a/arch/ia64/kernel/unwind.c +++ b/arch/ia64/kernel/unwind.c @@ -324,7 +324,7 @@ unw_access_gr (struct unw_frame_info *info, int regnum, unsigned long *val, char return 0; } } - /* fall through */ + fallthrough; case UNW_NAT_NONE: dummy_nat = 0; nat_addr = &dummy_nat; diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c index 37091898adb3..5e0e682f9c61 100644 --- a/arch/m68k/atari/atakeyb.c +++ b/arch/m68k/atari/atakeyb.c @@ -207,7 +207,7 @@ repeat: self_test_last_rcv = jiffies; break; } - /* FALL THROUGH */ + fallthrough; default: break_flag = scancode & BREAK_MASK; diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index fc034fd19798..a98fca977073 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -1067,7 +1067,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) regs->d0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: do_restart: regs->d0 = regs->orig_d0; diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c index 5c9f3a2d6538..a621fcc1a576 100644 --- a/arch/m68k/mac/config.c +++ b/arch/m68k/mac/config.c @@ -1018,7 +1018,7 @@ int __init mac_platform_init(void) */ platform_device_register_simple("mac_scsi", 1, mac_scsi_duo_rsrc, ARRAY_SIZE(mac_scsi_duo_rsrc)); - /* fall through */ + fallthrough; case MAC_SCSI_OLD: /* Addresses from Developer Notes for Duo System, * PowerBook 180 & 160, 140 & 170, Macintosh IIsi diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c index 1f0fad2a98a0..ac77d73af19a 100644 --- a/arch/m68k/mac/via.c +++ b/arch/m68k/mac/via.c @@ -370,7 +370,7 @@ void via_nubus_irq_startup(int irq) /* Allow NuBus slots 9 through F. */ via2[vDirA] &= 0x80 | ~(1 << irq_idx); } - /* fall through */ + fallthrough; case MAC_VIA_IICI: via_irq_enable(irq); break; diff --git a/arch/m68k/mm/fault.c b/arch/m68k/mm/fault.c index 795f483b1050..ef46e77e97a5 100644 --- a/arch/m68k/mm/fault.c +++ b/arch/m68k/mm/fault.c @@ -118,7 +118,7 @@ good_area: pr_debug("do_page_fault: good_area\n"); switch (error_code & 3) { default: /* 3: write, present */ - /* fall through */ + fallthrough; case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) goto acc_err; diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 65bf5fd8d473..4a96b59f0bee 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c @@ -249,7 +249,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) regs->r3 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: do_restart: /* offset of 4 bytes to re-execute trap (brki) instruction */ diff --git a/arch/mips/include/asm/unroll.h b/arch/mips/include/asm/unroll.h index 7dd4a80e05d6..6f4ac854b12d 100644 --- a/arch/mips/include/asm/unroll.h +++ b/arch/mips/include/asm/unroll.h @@ -28,38 +28,38 @@ BUILD_BUG_ON(!__builtin_constant_p(times)); \ \ switch (times) { \ - case 32: fn(__VA_ARGS__); /* fall through */ \ - case 31: fn(__VA_ARGS__); /* fall through */ \ - case 30: fn(__VA_ARGS__); /* fall through */ \ - case 29: fn(__VA_ARGS__); /* fall through */ \ - case 28: fn(__VA_ARGS__); /* fall through */ \ - case 27: fn(__VA_ARGS__); /* fall through */ \ - case 26: fn(__VA_ARGS__); /* fall through */ \ - case 25: fn(__VA_ARGS__); /* fall through */ \ - case 24: fn(__VA_ARGS__); /* fall through */ \ - case 23: fn(__VA_ARGS__); /* fall through */ \ - case 22: fn(__VA_ARGS__); /* fall through */ \ - case 21: fn(__VA_ARGS__); /* fall through */ \ - case 20: fn(__VA_ARGS__); /* fall through */ \ - case 19: fn(__VA_ARGS__); /* fall through */ \ - case 18: fn(__VA_ARGS__); /* fall through */ \ - case 17: fn(__VA_ARGS__); /* fall through */ \ - case 16: fn(__VA_ARGS__); /* fall through */ \ - case 15: fn(__VA_ARGS__); /* fall through */ \ - case 14: fn(__VA_ARGS__); /* fall through */ \ - case 13: fn(__VA_ARGS__); /* fall through */ \ - case 12: fn(__VA_ARGS__); /* fall through */ \ - case 11: fn(__VA_ARGS__); /* fall through */ \ - case 10: fn(__VA_ARGS__); /* fall through */ \ - case 9: fn(__VA_ARGS__); /* fall through */ \ - case 8: fn(__VA_ARGS__); /* fall through */ \ - case 7: fn(__VA_ARGS__); /* fall through */ \ - case 6: fn(__VA_ARGS__); /* fall through */ \ - case 5: fn(__VA_ARGS__); /* fall through */ \ - case 4: fn(__VA_ARGS__); /* fall through */ \ - case 3: fn(__VA_ARGS__); /* fall through */ \ - case 2: fn(__VA_ARGS__); /* fall through */ \ - case 1: fn(__VA_ARGS__); /* fall through */ \ + case 32: fn(__VA_ARGS__); fallthrough; \ + case 31: fn(__VA_ARGS__); fallthrough; \ + case 30: fn(__VA_ARGS__); fallthrough; \ + case 29: fn(__VA_ARGS__); fallthrough; \ + case 28: fn(__VA_ARGS__); fallthrough; \ + case 27: fn(__VA_ARGS__); fallthrough; \ + case 26: fn(__VA_ARGS__); fallthrough; \ + case 25: fn(__VA_ARGS__); fallthrough; \ + case 24: fn(__VA_ARGS__); fallthrough; \ + case 23: fn(__VA_ARGS__); fallthrough; \ + case 22: fn(__VA_ARGS__); fallthrough; \ + case 21: fn(__VA_ARGS__); fallthrough; \ + case 20: fn(__VA_ARGS__); fallthrough; \ + case 19: fn(__VA_ARGS__); fallthrough; \ + case 18: fn(__VA_ARGS__); fallthrough; \ + case 17: fn(__VA_ARGS__); fallthrough; \ + case 16: fn(__VA_ARGS__); fallthrough; \ + case 15: fn(__VA_ARGS__); fallthrough; \ + case 14: fn(__VA_ARGS__); fallthrough; \ + case 13: fn(__VA_ARGS__); fallthrough; \ + case 12: fn(__VA_ARGS__); fallthrough; \ + case 11: fn(__VA_ARGS__); fallthrough; \ + case 10: fn(__VA_ARGS__); fallthrough; \ + case 9: fn(__VA_ARGS__); fallthrough; \ + case 8: fn(__VA_ARGS__); fallthrough; \ + case 7: fn(__VA_ARGS__); fallthrough; \ + case 6: fn(__VA_ARGS__); fallthrough; \ + case 5: fn(__VA_ARGS__); fallthrough; \ + case 4: fn(__VA_ARGS__); fallthrough; \ + case 3: fn(__VA_ARGS__); fallthrough; \ + case 2: fn(__VA_ARGS__); fallthrough; \ + case 1: fn(__VA_ARGS__); fallthrough; \ case 0: break; \ \ default: \ diff --git a/arch/nds32/kernel/fpu.c b/arch/nds32/kernel/fpu.c index 62bdafbc53f4..9edd7ed7d7bf 100644 --- a/arch/nds32/kernel/fpu.c +++ b/arch/nds32/kernel/fpu.c @@ -45,7 +45,7 @@ void save_fpu(struct task_struct *tsk) : /* no output */ : "r" (&tsk->thread.fpu) : "memory"); - /* fall through */ + fallthrough; case SP32_DP16_reg: asm volatile ("fsdi $fd15, [%0+0x78]\n\t" "fsdi $fd14, [%0+0x70]\n\t" @@ -58,7 +58,7 @@ void save_fpu(struct task_struct *tsk) : /* no output */ : "r" (&tsk->thread.fpu) : "memory"); - /* fall through */ + fallthrough; case SP16_DP8_reg: asm volatile ("fsdi $fd7, [%0+0x38]\n\t" "fsdi $fd6, [%0+0x30]\n\t" @@ -67,7 +67,7 @@ void save_fpu(struct task_struct *tsk) : /* no output */ : "r" (&tsk->thread.fpu) : "memory"); - /* fall through */ + fallthrough; case SP8_DP4_reg: asm volatile ("fsdi $fd3, [%1+0x18]\n\t" "fsdi $fd2, [%1+0x10]\n\t" @@ -108,7 +108,7 @@ void load_fpu(const struct fpu_struct *fpregs) "fldi $fd16, [%0+0x80]\n\t" : /* no output */ : "r" (fpregs)); - /* fall through */ + fallthrough; case SP32_DP16_reg: asm volatile ("fldi $fd15, [%0+0x78]\n\t" "fldi $fd14, [%0+0x70]\n\t" @@ -120,7 +120,7 @@ void load_fpu(const struct fpu_struct *fpregs) "fldi $fd8, [%0+0x40]\n\t" : /* no output */ : "r" (fpregs)); - /* fall through */ + fallthrough; case SP16_DP8_reg: asm volatile ("fldi $fd7, [%0+0x38]\n\t" "fldi $fd6, [%0+0x30]\n\t" @@ -128,7 +128,7 @@ void load_fpu(const struct fpu_struct *fpregs) "fldi $fd4, [%0+0x20]\n\t" : /* no output */ : "r" (fpregs)); - /* fall through */ + fallthrough; case SP8_DP4_reg: asm volatile ("fldi $fd3, [%1+0x18]\n\t" "fldi $fd2, [%1+0x10]\n\t" diff --git a/arch/nds32/kernel/signal.c b/arch/nds32/kernel/signal.c index 330b19fcd990..36e25a410bb0 100644 --- a/arch/nds32/kernel/signal.c +++ b/arch/nds32/kernel/signal.c @@ -316,7 +316,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->uregs[0] = -EINTR; break; } - /* Else, fall through */ + fallthrough; case -ERESTARTNOINTR: regs->uregs[0] = regs->orig_r0; regs->ipc -= 4; @@ -361,7 +361,7 @@ static void do_signal(struct pt_regs *regs) switch (regs->uregs[0]) { case -ERESTART_RESTARTBLOCK: regs->uregs[15] = __NR_restart_syscall; - /* Fall through */ + fallthrough; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c index 97804f21a40c..c779364f0cd0 100644 --- a/arch/openrisc/kernel/signal.c +++ b/arch/openrisc/kernel/signal.c @@ -244,7 +244,7 @@ int do_signal(struct pt_regs *regs, int syscall) switch (retval) { case -ERESTART_RESTARTBLOCK: restart = -2; - /* Fall through */ + fallthrough; case -ERESTARTNOHAND: case -ERESTARTSYS: case -ERESTARTNOINTR: diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 5df5d4cd5d4c..3c037fc96038 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c @@ -502,7 +502,7 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) regs->gr[28] = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: check_syscallno_in_delay_branch(regs); break; diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 43875c289723..a52c7abf2ca4 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -437,7 +437,6 @@ void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long o break; default: - /* Fall through */ break; } @@ -644,12 +643,12 @@ void notrace handle_interruption(int code, struct pt_regs *regs) case 15: /* Data TLB miss fault/Data page fault */ - /* Fall through */ + fallthrough; case 16: /* Non-access instruction TLB miss fault */ /* The instruction TLB entry needed for the target address of the FIC is absent, and hardware can't find it, so we get to cleanup */ - /* Fall through */ + fallthrough; case 17: /* Non-access data TLB miss fault/Non-access data page fault */ /* FIXME: @@ -673,7 +672,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) handle_unaligned(regs); return; } - /* Fall Through */ + fallthrough; case 26: /* PCXL: Data memory access rights trap */ fault_address = regs->ior; @@ -683,7 +682,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) case 19: /* Data memory break trap */ regs->gr[0] |= PSW_X; /* So we can single-step over the trap */ - /* fall thru */ + fallthrough; case 21: /* Page reference trap */ handle_gdb_break(regs, TRAP_HWBKPT); @@ -730,7 +729,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs) } mmap_read_unlock(current->mm); } - /* Fall Through */ + fallthrough; case 27: /* Data memory protection ID trap */ if (code == 27 && !user_mode(regs) && diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 4bfe2da9fbe3..716960f5d92e 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -67,7 +67,7 @@ parisc_acctyp(unsigned long code, unsigned int inst) case 0x30000000: /* coproc2 */ if (bit22set(inst)) return VM_WRITE; - /* fall through */ + fallthrough; case 0x0: /* indexed/memory management */ if (bit22set(inst)) { @@ -370,7 +370,7 @@ bad_area: } /* probably address is outside of mapped file */ - /* fall through */ + fallthrough; case 17: /* NA data TLB miss / page fault */ case 18: /* Unaligned access - PCXS only */ signo = SIGBUS; diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 16d09b36fe06..78d61f97371e 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -475,7 +475,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, case BPF_JMP | BPF_JSET | BPF_K: case BPF_JMP | BPF_JSET | BPF_X: true_cond = COND_NE; - /* Fall through */ + fallthrough; cond_branch: /* same targets, can avoid doing the test :) */ if (filter[i].jt == filter[i].jf) { diff --git a/arch/riscv/kernel/signal.c b/arch/riscv/kernel/signal.c index 17ba190e84a5..e996e08f1061 100644 --- a/arch/riscv/kernel/signal.c +++ b/arch/riscv/kernel/signal.c @@ -250,7 +250,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->a0 = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->a0 = regs->orig_a0; regs->epc -= 0x4; diff --git a/arch/riscv/net/bpf_jit_comp32.c b/arch/riscv/net/bpf_jit_comp32.c index bc5f2204693f..579575f9cdae 100644 --- a/arch/riscv/net/bpf_jit_comp32.c +++ b/arch/riscv/net/bpf_jit_comp32.c @@ -1020,7 +1020,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, emit_zext64(dst, ctx); break; } - /* Fallthrough. */ + fallthrough; case BPF_ALU | BPF_ADD | BPF_X: case BPF_ALU | BPF_SUB | BPF_X: @@ -1079,7 +1079,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, case 16: emit(rv_slli(lo(rd), lo(rd), 16), ctx); emit(rv_srli(lo(rd), lo(rd), 16), ctx); - /* Fallthrough. */ + fallthrough; case 32: if (!ctx->prog->aux->verifier_zext) emit(rv_addi(hi(rd), RV_REG_ZERO, 0), ctx); diff --git a/arch/sh/drivers/platform_early.c b/arch/sh/drivers/platform_early.c index f3dc3f25b3ff..143747c45206 100644 --- a/arch/sh/drivers/platform_early.c +++ b/arch/sh/drivers/platform_early.c @@ -246,7 +246,7 @@ static int __init sh_early_platform_driver_probe_id(char *class_str, case EARLY_PLATFORM_ID_ERROR: pr_warn("%s: unable to parse %s parameter\n", class_str, epdrv->pdrv->driver.name); - /* fall-through */ + fallthrough; case EARLY_PLATFORM_ID_UNSET: match = NULL; break; diff --git a/arch/sh/kernel/disassemble.c b/arch/sh/kernel/disassemble.c index 08e1af63edd9..34e25a439c81 100644 --- a/arch/sh/kernel/disassemble.c +++ b/arch/sh/kernel/disassemble.c @@ -486,7 +486,7 @@ static void print_sh_insn(u32 memaddr, u16 insn) pr_cont("xd%d", rn & ~1); break; } - /* else, fall through */ + fallthrough; case D_REG_N: pr_cont("dr%d", rn); break; @@ -495,7 +495,7 @@ static void print_sh_insn(u32 memaddr, u16 insn) pr_cont("xd%d", rm & ~1); break; } - /* else, fall through */ + fallthrough; case D_REG_M: pr_cont("dr%d", rm); break; diff --git a/arch/sh/kernel/kgdb.c b/arch/sh/kernel/kgdb.c index 0d5f3c9d52f3..e4147efa9ec6 100644 --- a/arch/sh/kernel/kgdb.c +++ b/arch/sh/kernel/kgdb.c @@ -266,7 +266,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, ptr = &remcomInBuffer[1]; if (kgdb_hex2long(&ptr, &addr)) linux_regs->pc = addr; - /* fallthrough */ + fallthrough; case 'D': case 'k': atomic_set(&kgdb_cpu_doing_single_step, -1); diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index a0fbb8427b39..4fe3f00137bc 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -418,7 +418,7 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, case -ERESTARTSYS: if (!(sa->sa_flags & SA_RESTART)) goto no_system_call_restart; - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->regs[0] = save_r0; regs->pc -= instruction_size(__raw_readw(regs->pc - 4)); diff --git a/arch/sparc/kernel/auxio_64.c b/arch/sparc/kernel/auxio_64.c index 4843f48bfe85..774a82b0c649 100644 --- a/arch/sparc/kernel/auxio_64.c +++ b/arch/sparc/kernel/auxio_64.c @@ -87,7 +87,6 @@ void auxio_set_lte(int on) __auxio_sbus_set_lte(on); break; case AUXIO_TYPE_EBUS: - /* FALL-THROUGH */ default: break; } diff --git a/arch/sparc/kernel/central.c b/arch/sparc/kernel/central.c index bfae98ab8638..23f8838dd96e 100644 --- a/arch/sparc/kernel/central.c +++ b/arch/sparc/kernel/central.c @@ -55,7 +55,7 @@ static int clock_board_calc_nslots(struct clock_board *p) else return 5; } - /* Fallthrough */ + fallthrough; default: return 4; } diff --git a/arch/sparc/kernel/kgdb_32.c b/arch/sparc/kernel/kgdb_32.c index 7580775a14b9..58ad3f7de1fb 100644 --- a/arch/sparc/kernel/kgdb_32.c +++ b/arch/sparc/kernel/kgdb_32.c @@ -122,7 +122,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, linux_regs->pc = addr; linux_regs->npc = addr + 4; } - /* fall through */ + fallthrough; case 'D': case 'k': diff --git a/arch/sparc/kernel/kgdb_64.c b/arch/sparc/kernel/kgdb_64.c index 5d6c2d287e85..177746ae2c81 100644 --- a/arch/sparc/kernel/kgdb_64.c +++ b/arch/sparc/kernel/kgdb_64.c @@ -148,7 +148,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, linux_regs->tpc = addr; linux_regs->tnpc = addr + 4; } - /* fall through */ + fallthrough; case 'D': case 'k': diff --git a/arch/sparc/kernel/pcr.c b/arch/sparc/kernel/pcr.c index c0886b400dad..2a12c86af956 100644 --- a/arch/sparc/kernel/pcr.c +++ b/arch/sparc/kernel/pcr.c @@ -359,7 +359,7 @@ int __init pcr_arch_init(void) * counter overflow interrupt so we can't make use of * their hardware currently. */ - /* fallthrough */ + fallthrough; default: err = -ENODEV; goto out_unregister; diff --git a/arch/sparc/kernel/prom_32.c b/arch/sparc/kernel/prom_32.c index da8902295c8c..3df960c137f7 100644 --- a/arch/sparc/kernel/prom_32.c +++ b/arch/sparc/kernel/prom_32.c @@ -224,7 +224,7 @@ void __init of_console_init(void) case PROMDEV_TTYB: skip = 1; - /* FALLTHRU */ + fallthrough; case PROMDEV_TTYA: type = "serial"; diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index e2c6f0abda00..e9695a06492f 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -646,7 +646,7 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs case ERESTARTSYS: if (!(sa->sa_flags & SA_RESTART)) goto no_system_call_restart; - /* fallthrough */ + fallthrough; case ERESTARTNOINTR: regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; @@ -686,7 +686,7 @@ void do_signal32(struct pt_regs * regs) regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); - /* fall through */ + fallthrough; case ERESTART_RESTARTBLOCK: regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index f1f8c8ebe641..d0e0025ee3ba 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -440,7 +440,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, case ERESTARTSYS: if (!(sa->sa_flags & SA_RESTART)) goto no_system_call_restart; - /* fallthrough */ + fallthrough; case ERESTARTNOINTR: regs->u_regs[UREG_I0] = orig_i0; regs->pc -= 4; @@ -506,7 +506,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->pc -= 4; regs->npc -= 4; pt_regs_clear_syscall(regs); - /* fall through */ + fallthrough; case ERESTART_RESTARTBLOCK: regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->pc -= 4; diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 6937339a272c..255264bcb46a 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -461,7 +461,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, case ERESTARTSYS: if (!(sa->sa_flags & SA_RESTART)) goto no_system_call_restart; - /* fallthrough */ + fallthrough; case ERESTARTNOINTR: regs->u_regs[UREG_I0] = orig_i0; regs->tpc -= 4; @@ -532,7 +532,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->tpc -= 4; regs->tnpc -= 4; pt_regs_clear_syscall(regs); - /* fall through */ + fallthrough; case ERESTART_RESTARTBLOCK: regs->u_regs[UREG_G1] = __NR_restart_syscall; regs->tpc -= 4; diff --git a/arch/sparc/math-emu/math_32.c b/arch/sparc/math-emu/math_32.c index 72e560ef4a09..d5beec856146 100644 --- a/arch/sparc/math-emu/math_32.c +++ b/arch/sparc/math-emu/math_32.c @@ -359,7 +359,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) *pfsr |= (6 << 14); return 0; /* simulate invalid_fp_register exception */ } - /* fall through */ + fallthrough; case 2: if (freg & 1) { /* doublewords must have bit 5 zeroed */ *pfsr |= (6 << 14); @@ -380,7 +380,7 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) *pfsr |= (6 << 14); return 0; /* simulate invalid_fp_register exception */ } - /* fall through */ + fallthrough; case 2: if (freg & 1) { /* doublewords must have bit 5 zeroed */ *pfsr |= (6 << 14); @@ -408,13 +408,13 @@ static int do_one_mathemu(u32 insn, unsigned long *pfsr, unsigned long *fregs) *pfsr |= (6 << 14); return 0; /* simulate invalid_fp_register exception */ } - /* fall through */ + fallthrough; case 2: if (freg & 1) { /* doublewords must have bit 5 zeroed */ *pfsr |= (6 << 14); return 0; } - /* fall through */ + fallthrough; case 1: rd = (void *)&fregs[freg]; break; diff --git a/arch/sparc/net/bpf_jit_comp_32.c b/arch/sparc/net/bpf_jit_comp_32.c index c8eabb973b86..b1dbf2fa8c0a 100644 --- a/arch/sparc/net/bpf_jit_comp_32.c +++ b/arch/sparc/net/bpf_jit_comp_32.c @@ -491,7 +491,7 @@ void bpf_jit_compile(struct bpf_prog *fp) } else { emit_loadimm(K, r_A); } - /* Fallthrough */ + fallthrough; case BPF_RET | BPF_A: if (seen_or_pass0) { if (i != flen - 1) { diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 3d57c71c532e..88cd9b5c1b74 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c @@ -70,7 +70,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) PT_REGS_SYSCALL_RET(regs) = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: PT_REGS_RESTART_SYSCALL(regs); PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); diff --git a/arch/x86/boot/cmdline.c b/arch/x86/boot/cmdline.c index 4ff01176c1cc..21d56ae83cdf 100644 --- a/arch/x86/boot/cmdline.c +++ b/arch/x86/boot/cmdline.c @@ -54,7 +54,7 @@ int __cmdline_find_option(unsigned long cmdline_ptr, const char *option, char *b /* else */ state = st_wordcmp; opptr = option; - /* fall through */ + fallthrough; case st_wordcmp: if (c == '=' && !*opptr) { @@ -129,7 +129,7 @@ int __cmdline_find_option_bool(unsigned long cmdline_ptr, const char *option) state = st_wordcmp; opptr = option; wstart = pos; - /* fall through */ + fallthrough; case st_wordcmp: if (!*opptr) diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c index 0048269180d5..dde7cb3724df 100644 --- a/arch/x86/boot/compressed/kaslr.c +++ b/arch/x86/boot/compressed/kaslr.c @@ -178,7 +178,7 @@ parse_memmap(char *p, unsigned long long *start, unsigned long long *size, } *size = 0; } - /* Fall through */ + fallthrough; default: /* * If w/o offset, only size specified, memmap=nn[KMG] has the diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 50963472ee85..31e6887d24f1 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4682,7 +4682,7 @@ __init int intel_pmu_init(void) case INTEL_FAM6_CORE2_MEROM: x86_add_quirk(intel_clovertown_quirk); - /* fall through */ + fallthrough; case INTEL_FAM6_CORE2_MEROM_L: case INTEL_FAM6_CORE2_PENRYN: @@ -5062,7 +5062,7 @@ __init int intel_pmu_init(void) case INTEL_FAM6_SKYLAKE_X: pmem = true; - /* fall through */ + fallthrough; case INTEL_FAM6_SKYLAKE_L: case INTEL_FAM6_SKYLAKE: case INTEL_FAM6_KABYLAKE_L: @@ -5114,7 +5114,7 @@ __init int intel_pmu_init(void) case INTEL_FAM6_ICELAKE_X: case INTEL_FAM6_ICELAKE_D: pmem = true; - /* fall through */ + fallthrough; case INTEL_FAM6_ICELAKE_L: case INTEL_FAM6_ICELAKE: case INTEL_FAM6_TIGERLAKE_L: diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index 63f58bdf556c..8961653c5dd2 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1268,7 +1268,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort) ret = X86_BR_ZERO_CALL; break; } - /* fall through */ + fallthrough; case 0x9a: /* call far absolute */ ret = X86_BR_CALL; break; diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index c3daf0aaa0ee..cdaab30880b9 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -239,7 +239,7 @@ void __init arch_init_ideal_nops(void) return; } - /* fall through */ + fallthrough; default: #ifdef CONFIG_X86_64 diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 21325a4a78b9..779a89e31c4c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -800,7 +800,7 @@ static int irq_polarity(int idx) return IOAPIC_POL_HIGH; case MP_IRQPOL_RESERVED: pr_warn("IOAPIC: Invalid polarity: 2, defaulting to low\n"); - /* fall through */ + fallthrough; case MP_IRQPOL_ACTIVE_LOW: default: /* Pointless default required due to do gcc stupidity */ return IOAPIC_POL_LOW; @@ -848,7 +848,7 @@ static int irq_trigger(int idx) return IOAPIC_EDGE; case MP_IRQTRIG_RESERVED: pr_warn("IOAPIC: Invalid trigger mode 2 defaulting to level\n"); - /* fall through */ + fallthrough; case MP_IRQTRIG_LEVEL: default: /* Pointless default required due to do gcc stupidity */ return IOAPIC_LEVEL; diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index 7bda71def557..99ee61c9ba54 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -149,7 +149,7 @@ void __init default_setup_apic_routing(void) break; } /* P4 and above */ - /* fall through */ + fallthrough; case X86_VENDOR_HYGON: case X86_VENDOR_AMD: def_to_bigsmp = 1; diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c index c7503be92f35..57074cf3ad7c 100644 --- a/arch/x86/kernel/cpu/cacheinfo.c +++ b/arch/x86/kernel/cpu/cacheinfo.c @@ -248,7 +248,7 @@ amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, switch (leaf) { case 1: l1 = &l1i; - /* fall through */ + fallthrough; case 0: if (!l1->val) return; diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c index 7843ab3fde09..3a44346f2276 100644 --- a/arch/x86/kernel/cpu/mce/inject.c +++ b/arch/x86/kernel/cpu/mce/inject.c @@ -199,7 +199,7 @@ static int raise_local(void) * calling irq_enter, but the necessary * machinery isn't exported currently. */ - /*FALL THROUGH*/ + fallthrough; case MCJ_CTX_PROCESS: raise_exception(m, NULL); break; diff --git a/arch/x86/kernel/cpu/mce/intel.c b/arch/x86/kernel/cpu/mce/intel.c index d8f9230d2034..abe9fe0fb851 100644 --- a/arch/x86/kernel/cpu/mce/intel.c +++ b/arch/x86/kernel/cpu/mce/intel.c @@ -193,7 +193,7 @@ unsigned long cmci_intel_adjust_timer(unsigned long interval) if (!atomic_sub_return(1, &cmci_storm_on_cpus)) pr_notice("CMCI storm subsided: switching to interrupt mode\n"); - /* FALLTHROUGH */ + fallthrough; case CMCI_STORM_SUBSIDED: /* diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c index 72182809b333..ca670919b561 100644 --- a/arch/x86/kernel/cpu/mtrr/cyrix.c +++ b/arch/x86/kernel/cpu/mtrr/cyrix.c @@ -98,7 +98,7 @@ cyrix_get_free_region(unsigned long base, unsigned long size, int replace_reg) case 7: if (size < 0x40) break; - /* Else, fall through */ + fallthrough; case 6: case 5: case 4: diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 8cdf29ffd95f..b98ff620ba77 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -349,7 +349,7 @@ static int arch_build_bp_info(struct perf_event *bp, hw->len = X86_BREAKPOINT_LEN_X; return 0; } - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c index 68acd30c6b87..c2f02f308ecf 100644 --- a/arch/x86/kernel/kgdb.c +++ b/arch/x86/kernel/kgdb.c @@ -450,7 +450,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code, ptr = &remcomInBuffer[1]; if (kgdb_hex2long(&ptr, &addr)) linux_regs->ip = addr; - /* fall through */ + fallthrough; case 'D': case 'k': /* clear the trace bit */ @@ -539,7 +539,7 @@ static int __kgdb_notify(struct die_args *args, unsigned long cmd) * a system call which should be ignored */ return NOTIFY_DONE; - /* fall through */ + fallthrough; default: if (user_mode(regs)) return NOTIFY_DONE; diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c index 411af4aa7b51..baa21090c9be 100644 --- a/arch/x86/kernel/mpparse.c +++ b/arch/x86/kernel/mpparse.c @@ -312,7 +312,7 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) case 2: if (i == 0 || i == 13) continue; /* IRQ0 & IRQ13 not connected */ - /* fall through */ + fallthrough; default: if (i == 2) continue; /* IRQ2 is never connected */ @@ -356,7 +356,7 @@ static void __init construct_ioapic_table(int mpc_default_type) default: pr_err("???\nUnknown standard configuration %d\n", mpc_default_type); - /* fall through */ + fallthrough; case 1: case 5: memcpy(bus.bustype, "ISA ", 6); diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 5679aa3fdcb8..e7537c5440bb 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -204,7 +204,7 @@ static int set_segment_reg(struct task_struct *task, case offsetof(struct user_regs_struct, ss): if (unlikely(value == 0)) return -EIO; - /* Else, fall through */ + fallthrough; default: *pt_regs_access(task_pt_regs(task), offset) = value; diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 0ec7ced727fe..a515e2d230b7 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -654,7 +654,7 @@ static void native_machine_emergency_restart(void) case BOOT_CF9_FORCE: port_cf9_safe = true; - /* Fall through */ + fallthrough; case BOOT_CF9_SAFE: if (port_cf9_safe) { diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index d5fa494c2304..be0d7d4152ec 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -726,7 +726,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) regs->ax = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->ax = regs->orig_ax; regs->ip -= 2; diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c index 15e5aad8ac2c..3fdaa042823d 100644 --- a/arch/x86/kernel/uprobes.c +++ b/arch/x86/kernel/uprobes.c @@ -735,7 +735,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn) * OPCODE1() of the "short" jmp which checks the same condition. */ opc1 = OPCODE2(insn) - 0x10; - /* fall through */ + fallthrough; default: if (!is_cond_jmp_opcode(opc1)) return -ENOSYS; @@ -892,7 +892,7 @@ int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, fix_ip_or_call = 0; break; } - /* fall through */ + fallthrough; default: riprel_analyze(auprobe, &insn); } diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index d0e2825ae617..5299ef5ff18d 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3016,7 +3016,7 @@ static void string_registers_quirk(struct x86_emulate_ctxt *ctxt) case 0xa4: /* movsb */ case 0xa5: /* movsd/w */ *reg_rmw(ctxt, VCPU_REGS_RSI) &= (u32)-1; - /* fall through */ + fallthrough; case 0xaa: /* stosb */ case 0xab: /* stosd/w */ *reg_rmw(ctxt, VCPU_REGS_RDI) &= (u32)-1; diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 814d3aee5cef..1d330564eed8 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1779,7 +1779,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ret = kvm_hvcall_signal_event(vcpu, fast, ingpa); if (ret != HV_STATUS_INVALID_PORT_ID) break; - /* fall through - maybe userspace knows this conn_id. */ + fallthrough; /* maybe userspace knows this conn_id */ case HVCALL_POST_MESSAGE: /* don't bother userspace if it has no way to handle it */ if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) { diff --git a/arch/x86/kvm/irq_comm.c b/arch/x86/kvm/irq_comm.c index c47d2acec529..4aa1c2e00e2a 100644 --- a/arch/x86/kvm/irq_comm.c +++ b/arch/x86/kvm/irq_comm.c @@ -285,7 +285,7 @@ int kvm_set_routing_entry(struct kvm *kvm, switch (ue->u.irqchip.irqchip) { case KVM_IRQCHIP_PIC_SLAVE: e->irqchip.pin += PIC_NUM_PINS / 2; - /* fall through */ + fallthrough; case KVM_IRQCHIP_PIC_MASTER: if (ue->u.irqchip.pin >= PIC_NUM_PINS / 2) return -EINVAL; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 5ccbee7165a2..35cca2e0c802 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1053,7 +1053,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode, switch (delivery_mode) { case APIC_DM_LOWEST: vcpu->arch.apic_arb_prio++; - /* fall through */ + fallthrough; case APIC_DM_FIXED: if (unlikely(trig_mode && !level)) break; @@ -1341,7 +1341,7 @@ static u32 __apic_read(struct kvm_lapic *apic, unsigned int offset) break; case APIC_TASKPRI: report_tpr_access(apic, false); - /* fall thru */ + fallthrough; default: val = kvm_lapic_get_reg(apic, offset); break; @@ -2027,7 +2027,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val) case APIC_LVT0: apic_manage_nmi_watchdog(apic, val); - /* fall through */ + fallthrough; case APIC_LVTTHMR: case APIC_LVTPC: case APIC_LVT1: diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index a5d0207e7189..43fdb0c12a5d 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -4422,7 +4422,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu, rsvd_bits(maxphyaddr, 51); rsvd_check->rsvd_bits_mask[1][4] = rsvd_check->rsvd_bits_mask[0][4]; - /* fall through */ + fallthrough; case PT64_ROOT_4LEVEL: rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd | nonleaf_bit8_rsvd | rsvd_bits(7, 7) | diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 03dd7bac8034..0194336b64a4 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2668,7 +2668,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) case MSR_IA32_APICBASE: if (kvm_vcpu_apicv_active(vcpu)) avic_update_vapic_bar(to_svm(vcpu), data); - /* Fall through */ + fallthrough; default: return kvm_set_msr_common(vcpu, msr); } diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 46ba2e03a892..819c185adf09 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4654,7 +4654,7 @@ static bool rmode_exception(struct kvm_vcpu *vcpu, int vec) vmcs_read32(VM_EXIT_INSTRUCTION_LEN); if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) return false; - /* fall through */ + fallthrough; case DB_VECTOR: return !(vcpu->guest_debug & (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP)); @@ -4827,7 +4827,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) } kvm_run->debug.arch.dr6 = dr6 | DR6_FIXED_1 | DR6_RTM; kvm_run->debug.arch.dr7 = vmcs_readl(GUEST_DR7); - /* fall through */ + fallthrough; case BP_VECTOR: /* * Update instruction length as we may reinject #BP from @@ -5257,7 +5257,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu) error_code = vmcs_read32(IDT_VECTORING_ERROR_CODE); } - /* fall through */ + fallthrough; case INTR_TYPE_SOFT_EXCEPTION: kvm_clear_exception_queue(vcpu); break; @@ -5610,7 +5610,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu) * keeping track of global entries in shadow page tables. */ - /* fall-through */ + fallthrough; case INVPCID_TYPE_ALL_INCL_GLOBAL: kvm_mmu_unload(vcpu); return kvm_skip_emulated_instruction(vcpu); @@ -6578,7 +6578,7 @@ static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu, break; case INTR_TYPE_SOFT_EXCEPTION: vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field); - /* fall through */ + fallthrough; case INTR_TYPE_HARD_EXCEPTION: if (idt_vectoring_info & VECTORING_INFO_DELIVER_CODE_MASK) { u32 err = vmcs_read32(error_code_field); @@ -6588,7 +6588,7 @@ static void __vmx_complete_interrupts(struct kvm_vcpu *vcpu, break; case INTR_TYPE_SOFT_INTR: vcpu->arch.event_exit_inst_len = vmcs_read32(instr_len_field); - /* fall through */ + fallthrough; case INTR_TYPE_EXT_INTR: kvm_queue_interrupt(vcpu, vector, type == INTR_TYPE_SOFT_INTR); break; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 33945283fe07..d39d6cf1d473 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1116,14 +1116,12 @@ static int __kvm_set_dr(struct kvm_vcpu *vcpu, int dr, unsigned long val) vcpu->arch.eff_db[dr] = val; break; case 4: - /* fall through */ case 6: if (!kvm_dr6_valid(val)) return -1; /* #GP */ vcpu->arch.dr6 = (val & DR6_VOLATILE) | kvm_dr6_fixed(vcpu); break; case 5: - /* fall through */ default: /* 7 */ if (!kvm_dr7_valid(val)) return -1; /* #GP */ @@ -1154,12 +1152,10 @@ int kvm_get_dr(struct kvm_vcpu *vcpu, int dr, unsigned long *val) *val = vcpu->arch.db[array_index_nospec(dr, size)]; break; case 4: - /* fall through */ case 6: *val = vcpu->arch.dr6; break; case 5: - /* fall through */ default: /* 7 */ *val = vcpu->arch.dr7; break; @@ -3051,7 +3047,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3: case MSR_P6_PERFCTR0 ... MSR_P6_PERFCTR1: - pr = true; /* fall through */ + pr = true; + fallthrough; case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3: case MSR_P6_EVNTSEL0 ... MSR_P6_EVNTSEL1: if (kvm_pmu_is_valid_msr(vcpu, msr)) @@ -4359,7 +4356,7 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, case KVM_CAP_HYPERV_SYNIC2: if (cap->args[0]) return -EINVAL; - /* fall through */ + fallthrough; case KVM_CAP_HYPERV_SYNIC: if (!irqchip_in_kernel(vcpu->kvm)) @@ -8672,7 +8669,7 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu) vcpu->arch.pv.pv_unhalted = false; vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; - /* fall through */ + fallthrough; case KVM_MP_STATE_RUNNABLE: vcpu->arch.apf.halted = false; break; diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c index 4f1719e22d3c..b6da09339308 100644 --- a/arch/x86/lib/cmdline.c +++ b/arch/x86/lib/cmdline.c @@ -58,7 +58,7 @@ __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size, state = st_wordcmp; opptr = option; wstart = pos; - /* fall through */ + fallthrough; case st_wordcmp: if (!*opptr) { @@ -89,7 +89,7 @@ __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size, break; } state = st_wordskip; - /* fall through */ + fallthrough; case st_wordskip: if (!c) @@ -151,7 +151,7 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size, state = st_wordcmp; opptr = option; - /* fall through */ + fallthrough; case st_wordcmp: if ((c == '=') && !*opptr) { @@ -172,7 +172,7 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size, break; } state = st_wordskip; - /* fall through */ + fallthrough; case st_wordskip: if (myisspace(c)) diff --git a/arch/x86/lib/insn-eval.c b/arch/x86/lib/insn-eval.c index 31600d851fd8..5e69603ff63f 100644 --- a/arch/x86/lib/insn-eval.c +++ b/arch/x86/lib/insn-eval.c @@ -179,7 +179,7 @@ static int resolve_default_seg(struct insn *insn, struct pt_regs *regs, int off) if (insn->addr_bytes == 2) return -EINVAL; - /* fall through */ + fallthrough; case -EDOM: case offsetof(struct pt_regs, bx): @@ -362,7 +362,6 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx) case INAT_SEG_REG_GS: return vm86regs->gs; case INAT_SEG_REG_IGNORE: - /* fall through */ default: return -EINVAL; } @@ -386,7 +385,6 @@ static short get_segment_selector(struct pt_regs *regs, int seg_reg_idx) */ return get_user_gs(regs); case INAT_SEG_REG_IGNORE: - /* fall through */ default: return -EINVAL; } @@ -786,7 +784,7 @@ int insn_get_code_seg_params(struct pt_regs *regs) */ return INSN_CODE_SEG_PARAMS(4, 8); case 3: /* Invalid setting. CS.L=1, CS.D=1 */ - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/arch/x86/math-emu/errors.c b/arch/x86/math-emu/errors.c index 73dc66d887f3..ec071cbb0804 100644 --- a/arch/x86/math-emu/errors.c +++ b/arch/x86/math-emu/errors.c @@ -186,7 +186,7 @@ void FPU_printall(void) case TAG_Special: /* Update tagi for the printk below */ tagi = FPU_Special(r); - /* fall through */ + fallthrough; case TAG_Valid: printk("st(%d) %c .%04lx %04lx %04lx %04lx e%+-6d ", i, getsign(r) ? '-' : '+', diff --git a/arch/x86/math-emu/fpu_trig.c b/arch/x86/math-emu/fpu_trig.c index 127ea54122d7..4a9887851ad8 100644 --- a/arch/x86/math-emu/fpu_trig.c +++ b/arch/x86/math-emu/fpu_trig.c @@ -1352,7 +1352,7 @@ static void fyl2xp1(FPU_REG *st0_ptr, u_char st0_tag) case TW_Denormal: if (denormal_operand() < 0) return; - /* fall through */ + fallthrough; case TAG_Zero: case TAG_Valid: setsign(st0_ptr, getsign(st0_ptr) ^ getsign(st1_ptr)); diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c index 84d85dbd1dad..9e5ccc56f8e0 100644 --- a/arch/x86/mm/ioremap.c +++ b/arch/x86/mm/ioremap.c @@ -574,7 +574,7 @@ static bool memremap_should_map_decrypted(resource_size_t phys_addr, /* For SEV, these areas are encrypted */ if (sev_active()) break; - /* Fallthrough */ + fallthrough; case E820_TYPE_PRAM: return true; diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 76cee341507b..b3b17d6c50f0 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -448,7 +448,7 @@ static void do_signal(struct pt_regs *regs) regs->areg[2] = -EINTR; break; } - /* fallthrough */ + fallthrough; case -ERESTARTNOINTR: regs->areg[2] = regs->syscall; regs->pc -= 3; diff --git a/block/badblocks.c b/block/badblocks.c index 2e5f5697db35..d39056630d9c 100644 --- a/block/badblocks.c +++ b/block/badblocks.c @@ -525,7 +525,7 @@ ssize_t badblocks_store(struct badblocks *bb, const char *page, size_t len, case 3: if (newline != '\n') return -EINVAL; - /* fall through */ + fallthrough; case 2: if (length <= 0) return -EINVAL; diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index a4c0bec920cb..c34b090178a9 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -4980,7 +4980,7 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic) pr_err("bdi %s: bfq: bad prio class %d\n", bdi_dev_name(bfqq->bfqd->queue->backing_dev_info), ioprio_class); - /* fall through */ + fallthrough; case IOPRIO_CLASS_NONE: /* * No prio set, inherit CPU scheduling settings. @@ -5112,7 +5112,7 @@ static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd, return &bfqg->async_bfqq[0][ioprio]; case IOPRIO_CLASS_NONE: ioprio = IOPRIO_NORM; - /* fall through */ + fallthrough; case IOPRIO_CLASS_BE: return &bfqg->async_bfqq[1][ioprio]; case IOPRIO_CLASS_IDLE: diff --git a/block/blk-wbt.c b/block/blk-wbt.c index 0fa615eefd52..fd410086fe1d 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -528,7 +528,7 @@ static inline bool wbt_should_throttle(struct rq_wb *rwb, struct bio *bio) if ((bio->bi_opf & (REQ_SYNC | REQ_IDLE)) == (REQ_SYNC | REQ_IDLE)) return false; - /* fallthrough */ + fallthrough; case REQ_OP_DISCARD: return true; default: diff --git a/block/ioprio.c b/block/ioprio.c index 77bcab11dce5..04ebd37966f1 100644 --- a/block/ioprio.c +++ b/block/ioprio.c @@ -71,7 +71,7 @@ int ioprio_check_cap(int ioprio) case IOPRIO_CLASS_RT: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - /* fall through */ + fallthrough; /* rt has prio field too */ case IOPRIO_CLASS_BE: if (data >= IOPRIO_BE_NR || data < 0) diff --git a/crypto/drbg.c b/crypto/drbg.c index e99fe34cfa00..3132967a1749 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1521,7 +1521,7 @@ static int drbg_prepare_hrng(struct drbg_state *drbg) case -EALREADY: err = 0; - /* fall through */ + fallthrough; default: drbg->random_ready.func = NULL; diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index ba0b7702f2e9..12e82a61b896 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -2348,121 +2348,121 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) test_hash_speed(alg, sec, generic_hash_speed_template); break; } - /* fall through */ + fallthrough; case 301: test_hash_speed("md4", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 302: test_hash_speed("md5", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 303: test_hash_speed("sha1", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 304: test_hash_speed("sha256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 305: test_hash_speed("sha384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 306: test_hash_speed("sha512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 307: test_hash_speed("wp256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 308: test_hash_speed("wp384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 309: test_hash_speed("wp512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 310: test_hash_speed("tgr128", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 311: test_hash_speed("tgr160", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 312: test_hash_speed("tgr192", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 313: test_hash_speed("sha224", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 314: test_hash_speed("rmd128", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 315: test_hash_speed("rmd160", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 316: test_hash_speed("rmd256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 317: test_hash_speed("rmd320", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 318: test_hash_speed("ghash-generic", sec, hash_speed_template_16); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 319: test_hash_speed("crc32c", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 320: test_hash_speed("crct10dif", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 321: test_hash_speed("poly1305", sec, poly1305_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 322: test_hash_speed("sha3-224", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 323: test_hash_speed("sha3-256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 324: test_hash_speed("sha3-384", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 325: test_hash_speed("sha3-512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 326: test_hash_speed("sm3", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 327: test_hash_speed("streebog256", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 328: test_hash_speed("streebog512", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; - /* fall through */ + fallthrough; case 399: break; @@ -2471,121 +2471,121 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) test_ahash_speed(alg, sec, generic_hash_speed_template); break; } - /* fall through */ + fallthrough; case 401: test_ahash_speed("md4", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 402: test_ahash_speed("md5", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 403: test_ahash_speed("sha1", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 404: test_ahash_speed("sha256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 405: test_ahash_speed("sha384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 406: test_ahash_speed("sha512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 407: test_ahash_speed("wp256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 408: test_ahash_speed("wp384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 409: test_ahash_speed("wp512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 410: test_ahash_speed("tgr128", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 411: test_ahash_speed("tgr160", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 412: test_ahash_speed("tgr192", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 413: test_ahash_speed("sha224", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 414: test_ahash_speed("rmd128", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 415: test_ahash_speed("rmd160", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 416: test_ahash_speed("rmd256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 417: test_ahash_speed("rmd320", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 418: test_ahash_speed("sha3-224", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 419: test_ahash_speed("sha3-256", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 420: test_ahash_speed("sha3-384", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 421: test_ahash_speed("sha3-512", sec, generic_hash_speed_template); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 422: test_mb_ahash_speed("sha1", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 423: test_mb_ahash_speed("sha256", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 424: test_mb_ahash_speed("sha512", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 425: test_mb_ahash_speed("sm3", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 426: test_mb_ahash_speed("streebog256", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 427: test_mb_ahash_speed("streebog512", sec, generic_hash_speed_template, num_mb); if (mode > 400 && mode < 500) break; - /* fall through */ + fallthrough; case 499: break; diff --git a/drivers/accessibility/braille/braille_console.c b/drivers/accessibility/braille/braille_console.c index c2b452af6806..9861302cc7db 100644 --- a/drivers/accessibility/braille/braille_console.c +++ b/drivers/accessibility/braille/braille_console.c @@ -290,7 +290,7 @@ static int vt_notifier_call(struct notifier_block *blk, break; case '\t': c = ' '; - /* Fallthrough */ + fallthrough; default: if (c < 32) /* Ignore other control sequences */ diff --git a/drivers/ata/ahci_brcm.c b/drivers/ata/ahci_brcm.c index 6853dbb4131d..49f7acbfcf01 100644 --- a/drivers/ata/ahci_brcm.c +++ b/drivers/ata/ahci_brcm.c @@ -470,7 +470,7 @@ static int brcm_ahci_probe(struct platform_device *pdev) switch (priv->version) { case BRCM_SATA_BCM7425: hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE; - /* fall through */ + fallthrough; case BRCM_SATA_NSP: hpriv->flags |= AHCI_HFLAG_NO_NCQ; priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE; diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index 129556fcf6be..86261deeb4c5 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -326,7 +326,7 @@ static int ahci_platform_get_phy(struct ahci_host_priv *hpriv, u32 port, node); break; } - /* fall through */ + fallthrough; case -ENODEV: /* continue normally */ hpriv->phys[port] = NULL; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index b1cd4d97bc2a..1a82058defdb 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -190,7 +190,7 @@ struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, case ATA_LITER_PMP_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; - /* fall through */ + fallthrough; case ATA_LITER_HOST_FIRST: return &ap->link; } @@ -201,11 +201,11 @@ struct ata_link *ata_link_next(struct ata_link *link, struct ata_port *ap, case ATA_LITER_HOST_FIRST: if (sata_pmp_attached(ap)) return ap->pmp_link; - /* fall through */ + fallthrough; case ATA_LITER_PMP_FIRST: if (unlikely(ap->slave_link)) return ap->slave_link; - /* fall through */ + fallthrough; case ATA_LITER_EDGE: return NULL; } @@ -523,7 +523,7 @@ int atapi_cmd_type(u8 opcode) case ATA_12: if (atapi_passthru16) return ATAPI_PASS_THRU; - /* fall thru */ + fallthrough; default: return ATAPI_MISC; } @@ -1800,7 +1800,7 @@ retry: switch (class) { case ATA_DEV_SEMB: class = ATA_DEV_ATA; /* some hard drives report SEMB sig */ - /* fall through */ + fallthrough; case ATA_DEV_ATA: case ATA_DEV_ZAC: tf.command = ATA_CMD_ID_ATA; @@ -2907,7 +2907,7 @@ int ata_bus_probe(struct ata_port *ap) case -ENODEV: /* give it just one more chance */ tries[dev->devno] = min(tries[dev->devno], 1); - /* fall through */ + fallthrough; case -EIO: if (tries[dev->devno] == 1) { /* This is the last chance, better to slow @@ -3158,7 +3158,7 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) case ATA_DNXFER_FORCE_PIO0: pio_mask &= 1; - /* fall through */ + fallthrough; case ATA_DNXFER_FORCE_PIO: mwdma_mask = 0; udma_mask = 0; @@ -4694,7 +4694,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) qc->tf.feature != SETFEATURES_RA_ON && qc->tf.feature != SETFEATURES_RA_OFF) break; - /* fall through */ + fallthrough; case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */ case ATA_CMD_SET_MULTI: /* multi_count changed */ /* revalidate device */ diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 474c6c34fe02..d912eaa65c94 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1576,7 +1576,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, case ATA_DEV_ZAC: if (stat & ATA_SENSE) ata_eh_request_sense(qc, qc->scsicmd); - /* fall through */ + fallthrough; case ATA_DEV_ATA: if (err & ATA_ICRC) qc->err_mask |= AC_ERR_ATA_BUS; @@ -3473,11 +3473,11 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) case -ENODEV: /* device missing or wrong IDENTIFY data, schedule probing */ ehc->i.probe_mask |= (1 << dev->devno); - /* fall through */ + fallthrough; case -EINVAL: /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); - /* fall through */ + fallthrough; case -EIO: if (ehc->tries[dev->devno] == 1) { /* This is the last chance, better to slow diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index ec233208585b..4ce4cd32508c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -4162,7 +4162,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b6); break; } - /* Fallthrough */ + fallthrough; default: ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); break; @@ -4198,7 +4198,7 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) * turning this into a no-op. */ case SYNCHRONIZE_CACHE: - /* fall through */ + fallthrough; /* no-op's, complete with success */ case REZERO_UNIT: diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index e01a3a6e4d46..2bc5fc81efe3 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c @@ -157,7 +157,7 @@ static int atp867x_get_active_clocks_shifted(struct ata_port *ap, default: printk(KERN_WARNING "ATP867X: active %dclk is invalid. " "Using 12clk.\n", clk); - /* fall through */ + fallthrough; case 9 ... 12: clocks = 7; /* 12 clk */ break; @@ -190,7 +190,7 @@ static int atp867x_get_recover_clocks_shifted(unsigned int clk) default: printk(KERN_WARNING "ATP867X: recover %dclk is invalid. " "Using default 12clk.\n", clk); - /* fall through */ + fallthrough; case 12: /* default 12 clk */ clocks = 0; break; diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 916bf024d737..7511e11eef4d 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -369,7 +369,7 @@ static int serverworks_fixup(struct pci_dev *pdev) break; case PCI_DEVICE_ID_SERVERWORKS_CSB5IDE: ata_pci_bmdma_clear_simplex(pdev); - /* fall through */ + fallthrough; case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE: case PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2: rc = serverworks_fixup_csb(pdev); diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index d7228f8e9297..664ef658a955 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2010,7 +2010,7 @@ static void mv_rw_multi_errata_sata24(struct ata_queued_cmd *qc) break; case ATA_CMD_WRITE_MULTI_FUA_EXT: tf->flags &= ~ATA_TFLAG_FUA; /* ugh */ - /* fall through */ + fallthrough; case ATA_CMD_WRITE_MULTI_EXT: tf->command = ATA_CMD_PIO_WRITE_EXT; break; @@ -2044,7 +2044,7 @@ static enum ata_completion_errors mv_qc_prep(struct ata_queued_cmd *qc) case ATA_PROT_DMA: if (tf->command == ATA_CMD_DSM) return AC_ERR_OK; - /* fall-thru */ + fallthrough; case ATA_PROT_NCQ: break; /* continue below */ case ATA_PROT_PIO: @@ -2296,7 +2296,7 @@ static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATAPI_PROT_PIO: pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY; - /* fall through */ + fallthrough; case ATAPI_PROT_NODATA: ap->hsm_task_state = HSM_ST_FIRST; break; @@ -2347,7 +2347,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) return AC_ERR_OTHER; break; /* use bmdma for this */ } - /* fall thru */ + fallthrough; case ATA_PROT_NCQ: mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; @@ -2376,7 +2376,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) ": attempting PIO w/multiple DRQ: " "this may fail due to h/w errata\n"); } - /* fall through */ + fallthrough; case ATA_PROT_NODATA: case ATAPI_PROT_PIO: case ATAPI_PROT_NODATA: @@ -3864,7 +3864,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) " and avoid the final two gigabytes on" " all RocketRAID BIOS initialized drives.\n"); } - /* fall through */ + fallthrough; case chip_6042: hpriv->ops = &mv6xxx_ops; hp_flags |= MV_HP_GEN_IIE; diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 8729f78cef5f..7815da8ef9e5 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -637,7 +637,7 @@ static enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc) switch (qc->tf.protocol) { case ATA_PROT_DMA: pdc_fill_sg(qc); - /*FALLTHROUGH*/ + fallthrough; case ATA_PROT_NODATA: i = pdc_pkt_header(&qc->tf, qc->ap->bmdma_prd_dma, qc->dev->devno, pp->pkt); @@ -652,7 +652,7 @@ static enum ata_completion_errors pdc_qc_prep(struct ata_queued_cmd *qc) break; case ATAPI_PROT_DMA: pdc_fill_sg(qc); - /*FALLTHROUGH*/ + fallthrough; case ATAPI_PROT_NODATA: pdc_atapi_pkt(qc); break; @@ -1022,11 +1022,11 @@ static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc) case ATAPI_PROT_NODATA: if (qc->dev->flags & ATA_DFLAG_CDB_INTR) break; - /*FALLTHROUGH*/ + fallthrough; case ATA_PROT_NODATA: if (qc->tf.flags & ATA_TFLAG_POLLING) break; - /*FALLTHROUGH*/ + fallthrough; case ATAPI_PROT_DMA: case ATA_PROT_DMA: pdc_packet_start(qc); diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index 2c7b30c5ea3d..4c01190a5e37 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -669,7 +669,7 @@ static unsigned int pdc20621_qc_issue(struct ata_queued_cmd *qc) case ATA_PROT_NODATA: if (qc->tf.flags & ATA_TFLAG_POLLING) break; - /*FALLTHROUGH*/ + fallthrough; case ATA_PROT_DMA: pdc20621_packet_start(qc); return 0; diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 2ca9ec802734..c798856e74a4 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -711,7 +711,7 @@ static void process_txdone_queue (struct fs_dev *dev, struct queue *q) switch (STATUS_CODE (qe)) { case 0x01: /* This is for AAL0 where we put the chip in streaming mode */ - /* Fall through */ + fallthrough; case 0x02: /* Process a real txdone entry. */ tmp = qe->p0; diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index a81bc49c14ac..9a70bee84125 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -376,33 +376,33 @@ fore200e_shutdown(struct fore200e* fore200e) case FORE200E_STATE_COMPLETE: kfree(fore200e->stats); - /* fall through */ + fallthrough; case FORE200E_STATE_IRQ: free_irq(fore200e->irq, fore200e->atm_dev); - /* fall through */ + fallthrough; case FORE200E_STATE_ALLOC_BUF: fore200e_free_rx_buf(fore200e); - /* fall through */ + fallthrough; case FORE200E_STATE_INIT_BSQ: fore200e_uninit_bs_queue(fore200e); - /* fall through */ + fallthrough; case FORE200E_STATE_INIT_RXQ: fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.status); fore200e_dma_chunk_free(fore200e, &fore200e->host_rxq.rpd); - /* fall through */ + fallthrough; case FORE200E_STATE_INIT_TXQ: fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.status); fore200e_dma_chunk_free(fore200e, &fore200e->host_txq.tpd); - /* fall through */ + fallthrough; case FORE200E_STATE_INIT_CMDQ: fore200e_dma_chunk_free(fore200e, &fore200e->host_cmdq.status); - /* fall through */ + fallthrough; case FORE200E_STATE_INITIALIZE: /* nothing to do for that state */ @@ -415,7 +415,7 @@ fore200e_shutdown(struct fore200e* fore200e) case FORE200E_STATE_MAP: fore200e->bus->unmap(fore200e); - /* fall through */ + fallthrough; case FORE200E_STATE_CONFIGURE: /* nothing to do for that state */ diff --git a/drivers/atm/he.c b/drivers/atm/he.c index 8af793f5e811..17f44abc9418 100644 --- a/drivers/atm/he.c +++ b/drivers/atm/he.c @@ -1944,14 +1944,14 @@ he_tasklet(unsigned long data) switch (type) { case ITYPE_RBRQ_THRESH: HPRINTK("rbrq%d threshold\n", group); - /* fall through */ + fallthrough; case ITYPE_RBRQ_TIMER: if (he_service_rbrq(he_dev, group)) he_service_rbpl(he_dev, group); break; case ITYPE_TBRQ_THRESH: HPRINTK("tbrq%d threshold\n", group); - /* fall through */ + fallthrough; case ITYPE_TPD_COMPLETE: he_service_tbrq(he_dev, group); break; diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index 63871859e6e8..3c081b6171a8 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -192,7 +192,7 @@ static int idt77105_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) switch (cmd) { case IDT77105_GETSTATZ: if (!capable(CAP_NET_ADMIN)) return -EPERM; - /* fall through */ + fallthrough; case IDT77105_GETSTAT: return fetch_stats(dev, arg, cmd == IDT77105_GETSTATZ); case ATM_SETLOOP: diff --git a/drivers/atm/lanai.c b/drivers/atm/lanai.c index 986c1313694c..ac811cfa6843 100644 --- a/drivers/atm/lanai.c +++ b/drivers/atm/lanai.c @@ -2019,7 +2019,7 @@ static int lanai_normalize_ci(struct lanai_dev *lanai, switch (*vpip) { case ATM_VPI_ANY: *vpip = 0; - /* FALLTHROUGH */ + fallthrough; case 0: break; default: diff --git a/drivers/atm/zatm.c b/drivers/atm/zatm.c index ee059c77e3bb..cf5fffcf98a1 100644 --- a/drivers/atm/zatm.c +++ b/drivers/atm/zatm.c @@ -1447,7 +1447,7 @@ static int zatm_ioctl(struct atm_dev *dev,unsigned int cmd,void __user *arg) switch (cmd) { case ZATM_GETPOOLZ: if (!capable(CAP_NET_ADMIN)) return -EPERM; - /* fall through */ + fallthrough; case ZATM_GETPOOL: { struct zatm_pool_info info; diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index 99980aa3644b..1c82d824ae00 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -1365,7 +1365,7 @@ static void panel_process_inputs(void) break; input->rise_timer = 0; input->state = INPUT_ST_RISING; - /* fall through */ + fallthrough; case INPUT_ST_RISING: if ((phys_curr & input->mask) != input->value) { input->state = INPUT_ST_LOW; @@ -1378,11 +1378,11 @@ static void panel_process_inputs(void) } input->high_timer = 0; input->state = INPUT_ST_HIGH; - /* fall through */ + fallthrough; case INPUT_ST_HIGH: if (input_state_high(input)) break; - /* fall through */ + fallthrough; case INPUT_ST_FALLING: input_state_falling(input); } diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c index 5327bfc6ba71..283ca2de76d4 100644 --- a/drivers/base/firmware_loader/fallback.c +++ b/drivers/base/firmware_loader/fallback.c @@ -289,10 +289,10 @@ static ssize_t firmware_loading_store(struct device *dev, } break; } - /* fallthrough */ + fallthrough; default: dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); - /* fallthrough */ + fallthrough; case -1: fw_load_abort(fw_sysfs); break; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 3cf9bc5d8d95..6dba41395155 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -1135,7 +1135,7 @@ noskb: if (buf) break; } bvcpy(skb, f->buf->bio, f->iter, n); - /* fall through */ + fallthrough; case ATA_CMD_PIO_WRITE: case ATA_CMD_PIO_WRITE_EXT: spin_lock_irq(&d->lock); diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 1553d41f0b91..a50e13af0305 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c @@ -1726,7 +1726,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, /* MSch: invalidate default_params */ default_params[drive].blocks = 0; set_capacity(floppy->disk, MAX_DISK_SIZE * 2); - /* Fall through */ + fallthrough; case FDFMTEND: case FDFLUSH: /* invalidate the buffer track to force a reread */ diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index fe6cb99eb917..740e93bad21f 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1733,7 +1733,7 @@ static inline void __drbd_chk_io_error_(struct drbd_device *device, _drbd_set_state(_NS(device, disk, D_INCONSISTENT), CS_HARD, NULL); break; } - /* fall through - for DRBD_META_IO_ERROR or DRBD_FORCE_DETACH */ + fallthrough; /* for DRBD_META_IO_ERROR or DRBD_FORCE_DETACH */ case EP_DETACH: case EP_CALL_HELPER: /* Remember whether we saw a READ or WRITE error. diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index cb687ccdbd96..04b6bde9419d 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -430,7 +430,7 @@ int drbd_thread_start(struct drbd_thread *thi) thi->t_state = RESTARTING; drbd_info(resource, "Restarting %s thread (from %s [%d])\n", thi->name, current->comm, current->pid); - /* fall through */ + fallthrough; case RUNNING: case RESTARTING: default: diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 28eb078f8b75..43c8ae4d9fca 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -3883,7 +3883,7 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, if (nla_put_u32(skb, T_helper_exit_code, sib->helper_exit_code)) goto nla_put_failure; - /* fall through */ + fallthrough; case SIB_HELPER_PRE: if (nla_put_string(skb, T_helper, sib->helper_name)) goto nla_put_failure; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 1d17593f5d2b..422363daa618 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1797,7 +1797,7 @@ static int receive_Barrier(struct drbd_connection *connection, struct packet_inf break; else drbd_warn(connection, "Allocation of an epoch failed, slowing down\n"); - /* Fall through */ + fallthrough; case WO_BDEV_FLUSH: case WO_DRAIN_IO: @@ -2917,7 +2917,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet then we would do something smarter here than reading the block... */ peer_req->flags |= EE_RS_THIN_REQ; - /* fall through */ + fallthrough; case P_RS_DATA_REQUEST: peer_req->w.cb = w_e_end_rsdata_req; fault_type = DRBD_FAULT_RS_RD; @@ -3083,7 +3083,7 @@ static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold rv = 1; break; } - /* Else fall through - to one of the other strategies... */ + fallthrough; /* to one of the other strategies */ case ASB_DISCARD_OLDER_PRI: if (self == 0 && peer == 1) { rv = 1; @@ -3096,7 +3096,7 @@ static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold /* Else fall through to one of the other strategies... */ drbd_warn(device, "Discard younger/older primary did not find a decision\n" "Using discard-least-changes instead\n"); - /* fall through */ + fallthrough; case ASB_DISCARD_ZERO_CHG: if (ch_peer == 0 && ch_self == 0) { rv = test_bit(RESOLVE_CONFLICTS, &peer_device->connection->flags) @@ -3108,7 +3108,7 @@ static int drbd_asb_recover_0p(struct drbd_peer_device *peer_device) __must_hold } if (after_sb_0p == ASB_DISCARD_ZERO_CHG) break; - /* else, fall through */ + fallthrough; case ASB_DISCARD_LEAST_CHG: if (ch_self < ch_peer) rv = -1; @@ -3608,7 +3608,7 @@ static enum drbd_conns drbd_sync_handshake(struct drbd_peer_device *peer_device, switch (rr_conflict) { case ASB_CALL_HELPER: drbd_khelper(device, "pri-lost"); - /* fall through */ + fallthrough; case ASB_DISCONNECT: drbd_err(device, "I shall become SyncTarget, but I am primary!\n"); return C_MASK; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 674be09b2da9..5c975af9c15f 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -611,7 +611,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, drbd_set_out_of_sync(device, req->i.sector, req->i.size); drbd_report_io_error(device, req); __drbd_chk_io_error(device, DRBD_READ_ERROR); - /* fall through. */ + fallthrough; case READ_AHEAD_COMPLETED_WITH_ERROR: /* it is legal to fail read-ahead, no __drbd_chk_io_error in that case. */ mod_rq_state(req, m, RQ_LOCAL_PENDING, RQ_LOCAL_COMPLETED); @@ -836,7 +836,7 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what, } /* else: FIXME can this happen? */ break; } - /* else, fall through - to BARRIER_ACKED */ + fallthrough; /* to BARRIER_ACKED */ case BARRIER_ACKED: /* barrier ack for READ requests does not make sense */ diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 09079aee8dc4..a563b023458a 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -1680,7 +1680,7 @@ static void recal_interrupt(void) clear_bit(FD_DISK_NEWCHANGE_BIT, &drive_state[current_drive].flags); drive_state[current_drive].select_date = jiffies; - /* fall through */ + fallthrough; default: debugt(__func__, "default"); /* Recalibrate moves the head by at @@ -3592,7 +3592,7 @@ static int fd_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned int if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) return -EINTR; process_fd_request(); - /* fall through */ + fallthrough; case FDGETDRVSTAT: outparam = &drive_state[drive]; break; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 2f137d6ce169..33cc6558f9d2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1719,7 +1719,7 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode, case LOOP_SET_BLOCK_SIZE: if (!(mode & FMODE_WRITE) && !capable(CAP_SYS_ADMIN)) return -EPERM; - /* Fall through */ + fallthrough; default: err = lo_simple_ioctl(lo, cmd, arg); break; @@ -1867,7 +1867,7 @@ static int lo_compat_ioctl(struct block_device *bdev, fmode_t mode, case LOOP_SET_STATUS64: case LOOP_CONFIGURE: arg = (unsigned long) compat_ptr(arg); - /* fall through */ + fallthrough; case LOOP_SET_FD: case LOOP_CHANGE_FD: case LOOP_SET_BLOCK_SIZE: diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index c0967507d085..a7af4f27b7c3 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c @@ -440,7 +440,7 @@ static void run_fsm(void) pd_claimed = 1; if (!pi_schedule_claimed(pi_current, run_fsm)) return; - /* fall through */ + fallthrough; case 1: pd_claimed = 2; pi_current->proto->connect(pi_current); @@ -465,7 +465,7 @@ static void run_fsm(void) if (stop) return; } - /* fall through */ + fallthrough; case Hold: schedule_fsm(); return; diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 4becc1efe775..1034e445680c 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -2641,7 +2641,7 @@ static int pkt_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, */ if (pd->refcnt == 1) pkt_lock_door(pd, 0); - /* fall through */ + fallthrough; /* * forward selected CDROM ioctls to CD-ROM, for UDF */ diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index d9c0e7d154f9..011539039693 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -3293,7 +3293,7 @@ again: case __RBD_OBJ_COPYUP_OBJECT_MAPS: if (!pending_result_dec(&obj_req->pending, result)) return false; - /* fall through */ + fallthrough; case RBD_OBJ_COPYUP_OBJECT_MAPS: if (*result) { rbd_warn(rbd_dev, "snap object map update failed: %d", @@ -3312,7 +3312,7 @@ again: case __RBD_OBJ_COPYUP_WRITE_OBJECT: if (!pending_result_dec(&obj_req->pending, result)) return false; - /* fall through */ + fallthrough; case RBD_OBJ_COPYUP_WRITE_OBJECT: return true; default: @@ -3399,7 +3399,7 @@ again: case __RBD_OBJ_WRITE_COPYUP: if (!rbd_obj_advance_copyup(obj_req, result)) return false; - /* fall through */ + fallthrough; case RBD_OBJ_WRITE_COPYUP: if (*result) { rbd_warn(rbd_dev, "copyup failed: %d", *result); @@ -3592,7 +3592,7 @@ again: case __RBD_IMG_OBJECT_REQUESTS: if (!pending_result_dec(&img_req->pending, result)) return false; - /* fall through */ + fallthrough; case RBD_IMG_OBJECT_REQUESTS: return true; default: diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index 7e261224ff10..8799e3bab067 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c @@ -425,7 +425,7 @@ static void card_state_change(struct rsxx_cardinfo *card, * Fall through so the DMA devices can be attached and * the user can attempt to pull off their data. */ - /* fall through */ + fallthrough; case CARD_STATE_GOOD: st = rsxx_get_card_size8(card, &card->size8); if (st) diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 3a476dc1d14f..ae6454c24594 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -1436,7 +1436,7 @@ static void skd_resolve_req_exception(struct skd_device *skdev, blk_mq_requeue_request(req, true); break; } - /* fall through */ + fallthrough; case SKD_CHECK_STATUS_REPORT_ERROR: default: diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index c2f71265af4b..adfc9352351d 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -1260,7 +1260,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, break; case BLKIF_OP_WRITE_BARRIER: drain = true; - /* fall through */ + fallthrough; case BLKIF_OP_FLUSH_DISKCACHE: ring->st_f_req++; operation = REQ_OP_WRITE; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 42944d41aea0..b9aa5d1ac10b 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -843,7 +843,7 @@ static void frontend_changed(struct xenbus_device *dev, xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; - /* fall through */ + fallthrough; /* if not online */ case XenbusStateUnknown: /* implies xen_blkif_disconnect() via xen_blkbk_remove() */ diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 3bb3dd8da9b0..91de2e0755ae 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1403,7 +1403,6 @@ static enum blk_req_status blkif_rsp_to_req_status(int rsp) case BLKIF_RSP_EOPNOTSUPP: return REQ_EOPNOTSUPP; case BLKIF_RSP_ERROR: - /* Fallthrough. */ default: return REQ_ERROR; } @@ -1643,7 +1642,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) info->feature_flush = 0; xlvbd_flush(info); } - /* fall through */ + fallthrough; case BLKIF_OP_READ: case BLKIF_OP_WRITE: if (unlikely(bret->status != BLKIF_RSP_OKAY)) @@ -2484,7 +2483,7 @@ static void blkback_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through */ + fallthrough; case XenbusStateClosing: if (info) blkfront_closing(info); diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index fb5a901fd89e..efb088df1276 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -1849,7 +1849,7 @@ static int sysc_clockdomain_init(struct sysc *ddata) switch (ddata->nr_clocks) { case 2: ick = ddata->clocks[SYSC_ICK]; - /* fallthrough */ + fallthrough; case 1: fck = ddata->clocks[SYSC_FCK]; break; diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 89527bae4602..760d9a931289 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -357,7 +357,7 @@ found: default: break; } - /*FALLTHROUGH*/ + fallthrough; default: bridge->driver = &ali_generic_bridge; } diff --git a/drivers/char/ipmi/kcs_bmc.c b/drivers/char/ipmi/kcs_bmc.c index ed4dc3b1843e..f292e74bd4a5 100644 --- a/drivers/char/ipmi/kcs_bmc.c +++ b/drivers/char/ipmi/kcs_bmc.c @@ -99,7 +99,7 @@ static void kcs_bmc_handle_data(struct kcs_bmc *kcs_bmc) switch (kcs_bmc->phase) { case KCS_PHASE_WRITE_START: kcs_bmc->phase = KCS_PHASE_WRITE_DATA; - /* fall through */ + fallthrough; case KCS_PHASE_WRITE_DATA: if (kcs_bmc->data_in_idx < KCS_MSG_BUFSIZ) { diff --git a/drivers/char/lp.c b/drivers/char/lp.c index bd95aba1f9fe..45932f05fd67 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -734,7 +734,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd, ret = lp_set_timeout32(minor, (void __user *)arg); break; } - /* fall through - for 64-bit */ + fallthrough; /* for 64-bit */ case LPSETTIMEOUT_NEW: ret = lp_set_timeout64(minor, (void __user *)arg); break; @@ -762,7 +762,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, ret = lp_set_timeout32(minor, (void __user *)arg); break; } - /* fall through - for x32 mode */ + fallthrough; /* for x32 mode */ case LPSETTIMEOUT_NEW: ret = lp_set_timeout64(minor, (void __user *)arg); break; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 687d4af6945d..abd4ffdc8cde 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -791,7 +791,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) switch (orig) { case SEEK_CUR: offset += file->f_pos; - /* fall through */ + fallthrough; case SEEK_SET: /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ if ((unsigned long long)offset >= -MAX_ERRNO) { diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 8206412d25ba..e9f694b36871 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -286,7 +286,7 @@ static long nvram_misc_ioctl(struct file *file, unsigned int cmd, #ifdef CONFIG_PPC case OBSOLETE_PMAC_NVRAM_GET_OFFSET: pr_warn("nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); - /* fall through */ + fallthrough; case IOC_NVRAM_GET_OFFSET: ret = -EINVAL; #ifdef CONFIG_PPC_PMAC diff --git a/drivers/clocksource/timer-cadence-ttc.c b/drivers/clocksource/timer-cadence-ttc.c index 38858e141731..80e960602030 100644 --- a/drivers/clocksource/timer-cadence-ttc.c +++ b/drivers/clocksource/timer-cadence-ttc.c @@ -309,7 +309,7 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, /* restore original register value */ writel_relaxed(ttccs->scale_clk_ctrl_reg_old, ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - /* fall through */ + fallthrough; default: return NOTIFY_DONE; } @@ -392,7 +392,7 @@ static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, clockevents_update_freq(&ttcce->ce, ndata->new_rate / PRESCALE); - /* fall through */ + fallthrough; case PRE_RATE_CHANGE: case ABORT_RATE_CHANGE: default: diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index bb61677c11c7..ef0a3216a386 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -129,7 +129,7 @@ static unsigned int cpufreq_p4_get_frequency(struct cpuinfo_x86 *c) return speedstep_get_frequency(SPEEDSTEP_CPU_PCORE); case 0x0D: /* Pentium M (Dothan) */ p4clockmod_driver.flags |= CPUFREQ_CONST_LOOPS; - /* fall through */ + fallthrough; case 0x09: /* Pentium M (Banias) */ return speedstep_get_frequency(SPEEDSTEP_CPU_PM); } diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index 5c4f8f07c5a6..a13a2d1e444e 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -366,7 +366,7 @@ enum speedstep_processor speedstep_detect_processor(void) } else return SPEEDSTEP_CPU_PIII_C; } - /* fall through */ + fallthrough; default: return 0; } diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index ab0de27539ad..8f9fdd864391 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -86,11 +86,11 @@ static unsigned long dra7_efuse_xlate(struct ti_cpufreq_data *opp_data, case DRA76_EFUSE_HAS_PLUS_MPU_OPP: case DRA76_EFUSE_HAS_ALL_MPU_OPP: calculated_efuse |= DRA76_EFUSE_PLUS_MPU_OPP; - /* Fall through */ + fallthrough; case DRA7_EFUSE_HAS_ALL_MPU_OPP: case DRA7_EFUSE_HAS_HIGH_MPU_OPP: calculated_efuse |= DRA7_EFUSE_HIGH_MPU_OPP; - /* Fall through */ + fallthrough; case DRA7_EFUSE_HAS_OD_MPU_OPP: calculated_efuse |= DRA7_EFUSE_OD_MPU_OPP; } diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index 1a46eeddf082..809c3033ca74 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c @@ -2310,7 +2310,7 @@ static int artpec6_crypto_prepare_submit_hash(struct ahash_request *req) case ARTPEC6_CRYPTO_PREPARE_HASH_NO_START: ret = 0; - /* Fallthrough */ + fallthrough; default: artpec6_crypto_common_destroy(&req_ctx->common); diff --git a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c index dc5fda522719..4fe7898c8561 100644 --- a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c +++ b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c @@ -90,11 +90,11 @@ static int setup_sgio_components(struct cpt_vf *cptvf, struct buf_ptr *list, case 3: sg_ptr->u.s.len2 = cpu_to_be16(list[i * 4 + 2].size); sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr); - /* Fall through */ + fallthrough; case 2: sg_ptr->u.s.len1 = cpu_to_be16(list[i * 4 + 1].size); sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr); - /* Fall through */ + fallthrough; case 1: sg_ptr->u.s.len0 = cpu_to_be16(list[i * 4 + 0].size); sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr); diff --git a/drivers/crypto/chelsio/chcr_ktls.c b/drivers/crypto/chelsio/chcr_ktls.c index 91dee616d15e..c5cce024886a 100644 --- a/drivers/crypto/chelsio/chcr_ktls.c +++ b/drivers/crypto/chelsio/chcr_ktls.c @@ -135,7 +135,7 @@ static int chcr_ktls_update_connection_state(struct chcr_ktls_info *tx_info, break; /* update to the next state and also initialize TCB */ tx_info->connection_state = new_state; - /* FALLTHRU */ + fallthrough; case KTLS_CONN_ACT_OPEN_RPL: /* if we are stuck in this state, means tcb init might not * received by HW, try sending it again. @@ -150,7 +150,7 @@ static int chcr_ktls_update_connection_state(struct chcr_ktls_info *tx_info, break; /* update to the next state and check if l2t_state is valid */ tx_info->connection_state = new_state; - /* FALLTHRU */ + fallthrough; case KTLS_CONN_SET_TCB_RPL: /* Check if l2t state is valid, then move to ready state. */ if (cxgb4_check_l2t_valid(tx_info->l2te)) { diff --git a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c index cbc3d7869ebe..c80baf1ad90b 100644 --- a/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c +++ b/drivers/crypto/marvell/octeontx/otx_cptvf_reqmgr.c @@ -140,11 +140,11 @@ static inline int setup_sgio_components(struct pci_dev *pdev, case 3: sg_ptr->u.s.len2 = cpu_to_be16(list[i * 4 + 2].size); sg_ptr->ptr2 = cpu_to_be64(list[i * 4 + 2].dma_addr); - /* Fall through */ + fallthrough; case 2: sg_ptr->u.s.len1 = cpu_to_be16(list[i * 4 + 1].size); sg_ptr->ptr1 = cpu_to_be64(list[i * 4 + 1].dma_addr); - /* Fall through */ + fallthrough; case 1: sg_ptr->u.s.len0 = cpu_to_be16(list[i * 4 + 0].size); sg_ptr->ptr0 = cpu_to_be64(list[i * 4 + 0].dma_addr); diff --git a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c index 519fd5acf713..8b090b7ae8c6 100644 --- a/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c +++ b/drivers/crypto/qat/qat_common/adf_pf2vf_msg.c @@ -340,7 +340,7 @@ static int adf_vf2pf_request_version(struct adf_accel_dev *accel_dev) /* VF is newer than PF and decides whether it is compatible */ if (accel_dev->vf.pf_version >= hw_data->min_iov_compat_ver) break; - /* fall through */ + fallthrough; case ADF_PF2VF_VF_INCOMPATIBLE: dev_err(&GET_DEV(accel_dev), "PF (vers %d) and VF (vers %d) are not compatible\n", diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c index bff759e2f811..00c615f9f9a8 100644 --- a/drivers/crypto/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/qat/qat_common/qat_uclo.c @@ -752,7 +752,7 @@ static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle, case ICP_GPA_ABS: case ICP_GPB_ABS: ctx_mask = 0; - /* fall through */ + fallthrough; case ICP_GPA_REL: case ICP_GPB_REL: return qat_hal_init_gpr(handle, ae, ctx_mask, reg_type, @@ -762,7 +762,7 @@ static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle, case ICP_SR_RD_ABS: case ICP_DR_RD_ABS: ctx_mask = 0; - /* fall through */ + fallthrough; case ICP_SR_REL: case ICP_DR_REL: case ICP_SR_RD_REL: @@ -772,7 +772,7 @@ static int qat_uclo_init_reg(struct icp_qat_fw_loader_handle *handle, case ICP_SR_WR_ABS: case ICP_DR_WR_ABS: ctx_mask = 0; - /* fall through */ + fallthrough; case ICP_SR_WR_REL: case ICP_DR_WR_REL: return qat_hal_init_wr_xfer(handle, ae, ctx_mask, reg_type, diff --git a/drivers/crypto/ux500/cryp/cryp.c b/drivers/crypto/ux500/cryp/cryp.c index f22f6fa612b3..9866c2a5e9a7 100644 --- a/drivers/crypto/ux500/cryp/cryp.c +++ b/drivers/crypto/ux500/cryp/cryp.c @@ -314,17 +314,17 @@ void cryp_save_device_context(struct cryp_device_data *device_data, case CRYP_KEY_SIZE_256: ctx->key_4_l = readl_relaxed(&src_reg->key_4_l); ctx->key_4_r = readl_relaxed(&src_reg->key_4_r); - /* Fall through */ + fallthrough; case CRYP_KEY_SIZE_192: ctx->key_3_l = readl_relaxed(&src_reg->key_3_l); ctx->key_3_r = readl_relaxed(&src_reg->key_3_r); - /* Fall through */ + fallthrough; case CRYP_KEY_SIZE_128: ctx->key_2_l = readl_relaxed(&src_reg->key_2_l); ctx->key_2_r = readl_relaxed(&src_reg->key_2_r); - /* Fall through */ + fallthrough; default: ctx->key_1_l = readl_relaxed(&src_reg->key_1_l); @@ -364,17 +364,17 @@ void cryp_restore_device_context(struct cryp_device_data *device_data, case CRYP_KEY_SIZE_256: writel_relaxed(ctx->key_4_l, ®->key_4_l); writel_relaxed(ctx->key_4_r, ®->key_4_r); - /* Fall through */ + fallthrough; case CRYP_KEY_SIZE_192: writel_relaxed(ctx->key_3_l, ®->key_3_l); writel_relaxed(ctx->key_3_r, ®->key_3_r); - /* Fall through */ + fallthrough; case CRYP_KEY_SIZE_128: writel_relaxed(ctx->key_2_l, ®->key_2_l); writel_relaxed(ctx->key_2_r, ®->key_2_r); - /* Fall through */ + fallthrough; default: writel_relaxed(ctx->key_1_l, ®->key_1_l); diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 9adc7a2fa3d3..a24882ba3764 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -1767,7 +1767,7 @@ static u32 pl08x_memcpy_cctl(struct pl08x_driver_data *pl08x) default: dev_err(&pl08x->adev->dev, "illegal burst size for memcpy, set to 1\n"); - /* Fall through */ + fallthrough; case PL08X_BURST_SZ_1: cctl |= PL080_BSIZE_1 << PL080_CONTROL_SB_SIZE_SHIFT | PL080_BSIZE_1 << PL080_CONTROL_DB_SIZE_SHIFT; @@ -1806,7 +1806,7 @@ static u32 pl08x_memcpy_cctl(struct pl08x_driver_data *pl08x) default: dev_err(&pl08x->adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); - /* Fall through */ + fallthrough; case PL08X_BUS_WIDTH_8_BITS: cctl |= PL080_WIDTH_8BIT << PL080_CONTROL_SWIDTH_SHIFT | PL080_WIDTH_8BIT << PL080_CONTROL_DWIDTH_SHIFT; @@ -1850,7 +1850,7 @@ static u32 pl08x_ftdmac020_memcpy_cctl(struct pl08x_driver_data *pl08x) default: dev_err(&pl08x->adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); - /* Fall through */ + fallthrough; case PL08X_BUS_WIDTH_8_BITS: cctl |= PL080_WIDTH_8BIT << FTDMAC020_LLI_SRC_WIDTH_SHIFT | PL080_WIDTH_8BIT << FTDMAC020_LLI_DST_WIDTH_SHIFT; @@ -2612,7 +2612,7 @@ static int pl08x_of_probe(struct amba_device *adev, switch (val) { default: dev_err(&adev->dev, "illegal burst size for memcpy, set to 1\n"); - /* Fall through */ + fallthrough; case 1: pd->memcpy_burst_size = PL08X_BURST_SZ_1; break; @@ -2647,7 +2647,7 @@ static int pl08x_of_probe(struct amba_device *adev, switch (val) { default: dev_err(&adev->dev, "illegal bus width for memcpy, set to 8 bits\n"); - /* Fall through */ + fallthrough; case 8: pd->memcpy_bus_width = PL08X_BUS_WIDTH_8_BITS; break; diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index ad72b3f42ffa..e342cf52d296 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1163,7 +1163,7 @@ static int fsl_dma_chan_probe(struct fsldma_device *fdev, switch (chan->feature & FSL_DMA_IP_MASK) { case FSL_DMA_IP_85XX: chan->toggle_ext_pause = fsl_chan_toggle_ext_pause; - /* Fall through */ + fallthrough; case FSL_DMA_IP_83XX: chan->toggle_ext_start = fsl_chan_toggle_ext_start; chan->set_src_loop_size = fsl_chan_set_src_loop_size; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 5c0fb3134825..88717506c1f6 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -556,7 +556,7 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) * We fall-through here intentionally, since a 2D transfer is * similar to MEMCPY just adding the 2D slot configuration. */ - /* Fall through */ + fallthrough; case IMXDMA_DESC_MEMCPY: imx_dmav1_writel(imxdma, d->src, DMA_SAR(imxdmac->channel)); imx_dmav1_writel(imxdma, d->dest, DMA_DAR(imxdmac->channel)); diff --git a/drivers/dma/iop-adma.h b/drivers/dma/iop-adma.h index c499c9578f00..d44eabb6f5eb 100644 --- a/drivers/dma/iop-adma.h +++ b/drivers/dma/iop-adma.h @@ -496,7 +496,7 @@ iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, } hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = edcr; src_cnt = 24; - /* fall through */ + fallthrough; case 17 ... 24: if (!u_desc_ctrl.field.blk_ctrl) { hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0; @@ -510,7 +510,7 @@ iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, } hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = edcr; src_cnt = 16; - /* fall through */ + fallthrough; case 9 ... 16: if (!u_desc_ctrl.field.blk_ctrl) u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */ @@ -522,7 +522,7 @@ iop3xx_desc_init_xor(struct iop3xx_desc_aau *hw_desc, int src_cnt, } hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = edcr; src_cnt = 8; - /* fall through */ + fallthrough; case 2 ... 8: shift = 1; for (i = 0; i < src_cnt; i++) { @@ -602,19 +602,19 @@ iop_desc_init_null_xor(struct iop_adma_desc_slot *desc, int src_cnt, case 25 ... 32: u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */ hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0; - /* fall through */ + fallthrough; case 17 ... 24: if (!u_desc_ctrl.field.blk_ctrl) { hw_desc->src_edc[AAU_EDCR2_IDX].e_desc_ctrl = 0; u_desc_ctrl.field.blk_ctrl = 0x3; /* use EDCR[2:0] */ } hw_desc->src_edc[AAU_EDCR1_IDX].e_desc_ctrl = 0; - /* fall through */ + fallthrough; case 9 ... 16: if (!u_desc_ctrl.field.blk_ctrl) u_desc_ctrl.field.blk_ctrl = 0x2; /* use EDCR0 */ hw_desc->src_edc[AAU_EDCR0_IDX].e_desc_ctrl = 0; - /* fall through */ + fallthrough; case 1 ... 8: if (!u_desc_ctrl.field.blk_ctrl && src_cnt > 4) u_desc_ctrl.field.blk_ctrl = 0x1; /* use mini-desc */ diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index 74df621402e1..ca4e0930207a 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -483,7 +483,7 @@ static size_t nbpf_xfer_size(struct nbpf_device *nbpf, default: pr_warn("%s(): invalid bus width %u\n", __func__, width); - /* fall through */ + fallthrough; case DMA_SLAVE_BUSWIDTH_1_BYTE: size = burst; } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 2c508ee672b9..9b69716172a4 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1061,16 +1061,16 @@ static bool _start(struct pl330_thread *thrd) if (_state(thrd) == PL330_STATE_KILLING) UNTIL(thrd, PL330_STATE_STOPPED) - /* fall through */ + fallthrough; case PL330_STATE_FAULTING: _stop(thrd); - /* fall through */ + fallthrough; case PL330_STATE_KILLING: case PL330_STATE_COMPLETING: UNTIL(thrd, PL330_STATE_STOPPED) - /* fall through */ + fallthrough; case PL330_STATE_STOPPED: return _trigger(thrd); @@ -1121,7 +1121,6 @@ static u32 _emit_load(unsigned int dry_run, u8 buf[], switch (direction) { case DMA_MEM_TO_MEM: - /* fall through */ case DMA_MEM_TO_DEV: off += _emit_LD(dry_run, &buf[off], cond); break; @@ -1155,7 +1154,6 @@ static inline u32 _emit_store(unsigned int dry_run, u8 buf[], switch (direction) { case DMA_MEM_TO_MEM: - /* fall through */ case DMA_DEV_TO_MEM: off += _emit_ST(dry_run, &buf[off], cond); break; @@ -1216,7 +1214,6 @@ static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[], switch (pxs->desc->rqtype) { case DMA_MEM_TO_DEV: - /* fall through */ case DMA_DEV_TO_MEM: off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, cyc, cond); @@ -1266,7 +1263,6 @@ static int _dregs(struct pl330_dmac *pl330, unsigned int dry_run, u8 buf[], switch (pxs->desc->rqtype) { case DMA_MEM_TO_DEV: - /* fall through */ case DMA_DEV_TO_MEM: off += _emit_MOV(dry_run, &buf[off], CCR, dregs_ccr); off += _ldst_peripheral(pl330, dry_run, &buf[off], pxs, 1, diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 2deeaab078a4..788d696323bb 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c @@ -383,7 +383,7 @@ static dma_async_tx_callback __ld_cleanup(struct shdma_chan *schan, bool all) switch (desc->mark) { case DESC_COMPLETED: desc->mark = DESC_WAITING; - /* Fall through */ + fallthrough; case DESC_WAITING: if (head_acked) async_tx_ack(&desc->async_tx); diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 6262f6370c5d..fcc08bbf6945 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3375,7 +3375,7 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) pvt->ops = &family_types[F17_M70H_CPUS].ops; break; } - /* fall through */ + fallthrough; case 0x18: fam_type = &family_types[F17_CPUS]; pvt->ops = &family_types[F17_CPUS].ops; diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index b8fc4b84fd86..928f63a374c7 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -198,7 +198,7 @@ static int apl_rd_reg(int port, int off, int op, void *data, size_t sz, char *na switch (sz) { case 8: ret = _apl_rd_reg(port, off + 4, op, (u32 *)(data + 4)); - /* fall through */ + fallthrough; case 4: ret |= _apl_rd_reg(port, off, op, (u32 *)data); pnd2_printk(KERN_DEBUG, "%s=%x%08x ret=%d\n", name, diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index b785e936244f..80db43a22069 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -957,7 +957,7 @@ static void set_broadcast_channel(struct fw_device *device, int generation) device->bc_implemented = BC_IMPLEMENTED; break; } - /* else, fall through - to case address error */ + fallthrough; /* to case address error */ case RCODE_ADDRESS_ERROR: device->bc_implemented = BC_UNIMPLEMENTED; } diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c index 185b0b78b3d6..af70e74f9a7e 100644 --- a/drivers/firewire/core-iso.c +++ b/drivers/firewire/core-iso.c @@ -277,7 +277,7 @@ static int manage_channel(struct fw_card *card, int irm_id, int generation, if ((data[0] & bit) == (data[1] & bit)) continue; - /* fall through - It's a 1394-1995 IRM, retry. */ + fallthrough; /* It's a 1394-1995 IRM, retry */ default: if (retry) { retry--; diff --git a/drivers/firewire/core-topology.c b/drivers/firewire/core-topology.c index 94a13fca8267..ec68ed27b0a5 100644 --- a/drivers/firewire/core-topology.c +++ b/drivers/firewire/core-topology.c @@ -54,7 +54,7 @@ static u32 *count_ports(u32 *sid, int *total_port_count, int *child_port_count) switch (port_type) { case SELFID_PORT_CHILD: (*child_port_count)++; - /* fall through */ + fallthrough; case SELFID_PORT_PARENT: case SELFID_PORT_NCONN: (*total_port_count)++; diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 439d918bbaaf..ac487c96bb71 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c @@ -1097,14 +1097,14 @@ static void handle_registers(struct fw_card *card, struct fw_request *request, rcode = RCODE_ADDRESS_ERROR; break; } - /* else fall through */ + fallthrough; case CSR_NODE_IDS: /* * per IEEE 1394-2008 8.3.22.3, not IEEE 1394.1-2004 3.2.8 * and 9.6, but interoperable with IEEE 1394.1-2004 bridges */ - /* fall through */ + fallthrough; case CSR_STATE_CLEAR: case CSR_STATE_SET: diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 7dde21b18b04..020cb15a4d8f 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1495,7 +1495,7 @@ static int handle_at_packet(struct context *context, packet->ack = RCODE_GENERATION; break; } - /* fall through */ + fallthrough; default: packet->ack = RCODE_SEND_ERROR; @@ -3054,7 +3054,7 @@ static int ohci_start_iso(struct fw_iso_context *base, case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL: control |= IR_CONTEXT_BUFFER_FILL|IR_CONTEXT_MULTI_CHANNEL_MODE; - /* fall through */ + fallthrough; case FW_ISO_CONTEXT_RECEIVE: index = ctx - ohci->ir_context_list; match = (tags << 28) | (sync << 8) | ctx->base.channel; diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c index d16645c1d8d9..3aa45934d60c 100644 --- a/drivers/gpio/gpio-aspeed-sgpio.c +++ b/drivers/gpio/gpio-aspeed-sgpio.c @@ -303,16 +303,16 @@ static int aspeed_sgpio_set_type(struct irq_data *d, unsigned int type) switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: type2 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_EDGE_RISING: type0 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_EDGE_FALLING: handler = handle_edge_irq; break; case IRQ_TYPE_LEVEL_HIGH: type0 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_LEVEL_LOW: type1 |= bit; handler = handle_level_irq; diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 879db23d8454..bf08b4561f36 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -611,16 +611,16 @@ static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type) switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_BOTH: type2 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_EDGE_RISING: type0 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_EDGE_FALLING: handler = handle_edge_irq; break; case IRQ_TYPE_LEVEL_HIGH: type0 |= bit; - /* fall through */ + fallthrough; case IRQ_TYPE_LEVEL_LOW: type1 |= bit; handler = handle_level_irq; diff --git a/drivers/gpio/gpio-ath79.c b/drivers/gpio/gpio-ath79.c index 53fae02c40ad..d5359341cc6b 100644 --- a/drivers/gpio/gpio-ath79.c +++ b/drivers/gpio/gpio-ath79.c @@ -129,7 +129,7 @@ static int ath79_gpio_irq_set_type(struct irq_data *data, case IRQ_TYPE_LEVEL_HIGH: polarity |= mask; - /* fall through */ + fallthrough; case IRQ_TYPE_LEVEL_LOW: type |= mask; break; diff --git a/drivers/gpio/gpio-eic-sprd.c b/drivers/gpio/gpio-eic-sprd.c index 8c9757774010..ad61daf6c212 100644 --- a/drivers/gpio/gpio-eic-sprd.c +++ b/drivers/gpio/gpio-eic-sprd.c @@ -617,14 +617,12 @@ static int sprd_eic_probe(struct platform_device *pdev) sprd_eic->chip.free = sprd_eic_free; sprd_eic->chip.set_config = sprd_eic_set_config; sprd_eic->chip.set = sprd_eic_set; - /* fall-through */ + fallthrough; case SPRD_EIC_ASYNC: - /* fall-through */ case SPRD_EIC_SYNC: sprd_eic->chip.get = sprd_eic_get; break; case SPRD_EIC_LATCH: - /* fall-through */ default: break; } diff --git a/drivers/gpio/gpio-stmpe.c b/drivers/gpio/gpio-stmpe.c index 6c48809d0505..b0155d6007c8 100644 --- a/drivers/gpio/gpio-stmpe.c +++ b/drivers/gpio/gpio-stmpe.c @@ -308,7 +308,7 @@ static void stmpe_dbg_show_one(struct seq_file *s, if (ret < 0) return; edge_det = !!(ret & mask); - /* fall through */ + fallthrough; case STMPE1801: rise_reg = stmpe->regs[STMPE_IDX_GPRER_LSB + bank]; fall_reg = stmpe->regs[STMPE_IDX_GPFER_LSB + bank]; @@ -321,7 +321,7 @@ static void stmpe_dbg_show_one(struct seq_file *s, if (ret < 0) return; fall = !!(ret & mask); - /* fall through */ + fallthrough; case STMPE801: case STMPE1600: irqen_reg = stmpe->regs[STMPE_IDX_IEGPIOR_LSB + bank]; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 9276051663da..54ca3c18b291 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -1264,7 +1264,7 @@ static int acpi_gpio_package_count(const union acpi_object *obj) switch (element->type) { case ACPI_TYPE_LOCAL_REFERENCE: element += 3; - /* Fallthrough */ + fallthrough; case ACPI_TYPE_INTEGER: element++; count++; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index 7e59e473a190..cdea1338c8dc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -152,7 +152,7 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev, dev_warn(adev->dev, "Invalid sdma engine id (%d), using engine id 0\n", engine_id); - /* fall through */ + fallthrough; case 0: sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 33f1c4a46ebe..88f63d7ea371 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -3250,7 +3250,7 @@ static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev) dev_warn(adev->dev, "Unknown chip type (%d) in function gfx_v8_0_tiling_mode_table_init() falling through to CHIP_CARRIZO\n", adev->asic_type); - /* fall through */ + fallthrough; case CHIP_CARRIZO: modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6e4f3ff4810f..b67ba38a195f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1297,7 +1297,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) case CHIP_VEGA10: if (amdgpu_sriov_vf(adev)) break; - /* fall through */ + fallthrough; case CHIP_VEGA20: soc15_program_register_sequence(adev, golden_settings_mmhub_1_0_0, diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index ea914b256ebd..b5986d19dc08 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -6196,7 +6196,7 @@ static void si_request_link_speed_change_before_state_change(struct amdgpu_devic si_pi->force_pcie_gen = AMDGPU_PCIE_GEN2; if (current_link_speed == AMDGPU_PCIE_GEN2) break; - /* fall through */ + fallthrough; case AMDGPU_PCIE_GEN2: if (amdgpu_acpi_pcie_performance_request(adev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) break; diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index ca570b135478..e9de542f9b7c 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -532,7 +532,7 @@ static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); - /* fall through */ + fallthrough; case 1: malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); @@ -869,7 +869,7 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); - /* fall through */ + fallthrough; case 1: malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); @@ -1324,7 +1324,7 @@ static irqreturn_t malidp_se_irq(int irq, void *arg) break; case MW_RESTART: drm_writeback_signal_completion(&malidp->mw_connector, 0); - /* fall through - to a new start */ + fallthrough; /* to a new start */ case MW_START: /* writeback started, need to emulate one-shot mode */ hw->disable_memwrite(hwdev); diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index dd12b55d57a2..6a9fba051d13 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -238,7 +238,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ast->dp501_fw_addr = NULL; } } - /* fallthrough */ + fallthrough; case 0x0c: ast->tx_chip_type = AST_TX_DP501; } diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index ce94f797d090..66b67402f1ac 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -409,7 +409,6 @@ static bool nwl_dsi_read_packet(struct nwl_dsi *dsi, u32 status) switch (data_type) { case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: - fallthrough; case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: if (xfer->msg->rx_len > 1) { /* read second byte */ @@ -418,7 +417,6 @@ static bool nwl_dsi_read_packet(struct nwl_dsi *dsi, u32 status) } fallthrough; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: - fallthrough; case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: if (xfer->msg->rx_len > 0) { /* read first byte */ diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index d7e65c869415..9fef6413741d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -61,10 +61,10 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, switch (hparms->channels) { case 7 ... 8: conf0 |= HDMI_AUD_CONF0_I2S_EN3; - /* Fall-thru */ + fallthrough; case 5 ... 6: conf0 |= HDMI_AUD_CONF0_I2S_EN2; - /* Fall-thru */ + fallthrough; case 3 ... 4: conf0 |= HDMI_AUD_CONF0_I2S_EN1; /* Fall-thru */ diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 86b9f0f87a14..5b6e19ecbc84 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -604,13 +604,13 @@ static void ti_sn_bridge_read_valid_rates(struct ti_sn_bridge *pdata, DRM_DEV_ERROR(pdata->dev, "Unexpected max rate (%#x); assuming 5.4 GHz\n", (int)dpcd_val); - /* fall through */ + fallthrough; case DP_LINK_BW_5_4: rate_valid[7] = 1; - /* fall through */ + fallthrough; case DP_LINK_BW_2_7: rate_valid[4] = 1; - /* fall through */ + fallthrough; case DP_LINK_BW_1_62: rate_valid[1] = 1; break; diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index a0735fbc144b..7a01d0918861 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -537,7 +537,7 @@ int drm_legacy_rmmap_locked(struct drm_device *dev, struct drm_local_map *map) switch (map->type) { case _DRM_REGISTERS: iounmap(map->handle); - /* FALLTHROUGH */ + fallthrough; case _DRM_FRAME_BUFFER: arch_phys_wc_del(map->mtrr); break; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index a3c82e726057..092c8c985911 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -492,7 +492,7 @@ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], case DP_DS_16BPC: return 16; } - /* fall through */ + fallthrough; default: return 0; } diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 14b6f7638728..501b4fe55a3d 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1930,7 +1930,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, default: WARN(1, "Invalid aspect ratio (0%x) on mode\n", in->picture_aspect_ratio); - /* fall through */ + fallthrough; case HDMI_PICTURE_ASPECT_NONE: out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; break; diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 7a6f6df5e954..b38e9b592b8a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -987,10 +987,10 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi *dsi, switch (length) { case 3: reg |= payload[2] << 16; - /* Fall through */ + fallthrough; case 2: reg |= payload[1] << 8; - /* Fall through */ + fallthrough; case 1: reg |= payload[0]; exynos_dsi_write(dsi, DSIM_PAYLOAD_REG, reg); @@ -1038,7 +1038,7 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, payload[1] = reg >> 16; ++xfer->rx_done; } - /* Fall through */ + fallthrough; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: payload[0] = reg >> 8; @@ -1082,10 +1082,10 @@ static void exynos_dsi_read_from_fifo(struct exynos_dsi *dsi, switch (length) { case 3: payload[2] = (reg >> 16) & 0xff; - /* Fall through */ + fallthrough; case 2: payload[1] = (reg >> 8) & 0xff; - /* Fall through */ + fallthrough; case 1: payload[0] = reg & 0xff; } diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 86fac677fe69..3c6d9f3913d5 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -101,19 +101,19 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane, break; case DRM_FORMAT_ARGB8888: alpha = DCU_LAYER_AB_WHOLE_FRAME; - /* fall-through */ + fallthrough; case DRM_FORMAT_XRGB8888: bpp = FSL_DCU_ARGB8888; break; case DRM_FORMAT_ARGB4444: alpha = DCU_LAYER_AB_WHOLE_FRAME; - /* fall-through */ + fallthrough; case DRM_FORMAT_XRGB4444: bpp = FSL_DCU_ARGB4444; break; case DRM_FORMAT_ARGB1555: alpha = DCU_LAYER_AB_WHOLE_FRAME; - /* fall-through */ + fallthrough; case DRM_FORMAT_XRGB1555: bpp = FSL_DCU_ARGB1555; break; diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 8c55f5bee9ab..f4053dd6bde9 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -712,7 +712,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, switch (intel_dsi->pixel_format) { default: MISSING_CASE(intel_dsi->pixel_format); - /* fallthrough */ + fallthrough; case MIPI_DSI_FMT_RGB565: tmp |= PIX_FMT_RGB565; break; @@ -739,7 +739,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, switch (intel_dsi->video_mode_format) { default: MISSING_CASE(intel_dsi->video_mode_format); - /* fallthrough */ + fallthrough; case VIDEO_MODE_NON_BURST_WITH_SYNC_EVENTS: tmp |= VIDEO_MODE_SYNC_EVENT; break; @@ -792,7 +792,7 @@ gen11_dsi_configure_transcoder(struct intel_encoder *encoder, switch (pipe) { default: MISSING_CASE(pipe); - /* fallthrough */ + fallthrough; case PIPE_A: tmp |= TRANS_DDI_EDP_INPUT_A_ON; break; diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index c53c85d38fa5..a0a41ec5c341 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -905,7 +905,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) drm_dbg_kms(&dev_priv->drm, "VBT tp1 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n", psr_table->tp1_wakeup_time); - /* fallthrough */ + fallthrough; case 2: dev_priv->vbt.psr.tp1_wakeup_time_us = 2500; break; @@ -925,7 +925,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) drm_dbg_kms(&dev_priv->drm, "VBT tp2_tp3 wakeup time value %d is outside range[0-3], defaulting to max value 2500us\n", psr_table->tp2_tp3_wakeup_time); - /* fallthrough */ + fallthrough; case 2: dev_priv->vbt.psr.tp2_tp3_wakeup_time_us = 2500; break; @@ -1775,7 +1775,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, switch (child->hdmi_max_data_rate) { default: MISSING_CASE(child->hdmi_max_data_rate); - /* fall through */ + fallthrough; case HDMI_MAX_DATA_RATE_PLATFORM: max_tmds_clock = 0; break; diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index bb91dace304a..91a8161e7c05 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -326,7 +326,7 @@ static void pnv_get_cdclk(struct drm_i915_private *dev_priv, default: drm_err(&dev_priv->drm, "Unknown pnv display core clock 0x%04x\n", gcfgc); - /* fall through */ + fallthrough; case GC_DISPLAY_CLOCK_133_MHZ_PNV: cdclk_config->cdclk = 133333; break; @@ -766,7 +766,7 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, switch (cdclk) { default: MISSING_CASE(cdclk); - /* fall through */ + fallthrough; case 337500: val |= LCPLL_CLK_FREQ_337_5_BDW; break; @@ -1042,7 +1042,7 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, drm_WARN_ON(&dev_priv->drm, cdclk != dev_priv->cdclk.hw.bypass); drm_WARN_ON(&dev_priv->drm, vco != 0); - /* fall through */ + fallthrough; case 308571: case 337500: freq_select = CDCLK_FREQ_337_308; @@ -1333,7 +1333,7 @@ static void icl_readout_refclk(struct drm_i915_private *dev_priv, switch (dssm) { default: MISSING_CASE(dssm); - /* fall through */ + fallthrough; case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz: cdclk_config->ref = 24000; break; @@ -1561,7 +1561,7 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, drm_WARN_ON(&dev_priv->drm, cdclk != dev_priv->cdclk.hw.bypass); drm_WARN_ON(&dev_priv->drm, vco != 0); - /* fall through */ + fallthrough; case 2: divider = BXT_CDCLK_CD2X_DIV_SEL_1; break; diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index eccaa79cb4a9..6968de4f3477 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -52,7 +52,7 @@ cnl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy) switch (val & (PROCESS_INFO_MASK | VOLTAGE_INFO_MASK)) { default: MISSING_CASE(val); - /* fall through */ + fallthrough; case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0: procmon = &cnl_procmon_values[PROCMON_0_85V_DOT_0]; break; @@ -320,7 +320,7 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, break; default: MISSING_CASE(lane_count); - /* fall-through */ + fallthrough; case 4: lane_mask = PWR_UP_ALL_LANES; break; @@ -337,7 +337,7 @@ void intel_combo_phy_power_up_lanes(struct drm_i915_private *dev_priv, break; default: MISSING_CASE(lane_count); - /* fall-through */ + fallthrough; case 4: lane_mask = PWR_UP_ALL_LANES; break; diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 2c484b55bcdf..a49ff3a1a63c 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -1888,7 +1888,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder, switch (tmp & TRANS_DDI_EDP_INPUT_MASK) { default: MISSING_CASE(tmp & TRANS_DDI_EDP_INPUT_MASK); - /* fallthrough */ + fallthrough; case TRANS_DDI_EDP_INPUT_A_ON: case TRANS_DDI_EDP_INPUT_A_ONOFF: *pipe_mask = BIT(PIPE_A); @@ -4268,7 +4268,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder, pipe_config->hdmi_scrambling = true; if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE) pipe_config->hdmi_high_tmds_clock_ratio = true; - /* fall through */ + fallthrough; case TRANS_DDI_MODE_SELECT_DVI: pipe_config->output_types |= BIT(INTEL_OUTPUT_HDMI); pipe_config->lane_count = 4; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b2ec3a5141cc..68325678f5ef 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2029,12 +2029,12 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) case I915_FORMAT_MOD_Y_TILED_CCS: if (is_ccs_plane(fb, color_plane)) return 128; - /* fall through */ + fallthrough; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: if (is_ccs_plane(fb, color_plane)) return 64; - /* fall through */ + fallthrough; case I915_FORMAT_MOD_Y_TILED: if (IS_GEN(dev_priv, 2) || HAS_128_BYTE_Y_TILING(dev_priv)) return 128; @@ -2043,7 +2043,7 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) case I915_FORMAT_MOD_Yf_TILED_CCS: if (is_ccs_plane(fb, color_plane)) return 128; - /* fall through */ + fallthrough; case I915_FORMAT_MOD_Yf_TILED: switch (cpp) { case 1: @@ -2185,7 +2185,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: if (is_semiplanar_uv_plane(fb, color_plane)) return intel_tile_row_size(fb, color_plane); - /* Fall-through */ + fallthrough; case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: return 16 * 1024; case I915_FORMAT_MOD_Y_TILED_CCS: @@ -2194,7 +2194,7 @@ static unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, if (INTEL_GEN(dev_priv) >= 12 && is_semiplanar_uv_plane(fb, color_plane)) return intel_tile_row_size(fb, color_plane); - /* Fall-through */ + fallthrough; case I915_FORMAT_MOD_Yf_TILED: return 1 * 1024 * 1024; default: @@ -6211,7 +6211,7 @@ static int skl_update_scaler_plane(struct intel_crtc_state *crtc_state, case DRM_FORMAT_ARGB16161616F: if (INTEL_GEN(dev_priv) >= 11) break; - /* fall through */ + fallthrough; default: drm_dbg_kms(&dev_priv->drm, "[PLANE:%d:%s] FB:%d unsupported scaling format 0x%x\n", @@ -10896,7 +10896,7 @@ static void hsw_get_ddi_pll(struct drm_i915_private *dev_priv, enum port port, break; default: MISSING_CASE(ddi_pll_sel); - /* fall through */ + fallthrough; case PORT_CLK_SEL_NONE: return; } @@ -10956,10 +10956,10 @@ static bool hsw_get_transcoder_state(struct intel_crtc *crtc, drm_WARN(dev, 1, "unknown pipe linked to transcoder %s\n", transcoder_name(panel_transcoder)); - /* fall through */ + fallthrough; case TRANS_DDI_EDP_INPUT_A_ONOFF: force_thru = true; - /* fall through */ + fallthrough; case TRANS_DDI_EDP_INPUT_A_ON: trans_pipe = PIPE_A; break; @@ -13183,7 +13183,7 @@ static bool check_digital_port_conflicts(struct intel_atomic_state *state) case INTEL_OUTPUT_DDI: if (drm_WARN_ON(dev, !HAS_DDI(to_i915(dev)))) break; - /* else, fall through */ + fallthrough; case INTEL_OUTPUT_DP: case INTEL_OUTPUT_HDMI: case INTEL_OUTPUT_EDP: diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index aeb6ee395cce..afa7a378b31d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -892,7 +892,7 @@ static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, refclk = dev_priv->dpll.ref_clks.nssc; break; } - /* fall through */ + fallthrough; case WRPLL_REF_PCH_SSC: /* * We could calculate spread here, but our checking @@ -2977,7 +2977,7 @@ static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, switch (dev_priv->dpll.ref_clks.nssc) { default: MISSING_CASE(dev_priv->dpll.ref_clks.nssc); - /* fall-through */ + fallthrough; case 19200: *pll_params = tgl_tbt_pll_19_2MHz_values; break; @@ -2992,7 +2992,7 @@ static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, switch (dev_priv->dpll.ref_clks.nssc) { default: MISSING_CASE(dev_priv->dpll.ref_clks.nssc); - /* fall-through */ + fallthrough; case 19200: case 38400: *pll_params = icl_tbt_pll_19_2MHz_values; @@ -3120,7 +3120,7 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, switch (div1) { default: MISSING_CASE(div1); - /* fall through */ + fallthrough; case 2: hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2; break; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index bbde3b12c311..4072d7062efd 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -229,7 +229,7 @@ int intel_pch_panel_fitting(struct intel_crtc_state *crtc_state, case DRM_MODE_SCALE_NONE: WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w); WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h); - /* fall through */ + fallthrough; case DRM_MODE_SCALE_FULLSCREEN: x = y = 0; width = adjusted_mode->crtc_hdisplay; diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 2da4388e1540..5e9fb349c829 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -1531,7 +1531,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state, default: drm_WARN(&dev_priv->drm, 1, "unknown pixel multiplier specified\n"); - /* fall through */ + fallthrough; case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break; case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break; case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break; @@ -2549,19 +2549,19 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo) switch (sdvo->controlled_output) { case SDVO_OUTPUT_LVDS1: mask |= SDVO_OUTPUT_LVDS1; - /* fall through */ + fallthrough; case SDVO_OUTPUT_LVDS0: mask |= SDVO_OUTPUT_LVDS0; - /* fall through */ + fallthrough; case SDVO_OUTPUT_TMDS1: mask |= SDVO_OUTPUT_TMDS1; - /* fall through */ + fallthrough; case SDVO_OUTPUT_TMDS0: mask |= SDVO_OUTPUT_TMDS0; - /* fall through */ + fallthrough; case SDVO_OUTPUT_RGB1: mask |= SDVO_OUTPUT_RGB1; - /* fall through */ + fallthrough; case SDVO_OUTPUT_RGB0: mask |= SDVO_OUTPUT_RGB0; break; diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index d03860fef2d7..c89f5f7ccb06 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -2147,7 +2147,7 @@ static int skl_plane_check_fb(const struct intel_crtc_state *crtc_state, case DRM_FORMAT_RGB565: if (INTEL_GEN(dev_priv) >= 11) break; - /* fall through */ + fallthrough; case DRM_FORMAT_C8: case DRM_FORMAT_XRGB16161616F: case DRM_FORMAT_XBGR16161616F: @@ -2702,7 +2702,7 @@ static bool g4x_sprite_format_mod_supported(struct drm_plane *_plane, if (modifier == DRM_FORMAT_MOD_LINEAR || modifier == I915_FORMAT_MOD_X_TILED) return true; - /* fall through */ + fallthrough; default: return false; } @@ -2733,7 +2733,7 @@ static bool snb_sprite_format_mod_supported(struct drm_plane *_plane, if (modifier == DRM_FORMAT_MOD_LINEAR || modifier == I915_FORMAT_MOD_X_TILED) return true; - /* fall through */ + fallthrough; default: return false; } @@ -2768,7 +2768,7 @@ static bool vlv_sprite_format_mod_supported(struct drm_plane *_plane, if (modifier == DRM_FORMAT_MOD_LINEAR || modifier == I915_FORMAT_MOD_X_TILED) return true; - /* fall through */ + fallthrough; default: return false; } @@ -2801,7 +2801,7 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_ABGR8888: if (is_ccs_modifier(modifier)) return true; - /* fall through */ + fallthrough; case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: @@ -2819,7 +2819,7 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_XVYU2101010: if (modifier == I915_FORMAT_MOD_Yf_TILED) return true; - /* fall through */ + fallthrough; case DRM_FORMAT_C8: case DRM_FORMAT_XBGR16161616F: case DRM_FORMAT_ABGR16161616F: @@ -2834,7 +2834,7 @@ static bool skl_plane_format_mod_supported(struct drm_plane *_plane, modifier == I915_FORMAT_MOD_X_TILED || modifier == I915_FORMAT_MOD_Y_TILED) return true; - /* fall through */ + fallthrough; default: return false; } @@ -2860,7 +2860,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS: if (!gen12_plane_supports_mc_ccs(dev_priv, plane->id)) return false; - /* fall through */ + fallthrough; case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: @@ -2877,7 +2877,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_ABGR8888: if (is_ccs_modifier(modifier)) return true; - /* fall through */ + fallthrough; case DRM_FORMAT_YUYV: case DRM_FORMAT_YVYU: case DRM_FORMAT_UYVY: @@ -2889,7 +2889,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_P016: if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) return true; - /* fall through */ + fallthrough; case DRM_FORMAT_RGB565: case DRM_FORMAT_XRGB2101010: case DRM_FORMAT_XBGR2101010: @@ -2910,7 +2910,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, modifier == I915_FORMAT_MOD_X_TILED || modifier == I915_FORMAT_MOD_Y_TILED) return true; - /* fall through */ + fallthrough; default: return false; } diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c index 5b5dc86a5737..8f67aef18b2d 100644 --- a/drivers/gpu/drm/i915/display/intel_tc.c +++ b/drivers/gpu/drm/i915/display/intel_tc.c @@ -159,7 +159,7 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port) switch (lane_mask) { default: MISSING_CASE(lane_mask); - /* fall-through */ + fallthrough; case 0x1: case 0x2: case 0x4: diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index b23368529a40..753f82d87a31 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -209,7 +209,7 @@ static vm_fault_t i915_error_to_vmf_fault(int err) switch (err) { default: WARN_ONCE(err, "unhandled error in %s: %i\n", __func__, err); - /* fallthrough */ + fallthrough; case -EIO: /* shmemfs failure from swap device */ case -EFAULT: /* purged object */ case -ENODEV: /* bad object, how did you get here! */ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index 7050519c87a4..d15ff6748a50 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -276,7 +276,7 @@ static void *i915_gem_object_map(struct drm_i915_gem_object *obj, switch (type) { default: MISSING_CASE(type); - /* fallthrough - to use PAGE_KERNEL anyway */ + fallthrough; /* to use PAGE_KERNEL anyway */ case I915_MAP_WB: pgprot = PAGE_KERNEL; break; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index e0f21f12d3ce..0be5e8683337 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -249,7 +249,7 @@ static void vlv_get_stolen_reserved(struct drm_i915_private *i915, switch (reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK) { default: MISSING_CASE(reg_val & GEN7_STOLEN_RESERVED_SIZE_MASK); - /* fall through */ + fallthrough; case GEN7_STOLEN_RESERVED_1M: *size = 1024 * 1024; break; @@ -416,7 +416,7 @@ static int i915_gem_init_stolen(struct drm_i915_private *i915) case 4: if (!IS_G4X(i915)) break; - /* fall through */ + fallthrough; case 5: g4x_get_stolen_reserved(i915, uncore, &reserved_base, &reserved_size); @@ -445,7 +445,7 @@ static int i915_gem_init_stolen(struct drm_i915_private *i915) break; default: MISSING_CASE(INTEL_GEN(i915)); - /* fall-through */ + fallthrough; case 11: case 12: icl_get_stolen_reserved(i915, uncore, diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index dd1a42c4d344..26087dd79782 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -213,7 +213,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class) break; default: MISSING_CASE(class); - /* fall through */ + fallthrough; case VIDEO_DECODE_CLASS: case VIDEO_ENHANCEMENT_CLASS: case COPY_ENGINE_CLASS: diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 62979ea591f0..99e28d9021e8 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -1437,7 +1437,7 @@ i915_get_ggtt_vma_pages(struct i915_vma *vma) switch (vma->ggtt_view.type) { default: GEM_BUG_ON(vma->ggtt_view.type); - /* fall through */ + fallthrough; case I915_GGTT_VIEW_NORMAL: vma->pages = vma->obj->mm.pages; return 0; diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 94915f668715..898593ca4889 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -100,7 +100,7 @@ static void set_hwsp(struct intel_engine_cs *engine, u32 offset) */ default: GEM_BUG_ON(engine->id); - /* fallthrough */ + fallthrough; case RCS0: hwsp = RENDER_HWS_PGA_GEN7; break; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 63bba7b4bb2f..05f3bc98d242 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1226,7 +1226,7 @@ static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) switch (notification) { case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE: root_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY; - /* fall through */ + fallthrough; case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE: mm = intel_vgpu_get_ppgtt_mm(vgpu, root_entry_type, pdps); return PTR_ERR_OR_ZERO(mm); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 6a3a2ce0b394..3e6cbb0d1150 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -1159,7 +1159,7 @@ static void engine_record_registers(struct intel_engine_coredump *ee) switch (engine->id) { default: MISSING_CASE(engine->id); - /* fall through */ + fallthrough; case RCS0: mmio = RENDER_HWS_PGA_GEN7; break; diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 056994224c6b..69c0fa20eba1 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c @@ -474,7 +474,7 @@ config_status(struct drm_i915_private *i915, u64 config) if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) /* Requires a mutex for sampling! */ return -ENODEV; - /* Fall-through. */ + fallthrough; case I915_PMU_REQUESTED_FREQUENCY: if (INTEL_GEN(i915) < 6) return -ENODEV; diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 6776ebb3246d..8a4235d9d9f1 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -447,7 +447,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane, if (fb->pitches[1] != fb->pitches[2]) return -EINVAL; - /* fall-through */ + fallthrough; case DRM_FORMAT_NV12: case DRM_FORMAT_NV16: ubo = drm_plane_state_to_ubo(state); diff --git a/drivers/gpu/drm/meson/meson_osd_afbcd.c b/drivers/gpu/drm/meson/meson_osd_afbcd.c index f12e0271f166..ffc6b584dbf8 100644 --- a/drivers/gpu/drm/meson/meson_osd_afbcd.c +++ b/drivers/gpu/drm/meson/meson_osd_afbcd.c @@ -205,7 +205,7 @@ static int meson_g12a_afbcd_pixel_fmt(u64 modifier, uint32_t format) /* YTR is forbidden for non XBGR formats */ if (modifier & AFBC_FORMAT_MOD_YTR) return -EINVAL; - /* fall through */ + fallthrough; case DRM_FORMAT_XBGR8888: case DRM_FORMAT_ABGR8888: return MAFBC_FMT_RGBA8888; diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index a8bcc70644df..1ffbbecafa22 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -654,7 +654,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_addr2, priv->viu.vd1_stride2, priv->viu.vd1_height2); - /* fallthrough */ + fallthrough; case 2: gem = drm_fb_cma_get_gem_obj(fb, 1); priv->viu.vd1_addr1 = gem->paddr + fb->offsets[1]; @@ -666,7 +666,7 @@ static void meson_overlay_atomic_update(struct drm_plane *plane, priv->viu.vd1_addr1, priv->viu.vd1_stride1, priv->viu.vd1_height1); - /* fallthrough */ + fallthrough; case 1: gem = drm_fb_cma_get_gem_obj(fb, 0); priv->viu.vd1_addr0 = gem->paddr + fb->offsets[0]; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 9e63a190642c..84a5d9c1f2a2 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -59,7 +59,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: if (priv->lastctx == ctx) break; - /* fall-thru */ + fallthrough; case MSM_SUBMIT_CMD_BUF: /* copy commands into RB: */ obj = submit->bos[submit->cmd[i].idx].obj; @@ -150,7 +150,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: if (priv->lastctx == ctx) break; - /* fall-thru */ + fallthrough; case MSM_SUBMIT_CMD_BUF: OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index b67b38c8fadf..4c9bda19cbc4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -602,7 +602,7 @@ static void a6xx_gmu_power_config(struct a6xx_gmu *gmu) gmu_rmw(gmu, REG_A6XX_GMU_PWR_COL_INTER_FRAME_CTRL, 0, A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_IFPC_ENABLE | A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_HM_POWER_COLLAPSE_ENABLE); - /* Fall through */ + fallthrough; case GMU_IDLE_STATE_SPTP: gmu_write(gmu, REG_A6XX_GMU_PWR_COL_SPTPRAC_HYST, GMU_PWR_COL_HYST); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index c5a3e4d4c007..3966abd523cc 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -117,7 +117,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: if (priv->lastctx == ctx) break; - /* fall-thru */ + fallthrough; case MSM_SUBMIT_CMD_BUF: OUT_PKT7(ring, CP_INDIRECT_BUFFER_PFE, 3); OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index e23641a5ec84..bb0b09790157 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -474,7 +474,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, /* ignore if there has not been a ctx switch: */ if (priv->lastctx == ctx) break; - /* fall-thru */ + fallthrough; case MSM_SUBMIT_CMD_BUF: OUT_PKT3(ring, adreno_is_a4xx(adreno_gpu) ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2); diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index e0817934ee16..bd12eae0cb31 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -597,7 +597,7 @@ static void venc_bridge_mode_set(struct drm_bridge *bridge, switch (venc_mode) { default: WARN_ON_ONCE(1); - /* Fall-through */ + fallthrough; case VENC_MODE_PAL: venc->config = &venc_config_pal_trm; break; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index ba20c6f03719..886e9959496f 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4856,7 +4856,7 @@ static void ci_request_link_speed_change_before_state_change(struct radeon_devic pi->force_pcie_gen = RADEON_PCIE_GEN2; if (current_link_speed == RADEON_PCIE_GEN2) break; - /* fall through */ + fallthrough; case RADEON_PCIE_GEN2: if (radeon_acpi_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) break; diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 3b7ead5be5bf..73f67bf222e1 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -820,7 +820,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ((idx_value >> 21) & 0xF)); return -EINVAL; } - /* Fall through. */ + fallthrough; case 6: track->cb[i].cpp = 4; break; @@ -971,7 +971,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, return -EINVAL; } /* The same rules apply as for DXT3/5. */ - /* Fall through. */ + fallthrough; case R300_TX_FORMAT_DXT3: case R300_TX_FORMAT_DXT5: track->textures[i].cpp = 1; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 1d4c04e0a449..50b89b6d9a6c 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -115,7 +115,7 @@ void r420_pipes_init(struct radeon_device *rdev) default: /* force to 1 pipe */ num_pipes = 1; - /* fall through */ + fallthrough; case 1: tmp = (0 << 1); break; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 49e8266461f8..390a9621604a 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -487,7 +487,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i) return -EINVAL; } } - /* fall through */ + fallthrough; case V_0280A0_CLEAR_ENABLE: { uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]); @@ -1535,7 +1535,7 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p, u32 idx, break; case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA: is_array = true; - /* fall through */ + fallthrough; case V_038000_SQ_TEX_DIM_2D_MSAA: array_check.nsamples = 1 << llevel; llevel = 0; diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 1ad5c3b86b64..57fb3eb3a4b4 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -454,7 +454,7 @@ static int radeon_uvd_validate_codec(struct radeon_cs_parser *p, if (p->rdev->family >= CHIP_PALM) return 0; - /* fall through */ + fallthrough; default: DRM_ERROR("UVD codec not supported by hardware %d!\n", stream_type); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index a167e1c36d24..d1c73e9db889 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -5744,7 +5744,7 @@ static void si_request_link_speed_change_before_state_change(struct radeon_devic si_pi->force_pcie_gen = RADEON_PCIE_GEN2; if (current_link_speed == RADEON_PCIE_GEN2) break; - /* fall through */ + fallthrough; case RADEON_PCIE_GEN2: if (radeon_acpi_pcie_performance_request(rdev, PCIE_PERF_REQ_PECI_GEN2, false) == 0) break; diff --git a/drivers/gpu/drm/radeon/uvd_v1_0.c b/drivers/gpu/drm/radeon/uvd_v1_0.c index f858d8d06347..800721153d51 100644 --- a/drivers/gpu/drm/radeon/uvd_v1_0.c +++ b/drivers/gpu/drm/radeon/uvd_v1_0.c @@ -219,7 +219,7 @@ done: WREG32(RS_DQ_RD_RET_CONF, 0x3f); WREG32(MC_CONFIG, 0x1f); - /* fall through */ + fallthrough; case CHIP_RV670: case CHIP_RV635: diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c index a2ac25c11c90..e0d40ae67d54 100644 --- a/drivers/gpu/drm/savage/savage_state.c +++ b/drivers/gpu/drm/savage/savage_state.c @@ -306,7 +306,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; - /* fall through */ + fallthrough; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", @@ -444,7 +444,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; - /* fall through */ + fallthrough; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", @@ -566,7 +566,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; - /* fall through */ + fallthrough; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); @@ -705,7 +705,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST_201: reorder = 1; prim = SAVAGE_PRIM_TRILIST; - /* fall through */ + fallthrough; case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); @@ -1066,7 +1066,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ ret = -EINVAL; goto done; } - /* fall through */ + fallthrough; case SAVAGE_CMD_DMA_PRIM: case SAVAGE_CMD_VB_PRIM: if (!first_draw_cmd) diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 008f07923bbc..38a558768e53 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -850,13 +850,13 @@ static int hdmi_audio_configure(struct sti_hdmi *hdmi) switch (info->channels) { case 8: audio_cfg |= HDMI_AUD_CFG_CH78_VALID; - /* fall through */ + fallthrough; case 6: audio_cfg |= HDMI_AUD_CFG_CH56_VALID; - /* fall through */ + fallthrough; case 4: audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH; - /* fall through */ + fallthrough; case 2: audio_cfg |= HDMI_AUD_CFG_CH12_VALID; break; diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 359b56e43b83..ced9a8287dd8 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -195,7 +195,7 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon, switch (encoder->encoder_type) { case DRM_MODE_ENCODER_LVDS: is_lvds = true; - /* Fallthrough */ + fallthrough; case DRM_MODE_ENCODER_DSI: case DRM_MODE_ENCODER_NONE: channel = 0; @@ -342,7 +342,7 @@ static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon, /* R and B components are only 5 bits deep */ val |= SUN4I_TCON0_FRM_CTL_MODE_R; val |= SUN4I_TCON0_FRM_CTL_MODE_B; - /* Fall through */ + fallthrough; case MEDIA_BUS_FMT_RGB666_1X18: case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* Fall through: enable dithering */ diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index aa67cb037e9d..7f13f4d715bf 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -1027,7 +1027,7 @@ static ssize_t sun6i_dsi_transfer(struct mipi_dsi_host *host, ret = sun6i_dsi_dcs_read(dsi, msg); break; } - /* Else, fall through */ + fallthrough; default: ret = -EINVAL; diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 9a0b3240bc58..424ad60b4f38 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -135,7 +135,7 @@ static inline u32 compute_dda_inc(unsigned int in, unsigned int out, bool v, default: WARN_ON_ONCE(1); - /* fallthrough */ + fallthrough; case 4: max = 4; break; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 1856962411c7..518220bd092a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -386,7 +386,7 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) case DRM_FORMAT_XBGR8888: case DRM_FORMAT_XRGB8888: reg |= LCDC_V2_TFT_24BPP_UNPACK; - /* fallthrough */ + fallthrough; case DRM_FORMAT_BGR888: case DRM_FORMAT_RGB888: reg |= LCDC_V2_TFT_24BPP_MODE; diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 33526c5df0e8..4732dcc80e11 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -525,7 +525,7 @@ int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, if (unlikely(ret != 0)) return ret; } - /* fall through */ + fallthrough; case TTM_PL_TT: ret = ttm_bo_vm_access_kmap(bo, offset, buf, len, write); break; diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 551fa31629af..5771bb53ce6a 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -179,21 +179,21 @@ via_free_sg_info(struct pci_dev *pdev, drm_via_sg_info_t *vsg) switch (vsg->state) { case dr_via_device_mapped: via_unmap_blit_from_device(pdev, vsg); - /* fall through */ + fallthrough; case dr_via_desc_pages_alloc: for (i = 0; i < vsg->num_desc_pages; ++i) { if (vsg->desc_pages[i] != NULL) free_page((unsigned long)vsg->desc_pages[i]); } kfree(vsg->desc_pages); - /* fall through */ + fallthrough; case dr_via_pages_locked: unpin_user_pages_dirty_lock(vsg->pages, vsg->num_pages, (vsg->direction == DMA_FROM_DEVICE)); - /* fall through */ + fallthrough; case dr_via_pages_alloc: vfree(vsg->pages); - /* fall through */ + fallthrough; default: vsg->state = dr_via_sg_init; } diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 013c9e0e412c..cc93a8c9547b 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -649,9 +649,7 @@ static void displback_changed(struct xenbus_device *xb_dev, switch (backend_state) { case XenbusStateReconfiguring: - /* fall through */ case XenbusStateReconfigured: - /* fall through */ case XenbusStateInitialised: break; @@ -701,7 +699,6 @@ static void displback_changed(struct xenbus_device *xb_dev, break; case XenbusStateUnknown: - /* fall through */ case XenbusStateClosed: if (xb_dev->state == XenbusStateClosed) break; diff --git a/drivers/gpu/ipu-v3/ipu-dc.c b/drivers/gpu/ipu-v3/ipu-dc.c index dbcc16721931..34b4075a6a8e 100644 --- a/drivers/gpu/ipu-v3/ipu-dc.c +++ b/drivers/gpu/ipu-v3/ipu-dc.c @@ -141,7 +141,7 @@ static int ipu_bus_format_to_map(u32 fmt) switch (fmt) { default: WARN_ON(1); - /* fall-through */ + fallthrough; case MEDIA_BUS_FMT_RGB888_1X24: return IPU_DC_MAP_RGB24; case MEDIA_BUS_FMT_RGB565_1X16: diff --git a/drivers/hid/hid-lg-g15.c b/drivers/hid/hid-lg-g15.c index ef0cbcd7540d..fcaf8466e627 100644 --- a/drivers/hid/hid-lg-g15.c +++ b/drivers/hid/hid-lg-g15.c @@ -680,7 +680,7 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i) * but it does have a separate power-on (reset) value. */ g15->leds[i].cdev.name = "g15::power_on_backlight_val"; - /* fall through */ + fallthrough; case LG_G15_KBD_BRIGHTNESS: g15->leds[i].cdev.brightness_set_blocking = lg_g510_kbd_led_set; diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index a78c13cc9f47..38ee25a813b9 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c @@ -844,7 +844,7 @@ static void logi_dj_recv_queue_notification(struct dj_receiver_dev *djrcv_dev, workitem.type = WORKITEM_TYPE_EMPTY; break; } - /* fall-through */ + fallthrough; case REPORT_TYPE_NOTIF_DEVICE_UNPAIRED: workitem.quad_id_msb = dj_report->report_params[DEVICE_PAIRED_PARAM_EQUAD_ID_MSB]; diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 2d8b589201a4..5576fed7bc15 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -163,16 +163,13 @@ static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field, { switch (usage->hid & HID_USAGE_PAGE) { case 0xff070000: - /* fall-through */ case HID_UP_DIGITIZER: /* ignore those axis */ return -1; case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: - /* fall-through */ case HID_GD_Y: - /* fall-through */ case HID_GD_RFKILL_BTN: /* ignore those axis */ return -1; diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 8cffa84c9650..7f41213d5ae3 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -428,7 +428,6 @@ static void rmi_report(struct hid_device *hid, struct hid_report *report) switch (report->id) { case RMI_READ_DATA_REPORT_ID: - /* fall-through */ case RMI_ATTN_REPORT_ID: return; } diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 1a6e600197d0..2ff4c8e366ff 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -780,7 +780,7 @@ static void kone_keep_values_up_to_date(struct kone_device *kone, case kone_mouse_event_switch_profile: kone->actual_dpi = kone->profiles[event->value - 1]. startup_dpi; - /* fall through */ + fallthrough; case kone_mouse_event_osd_profile: kone->actual_profile = event->value; break; diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 78a364ae2f68..7d20d1fcf8d2 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -974,7 +974,7 @@ int uclogic_params_init(struct uclogic_params *params, } break; } - /* FALL THROUGH */ + fallthrough; case VID_PID(USB_VENDOR_ID_HUION, USB_DEVICE_ID_HUION_TABLET): case VID_PID(USB_VENDOR_ID_HUION, diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index 679e142fc850..e484c3618dec 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -1672,7 +1672,6 @@ static ssize_t wiimote_ext_show(struct device *dev, case WIIMOTE_EXT_GUITAR: return sprintf(buf, "guitar\n"); case WIIMOTE_EXT_UNKNOWN: - /* fallthrough */ default: return sprintf(buf, "unknown\n"); } @@ -1722,7 +1721,6 @@ static ssize_t wiimote_dev_show(struct device *dev, case WIIMOTE_DEV_PENDING: return sprintf(buf, "pending\n"); case WIIMOTE_DEV_UNKNOWN: - /* fallthrough */ default: return sprintf(buf, "unknown\n"); } diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4140dea693e9..7c0752fbfcf7 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -781,7 +781,6 @@ static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; case HIDIOCGUCODE: - /* fall through */ case HIDIOCGUSAGE: case HIDIOCSUSAGE: case HIDIOCGUSAGES: diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 1c96809b51c9..83dfec327c42 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -341,7 +341,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) case 2: /* Mouse with wheel */ input_report_key(input, BTN_MIDDLE, data[1] & 0x04); - /* fall through */ + fallthrough; case 3: /* Mouse without wheel */ wacom->tool[0] = BTN_TOOL_MOUSE; @@ -1201,7 +1201,7 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) case 0x04: wacom_intuos_bt_process_data(wacom, data + i); i += 10; - /* fall through */ + fallthrough; case 0x03: wacom_intuos_bt_process_data(wacom, data + i); i += 10; @@ -2148,7 +2148,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field for (i = 0; i < wacom->led.count; i++) wacom_update_led(wacom, features->numbered_buttons, value, i); - /* fall through*/ + fallthrough; default: do_report = true; break; @@ -3602,14 +3602,14 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, switch (features->type) { case GRAPHIRE_BT: __clear_bit(ABS_MISC, input_dev->absbit); - /* fall through */ + fallthrough; case WACOM_MO: case WACOM_G4: input_set_abs_params(input_dev, ABS_DISTANCE, 0, features->distance_max, features->distance_fuzz, 0); - /* fall through */ + fallthrough; case GRAPHIRE: input_set_capability(input_dev, EV_REL, REL_WHEEL); @@ -3649,7 +3649,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, case INTUOS4S: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); input_abs_set_res(input_dev, ABS_Z, 287); - /* fall through */ + fallthrough; case INTUOS: wacom_setup_intuos(wacom_wac); @@ -3682,7 +3682,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, case TABLETPC: case TABLETPCE: __clear_bit(ABS_MISC, input_dev->absbit); - /* fall through */ + fallthrough; case DTUS: case DTUSX: @@ -3696,7 +3696,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, case PTU: __set_bit(BTN_STYLUS2, input_dev->keybit); - /* fall through */ + fallthrough; case PENPARTNER: __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -3799,7 +3799,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, input_abs_set_res(input_dev, ABS_MT_POSITION_X, 40); input_abs_set_res(input_dev, ABS_MT_POSITION_Y, 40); - /* fall through */ + fallthrough; case INTUOS5: case INTUOS5L: @@ -3817,7 +3817,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); - /* fall through */ + fallthrough; case WACOM_27QHDT: if (wacom_wac->shared->touch->product == 0x32C || @@ -3826,14 +3826,14 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, __set_bit(SW_MUTE_DEVICE, input_dev->swbit); wacom_wac->shared->has_mute_touch_switch = true; } - /* fall through */ + fallthrough; case MTSCREEN: case MTTPC: case MTTPC_B: case TABLETPC2FG: input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT); - /*fall through */ + fallthrough; case TABLETPC: case TABLETPCE: @@ -3843,7 +3843,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, case INTUOSHT2: input_dev->evbit[0] |= BIT_MASK(EV_SW); __set_bit(SW_MUTE_DEVICE, input_dev->swbit); - /* fall through */ + fallthrough; case BAMBOO_PT: case BAMBOO_TOUCH: @@ -4099,7 +4099,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, __set_bit(KEY_BUTTONCONFIG, input_dev->keybit); __set_bit(KEY_INFO, input_dev->keybit); - /* fall through */ + fallthrough; case WACOM_21UX2: case WACOM_BEE: @@ -4115,7 +4115,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOS3: case INTUOS3L: input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0); - /* fall through */ + fallthrough; case INTUOS3S: input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0); @@ -4139,7 +4139,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, * ID_INPUT_TABLET to be set. */ __set_bit(BTN_STYLUS, input_dev->keybit); - /* fall through */ + fallthrough; case INTUOS4: case INTUOS4L: diff --git a/drivers/hsi/clients/ssi_protocol.c b/drivers/hsi/clients/ssi_protocol.c index 365b5d5967ac..96d0eccca3aa 100644 --- a/drivers/hsi/clients/ssi_protocol.c +++ b/drivers/hsi/clients/ssi_protocol.c @@ -291,7 +291,7 @@ static void ssip_set_rxstate(struct ssi_protocol *ssi, unsigned int state) /* CMT speech workaround */ if (atomic_read(&ssi->tx_usecnt)) break; - /* Else, fall through */ + fallthrough; case RECEIVING: mod_timer(&ssi->keep_alive, jiffies + msecs_to_jiffies(SSIP_KATOUT)); @@ -466,7 +466,7 @@ static void ssip_keep_alive(struct timer_list *t) case SEND_READY: if (atomic_read(&ssi->tx_usecnt) == 0) break; - /* Fall through */ + fallthrough; /* * Workaround for cmt-speech in that case * we relay on audio timers. @@ -668,7 +668,7 @@ static void ssip_rx_bootinforeq(struct hsi_client *cl, u32 cmd) case ACTIVE: dev_err(&cl->device, "Boot info req on active state\n"); ssip_error(cl); - /* Fall through */ + fallthrough; case INIT: case HANDSHAKE: spin_lock_bh(&ssi->lock); diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c index 4bc4a201f0f6..fa69b94debd9 100644 --- a/drivers/hsi/controllers/omap_ssi_core.c +++ b/drivers/hsi/controllers/omap_ssi_core.c @@ -296,7 +296,7 @@ static int ssi_clk_event(struct notifier_block *nb, unsigned long event, break; case ABORT_RATE_CHANGE: dev_dbg(&ssi->device, "abort rate change\n"); - /* Fall through */ + fallthrough; case POST_RATE_CHANGE: dev_dbg(&ssi->device, "post rate change (%lu -> %lu)\n", clk_data->old_rate, clk_data->new_rate); diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index e74b144b8f3d..754d35a25a1c 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -354,7 +354,7 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op) out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; - /* fallthrough */ + fallthrough; case KVP_OP_GET_IP_INFO: utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id, diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 319a0519ebdb..208813158bb4 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -435,7 +435,7 @@ static const char *voltage_label(struct adt7462_data *data, int which) case 3: return "+1.5V"; } - /* fall through */ + fallthrough; case 2: if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) return "+12V3"; @@ -493,7 +493,7 @@ static const char *voltage_label(struct adt7462_data *data, int which) case 3: return "+1.5"; } - /* fall through */ + fallthrough; case 11: if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == ADT7462_PIN28_VOLT && @@ -531,7 +531,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which) case 3: return 7800; } - /* fall through */ + fallthrough; case 2: if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) return 62500; @@ -589,7 +589,7 @@ static int voltage_multiplier(struct adt7462_data *data, int which) case 3: return 7800; } - /* fall through */ + fallthrough; case 11: case 12: if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index cf0962f7a020..e9c0bbc2caa9 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -406,10 +406,10 @@ static int emc1403_probe(struct i2c_client *client, switch (id->driver_data) { case emc1404: data->groups[2] = &emc1404_group; - /* fall through */ + fallthrough; case emc1403: data->groups[1] = &emc1403_group; - /* fall through */ + fallthrough; case emc1402: data->groups[0] = &emc1402_group; } diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index d09deb409de7..4dec793fd07d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -1285,7 +1285,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) data->pwm_auto_point_pwm[nr][0] = f71882fg_read8(data, F71882FG_REG_POINT_PWM(nr, 0)); - /* Fall through */ + fallthrough; case f71862fg: data->pwm_auto_point_pwm[nr][1] = f71882fg_read8(data, @@ -2442,7 +2442,7 @@ static int f71882fg_probe(struct platform_device *pdev) case f71869a: /* These always have signed auto point temps */ data->auto_point_temp_signed = 1; - /* Fall through - to select correct fan/pwm reg bank! */ + fallthrough; /* to select correct fan/pwm reg bank! */ case f71889fg: case f71889ed: case f71889a: diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c index eb72e390844e..6d1175a51832 100644 --- a/drivers/hwmon/hwmon-vid.c +++ b/drivers/hwmon/hwmon-vid.c @@ -96,7 +96,7 @@ int vid_from_reg(int val, u8 vrm) val &= 0x1f; if (val == 0x1f) return 0; - /* fall through */ + fallthrough; case 25: /* AMD NPT 0Fh */ val &= 0x3f; return (val < 32) ? 1550 - 25 * val @@ -122,7 +122,7 @@ int vid_from_reg(int val, u8 vrm) case 84: /* VRM 8.4 */ val &= 0x0f; - /* fall through */ + fallthrough; case 82: /* VRM 8.2 */ val &= 0x1f; return val == 0x1f ? 0 : diff --git a/drivers/hwmon/ina3221.c b/drivers/hwmon/ina3221.c index 7fc5b065ad8b..81e155692aba 100644 --- a/drivers/hwmon/ina3221.c +++ b/drivers/hwmon/ina3221.c @@ -352,7 +352,7 @@ static int ina3221_read_curr(struct device *dev, u32 attr, if (ret) return ret; - /* fall through */ + fallthrough; case hwmon_curr_crit: case hwmon_curr_max: if (!resistance_uo) diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 750b08713dee..5bd15622a85f 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -2669,7 +2669,7 @@ static void pwm_update_registers(struct nct6775_data *data, int nr) case thermal_cruise: nct6775_write_value(data, data->REG_TARGET[nr], data->target_temp[nr]); - /* fall through */ + fallthrough; default: reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]); reg = (reg & ~data->tolerance_mask) | diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c index 30e18eb60da7..a71777990d49 100644 --- a/drivers/hwmon/occ/common.c +++ b/drivers/hwmon/occ/common.c @@ -752,7 +752,7 @@ static int occ_setup_sensor_attrs(struct occ *occ) switch (sensors->freq.version) { case 2: show_freq = occ_show_freq_2; - /* fall through */ + fallthrough; case 1: num_attrs += (sensors->freq.num_sensors * 2); break; @@ -763,7 +763,7 @@ static int occ_setup_sensor_attrs(struct occ *occ) switch (sensors->power.version) { case 2: show_power = occ_show_power_2; - /* fall through */ + fallthrough; case 1: num_attrs += (sensors->power.num_sensors * 4); break; @@ -781,7 +781,7 @@ static int occ_setup_sensor_attrs(struct occ *occ) break; case 3: show_caps = occ_show_caps_3; - /* fall through */ + fallthrough; case 2: num_attrs += (sensors->caps.num_sensors * 8); break; diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c index e1d10a6b7f7c..a07b97400cba 100644 --- a/drivers/hwmon/w83627hf.c +++ b/drivers/hwmon/w83627hf.c @@ -1213,7 +1213,7 @@ temp_type_store(struct device *dev, struct device_attribute *devattr, case W83781D_DEFAULT_BETA: dev_warn(dev, "Sensor type %d is deprecated, please use 4 " "instead\n", W83781D_DEFAULT_BETA); - /* fall through */ + fallthrough; case 4: /* thermistor */ tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); w83627hf_write_value(data, W83781D_REG_SCFG1, diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 015f1ea31966..d833a4f16c47 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -814,7 +814,7 @@ store_sensor(struct device *dev, struct device_attribute *da, dev_warn(dev, "Sensor type %d is deprecated, please use 4 instead\n", W83781D_DEFAULT_BETA); - /* fall through */ + fallthrough; case 4: /* thermistor */ tmp = w83781d_read_value(data, W83781D_REG_SCFG1); w83781d_write_value(data, W83781D_REG_SCFG1, diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 44f68b965aec..6d52b530b429 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -2127,7 +2127,7 @@ static void w83795_apply_temp_config(struct w83795_data *data, u8 config, if (temp_chan >= 4) break; data->temp_mode |= 1 << temp_chan; - /* fall through */ + fallthrough; case 0x3: /* Thermistor */ data->has_temp |= 1 << temp_chan; break; diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index 96544b348c27..7e642fb3ed15 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -346,10 +346,10 @@ static void debug_init_arch_data(void *info) switch (mode) { case EDDEVID_IMPL_FULL: drvdata->edvidsr_present = true; - /* Fall through */ + fallthrough; case EDDEVID_IMPL_EDPCSR_EDCIDSR: drvdata->edcidsr_present = true; - /* Fall through */ + fallthrough; case EDDEVID_IMPL_EDPCSR: /* * In ARM DDI 0487A.k, the EDDEVID1.PCSROffset is used to diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 6d7d2169bfb2..96425e818fc2 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1382,7 +1382,6 @@ static int etm4_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd, return NOTIFY_BAD; break; case CPU_PM_EXIT: - /* fallthrough */ case CPU_PM_ENTER_FAILED: if (drvdata->state_needs_restore) etm4_cpu_restore(drvdata); diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 7040d583bed9..9ca3aaafcfbc 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -84,9 +84,7 @@ u32 tmc_get_memwidth_mask(struct tmc_drvdata *drvdata) */ switch (drvdata->memwidth) { case TMC_MEM_INTF_WIDTH_32BITS: - /* fallthrough */ case TMC_MEM_INTF_WIDTH_64BITS: - /* fallthrough */ case TMC_MEM_INTF_WIDTH_128BITS: mask = GENMASK(31, 4); break; diff --git a/drivers/hwtracing/intel_th/sth.c b/drivers/hwtracing/intel_th/sth.c index a1529f571491..9ca8c4e045f8 100644 --- a/drivers/hwtracing/intel_th/sth.c +++ b/drivers/hwtracing/intel_th/sth.c @@ -84,11 +84,11 @@ static ssize_t notrace sth_stm_packet(struct stm_data *stm_data, /* Global packets (GERR, XSYNC, TRIG) are sent with register writes */ case STP_PACKET_GERR: reg += 4; - /* fall through */ + fallthrough; case STP_PACKET_XSYNC: reg += 8; - /* fall through */ + fallthrough; case STP_PACKET_TRIG: if (flags & STP_PACKET_TIMESTAMPED) diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 175c590b93b7..12ac4212aded 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -1425,7 +1425,6 @@ omap_i2c_probe(struct platform_device *pdev) major = OMAP_I2C_REV_SCHEME_0_MAJOR(omap->rev); break; case OMAP_I2C_SCHEME_1: - /* FALLTHROUGH */ default: omap->regs = (u8 *)reg_map_ip_v2; rev = (rev << 16) | diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c index 1c4c9bb06a0b..6eb0f50c5d28 100644 --- a/drivers/i2c/busses/i2c-opal.c +++ b/drivers/i2c/busses/i2c-opal.c @@ -125,7 +125,7 @@ static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr, case I2C_SMBUS_BYTE: req.buffer_ra = cpu_to_be64(__pa(&data->byte)); req.size = cpu_to_be32(1); - /* Fall through */ + fallthrough; case I2C_SMBUS_QUICK: req.type = (read_write == I2C_SMBUS_READ) ? OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE; diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c index 5c5306cd50ec..8513bd353c05 100644 --- a/drivers/i3c/master/dw-i3c-master.c +++ b/drivers/i3c/master/dw-i3c-master.c @@ -603,7 +603,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m) ret = dw_i2c_clk_cfg(master); if (ret) return ret; - /* fall through */ + fallthrough; case I3C_BUS_MODE_PURE: ret = dw_i3c_clk_cfg(master); if (ret) diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index fd3b5da44619..50c9a41467c8 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -575,14 +575,14 @@ static u8 hpt3xx_udma_filter(ide_drive_t *drive) if (!HPT370_ALLOW_ATA100_5 || check_in_drive_list(drive, bad_ata100_5)) return ATA_UDMA4; - /* fall through */ + fallthrough; case HPT372 : case HPT372A: case HPT372N: case HPT374 : if (ata_id_is_sata(drive->id)) mask &= ~0x0e; - /* fall through */ + fallthrough; default: return mask; } @@ -602,7 +602,7 @@ static u8 hpt3xx_mdma_filter(ide_drive_t *drive) case HPT374 : if (ata_id_is_sata(drive->id)) return 0x00; - /* fall through */ + fallthrough; default: return 0x07; } diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 7f17f8303988..212bb2d8bf34 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -350,7 +350,7 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) */ if (scsi_req(rq)->cmd[0] == GPCMD_START_STOP_UNIT) break; - /* fall-through */ + fallthrough; case DATA_PROTECT: /* * No point in retrying after an illegal request or data @@ -750,7 +750,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) case REQ_OP_DRV_IN: case REQ_OP_DRV_OUT: expiry = ide_cd_expiry; - /*FALLTHRU*/ + fallthrough; default: timeout = ATAPI_WAIT_PC; break; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 1fe1f9d37a51..af7503b47dbe 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -428,7 +428,7 @@ static int ide_floppy_get_capacity(ide_drive_t *drive) * (maintains previous driver behaviour) */ break; - /* fall through */ + fallthrough; case CAPACITY_CURRENT: /* Normal Zip/LS-120 disks */ if (memcmp(cap_desc, &floppy->cap_desc, 8)) diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index e867129466b0..1ddc45a04418 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -143,7 +143,7 @@ static void ide_classify_atapi_dev(ide_drive_t *drive) } /* Early cdrom models used zero */ type = ide_cdrom; - /* fall through */ + fallthrough; case ide_cdrom: drive->dev_flags |= IDE_DFLAG_REMOVABLE; #ifdef CONFIG_PPC diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index a26f85ab58a9..d016cbe68cba 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -129,7 +129,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) return pre_task_out_intr(drive, cmd); } handler = task_pio_intr; - /* fall through */ + fallthrough; case ATA_PROT_NODATA: if (handler == NULL) handler = task_no_data_intr; @@ -141,7 +141,7 @@ ide_startstop_t do_rw_taskfile(ide_drive_t *drive, struct ide_cmd *orig_cmd) hwif->expiry = dma_ops->dma_timer_expiry; ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD); dma_ops->dma_start(drive); - /* fall through */ + fallthrough; default: return ide_started; } @@ -579,10 +579,10 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) goto abort; } cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; - /* fall through */ + fallthrough; case TASKFILE_OUT: cmd.protocol = ATA_PROT_PIO; - /* fall through */ + fallthrough; case TASKFILE_OUT_DMAQ: case TASKFILE_OUT_DMA: cmd.tf_flags |= IDE_TFLAG_WRITE; @@ -598,10 +598,10 @@ int ide_taskfile_ioctl(ide_drive_t *drive, unsigned long arg) goto abort; } cmd.tf_flags |= IDE_TFLAG_MULTI_PIO; - /* fall through */ + fallthrough; case TASKFILE_IN: cmd.protocol = ATA_PROT_PIO; - /* fall through */ + fallthrough; case TASKFILE_IN_DMAQ: case TASKFILE_IN_DMA: nsect = taskin / SECTOR_SIZE; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 024bc7ba49ee..1a700bef6c56 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -494,7 +494,7 @@ static int init_chipset_sis5513(struct pci_dev *dev) pci_read_config_byte(dev, 0x09, ®); if ((reg & 0x0f) != 0x00) pci_write_config_byte(dev, 0x09, reg&0xf0); - /* fall through */ + fallthrough; case ATA_16: /* force per drive recovery and active timings needed on ATA_33 and below chips */ diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c index ba27f8673131..4e6e70250048 100644 --- a/drivers/iio/accel/mma8452.c +++ b/drivers/iio/accel/mma8452.c @@ -1580,7 +1580,7 @@ static int mma8452_probe(struct i2c_client *client, case FXLS8471_DEVICE_ID: if (ret == data->chip_info->chip_id) break; - /* fall through */ + fallthrough; default: ret = -ENODEV; goto disable_regulators; diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c index 7fdc5d2d1d35..1bb987a4acba 100644 --- a/drivers/iio/adc/ab8500-gpadc.c +++ b/drivers/iio/adc/ab8500-gpadc.c @@ -484,7 +484,7 @@ static int ab8500_gpadc_read(struct ab8500_gpadc *gpadc, delay_max = 10000; /* large range optimises sleepmode */ break; } - /* Fall through */ + fallthrough; default: ctrl1 |= AB8500_GPADC_CTRL1_BUF_ENA; break; diff --git a/drivers/iio/adc/cpcap-adc.c b/drivers/iio/adc/cpcap-adc.c index 84a1733e5913..64c3cc382311 100644 --- a/drivers/iio/adc/cpcap-adc.c +++ b/drivers/iio/adc/cpcap-adc.c @@ -690,7 +690,7 @@ static void cpcap_adc_phase(struct cpcap_adc_request *req) break; case CPCAP_ADC_BATTI_PI17: index = req->bank_index; - /* fallthrough */ + fallthrough; default: req->result += conv_tbl[index].cal_offset; req->result += conv_tbl[index].align_offset; diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c index 5a29e32c295f..2ea9a5c4d846 100644 --- a/drivers/iio/chemical/sps30.c +++ b/drivers/iio/chemical/sps30.c @@ -118,7 +118,7 @@ static int sps30_do_cmd(struct sps30_state *state, u16 cmd, u8 *data, int size) case SPS30_READ_AUTO_CLEANING_PERIOD: buf[0] = SPS30_AUTO_CLEANING_PERIOD >> 8; buf[1] = (u8)(SPS30_AUTO_CLEANING_PERIOD & 0xff); - /* fall through */ + fallthrough; case SPS30_READ_DATA_READY_FLAG: case SPS30_READ_DATA: case SPS30_READ_SERIAL: diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index cc4875660a69..1fd75c02a7cd 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -220,7 +220,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st) break; case CH_MODE_UNUSED: - /* fall-through */ default: switch (st->channel_offstate[i]) { case CH_OFFSTATE_OUT_TRISTATE: @@ -237,7 +236,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st) break; case CH_OFFSTATE_PULLDOWN: - /* fall-through */ default: pulldown |= BIT(i); break; diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c index b3835fb6b862..be61c3b01e8b 100644 --- a/drivers/iio/dac/dpot-dac.c +++ b/drivers/iio/dac/dpot-dac.c @@ -78,7 +78,7 @@ static int dpot_dac_read_raw(struct iio_dev *indio_dev, */ *val2 = 1; ret = IIO_VAL_FRACTIONAL; - /* fall through */ + fallthrough; case IIO_VAL_FRACTIONAL: *val *= regulator_get_voltage(dac->vref) / 1000; *val2 *= dac->max_ohms; diff --git a/drivers/iio/health/max30102.c b/drivers/iio/health/max30102.c index 9b47d9472a4f..d9b2ed80882a 100644 --- a/drivers/iio/health/max30102.c +++ b/drivers/iio/health/max30102.c @@ -273,10 +273,10 @@ static int max30102_read_measurement(struct max30102_data *data, switch (measurements) { case 3: MAX30102_COPY_DATA(2); - /* fall through */ + fallthrough; case 2: MAX30102_COPY_DATA(1); - /* fall through */ + fallthrough; case 1: MAX30102_COPY_DATA(0); break; diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c index c539dfa3b8d3..319b64b2fd88 100644 --- a/drivers/iio/imu/adis.c +++ b/drivers/iio/imu/adis.c @@ -97,11 +97,11 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, adis->tx[9] = (value >> 24) & 0xff; adis->tx[6] = ADIS_WRITE_REG(reg + 2); adis->tx[7] = (value >> 16) & 0xff; - /* fall through */ + fallthrough; case 2: adis->tx[4] = ADIS_WRITE_REG(reg + 1); adis->tx[5] = (value >> 8) & 0xff; - /* fall through */ + fallthrough; case 1: adis->tx[2] = ADIS_WRITE_REG(reg); adis->tx[3] = value & 0xff; @@ -191,7 +191,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, adis->tx[2] = ADIS_READ_REG(reg + 2); adis->tx[3] = 0; spi_message_add_tail(&xfers[1], &msg); - /* fall through */ + fallthrough; case 2: adis->tx[4] = ADIS_READ_REG(reg); adis->tx[5] = 0; diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 606d5e61c575..cdcd16f19500 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -599,7 +599,7 @@ static ssize_t __iio_format_value(char *buf, size_t len, unsigned int type, return scnprintf(buf, len, "%d", vals[0]); case IIO_VAL_INT_PLUS_MICRO_DB: scale_db = true; - /* fall through */ + fallthrough; case IIO_VAL_INT_PLUS_MICRO: if (vals[1] < 0) return scnprintf(buf, len, "-%d.%06u%s", abs(vals[0]), @@ -918,7 +918,7 @@ static ssize_t iio_write_channel_info(struct device *dev, break; case IIO_VAL_INT_PLUS_MICRO_DB: scale_db = true; - /* fall through */ + fallthrough; case IIO_VAL_INT_PLUS_MICRO: fract_mult = 100000; break; diff --git a/drivers/iio/light/si1145.c b/drivers/iio/light/si1145.c index 155faaea8c72..8f5f857c2e7d 100644 --- a/drivers/iio/light/si1145.c +++ b/drivers/iio/light/si1145.c @@ -1042,7 +1042,7 @@ static int si1145_initialize(struct si1145_data *data) SI1145_LED_CURRENT_45mA); if (ret < 0) return ret; - /* fallthrough */ + fallthrough; case 2: ret = i2c_smbus_write_byte_data(client, SI1145_REG_PS_LED21, diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c index 6a8ae145f0c0..cbb44e401c0a 100644 --- a/drivers/iio/magnetometer/ak8974.c +++ b/drivers/iio/magnetometer/ak8974.c @@ -499,7 +499,7 @@ static int ak8974_detect(struct ak8974 *ak8974) switch (whoami) { case AK8974_WHOAMI_VALUE_AMI306: name = "ami306"; - /* fall-through */ + fallthrough; case AK8974_WHOAMI_VALUE_AMI305: ret = regmap_read(ak8974->map, AMI305_VER, &fw); if (ret) diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index dc0558b23158..fbc28f1a8b92 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3034,7 +3034,7 @@ static int cm_rej_handler(struct cm_work *work) case IB_CM_REP_SENT: case IB_CM_MRA_REP_RCVD: ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); - /* fall through */ + fallthrough; case IB_CM_REQ_RCVD: case IB_CM_MRA_REQ_SENT: if (IBA_GET(CM_REJ_REASON, rej_msg) == IB_CM_REJ_STALE_CONN) @@ -3044,7 +3044,7 @@ static int cm_rej_handler(struct cm_work *work) break; case IB_CM_DREQ_SENT: ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg); - /* fall through */ + fallthrough; case IB_CM_REP_RCVD: case IB_CM_MRA_REP_SENT: cm_enter_timewait(cm_id_priv); @@ -3058,7 +3058,7 @@ static int cm_rej_handler(struct cm_work *work) cm_enter_timewait(cm_id_priv); break; } - /* fall through */ + fallthrough; default: pr_debug("%s: local_id %d, cm_id_priv->id.state: %d\n", __func__, be32_to_cpu(cm_id_priv->id.local_id), @@ -3116,7 +3116,7 @@ int ib_send_cm_mra(struct ib_cm_id *cm_id, msg_response = CM_MSG_RESPONSE_OTHER; break; } - /* fall through */ + fallthrough; default: pr_debug("%s: local_id %d, cm_id_priv->id.state: %d\n", __func__, be32_to_cpu(cm_id_priv->id.local_id), @@ -3227,7 +3227,7 @@ static int cm_mra_handler(struct cm_work *work) case IB_CM_MRA_REP_RCVD: atomic_long_inc(&work->port->counter_group[CM_RECV_DUPLICATES]. counter[CM_MRA_COUNTER]); - /* fall through */ + fallthrough; default: pr_debug("%s local_id %d, cm_id_priv->id.state: %d\n", __func__, be32_to_cpu(cm_id_priv->id.local_id), @@ -4214,7 +4214,7 @@ static int cm_init_qp_rts_attr(struct cm_id_private *cm_id_priv, qp_attr->retry_cnt = cm_id_priv->retry_count; qp_attr->rnr_retry = cm_id_priv->rnr_retry_count; qp_attr->max_rd_atomic = cm_id_priv->initiator_depth; - /* fall through */ + fallthrough; case IB_QPT_XRC_TGT: *qp_attr_mask |= IB_QP_TIMEOUT; qp_attr->timeout = cm_id_priv->av.timeout; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 26de0dab60bb..7f0e91e92968 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1985,7 +1985,8 @@ static int cma_ib_handler(struct ib_cm_id *cm_id, event.event = RDMA_CM_EVENT_ESTABLISHED; break; case IB_CM_DREQ_ERROR: - event.status = -ETIMEDOUT; /* fall through */ + event.status = -ETIMEDOUT; + fallthrough; case IB_CM_DREQ_RECEIVED: case IB_CM_DREP_RECEIVED: if (!cma_comp_exch(id_priv, RDMA_CM_CONNECT, diff --git a/drivers/infiniband/core/rw.c b/drivers/infiniband/core/rw.c index 614cff89fc71..13f43ab7220b 100644 --- a/drivers/infiniband/core/rw.c +++ b/drivers/infiniband/core/rw.c @@ -510,7 +510,6 @@ struct ib_send_wr *rdma_rw_ctx_wrs(struct rdma_rw_ctx *ctx, struct ib_qp *qp, switch (ctx->type) { case RDMA_RW_SIG_MR: case RDMA_RW_MR: - /* fallthrough */ for (i = 0; i < ctx->nr_ops; i++) { rdma_rw_update_lkey(&ctx->reg[i], ctx->reg[i].wr.wr.opcode != diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index d03dacaef788..1d184ea05eba 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -794,7 +794,7 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp, case 2: ib_copy_path_rec_to_user(&resp->ib_route[1], &route->path_rec[1]); - /* fall through */ + fallthrough; case 1: ib_copy_path_rec_to_user(&resp->ib_route[0], &route->path_rec[0]); @@ -820,7 +820,7 @@ static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp, case 2: ib_copy_path_rec_to_user(&resp->ib_route[1], &route->path_rec[1]); - /* fall through */ + fallthrough; case 1: ib_copy_path_rec_to_user(&resp->ib_route[0], &route->path_rec[0]); diff --git a/drivers/infiniband/core/uverbs_ioctl.c b/drivers/infiniband/core/uverbs_ioctl.c index ef04a261097f..e47c5949013f 100644 --- a/drivers/infiniband/core/uverbs_ioctl.c +++ b/drivers/infiniband/core/uverbs_ioctl.c @@ -259,7 +259,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle, return -EOPNOTSUPP; e->ptr_attr.enum_id = uattr->attr_data.enum_data.elem_id; - /* fall through */ + fallthrough; case UVERBS_ATTR_TYPE_PTR_IN: /* Ensure that any data provided by userspace beyond the known * struct is zero. Userspace that knows how to use some future @@ -271,7 +271,7 @@ static int uverbs_process_attr(struct bundle_priv *pbundle, !uverbs_is_attr_cleared(uattr, val_spec->u.ptr.len)) return -EOPNOTSUPP; - /* fall through */ + fallthrough; case UVERBS_ATTR_TYPE_PTR_OUT: if (uattr->len < val_spec->u.ptr.min_len || (!val_spec->zero_trailing && diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 3f18efc0c297..5ee272d27aaa 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -2657,7 +2657,7 @@ int bnxt_re_post_send(struct ib_qp *ib_qp, const struct ib_send_wr *wr, default: break; } - /* fall through */ + fallthrough; case IB_WR_SEND_WITH_INV: rc = bnxt_re_build_send_wqe(qp, wr, &wqe); break; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index 117b42349a28..d60e3dcea087 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -1779,7 +1779,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, break; } - /* fall thru */ + fallthrough; case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_IMM: case BNXT_QPLIB_SWQE_TYPE_SEND_WITH_INV: { diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 77bc02a9228e..1f288c73ccfc 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -2885,7 +2885,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) case MORIBUND: case CLOSING: stop_ep_timer(ep); - /*FALLTHROUGH*/ + fallthrough; case FPDU_MODE: if (ep->com.qp && ep->com.qp->srq) { srqidx = ABORT_RSS_SRQIDX_G( @@ -3759,7 +3759,7 @@ static void active_ofld_conn_reply(struct c4iw_dev *dev, struct sk_buff *skb, send_fw_act_open_req(ep, atid); return; } - /* fall through */ + fallthrough; case FW_EADDRINUSE: set_bit(ACT_RETRY_INUSE, &ep->com.history); if (ep->retry_count++ < ACT_OPEN_RETRY_COUNT) { diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index ac48012c992f..cbddb20c6121 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1165,7 +1165,7 @@ int c4iw_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, break; } fw_flags |= FW_RI_RDMA_WRITE_WITH_IMMEDIATE; - /*FALLTHROUGH*/ + fallthrough; case IB_WR_RDMA_WRITE: fw_opcode = FW_RI_RDMA_WRITE_WR; swsqe->opcode = FW_RI_RDMA_WRITE; diff --git a/drivers/infiniband/hw/hfi1/pio_copy.c b/drivers/infiniband/hw/hfi1/pio_copy.c index b12e4665c9ab..4a4ec2397857 100644 --- a/drivers/infiniband/hw/hfi1/pio_copy.c +++ b/drivers/infiniband/hw/hfi1/pio_copy.c @@ -209,7 +209,6 @@ static inline void jcopy(u8 *dest, const u8 *src, u32 n) fallthrough; case 1: *dest++ = *src++; - /* fall through */ } } diff --git a/drivers/infiniband/hw/i40iw/i40iw_cm.c b/drivers/infiniband/hw/i40iw/i40iw_cm.c index fa7a5ff498c7..a3b95805c154 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_cm.c +++ b/drivers/infiniband/hw/i40iw/i40iw_cm.c @@ -2443,7 +2443,7 @@ static void i40iw_handle_rst_pkt(struct i40iw_cm_node *cm_node, case I40IW_CM_STATE_FIN_WAIT1: case I40IW_CM_STATE_LAST_ACK: cm_node->cm_id->rem_ref(cm_node->cm_id); - /* fall through */ + fallthrough; case I40IW_CM_STATE_TIME_WAIT: cm_node->state = I40IW_CM_STATE_CLOSED; i40iw_rem_ref_cm_node(cm_node); diff --git a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c index 688f19667221..86d3f8aff329 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c +++ b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c @@ -1964,7 +1964,6 @@ static enum i40iw_status_code i40iw_sc_get_next_aeqe(struct i40iw_sc_aeq *aeq, info->out_rdrsp = true; break; case I40IW_AE_SOURCE_RSVD: - /* fallthrough */ default: break; } @@ -3762,14 +3761,14 @@ static enum i40iw_status_code cqp_sds_wqe_fill(struct i40iw_sc_cqp *cqp, LS_64(1, I40IW_CQPSQ_UPESD_ENTRY_VALID))); set_64bit_val(wqe, 56, info->entry[2].data); - /* fallthrough */ + fallthrough; case 2: set_64bit_val(wqe, 32, (LS_64(info->entry[1].cmd, I40IW_CQPSQ_UPESD_SDCMD) | LS_64(1, I40IW_CQPSQ_UPESD_ENTRY_VALID))); set_64bit_val(wqe, 40, info->entry[1].data); - /* fallthrough */ + fallthrough; case 1: set_64bit_val(wqe, 0, LS_64(info->entry[0].cmd, I40IW_CQPSQ_UPESD_SDCMD)); diff --git a/drivers/infiniband/hw/i40iw/i40iw_hw.c b/drivers/infiniband/hw/i40iw/i40iw_hw.c index ae8b97c30665..e1085634b8d9 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_hw.c +++ b/drivers/infiniband/hw/i40iw/i40iw_hw.c @@ -353,7 +353,6 @@ void i40iw_process_aeq(struct i40iw_device *iwdev) i40iw_cm_disconn(iwqp); break; case I40IW_AE_BAD_CLOSE: - /* fall through */ case I40IW_AE_RESET_SENT: i40iw_next_iw_state(iwqp, I40IW_QP_STATE_ERROR, 1, 0, 0); i40iw_cm_disconn(iwqp); @@ -413,7 +412,7 @@ void i40iw_process_aeq(struct i40iw_device *iwdev) case I40IW_AE_UDA_XMIT_DGRAM_TOO_LONG: case I40IW_AE_UDA_XMIT_DGRAM_TOO_SHORT: ctx_info->err_rq_idx_valid = false; - /* fall through */ + fallthrough; default: if (!info->sq && ctx_info->err_rq_idx_valid) { ctx_info->err_rq_idx = info->wqe_idx; diff --git a/drivers/infiniband/hw/i40iw/i40iw_main.c b/drivers/infiniband/hw/i40iw/i40iw_main.c index 9c96ece5e7f3..58a433135a03 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_main.c +++ b/drivers/infiniband/hw/i40iw/i40iw_main.c @@ -1489,36 +1489,35 @@ static void i40iw_deinit_device(struct i40iw_device *iwdev) iwdev->iw_status = 0; i40iw_port_ibevent(iwdev); i40iw_destroy_rdma_device(iwdev->iwibdev); - /* fallthrough */ + fallthrough; case IP_ADDR_REGISTERED: if (!iwdev->reset) i40iw_del_macip_entry(iwdev, (u8)iwdev->mac_ip_table_idx); - /* fallthrough */ - /* fallthrough */ + fallthrough; case PBLE_CHUNK_MEM: i40iw_destroy_pble_pool(dev, iwdev->pble_rsrc); - /* fallthrough */ + fallthrough; case CEQ_CREATED: i40iw_dele_ceqs(iwdev); - /* fallthrough */ + fallthrough; case AEQ_CREATED: i40iw_destroy_aeq(iwdev); - /* fallthrough */ + fallthrough; case IEQ_CREATED: i40iw_puda_dele_resources(&iwdev->vsi, I40IW_PUDA_RSRC_TYPE_IEQ, iwdev->reset); - /* fallthrough */ + fallthrough; case ILQ_CREATED: i40iw_puda_dele_resources(&iwdev->vsi, I40IW_PUDA_RSRC_TYPE_ILQ, iwdev->reset); - /* fallthrough */ + fallthrough; case CCQ_CREATED: i40iw_destroy_ccq(iwdev); - /* fallthrough */ + fallthrough; case HMC_OBJS_CREATED: i40iw_del_hmc_objects(dev, dev->hmc_info, true, iwdev->reset); - /* fallthrough */ + fallthrough; case CQP_CREATED: i40iw_destroy_cqp(iwdev, true); - /* fallthrough */ + fallthrough; case INITIAL_STATE: i40iw_cleanup_cm_core(&iwdev->cm_core); if (iwdev->vsi.pestat) { @@ -1528,7 +1527,6 @@ static void i40iw_deinit_device(struct i40iw_device *iwdev) i40iw_del_init_mem(iwdev); break; case INVALID_STATE: - /* fallthrough */ default: i40iw_pr_err("bad init_state = %d\n", iwdev->init_state); break; diff --git a/drivers/infiniband/hw/i40iw/i40iw_puda.c b/drivers/infiniband/hw/i40iw/i40iw_puda.c index d9c7ae6a7030..924be4b03c9a 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_puda.c +++ b/drivers/infiniband/hw/i40iw/i40iw_puda.c @@ -814,13 +814,13 @@ void i40iw_puda_dele_resources(struct i40iw_sc_vsi *vsi, switch (rsrc->completion) { case PUDA_HASH_CRC_COMPLETE: i40iw_free_hash_desc(rsrc->hash_desc); - /* fall through */ + fallthrough; case PUDA_QP_CREATED: if (!reset) i40iw_puda_free_qp(rsrc); i40iw_free_dma_mem(dev->hw, &rsrc->qpmem); - /* fallthrough */ + fallthrough; case PUDA_CQ_CREATED: if (!reset) i40iw_puda_free_cq(rsrc); diff --git a/drivers/infiniband/hw/i40iw/i40iw_utils.c b/drivers/infiniband/hw/i40iw/i40iw_utils.c index 016524683e17..e07fb37af086 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_utils.c +++ b/drivers/infiniband/hw/i40iw/i40iw_utils.c @@ -190,9 +190,8 @@ int i40iw_inetaddr_event(struct notifier_block *notifier, switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; - /* Fall through */ + fallthrough; case NETDEV_UP: - /* Fall through */ case NETDEV_CHANGEADDR: /* Just skip if no need to handle ARP cache */ @@ -247,9 +246,8 @@ int i40iw_inet6addr_event(struct notifier_block *notifier, switch (event) { case NETDEV_DOWN: action = I40IW_ARP_DELETE; - /* Fall through */ + fallthrough; case NETDEV_UP: - /* Fall through */ case NETDEV_CHANGEADDR: i40iw_manage_arp_cache(iwdev, netdev->dev_addr, @@ -344,7 +342,7 @@ int i40iw_netdevice_event(struct notifier_block *notifier, switch (event) { case NETDEV_DOWN: iwdev->iw_status = 0; - /* Fall through */ + fallthrough; case NETDEV_UP: i40iw_port_ibevent(iwdev); break; diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c index 6957e4f3404b..b51339328a51 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -810,7 +810,7 @@ void i40iw_hw_modify_qp(struct i40iw_device *iwdev, struct i40iw_qp *iwqp, case I40IW_QP_STATE_RTS: if (iwqp->iwarp_state == I40IW_QP_STATE_IDLE) i40iw_send_reset(iwqp->cm_node); - /* fall through */ + fallthrough; case I40IW_QP_STATE_IDLE: case I40IW_QP_STATE_TERMINATE: case I40IW_QP_STATE_CLOSING: @@ -2144,7 +2144,6 @@ static int i40iw_post_send(struct ib_qp *ibqp, switch (ib_wr->opcode) { case IB_WR_SEND: - /* fall-through */ case IB_WR_SEND_WITH_INV: if (ib_wr->opcode == IB_WR_SEND) { if (ib_wr->send_flags & IB_SEND_SOLICITED) @@ -2201,7 +2200,7 @@ static int i40iw_post_send(struct ib_qp *ibqp, break; case IB_WR_RDMA_READ_WITH_INV: inv_stag = true; - /* fall-through*/ + fallthrough; case IB_WR_RDMA_READ: if (ib_wr->num_sge > I40IW_MAX_SGE_RD) { err = -EINVAL; diff --git a/drivers/infiniband/hw/mlx4/cq.c b/drivers/infiniband/hw/mlx4/cq.c index f8b936b76dcd..8a3436994f80 100644 --- a/drivers/infiniband/hw/mlx4/cq.c +++ b/drivers/infiniband/hw/mlx4/cq.c @@ -765,13 +765,13 @@ repoll: switch (cqe->owner_sr_opcode & MLX4_CQE_OPCODE_MASK) { case MLX4_OPCODE_RDMA_WRITE_IMM: wc->wc_flags |= IB_WC_WITH_IMM; - /* fall through */ + fallthrough; case MLX4_OPCODE_RDMA_WRITE: wc->opcode = IB_WC_RDMA_WRITE; break; case MLX4_OPCODE_SEND_IMM: wc->wc_flags |= IB_WC_WITH_IMM; - /* fall through */ + fallthrough; case MLX4_OPCODE_SEND: case MLX4_OPCODE_SEND_INVAL: wc->opcode = IB_WC_SEND; diff --git a/drivers/infiniband/hw/mlx4/mcg.c b/drivers/infiniband/hw/mlx4/mcg.c index d844831179cf..5e4ec9786081 100644 --- a/drivers/infiniband/hw/mlx4/mcg.c +++ b/drivers/infiniband/hw/mlx4/mcg.c @@ -944,7 +944,7 @@ int mlx4_ib_mcg_multiplex_handler(struct ib_device *ibdev, int port, switch (sa_mad->mad_hdr.method) { case IB_MGMT_METHOD_SET: may_create = 1; - /* fall through */ + fallthrough; case IB_SA_METHOD_DELETE: req = kzalloc(sizeof *req, GFP_KERNEL); if (!req) diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index f9ca6e000a81..2975f350b9fd 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -1578,12 +1578,12 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd, pd = to_mxrcd(init_attr->xrcd)->pd; xrcdn = to_mxrcd(init_attr->xrcd)->xrcdn; init_attr->send_cq = to_mxrcd(init_attr->xrcd)->cq; - /* fall through */ + fallthrough; case IB_QPT_XRC_INI: if (!(to_mdev(pd->device)->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) return ERR_PTR(-ENOSYS); init_attr->recv_cq = init_attr->send_cq; - /* fall through */ + fallthrough; case IB_QPT_RC: case IB_QPT_UC: case IB_QPT_RAW_PACKET: @@ -1592,7 +1592,7 @@ static struct ib_qp *_mlx4_ib_create_qp(struct ib_pd *pd, return ERR_PTR(-ENOMEM); qp->pri.vid = 0xFFFF; qp->alt.vid = 0xFFFF; - /* fall through */ + fallthrough; case IB_QPT_UD: { err = create_qp_common(pd, init_attr, udata, 0, &qp); diff --git a/drivers/infiniband/hw/mlx5/cq.c b/drivers/infiniband/hw/mlx5/cq.c index 0133ebb8d740..dceb0eb2bed1 100644 --- a/drivers/infiniband/hw/mlx5/cq.c +++ b/drivers/infiniband/hw/mlx5/cq.c @@ -121,13 +121,13 @@ static void handle_good_req(struct ib_wc *wc, struct mlx5_cqe64 *cqe, switch (be32_to_cpu(cqe->sop_drop_qpn) >> 24) { case MLX5_OPCODE_RDMA_WRITE_IMM: wc->wc_flags |= IB_WC_WITH_IMM; - /* fall through */ + fallthrough; case MLX5_OPCODE_RDMA_WRITE: wc->opcode = IB_WC_RDMA_WRITE; break; case MLX5_OPCODE_SEND_IMM: wc->wc_flags |= IB_WC_WITH_IMM; - /* fall through */ + fallthrough; case MLX5_OPCODE_SEND: case MLX5_OPCODE_SEND_INVAL: wc->opcode = IB_WC_SEND; diff --git a/drivers/infiniband/hw/mlx5/mad.c b/drivers/infiniband/hw/mlx5/mad.c index 454ce5de2de7..9bb9bb058932 100644 --- a/drivers/infiniband/hw/mlx5/mad.c +++ b/drivers/infiniband/hw/mlx5/mad.c @@ -250,9 +250,8 @@ int mlx5_ib_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, if (MLX5_CAP_GEN(dev->mdev, vport_counters) && method == IB_MGMT_METHOD_GET) return process_pma_cmd(dev, port_num, in, out); - /* fallthrough */ + fallthrough; case MLX5_IB_VENDOR_CLASS1: - /* fallthrough */ case MLX5_IB_VENDOR_CLASS2: case IB_MGMT_CLASS_CONG_MGMT: { if (method != IB_MGMT_METHOD_GET && diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index fbc45a5e76c5..d60d63221b14 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -2872,7 +2872,7 @@ static void mlx5_ib_handle_event(struct work_struct *_work) break; case MLX5_EVENT_TYPE_GENERAL_EVENT: handle_general_event(ibdev, work->param, &ibev); - /* fall through */ + fallthrough; default: goto out; } diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 59fce5fac7a3..5758dbe64045 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -416,7 +416,7 @@ static int sq_overhead(struct ib_qp_init_attr *attr) switch (attr->qp_type) { case IB_QPT_XRC_INI: size += sizeof(struct mlx5_wqe_xrc_seg); - /* fall through */ + fallthrough; case IB_QPT_RC: size += sizeof(struct mlx5_wqe_ctrl_seg) + max(sizeof(struct mlx5_wqe_atomic_seg) + @@ -441,7 +441,7 @@ static int sq_overhead(struct ib_qp_init_attr *attr) if (attr->create_flags & IB_QP_CREATE_IPOIB_UD_LSO) size += sizeof(struct mlx5_wqe_eth_pad) + sizeof(struct mlx5_wqe_eth_seg); - /* fall through */ + fallthrough; case IB_QPT_SMI: case MLX5_IB_QPT_HW_GSI: size += sizeof(struct mlx5_wqe_ctrl_seg) + diff --git a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c index 0823c0bc7e73..f051f4e06b53 100644 --- a/drivers/infiniband/hw/mthca/mthca_av.c +++ b/drivers/infiniband/hw/mthca/mthca_av.c @@ -115,7 +115,7 @@ static u8 ib_rate_to_memfree(u8 req_rate, u8 cur_rate) switch ((cur_rate - 1) / req_rate) { case 0: return MTHCA_RATE_MEMFREE_FULL; case 1: return MTHCA_RATE_MEMFREE_HALF; - case 2: /* fall through */ + case 2: case 3: return MTHCA_RATE_MEMFREE_QUARTER; default: return MTHCA_RATE_MEMFREE_EIGHTH; } diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index 6cdbec13756a..c1751c9a0f62 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -2134,7 +2134,7 @@ int ocrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, case IB_WR_SEND_WITH_IMM: hdr->cw |= (OCRDMA_FLAG_IMM << OCRDMA_WQE_FLAGS_SHIFT); hdr->immdt = ntohl(wr->ex.imm_data); - /* fall through */ + fallthrough; case IB_WR_SEND: hdr->cw |= (OCRDMA_SEND << OCRDMA_WQE_OPCODE_SHIFT); ocrdma_build_send(qp, hdr, wr); @@ -2148,7 +2148,7 @@ int ocrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, case IB_WR_RDMA_WRITE_WITH_IMM: hdr->cw |= (OCRDMA_FLAG_IMM << OCRDMA_WQE_FLAGS_SHIFT); hdr->immdt = ntohl(wr->ex.imm_data); - /* fall through */ + fallthrough; case IB_WR_RDMA_WRITE: hdr->cw |= (OCRDMA_WRITE << OCRDMA_WQE_OPCODE_SHIFT); status = ocrdma_build_write(qp, hdr, wr); diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 4ce4e2eef6cc..b49bef94637e 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -3528,7 +3528,7 @@ static int __qedr_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, break; case IB_WR_RDMA_READ_WITH_INV: SET_FIELD2(wqe->flags, RDMA_SQ_RDMA_WQE_1ST_READ_INV_FLG, 1); - /* fallthrough -- same is identical to RDMA READ */ + fallthrough; /* same is identical to RDMA READ */ case IB_WR_RDMA_READ: wqe->req_type = RDMA_SQ_REQ_TYPE_RDMA_RD; diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index ca5ea734e3d0..44150be215bf 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c @@ -2973,11 +2973,11 @@ static u32 qib_6120_iblink_state(u64 ibcs) state = IB_PORT_ARMED; break; case IB_6120_L_STATE_ACTIVE: - /* fall through */ case IB_6120_L_STATE_ACT_DEFER: state = IB_PORT_ACTIVE; break; - default: /* fall through */ + default: + fallthrough; case IB_6120_L_STATE_DOWN: state = IB_PORT_DOWN; break; diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c index ea3ddb05cbad..0a6f26d4cb31 100644 --- a/drivers/infiniband/hw/qib/qib_iba7220.c +++ b/drivers/infiniband/hw/qib/qib_iba7220.c @@ -3586,11 +3586,11 @@ static u32 qib_7220_iblink_state(u64 ibcs) state = IB_PORT_ARMED; break; case IB_7220_L_STATE_ACTIVE: - /* fall through */ case IB_7220_L_STATE_ACT_DEFER: state = IB_PORT_ACTIVE; break; - default: /* fall through */ + default: + fallthrough; case IB_7220_L_STATE_DOWN: state = IB_PORT_DOWN; break; diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 8bcbc884e5b6..a10eab89aee4 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c @@ -5508,11 +5508,11 @@ static u32 qib_7322_iblink_state(u64 ibcs) state = IB_PORT_ARMED; break; case IB_7322_L_STATE_ACTIVE: - /* fall through */ case IB_7322_L_STATE_ACT_DEFER: state = IB_PORT_ACTIVE; break; - default: /* fall through */ + default: + fallthrough; case IB_7322_L_STATE_DOWN: state = IB_PORT_DOWN; break; @@ -6533,7 +6533,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd) "Invalid num_vls %u, using 4 VLs\n", qib_num_cfg_vls); qib_num_cfg_vls = 4; - /* fall through */ + fallthrough; case 4: ppd->vls_supported = IB_VL_VL0_3; break; diff --git a/drivers/infiniband/hw/qib/qib_mad.c b/drivers/infiniband/hw/qib/qib_mad.c index 79bb83222e8d..e7789e724f56 100644 --- a/drivers/infiniband/hw/qib/qib_mad.c +++ b/drivers/infiniband/hw/qib/qib_mad.c @@ -433,7 +433,7 @@ static int check_mkey(struct qib_ibport *ibp, struct ib_smp *smp, int mad_flags) /* Bad mkey not a violation below level 2 */ if (ibp->rvp.mkeyprot < 2) break; - /* fall through */ + fallthrough; case IB_MGMT_METHOD_SET: case IB_MGMT_METHOD_TRAP_REPRESS: if (ibp->rvp.mkey_violations != 0xFFFF) @@ -828,7 +828,7 @@ static int subn_set_portinfo(struct ib_smp *smp, struct ib_device *ibdev, case IB_PORT_NOP: if (lstate == 0) break; - /* FALLTHROUGH */ + fallthrough; case IB_PORT_DOWN: if (lstate == 0) lstate = QIB_IB_LINKDOWN_ONLY; @@ -1928,7 +1928,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags, ret = IB_MAD_RESULT_SUCCESS; goto bail; } - /* FALLTHROUGH */ + fallthrough; default: smp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply(smp); @@ -1962,7 +1962,7 @@ static int process_subn(struct ib_device *ibdev, int mad_flags, ret = IB_MAD_RESULT_SUCCESS; goto bail; } - /* FALLTHROUGH */ + fallthrough; default: smp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply(smp); @@ -2322,7 +2322,7 @@ static int process_cc(struct ib_device *ibdev, int mad_flags, ret = cc_get_congestion_control_table(ccp, ibdev, port); goto bail; - /* FALLTHROUGH */ + fallthrough; default: ccp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply((struct ib_smp *) ccp); @@ -2339,7 +2339,7 @@ static int process_cc(struct ib_device *ibdev, int mad_flags, ret = cc_set_congestion_control_table(ccp, ibdev, port); goto bail; - /* FALLTHROUGH */ + fallthrough; default: ccp->status |= IB_SMP_UNSUP_METH_ATTR; ret = reply((struct ib_smp *) ccp); diff --git a/drivers/infiniband/hw/qib/qib_rc.c b/drivers/infiniband/hw/qib/qib_rc.c index aaf7438258fa..3915e5b4a9bc 100644 --- a/drivers/infiniband/hw/qib/qib_rc.c +++ b/drivers/infiniband/hw/qib/qib_rc.c @@ -83,7 +83,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct rvt_qp *qp, rvt_put_mr(e->rdma_sge.mr); e->rdma_sge.mr = NULL; } - /* FALLTHROUGH */ + fallthrough; case OP(ATOMIC_ACKNOWLEDGE): /* * We can increment the tail pointer now that the last @@ -92,7 +92,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct rvt_qp *qp, */ if (++qp->s_tail_ack_queue > QIB_MAX_RDMA_ATOMIC) qp->s_tail_ack_queue = 0; - /* FALLTHROUGH */ + fallthrough; case OP(SEND_ONLY): case OP(ACKNOWLEDGE): /* Check for no next entry in the queue. */ @@ -149,7 +149,7 @@ static int qib_make_rc_ack(struct qib_ibdev *dev, struct rvt_qp *qp, case OP(RDMA_READ_RESPONSE_FIRST): qp->s_ack_state = OP(RDMA_READ_RESPONSE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_READ_RESPONSE_MIDDLE): qp->s_cur_sge = &qp->s_ack_rdma_sge; qp->s_rdma_mr = qp->s_ack_rdma_sge.sge.mr; @@ -471,10 +471,10 @@ no_flow_control: * See qib_restart_rc(). */ qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_FIRST): qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): bth2 = qp->s_psn++ & QIB_PSN_MASK; ss = &qp->s_sge; @@ -510,10 +510,10 @@ no_flow_control: * See qib_restart_rc(). */ qp->s_len = restart_sge(&qp->s_sge, wqe, qp->s_psn, pmtu); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_FIRST): qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): bth2 = qp->s_psn++ & QIB_PSN_MASK; ss = &qp->s_sge; @@ -1807,7 +1807,7 @@ void qib_rc_rcv(struct qib_ctxtdata *rcd, struct ib_header *hdr, if (!ret) goto rnr_nak; qp->r_rcv_len = 0; - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): case OP(RDMA_WRITE_MIDDLE): send_middle: @@ -1839,7 +1839,7 @@ send_middle: qp->r_rcv_len = 0; if (opcode == OP(SEND_ONLY)) goto no_immediate_data; - /* fall through -- for SEND_ONLY_WITH_IMMEDIATE */ + fallthrough; /* for SEND_ONLY_WITH_IMMEDIATE */ case OP(SEND_LAST_WITH_IMMEDIATE): send_last_imm: wc.ex.imm_data = ohdr->u.imm_data; diff --git a/drivers/infiniband/hw/qib/qib_sdma.c b/drivers/infiniband/hw/qib/qib_sdma.c index 99e11c347130..8f8d61736656 100644 --- a/drivers/infiniband/hw/qib/qib_sdma.c +++ b/drivers/infiniband/hw/qib/qib_sdma.c @@ -763,7 +763,7 @@ void __qib_sdma_process_event(struct qib_pportdata *ppd, * bringing the link up with traffic active on * 7220, e.g. */ ss->go_s99_running = 1; - /* fall through -- and start dma engine */ + fallthrough; /* and start dma engine */ case qib_sdma_event_e10_go_hw_start: /* This reference means the state machine is started */ sdma_get(&ppd->sdma_state); diff --git a/drivers/infiniband/hw/qib/qib_uc.c b/drivers/infiniband/hw/qib/qib_uc.c index e17b91e2c22a..554af4273a13 100644 --- a/drivers/infiniband/hw/qib/qib_uc.c +++ b/drivers/infiniband/hw/qib/qib_uc.c @@ -161,7 +161,7 @@ int qib_make_uc_req(struct rvt_qp *qp, unsigned long *flags) case OP(SEND_FIRST): qp->s_state = OP(SEND_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): len = qp->s_len; if (len > pmtu) { @@ -185,7 +185,7 @@ int qib_make_uc_req(struct rvt_qp *qp, unsigned long *flags) case OP(RDMA_WRITE_FIRST): qp->s_state = OP(RDMA_WRITE_MIDDLE); - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): len = qp->s_len; if (len > pmtu) { @@ -351,7 +351,7 @@ send_first: goto no_immediate_data; else if (opcode == OP(SEND_ONLY_WITH_IMMEDIATE)) goto send_last_imm; - /* FALLTHROUGH */ + fallthrough; case OP(SEND_MIDDLE): /* Check for invalid length PMTU or posted rwqe len. */ if (unlikely(tlen != (hdrsize + pmtu + 4))) @@ -440,7 +440,7 @@ rdma_first: wc.ex.imm_data = ohdr->u.rc.imm_data; goto rdma_last_imm; } - /* FALLTHROUGH */ + fallthrough; case OP(RDMA_WRITE_MIDDLE): /* Check for invalid length PMTU or posted rwqe len. */ if (unlikely(tlen != (hdrsize + pmtu + 4))) diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 7acf9ba5358a..f6c01bad5a74 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -237,7 +237,7 @@ static void qib_qp_rcv(struct qib_ctxtdata *rcd, struct ib_header *hdr, case IB_QPT_GSI: if (ib_qib_disable_sma) break; - /* FALLTHROUGH */ + fallthrough; case IB_QPT_UD: qib_ud_rcv(ibp, hdr, has_grh, data, tlen, qp); break; diff --git a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c index afcc2abcf55c..9a8f2a9507be 100644 --- a/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c +++ b/drivers/infiniband/hw/vmw_pvrdma/pvrdma_qp.c @@ -238,7 +238,7 @@ struct ib_qp *pvrdma_create_qp(struct ib_pd *pd, ret = -EINVAL; goto err_qp; } - /* fall through */ + fallthrough; case IB_QPT_RC: case IB_QPT_UD: qp = kzalloc(sizeof(*qp), GFP_KERNEL); diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 332a8ba94b81..ee48befc8978 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -1111,7 +1111,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd, if (init_attr->port_num == 0 || init_attr->port_num > ibpd->device->phys_port_cnt) return ERR_PTR(-EINVAL); - /* fall through */ + fallthrough; case IB_QPT_UC: case IB_QPT_RC: case IB_QPT_UD: diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index 4bc88708b355..7b4df0028388 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -282,7 +282,7 @@ static inline enum comp_state check_ack(struct rxe_qp *qp, if ((syn & AETH_TYPE_MASK) != AETH_ACK) return COMPST_ERROR; - /* fall through */ + fallthrough; /* (IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE doesn't have an AETH) */ case IB_OPCODE_RC_RDMA_READ_RESPONSE_MIDDLE: diff --git a/drivers/infiniband/sw/rxe/rxe_task.c b/drivers/infiniband/sw/rxe/rxe_task.c index 08f05ac5f5d5..ecdac3f8fcc9 100644 --- a/drivers/infiniband/sw/rxe/rxe_task.c +++ b/drivers/infiniband/sw/rxe/rxe_task.c @@ -71,7 +71,7 @@ void rxe_do_task(unsigned long data) case TASK_STATE_BUSY: task->state = TASK_STATE_ARMED; - /* fall through */ + fallthrough; case TASK_STATE_ARMED: spin_unlock_irqrestore(&task->state_lock, flags); return; diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index bb61e534e468..658939e5c34a 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -540,7 +540,7 @@ static void init_send_wr(struct rxe_qp *qp, struct rxe_send_wr *wr, switch (wr->opcode) { case IB_WR_RDMA_WRITE_WITH_IMM: wr->ex.imm_data = ibwr->ex.imm_data; - /* fall through */ + fallthrough; case IB_WR_RDMA_READ: case IB_WR_RDMA_WRITE: wr->wr.rdma.remote_addr = rdma_wr(ibwr)->remote_addr; diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c index 1662216be66d..66764f7ef072 100644 --- a/drivers/infiniband/sw/siw/siw_cm.c +++ b/drivers/infiniband/sw/siw/siw_cm.c @@ -1224,12 +1224,10 @@ static void siw_cm_llp_data_ready(struct sock *sk) switch (cep->state) { case SIW_EPSTATE_RDMA_MODE: - /* fall through */ case SIW_EPSTATE_LISTENING: break; case SIW_EPSTATE_AWAIT_MPAREQ: - /* fall through */ case SIW_EPSTATE_AWAIT_MPAREP: siw_cm_queue_work(cep, SIW_CM_WORK_READ_MPAHDR); break; diff --git a/drivers/infiniband/sw/siw/siw_qp_rx.c b/drivers/infiniband/sw/siw/siw_qp_rx.c index 857be5a7d0bd..4bd1f1f84057 100644 --- a/drivers/infiniband/sw/siw/siw_qp_rx.c +++ b/drivers/infiniband/sw/siw/siw_qp_rx.c @@ -1215,7 +1215,7 @@ static int siw_rdmap_complete(struct siw_qp *qp, int error) case RDMAP_SEND_SE: case RDMAP_SEND_SE_INVAL: wqe->rqe.flags |= SIW_WQE_SOLICITED; - /* Fall through */ + fallthrough; case RDMAP_SEND: case RDMAP_SEND_INVAL: @@ -1386,7 +1386,7 @@ int siw_tcp_rx_data(read_descriptor_t *rd_desc, struct sk_buff *skb, * DDP segment. */ qp->rx_fpdu->first_ddp_seg = 0; - /* Fall through */ + fallthrough; case SIW_GET_DATA_START: /* diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c index 9f53aa4feb87..d19d8325588b 100644 --- a/drivers/infiniband/sw/siw/siw_qp_tx.c +++ b/drivers/infiniband/sw/siw/siw_qp_tx.c @@ -1042,7 +1042,7 @@ next_wqe: case SIW_OP_SEND_REMOTE_INV: case SIW_OP_WRITE: siw_wqe_put_mem(wqe, tx_type); - /* Fall through */ + fallthrough; case SIW_OP_INVAL_STAG: case SIW_OP_REG_MR: @@ -1128,7 +1128,7 @@ next_wqe: case SIW_OP_READ: case SIW_OP_READ_LOCAL_INV: siw_wqe_put_mem(wqe, tx_type); - /* Fall through */ + fallthrough; case SIW_OP_INVAL_STAG: case SIW_OP_REG_MR: diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 9bf0fa30df28..7c41fb040f7c 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -512,13 +512,13 @@ static int ipoib_cm_rx_handler(struct ib_cm_id *cm_id, return ipoib_cm_req_handler(cm_id, event); case IB_CM_DREQ_RECEIVED: ib_send_cm_drep(cm_id, NULL, 0); - /* Fall through */ + fallthrough; case IB_CM_REJ_RECEIVED: p = cm_id->context; priv = ipoib_priv(p->dev); if (ib_modify_qp(p->qp, &ipoib_cm_err_attr, IB_QP_STATE)) ipoib_warn(priv, "unable to move qp to error state\n"); - /* Fall through */ + fallthrough; default: return 0; } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 752581a8627b..ab75b7f745d4 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -502,7 +502,7 @@ static struct net_device *ipoib_get_net_dev_by_params( default: dev_warn_ratelimited(&dev->dev, "duplicate IP address detected\n"); - /* Fall through */ + fallthrough; case 1: return net_dev; } diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 699e075ae1b3..2f3ebc0a75d9 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -711,7 +711,7 @@ static int iser_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *eve case RDMA_CM_EVENT_REJECTED: iser_info("Connection rejected: %s\n", rdma_reject_msg(cma_id, event->status)); - /* FALLTHROUGH */ + fallthrough; case RDMA_CM_EVENT_ADDR_ERROR: case RDMA_CM_EVENT_ROUTE_ERROR: case RDMA_CM_EVENT_CONNECT_ERROR: diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 61e2f7fc513d..e86acda3cf8c 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -664,8 +664,8 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) case RDMA_CM_EVENT_ESTABLISHED: isert_connected_handler(cma_id); break; - case RDMA_CM_EVENT_ADDR_CHANGE: /* FALLTHRU */ - case RDMA_CM_EVENT_DISCONNECTED: /* FALLTHRU */ + case RDMA_CM_EVENT_ADDR_CHANGE: + case RDMA_CM_EVENT_DISCONNECTED: case RDMA_CM_EVENT_TIMEWAIT_EXIT: /* FALLTHRU */ ret = isert_disconnected_handler(cma_id, event->event); break; @@ -684,7 +684,7 @@ isert_cma_handler(struct rdma_cm_id *cma_id, struct rdma_cm_event *event) case RDMA_CM_EVENT_REJECTED: isert_info("Connection rejected: %s\n", rdma_reject_msg(cma_id, event->status)); - /* fall through */ + fallthrough; case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_CONNECT_ERROR: ret = isert_connect_error(cma_id); @@ -1470,7 +1470,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) transport_generic_free_cmd(&cmd->se_cmd, 0); break; } - /* fall through */ + fallthrough; default: iscsit_release_cmd(cmd); break; @@ -1648,7 +1648,7 @@ isert_do_control_comp(struct work_struct *work) switch (cmd->i_state) { case ISTATE_SEND_TASKMGTRSP: iscsit_tmr_post_handler(cmd, cmd->conn); - /* fall through */ + fallthrough; case ISTATE_SEND_REJECT: case ISTATE_SEND_TEXTRSP: cmd->i_state = ISTATE_SENT_STATUS; diff --git a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c index 874a8eb7638c..4933085a864a 100644 --- a/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c +++ b/drivers/infiniband/ulp/opa_vnic/opa_vnic_vema.c @@ -547,7 +547,6 @@ static void vema_get(struct opa_vnic_vema_port *port, vema_get_mac_entries(port, recvd_mad, rsp_mad); break; case OPA_EM_ATTR_IFACE_UCAST_MACS: - /* fall through */ case OPA_EM_ATTR_IFACE_MCAST_MACS: vema_get_mac_list(port, recvd_mad, rsp_mad, attr_id); break; diff --git a/drivers/input/joystick/fsia6b.c b/drivers/input/joystick/fsia6b.c index e78c4c768990..76ffdec5c183 100644 --- a/drivers/input/joystick/fsia6b.c +++ b/drivers/input/joystick/fsia6b.c @@ -102,12 +102,12 @@ static irqreturn_t fsia6b_serio_irq(struct serio *serio, input_report_key(fsia6b->dev, sw_id++, sw_state == 0); - /* fall-through */ + fallthrough; case '2': input_report_key(fsia6b->dev, sw_id++, sw_state == 1); - /* fall-through */ + fallthrough; case '1': input_report_key(fsia6b->dev, sw_id++, diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index 88df68cc4ac6..d37645e496ff 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -885,7 +885,6 @@ static int gc_setup_pad(struct gc *gc, int idx, int pad_type) case GC_MULTI: input_set_capability(input_dev, EV_KEY, BTN_TRIGGER); - /* fall through */ break; case GC_PSX: diff --git a/drivers/input/tablet/wacom_serial4.c b/drivers/input/tablet/wacom_serial4.c index 959c1d82aa66..1cedb45ba497 100644 --- a/drivers/input/tablet/wacom_serial4.c +++ b/drivers/input/tablet/wacom_serial4.c @@ -213,7 +213,7 @@ static void wacom_handle_model_response(struct wacom *wacom) case 0x3731: /* PL-710 */ wacom->res_x = 2540; wacom->res_y = 2540; - /* fall through */ + fallthrough; case 0x3535: /* PL-550 */ case 0x3830: /* PL-800 */ wacom->extra_z_bits = 2; diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 6b71b0aff115..98f17fa3a892 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c @@ -477,7 +477,7 @@ static int mxt_lookup_bootloader_address(struct mxt_data *data, bool retry) bootloader = appmode - 0x24; break; } - /* Fall through - for normal case */ + fallthrough; /* for normal case */ case 0x4c: case 0x4d: case 0x5a: diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 607d1aeb595d..bb1699e0d3c7 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c @@ -290,7 +290,7 @@ static int wm831x_ts_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n", pdata->isel); - /* Fall through */ + fallthrough; case 200: case 0: wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2, diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 958050c213f9..c652f16eb702 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -2258,7 +2258,7 @@ static void iommu_enable_ga(struct amd_iommu *iommu) switch (amd_iommu_guest_ir) { case AMD_IOMMU_GUEST_IR_VAPIC: iommu_feature_enable(iommu, CONTROL_GAM_EN); - /* Fall through */ + fallthrough; case AMD_IOMMU_GUEST_IR_LEGACY_GA: iommu_feature_enable(iommu, CONTROL_GA_EN); iommu->irte_ops = &irte_128_ops; diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c index 7196207be7ea..c192544e874b 100644 --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c @@ -903,7 +903,7 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) break; case CMDQ_OP_CFGI_CD: cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SSID, ent->cfgi.ssid); - /* Fallthrough */ + fallthrough; case CMDQ_OP_CFGI_STE: cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid); cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_LEAF, ent->cfgi.leaf); @@ -936,7 +936,7 @@ static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent) break; case CMDQ_OP_TLBI_NH_ASID: cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid); - /* Fallthrough */ + fallthrough; case CMDQ_OP_TLBI_S12_VMALL: cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid); break; @@ -1036,7 +1036,6 @@ static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu) */ return; case CMDQ_ERR_CERROR_ILL_IDX: - /* Fallthrough */ default: break; } @@ -3758,7 +3757,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) switch (FIELD_GET(IDR0_STALL_MODEL, reg)) { case IDR0_STALL_MODEL_FORCE: smmu->features |= ARM_SMMU_FEAT_STALL_FORCE; - /* Fallthrough */ + fallthrough; case IDR0_STALL_MODEL_STALL: smmu->features |= ARM_SMMU_FEAT_STALLS; } @@ -3778,7 +3777,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) switch (FIELD_GET(IDR0_TTF, reg)) { case IDR0_TTF_AARCH32_64: smmu->ias = 40; - /* Fallthrough */ + fallthrough; case IDR0_TTF_AARCH64: break; default: @@ -3875,7 +3874,7 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) default: dev_info(smmu->dev, "unknown output address size. Truncating to 48-bit\n"); - /* Fallthrough */ + fallthrough; case IDR5_OAS_48_BIT: smmu->oas = 48; } diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index e9864e52b0e9..f8177c59d229 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -5070,7 +5070,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type) switch (type) { case IOMMU_DOMAIN_DMA: - /* fallthrough */ case IOMMU_DOMAIN_UNMANAGED: dmar_domain = alloc_domain(0); if (!dmar_domain) { diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c index b4da396cce60..2bfdd5734844 100644 --- a/drivers/iommu/virtio-iommu.c +++ b/drivers/iommu/virtio-iommu.c @@ -440,7 +440,7 @@ static int viommu_add_resv_mem(struct viommu_endpoint *vdev, default: dev_warn(vdev->dev, "unknown resv mem subtype 0x%x\n", mem->subtype); - /* Fall-through */ + fallthrough; case VIRTIO_IOMMU_RESV_MEM_T_RESERVED: region = iommu_alloc_resv_region(start, size, 0, IOMMU_RESV_RESERVED); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 95f097448f97..548de7538632 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2737,7 +2737,7 @@ static bool allocate_vpe_l2_table(int cpu, u32 id) switch (gpsz) { default: WARN_ON(1); - /* fall through */ + fallthrough; case GIC_PAGE_SIZE_4K: psz = SZ_4K; break; @@ -2832,7 +2832,7 @@ static int allocate_vpe_l1_table(void) switch (gpsz) { default: gpsz = GIC_PAGE_SIZE_4K; - /* fall through */ + fallthrough; case GIC_PAGE_SIZE_4K: psz = SZ_4K; break; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 324f280ff606..850842f27bee 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -965,10 +965,10 @@ static void gic_cpu_sys_reg_init(void) case 7: write_gicreg(0, ICC_AP0R3_EL1); write_gicreg(0, ICC_AP0R2_EL1); - /* Fall through */ + fallthrough; case 6: write_gicreg(0, ICC_AP0R1_EL1); - /* Fall through */ + fallthrough; case 5: case 4: write_gicreg(0, ICC_AP0R0_EL1); @@ -982,10 +982,10 @@ static void gic_cpu_sys_reg_init(void) case 7: write_gicreg(0, ICC_AP1R3_EL1); write_gicreg(0, ICC_AP1R2_EL1); - /* Fall through */ + fallthrough; case 6: write_gicreg(0, ICC_AP1R1_EL1); - /* Fall through */ + fallthrough; case 5: case 4: write_gicreg(0, ICC_AP1R0_EL1); diff --git a/drivers/irqchip/irq-imx-gpcv2.c b/drivers/irqchip/irq-imx-gpcv2.c index 4f74c15c4755..7031ef44de4f 100644 --- a/drivers/irqchip/irq-imx-gpcv2.c +++ b/drivers/irqchip/irq-imx-gpcv2.c @@ -259,7 +259,7 @@ static int __init imx_gpcv2_irqchip_init(struct device_node *node, case 4: writel_relaxed(~0, reg + GPC_IMR1_CORE2); writel_relaxed(~0, reg + GPC_IMR1_CORE3); - /* fall through */ + fallthrough; case 2: writel_relaxed(~0, reg + GPC_IMR1_CORE0); writel_relaxed(~0, reg + GPC_IMR1_CORE1); diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index aacfa012c082..215885962bb0 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -480,7 +480,7 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, case GIC_LOCAL_INT_TIMER: /* CONFIG_MIPS_CMP workaround (see __gic_init) */ map = GIC_MAP_PIN_MAP_TO_PIN | timer_cpu_pin; - /* fall-through */ + fallthrough; case GIC_LOCAL_INT_PERFCTR: case GIC_LOCAL_INT_FDC: /* diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c index bc235db8a4c5..e46036374227 100644 --- a/drivers/irqchip/irq-vic.c +++ b/drivers/irqchip/irq-vic.c @@ -455,7 +455,7 @@ static void __init __vic_init(void __iomem *base, int parent_irq, int irq_start, return; default: printk(KERN_WARNING "VIC: unknown vendor, continuing anyways\n"); - /* fall through */ + fallthrough; case AMBA_VENDOR_ARM: break; } diff --git a/drivers/isdn/hardware/mISDN/avmfritz.c b/drivers/isdn/hardware/mISDN/avmfritz.c index ecc1ef6c386d..f68569bfef7a 100644 --- a/drivers/isdn/hardware/mISDN/avmfritz.c +++ b/drivers/isdn/hardware/mISDN/avmfritz.c @@ -348,7 +348,7 @@ modehdlc(struct bchannel *bch, int protocol) switch (protocol) { case -1: /* used for init */ bch->state = -1; - /* fall through */ + fallthrough; case ISDN_P_NONE: if (bch->state == ISDN_P_NONE) break; diff --git a/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h b/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h index b0d772340e16..448ded8f9d24 100644 --- a/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h +++ b/drivers/isdn/hardware/mISDN/hfc_multi_8xx.h @@ -121,7 +121,6 @@ setup_embedded(struct hfc_multi *hc, struct hm_map *m) case HFC_IO_MODE_EMBSD: test_and_set_bit(HFC_CHIP_EMBSD, &hc->chip); hc->slots = 128; /* required */ - /* fall through */ hc->HFC_outb = HFC_outb_embsd; hc->HFC_inb = HFC_inb_embsd; hc->HFC_inw = HFC_inw_embsd; diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 904a4f4c5ff9..56bd2e9db6ed 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -1280,7 +1280,7 @@ mode_hfcpci(struct bchannel *bch, int bc, int protocol) case (-1): /* used for init */ bch->state = -1; bch->nr = bc; - /* fall through */ + fallthrough; case (ISDN_P_NONE): if (bch->state == ISDN_P_NONE) return 0; diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.c b/drivers/isdn/hardware/mISDN/hfcsusb.c index 4274906f8654..70061991915a 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.c +++ b/drivers/isdn/hardware/mISDN/hfcsusb.c @@ -695,7 +695,7 @@ hfcsusb_setup_bch(struct bchannel *bch, int protocol) switch (protocol) { case (-1): /* used for init */ bch->state = -1; - /* fall through */ + fallthrough; case (ISDN_P_NONE): if (bch->state == ISDN_P_NONE) return 0; /* already in idle state */ diff --git a/drivers/isdn/hardware/mISDN/isdnhdlc.c b/drivers/isdn/hardware/mISDN/isdnhdlc.c index 9fea16ed3dd8..985367e6711d 100644 --- a/drivers/isdn/hardware/mISDN/isdnhdlc.c +++ b/drivers/isdn/hardware/mISDN/isdnhdlc.c @@ -397,7 +397,7 @@ int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const u8 *src, u16 slen, dsize--; break; } - /* fall through */ + fallthrough; case HDLC_SENDFLAG_ONE: if (hdlc->bit_shift == 8) { hdlc->cbin = hdlc->ffvalue >> diff --git a/drivers/isdn/hardware/mISDN/mISDNinfineon.c b/drivers/isdn/hardware/mISDN/mISDNinfineon.c index f4cb29766888..a16c7a2a7f3d 100644 --- a/drivers/isdn/hardware/mISDN/mISDNinfineon.c +++ b/drivers/isdn/hardware/mISDN/mISDNinfineon.c @@ -875,7 +875,7 @@ release_card(struct inf_hw *card) { release_card(card->sc[i]); card->sc[i] = NULL; } - /* fall through */ + fallthrough; default: pci_disable_device(card->pdev); pci_set_drvdata(card->pdev, NULL); diff --git a/drivers/isdn/hardware/mISDN/mISDNisar.c b/drivers/isdn/hardware/mISDN/mISDNisar.c index 11e8c7d8b6e8..56943409b60d 100644 --- a/drivers/isdn/hardware/mISDN/mISDNisar.c +++ b/drivers/isdn/hardware/mISDN/mISDNisar.c @@ -957,7 +957,7 @@ isar_pump_statev_fax(struct isar_ch *ch, u8 devt) { break; case PCTRL_CMD_FTM: p1 = 2; - /* fall through */ + fallthrough; case PCTRL_CMD_FTH: send_mbox(ch->is, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_SILON, 1, &p1); @@ -1163,7 +1163,7 @@ setup_pump(struct isar_ch *ch) { send_mbox(ch->is, dps | ISAR_HIS_PUMPCFG, PMOD_DTMF, 1, param); } - /* fall through */ + fallthrough; case ISDN_P_B_MODEM_ASYNC: ctrl = PMOD_DATAMODEM; if (test_bit(FLG_ORIGIN, &ch->bch.Flags)) { @@ -1255,7 +1255,7 @@ setup_iom2(struct isar_ch *ch) { case ISDN_P_B_MODEM_ASYNC: case ISDN_P_B_T30_FAX: cmsb |= IOM_CTRL_RCV; - /* fall through */ + fallthrough; case ISDN_P_B_L2DTMF: if (test_bit(FLG_DTMFSEND, &ch->bch.Flags)) cmsb |= IOM_CTRL_RCV; @@ -1548,7 +1548,7 @@ isar_l2l1(struct mISDNchannel *ch, struct sk_buff *skb) ich->is->name, hh->id); ret = -EINVAL; } - /* fall through */ + fallthrough; default: pr_info("%s: %s unknown prim(%x,%x)\n", ich->is->name, __func__, hh->prim, hh->id); diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index 27aa32914425..c2f76f398613 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c @@ -528,7 +528,7 @@ create_l2entity(struct mISDNdevice *dev, struct mISDNchannel *ch, rq.protocol = ISDN_P_NT_S0; if (dev->Dprotocols & (1 << ISDN_P_NT_E1)) rq.protocol = ISDN_P_NT_E1; - /* fall through */ + fallthrough; case ISDN_P_LAPD_TE: ch->recv = mISDN_queue_message; ch->peer = &dev->D.st->own; diff --git a/drivers/lightnvm/pblk-core.c b/drivers/lightnvm/pblk-core.c index b413bafe93fd..97c68731406b 100644 --- a/drivers/lightnvm/pblk-core.c +++ b/drivers/lightnvm/pblk-core.c @@ -301,7 +301,7 @@ void pblk_free_rqd(struct pblk *pblk, struct nvm_rq *rqd, int type) switch (type) { case PBLK_WRITE: kfree(((struct pblk_c_ctx *)nvm_rq_to_pdu(rqd))->lun_bitmap); - /* fall through */ + fallthrough; case PBLK_WRITE_INT: pool = &pblk->w_rq_pool; break; diff --git a/drivers/macintosh/adbhid.c b/drivers/macintosh/adbhid.c index 75482eeab2c4..994ba5cb3678 100644 --- a/drivers/macintosh/adbhid.c +++ b/drivers/macintosh/adbhid.c @@ -881,7 +881,7 @@ adbhid_input_register(int id, int default_id, int original_handler_id, } if (hid->name[0]) break; - /* else fall through */ + fallthrough; default: pr_info("Trying to register unknown ADB device to input layer.\n"); diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index 23f1f41c8602..96684581a25d 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -852,7 +852,7 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) break; case SMU_I2C_TRANSFER_COMBINED: cmd->info.devaddr &= 0xfe; - /* fall through */ + fallthrough; case SMU_I2C_TRANSFER_STDSUB: if (cmd->info.sublen > 3) return -EINVAL; diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 77fbfd52edcf..c1227bdb57e7 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -608,7 +608,7 @@ static void do_journal_discard(struct cache *ca) ca->sb.njournal_buckets; atomic_set(&ja->discard_in_flight, DISCARD_READY); - /* fallthrough */ + fallthrough; case DISCARD_READY: if (ja->discard_idx == ja->last_idx) diff --git a/drivers/md/bcache/util.c b/drivers/md/bcache/util.c index 62fb917f7a4f..ae380bc3992e 100644 --- a/drivers/md/bcache/util.c +++ b/drivers/md/bcache/util.c @@ -33,27 +33,27 @@ int bch_ ## name ## _h(const char *cp, type *res) \ case 'y': \ case 'z': \ u++; \ - /* fall through */ \ + fallthrough; \ case 'e': \ u++; \ - /* fall through */ \ + fallthrough; \ case 'p': \ u++; \ - /* fall through */ \ + fallthrough; \ case 't': \ u++; \ - /* fall through */ \ + fallthrough; \ case 'g': \ u++; \ - /* fall through */ \ + fallthrough; \ case 'm': \ u++; \ - /* fall through */ \ + fallthrough; \ case 'k': \ u++; \ if (e++ == cp) \ return -EINVAL; \ - /* fall through */ \ + fallthrough; \ case '\n': \ case '\0': \ if (*e == '\n') \ diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 148960721254..238cd80826a6 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1552,7 +1552,7 @@ static blk_status_t crypt_convert(struct crypt_config *cc, case -EBUSY: wait_for_completion(&ctx->restart); reinit_completion(&ctx->restart); - /* fall through */ + fallthrough; /* * The request is queued and processed asynchronously, * completion function kcryptd_async_done() will be called. diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 53645a6f474c..e3283d35c7fd 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1554,7 +1554,7 @@ static void pg_init_done(void *data, int errors) case SCSI_DH_RETRY: /* Wait before retrying. */ delay_retry = true; - /* fall through */ + fallthrough; case SCSI_DH_IMM_RETRY: case SCSI_DH_RES_TEMP_UNAVAIL: if (pg_init_limit_reached(m, pgpath)) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 32fa6499739f..fb0255d25e4b 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1021,7 +1021,7 @@ static void clone_endio(struct bio *bio) switch (r) { case DM_ENDIO_REQUEUE: error = BLK_STS_DM_REQUEUE; - /*FALLTHRU*/ + fallthrough; case DM_ENDIO_DONE: break; case DM_ENDIO_INCOMPLETE: diff --git a/drivers/md/md-autodetect.c b/drivers/md/md-autodetect.c index 6bbec89976a7..2cf973722f59 100644 --- a/drivers/md/md-autodetect.c +++ b/drivers/md/md-autodetect.c @@ -102,10 +102,10 @@ static int __init md_setup(char *str) pername = "raid0"; break; } - /* FALL THROUGH */ + fallthrough; case 1: /* the first device is numeric */ str = str1; - /* FALL THROUGH */ + fallthrough; case 0: md_setup_args[ent].level = LEVEL_NONE; pername="super-block"; diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c index d61b524ae440..b10c51988c8e 100644 --- a/drivers/md/md-bitmap.c +++ b/drivers/md/md-bitmap.c @@ -1433,7 +1433,7 @@ int md_bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long s case 0: md_bitmap_file_set_bit(bitmap, offset); md_bitmap_count_page(&bitmap->counts, offset, 1); - /* fall through */ + fallthrough; case 1: *bmc = 2; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index ef0fd4830803..8b743657b957 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4083,7 +4083,7 @@ static void handle_parity_checks5(struct r5conf *conf, struct stripe_head *sh, break; } dev = &sh->dev[s->failed_num[0]]; - /* fall through */ + fallthrough; case check_state_compute_result: sh->check_state = check_state_idle; if (!dev) @@ -4214,7 +4214,7 @@ static void handle_parity_checks6(struct r5conf *conf, struct stripe_head *sh, /* we have 2-disk failure */ BUG_ON(s->failed != 2); - /* fall through */ + fallthrough; case check_state_compute_result: sh->check_state = check_state_idle; diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c index 630a75e0eeb1..7607b516a7c4 100644 --- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c +++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c @@ -210,7 +210,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) tpg->vdownsampling[1] = 1; tpg->hdownsampling[1] = 1; tpg->planes = 2; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_RGB332: case V4L2_PIX_FMT_RGB565: case V4L2_PIX_FMT_RGB565X: @@ -271,7 +271,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_YUV420M: case V4L2_PIX_FMT_YVU420M: tpg->buffers = 3; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_YUV420: case V4L2_PIX_FMT_YVU420: tpg->vdownsampling[1] = 2; @@ -284,7 +284,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_YUV422M: case V4L2_PIX_FMT_YVU422M: tpg->buffers = 3; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_YUV422P: tpg->vdownsampling[1] = 1; tpg->vdownsampling[2] = 1; @@ -296,7 +296,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_NV16M: case V4L2_PIX_FMT_NV61M: tpg->buffers = 2; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: tpg->vdownsampling[1] = 1; @@ -308,7 +308,7 @@ bool tpg_s_fourcc(struct tpg_data *tpg, u32 fourcc) case V4L2_PIX_FMT_NV12M: case V4L2_PIX_FMT_NV21M: tpg->buffers = 2; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: tpg->vdownsampling[1] = 2; @@ -1275,7 +1275,7 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_RGB444: case V4L2_PIX_FMT_XRGB444: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_YUV444: case V4L2_PIX_FMT_ARGB444: buf[0][offset] = (g_u_s << 4) | b_v; @@ -1283,21 +1283,21 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_RGBX444: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_RGBA444: buf[0][offset] = (b_v << 4) | (alpha >> 4); buf[0][offset + 1] = (r_y_h << 4) | g_u_s; break; case V4L2_PIX_FMT_XBGR444: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_ABGR444: buf[0][offset] = (g_u_s << 4) | r_y_h; buf[0][offset + 1] = (alpha & 0xf0) | b_v; break; case V4L2_PIX_FMT_BGRX444: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_BGRA444: buf[0][offset] = (r_y_h << 4) | (alpha >> 4); buf[0][offset + 1] = (b_v << 4) | g_u_s; @@ -1305,7 +1305,7 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_XRGB555: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_YUV555: case V4L2_PIX_FMT_ARGB555: buf[0][offset] = (g_u_s << 5) | b_v; @@ -1314,7 +1314,7 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_RGBX555: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_RGBA555: buf[0][offset] = (g_u_s << 6) | (b_v << 1) | ((alpha & 0x80) >> 7); @@ -1322,7 +1322,7 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_XBGR555: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_ABGR555: buf[0][offset] = (g_u_s << 5) | r_y_h; buf[0][offset + 1] = (alpha & 0x80) | (b_v << 2) @@ -1330,7 +1330,7 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_BGRX555: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_BGRA555: buf[0][offset] = (g_u_s << 6) | (r_y_h << 1) | ((alpha & 0x80) >> 7); @@ -1339,7 +1339,7 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_RGB555X: case V4L2_PIX_FMT_XRGB555X: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_ARGB555X: buf[0][offset] = (alpha & 0x80) | (r_y_h << 2) | (g_u_s >> 3); buf[0][offset + 1] = (g_u_s << 5) | b_v; @@ -1366,7 +1366,7 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_HSV32: case V4L2_PIX_FMT_XYUV32: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_YUV32: case V4L2_PIX_FMT_ARGB32: case V4L2_PIX_FMT_AYUV32: @@ -1377,7 +1377,7 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_RGBX32: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_RGBA32: buf[0][offset] = r_y_h; buf[0][offset + 1] = g_u_s; @@ -1388,7 +1388,7 @@ static void gen_twopix(struct tpg_data *tpg, case V4L2_PIX_FMT_XBGR32: case V4L2_PIX_FMT_VUYX32: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_ABGR32: case V4L2_PIX_FMT_VUYA32: buf[0][offset] = b_v; @@ -1398,7 +1398,7 @@ static void gen_twopix(struct tpg_data *tpg, break; case V4L2_PIX_FMT_BGRX32: alpha = 0; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_BGRA32: buf[0][offset] = alpha; buf[0][offset + 1] = b_v; diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 630509ecee20..89620da983ba 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -546,7 +546,7 @@ static int dvb_net_ule_new_payload(struct dvb_net_ule_handle *h) h->priv->ule_sndu_type_1 = 1; h->ts_remain -= 1; h->from_where += 1; - /* fallthrough */ + fallthrough; case 0: h->new_ts = 1; h->ts += TS_SZ; diff --git a/drivers/media/dvb-frontends/bcm3510.c b/drivers/media/dvb-frontends/bcm3510.c index e92542b92d34..da0ff7b44da4 100644 --- a/drivers/media/dvb-frontends/bcm3510.c +++ b/drivers/media/dvb-frontends/bcm3510.c @@ -773,7 +773,7 @@ static int bcm3510_init(struct dvb_frontend* fe) deb_info("attempting to download firmware\n"); if ((ret = bcm3510_init_cold(st)) < 0) return ret; - /* fall-through */ + fallthrough; case JDEC_EEPROM_LOAD_WAIT: deb_info("firmware is loaded\n"); bcm3510_check_firmware_version(st); diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c index bc374750529b..08a85831e917 100644 --- a/drivers/media/dvb-frontends/dib0090.c +++ b/drivers/media/dvb-frontends/dib0090.c @@ -1693,7 +1693,7 @@ static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum front if (state->identity.p1g) state->dc = dc_p1g_table; - /* fall through */ + fallthrough; case CT_TUNER_STEP_0: dprintk("Start/continue DC calibration for %s path\n", (state->dc->i == 1) ? "I" : "Q"); diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c index 0f0480d8576d..a6c2fc4586eb 100644 --- a/drivers/media/dvb-frontends/dib3000mb.c +++ b/drivers/media/dvb-frontends/dib3000mb.c @@ -224,7 +224,7 @@ static int dib3000mb_set_frontend(struct dvb_frontend *fe, int tuner) switch (c->hierarchy) { case HIERARCHY_NONE: deb_setf("hierarchy: none\n"); - /* fall through */ + fallthrough; case HIERARCHY_1: deb_setf("hierarchy: alpha=1\n"); wr(DIB3000MB_REG_VIT_ALPHA, DIB3000_ALPHA_1); diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c index 0a7790c4bad3..55bee50aa871 100644 --- a/drivers/media/dvb-frontends/dib7000p.c +++ b/drivers/media/dvb-frontends/dib7000p.c @@ -276,7 +276,7 @@ static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_p if (state->version != SOC7090) reg_1280 &= ~((1 << 11)); reg_1280 &= ~(1 << 6); - /* fall-through */ + fallthrough; case DIB7000P_POWER_INTERFACE_ONLY: /* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */ /* TODO power up either SDIO or I2C */ diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c index 5de016412c42..237b9d04c076 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drxj.c +++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c @@ -2306,7 +2306,7 @@ hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 pr_err("error %d\n", rc); goto rw_error; } - /* fallthrough */ + fallthrough; case SIO_HI_RA_RAM_CMD_BRDCTRL: rc = drxj_dap_write_reg16(dev_addr, SIO_HI_RA_RAM_PAR_2__A, cmd->param2, 0); if (rc != 0) { @@ -2318,7 +2318,7 @@ hi_command(struct i2c_device_addr *dev_addr, const struct drxj_hi_cmd *cmd, u16 pr_err("error %d\n", rc); goto rw_error; } - /* fallthrough */ + fallthrough; case SIO_HI_RA_RAM_CMD_NULL: /* No parameters */ break; @@ -2841,7 +2841,7 @@ ctrl_set_cfg_mpeg_output(struct drx_demod_instance *demod, struct drx_cfg_mpeg_o /* coef = 188/204 */ max_bit_rate = (ext_attr->curr_symbol_rate / 8) * nr_bits * 188; - /* fall-through - as b/c Annex A/C need following settings */ + fallthrough; /* as b/c Annex A/C need following settings */ case DRX_STANDARD_ITU_B: rc = drxj_dap_write_reg16(dev_addr, FEC_OC_FCT_USAGE__A, FEC_OC_FCT_USAGE__PRE, 0); if (rc != 0) { @@ -3555,8 +3555,8 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_smatx) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE_SMA: /* fall through */ - case DRX_UIO_MODE_FIRMWARE_SAW: /* fall through */ + case DRX_UIO_MODE_FIRMWARE_SMA: + case DRX_UIO_MODE_FIRMWARE_SAW: case DRX_UIO_MODE_READWRITE: ext_attr->uio_sma_tx_mode = uio_cfg->mode; break; @@ -3579,7 +3579,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_smarx) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE0: /* fall through */ + case DRX_UIO_MODE_FIRMWARE0: case DRX_UIO_MODE_READWRITE: ext_attr->uio_sma_rx_mode = uio_cfg->mode; break; @@ -3603,7 +3603,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg if (!ext_attr->has_gpio) return -EIO; switch (uio_cfg->mode) { - case DRX_UIO_MODE_FIRMWARE0: /* fall through */ + case DRX_UIO_MODE_FIRMWARE0: case DRX_UIO_MODE_READWRITE: ext_attr->uio_gpio_mode = uio_cfg->mode; break; @@ -3639,7 +3639,7 @@ static int ctrl_set_uio_cfg(struct drx_demod_instance *demod, struct drxuio_cfg } ext_attr->uio_irqn_mode = uio_cfg->mode; break; - case DRX_UIO_MODE_FIRMWARE0: /* fall through */ + case DRX_UIO_MODE_FIRMWARE0: default: return -EINVAL; break; @@ -4004,31 +4004,36 @@ static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 4: rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_3__A, *(cmd->parameter + 3), 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 3: rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_2__A, *(cmd->parameter + 2), 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 2: rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_1__A, *(cmd->parameter + 1), 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 1: rc = drxj_dap_write_reg16(dev_addr, SCU_RAM_PARAM_0__A, *(cmd->parameter + 0), 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 0: /* do nothing */ break; @@ -4068,25 +4073,29 @@ static int scu_command(struct i2c_device_addr *dev_addr, struct drxjscu_cmd *cmd if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 3: rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_2__A, cmd->result + 2, 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 2: rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_1__A, cmd->result + 1, 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 1: rc = drxj_dap_read_reg16(dev_addr, SCU_RAM_PARAM_0__A, cmd->result + 0, 0); if (rc != 0) { pr_err("error %d\n", rc); goto rw_error; - } /* fallthrough */ + } + fallthrough; case 0: /* do nothing */ break; @@ -4791,7 +4800,7 @@ set_frequency(struct drx_demod_instance *demod, Sound carrier is already 3Mhz above centre frequency due to tuner setting so now add an extra shift of 1MHz... */ fm_frequency_shift = 1000; - /*fall through */ + fallthrough; case DRX_STANDARD_ITU_B: case DRX_STANDARD_NTSC: case DRX_STANDARD_PAL_SECAM_BG: @@ -10475,11 +10484,11 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel) (standard == DRX_STANDARD_NTSC)) { switch (channel->bandwidth) { case DRX_BANDWIDTH_6MHZ: - case DRX_BANDWIDTH_UNKNOWN: /* fall through */ + case DRX_BANDWIDTH_UNKNOWN: channel->bandwidth = DRX_BANDWIDTH_6MHZ; break; - case DRX_BANDWIDTH_8MHZ: /* fall through */ - case DRX_BANDWIDTH_7MHZ: /* fall through */ + case DRX_BANDWIDTH_8MHZ: + case DRX_BANDWIDTH_7MHZ: default: return -EINVAL; } @@ -10511,10 +10520,10 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel) } switch (channel->constellation) { - case DRX_CONSTELLATION_QAM16: /* fall through */ - case DRX_CONSTELLATION_QAM32: /* fall through */ - case DRX_CONSTELLATION_QAM64: /* fall through */ - case DRX_CONSTELLATION_QAM128: /* fall through */ + case DRX_CONSTELLATION_QAM16: + case DRX_CONSTELLATION_QAM32: + case DRX_CONSTELLATION_QAM64: + case DRX_CONSTELLATION_QAM128: case DRX_CONSTELLATION_QAM256: bandwidth_temp = channel->symbolrate * bw_rolloff_factor; bandwidth = bandwidth_temp / 100; @@ -10628,8 +10637,8 @@ ctrl_set_channel(struct drx_demod_instance *demod, struct drx_channel *channel) } break; #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: rc = set_qam_channel(demod, channel, tuner_freq_offset); if (rc != 0) { @@ -10820,7 +10829,7 @@ ctrl_lock_status(struct drx_demod_instance *demod, enum drx_lock_status *lock_st SCU_RAM_COMMAND_CMD_DEMOD_GET_LOCK; break; #endif - case DRX_STANDARD_UNKNOWN: /* fallthrough */ + case DRX_STANDARD_UNKNOWN: default: return -EIO; } @@ -10888,8 +10897,8 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard) */ switch (prev_standard) { #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: rc = power_down_qam(demod, false); if (rc != 0) { @@ -10908,7 +10917,7 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard) case DRX_STANDARD_UNKNOWN: /* Do nothing */ break; - case DRX_STANDARD_AUTO: /* fallthrough */ + case DRX_STANDARD_AUTO: default: return -EINVAL; } @@ -10921,8 +10930,8 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard) switch (*standard) { #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: do { u16 dummy; @@ -11111,12 +11120,12 @@ ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode) goto rw_error; } break; - case DRX_STANDARD_PAL_SECAM_BG: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_DK: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_I: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_L: /* fallthrough */ - case DRX_STANDARD_PAL_SECAM_LP: /* fallthrough */ - case DRX_STANDARD_NTSC: /* fallthrough */ + case DRX_STANDARD_PAL_SECAM_BG: + case DRX_STANDARD_PAL_SECAM_DK: + case DRX_STANDARD_PAL_SECAM_I: + case DRX_STANDARD_PAL_SECAM_L: + case DRX_STANDARD_PAL_SECAM_LP: + case DRX_STANDARD_NTSC: case DRX_STANDARD_FM: rc = power_down_atv(demod, ext_attr->standard, true); if (rc != 0) { @@ -11127,7 +11136,7 @@ ctrl_power_mode(struct drx_demod_instance *demod, enum drx_power_mode *mode) case DRX_STANDARD_UNKNOWN: /* Do nothing */ break; - case DRX_STANDARD_AUTO: /* fallthrough */ + case DRX_STANDARD_AUTO: default: return -EIO; } @@ -11220,8 +11229,8 @@ ctrl_set_cfg_pre_saw(struct drx_demod_instance *demod, struct drxj_cfg_pre_saw * ext_attr->vsb_pre_saw_cfg = *pre_saw; break; #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: ext_attr->qam_pre_saw_cfg = *pre_saw; break; @@ -11264,10 +11273,10 @@ ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain ext_attr = (struct drxj_data *) demod->my_ext_attr; switch (afe_gain->standard) { - case DRX_STANDARD_8VSB: /* fallthrough */ + case DRX_STANDARD_8VSB: fallthrough; #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: #endif /* Do nothing */ @@ -11301,8 +11310,8 @@ ctrl_set_cfg_afe_gain(struct drx_demod_instance *demod, struct drxj_cfg_afe_gain ext_attr->vsb_pga_cfg = gain * 13 + 140; break; #ifndef DRXJ_VSB_ONLY - case DRX_STANDARD_ITU_A: /* fallthrough */ - case DRX_STANDARD_ITU_B: /* fallthrough */ + case DRX_STANDARD_ITU_A: + case DRX_STANDARD_ITU_B: case DRX_STANDARD_ITU_C: ext_attr->qam_pga_cfg = gain * 13 + 140; break; diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c index fae6f3763364..45f982863904 100644 --- a/drivers/media/dvb-frontends/drxd_hard.c +++ b/drivers/media/dvb-frontends/drxd_hard.c @@ -1512,14 +1512,14 @@ static int SetDeviceTypeId(struct drxd_state *state) switch (deviceId) { case 4: state->diversity = 1; - /* fall through */ + fallthrough; case 3: case 7: state->PGA = 1; break; case 6: state->diversity = 1; - /* fall through */ + fallthrough; case 5: case 8: break; @@ -1966,7 +1966,7 @@ static int DRX_Start(struct drxd_state *state, s32 off) switch (p->transmission_mode) { default: /* Not set, detect it automatically */ operationMode |= SC_RA_RAM_OP_AUTO_MODE__M; - /* fall through - try first guess DRX_FFTMODE_8K */ + fallthrough; /* try first guess DRX_FFTMODE_8K */ case TRANSMISSION_MODE_8K: transmissionParams |= SC_RA_RAM_OP_PARAM_MODE_8K; if (state->type_A) { @@ -2139,7 +2139,7 @@ static int DRX_Start(struct drxd_state *state, s32 off) switch (p->modulation) { default: operationMode |= SC_RA_RAM_OP_AUTO_CONST__M; - /* fall through - try first guess DRX_CONSTELLATION_QAM64 */ + fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64: transmissionParams |= SC_RA_RAM_OP_PARAM_CONST_QAM64; if (state->type_A) { @@ -2266,7 +2266,7 @@ static int DRX_Start(struct drxd_state *state, s32 off) break; default: operationMode |= SC_RA_RAM_OP_AUTO_RATE__M; - /* fall through */ + fallthrough; case FEC_2_3: transmissionParams |= SC_RA_RAM_OP_PARAM_RATE_2_3; if (state->type_A) @@ -2301,7 +2301,7 @@ static int DRX_Start(struct drxd_state *state, s32 off) switch (p->bandwidth_hz) { case 0: p->bandwidth_hz = 8000000; - /* fall through */ + fallthrough; case 8000000: /* (64/7)*(8/8)*1000000 */ bandwidth = DRXD_BANDWIDTH_8MHZ_IN_HZ; diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c index 0ae9d8c72d8d..32f9346deb3e 100644 --- a/drivers/media/dvb-frontends/drxk_hard.c +++ b/drivers/media/dvb-frontends/drxk_hard.c @@ -1756,7 +1756,7 @@ static int setoperation_mode(struct drxk_state *state, goto error; state->m_operation_mode = OM_NONE; break; - case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_A: case OM_QAM_ITU_C: status = mpegts_stop(state); if (status < 0) @@ -1783,7 +1783,7 @@ static int setoperation_mode(struct drxk_state *state, if (status < 0) goto error; break; - case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_A: case OM_QAM_ITU_C: dprintk(1, ": DVB-C Annex %c\n", (state->m_operation_mode == OM_QAM_ITU_A) ? 'A' : 'C'); @@ -2012,7 +2012,7 @@ static int mpegts_dto_setup(struct drxk_state *state, fec_oc_rcn_ctl_rate = 0xC00000; static_clk = state->m_dvbt_static_clk; break; - case OM_QAM_ITU_A: /* fallthrough */ + case OM_QAM_ITU_A: case OM_QAM_ITU_C: fec_oc_tmd_mode = 0x0004; fec_oc_rcn_ctl_rate = 0xD2B4EE; /* good for >63 Mb/s */ @@ -3249,11 +3249,11 @@ static int dvbt_sc_command(struct drxk_state *state, case OFDM_SC_RA_RAM_CMD_SET_PREF_PARAM: case OFDM_SC_RA_RAM_CMD_PROGRAM_PARAM: status |= write16(state, OFDM_SC_RA_RAM_PARAM1__A, param1); - /* fall through - All commands using 1 parameters */ + fallthrough; /* All commands using 1 parameters */ case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING: case OFDM_SC_RA_RAM_CMD_USER_IO: status |= write16(state, OFDM_SC_RA_RAM_PARAM0__A, param0); - /* fall through - All commands using 0 parameters */ + fallthrough; /* All commands using 0 parameters */ case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM: case OFDM_SC_RA_RAM_CMD_NULL: /* Write command */ @@ -3761,7 +3761,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case TRANSMISSION_MODE_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M; - /* fall through - try first guess DRX_FFTMODE_8K */ + fallthrough; /* try first guess DRX_FFTMODE_8K */ case TRANSMISSION_MODE_8K: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K; break; @@ -3775,7 +3775,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, default: case GUARD_INTERVAL_AUTO: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M; - /* fall through - try first guess DRX_GUARD_1DIV4 */ + fallthrough; /* try first guess DRX_GUARD_1DIV4 */ case GUARD_INTERVAL_1_4: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4; break; @@ -3798,7 +3798,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M; /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */ /* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */ - /* fall through */ + fallthrough; case HIERARCHY_1: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1; break; @@ -3816,7 +3816,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case QAM_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M; - /* fall through - try first guess DRX_CONSTELLATION_QAM64 */ + fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */ case QAM_64: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64; break; @@ -3841,7 +3841,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, WR16(dev_addr, OFDM_EC_SB_PRIOR__A, OFDM_EC_SB_PRIOR_HI)); break; - case DRX_PRIORITY_UNKNOWN: /* fall through */ + case DRX_PRIORITY_UNKNOWN: default: status = -EINVAL; goto error; @@ -3859,7 +3859,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, case FEC_AUTO: default: operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M; - /* fall through - try first guess DRX_CODERATE_2DIV3 */ + fallthrough; /* try first guess DRX_CODERATE_2DIV3 */ case FEC_2_3: transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3; break; @@ -3893,7 +3893,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz, switch (state->props.bandwidth_hz) { case 0: state->props.bandwidth_hz = 8000000; - /* fall through */ + fallthrough; case 8000000: bandwidth = DRXK_BANDWIDTH_8MHZ_IN_HZ; status = write16(state, OFDM_SC_RA_RAM_SRMM_FIX_FACT_8K__A, diff --git a/drivers/media/dvb-frontends/lgdt3306a.c b/drivers/media/dvb-frontends/lgdt3306a.c index d3c330e035c4..722576f1732a 100644 --- a/drivers/media/dvb-frontends/lgdt3306a.c +++ b/drivers/media/dvb-frontends/lgdt3306a.c @@ -768,7 +768,7 @@ static int lgdt3306a_set_if(struct lgdt3306a_state *state, default: pr_warn("IF=%d KHz is not supported, 3250 assumed\n", if_freq_khz); - /* fallthrough */ + fallthrough; case 3250: /* 3.25Mhz */ nco1 = 0x34; nco2 = 0x00; diff --git a/drivers/media/dvb-frontends/mt352.c b/drivers/media/dvb-frontends/mt352.c index 881897583cf2..399d5c519027 100644 --- a/drivers/media/dvb-frontends/mt352.c +++ b/drivers/media/dvb-frontends/mt352.c @@ -201,7 +201,7 @@ static int mt352_set_parameters(struct dvb_frontend *fe) if (op->hierarchy == HIERARCHY_AUTO || op->hierarchy == HIERARCHY_NONE) break; - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/drivers/media/dvb-frontends/mxl5xx.c b/drivers/media/dvb-frontends/mxl5xx.c index 290b9eab099f..4404ace82981 100644 --- a/drivers/media/dvb-frontends/mxl5xx.c +++ b/drivers/media/dvb-frontends/mxl5xx.c @@ -739,7 +739,7 @@ static int get_frontend(struct dvb_frontend *fe, default: break; } - /* Fall through */ + fallthrough; case SYS_DVBS: switch ((enum MXL_HYDRA_MODULATION_E) reg_data[DMD_MODULATION_SCHEME_ADDR]) { diff --git a/drivers/media/dvb-frontends/or51132.c b/drivers/media/dvb-frontends/or51132.c index 35a3e47497c2..24de1b115158 100644 --- a/drivers/media/dvb-frontends/or51132.c +++ b/drivers/media/dvb-frontends/or51132.c @@ -482,7 +482,7 @@ start: switch (reg&0xff) { case 0x06: if (reg & 0x1000) usK = 3 << 24; - /* fall through */ + fallthrough; case 0x43: /* QAM64 */ c = 150204167; break; diff --git a/drivers/media/dvb-frontends/s5h1411.c b/drivers/media/dvb-frontends/s5h1411.c index 89402916d301..c1334d7eb442 100644 --- a/drivers/media/dvb-frontends/s5h1411.c +++ b/drivers/media/dvb-frontends/s5h1411.c @@ -398,7 +398,7 @@ static int s5h1411_set_if_freq(struct dvb_frontend *fe, int KHz) default: dprintk("%s(%d KHz) Invalid, defaulting to 5380\n", __func__, KHz); - /* fall through */ + fallthrough; case 5380: case 44000: s5h1411_writereg(state, S5H1411_I2C_TOP_ADDR, 0x38, 0x1be4); diff --git a/drivers/media/dvb-frontends/zl10353.c b/drivers/media/dvb-frontends/zl10353.c index 2fc6aea580f9..2a2cf20a73d6 100644 --- a/drivers/media/dvb-frontends/zl10353.c +++ b/drivers/media/dvb-frontends/zl10353.c @@ -201,7 +201,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) break; default: c->bandwidth_hz = 8000000; - /* fall through */ + fallthrough; case 8000000: zl10353_single_write(fe, MCLK_RATIO, 0x75); zl10353_single_write(fe, 0x64, 0x36); @@ -258,7 +258,7 @@ static int zl10353_set_parameters(struct dvb_frontend *fe) if (c->hierarchy == HIERARCHY_AUTO || c->hierarchy == HIERARCHY_NONE) break; - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c index 570a4a09c387..03eee606af91 100644 --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c @@ -2209,7 +2209,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; - /* fall-through */ + fallthrough; case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP: ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ @@ -2370,7 +2370,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) /* Currently only enabled for the integrated IR controller */ if (!enable_885_ir) break; - /* fall-through */ + fallthrough; case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE: diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 7cabb9e9ffe2..92fe051c672f 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -1310,7 +1310,7 @@ static void dvb_input_detach(struct ddb_input *input) dvb_unregister_frontend(dvb->fe2); if (dvb->fe) dvb_unregister_frontend(dvb->fe); - /* fallthrough */ + fallthrough; case 0x30: dvb_module_release(dvb->i2c_client[0]); dvb->i2c_client[0] = NULL; @@ -1321,22 +1321,22 @@ static void dvb_input_detach(struct ddb_input *input) dvb_frontend_detach(dvb->fe); dvb->fe = NULL; dvb->fe2 = NULL; - /* fallthrough */ + fallthrough; case 0x20: dvb_net_release(&dvb->dvbnet); - /* fallthrough */ + fallthrough; case 0x12: dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &dvb->hw_frontend); dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &dvb->mem_frontend); - /* fallthrough */ + fallthrough; case 0x11: dvb_dmxdev_release(&dvb->dmxdev); - /* fallthrough */ + fallthrough; case 0x10: dvb_dmx_release(&dvb->demux); - /* fallthrough */ + fallthrough; case 0x01: break; } @@ -1559,7 +1559,7 @@ static int dvb_input_attach(struct ddb_input *input) osc24 = 0; else osc24 = 1; - /* fall-through */ + fallthrough; case DDB_TUNER_DVBCT2_SONY_P: case DDB_TUNER_DVBC2T2_SONY_P: case DDB_TUNER_ISDBT_SONY_P: @@ -1575,7 +1575,7 @@ static int dvb_input_attach(struct ddb_input *input) break; case DDB_TUNER_DVBC2T2I_SONY: osc24 = 1; - /* fall-through */ + fallthrough; case DDB_TUNER_DVBCT2_SONY: case DDB_TUNER_DVBC2T2_SONY: case DDB_TUNER_ISDBT_SONY: @@ -2036,7 +2036,7 @@ static int ddb_port_attach(struct ddb_port *port) ret = ddb_ci_attach(port, ci_bitrate); if (ret < 0) break; - /* fall-through */ + fallthrough; case DDB_PORT_LOOP: ret = dvb_register_device(port->dvb[0].adap, &port->dvb[0].dev, @@ -2432,7 +2432,8 @@ void ddb_ports_init(struct ddb *dev) ddb_input_init(port, 4 + i, 1, 4 + i); ddb_output_init(port, i); break; - } /* fallthrough */ + } + fallthrough; case DDB_OCTOPUS: ddb_input_init(port, 2 * i, 0, 2 * i); ddb_input_init(port, 2 * i + 1, 1, 2 * i + 1); @@ -3417,7 +3418,7 @@ int ddb_exit_ddbridge(int stage, int error) default: case 2: destroy_workqueue(ddb_wq); - /* fall-through */ + fallthrough; case 1: ddb_class_destroy(); break; diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c index 7fb3b1853b87..8944e4bd4638 100644 --- a/drivers/media/pci/meye/meye.c +++ b/drivers/media/pci/meye/meye.c @@ -952,7 +952,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) mutex_unlock(&meye.lock); return -EINTR; } - /* fall through */ + fallthrough; case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, diff --git a/drivers/media/pci/ttpci/av7110.c b/drivers/media/pci/ttpci/av7110.c index bf36b1e22b63..45228f4f6fc6 100644 --- a/drivers/media/pci/ttpci/av7110.c +++ b/drivers/media/pci/ttpci/av7110.c @@ -637,7 +637,7 @@ static void gpioirq(unsigned long cookie) iwdebi(av7110, DEBINOSWAP, RX_BUFF, 0, 2); break; } - /* fall through */ + fallthrough; case DATA_TS_RECORD: case DATA_PES_RECORD: @@ -2176,7 +2176,7 @@ static int frontend_init(struct av7110 *av7110) break; } } - /* fall-thru */ + fallthrough; case 0x0008: // Hauppauge/TT DVB-T // Grundig 29504-401 diff --git a/drivers/media/pci/ttpci/av7110_hw.c b/drivers/media/pci/ttpci/av7110_hw.c index e8a8ec5405e2..93ca31e38ddd 100644 --- a/drivers/media/pci/ttpci/av7110_hw.c +++ b/drivers/media/pci/ttpci/av7110_hw.c @@ -1107,7 +1107,7 @@ int av7110_osd_cmd(struct av7110 *av7110, osd_cmd_t *dc) break; case OSD_SetRow: dc->y1 = dc->y0; - /* fall through */ + fallthrough; case OSD_SetBlock: ret = OSDSetBlock(av7110, dc->x0, dc->y0, dc->x1, dc->y1, dc->color, dc->data); break; diff --git a/drivers/media/pci/ttpci/av7110_ipack.c b/drivers/media/pci/ttpci/av7110_ipack.c index ec528fae7333..30330ed01ce8 100644 --- a/drivers/media/pci/ttpci/av7110_ipack.c +++ b/drivers/media/pci/ttpci/av7110_ipack.c @@ -182,7 +182,7 @@ int av7110_ipack_instant_repack (const u8 *buf, int count, struct ipack *p) case DSM_CC_STREAM : case ISO13522_STREAM: p->done = 1; - /* fall through */ + fallthrough; case PRIVATE_STREAM1: case VIDEO_STREAM_S ... VIDEO_STREAM_E: case AUDIO_STREAM_S ... AUDIO_STREAM_E: diff --git a/drivers/media/pci/ttpci/budget-av.c b/drivers/media/pci/ttpci/budget-av.c index 38cac508bd72..3cb83005cf09 100644 --- a/drivers/media/pci/ttpci/budget-av.c +++ b/drivers/media/pci/ttpci/budget-av.c @@ -1226,7 +1226,7 @@ static void frontend_init(struct budget_av *budget_av) * but so far it has been only confirmed for this type */ budget_av->reinitialise_demod = 1; - /* fall through */ + fallthrough; case SUBID_DVBS_KNC1_PLUS: case SUBID_DVBS_EASYWATCH_1: if (saa->pci->subsystem_vendor == 0x1894) { diff --git a/drivers/media/pci/ttpci/budget.c b/drivers/media/pci/ttpci/budget.c index 9c811272abfe..a88711a3ac7f 100644 --- a/drivers/media/pci/ttpci/budget.c +++ b/drivers/media/pci/ttpci/budget.c @@ -613,7 +613,7 @@ static void frontend_init(struct budget *budget) break; } } - /* fall through */ + fallthrough; case 0x1018: // TT Budget-S-1401 (philips tda10086/philips tda8262) { struct dvb_frontend *fe; @@ -638,7 +638,7 @@ static void frontend_init(struct budget *budget) break; } } - /* fall through */ + fallthrough; case 0x101c: { /* TT S2-1600 */ const struct stv6110x_devctl *ctl; diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index 36e5f2ff4ef1..b22dc1d72527 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -220,7 +220,7 @@ static void sh_vou_stream_config(struct sh_vou_device *vou_dev) break; case V4L2_PIX_FMT_RGB565: dataswap ^= 1; - /* fall through */ + fallthrough; case V4L2_PIX_FMT_RGB565X: row_coeff = 2; break; @@ -802,7 +802,7 @@ static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt) default: pr_warn("%s(): Invalid bus-format code %d, using default 8-bit\n", __func__, bus_fmt); - /* fall through */ + fallthrough; case SH_VOU_BUS_8BIT: return 1; case SH_VOU_BUS_16BIT: diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c index b203296de977..7e2460263882 100644 --- a/drivers/media/radio/radio-si476x.c +++ b/drivers/media/radio/radio-si476x.c @@ -105,7 +105,8 @@ static inline enum phase_diversity_modes_idx si476x_phase_diversity_mode_to_idx(enum si476x_phase_diversity_mode mode) { switch (mode) { - default: /* FALLTHROUGH */ + default: + fallthrough; case SI476X_PHDIV_DISABLED: return SI476X_IDX_PHDIV_DISABLED; case SI476X_PHDIV_PRIMARY_COMBINING: diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c index b0303cf00387..c37315226c42 100644 --- a/drivers/media/radio/tea575x.c +++ b/drivers/media/radio/tea575x.c @@ -249,7 +249,7 @@ int snd_tea575x_enum_freq_bands(struct snd_tea575x *tea, index = BAND_AM; break; } - /* Fall through */ + fallthrough; default: return -EINVAL; } diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c index 5bb144435c16..3fe3edd80876 100644 --- a/drivers/media/rc/bpf-lirc.c +++ b/drivers/media/rc/bpf-lirc.c @@ -112,7 +112,7 @@ lirc_mode2_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog) case BPF_FUNC_trace_printk: if (perfmon_capable()) return bpf_get_trace_printk_proto(); - /* fall through */ + fallthrough; default: return NULL; } diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c index 95727ca910f7..0cda78f72fd8 100644 --- a/drivers/media/rc/ir-rc6-decoder.c +++ b/drivers/media/rc/ir-rc6-decoder.c @@ -64,7 +64,7 @@ static enum rc6_mode rc6_mode(struct rc6_dec *data) case 6: if (!data->toggle) return RC6_MODE_6A; - /* fall through */ + fallthrough; default: return RC6_MODE_UNKNOWN; } diff --git a/drivers/media/rc/ir-sony-decoder.c b/drivers/media/rc/ir-sony-decoder.c index 9fa58d92eb09..7d9a7c000c75 100644 --- a/drivers/media/rc/ir-sony-decoder.c +++ b/drivers/media/rc/ir-sony-decoder.c @@ -102,7 +102,7 @@ static int ir_sony_decode(struct rc_dev *dev, struct ir_raw_event ev) } data->state = STATE_FINISHED; - /* Fall through */ + fallthrough; case STATE_FINISHED: if (ev.pulse) diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c index 734a92caad8d..7b7d9fe4f945 100644 --- a/drivers/media/tuners/xc5000.c +++ b/drivers/media/tuners/xc5000.c @@ -756,7 +756,7 @@ static int xc5000_set_digital_params(struct dvb_frontend *fe) if (!bw) bw = 6000000; /* fall to OFDM handling */ - /* fall through */ + fallthrough; case SYS_DMBTH: case SYS_DVBT: case SYS_DVBT2: diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index 198ddfb8d2b1..e3234d169065 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -525,7 +525,7 @@ static int flexcop_usb_init(struct flexcop_usb *fc_usb) case USB_SPEED_HIGH: info("running at HIGH speed."); break; - case USB_SPEED_UNKNOWN: /* fall through */ + case USB_SPEED_UNKNOWN: default: err("cannot handle USB speed because it is unknown."); return -ENODEV; diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index 20c50c2d042e..e747548ab286 100644 --- a/drivers/media/usb/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -165,7 +165,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_BRIGHTNESS: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_BRIGHTNESS: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -176,7 +176,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_CONTRAST: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_CONTRAST: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -184,7 +184,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_SATURATION: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_SATURATION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -195,7 +195,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_GPIO_DATA: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_GPIO_DATA: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -203,7 +203,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_GPIO_DIRECTION: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_GPIO_DIRECTION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -211,7 +211,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VC_MP_GPIO_DATA: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VC_MP_GPIO_DATA: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -219,7 +219,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VC_MP_GPIO_DIRECTION: cmd.buffer.block_data[0] = param; - /*fall through */ + fallthrough; case CPIA2_CMD_GET_VC_MP_GPIO_DIRECTION: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -234,7 +234,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_FLICKER_MODES: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_FLICKER_MODES: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -281,7 +281,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_USER_MODE: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_USER_MODE: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -301,7 +301,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_WAKEUP: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_WAKEUP: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -309,7 +309,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_PW_CONTROL: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_PW_CONTROL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -322,7 +322,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_SYSTEM_CTRL: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_SYSTEM_CTRL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_SYSTEM; @@ -331,7 +331,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_SYSTEM_CTRL: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_SYSTEM_CTRL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -339,7 +339,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VP_EXP_MODES: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VP_EXP_MODES: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -347,7 +347,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_DEVICE_CONFIG: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_DEVICE_CONFIG: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -368,7 +368,7 @@ int cpia2_do_command(struct camera_data *cam, break; case CPIA2_CMD_SET_VC_CONTROL: cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_VC_CONTROL: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VC; cmd.reg_count = 1; @@ -403,7 +403,7 @@ int cpia2_do_command(struct camera_data *cam, this register can also affect flicker modes */ cmd.buffer.block_data[0] = param; - /* fall through */ + fallthrough; case CPIA2_CMD_GET_USER_EFFECTS: cmd.req_mode = CAMERAACCESS_TYPE_BLOCK | CAMERAACCESS_VP; cmd.reg_count = 1; @@ -1751,7 +1751,7 @@ int cpia2_set_fps(struct camera_data *cam, int framerate) CPIA2_VP_SENSOR_FLAGS_500) { return -EINVAL; } - /* Fall through */ + fallthrough; case CPIA2_VP_FRAMERATE_15: case CPIA2_VP_FRAMERATE_12_5: case CPIA2_VP_FRAMERATE_7_5: diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c index d9f953f2d088..425e470b0fd3 100644 --- a/drivers/media/usb/cx231xx/cx231xx-video.c +++ b/drivers/media/usb/cx231xx/cx231xx-video.c @@ -996,7 +996,7 @@ void cx231xx_v4l2_create_entities(struct cx231xx *dev) /* The DVB core will handle it */ if (dev->tuner_type == TUNER_ABSENT) continue; - /* fall through */ + fallthrough; default: /* just to shut up a gcc warning */ ent->function = MEDIA_ENT_F_CONN_RF; break; diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 4ef3fa98d20f..a6ae46567a31 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -1660,7 +1660,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe) switch (band) { default: deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency); - /* fall through */ + fallthrough; case BAND_VHF: state->dib8000_ops.set_gpio(fe, 3, 0, 1); break; diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index f96626fe2c0b..a27a68440325 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -1886,12 +1886,12 @@ static int dw2102_load_firmware(struct usb_device *dev, switch (le16_to_cpu(dev->descriptor.idProduct)) { case USB_PID_TEVII_S650: dw2104_properties.rc.core.rc_codes = RC_MAP_TEVII_NEC; - /* fall through */ + fallthrough; case USB_PID_DW2104: reset = 1; dw210x_op_rw(dev, 0xc4, 0x0000, 0, &reset, 1, DW210X_WRITE_MSG); - /* fall through */ + fallthrough; case USB_PID_DW3101: reset = 0; dw210x_op_rw(dev, 0xbf, 0x0040, 0, &reset, 0, @@ -1924,7 +1924,7 @@ static int dw2102_load_firmware(struct usb_device *dev, break; } } - /* fall through */ + fallthrough; case 0x2101: dw210x_op_rw(dev, 0xbc, 0x0030, 0, &reset16[0], 2, DW210X_READ_MSG); diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 3f3fbcd60cc6..45a2403aa039 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -2200,7 +2200,7 @@ static int check_range(enum v4l2_ctrl_type type, case V4L2_CTRL_TYPE_BOOLEAN: if (step != 1 || max > 1 || min < 0) return -ERANGE; - /* fall through */ + fallthrough; case V4L2_CTRL_TYPE_U8: case V4L2_CTRL_TYPE_U16: case V4L2_CTRL_TYPE_U32: diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index a556880f225a..2a22e13a6303 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -782,7 +782,6 @@ static void v4l_print_frmsizeenum(const void *arg, bool write_only) p->stepwise.step_height); break; case V4L2_FRMSIZE_TYPE_CONTINUOUS: - /* fall through */ default: pr_cont("\n"); break; @@ -816,7 +815,6 @@ static void v4l_print_frmivalenum(const void *arg, bool write_only) p->stepwise.step.denominator); break; case V4L2_FRMIVAL_TYPE_CONTINUOUS: - /* fall through */ default: pr_cont("\n"); break; diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c index 5c91fc3e65b5..606a271bdd2d 100644 --- a/drivers/media/v4l2-core/videobuf-core.c +++ b/drivers/media/v4l2-core/videobuf-core.c @@ -354,7 +354,7 @@ static void videobuf_status(struct videobuf_queue *q, struct v4l2_buffer *b, break; case VIDEOBUF_ERROR: b->flags |= V4L2_BUF_FLAG_ERROR; - /* fall through */ + fallthrough; case VIDEOBUF_DONE: b->flags |= V4L2_BUF_FLAG_DONE; break; diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index f512cbc7a36c..ca0097664b12 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -313,7 +313,6 @@ static unsigned long gpmc_get_clk_period(int cs, enum gpmc_clk_domain cd) tick_ps *= div; break; case GPMC_CD_FCLK: - /* FALL-THROUGH */ default: break; } diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index d9ee8e3dc72d..178954228631 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -371,7 +371,7 @@ again: serial mode), then just fall through */ if (msb_read_int_reg(msb, -1)) return 0; - /* fallthrough */ + fallthrough; case MSB_RP_RECEIVE_INT_REQ_RESULT: intreg = mrq->data[0]; @@ -403,7 +403,7 @@ again: case MSB_RP_RECEIVE_STATUS_REG: msb->regs.status = *(struct ms_status_register *)mrq->data; msb->state = MSB_RP_SEND_OOB_READ; - /* fallthrough */ + fallthrough; case MSB_RP_SEND_OOB_READ: if (!msb_read_regs(msb, @@ -418,7 +418,7 @@ again: msb->regs.extra_data = *(struct ms_extra_data_register *) mrq->data; msb->state = MSB_RP_SEND_READ_DATA; - /* fallthrough */ + fallthrough; case MSB_RP_SEND_READ_DATA: /* Skip that state if we only read the oob */ @@ -518,7 +518,7 @@ again: msb->state = MSB_WB_RECEIVE_INT_REQ; if (msb_read_int_reg(msb, -1)) return 0; - /* fallthrough */ + fallthrough; case MSB_WB_RECEIVE_INT_REQ: intreg = mrq->data[0]; @@ -549,7 +549,7 @@ again: msb->int_polling = false; msb->state = MSB_WB_SEND_WRITE_DATA; - /* fallthrough */ + fallthrough; case MSB_WB_SEND_WRITE_DATA: sg_init_table(sg, ARRAY_SIZE(sg)); @@ -628,7 +628,7 @@ again: msb->state = MSB_SC_RECEIVE_INT_REQ; if (msb_read_int_reg(msb, -1)) return 0; - /* fallthrough */ + fallthrough; case MSB_SC_RECEIVE_INT_REQ: intreg = mrq->data[0]; diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c index 4a6b866b0291..e83c3ada9389 100644 --- a/drivers/memstick/host/jmb38x_ms.c +++ b/drivers/memstick/host/jmb38x_ms.c @@ -255,11 +255,11 @@ static unsigned int jmb38x_ms_write_data(struct jmb38x_ms_host *host, case 3: host->io_word[0] |= buf[off + 2] << 16; host->io_pos++; - /* fall through */ + fallthrough; case 2: host->io_word[0] |= buf[off + 1] << 8; host->io_pos++; - /* fall through */ + fallthrough; case 1: host->io_word[0] |= buf[off]; host->io_pos++; diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c index fc35c7404429..786e46798da2 100644 --- a/drivers/memstick/host/tifm_ms.c +++ b/drivers/memstick/host/tifm_ms.c @@ -162,11 +162,11 @@ static unsigned int tifm_ms_write_data(struct tifm_ms *host, case 3: host->io_word |= buf[off + 2] << 16; host->io_pos++; - /* fall through */ + fallthrough; case 2: host->io_word |= buf[off + 1] << 8; host->io_pos++; - /* fall through */ + fallthrough; case 1: host->io_word |= buf[off]; host->io_pos++; diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 5216487db4fb..9903e9660a38 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -642,7 +642,7 @@ mptbase_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req, MPT_FRAME_HDR *reply) freereq = 0; if (event != MPI_EVENT_EVENT_CHANGE) break; - /* fall through */ + fallthrough; case MPI_FUNCTION_CONFIG: case MPI_FUNCTION_SAS_IO_UNIT_CONTROL: ioc->mptbase_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD; @@ -1887,7 +1887,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) case MPI_MANUFACTPAGE_DEVICEID_FC939X: case MPI_MANUFACTPAGE_DEVICEID_FC949X: ioc->errata_flag_1064 = 1; - /* fall through */ + fallthrough; case MPI_MANUFACTPAGE_DEVICEID_FC909: case MPI_MANUFACTPAGE_DEVICEID_FC929: case MPI_MANUFACTPAGE_DEVICEID_FC919: @@ -1932,7 +1932,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) pcixcmd &= 0x8F; pci_write_config_byte(pdev, 0x6a, pcixcmd); } - /* fall through */ + fallthrough; case MPI_MANUFACTPAGE_DEVID_1030_53C1035: ioc->bus_type = SPI; diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 6a79cd0ebe2b..18b91ea1a353 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -4326,7 +4326,7 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event, } } mpt_findImVolumes(ioc); - /* fall through */ + fallthrough; case MPTSAS_ADD_DEVICE: memset(&sas_device, 0, sizeof(struct mptsas_devinfo)); diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 1491561d2e5c..8543f0324d5a 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -784,7 +784,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) /* * Allow non-SAS & non-NEXUS_LOSS to drop into below code */ - /* Fall through */ + fallthrough; case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: /* 0x0048 */ /* Linux handles an unsolicited DID_RESET better @@ -881,7 +881,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: /* 0x0044 */ scsi_set_resid(sc, 0); - /* Fall through */ + fallthrough; case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: /* 0x0040 */ case MPI_IOCSTATUS_SUCCESS: /* 0x0000 */ sc->result = (DID_OK << 16) | scsi_status; diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index a9d9c1cdf546..a5983d515db0 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c @@ -1515,10 +1515,10 @@ static unsigned long dsiclk_rate(u8 n) switch (divsel) { case PRCM_DSI_PLLOUT_SEL_PHI_4: div *= 2; - /* Fall through */ + fallthrough; case PRCM_DSI_PLLOUT_SEL_PHI_2: div *= 2; - /* Fall through */ + fallthrough; case PRCM_DSI_PLLOUT_SEL_PHI: return pll_rate(PRCM_PLLDSI_FREQ, clock_rate(PRCMU_HDMICLK), PLL_RAW) / div; diff --git a/drivers/mfd/iqs62x.c b/drivers/mfd/iqs62x.c index af764bc87d7c..761b4ef3a381 100644 --- a/drivers/mfd/iqs62x.c +++ b/drivers/mfd/iqs62x.c @@ -136,7 +136,7 @@ static int iqs62x_dev_init(struct iqs62x_core *iqs62x) if (val & IQS620_PROX_SETTINGS_4_SAR_EN) iqs62x->ui_sel = IQS62X_UI_SAR1; - /* fall through */ + fallthrough; case IQS621_PROD_NUM: ret = regmap_write(iqs62x->regmap, IQS620_GLBL_EVENT_MASK, @@ -470,7 +470,7 @@ static irqreturn_t iqs62x_irq(int irq, void *context) case IQS62X_EVENT_UI_LO: event_data.ui_data = get_unaligned_le16(&event_map[i]); - /* fall through */ + fallthrough; case IQS62X_EVENT_UI_HI: case IQS62X_EVENT_NONE: @@ -491,7 +491,7 @@ static irqreturn_t iqs62x_irq(int irq, void *context) case IQS62X_EVENT_HYST: event_map[i] <<= iqs62x->dev_desc->hyst_shift; - /* fall through */ + fallthrough; case IQS62X_EVENT_WHEEL: case IQS62X_EVENT_HALL: diff --git a/drivers/mfd/mxs-lradc.c b/drivers/mfd/mxs-lradc.c index 5bef142c4835..111d11fd25aa 100644 --- a/drivers/mfd/mxs-lradc.c +++ b/drivers/mfd/mxs-lradc.c @@ -172,7 +172,7 @@ static int mxs_lradc_probe(struct platform_device *pdev) MXS_LRADC_TOUCHSCREEN_5WIRE; break; } - /* fall through - to an error message for i.MX23 */ + fallthrough; /* to an error message for i.MX23 */ default: dev_err(&pdev->dev, "Unsupported number of touchscreen wires (%d)\n" diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 1e6431cb8536..2a3a240b4619 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c @@ -308,7 +308,7 @@ static int usbhs_runtime_resume(struct device *dev) i, r); } } - /* Fall through - as HSIC mode needs utmi_clk */ + fallthrough; /* as HSIC mode needs utmi_clk */ case OMAP_EHCI_PORT_MODE_TLL: if (!IS_ERR(omap->utmi_clk[i])) { @@ -344,7 +344,7 @@ static int usbhs_runtime_suspend(struct device *dev) if (!IS_ERR(omap->hsic480m_clk[i])) clk_disable_unprepare(omap->hsic480m_clk[i]); - /* Fall through - as utmi_clks were used in HSIC mode */ + fallthrough; /* as utmi_clks were used in HSIC mode */ case OMAP_EHCI_PORT_MODE_TLL: if (!IS_ERR(omap->utmi_clk[i])) diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index abaab541df19..545196c85b5c 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -270,7 +270,7 @@ static void *stuff(unsigned char *dest, const unsigned char *src, size_t n) case RAVE_SP_ETX: case RAVE_SP_DLE: *dest++ = RAVE_SP_DLE; - /* FALLTHROUGH */ + fallthrough; default: *dest++ = byte; } @@ -541,7 +541,7 @@ static int rave_sp_receive_buf(struct serdev_device *serdev, * deframer buffer */ - /* FALLTHROUGH */ + fallthrough; case RAVE_SP_EXPECT_ESCAPED_DATA: if (deframer->length == sizeof(deframer->data)) { diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index 75859e492984..df5cebb372a5 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -95,7 +95,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) break; default: pr_err("Failed to retrieve valid hwlock: %d\n", ret); - /* fall-through */ + fallthrough; case -EPROBE_DEFER: goto err_regmap; } diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c index cde9a2fc1325..ed8d38b09925 100644 --- a/drivers/misc/eeprom/at25.c +++ b/drivers/misc/eeprom/at25.c @@ -90,10 +90,10 @@ static int at25_ee_read(void *priv, unsigned int offset, switch (at25->addrlen) { default: /* case 3 */ *cp++ = offset >> 16; - /* fall through */ + fallthrough; case 2: *cp++ = offset >> 8; - /* fall through */ + fallthrough; case 1: case 0: /* can't happen: for better codegen */ *cp++ = offset >> 0; @@ -178,10 +178,10 @@ static int at25_ee_write(void *priv, unsigned int off, void *val, size_t count) switch (at25->addrlen) { default: /* case 3 */ *cp++ = offset >> 16; - /* fall through */ + fallthrough; case 2: *cp++ = offset >> 8; - /* fall through */ + fallthrough; case 1: case 0: /* can't happen: for better codegen */ *cp++ = offset >> 0; @@ -278,7 +278,7 @@ static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip) switch (val) { case 9: chip->flags |= EE_INSTR_BIT3_IS_ADDR; - /* fall through */ + fallthrough; case 8: chip->flags |= EE_ADDR1; break; diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c index 9cc6b2a6cf22..304d6c833712 100644 --- a/drivers/misc/mic/scif/scif_api.c +++ b/drivers/misc/mic/scif/scif_api.c @@ -178,7 +178,7 @@ int scif_close(scif_epd_t epd) case SCIFEP_ZOMBIE: dev_err(scif_info.mdev.this_device, "SCIFAPI close: zombie state unexpected\n"); - /* fall through */ + fallthrough; case SCIFEP_DISCONNECTED: spin_unlock(&ep->lock); scif_unregister_all_windows(epd); @@ -645,7 +645,7 @@ int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block) ep->port.port = err; ep->port.node = scif_info.nodeid; ep->conn_async_state = ASYNC_CONN_IDLE; - /* Fall through */ + fallthrough; case SCIFEP_BOUND: /* * If a non-blocking connect has been already initiated diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c index de8f61efaef5..2da3b474f486 100644 --- a/drivers/misc/mic/scif/scif_rma.c +++ b/drivers/misc/mic/scif/scif_rma.c @@ -657,7 +657,7 @@ int scif_unregister_window(struct scif_window *window) window->unreg_state = OP_IN_PROGRESS; send_msg = true; } - /* fall through */ + fallthrough; case OP_IN_PROGRESS: { scif_get_window(window, 1); diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c index f6e600bfac5d..0ea923fe6371 100644 --- a/drivers/misc/sgi-gru/grukservices.c +++ b/drivers/misc/sgi-gru/grukservices.c @@ -622,7 +622,7 @@ static int send_noop_message(void *cb, struct gru_message_queue_desc *mqd, break; case CBSS_PAGE_OVERFLOW: STAT(mesq_noop_page_overflow); - /* fall through */ + fallthrough; default: BUG(); } @@ -780,7 +780,7 @@ static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd, break; case CBSS_PAGE_OVERFLOW: STAT(mesq_page_overflow); - /* fall through */ + fallthrough; default: BUG(); } diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index d5e097cd556d..8a495dc82f16 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -1173,7 +1173,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) if (!xpc_kdebug_ignore) break; - /* fall through */ + fallthrough; case DIE_MCA_MONARCH_ENTER: case DIE_INIT_MONARCH_ENTER: xpc_arch_ops.offline_heartbeat(); @@ -1184,7 +1184,7 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) if (!xpc_kdebug_ignore) break; - /* fall through */ + fallthrough; case DIE_MCA_MONARCH_LEAVE: case DIE_INIT_MONARCH_LEAVE: xpc_arch_ops.online_heartbeat(); diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index 21a04bc97d40..099a53bdbb7d 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -441,10 +441,10 @@ xpc_discovery(void) switch (region_size) { case 128: max_regions *= 2; - /* fall through */ + fallthrough; case 64: max_regions *= 2; - /* fall through */ + fallthrough; case 32: max_regions *= 2; region_size = 16; diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 98c60f11b76b..7791bde81a36 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -574,7 +574,7 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part, xpc_wakeup_channel_mgr(part); } - /* fall through */ + fallthrough; case XPC_ACTIVATE_MQ_MSG_MARK_ENGAGED_UV: spin_lock_irqsave(&part_uv->flags_lock, irq_flags); part_uv->flags |= XPC_P_ENGAGED_UV; diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index ce43f7573d80..c8fae6611b73 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -191,7 +191,7 @@ int mmc_of_parse(struct mmc_host *host) switch (bus_width) { case 8: host->caps |= MMC_CAP_8_BIT_DATA; - /* fall through - Hosts capable of 8-bit can also do 4 bits */ + fallthrough; /* Hosts capable of 8-bit can also do 4 bits */ case 4: host->caps |= MMC_CAP_4_BIT_DATA; break; diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 300901415aa2..3fc3bbea8536 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -2418,7 +2418,7 @@ static void atmci_get_cap(struct atmel_mci *host) case 0x600: case 0x500: host->caps.has_odd_clk_div = 1; - /* Fall through */ + fallthrough; case 0x400: case 0x300: host->caps.has_dma_conf_reg = 1; @@ -2426,16 +2426,16 @@ static void atmci_get_cap(struct atmel_mci *host) host->caps.has_cfg_reg = 1; host->caps.has_cstor_reg = 1; host->caps.has_highspeed = 1; - /* Fall through */ + fallthrough; case 0x200: host->caps.has_rwproof = 1; host->caps.need_blksz_mul_4 = 0; host->caps.need_notbusy_for_read_ops = 1; - /* Fall through */ + fallthrough; case 0x100: host->caps.has_bad_data_ordering = 0; host->caps.need_reset_after_xfer = 0; - /* Fall through */ + fallthrough; case 0x0: break; default: diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index f01fecd75833..e50a08bce7ef 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -300,7 +300,7 @@ static void mmc_davinci_start_command(struct mmc_davinci_host *host, * then it's harmless for us to allow it. */ cmd_reg |= MMCCMD_BSYEXP; - /* FALLTHROUGH */ + fallthrough; case MMC_RSP_R1: /* 48 bits, CRC */ cmd_reg |= MMCCMD_RSPFMT_R1456; break; diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 50977ff18074..db1a84b2ba61 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -238,7 +238,7 @@ static void dw_mci_hs_set_timing(struct dw_mci *host, int timing, if (smpl_phase >= USE_DLY_MIN_SMPL && smpl_phase <= USE_DLY_MAX_SMPL) use_smpl_dly = 1; - /* fallthrough */ + fallthrough; case MMC_TIMING_UHS_SDR50: if (smpl_phase >= ENABLE_SHIFT_MIN_SMPL && smpl_phase <= ENABLE_SHIFT_MAX_SMPL) diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 35ae5737c622..0fba940544ca 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2030,7 +2030,7 @@ static void dw_mci_tasklet_func(unsigned long priv) } prev_state = state = STATE_SENDING_DATA; - /* fall through */ + fallthrough; case STATE_SENDING_DATA: /* @@ -2088,7 +2088,7 @@ static void dw_mci_tasklet_func(unsigned long priv) } prev_state = state = STATE_DATA_BUSY; - /* fall through */ + fallthrough; case STATE_DATA_BUSY: if (!dw_mci_clear_pending_data_complete(host)) { @@ -2141,7 +2141,7 @@ static void dw_mci_tasklet_func(unsigned long priv) */ prev_state = state = STATE_SENDING_STOP; - /* fall through */ + fallthrough; case STATE_SENDING_STOP: if (!dw_mci_clear_pending_cmd_complete(host)) diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index 447552ac25c4..81d71010b474 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -739,7 +739,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) break; jz_mmc_prepare_data_transfer(host); - /* fall through */ + fallthrough; case JZ4740_MMC_STATE_TRANSFER_DATA: if (host->use_dma) { @@ -774,7 +774,7 @@ static irqreturn_t jz_mmc_irq_worker(int irq, void *devid) break; } jz4740_mmc_write_irq_reg(host, JZ_MMC_IRQ_DATA_TRAN_DONE); - /* fall through */ + fallthrough; case JZ4740_MMC_STATE_SEND_STOP: if (!req->stop) diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 9b2cf7afc246..703d5834f9a5 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -294,7 +294,7 @@ static void meson_mx_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) switch (ios->power_mode) { case MMC_POWER_OFF: vdd = 0; - /* fall through */ + fallthrough; case MMC_POWER_UP: if (!IS_ERR(mmc->supply.vmmc)) { host->error = mmc_regulator_set_ocr(mmc, diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 15e21894bd44..904f5237d8f7 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -685,7 +685,7 @@ static int renesas_sdhi_write16_hook(struct tmio_mmc_host *host, int addr) case HOST_MODE: if (host->pdata->flags & TMIO_MMC_HAVE_CBSY) bit = TMIO_STAT_CMD_BUSY; - /* fallthrough */ + fallthrough; case CTL_SD_CARD_CLK_CTL: return renesas_sdhi_wait_idle(host, bit); } diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index a76b4513fbec..d738907a622f 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1556,7 +1556,7 @@ static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev, "failed to request card-detect gpio!\n"); return err; } - /* fall through */ + fallthrough; case ESDHC_CD_CONTROLLER: /* we have a working card_detect back */ diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 9194bb73e601..080ced1e63f0 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -609,7 +609,7 @@ static int sdhci_s3c_probe(struct platform_device *pdev) switch (pdata->max_width) { case 8: host->mmc->caps |= MMC_CAP_8_BIT_DATA; - /* Fall through */ + fallthrough; case 4: host->mmc->caps |= MMC_CAP_4_BIT_DATA; break; diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index a910cb461ed7..bafa2e41c8b6 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -470,7 +470,7 @@ static int sdhci_sprd_voltage_switch(struct mmc_host *mmc, struct mmc_ios *ios) break; default: - /* fall-through */ + fallthrough; case MMC_SIGNAL_VOLTAGE_330: ret = pinctrl_select_state(sprd_host->pinctrl, sprd_host->pins_default); diff --git a/drivers/mmc/host/sdhci-xenon-phy.c b/drivers/mmc/host/sdhci-xenon-phy.c index e6e9e286cc34..03ce57ef4585 100644 --- a/drivers/mmc/host/sdhci-xenon-phy.c +++ b/drivers/mmc/host/sdhci-xenon-phy.c @@ -527,7 +527,7 @@ static bool xenon_emmc_phy_slow_mode(struct sdhci_host *host, ret = true; break; } - /* fall through */ + fallthrough; default: reg &= ~XENON_TIMING_ADJUST_SLOW_MODE; ret = false; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 3ad394b40eb1..592a55a34b58 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2825,7 +2825,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) case MMC_TIMING_UHS_SDR50: if (host->flags & SDHCI_SDR50_NEEDS_TUNING) break; - /* FALLTHROUGH */ + fallthrough; default: goto out; diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 5987656e0474..fd8b72d3e02c 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -335,7 +335,7 @@ static unsigned int tifm_sd_op_flags(struct mmc_command *cmd) break; case MMC_RSP_R1B: rc |= TIFM_MMCSD_RSP_BUSY; - /* fall-through */ + fallthrough; case MMC_RSP_R1: rc |= TIFM_MMCSD_RSP_R1; break; diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 369b8dee2e3d..7666c90054ae 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1343,7 +1343,7 @@ static int usdhi6_stop_cmd(struct usdhi6_host *host) host->wait = USDHI6_WAIT_FOR_STOP; return 0; } - /* fall through - Unsupported STOP command. */ + fallthrough; /* Unsupported STOP command */ default: dev_err(mmc_dev(host->mmc), "unsupported stop CMD%d for CMD%d\n", @@ -1691,7 +1691,7 @@ static void usdhi6_timeout_work(struct work_struct *work) switch (host->wait) { default: dev_err(mmc_dev(host->mmc), "Invalid state %u\n", host->wait); - /* fall through - mrq can be NULL, but is impossible. */ + fallthrough; /* mrq can be NULL, but is impossible */ case USDHI6_WAIT_FOR_CMD: usdhi6_error_code(host); if (mrq) @@ -1713,7 +1713,7 @@ static void usdhi6_timeout_work(struct work_struct *work) host->offset, data->blocks, data->blksz, data->sg_len, sg_dma_len(sg), sg->offset); usdhi6_sg_unmap(host, true); - /* fall through - page unmapped in USDHI6_WAIT_FOR_DATA_END. */ + fallthrough; /* page unmapped in USDHI6_WAIT_FOR_DATA_END */ case USDHI6_WAIT_FOR_DATA_END: usdhi6_error_code(host); data->error = -ETIMEDOUT; diff --git a/drivers/mux/adgs1408.c b/drivers/mux/adgs1408.c index 12466b06692c..22ed051eb1a4 100644 --- a/drivers/mux/adgs1408.c +++ b/drivers/mux/adgs1408.c @@ -93,7 +93,7 @@ static int adgs1408_probe(struct spi_device *spi) mux->idle_state = idle_state; break; } - /* fall through */ + fallthrough; default: dev_err(dev, "invalid idle-state %d\n", idle_state); return -EINVAL; diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c index 18428e104445..1c6c27f35ac4 100644 --- a/drivers/net/appletalk/cops.c +++ b/drivers/net/appletalk/cops.c @@ -301,7 +301,7 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) dev->irq = cops_irq(ioaddr, board); if (dev->irq) break; - /* fall through - Once no IRQ found on this port. */ + fallthrough; /* Once no IRQ found on this port */ case 1: retval = -EINVAL; goto err_out; diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c index 14a5fb378145..98df38fe553c 100644 --- a/drivers/net/arcnet/arc-rimi.c +++ b/drivers/net/arcnet/arc-rimi.c @@ -363,13 +363,13 @@ static int __init arcrimi_setup(char *s) switch (ints[0]) { default: /* ERROR */ pr_err("Too many arguments\n"); - /* Fall through */ + fallthrough; case 3: /* Node ID */ node = ints[3]; - /* Fall through */ + fallthrough; case 2: /* IRQ */ irq = ints[2]; - /* Fall through */ + fallthrough; case 1: /* IO address */ io = ints[1]; } diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c index cd27fdc1059b..f983c4ce6b07 100644 --- a/drivers/net/arcnet/com20020-isa.c +++ b/drivers/net/arcnet/com20020-isa.c @@ -197,22 +197,22 @@ static int __init com20020isa_setup(char *s) switch (ints[0]) { default: /* ERROR */ pr_info("Too many arguments\n"); - /* Fall through */ + fallthrough; case 6: /* Timeout */ timeout = ints[6]; - /* Fall through */ + fallthrough; case 5: /* CKP value */ clockp = ints[5]; - /* Fall through */ + fallthrough; case 4: /* Backplane flag */ backplane = ints[4]; - /* Fall through */ + fallthrough; case 3: /* Node ID */ node = ints[3]; - /* Fall through */ + fallthrough; case 2: /* IRQ */ irq = ints[2]; - /* Fall through */ + fallthrough; case 1: /* IO address */ io = ints[1]; } diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c index 186bbf87bc84..cf214b730671 100644 --- a/drivers/net/arcnet/com90io.c +++ b/drivers/net/arcnet/com90io.c @@ -363,10 +363,10 @@ static int __init com90io_setup(char *s) switch (ints[0]) { default: /* ERROR */ pr_err("Too many arguments\n"); - /* Fall through */ + fallthrough; case 2: /* IRQ */ irq = ints[2]; - /* Fall through */ + fallthrough; case 1: /* IO address */ io = ints[1]; } diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c index bd75d06ad7df..3dc3d533cb19 100644 --- a/drivers/net/arcnet/com90xx.c +++ b/drivers/net/arcnet/com90xx.c @@ -693,13 +693,13 @@ static int __init com90xx_setup(char *s) switch (ints[0]) { default: /* ERROR */ pr_err("Too many arguments\n"); - /* Fall through */ + fallthrough; case 3: /* Mem address */ shmem = ints[3]; - /* Fall through */ + fallthrough; case 2: /* IRQ */ irq = ints[2]; - /* Fall through */ + fallthrough; case 1: /* IO address */ io = ints[1]; } diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index cddaa43a9d52..aa001b16765a 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c @@ -1149,7 +1149,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) port->actor_oper_port_state &= ~LACP_STATE_EXPIRED; port->sm_rx_state = AD_RX_PORT_DISABLED; - /* Fall Through */ + fallthrough; case AD_RX_PORT_DISABLED: port->sm_vars &= ~AD_PORT_MATCHED; break; @@ -1588,7 +1588,7 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best, if (__agg_active_ports(curr) < __agg_active_ports(best)) return best; - /*FALLTHROUGH*/ + fallthrough; case BOND_AD_STABLE: case BOND_AD_BANDWIDTH: if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best)) diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index c5d3032dd1a2..42ef25ec0af5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -2274,7 +2274,7 @@ static int bond_miimon_inspect(struct bonding *bond) "active " : "backup ") : "", bond->params.downdelay * bond->params.miimon); } - /*FALLTHRU*/ + fallthrough; case BOND_LINK_FAIL: if (link_state) { /* recovered before downdelay expired */ @@ -2310,7 +2310,7 @@ static int bond_miimon_inspect(struct bonding *bond) bond->params.updelay * bond->params.miimon); } - /*FALLTHRU*/ + fallthrough; case BOND_LINK_BACK: if (!link_state) { bond_propose_link_state(slave, BOND_LINK_DOWN); @@ -3322,7 +3322,7 @@ static int bond_slave_netdev_event(unsigned long event, if (BOND_MODE(bond) == BOND_MODE_8023AD) bond_3ad_adapter_speed_duplex_changed(slave); - /* Fallthrough */ + fallthrough; case NETDEV_DOWN: /* Refresh slave-array if applicable! * If the setup does not use miimon or arpmon (mode-specific!), @@ -3760,7 +3760,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd return -EINVAL; mii->phy_id = 0; - /* Fall Through */ + fallthrough; case SIOCGMIIREG: /* We do this again just in case we were called by SIOCGMIIREG * instead of SIOCGMIIPHY. diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 9df2007b5e56..38e9f80ed1ef 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -898,7 +898,7 @@ static void at91_irq_err_state(struct net_device *dev, CAN_ERR_CRTL_TX_WARNING : CAN_ERR_CRTL_RX_WARNING; } - /* fall through */ + fallthrough; case CAN_STATE_ERROR_WARNING: /* * from: ERROR_ACTIVE, ERROR_WARNING @@ -948,7 +948,7 @@ static void at91_irq_err_state(struct net_device *dev, netdev_dbg(dev, "Error Active\n"); cf->can_id |= CAN_ERR_PROT; cf->data[2] = CAN_ERR_PROT_ACTIVE; - /* fall through */ + fallthrough; case CAN_STATE_ERROR_WARNING: reg_idr = AT91_IRQ_ERRA | AT91_IRQ_WARN | AT91_IRQ_BOFF; reg_ier = AT91_IRQ_ERRP; diff --git a/drivers/net/can/peak_canfd/peak_pciefd_main.c b/drivers/net/can/peak_canfd/peak_pciefd_main.c index 6ad83a881039..9469d4421afe 100644 --- a/drivers/net/can/peak_canfd/peak_pciefd_main.c +++ b/drivers/net/can/peak_canfd/peak_pciefd_main.c @@ -659,7 +659,7 @@ static int pciefd_can_probe(struct pciefd_board *pciefd) pciefd_can_writereg(priv, CANFD_CLK_SEL_80MHZ, PCIEFD_REG_CAN_CLK_SEL); - /* fall through */ + fallthrough; case CANFD_CLK_SEL_80MHZ: priv->ucan.can.clock.freq = 80 * 1000 * 1000; break; diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c index d7222ba46622..d7c2ec529b8f 100644 --- a/drivers/net/can/sja1000/sja1000_platform.c +++ b/drivers/net/can/sja1000/sja1000_platform.c @@ -150,7 +150,7 @@ static void sp_populate_of(struct sja1000_priv *priv, struct device_node *of) priv->read_reg = sp_read_reg16; priv->write_reg = sp_write_reg16; break; - case 1: /* fallthrough */ + case 1: default: priv->read_reg = sp_read_reg8; priv->write_reg = sp_write_reg8; diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c index 91cdc0a2b1a7..b4a39f0449ba 100644 --- a/drivers/net/can/slcan.c +++ b/drivers/net/can/slcan.c @@ -153,7 +153,7 @@ static void slc_bump(struct slcan *sl) switch (*cmd) { case 'r': cf.can_id = CAN_RTR_FLAG; - /* fallthrough */ + fallthrough; case 't': /* store dlc ASCII value and terminate SFF CAN ID string */ cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN]; @@ -163,7 +163,7 @@ static void slc_bump(struct slcan *sl) break; case 'R': cf.can_id = CAN_RTR_FLAG; - /* fallthrough */ + fallthrough; case 'T': cf.can_id |= CAN_EFF_FLAG; /* store dlc ASCII value and terminate EFF CAN ID string */ diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 5009ff294941..d17608870f2d 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -864,7 +864,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) if (new_state >= CAN_STATE_ERROR_WARNING && new_state <= CAN_STATE_BUS_OFF) priv->can.can_stats.error_warning++; - /* fall through */ + fallthrough; case CAN_STATE_ERROR_WARNING: if (new_state >= CAN_STATE_ERROR_PASSIVE && new_state <= CAN_STATE_BUS_OFF) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index d2539c95adb6..66d0198e7834 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -415,7 +415,7 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, new_state = CAN_STATE_ERROR_WARNING; break; } - /* fall through */ + fallthrough; case CAN_STATE_ERROR_WARNING: if (n & PCAN_USB_ERROR_BUS_HEAVY) { diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 0b7766b715fd..d91df34e7fa8 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -345,7 +345,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb, default: netdev_warn(netdev, "tx urb submitting failed err=%d\n", err); - /* fall through */ + fallthrough; case -ENOENT: /* cable unplugged */ stats->tx_dropped++; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 53cb2f72bdd0..1689ab387612 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -133,10 +133,10 @@ static int pcan_msg_add_rec(struct pcan_usb_pro_msg *pm, int id, ...) switch (id) { case PCAN_USBPRO_TXMSG8: i += 4; - /* fall through */ + fallthrough; case PCAN_USBPRO_TXMSG4: i += 4; - /* fall through */ + fallthrough; case PCAN_USBPRO_TXMSG0: *pc++ = va_arg(ap, int); *pc++ = va_arg(ap, int); diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c index 0837ae0e0c5e..e731db900ee0 100644 --- a/drivers/net/dsa/b53/b53_common.c +++ b/drivers/net/dsa/b53/b53_common.c @@ -1061,7 +1061,7 @@ static void b53_force_port_config(struct b53_device *dev, int port, switch (speed) { case 2000: reg |= PORT_OVERRIDE_SPEED_2000M; - /* fallthrough */ + fallthrough; case SPEED_1000: reg |= PORT_OVERRIDE_SPEED_1000M; break; diff --git a/drivers/net/dsa/b53/b53_serdes.c b/drivers/net/dsa/b53/b53_serdes.c index 629bf14128a2..5ae3d9783b68 100644 --- a/drivers/net/dsa/b53/b53_serdes.c +++ b/drivers/net/dsa/b53/b53_serdes.c @@ -170,7 +170,7 @@ void b53_serdes_phylink_validate(struct b53_device *dev, int port, switch (lane) { case 0: phylink_set(supported, 2500baseX_Full); - /* fallthrough */ + fallthrough; case 1: phylink_set(supported, 1000baseX_Full); break; diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index bafddb35f3a9..5ebff986a1ac 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -566,7 +566,7 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, switch (state->interface) { case PHY_INTERFACE_MODE_RGMII: id_mode_dis = 1; - /* fallthrough */ + fallthrough; case PHY_INTERFACE_MODE_RGMII_TXID: port_mode = EXT_GPHY; break; diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index dc999406ce86..3cb22d149813 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -1083,7 +1083,7 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) interface = PHY_INTERFACE_MODE_GMII; if (gbit) break; - /* fall through */ + fallthrough; case 0: interface = PHY_INTERFACE_MODE_MII; break; diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c index 8dcb8a49ab67..0c37ddb58c1e 100644 --- a/drivers/net/dsa/mt7530.c +++ b/drivers/net/dsa/mt7530.c @@ -566,7 +566,7 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface) case P5_INTF_SEL_PHY_P0: /* MT7530_P5_MODE_GPHY_P0: 2nd GMAC -> P5 -> P0 */ val |= MHWTRAP_PHY0_SEL; - /* fall through */ + fallthrough; case P5_INTF_SEL_PHY_P4: /* MT7530_P5_MODE_GPHY_P4: 2nd GMAC -> P5 -> P4 */ val &= ~MHWTRAP_P5_MAC_SEL & ~MHWTRAP_P5_DIS; diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7a71c9902e73..f0dbc05e30a4 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -875,7 +875,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, break; case STATS_TYPE_BANK1: reg = bank1_select; - /* fall through */ + fallthrough; case STATS_TYPE_BANK0: reg |= s->reg | histogram; mv88e6xxx_g1_stats_read(chip, reg, &low); diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 139d0120f511..667f38c9e4c6 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -1259,14 +1259,14 @@ el3_up(struct net_device *dev) pr_cont("Forcing 3c5x9b full-duplex mode"); break; } - /* fall through */ + fallthrough; case 8: /* set full-duplex mode based on eeprom config setting */ if ((sw_info & 0x000f) && (sw_info & 0x8000)) { pr_cont("Setting 3c5x9b full-duplex mode (from EEPROM configuration bit)"); break; } - /* fall through */ + fallthrough; default: /* xcvr=(0 || 4) OR user has an old 3c5x9 non "B" model */ pr_cont("Setting 3c5x9/3c5x9B half-duplex mode"); diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index bd0ada4e81b0..f66e7fb9a2bb 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c @@ -1046,7 +1046,7 @@ static int el3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data->phy_id = phy; - /* fall through */ + fallthrough; case SIOCGMIIREG: /* Read the specified MII register. */ { int saved_window; diff --git a/drivers/net/ethernet/8390/axnet_cs.c b/drivers/net/ethernet/8390/axnet_cs.c index 08db4c9da2fa..a00b36f91d9f 100644 --- a/drivers/net/ethernet/8390/axnet_cs.c +++ b/drivers/net/ethernet/8390/axnet_cs.c @@ -610,7 +610,7 @@ static int axnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCGMIIPHY: data->phy_id = info->phy_id; - /* Fall through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f); return 0; diff --git a/drivers/net/ethernet/8390/pcnet_cs.c b/drivers/net/ethernet/8390/pcnet_cs.c index 645efac6310d..164c3ed550bf 100644 --- a/drivers/net/ethernet/8390/pcnet_cs.c +++ b/drivers/net/ethernet/8390/pcnet_cs.c @@ -1108,7 +1108,7 @@ static int ei_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCGMIIPHY: data->phy_id = info->phy_id; - /* fall through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = mdio_read(mii_addr, data->phy_id, data->reg_num & 0x1f); return 0; diff --git a/drivers/net/ethernet/alacritech/slicoss.c b/drivers/net/ethernet/alacritech/slicoss.c index 6234fcd844ee..696517eae77f 100644 --- a/drivers/net/ethernet/alacritech/slicoss.c +++ b/drivers/net/ethernet/alacritech/slicoss.c @@ -1712,13 +1712,13 @@ static bool slic_is_fiber(unsigned short subdev) { switch (subdev) { /* Mojave */ - case PCI_SUBDEVICE_ID_ALACRITECH_1000X1F: /* fallthrough */ - case PCI_SUBDEVICE_ID_ALACRITECH_SES1001F: /* fallthrough */ + case PCI_SUBDEVICE_ID_ALACRITECH_1000X1F: + case PCI_SUBDEVICE_ID_ALACRITECH_SES1001F: fallthrough; /* Oasis */ - case PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF: /* fallthrough */ - case PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF: /* fallthrough */ - case PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF: /* fallthrough */ - case PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF: /* fallthrough */ + case PCI_SUBDEVICE_ID_ALACRITECH_SEN2002XF: + case PCI_SUBDEVICE_ID_ALACRITECH_SEN2001XF: + case PCI_SUBDEVICE_ID_ALACRITECH_SEN2104EF: + case PCI_SUBDEVICE_ID_ALACRITECH_SEN2102EF: return true; } return false; diff --git a/drivers/net/ethernet/alteon/acenic.c b/drivers/net/ethernet/alteon/acenic.c index ac86fcae1582..8470c836fa18 100644 --- a/drivers/net/ethernet/alteon/acenic.c +++ b/drivers/net/ethernet/alteon/acenic.c @@ -547,7 +547,7 @@ static int acenic_probe_one(struct pci_dev *pdev, ap->name); break; } - /* Fall through */ + fallthrough; case PCI_VENDOR_ID_SGI: printk(KERN_INFO "%s: SGI AceNIC ", ap->name); break; diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index b6c43b58ed3d..960d483e8997 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1475,7 +1475,7 @@ static int amd8111e_ioctl(struct net_device *dev , struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = lp->ext_phy_addr; - /* fallthru */ + fallthrough; case SIOCGMIIREG: spin_lock_irq(&lp->lock); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 43294a148f8a..4ba75551cb17 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -1538,7 +1538,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, /* PTP v2, UDP, any kind of event packet */ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - /* Fall through - to PTP v1, UDP, any kind of event packet */ + fallthrough; /* to PTP v1, UDP, any kind of event packet */ case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); @@ -1549,7 +1549,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, /* PTP v2, UDP, Sync packet */ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - /* Fall through - to PTP v1, UDP, Sync packet */ + fallthrough; /* to PTP v1, UDP, Sync packet */ case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); @@ -1560,7 +1560,7 @@ static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, /* PTP v2, UDP, Delay_req packet */ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - /* Fall through - to PTP v1, UDP, Delay_req packet */ + fallthrough; /* to PTP v1, UDP, Delay_req packet */ case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); diff --git a/drivers/net/ethernet/broadcom/bgmac-bcma.c b/drivers/net/ethernet/broadcom/bgmac-bcma.c index 34d18302b1a3..a5fd161ab5ee 100644 --- a/drivers/net/ethernet/broadcom/bgmac-bcma.c +++ b/drivers/net/ethernet/broadcom/bgmac-bcma.c @@ -217,7 +217,7 @@ static int bgmac_probe(struct bcma_device *core) /* BCM 471X/535X family */ case BCMA_CHIP_ID_BCM4716: bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST; - /* fallthrough */ + fallthrough; case BCMA_CHIP_ID_BCM47162: bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2; bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK; diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c index 6795b6d95f54..f37f1c58f368 100644 --- a/drivers/net/ethernet/broadcom/bgmac-platform.c +++ b/drivers/net/ethernet/broadcom/bgmac-platform.c @@ -131,7 +131,7 @@ static void bgmac_nicpm_speed_set(struct net_device *net_dev) switch (bgmac->net_dev->phydev->speed) { default: netdev_err(net_dev, "Unsupported speed. Defaulting to 1000Mb\n"); - /* fall through */ + fallthrough; case SPEED_1000: val |= NICPM_IOMUX_CTRL_SPD_1000M << NICPM_IOMUX_CTRL_SPD_SHIFT; break; diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index c8cc14eadbb4..3e8a179f39db 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -1337,13 +1337,13 @@ bnx2_set_mac_link(struct bnx2 *bp) val |= BNX2_EMAC_MODE_PORT_MII_10M; break; } - /* fall through */ + fallthrough; case SPEED_100: val |= BNX2_EMAC_MODE_PORT_MII; break; case SPEED_2500: val |= BNX2_EMAC_MODE_25G_MODE; - /* fall through */ + fallthrough; case SPEED_1000: val |= BNX2_EMAC_MODE_PORT_GMII; break; @@ -1995,26 +1995,26 @@ bnx2_remote_phy_event(struct bnx2 *bp) switch (speed) { case BNX2_LINK_STATUS_10HALF: bp->duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case BNX2_LINK_STATUS_10FULL: bp->line_speed = SPEED_10; break; case BNX2_LINK_STATUS_100HALF: bp->duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case BNX2_LINK_STATUS_100BASE_T4: case BNX2_LINK_STATUS_100FULL: bp->line_speed = SPEED_100; break; case BNX2_LINK_STATUS_1000HALF: bp->duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case BNX2_LINK_STATUS_1000FULL: bp->line_speed = SPEED_1000; break; case BNX2_LINK_STATUS_2500HALF: bp->duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case BNX2_LINK_STATUS_2500FULL: bp->line_speed = SPEED_2500; break; @@ -7856,7 +7856,7 @@ bnx2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = bp->phy_addr; - /* fallthru */ + fallthrough; case SIOCGMIIREG: { u32 mii_regval; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1426c691c7c4..4e85e7dbc2be 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -4712,14 +4712,14 @@ static void bnx2x_sync_link(struct link_params *params, LINK_STATUS_SPEED_AND_DUPLEX_MASK) { case LINK_10THD: vars->duplex = DUPLEX_HALF; - /* Fall thru */ + fallthrough; case LINK_10TFD: vars->line_speed = SPEED_10; break; case LINK_100TXHD: vars->duplex = DUPLEX_HALF; - /* Fall thru */ + fallthrough; case LINK_100T4: case LINK_100TXFD: vars->line_speed = SPEED_100; @@ -4727,14 +4727,14 @@ static void bnx2x_sync_link(struct link_params *params, case LINK_1000THD: vars->duplex = DUPLEX_HALF; - /* Fall thru */ + fallthrough; case LINK_1000TFD: vars->line_speed = SPEED_1000; break; case LINK_2500THD: vars->duplex = DUPLEX_HALF; - /* Fall thru */ + fallthrough; case LINK_2500TFD: vars->line_speed = SPEED_2500; break; @@ -6339,7 +6339,7 @@ int bnx2x_set_led(struct link_params *params, */ if (!vars->link_up) break; - /* fall through */ + fallthrough; case LED_MODE_ON: if (((params->phy[EXT_PHY1].type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) || @@ -12508,13 +12508,13 @@ static void bnx2x_phy_def_cfg(struct link_params *params, switch (link_config & PORT_FEATURE_LINK_SPEED_MASK) { case PORT_FEATURE_LINK_SPEED_10M_HALF: phy->req_duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case PORT_FEATURE_LINK_SPEED_10M_FULL: phy->req_line_speed = SPEED_10; break; case PORT_FEATURE_LINK_SPEED_100M_HALF: phy->req_duplex = DUPLEX_HALF; - /* fall through */ + fallthrough; case PORT_FEATURE_LINK_SPEED_100M_FULL: phy->req_line_speed = SPEED_100; break; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 7f24d2689fdd..3c543dd7a8f3 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -8600,11 +8600,11 @@ int bnx2x_set_int_mode(struct bnx2x *bp) bp->num_queues, 1 + bp->num_cnic_queues); - /* fall through */ + fallthrough; case BNX2X_INT_MODE_MSI: bnx2x_enable_msi(bp); - /* fall through */ + fallthrough; case BNX2X_INT_MODE_INTX: bp->num_ethernet_queues = 1; bp->num_queues = bp->num_ethernet_queues + bp->num_cnic_queues; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 80d250a6d048..e26f4da5a6d7 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -3258,7 +3258,7 @@ static int bnx2x_mcast_validate_e2(struct bnx2x *bp, /* DEL command deletes all currently configured MACs */ case BNX2X_MCAST_CMD_DEL: o->set_registry_size(o, 0); - /* fall through */ + fallthrough; /* RESTORE command will restore the entire multicast configuration */ case BNX2X_MCAST_CMD_RESTORE: @@ -3592,7 +3592,7 @@ static int bnx2x_mcast_validate_e1(struct bnx2x *bp, /* DEL command deletes all currently configured MACs */ case BNX2X_MCAST_CMD_DEL: o->set_registry_size(o, 0); - /* fall through */ + fallthrough; /* RESTORE command will restore the entire multicast configuration */ case BNX2X_MCAST_CMD_RESTORE: diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c index b4476f44e386..9c2f51f23035 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c @@ -1809,7 +1809,7 @@ get_vf: DP(BNX2X_MSG_IOV, "got VF [%d:%d] RSS update ramrod\n", vf->abs_vfid, qidx); bnx2x_vf_handle_rss_update_eqe(bp, vf); - /* fall through */ + fallthrough; case EVENT_RING_OPCODE_VF_FLR: /* Do nothing for now */ return 0; @@ -2207,7 +2207,7 @@ int bnx2x_vf_free(struct bnx2x *bp, struct bnx2x_virtf *vf) rc = bnx2x_vf_close(bp, vf); if (rc) goto op_err; - /* Fall through - to release resources */ + fallthrough; /* to release resources */ case VF_ACQUIRED: DP(BNX2X_MSG_IOV, "about to free resources\n"); bnx2x_vf_free_resc(bp, vf); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 31fb5a28e1c4..f92fd8863f48 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1923,7 +1923,7 @@ u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx) break; case BNXT_FW_HEALTH_REG_TYPE_GRC: reg_off = fw_health->mapped_regs[reg_idx]; - /* fall through */ + fallthrough; case BNXT_FW_HEALTH_REG_TYPE_BAR0: val = readl(bp->bar0 + reg_off); break; @@ -1966,11 +1966,11 @@ static int bnxt_async_event_process(struct bnxt *bp, } set_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event); } - /* fall through */ + fallthrough; case ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE: case ASYNC_EVENT_CMPL_EVENT_ID_PORT_PHY_CFG_CHANGE: set_bit(BNXT_LINK_CFG_CHANGE_SP_EVENT, &bp->sp_event); - /* fall through */ + fallthrough; case ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE: set_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event); break; @@ -9765,7 +9765,7 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: mdio->phy_id = bp->link_info.phy_addr; - /* fallthru */ + fallthrough; case SIOCGMIIREG: { u16 mii_regval = 0; @@ -11022,7 +11022,7 @@ static void bnxt_fw_reset_writel(struct bnxt *bp, int reg_idx) writel(reg_off & BNXT_GRC_BASE_MASK, bp->bar0 + BNXT_GRCPF_REG_WINDOW_BASE_OUT + 4); reg_off = (reg_off & BNXT_GRC_OFFSET_MASK) + 0x2000; - /* fall through */ + fallthrough; case BNXT_FW_HEALTH_REG_TYPE_BAR0: writel(val, bp->bar0 + reg_off); break; @@ -11135,7 +11135,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) } bp->fw_reset_state = BNXT_FW_RESET_STATE_RESET_FW; } - /* fall through */ + fallthrough; case BNXT_FW_RESET_STATE_RESET_FW: bnxt_reset_all(bp); bp->fw_reset_state = BNXT_FW_RESET_STATE_ENABLE_DEV; @@ -11158,7 +11158,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) } pci_set_master(bp->pdev); bp->fw_reset_state = BNXT_FW_RESET_STATE_POLL_FW; - /* fall through */ + fallthrough; case BNXT_FW_RESET_STATE_POLL_FW: bp->hwrm_cmd_timeout = SHORT_HWRM_CMD_TIMEOUT; rc = __bnxt_hwrm_ver_get(bp, true); @@ -11173,7 +11173,7 @@ static void bnxt_fw_reset_task(struct work_struct *work) } bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT; bp->fw_reset_state = BNXT_FW_RESET_STATE_OPENING; - /* fall through */ + fallthrough; case BNXT_FW_RESET_STATE_OPENING: while (!rtnl_trylock()) { bnxt_queue_fw_reset_work(bp, HZ / 10); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 64da654f1038..17934cd87a4a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1073,7 +1073,7 @@ static int bnxt_grxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd) if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV4) cmd->data |= RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ + fallthrough; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case AH_V4_FLOW: @@ -1092,7 +1092,7 @@ static int bnxt_grxfh(struct bnxt *bp, struct ethtool_rxnfc *cmd) if (bp->rss_hash_cfg & VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6) cmd->data |= RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ + fallthrough; case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c index 2704a4709bc7..fcc262064766 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c @@ -201,10 +201,10 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, break; default: bpf_warn_invalid_xdp_action(act); - /* Fall thru */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(bp->dev, xdp_prog, act); - /* Fall thru */ + fallthrough; case XDP_DROP: bnxt_reuse_rx_data(rxr, cons, page); break; diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index c5cca63b8571..84536292b031 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -3311,7 +3311,7 @@ static int cnic_ctl(void *data, struct cnic_ctl_info *info) } case CNIC_CTL_FCOE_STATS_GET_CMD: ulp_type = CNIC_ULP_FCOE; - /* fall through */ + fallthrough; case CNIC_CTL_ISCSI_STATS_GET_CMD: cnic_hold(dev); cnic_copy_ulp_stats(dev, ulp_type); @@ -4044,7 +4044,7 @@ static void cnic_cm_process_kcqe(struct cnic_dev *dev, struct kcqe *kcqe) l4kcqe->status, l5kcqe->completion_status); opcode = L4_KCQE_OPCODE_VALUE_CLOSE_COMP; } - /* Fall through */ + fallthrough; case L4_KCQE_OPCODE_VALUE_RESET_RECEIVED: case L4_KCQE_OPCODE_VALUE_CLOSE_COMP: case L4_KCQE_OPCODE_VALUE_RESET_COMP: diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 1fecc25767bd..0ca8436d2e9d 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1185,10 +1185,10 @@ static void bcmgenet_update_mib_counters(struct bcmgenet_priv *priv) continue; case BCMGENET_STAT_RUNT: offset += BCMGENET_STAT_OFFSET; - /* fall through */ + fallthrough; case BCMGENET_STAT_MIB_TX: offset += BCMGENET_STAT_OFFSET; - /* fall through */ + fallthrough; case BCMGENET_STAT_MIB_RX: val = bcmgenet_umac_readl(priv, UMAC_MIB_START + j + offset); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 511d553a4d11..6fb6c3556285 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -192,7 +192,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) switch (priv->phy_interface) { case PHY_INTERFACE_MODE_INTERNAL: phy_name = "internal PHY"; - /* fall through */ + fallthrough; case PHY_INTERFACE_MODE_MOCA: /* Irrespective of the actually configured PHY speed (100 or * 1000) GENETv4 only has an internal GPHY so we will just end diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ebff1fc0d8ce..9894594d957d 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -715,7 +715,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) case TG3_APE_LOCK_GPIO: if (tg3_asic_rev(tp) == ASIC_REV_5761) return 0; - /* fall through */ + fallthrough; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: if (!tp->pci_fn) @@ -776,7 +776,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) case TG3_APE_LOCK_GPIO: if (tg3_asic_rev(tp) == ASIC_REV_5761) return; - /* fall through */ + fallthrough; case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: if (!tp->pci_fn) @@ -1586,7 +1586,7 @@ static int tg3_mdio_init(struct tg3 *tp) phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE; if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN)) phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE; - /* fall through */ + fallthrough; case PHY_ID_RTL8211C: phydev->interface = PHY_INTERFACE_MODE_RGMII; break; @@ -2114,7 +2114,7 @@ static int tg3_phy_init(struct tg3 *tp) phy_support_asym_pause(phydev); break; } - /* fall through */ + fallthrough; case PHY_INTERFACE_MODE_MII: phy_set_max_speed(phydev, SPEED_100); phy_support_asym_pause(phydev); @@ -4390,7 +4390,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) MII_TG3_DSP_TAP26_RMRXSTO | MII_TG3_DSP_TAP26_OPCSINPT; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - /* Fall through */ + fallthrough; case ASIC_REV_5720: case ASIC_REV_5762: if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val)) @@ -4538,7 +4538,7 @@ static int tg3_phy_pull_config(struct tg3 *tp) tp->link_config.speed = SPEED_1000; break; } - /* Fall through */ + fallthrough; default: goto done; } @@ -5209,7 +5209,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN)) ap->state = ANEG_STATE_AN_ENABLE; - /* fall through */ + fallthrough; case ANEG_STATE_AN_ENABLE: ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX); if (ap->flags & MR_AN_ENABLE) { @@ -5239,7 +5239,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, ret = ANEG_TIMER_ENAB; ap->state = ANEG_STATE_RESTART; - /* fall through */ + fallthrough; case ANEG_STATE_RESTART: delta = ap->cur_time - ap->link_time; if (delta > ANEG_STATE_SETTLE_TIME) @@ -5282,7 +5282,7 @@ static int tg3_fiber_aneg_smachine(struct tg3 *tp, ap->state = ANEG_STATE_ACK_DETECT; - /* fall through */ + fallthrough; case ANEG_STATE_ACK_DETECT: if (ap->ack_match != 0) { if ((ap->rxconfig & ~ANEG_CFG_ACK) == @@ -10720,40 +10720,40 @@ static int tg3_reset_hw(struct tg3 *tp, bool reset_phy) switch (limit) { case 16: tw32(MAC_RCV_RULE_15, 0); tw32(MAC_RCV_VALUE_15, 0); - /* fall through */ + fallthrough; case 15: tw32(MAC_RCV_RULE_14, 0); tw32(MAC_RCV_VALUE_14, 0); - /* fall through */ + fallthrough; case 14: tw32(MAC_RCV_RULE_13, 0); tw32(MAC_RCV_VALUE_13, 0); - /* fall through */ + fallthrough; case 13: tw32(MAC_RCV_RULE_12, 0); tw32(MAC_RCV_VALUE_12, 0); - /* fall through */ + fallthrough; case 12: tw32(MAC_RCV_RULE_11, 0); tw32(MAC_RCV_VALUE_11, 0); - /* fall through */ + fallthrough; case 11: tw32(MAC_RCV_RULE_10, 0); tw32(MAC_RCV_VALUE_10, 0); - /* fall through */ + fallthrough; case 10: tw32(MAC_RCV_RULE_9, 0); tw32(MAC_RCV_VALUE_9, 0); - /* fall through */ + fallthrough; case 9: tw32(MAC_RCV_RULE_8, 0); tw32(MAC_RCV_VALUE_8, 0); - /* fall through */ + fallthrough; case 8: tw32(MAC_RCV_RULE_7, 0); tw32(MAC_RCV_VALUE_7, 0); - /* fall through */ + fallthrough; case 7: tw32(MAC_RCV_RULE_6, 0); tw32(MAC_RCV_VALUE_6, 0); - /* fall through */ + fallthrough; case 6: tw32(MAC_RCV_RULE_5, 0); tw32(MAC_RCV_VALUE_5, 0); - /* fall through */ + fallthrough; case 5: tw32(MAC_RCV_RULE_4, 0); tw32(MAC_RCV_VALUE_4, 0); - /* fall through */ + fallthrough; case 4: /* tw32(MAC_RCV_RULE_3, 0); tw32(MAC_RCV_VALUE_3, 0); */ case 3: @@ -13998,7 +13998,7 @@ static int tg3_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = tp->phy_addr; - /* fall through */ + fallthrough; case SIOCGMIIREG: { u32 mii_regval; @@ -17136,7 +17136,7 @@ static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val) val |= DMA_RWCTRL_WRITE_BNDRY_64_PCIE; break; } - /* fallthrough */ + fallthrough; case 128: default: val &= ~DMA_RWCTRL_WRITE_BNDRY_DISAB_PCIE; @@ -17151,28 +17151,28 @@ static u32 tg3_calc_dma_bndry(struct tg3 *tp, u32 val) DMA_RWCTRL_WRITE_BNDRY_16); break; } - /* fallthrough */ + fallthrough; case 32: if (goal == BOUNDARY_SINGLE_CACHELINE) { val |= (DMA_RWCTRL_READ_BNDRY_32 | DMA_RWCTRL_WRITE_BNDRY_32); break; } - /* fallthrough */ + fallthrough; case 64: if (goal == BOUNDARY_SINGLE_CACHELINE) { val |= (DMA_RWCTRL_READ_BNDRY_64 | DMA_RWCTRL_WRITE_BNDRY_64); break; } - /* fallthrough */ + fallthrough; case 128: if (goal == BOUNDARY_SINGLE_CACHELINE) { val |= (DMA_RWCTRL_READ_BNDRY_128 | DMA_RWCTRL_WRITE_BNDRY_128); break; } - /* fallthrough */ + fallthrough; case 256: val |= (DMA_RWCTRL_READ_BNDRY_256 | DMA_RWCTRL_WRITE_BNDRY_256); diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 49358d42a0e2..b9dd06b12945 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -321,7 +321,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) case IOC_E_PFFAILED: case IOC_E_HWERROR: del_timer(&ioc->ioc_timer); - /* fall through */ + fallthrough; case IOC_E_TIMEOUT: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); @@ -780,7 +780,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_INITFAIL: del_timer(&ioc->iocpf_timer); - /* fall through */ + fallthrough; case IOCPF_E_TIMEOUT: bfa_nw_ioc_hw_sem_release(ioc); @@ -849,7 +849,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_FAIL: del_timer(&ioc->iocpf_timer); - /* fall through*/ + fallthrough; case IOCPF_E_TIMEOUT: bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); diff --git a/drivers/net/ethernet/brocade/bna/bna_enet.c b/drivers/net/ethernet/brocade/bna/bna_enet.c index 40107a9bd120..a2c983f56b00 100644 --- a/drivers/net/ethernet/brocade/bna/bna_enet.c +++ b/drivers/net/ethernet/brocade/bna/bna_enet.c @@ -1084,7 +1084,7 @@ bna_enet_sm_cfg_wait(struct bna_enet *enet, case ENET_E_CHLD_STOPPED: bna_enet_rx_start(enet); - /* Fall through */ + fallthrough; case ENET_E_FWRESP_PAUSE: if (enet->flags & BNA_ENET_F_PAUSE_CHANGED) { enet->flags &= ~BNA_ENET_F_PAUSE_CHANGED; diff --git a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c index b5ecbfe13ab0..2623a0da4682 100644 --- a/drivers/net/ethernet/brocade/bna/bna_tx_rx.c +++ b/drivers/net/ethernet/brocade/bna/bna_tx_rx.c @@ -1636,7 +1636,7 @@ bna_bfi_rx_enet_start(struct bna_rx *rx) &q1->qpt); cfg_req->q_cfg[i].qs.rx_buffer_size = htons((u16)q1->buffer_size); - /* Fall through */ + fallthrough; case BNA_RXP_SINGLE: /* Large/Single RxQ */ diff --git a/drivers/net/ethernet/cadence/macb_ptp.c b/drivers/net/ethernet/cadence/macb_ptp.c index 31ebf3ee7ec0..283918aeb741 100644 --- a/drivers/net/ethernet/cadence/macb_ptp.c +++ b/drivers/net/ethernet/cadence/macb_ptp.c @@ -460,7 +460,7 @@ int gem_set_hwtst(struct net_device *dev, struct ifreq *ifr, int cmd) case HWTSTAMP_TX_ONESTEP_SYNC: if (gem_ptp_set_one_step_sync(bp, 1) != 0) return -ERANGE; - /* fall through */ + fallthrough; case HWTSTAMP_TX_ON: tx_bd_control = TSTAMP_ALL_FRAMES; break; diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index e73bc211779a..8e0ed01e7f03 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -977,15 +977,14 @@ static void octeon_destroy_resources(struct octeon_device *oct) schedule_timeout_uninterruptible(HZ / 10); - /* fallthrough */ + fallthrough; case OCT_DEV_HOST_OK: - /* fallthrough */ case OCT_DEV_CONSOLE_INIT_DONE: /* Remove any consoles */ octeon_remove_consoles(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_IO_QUEUES_DONE: if (lio_wait_for_instr_fetch(oct)) dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n"); @@ -1027,7 +1026,7 @@ static void octeon_destroy_resources(struct octeon_device *oct) octeon_free_sc_done_list(oct); octeon_free_sc_zombie_list(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_INTR_SET_DONE: /* Disable interrupts */ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); @@ -1062,17 +1061,17 @@ static void octeon_destroy_resources(struct octeon_device *oct) kfree(oct->irq_name_storage); oct->irq_name_storage = NULL; - /* fallthrough */ + fallthrough; case OCT_DEV_MSIX_ALLOC_VECTOR_DONE: if (OCTEON_CN23XX_PF(oct)) octeon_free_ioq_vector(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_MBOX_SETUP_DONE: if (OCTEON_CN23XX_PF(oct)) oct->fn_list.free_mbox(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_IN_RESET: case OCT_DEV_DROQ_INIT_DONE: /* Wait for any pending operations */ @@ -1095,11 +1094,11 @@ static void octeon_destroy_resources(struct octeon_device *oct) } } - /* fallthrough */ + fallthrough; case OCT_DEV_RESP_LIST_INIT_DONE: octeon_delete_response_list(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_INSTR_QUEUE_INIT_DONE: for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { if (!(oct->io_qmask.iq & BIT_ULL(i))) @@ -1110,16 +1109,16 @@ static void octeon_destroy_resources(struct octeon_device *oct) if (oct->sriov_info.sriov_enabled) pci_disable_sriov(oct->pci_dev); #endif - /* fallthrough */ + fallthrough; case OCT_DEV_SC_BUFF_POOL_INIT_DONE: octeon_free_sc_buffer_pool(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_DISPATCH_INIT_DONE: octeon_delete_dispatch_list(oct); cancel_delayed_work_sync(&oct->nic_poll_work.work); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_MAP_DONE: refcount = octeon_deregister_device(oct); @@ -1137,13 +1136,13 @@ static void octeon_destroy_resources(struct octeon_device *oct) octeon_unmap_pci_barx(oct, 0); octeon_unmap_pci_barx(oct, 1); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_ENABLE_DONE: pci_clear_master(oct->pci_dev); /* Disable the device, releasing the PCI INT */ pci_disable_device(oct->pci_dev); - /* fallthrough */ + fallthrough; case OCT_DEV_BEGIN_STATE: /* Nothing to be done here either */ break; @@ -2168,7 +2167,7 @@ static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) case SIOCSHWTSTAMP: if (lio->oct_dev->ptp_enable) return hwtstamp_ioctl(netdev, ifr); - /* fall through */ + fallthrough; default: return -EOPNOTSUPP; } diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c index 90ef21086f27..8c5879e31240 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c @@ -460,9 +460,8 @@ static void octeon_destroy_resources(struct octeon_device *oct) schedule_timeout_uninterruptible(HZ / 10); - /* fallthrough */ + fallthrough; case OCT_DEV_HOST_OK: - /* fallthrough */ case OCT_DEV_IO_QUEUES_DONE: if (lio_wait_for_instr_fetch(oct)) dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n"); @@ -504,7 +503,7 @@ static void octeon_destroy_resources(struct octeon_device *oct) octeon_free_sc_done_list(oct); octeon_free_sc_zombie_list(oct); - /* fall through */ + fallthrough; case OCT_DEV_INTR_SET_DONE: /* Disable interrupts */ oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); @@ -533,15 +532,15 @@ static void octeon_destroy_resources(struct octeon_device *oct) else cn23xx_vf_ask_pf_to_do_flr(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_MSIX_ALLOC_VECTOR_DONE: octeon_free_ioq_vector(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_MBOX_SETUP_DONE: oct->fn_list.free_mbox(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_IN_RESET: case OCT_DEV_DROQ_INIT_DONE: mdelay(100); @@ -551,11 +550,11 @@ static void octeon_destroy_resources(struct octeon_device *oct) octeon_delete_droq(oct, i); } - /* fallthrough */ + fallthrough; case OCT_DEV_RESP_LIST_INIT_DONE: octeon_delete_response_list(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_INSTR_QUEUE_INIT_DONE: for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { if (!(oct->io_qmask.iq & BIT_ULL(i))) @@ -563,27 +562,27 @@ static void octeon_destroy_resources(struct octeon_device *oct) octeon_delete_instr_queue(oct, i); } - /* fallthrough */ + fallthrough; case OCT_DEV_SC_BUFF_POOL_INIT_DONE: octeon_free_sc_buffer_pool(oct); - /* fallthrough */ + fallthrough; case OCT_DEV_DISPATCH_INIT_DONE: octeon_delete_dispatch_list(oct); cancel_delayed_work_sync(&oct->nic_poll_work.work); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_MAP_DONE: octeon_unmap_pci_barx(oct, 0); octeon_unmap_pci_barx(oct, 1); - /* fallthrough */ + fallthrough; case OCT_DEV_PCI_ENABLE_DONE: pci_clear_master(oct->pci_dev); /* Disable the device, releasing the PCI INT */ pci_disable_device(oct->pci_dev); - /* fallthrough */ + fallthrough; case OCT_DEV_BEGIN_STATE: /* Nothing to be done here either */ break; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c index 83dabcffc789..c7bdac79299a 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c @@ -522,7 +522,7 @@ static int nicvf_get_rss_hash_opts(struct nicvf *nic, case SCTP_V4_FLOW: case SCTP_V6_FLOW: info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + fallthrough; case IPV4_FLOW: case IPV6_FLOW: info->data |= RXH_IP_SRC | RXH_IP_DST; diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index c1378b5c780c..063e560d9c1b 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -594,10 +594,10 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog, return true; default: bpf_warn_invalid_xdp_action(action); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(nic->netdev, prog, action); - /* fall through */ + fallthrough; case XDP_DROP: /* Check if it's a recycled page, if not * unmap the DMA mapping. diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 42c6e9379882..387c357e1b8e 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -2543,7 +2543,7 @@ static int cxgb_ioctl(struct net_device *dev, struct ifreq *req, int cmd) !(data->phy_id & 0xe0e0)) data->phy_id = mdio_phy_id_c45(data->phy_id >> 8, data->phy_id & 0x1f); - /* FALLTHRU */ + fallthrough; case SIOCGMIIPHY: return mdio_mii_ioctl(&pi->phy.mdio, data, cmd); case SIOCCHIOCTL: diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.c b/drivers/net/ethernet/chelsio/cxgb3/l2t.c index b3e4118a15e7..9749d1239f58 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.c @@ -136,7 +136,7 @@ again: if (e->state == L2T_STATE_STALE) e->state = L2T_STATE_VALID; spin_unlock_bh(&e->lock); - /* fall through */ + fallthrough; case L2T_STATE_VALID: /* fast-path, send the packet on */ return cxgb3_ofld_send(dev, skb); case L2T_STATE_RESOLVING: diff --git a/drivers/net/ethernet/chelsio/cxgb4/l2t.c b/drivers/net/ethernet/chelsio/cxgb4/l2t.c index c4864125fe02..a10a6862a9a4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/l2t.c +++ b/drivers/net/ethernet/chelsio/cxgb4/l2t.c @@ -231,7 +231,7 @@ again: if (e->state == L2T_STATE_STALE) e->state = L2T_STATE_VALID; spin_unlock_bh(&e->lock); - /* fall through */ + fallthrough; case L2T_STATE_VALID: /* fast-path, send the packet on */ return t4_ofld_send(adap, skb); case L2T_STATE_RESOLVING: diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 8a56491bb034..fa3367966f4b 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -7656,13 +7656,13 @@ int t4_alloc_vi(struct adapter *adap, unsigned int mbox, unsigned int port, switch (nmac) { case 5: memcpy(mac + 24, c.nmac3, sizeof(c.nmac3)); - /* Fall through */ + fallthrough; case 4: memcpy(mac + 18, c.nmac2, sizeof(c.nmac2)); - /* Fall through */ + fallthrough; case 3: memcpy(mac + 12, c.nmac1, sizeof(c.nmac1)); - /* Fall through */ + fallthrough; case 2: memcpy(mac + 6, c.nmac0, sizeof(c.nmac0)); } diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index dbe8ee7e0e21..e2fe78e2e242 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -517,7 +517,7 @@ static int fwevtq_handler(struct sge_rspq *rspq, const __be64 *rsp, } cpl = (void *)p; } - /* Fall through */ + fallthrough; case CPL_SGE_EGR_UPDATE: { /* diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 6bc7e7ba38c3..552d89fdf54a 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -272,7 +272,7 @@ static netdev_features_t enic_features_check(struct sk_buff *skb, case ntohs(ETH_P_IPV6): if (!(enic->vxlan.flags & ENIC_VXLAN_INNER_IPV6)) goto out; - /* Fall through */ + fallthrough; case ntohs(ETH_P_IP): break; default: diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 7f7705138262..5c6c8c5ec747 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -385,7 +385,7 @@ static void dm9000_set_io(struct board_info *db, int byte_width) case 3: dev_dbg(db->dev, ": 3 byte IO, falling back to 16bit\n"); - /* fall through */ + fallthrough; case 2: db->dumpblk = dm9000_dumpblk_16bit; db->outblk = dm9000_outblk_16bit; diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 0ccd9994ad45..f9dd1aa9f2da 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -3203,7 +3203,7 @@ srom_map_media(struct net_device *dev) case SROM_10BASETF: if (!lp->params.fdx) return -1; lp->fdx = true; - /* fall through */ + fallthrough; case SROM_10BASET: if (lp->params.fdx && !lp->fdx) return -1; @@ -3225,7 +3225,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASETF: if (!lp->params.fdx) return -1; lp->fdx = true; - /* fall through */ + fallthrough; case SROM_100BASET: if (lp->params.fdx && !lp->fdx) return -1; @@ -3239,7 +3239,7 @@ srom_map_media(struct net_device *dev) case SROM_100BASEFF: if (!lp->params.fdx) return -1; lp->fdx = true; - /* fall through */ + fallthrough; case SROM_100BASEF: if (lp->params.fdx && !lp->fdx) return -1; diff --git a/drivers/net/ethernet/dec/tulip/tulip_core.c b/drivers/net/ethernet/dec/tulip/tulip_core.c index 9db23527275a..3a8659c5da06 100644 --- a/drivers/net/ethernet/dec/tulip/tulip_core.c +++ b/drivers/net/ethernet/dec/tulip/tulip_core.c @@ -911,7 +911,7 @@ static int private_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) data->phy_id = 1; else return -ENODEV; - /* Fall through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ if (data->phy_id == 32 && (tp->flags & HAS_NWAY)) { diff --git a/drivers/net/ethernet/dec/tulip/winbond-840.c b/drivers/net/ethernet/dec/tulip/winbond-840.c index 5dcc66f60144..5a43be327f58 100644 --- a/drivers/net/ethernet/dec/tulip/winbond-840.c +++ b/drivers/net/ethernet/dec/tulip/winbond-840.c @@ -1443,7 +1443,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = ((struct netdev_private *)netdev_priv(dev))->phys[0] & 0x1f; - /* Fall Through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ spin_lock_irq(&np->lock); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index d6ed1d943762..99cc1c46fb30 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -571,7 +571,7 @@ static u32 convert_to_et_setting(struct be_adapter *adapter, u32 if_speeds) break; } } - /* fall through */ + fallthrough; case PHY_TYPE_SFP_PLUS_10GB: case PHY_TYPE_XFP_10GB: case PHY_TYPE_SFP_1GB: diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 43570f4911ea..fdff3b4723ba 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -945,7 +945,7 @@ static void dpaa_fq_setup(struct dpaa_priv *priv, break; case FQ_TYPE_TX_CONF_MQ: priv->conf_fqs[conf_cnt++] = &fq->fq_base; - /* fall through */ + fallthrough; case FQ_TYPE_TX_CONFIRM: dpaa_setup_ingress(priv, fq, &fq_cbs->tx_defq); break; diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c index 9db2a02fb531..1268996b7030 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c @@ -375,7 +375,7 @@ static int dpaa_get_hash_opts(struct net_device *dev, case UDP_V6_FLOW: if (priv->keygen_in_use) cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + fallthrough; case IPV4_FLOW: case IPV6_FLOW: case SCTP_V4_FLOW: diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index 457106e761be..cf5383bb8331 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -376,10 +376,10 @@ static u32 run_xdp(struct dpaa2_eth_priv *priv, break; default: bpf_warn_invalid_xdp_action(xdp_act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(priv->net_dev, xdp_prog, xdp_act); - /* fall through */ + fallthrough; case XDP_DROP: xdp_release_buf(priv, ch, addr); ch->stats.xdp_drop++; diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 645764abdaae..bb9887f98841 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -528,7 +528,7 @@ static void setup_sgmii_internal_phy(struct fman_mac *memac, case 100: tmp_reg16 |= IF_MODE_SGMII_SPEED_100M; break; - case 1000: /* fallthrough */ + case 1000: default: tmp_reg16 |= IF_MODE_SGMII_SPEED_1G; break; diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c index c27df153f895..624b2eb6f01d 100644 --- a/drivers/net/ethernet/freescale/fman/fman_port.c +++ b/drivers/net/ethernet/freescale/fman/fman_port.c @@ -1344,10 +1344,10 @@ int fman_port_config(struct fman_port *port, struct fman_port_params *params) switch (port->port_type) { case FMAN_PORT_TYPE_RX: set_rx_dflt_cfg(port, params); - /* fall through */ + fallthrough; case FMAN_PORT_TYPE_TX: set_tx_dflt_cfg(port, params, &port->dts_params); - /* fall through */ + fallthrough; default: set_dflt_cfg(port, params); } diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c index db791f60b884..714b501be7d0 100644 --- a/drivers/net/ethernet/freescale/ucc_geth.c +++ b/drivers/net/ethernet/freescale/ucc_geth.c @@ -1348,7 +1348,7 @@ static int adjust_enet_interface(struct ucc_geth_private *ugeth) switch (ugeth->max_speed) { case SPEED_10: upsmr |= UCC_GETH_UPSMR_R10M; - /* FALLTHROUGH */ + fallthrough; case SPEED_100: if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI) upsmr |= UCC_GETH_UPSMR_RMM; diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 49624acf2473..4eb50296f653 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -305,7 +305,7 @@ static int __lb_setup(struct net_device *ndev, break; case MAC_LOOP_PHY_NONE: ret = hns_nic_config_phy_loopback(phy_dev, 0x0); - /* fall through */ + fallthrough; case MAC_LOOP_NONE: if (!ret && h->dev->ops->set_loopback) { if (priv->ae_handle->phy_if != PHY_INTERFACE_MODE_XGMII) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 87776ce3539b..c2ea0348b2f7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -2746,7 +2746,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, case HNS3_OL4_TYPE_MAC_IN_UDP: case HNS3_OL4_TYPE_NVGRE: skb->csum_level = 1; - /* fall through */ + fallthrough; case HNS3_OL4_TYPE_NO_TUN: l3_type = hnae3_get_field(l234info, HNS3_RXD_L3ID_M, HNS3_RXD_L3ID_S); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 36575e72a915..d553ed7ee64c 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3061,7 +3061,7 @@ static irqreturn_t hclge_misc_irq_handle(int irq, void *data) * by first decoding the types of errors. */ set_bit(HNAE3_UNKNOWN_RESET, &hdev->reset_request); - /* fall through */ + fallthrough; case HCLGE_VECTOR0_EVENT_RST: hclge_reset_task_schedule(hdev); break; @@ -3686,12 +3686,10 @@ static int hclge_reset_prepare_up(struct hclge_dev *hdev) switch (hdev->reset_type) { case HNAE3_FUNC_RESET: - /* fall through */ case HNAE3_FLR_RESET: ret = hclge_set_all_vf_rst(hdev, false); break; case HNAE3_GLOBAL_RESET: - /* fall through */ case HNAE3_IMP_RESET: ret = hclge_set_rst_done(hdev); break; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index 0273fb7a9d01..3153d62cc73e 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3247,7 +3247,7 @@ static int ehea_mem_notifier(struct notifier_block *nb, switch (action) { case MEM_CANCEL_OFFLINE: pr_info("memory offlining canceled"); - /* Fall through - re-add canceled memory block */ + fallthrough; /* re-add canceled memory block */ case MEM_ONLINE: pr_info("memory is going online"); diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 06248a7db7f2..c00b9097eeea 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -2319,7 +2319,7 @@ static int emac_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCGMIIPHY: data->phy_id = dev->phy.address; - /* Fall through */ + fallthrough; case SIOCGMIIREG: data->val_out = emac_mdio_read(ndev, dev->phy.address, data->reg_num); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 63dde3bcf5bc..664e8ccc88d2 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4079,7 +4079,6 @@ void e1000e_reset(struct e1000_adapter *adapter) case e1000_pch_lpt: case e1000_pch_spt: case e1000_pch_cnp: - fallthrough; case e1000_pch_tgp: case e1000_pch_adp: fc->refresh_time = 0xFFFF; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 4f05f6efe6af..d9c3a6b169f9 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -718,7 +718,6 @@ static void igb_cache_ring_register(struct igb_adapter *adapter) case e1000_i354: case e1000_i210: case e1000_i211: - fallthrough; default: for (; i < adapter->num_rx_queues; i++) adapter->rx_ring[i]->reg_idx = rbase_offset + i; diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 832bbb8b05c8..dfcb1767acbb 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2205,10 +2205,10 @@ mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq, break; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(pp->dev, prog, act); - /* fall through */ + fallthrough; case XDP_DROP: mvneta_xdp_put_buff(pp, rxq, xdp, sync, true); ret = MVNETA_XDP_DROPPED; diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c index d4a4e241333d..41d935d1aaf6 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_cls.c @@ -1638,7 +1638,7 @@ int mvpp2_ethtool_rxfh_set(struct mvpp2_port *port, struct ethtool_rxnfc *info) hash_opts |= MVPP22_CLS_HEK_OPT_L4SIP; if (info->data & RXH_L4_B_2_3) hash_opts |= MVPP22_CLS_HEK_OPT_L4DIP; - /* Fallthrough */ + fallthrough; case MVPP22_FLOW_IP4: case MVPP22_FLOW_IP6: if (info->data & RXH_L2DA) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 2a8a5842eaef..6e140d1b8967 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -5437,7 +5437,7 @@ static void mvpp2_phylink_validate(struct phylink_config *config, } if (state->interface != PHY_INTERFACE_MODE_NA) break; - /* Fall-through */ + fallthrough; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: @@ -5451,7 +5451,7 @@ static void mvpp2_phylink_validate(struct phylink_config *config, phylink_set(mask, 1000baseX_Full); if (state->interface != PHY_INTERFACE_MODE_NA) break; - /* Fall-through */ + fallthrough; case PHY_INTERFACE_MODE_1000BASEX: case PHY_INTERFACE_MODE_2500BASEX: if (port->comphy || diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 36953d4f51c7..01a793105599 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -737,7 +737,7 @@ static int rvu_nix_aq_enq_inst(struct rvu *rvu, struct nix_aq_enq_req *req, else if (req->ctype == NIX_AQ_CTYPE_MCE) memcpy(mask, &req->mce_mask, sizeof(struct nix_rx_mce_s)); - /* Fall through */ + fallthrough; case NIX_AQ_INSTOP_INIT: if (req->ctype == NIX_AQ_CTYPE_RQ) memcpy(ctx, &req->rq, sizeof(struct nix_rq_ctx_s)); diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index b792f6306a64..6a930351cb23 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -2448,7 +2448,7 @@ static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = hw->phy_addr; - /* fallthru */ + fallthrough; case SIOCGMIIREG: { u16 val = 0; spin_lock_bh(&hw->phy_lock); diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index cec8124301c7..344864275ed5 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1376,7 +1376,7 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCGMIIPHY: data->phy_id = PHY_ADDR_MARV; - /* fallthru */ + fallthrough; case SIOCGMIIREG: { u16 val = 0; @@ -2764,7 +2764,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx) case OP_RXCHKSVLAN: sky2_rx_tag(sky2, length); - /* fall through */ + fallthrough; case OP_RXCHKS: if (likely(dev->features & NETIF_F_RXCSUM)) sky2_rx_checksum(sky2, status); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 0870fe78ea38..6d2d60675ffd 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -228,7 +228,7 @@ static void mtk_mac_config(struct phylink_config *config, unsigned int mode, if (!MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GMAC1_TRGMII)) goto err_phy; - /* fall through */ + fallthrough; case PHY_INTERFACE_MODE_RGMII_TXID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_ID: @@ -501,11 +501,11 @@ static void mtk_validate(struct phylink_config *config, case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: phylink_set(mask, 1000baseT_Half); - /* fall through */ + fallthrough; case PHY_INTERFACE_MODE_SGMII: phylink_set(mask, 1000baseT_Full); phylink_set(mask, 1000baseX_Full); - /* fall through */ + fallthrough; case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_RMII: case PHY_INTERFACE_MODE_REVMII: diff --git a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c index 7a04c626a2aa..bcd166911d44 100644 --- a/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c +++ b/drivers/net/ethernet/mellanox/mlxfw/mlxfw_fsm.c @@ -72,7 +72,7 @@ static int mlxfw_fsm_state_err(struct mlxfw_dev *mlxfw_dev, case MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET: MLXFW_ERR_MSG(mlxfw_dev, extack, "pending reset", err); break; - case MLXFW_FSM_STATE_ERR_OK: /* fall through */ + case MLXFW_FSM_STATE_ERR_OK: case MLXFW_FSM_STATE_ERR_MAX: MLXFW_ERR_MSG(mlxfw_dev, extack, "unknown error", err); break; @@ -155,7 +155,7 @@ mlxfw_fsm_reactivate_err(struct mlxfw_dev *mlxfw_dev, case MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED: MLXFW_REACT_ERR("fw already activated", err); break; - case MLXFW_FSM_REACTIVATE_STATUS_OK: /* fall through */ + case MLXFW_FSM_REACTIVATE_STATUS_OK: case MLXFW_FSM_REACTIVATE_STATUS_MAX: MLXFW_REACT_ERR("unexpected error", err); break; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 08d101138fbe..ec45a03140d7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -2289,21 +2289,21 @@ int mlxsw_core_module_max_width(struct mlxsw_core *mlxsw_core, u8 module) /* Here we need to get the module width according to the module type. */ switch (module_type) { - case MLXSW_REG_PMTM_MODULE_TYPE_C2C8X: /* fall through */ - case MLXSW_REG_PMTM_MODULE_TYPE_QSFP_DD: /* fall through */ + case MLXSW_REG_PMTM_MODULE_TYPE_C2C8X: + case MLXSW_REG_PMTM_MODULE_TYPE_QSFP_DD: case MLXSW_REG_PMTM_MODULE_TYPE_OSFP: return 8; - case MLXSW_REG_PMTM_MODULE_TYPE_C2C4X: /* fall through */ - case MLXSW_REG_PMTM_MODULE_TYPE_BP_4X: /* fall through */ + case MLXSW_REG_PMTM_MODULE_TYPE_C2C4X: + case MLXSW_REG_PMTM_MODULE_TYPE_BP_4X: case MLXSW_REG_PMTM_MODULE_TYPE_QSFP: return 4; - case MLXSW_REG_PMTM_MODULE_TYPE_C2C2X: /* fall through */ - case MLXSW_REG_PMTM_MODULE_TYPE_BP_2X: /* fall through */ - case MLXSW_REG_PMTM_MODULE_TYPE_SFP_DD: /* fall through */ + case MLXSW_REG_PMTM_MODULE_TYPE_C2C2X: + case MLXSW_REG_PMTM_MODULE_TYPE_BP_2X: + case MLXSW_REG_PMTM_MODULE_TYPE_SFP_DD: case MLXSW_REG_PMTM_MODULE_TYPE_DSFP: return 2; - case MLXSW_REG_PMTM_MODULE_TYPE_C2C1X: /* fall through */ - case MLXSW_REG_PMTM_MODULE_TYPE_BP_1X: /* fall through */ + case MLXSW_REG_PMTM_MODULE_TYPE_C2C1X: + case MLXSW_REG_PMTM_MODULE_TYPE_BP_1X: case MLXSW_REG_PMTM_MODULE_TYPE_SFP: return 1; default: diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 44fa02cbb683..056eeb85be60 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -30,8 +30,8 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: *qsfp = false; break; - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: /* fall-through */ - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP: + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: *qsfp = true; break; @@ -205,7 +205,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, modinfo->type = ETH_MODULE_SFF_8436; modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN; break; - case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */ + case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28: if (module_id == MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28 || module_rev_id >= diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c index 3fe878d7c94c..61719ec89808 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_hwmon.c @@ -259,8 +259,8 @@ static ssize_t mlxsw_hwmon_module_temp_fault_show(struct device *dev, */ fault = 1; break; - case MLXSW_REG_MTBR_NO_CONN: /* fall-through */ - case MLXSW_REG_MTBR_NO_TEMP_SENS: /* fall-through */ + case MLXSW_REG_MTBR_NO_CONN: + case MLXSW_REG_MTBR_NO_TEMP_SENS: case MLXSW_REG_MTBR_INDEX_NA: default: fault = 0; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index fdf9aa8314b2..4186e29119c2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -517,8 +517,8 @@ enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state) return MLXSW_REG_SPMS_STATE_FORWARDING; case BR_STATE_LEARNING: return MLXSW_REG_SPMS_STATE_LEARNING; - case BR_STATE_LISTENING: /* fall-through */ - case BR_STATE_DISABLED: /* fall-through */ + case BR_STATE_LISTENING: + case BR_STATE_DISABLED: case BR_STATE_BLOCKING: return MLXSW_REG_SPMS_STATE_DISCARDING; default: diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index f9ba59641b4d..5240bf11b6c4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -636,11 +636,11 @@ static inline unsigned int mlxsw_sp_kvdl_entry_size(enum mlxsw_sp_kvdl_entry_type type) { switch (type) { - case MLXSW_SP_KVDL_ENTRY_TYPE_ADJ: /* fall through */ - case MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET: /* fall through */ - case MLXSW_SP_KVDL_ENTRY_TYPE_PBS: /* fall through */ - case MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR: /* fall through */ - case MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT: /* fall through */ + case MLXSW_SP_KVDL_ENTRY_TYPE_ADJ: + case MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET: + case MLXSW_SP_KVDL_ENTRY_TYPE_PBS: + case MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR: + case MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT: default: return 1; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 0521e9d48c45..24f1fd1f8d56 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -1164,7 +1164,7 @@ mlxsw_sp_router_ip2me_fib_entry_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id, addr_len = 4; addr_prefix_len = 32; break; - case MLXSW_SP_L3_PROTO_IPV6: /* fall through */ + case MLXSW_SP_L3_PROTO_IPV6: default: WARN_ON(1); return NULL; @@ -4555,14 +4555,14 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp, fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP; return 0; } - /* fall through */ + fallthrough; case RTN_BROADCAST: fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP; return 0; case RTN_BLACKHOLE: fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_BLACKHOLE; return 0; - case RTN_UNREACHABLE: /* fall through */ + case RTN_UNREACHABLE: case RTN_PROHIBIT: /* Packets hitting these routes need to be trapped, but * can do so with a lower priority than packets directed @@ -5990,7 +5990,7 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work) mlxsw_sp_router_fib4_del(mlxsw_sp, &fib_work->fen_info); fib_info_put(fib_work->fen_info.fi); break; - case FIB_EVENT_NH_ADD: /* fall through */ + case FIB_EVENT_NH_ADD: case FIB_EVENT_NH_DEL: mlxsw_sp_nexthop4_event(mlxsw_sp, fib_work->event, fib_work->fnh_info.fib_nh); @@ -6050,7 +6050,7 @@ static void mlxsw_sp_router_fibmr_event_work(struct work_struct *work) rtnl_lock(); mutex_lock(&mlxsw_sp->router->lock); switch (fib_work->event) { - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_ADD: replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE; @@ -6089,7 +6089,7 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work, struct fib_nh_notifier_info *fnh_info; switch (fib_work->event) { - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_DEL: fen_info = container_of(info, struct fib_entry_notifier_info, info); @@ -6099,7 +6099,7 @@ static void mlxsw_sp_router_fib4_event(struct mlxsw_sp_fib_event_work *fib_work, */ fib_info_hold(fib_work->fen_info.fi); break; - case FIB_EVENT_NH_ADD: /* fall through */ + case FIB_EVENT_NH_ADD: case FIB_EVENT_NH_DEL: fnh_info = container_of(info, struct fib_nh_notifier_info, info); @@ -6116,8 +6116,8 @@ static int mlxsw_sp_router_fib6_event(struct mlxsw_sp_fib_event_work *fib_work, int err; switch (fib_work->event) { - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ - case FIB_EVENT_ENTRY_APPEND: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: case FIB_EVENT_ENTRY_DEL: fen6_info = container_of(info, struct fib6_entry_notifier_info, info); @@ -6136,13 +6136,13 @@ mlxsw_sp_router_fibmr_event(struct mlxsw_sp_fib_event_work *fib_work, struct fib_notifier_info *info) { switch (fib_work->event) { - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ - case FIB_EVENT_ENTRY_ADD: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_ADD: case FIB_EVENT_ENTRY_DEL: memcpy(&fib_work->men_info, info, sizeof(fib_work->men_info)); mr_cache_hold(fib_work->men_info.mfc); break; - case FIB_EVENT_VIF_ADD: /* fall through */ + case FIB_EVENT_VIF_ADD: case FIB_EVENT_VIF_DEL: memcpy(&fib_work->ven_info, info, sizeof(fib_work->ven_info)); dev_hold(fib_work->ven_info.dev); @@ -6215,13 +6215,13 @@ static int mlxsw_sp_router_fib_event(struct notifier_block *nb, router = container_of(nb, struct mlxsw_sp_router, fib_nb); switch (event) { - case FIB_EVENT_RULE_ADD: /* fall through */ + case FIB_EVENT_RULE_ADD: case FIB_EVENT_RULE_DEL: err = mlxsw_sp_router_fib_rule_event(event, info, router->mlxsw_sp); return notifier_from_errno(err); - case FIB_EVENT_ENTRY_ADD: /* fall through */ - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_ADD: + case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_APPEND: if (router->aborted) { NL_SET_ERR_MSG_MOD(info->extack, "FIB offload was aborted. Not configuring route"); @@ -7277,7 +7277,7 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev, goto out; switch (event) { - case NETDEV_CHANGEMTU: /* fall through */ + case NETDEV_CHANGEMTU: case NETDEV_CHANGEADDR: err = mlxsw_sp_router_port_change_event(mlxsw_sp, rif); break; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index 5c959a995199..1d18e41ab255 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c @@ -1523,12 +1523,12 @@ mlxsw_sp_span_trigger_ops_set(struct mlxsw_sp_span_trigger_entry *trigger_entry) enum mlxsw_sp_span_trigger_type type; switch (trigger_entry->trigger) { - case MLXSW_SP_SPAN_TRIGGER_INGRESS: /* fall-through */ + case MLXSW_SP_SPAN_TRIGGER_INGRESS: case MLXSW_SP_SPAN_TRIGGER_EGRESS: type = MLXSW_SP_SPAN_TRIGGER_TYPE_PORT; break; - case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP: /* fall-through */ - case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP: /* fall-through */ + case MLXSW_SP_SPAN_TRIGGER_TAIL_DROP: + case MLXSW_SP_SPAN_TRIGGER_EARLY_DROP: case MLXSW_SP_SPAN_TRIGGER_ECN: type = MLXSW_SP_SPAN_TRIGGER_TYPE_GLOBAL; break; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c index a26162b08b7d..72912afa6f72 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c @@ -1297,7 +1297,7 @@ static int mlxsw_sp_port_fdb_tunnel_uc_op(struct mlxsw_sp *mlxsw_sp, uip = be32_to_cpu(addr->addr4); sfd_proto = MLXSW_REG_SFD_UC_TUNNEL_PROTOCOL_IPV4; break; - case MLXSW_SP_L3_PROTO_IPV6: /* fall through */ + case MLXSW_SP_L3_PROTO_IPV6: default: WARN_ON(1); return -EOPNOTSUPP; @@ -2870,7 +2870,7 @@ static void mlxsw_sp_switchdev_bridge_fdb_event_work(struct work_struct *work) fdb_info = &switchdev_work->fdb_info; mlxsw_sp_port_fdb_set(mlxsw_sp_port, fdb_info, false); break; - case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */ + case SWITCHDEV_FDB_ADD_TO_BRIDGE: case SWITCHDEV_FDB_DEL_TO_BRIDGE: /* These events are only used to potentially update an existing * SPAN mirror. @@ -3116,9 +3116,9 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused, switchdev_work->event = event; switch (event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */ - case SWITCHDEV_FDB_DEL_TO_DEVICE: /* fall through */ - case SWITCHDEV_FDB_ADD_TO_BRIDGE: /* fall through */ + case SWITCHDEV_FDB_ADD_TO_DEVICE: + case SWITCHDEV_FDB_DEL_TO_DEVICE: + case SWITCHDEV_FDB_ADD_TO_BRIDGE: case SWITCHDEV_FDB_DEL_TO_BRIDGE: fdb_info = container_of(info, struct switchdev_notifier_fdb_info, @@ -3138,7 +3138,7 @@ static int mlxsw_sp_switchdev_event(struct notifier_block *unused, */ dev_hold(dev); break; - case SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE: /* fall through */ + case SWITCHDEV_VXLAN_FDB_ADD_TO_DEVICE: case SWITCHDEV_VXLAN_FDB_DEL_TO_DEVICE: INIT_WORK(&switchdev_work->work, mlxsw_sp_switchdev_vxlan_fdb_event_work); diff --git a/drivers/net/ethernet/microchip/lan743x_ethtool.c b/drivers/net/ethernet/microchip/lan743x_ethtool.c index c533d06fbe3a..dcde496da7fb 100644 --- a/drivers/net/ethernet/microchip/lan743x_ethtool.c +++ b/drivers/net/ethernet/microchip/lan743x_ethtool.c @@ -548,7 +548,7 @@ static int lan743x_ethtool_get_rxnfc(struct net_device *netdev, case TCP_V4_FLOW:case UDP_V4_FLOW: case TCP_V6_FLOW:case UDP_V6_FLOW: rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ + fallthrough; case IPV4_FLOW: case IPV6_FLOW: rxnfc->data |= RXH_IP_SRC | RXH_IP_DST; return 0; diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 867c680f5917..5abb7d2b0a9e 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -859,7 +859,7 @@ void ocelot_bridge_stp_state_set(struct ocelot *ocelot, int port, u8 state) switch (state) { case BR_STATE_FORWARDING: ocelot->bridge_fwd_mask |= BIT(port); - /* Fallthrough */ + fallthrough; case BR_STATE_LEARNING: port_cfg |= ANA_PORT_PORT_CFG_LEARN_ENA; break; diff --git a/drivers/net/ethernet/natsemi/natsemi.c b/drivers/net/ethernet/natsemi/natsemi.c index c2867fe995bc..3de8430ee8c5 100644 --- a/drivers/net/ethernet/natsemi/natsemi.c +++ b/drivers/net/ethernet/natsemi/natsemi.c @@ -3081,7 +3081,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = np->phy_addr_external; - /* Fall Through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ /* The phy_id is not enough to uniquely identify diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c index 4f1f90f5e178..78eba10300ae 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-config.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c @@ -3768,20 +3768,20 @@ vxge_hw_rts_rth_data0_data1_get(u32 j, u64 *data0, u64 *data1, VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_ENTRY_EN | VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM0_BUCKET_DATA( itable[j]); - /* fall through */ + fallthrough; case 2: *data0 |= VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_NUM(j)| VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_ENTRY_EN | VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_ITEM1_BUCKET_DATA( itable[j]); - /* fall through */ + fallthrough; case 3: *data1 = VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_NUM(j)| VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_ENTRY_EN | VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM0_BUCKET_DATA( itable[j]); - /* fall through */ + fallthrough; case 4: *data1 |= VXGE_HW_RTS_ACCESS_STEER_DATA1_RTH_ITEM1_BUCKET_NUM(j)| diff --git a/drivers/net/ethernet/netronome/nfp/crypto/tls.c b/drivers/net/ethernet/netronome/nfp/crypto/tls.c index 7c50e3dfb9d5..76c51da5b66f 100644 --- a/drivers/net/ethernet/netronome/nfp/crypto/tls.c +++ b/drivers/net/ethernet/netronome/nfp/crypto/tls.c @@ -296,7 +296,7 @@ nfp_net_tls_add(struct net_device *netdev, struct sock *sk, break; } #endif - /* fall through */ + fallthrough; case AF_INET: req_sz = sizeof(struct nfp_crypto_req_add_v4); ipv6 = false; diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index ff844e5cc41f..1cbe2c9f3959 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -297,7 +297,7 @@ nfp_fl_get_tun_from_act(struct nfp_app *app, case htons(GENEVE_UDP_PORT): if (priv->flower_ext_feats & NFP_FL_FEATS_GENEVE) return NFP_FL_TUNNEL_GENEVE; - /* FALLTHROUGH */ + fallthrough; default: return NFP_FL_TUNNEL_NONE; } diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c index a050cb898782..f21cf1f40f98 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.c @@ -289,7 +289,7 @@ nfp_flower_cmsg_process_one_rx(struct nfp_app *app, struct sk_buff *skb) skb_stored = nfp_flower_lag_unprocessed_msg(app, skb); break; } - /* fall through */ + fallthrough; default: err_default: nfp_flower_cmsg_warn(app, "Cannot handle invalid repr control type %u\n", diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index 4651fe417b7f..36356f96661d 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -784,7 +784,7 @@ nfp_flower_copy_pre_actions(char *act_dst, char *act_src, int len, case NFP_FL_ACTION_OPCODE_PRE_TUNNEL: if (tunnel_act) *tunnel_act = true; - /* fall through */ + fallthrough; case NFP_FL_ACTION_OPCODE_PRE_LAG: memcpy(act_dst + act_off, act_src + act_off, act_len); break; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_asm.c b/drivers/net/ethernet/netronome/nfp/nfp_asm.c index b04b83687fe2..2643ea5948f4 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_asm.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_asm.c @@ -137,7 +137,7 @@ static u16 nfp_swreg_to_unreg(swreg reg, bool is_dst) val; case NN_LM_MOD_DEC: lm_dec = true; - /* fall through */ + fallthrough; case NN_LM_MOD_INC: if (val) { pr_err("LM offset in inc/dev mode\n"); diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 39ee23e8c0bf..21ea22694e47 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1940,10 +1940,10 @@ static int nfp_net_rx(struct nfp_net_rx_ring *rx_ring, int budget) continue; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(dp->netdev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: nfp_net_rx_give_one(dp, rx_ring, rxbuf->frag, rxbuf->dma_addr); diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c index a486008eb80a..252fe06f58aa 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp6000_pcie.c @@ -340,12 +340,12 @@ static int matching_bar(struct nfp_bar *bar, u32 tgt, u32 act, u32 tok, switch (maptype) { case NFP_PCIE_BAR_PCIE2CPP_MapType_TARGET: bartok = -1; - /* FALLTHROUGH */ + fallthrough; case NFP_PCIE_BAR_PCIE2CPP_MapType_BULK: baract = NFP_CPP_ACTION_RW; if (act == 0) act = NFP_CPP_ACTION_RW; - /* FALLTHROUGH */ + fallthrough; case NFP_PCIE_BAR_PCIE2CPP_MapType_FIXED: break; default: diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c index 75f012444796..2260c2403a83 100644 --- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c +++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_rtsym.c @@ -213,7 +213,7 @@ u64 nfp_rtsym_size(const struct nfp_rtsym *sym) return 0; default: pr_warn("rtsym '%s': unknown type: %d\n", sym->name, sym->type); - /* fall through */ + fallthrough; case NFP_RTSYM_TYPE_OBJECT: case NFP_RTSYM_TYPE_FUNCTION: return sym->size; diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c index a26966fa40b9..dceec80fd642 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c @@ -410,7 +410,7 @@ static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter) case SPEED_1000 + HALF_DUPLEX: netdev_dbg(adapter->netdev, "Half Duplex is not supported at 1000 Mbps\n"); - /* fall through */ + fallthrough; case SPEED_1000 + FULL_DUPLEX: full_duplex_only: netdev_dbg(adapter->netdev, diff --git a/drivers/net/ethernet/packetengines/yellowfin.c b/drivers/net/ethernet/packetengines/yellowfin.c index 647a1431b359..3da075307178 100644 --- a/drivers/net/ethernet/packetengines/yellowfin.c +++ b/drivers/net/ethernet/packetengines/yellowfin.c @@ -1356,7 +1356,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = np->phys[0] & 0x1f; - /* Fall Through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = mdio_read(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 66f45fce90fa..c3f50ddbe824 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -153,7 +153,7 @@ skip: case NETXEN_BRDTYPE_P3_4_GB_MM: supported |= SUPPORTED_Autoneg; advertising |= ADVERTISED_Autoneg; - /* fall through */ + fallthrough; case NETXEN_BRDTYPE_P2_SB31_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4: case NETXEN_BRDTYPE_P3_10G_CX4_LP: @@ -182,7 +182,7 @@ skip: supported |= SUPPORTED_TP; check_sfp_module = netif_running(dev) && adapter->has_link_events; - /* fall through */ + fallthrough; case NETXEN_BRDTYPE_P2_SB31_10G: case NETXEN_BRDTYPE_P3_10G_XFP: supported |= SUPPORTED_FIBRE; diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 876743a79c1f..0e4cd8890cff 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -2046,7 +2046,7 @@ int qed_cxt_set_pf_params(struct qed_hwfn *p_hwfn, u32 rdma_tasks) rdma_tasks); /* no need for break since RoCE coexist with Ethernet */ } - /* fall through */ + fallthrough; case QED_PCI_ETH: { struct qed_eth_pf_params *p_params = diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index b3c9ebaf2280..b8f076e4e6b8 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -3109,14 +3109,14 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) p_hwfn->hw_info.hw_mode); if (rc) break; - /* Fall through */ + fallthrough; case FW_MSG_CODE_DRV_LOAD_PORT: rc = qed_hw_init_port(p_hwfn, p_hwfn->p_main_ptt, p_hwfn->hw_info.hw_mode); if (rc) break; - /* Fall through */ + fallthrough; case FW_MSG_CODE_DRV_LOAD_FUNCTION: rc = qed_hw_init_pf(p_hwfn, p_hwfn->p_main_ptt, p_params->p_tunn, diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 2558cb680db3..f39f629242a1 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -761,7 +761,7 @@ static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) kfree(int_params->msix_table); if (force_mode) goto out; - /* Fallthrough */ + fallthrough; case QED_INT_MODE_MSI: if (cdev->num_hwfns == 1) { @@ -775,7 +775,7 @@ static int qed_set_int_mode(struct qed_dev *cdev, bool force_mode) if (force_mode) goto out; } - /* Fallthrough */ + fallthrough; case QED_INT_MODE_INTA: int_params->out.int_mode = QED_INT_MODE_INTA; diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index 5be08f83e0aa..cd882c453394 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1085,7 +1085,7 @@ int qed_mcp_unload_req(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) DP_NOTICE(p_hwfn, "Unknown WoL configuration %02x\n", p_hwfn->cdev->wol_config); - /* Fallthrough */ + fallthrough; case QED_OV_WOL_DEFAULT: wol_param = DRV_MB_PARAM_UNLOAD_WOL_MCP; } @@ -1365,7 +1365,7 @@ static void qed_mcp_handle_link_change(struct qed_hwfn *p_hwfn, break; case LINK_STATUS_SPEED_AND_DUPLEX_1000THD: p_link->full_duplex = false; - /* Fall-through */ + fallthrough; case LINK_STATUS_SPEED_AND_DUPLEX_1000TFD: p_link->speed = 1000; break; @@ -2451,7 +2451,7 @@ qed_mcp_get_shmem_proto(struct qed_hwfn *p_hwfn, break; case FUNC_MF_CFG_PROTOCOL_ROCE: DP_NOTICE(p_hwfn, "RoCE personality is not a valid value!\n"); - /* Fallthrough */ + fallthrough; default: rc = -EINVAL; } @@ -3546,7 +3546,7 @@ qed_mcp_resc_allocation_msg(struct qed_hwfn *p_hwfn, switch (p_in_params->cmd) { case DRV_MSG_SET_RESOURCE_VALUE_MSG: mfw_resc_info.size = p_in_params->resc_max_val; - /* Fallthrough */ + fallthrough; case DRV_MSG_GET_RESOURCE_ALLOC_MSG: break; default: @@ -3823,7 +3823,7 @@ qed_mcp_resc_unlock(struct qed_hwfn *p_hwfn, DP_INFO(p_hwfn, "Resource unlock request for an already released resource [%d]\n", p_params->resource); - /* Fallthrough */ + fallthrough; case RESOURCE_OPCODE_RELEASED: p_params->b_released = true; break; diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 0d0e38debbc2..569e2a7a64e5 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c @@ -1542,7 +1542,7 @@ static void ql_link_state_machine_work(struct work_struct *work) if (test_bit(QL_LINK_MASTER, &qdev->flags)) ql_port_start(qdev); qdev->port_link_state = LS_DOWN; - /* Fall Through */ + fallthrough; case LS_DOWN: if (curr_link_state == LS_UP) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 5c2a3acf1e89..b9894d54469c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c @@ -353,7 +353,7 @@ skip: case QLCNIC_BRDTYPE_P3P_4_GB_MM: supported |= SUPPORTED_Autoneg; advertising |= ADVERTISED_Autoneg; - /* fall through */ + fallthrough; case QLCNIC_BRDTYPE_P3P_10G_CX4: case QLCNIC_BRDTYPE_P3P_10G_CX4_LP: case QLCNIC_BRDTYPE_P3P_10000_BASE_T: @@ -377,7 +377,7 @@ skip: supported |= SUPPORTED_TP; check_sfp_module = netif_running(adapter->netdev) && ahw->has_link_events; - /* fall through */ + fallthrough; case QLCNIC_BRDTYPE_P3P_10G_XFP: supported |= SUPPORTED_FIBRE; advertising |= ADVERTISED_FIBRE; diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index d1da92ac7fbe..fc9e6626db55 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -4994,7 +4994,7 @@ static int rtl_alloc_irq(struct rtl8169_private *tp) rtl_unlock_config_regs(tp); RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable); rtl_lock_config_regs(tp); - /* fall through */ + fallthrough; case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_17: flags = PCI_IRQ_LEGACY; break; @@ -5137,7 +5137,7 @@ static void rtl_hw_initialize(struct rtl8169_private *tp) switch (tp->mac_version) { case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52: rtl8168ep_stop_cmac(tp); - /* fall through */ + fallthrough; case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48: rtl_hw_init_8168g(tp); break; diff --git a/drivers/net/ethernet/rocker/rocker_main.c b/drivers/net/ethernet/rocker/rocker_main.c index fc99e7118e49..42458a46ffaf 100644 --- a/drivers/net/ethernet/rocker/rocker_main.c +++ b/drivers/net/ethernet/rocker/rocker_main.c @@ -2169,7 +2169,7 @@ static void rocker_router_fib_event_work(struct work_struct *work) rocker_world_fib4_del(rocker, &fib_work->fen_info); fib_info_put(fib_work->fen_info.fi); break; - case FIB_EVENT_RULE_ADD: /* fall through */ + case FIB_EVENT_RULE_ADD: case FIB_EVENT_RULE_DEL: rule = fib_work->fr_info.rule; if (!fib4_rule_default(rule)) @@ -2201,7 +2201,7 @@ static int rocker_router_fib_event(struct notifier_block *nb, fib_work->event = event; switch (event) { - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: case FIB_EVENT_ENTRY_DEL: if (info->family == AF_INET) { struct fib_entry_notifier_info *fen_info = ptr; @@ -2224,7 +2224,7 @@ static int rocker_router_fib_event(struct notifier_block *nb, */ fib_info_hold(fib_work->fen_info.fi); break; - case FIB_EVENT_RULE_ADD: /* fall through */ + case FIB_EVENT_RULE_ADD: case FIB_EVENT_RULE_DEL: memcpy(&fib_work->fr_info, ptr, sizeof(fib_work->fr_info)); fib_rule_get(fib_work->fr_info.rule); @@ -2811,7 +2811,7 @@ static int rocker_switchdev_event(struct notifier_block *unused, switchdev_work->event = event; switch (event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */ + case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: memcpy(&switchdev_work->fdb_info, ptr, sizeof(switchdev_work->fdb_info)); diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c index 21465cb3d60a..7f8b10c49660 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c @@ -316,7 +316,7 @@ static int sxgbe_get_rss_hash_opts(struct sxgbe_priv_data *priv, case TCP_V4_FLOW: case UDP_V4_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + fallthrough; case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: case AH_V4_FLOW: @@ -327,7 +327,7 @@ static int sxgbe_get_rss_hash_opts(struct sxgbe_priv_data *priv, case TCP_V6_FLOW: case UDP_V6_FLOW: cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + fallthrough; case SCTP_V6_FLOW: case AH_ESP_V6_FLOW: case AH_V6_FLOW: diff --git a/drivers/net/ethernet/sfc/falcon/ethtool.c b/drivers/net/ethernet/sfc/falcon/ethtool.c index db90d94e24c9..a6bae6a234ba 100644 --- a/drivers/net/ethernet/sfc/falcon/ethtool.c +++ b/drivers/net/ethernet/sfc/falcon/ethtool.c @@ -957,7 +957,7 @@ ef4_ethtool_get_rxnfc(struct net_device *net_dev, switch (info->flow_type) { case TCP_V4_FLOW: info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* Fall through */ + fallthrough; case UDP_V4_FLOW: case SCTP_V4_FLOW: case AH_ESP_V4_FLOW: diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c index 332183280a45..fa1ade856b10 100644 --- a/drivers/net/ethernet/sfc/falcon/farch.c +++ b/drivers/net/ethernet/sfc/falcon/farch.c @@ -1049,10 +1049,10 @@ ef4_farch_handle_rx_event(struct ef4_channel *channel, const ef4_qword_t *event) switch (rx_ev_hdr_type) { case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP: flags |= EF4_RX_PKT_TCP; - /* fall through */ + fallthrough; case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP: flags |= EF4_RX_PKT_CSUMMED; - /* fall through */ + fallthrough; case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER: case FSE_AZ_RX_EV_HDR_TYPE_OTHER: break; @@ -1310,7 +1310,7 @@ int ef4_farch_ev_process(struct ef4_channel *channel, int budget) if (efx->type->handle_global_event && efx->type->handle_global_event(channel, &event)) break; - /* else fall through */ + fallthrough; default: netif_err(channel->efx, hw, channel->efx->net_dev, "channel %d unknown event type %d (data " @@ -1983,7 +1983,7 @@ ef4_farch_filter_from_gen_spec(struct ef4_farch_filter_spec *spec, EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT | EF4_FILTER_MATCH_REM_HOST | EF4_FILTER_MATCH_REM_PORT): is_full = true; - /* fall through */ + fallthrough; case (EF4_FILTER_MATCH_ETHER_TYPE | EF4_FILTER_MATCH_IP_PROTO | EF4_FILTER_MATCH_LOC_HOST | EF4_FILTER_MATCH_LOC_PORT): { __be32 rhost, host1, host2; @@ -2034,7 +2034,7 @@ ef4_farch_filter_from_gen_spec(struct ef4_farch_filter_spec *spec, case EF4_FILTER_MATCH_LOC_MAC | EF4_FILTER_MATCH_OUTER_VID: is_full = true; - /* fall through */ + fallthrough; case EF4_FILTER_MATCH_LOC_MAC: spec->type = (is_full ? EF4_FARCH_FILTER_MAC_FULL : EF4_FARCH_FILTER_MAC_WILD); @@ -2081,7 +2081,7 @@ ef4_farch_filter_to_gen_spec(struct ef4_filter_spec *gen_spec, case EF4_FARCH_FILTER_TCP_FULL: case EF4_FARCH_FILTER_UDP_FULL: is_full = true; - /* fall through */ + fallthrough; case EF4_FARCH_FILTER_TCP_WILD: case EF4_FARCH_FILTER_UDP_WILD: { __be32 host1, host2; @@ -2125,7 +2125,7 @@ ef4_farch_filter_to_gen_spec(struct ef4_filter_spec *gen_spec, case EF4_FARCH_FILTER_MAC_FULL: is_full = true; - /* fall through */ + fallthrough; case EF4_FARCH_FILTER_MAC_WILD: gen_spec->match_flags = EF4_FILTER_MATCH_LOC_MAC; if (is_full) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index d07eeaad9bdf..4002f9a3ae90 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -1038,10 +1038,10 @@ efx_farch_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event) switch (rx_ev_hdr_type) { case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_TCP: flags |= EFX_RX_PKT_TCP; - /* fall through */ + fallthrough; case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_UDP: flags |= EFX_RX_PKT_CSUMMED; - /* fall through */ + fallthrough; case FSE_CZ_RX_EV_HDR_TYPE_IPV4V6_OTHER: case FSE_AZ_RX_EV_HDR_TYPE_OTHER: break; @@ -1316,7 +1316,7 @@ int efx_farch_ev_process(struct efx_channel *channel, int budget) if (efx->type->handle_global_event && efx->type->handle_global_event(channel, &event)) break; - /* else fall through */ + fallthrough; default: netif_err(channel->efx, hw, channel->efx->net_dev, "channel %d unknown event type %d (data " @@ -2043,7 +2043,7 @@ efx_farch_filter_from_gen_spec(struct efx_farch_filter_spec *spec, EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT): is_full = true; - /* fall through */ + fallthrough; case (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO | EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT): { __be32 rhost, host1, host2; @@ -2094,7 +2094,7 @@ efx_farch_filter_from_gen_spec(struct efx_farch_filter_spec *spec, case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID: is_full = true; - /* fall through */ + fallthrough; case EFX_FILTER_MATCH_LOC_MAC: spec->type = (is_full ? EFX_FARCH_FILTER_MAC_FULL : EFX_FARCH_FILTER_MAC_WILD); @@ -2141,7 +2141,7 @@ efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec, case EFX_FARCH_FILTER_TCP_FULL: case EFX_FARCH_FILTER_UDP_FULL: is_full = true; - /* fall through */ + fallthrough; case EFX_FARCH_FILTER_TCP_WILD: case EFX_FARCH_FILTER_UDP_WILD: { __be32 host1, host2; @@ -2185,7 +2185,7 @@ efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec, case EFX_FARCH_FILTER_MAC_FULL: is_full = true; - /* fall through */ + fallthrough; case EFX_FARCH_FILTER_MAC_WILD: gen_spec->match_flags = EFX_FILTER_MATCH_LOC_MAC; if (is_full) diff --git a/drivers/net/ethernet/sfc/mcdi_filters.c b/drivers/net/ethernet/sfc/mcdi_filters.c index 5a74d880b733..1523be77b9db 100644 --- a/drivers/net/ethernet/sfc/mcdi_filters.c +++ b/drivers/net/ethernet/sfc/mcdi_filters.c @@ -140,7 +140,7 @@ efx_mcdi_filter_push_prep_set_match_fields(struct efx_nic *efx, switch (encap_type & EFX_ENCAP_TYPES_MASK) { case EFX_ENCAP_TYPE_VXLAN: vni_type = MC_CMD_FILTER_OP_EXT_IN_VNI_TYPE_VXLAN; - /* fallthrough */ + fallthrough; case EFX_ENCAP_TYPE_GENEVE: COPY_VALUE(ether_type, ETHER_TYPE); outer_ip_proto = IPPROTO_UDP; diff --git a/drivers/net/ethernet/sfc/mcdi_port_common.c b/drivers/net/ethernet/sfc/mcdi_port_common.c index 56af8b54a864..714d7f937212 100644 --- a/drivers/net/ethernet/sfc/mcdi_port_common.c +++ b/drivers/net/ethernet/sfc/mcdi_port_common.c @@ -282,7 +282,7 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx, break; default: WARN_ON(1); - /* Fall through */ + fallthrough; case MC_CMD_FCNTL_OFF: link_state->fc = 0; break; diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 59a43d586967..aaa112877561 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -358,7 +358,7 @@ static bool efx_do_xdp(struct efx_nic *efx, struct efx_channel *channel, case XDP_ABORTED: trace_xdp_exception(efx->net_dev, xdp_prog, xdp_act); - /* Fall through */ + fallthrough; case XDP_DROP: efx_free_rx_buffers(rx_queue, rx_buf, 1); channel->n_rx_xdp_drops++; diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 336105f77313..cfa460c7db23 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -2228,7 +2228,7 @@ static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = sis_priv->mii->phy_addr; - /* Fall Through */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = mdio_read(net_dev, data->phy_id & 0x1f, data->reg_num & 0x1f); diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c index 186c0bddbe5f..01069dfaf75c 100644 --- a/drivers/net/ethernet/smsc/smc911x.c +++ b/drivers/net/ethernet/smsc/smc911x.c @@ -712,7 +712,7 @@ static void smc911x_phy_detect(struct net_device *dev) /* Found an external PHY */ break; } - /* Else, fall through */ + fallthrough; default: /* Internal media only */ SMC_GET_PHY_ID1(lp, 1, id1); diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c index 25db667fa879..806eb651cea3 100644 --- a/drivers/net/ethernet/socionext/netsec.c +++ b/drivers/net/ethernet/socionext/netsec.c @@ -919,10 +919,10 @@ static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog, break; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(priv->ndev, prog, act); - /* fall through -- handle aborts by dropping packet */ + fallthrough; /* handle aborts by dropping packet */ case XDP_DROP: ret = NETSEC_XDP_CONSUMED; page = virt_to_head_page(xdp->data); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c index d0d2d0fc5f0a..08c76636c164 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-anarion.c @@ -84,9 +84,10 @@ static struct anarion_gmac *anarion_config_dt(struct platform_device *pdev) return ERR_PTR(err); switch (phy_mode) { - case PHY_INTERFACE_MODE_RGMII: /* Fall through */ - case PHY_INTERFACE_MODE_RGMII_ID /* Fall through */: - case PHY_INTERFACE_MODE_RGMII_RXID: /* Fall through */ + case PHY_INTERFACE_MODE_RGMII: + fallthrough; + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: gmac->phy_intf_sel = GMAC_CONFIG_INTF_RGMII; break; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c index e113b1376fdd..bf195adee393 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c @@ -1985,7 +1985,7 @@ void stmmac_selftest_run(struct net_device *dev, ret = phy_loopback(dev->phydev, true); if (!ret) break; - /* Fallthrough */ + fallthrough; case STMMAC_LOOPBACK_MAC: ret = stmmac_set_mac_loopback(priv, priv->ioaddr, true); break; @@ -2018,7 +2018,7 @@ void stmmac_selftest_run(struct net_device *dev, ret = phy_loopback(dev->phydev, false); if (!ret) break; - /* Fallthrough */ + fallthrough; case STMMAC_LOOPBACK_MAC: stmmac_set_mac_loopback(priv, priv->ioaddr, false); break; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 3d747846f482..cc27d660a818 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -228,7 +228,7 @@ static int tc_setup_cls_u32(struct stmmac_priv *priv, switch (cls->command) { case TC_CLSU32_REPLACE_KNODE: tc_unfill_entry(priv, cls); - /* Fall through */ + fallthrough; case TC_CLSU32_NEW_KNODE: return tc_config_knode(priv, cls); case TC_CLSU32_DELETE_KNODE: diff --git a/drivers/net/ethernet/sun/cassini.c b/drivers/net/ethernet/sun/cassini.c index e2bc7a25f6d1..b624e177ec71 100644 --- a/drivers/net/ethernet/sun/cassini.c +++ b/drivers/net/ethernet/sun/cassini.c @@ -4759,7 +4759,7 @@ static int cas_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = cp->phy_addr; - /* Fallthrough... */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ spin_lock_irqsave(&cp->lock, flags); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index 9b5effb72657..68695d4afacd 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -8835,7 +8835,7 @@ static int walk_phys(struct niu *np, struct niu_parent *parent) else goto unknown_vg_1g_port; - /* fallthru */ + fallthrough; case 0x22: val = (phy_encode(PORT_TYPE_10G, 0) | phy_encode(PORT_TYPE_10G, 1) | @@ -8860,7 +8860,7 @@ static int walk_phys(struct niu *np, struct niu_parent *parent) else goto unknown_vg_1g_port; - /* fallthru */ + fallthrough; case 0x13: if ((lowest_10g & 0x7) == 0) val = (phy_encode(PORT_TYPE_10G, 0) | diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c index eeb8518c8a84..8deb943ca5de 100644 --- a/drivers/net/ethernet/sun/sungem.c +++ b/drivers/net/ethernet/sun/sungem.c @@ -2712,7 +2712,7 @@ static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGMIIPHY: /* Get address of MII PHY in use. */ data->phy_id = gp->mii_phy_addr; - /* Fallthrough... */ + fallthrough; case SIOCGMIIREG: /* Read MII PHY register. */ data->val_out = __sungem_phy_read(gp, data->phy_id & 0x1f, diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c index 4e184eecc8e1..6e72ecbe5cf7 100644 --- a/drivers/net/ethernet/ti/cpsw-phy-sel.c +++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c @@ -67,7 +67,7 @@ static void cpsw_gmii_sel_am3352(struct cpsw_phy_sel_priv *priv, dev_warn(priv->dev, "Unsupported PHY mode: \"%s\". Defaulting to MII.\n", phy_modes(phy_mode)); - /* fallthrough */ + fallthrough; case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; @@ -122,7 +122,7 @@ static void cpsw_gmii_sel_dra7xx(struct cpsw_phy_sel_priv *priv, dev_warn(priv->dev, "Unsupported PHY mode: \"%s\". Defaulting to MII.\n", phy_modes(phy_mode)); - /* fallthrough */ + fallthrough; case PHY_INTERFACE_MODE_MII: mode = AM33XX_GMII_SEL_MODE_MII; break; diff --git a/drivers/net/ethernet/ti/cpsw_priv.c b/drivers/net/ethernet/ti/cpsw_priv.c index d6d7a7d9c7ad..482a1a451e43 100644 --- a/drivers/net/ethernet/ti/cpsw_priv.c +++ b/drivers/net/ethernet/ti/cpsw_priv.c @@ -1371,10 +1371,10 @@ int cpsw_run_xdp(struct cpsw_priv *priv, int ch, struct xdp_buff *xdp, break; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(ndev, prog, act); - /* fall through -- handle aborts by dropping packet */ + fallthrough; /* handle aborts by dropping packet */ case XDP_DROP: goto drop; } diff --git a/drivers/net/ethernet/ti/tlan.c b/drivers/net/ethernet/ti/tlan.c index 58623e974a0c..76a342ea3797 100644 --- a/drivers/net/ethernet/ti/tlan.c +++ b/drivers/net/ethernet/ti/tlan.c @@ -948,7 +948,7 @@ static int tlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCGMIIPHY: /* get address of MII PHY in use. */ data->phy_id = phy; - /* fall through */ + fallthrough; case SIOCGMIIREG: /* read MII PHY register. */ diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c index 2db546b27ee0..dc14a66583ff 100644 --- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c +++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c @@ -877,7 +877,7 @@ static int gelic_wl_set_auth(struct net_device *netdev, case IW_AUTH_KEY_MGMT: if (param->value & IW_AUTH_KEY_MGMT_PSK) break; - /* intentionally fall through */ + fallthrough; default: ret = -EOPNOTSUPP; break; diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index 07389702a540..5f5b33e6653b 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -786,7 +786,7 @@ spider_net_release_tx_chain(struct spider_net_card *card, int brutal) /* fallthrough, if we release the descriptors * brutally (then we don't care about * SPIDER_NET_DESCR_CARDOWNED) */ - /* Fall through */ + fallthrough; case SPIDER_NET_DESCR_RESPONSE_ERROR: case SPIDER_NET_DESCR_PROTECTION_ERROR: @@ -1397,9 +1397,9 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, show_error = 0; break; - case SPIDER_NET_GDDDEN0INT: /* fallthrough */ - case SPIDER_NET_GDCDEN0INT: /* fallthrough */ - case SPIDER_NET_GDBDEN0INT: /* fallthrough */ + case SPIDER_NET_GDDDEN0INT: + case SPIDER_NET_GDCDEN0INT: + case SPIDER_NET_GDBDEN0INT: case SPIDER_NET_GDADEN0INT: /* someone has set RX_DMA_EN to 0 */ show_error = 0; @@ -1449,10 +1449,10 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, * Logging is not needed. */ show_error = 0; break; - case SPIDER_NET_GRFDFLLINT: /* fallthrough */ - case SPIDER_NET_GRFCFLLINT: /* fallthrough */ - case SPIDER_NET_GRFBFLLINT: /* fallthrough */ - case SPIDER_NET_GRFAFLLINT: /* fallthrough */ + case SPIDER_NET_GRFDFLLINT: + case SPIDER_NET_GRFCFLLINT: + case SPIDER_NET_GRFBFLLINT: + case SPIDER_NET_GRFAFLLINT: case SPIDER_NET_GRMFLLINT: /* Could happen when rx chain is full */ if (card->ignore_rx_ramfull == 0) { @@ -1473,9 +1473,9 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, break; /* chain end */ - case SPIDER_NET_GDDDCEINT: /* fallthrough */ - case SPIDER_NET_GDCDCEINT: /* fallthrough */ - case SPIDER_NET_GDBDCEINT: /* fallthrough */ + case SPIDER_NET_GDDDCEINT: + case SPIDER_NET_GDCDCEINT: + case SPIDER_NET_GDBDCEINT: case SPIDER_NET_GDADCEINT: spider_net_resync_head_ptr(card); spider_net_refill_rx_chain(card); @@ -1486,9 +1486,9 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg, break; /* invalid descriptor */ - case SPIDER_NET_GDDINVDINT: /* fallthrough */ - case SPIDER_NET_GDCINVDINT: /* fallthrough */ - case SPIDER_NET_GDBINVDINT: /* fallthrough */ + case SPIDER_NET_GDDINVDINT: + case SPIDER_NET_GDCINVDINT: + case SPIDER_NET_GDBINVDINT: case SPIDER_NET_GDAINVDINT: /* Could happen when rx chain is full */ spider_net_resync_head_ptr(card); diff --git a/drivers/net/ethernet/xircom/xirc2ps_cs.c b/drivers/net/ethernet/xircom/xirc2ps_cs.c index 3e3883ad88b0..3e337142b516 100644 --- a/drivers/net/ethernet/xircom/xirc2ps_cs.c +++ b/drivers/net/ethernet/xircom/xirc2ps_cs.c @@ -1434,7 +1434,7 @@ do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) switch(cmd) { case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data->phy_id = 0; /* we have only this address */ - /* fall through */ + fallthrough; case SIOCGMIIREG: /* Read the specified MII register. */ data->val_out = mii_rd(ioaddr, data->phy_id & 0x1f, data->reg_num & 0x1f); diff --git a/drivers/net/fddi/skfp/pcmplc.c b/drivers/net/fddi/skfp/pcmplc.c index 1be039579d70..554cde8d6073 100644 --- a/drivers/net/fddi/skfp/pcmplc.c +++ b/drivers/net/fddi/skfp/pcmplc.c @@ -847,7 +847,7 @@ static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) case ACTIONS(PC5_SIGNAL) : ACTIONS_DONE() ; - /* fall through */ + fallthrough; case PC5_SIGNAL : if ((cmd != PC_SIGNAL) && (cmd != PC_TIMEOUT_LCT)) break ; @@ -946,7 +946,7 @@ static void pcm_fsm(struct s_smc *smc, struct s_phy *phy, int cmd) SETMASK(PLC(np,PL_CNTRL_B),PL_PC_JOIN,PL_PC_JOIN) ; ACTIONS_DONE() ; cmd = 0 ; - /* fall thru */ + fallthrough; case PC6_JOIN : switch (plc->p_state) { case PS_ACTIVE: diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 8c810edece86..466622664424 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -974,7 +974,7 @@ static void fjes_stop_req_irq(struct fjes_adapter *adapter, int src_epid) FJES_RX_STOP_REQ_DONE; spin_unlock_irqrestore(&hw->rx_status_lock, flags); clear_bit(src_epid, &hw->txrx_stop_req_bit); - /* fall through */ + fallthrough; case EP_PARTNER_UNSHARE: case EP_PARTNER_COMPLETE: default: diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c index 4476491b58f9..e4e4981ac1d2 100644 --- a/drivers/net/hamradio/baycom_epp.c +++ b/drivers/net/hamradio/baycom_epp.c @@ -500,7 +500,7 @@ static int transmit(struct baycom_state *bc, int cnt, unsigned char stat) } break; } - /* fall through */ + fallthrough; default: if (bc->hdlctx.calibrate <= 0) diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index deef14215110..17be2bb2985c 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -482,7 +482,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) case CRC_MODE_SMACK_TEST: ax->crcmode = CRC_MODE_FLEX_TEST; printk(KERN_INFO "mkiss: %s: Trying crc-smack\n", ax->dev->name); - // fall through + fallthrough; case CRC_MODE_SMACK: *p |= 0x80; crc = swab16(crc16(0, p, len)); @@ -491,7 +491,7 @@ static void ax_encaps(struct net_device *dev, unsigned char *icp, int len) case CRC_MODE_FLEX_TEST: ax->crcmode = CRC_MODE_NONE; printk(KERN_INFO "mkiss: %s: Trying crc-flexnet\n", ax->dev->name); - // fall through + fallthrough; case CRC_MODE_FLEX: *p |= 0x20; crc = calc_crc_flex(p, len); @@ -744,7 +744,6 @@ static int mkiss_open(struct tty_struct *tty) ax->dev->name); break; case 0: - /* fall through */ default: crc_force = 0; printk(KERN_INFO "mkiss: %s: crc mode is auto.\n", diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 5da04e997989..c8d803d3616c 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -842,7 +842,7 @@ static int macvlan_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCSHWTSTAMP: if (!net_eq(dev_net(dev), &init_net)) break; - /* fall through */ + fallthrough; case SIOCGHWTSTAMP: if (netif_device_present(real_dev) && ops->ndo_do_ioctl) err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); diff --git a/drivers/net/mii.c b/drivers/net/mii.c index 44612122338b..f6a97c859f3a 100644 --- a/drivers/net/mii.c +++ b/drivers/net/mii.c @@ -597,7 +597,7 @@ int generic_mii_ioctl(struct mii_if_info *mii_if, switch(cmd) { case SIOCGMIIPHY: mii_data->phy_id = mii_if->phy_id; - /* fall through */ + fallthrough; case SIOCGMIIREG: mii_data->val_out = diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index 7971dc4f54f1..0e9511661601 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -193,7 +193,7 @@ new_device_store(struct bus_type *bus, const char *buf, size_t count) switch (err) { case 1: port_count = 1; - /* fall through */ + fallthrough; case 2: if (id > INT_MAX) { pr_err("Value of \"id\" is too big.\n"); diff --git a/drivers/net/netdevsim/fib.c b/drivers/net/netdevsim/fib.c index f32d56ac3e80..deea17a0e79c 100644 --- a/drivers/net/netdevsim/fib.c +++ b/drivers/net/netdevsim/fib.c @@ -760,14 +760,14 @@ static int nsim_fib_event_nb(struct notifier_block *nb, unsigned long event, spin_lock_bh(&data->fib_lock); switch (event) { - case FIB_EVENT_RULE_ADD: /* fall through */ + case FIB_EVENT_RULE_ADD: case FIB_EVENT_RULE_DEL: err = nsim_fib_rule_event(data, info, event == FIB_EVENT_RULE_ADD); break; - case FIB_EVENT_ENTRY_REPLACE: /* fall through */ - case FIB_EVENT_ENTRY_APPEND: /* fall through */ + case FIB_EVENT_ENTRY_REPLACE: + case FIB_EVENT_ENTRY_APPEND: case FIB_EVENT_ENTRY_DEL: err = nsim_fib_event(data, info, event); break; diff --git a/drivers/net/phy/adin.c b/drivers/net/phy/adin.c index 7471a8b90873..307f0ac1287b 100644 --- a/drivers/net/phy/adin.c +++ b/drivers/net/phy/adin.c @@ -366,10 +366,10 @@ static int adin_set_edpd(struct phy_device *phydev, u16 tx_interval) switch (tx_interval) { case 1000: /* 1 second */ - /* fallthrough */ + fallthrough; case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS: val |= ADIN1300_NRG_PD_TX_EN; - /* fallthrough */ + fallthrough; case ETHTOOL_PHY_EDPD_NO_TX: break; default: diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index 50fb7d16b75a..79e67f2fe00a 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -766,13 +766,13 @@ static int decode_evnt(struct dp83640_private *dp83640, switch (words) { case 3: dp83640->edata.sec_hi = phy_txts->sec_hi; - /* fall through */ + fallthrough; case 2: dp83640->edata.sec_lo = phy_txts->sec_lo; - /* fall through */ + fallthrough; case 1: dp83640->edata.ns_hi = phy_txts->ns_hi; - /* fall through */ + fallthrough; case 0: dp83640->edata.ns_lo = phy_txts->ns_lo; } @@ -1409,7 +1409,7 @@ static void dp83640_txtstamp(struct mii_timestamper *mii_ts, kfree_skb(skb); return; } - /* fall through */ + fallthrough; case HWTSTAMP_TX_ON: skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT; diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c index c4641b1704d6..18d81f43f2a8 100644 --- a/drivers/net/phy/fixed_phy.c +++ b/drivers/net/phy/fixed_phy.c @@ -279,13 +279,13 @@ static struct phy_device *__fixed_phy_register(unsigned int irq, phy->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, phy->supported); - /* fall through */ + fallthrough; case SPEED_100: linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, phy->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, phy->supported); - /* fall through */ + fallthrough; case SPEED_10: default: linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 79b4f35d151e..735a806045ac 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -355,7 +355,7 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGMIIPHY: mii_data->phy_id = phydev->mdio.addr; - /* fall through */ + fallthrough; case SIOCGMIIREG: if (mdio_phy_id_is_c45(mii_data->phy_id)) { @@ -433,7 +433,7 @@ int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd) case SIOCSHWTSTAMP: if (phydev->mii_ts && phydev->mii_ts->hwtstamp) return phydev->mii_ts->hwtstamp(phydev->mii_ts, ifr); - /* fall through */ + fallthrough; default: return -EOPNOTSUPP; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 57d44648c8dd..8adfbad0a1e8 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1979,7 +1979,7 @@ static int genphy_setup_master_slave(struct phy_device *phydev) break; case MASTER_SLAVE_CFG_MASTER_FORCE: ctl |= CTL1000_AS_MASTER; - /* fallthrough */ + fallthrough; case MASTER_SLAVE_CFG_SLAVE_FORCE: ctl |= CTL1000_ENABLE_MASTER; break; diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 32b4bd6a5b55..32f4e8ec96cf 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1905,7 +1905,7 @@ int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGMIIPHY: mii->phy_id = pl->phydev->mdio.addr; - /* fall through */ + fallthrough; case SIOCGMIIREG: ret = phylink_phy_read(pl, mii->phy_id, mii->reg_num); @@ -1928,7 +1928,7 @@ int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd) switch (cmd) { case SIOCGMIIPHY: mii->phy_id = 0; - /* fall through */ + fallthrough; case SIOCGMIIREG: ret = phylink_mii_read(pl, mii->phy_id, mii->reg_num); diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c index 6900c68260e0..58014feedf6c 100644 --- a/drivers/net/phy/sfp-bus.c +++ b/drivers/net/phy/sfp-bus.c @@ -149,7 +149,7 @@ int sfp_parse_port(struct sfp_bus *bus, const struct sfp_eeprom_id *id, port = PORT_TP; break; } - /* fallthrough */ + fallthrough; case SFF8024_CONNECTOR_SG: /* guess */ case SFF8024_CONNECTOR_HSSDC_II: case SFF8024_CONNECTOR_NOSEPARATE: @@ -301,7 +301,7 @@ void sfp_parse_support(struct sfp_bus *bus, const struct sfp_eeprom_id *id, break; case SFF8024_ECC_100GBASE_CR4: phylink_set(modes, 100000baseCR4_Full); - /* fallthrough */ + fallthrough; case SFF8024_ECC_25GBASE_CR_S: case SFF8024_ECC_25GBASE_CR_N: phylink_set(modes, 25000baseCR_Full); diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index c24b0e83dd32..cf83314c8591 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -552,7 +552,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, case hwmon_temp_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0; - /* fall through */ + fallthrough; case hwmon_temp_input: case hwmon_temp_label: return 0444; @@ -571,7 +571,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, case hwmon_in_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0; - /* fall through */ + fallthrough; case hwmon_in_input: case hwmon_in_label: return 0444; @@ -590,7 +590,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, case hwmon_curr_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0; - /* fall through */ + fallthrough; case hwmon_curr_input: case hwmon_curr_label: return 0444; @@ -618,7 +618,7 @@ static umode_t sfp_hwmon_is_visible(const void *data, case hwmon_power_crit: if (!(sfp->id.ext.enhopts & SFP_ENHOPTS_ALARMWARN)) return 0; - /* fall through */ + fallthrough; case hwmon_power_input: case hwmon_power_label: return 0444; @@ -1872,7 +1872,7 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event) dev_warn(sfp->dev, "hwmon probe failed: %d\n", err); sfp_sm_mod_next(sfp, SFP_MOD_WAITDEV, 0); - /* fall through */ + fallthrough; case SFP_MOD_WAITDEV: /* Ensure that the device is attached before proceeding */ if (sfp->sm_dev_state < SFP_DEV_DOWN) @@ -1890,7 +1890,7 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event) goto insert; sfp_sm_mod_next(sfp, SFP_MOD_HPOWER, 0); - /* fall through */ + fallthrough; case SFP_MOD_HPOWER: /* Enable high power mode */ err = sfp_sm_mod_hpower(sfp, true); diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c index d82016dcde3b..4406b353123e 100644 --- a/drivers/net/plip/plip.c +++ b/drivers/net/plip/plip.c @@ -498,7 +498,7 @@ plip_receive(unsigned short nibble_timeout, struct net_device *dev, *data_p = (c0 >> 3) & 0x0f; write_data (dev, 0x10); /* send ACK */ *ns_p = PLIP_NB_1; - /* fall through */ + fallthrough; case PLIP_NB_1: cx = nibble_timeout; @@ -594,7 +594,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, printk(KERN_DEBUG "%s: receive start\n", dev->name); rcv->state = PLIP_PK_LENGTH_LSB; rcv->nibble = PLIP_NB_BEGIN; - /* fall through */ + fallthrough; case PLIP_PK_LENGTH_LSB: if (snd->state != PLIP_PK_DONE) { @@ -615,7 +615,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, return TIMEOUT; } rcv->state = PLIP_PK_LENGTH_MSB; - /* fall through */ + fallthrough; case PLIP_PK_LENGTH_MSB: if (plip_receive(nibble_timeout, dev, @@ -638,7 +638,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, rcv->state = PLIP_PK_DATA; rcv->byte = 0; rcv->checksum = 0; - /* fall through */ + fallthrough; case PLIP_PK_DATA: lbuf = rcv->skb->data; @@ -651,7 +651,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, rcv->checksum += lbuf[--rcv->byte]; } while (rcv->byte); rcv->state = PLIP_PK_CHECKSUM; - /* fall through */ + fallthrough; case PLIP_PK_CHECKSUM: if (plip_receive(nibble_timeout, dev, @@ -664,7 +664,7 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl, return ERROR; } rcv->state = PLIP_PK_DONE; - /* fall through */ + fallthrough; case PLIP_PK_DONE: /* Inform the upper layer for the arrival of a packet. */ @@ -710,7 +710,7 @@ plip_send(unsigned short nibble_timeout, struct net_device *dev, case PLIP_NB_BEGIN: write_data (dev, data & 0x0f); *ns_p = PLIP_NB_1; - /* fall through */ + fallthrough; case PLIP_NB_1: write_data (dev, 0x10 | (data & 0x0f)); @@ -725,7 +725,7 @@ plip_send(unsigned short nibble_timeout, struct net_device *dev, } write_data (dev, 0x10 | (data >> 4)); *ns_p = PLIP_NB_2; - /* fall through */ + fallthrough; case PLIP_NB_2: write_data (dev, (data >> 4)); @@ -814,7 +814,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl, &snd->nibble, snd->length.b.lsb)) return TIMEOUT; snd->state = PLIP_PK_LENGTH_MSB; - /* fall through */ + fallthrough; case PLIP_PK_LENGTH_MSB: if (plip_send(nibble_timeout, dev, @@ -823,7 +823,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl, snd->state = PLIP_PK_DATA; snd->byte = 0; snd->checksum = 0; - /* fall through */ + fallthrough; case PLIP_PK_DATA: do { @@ -835,7 +835,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl, snd->checksum += lbuf[--snd->byte]; } while (snd->byte); snd->state = PLIP_PK_CHECKSUM; - /* fall through */ + fallthrough; case PLIP_PK_CHECKSUM: if (plip_send(nibble_timeout, dev, @@ -846,7 +846,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl, dev_kfree_skb(snd->skb); dev->stats.tx_packets++; snd->state = PLIP_PK_DONE; - /* fall through */ + fallthrough; case PLIP_PK_DONE: /* Close the connection */ @@ -935,7 +935,7 @@ plip_interrupt(void *dev_id) switch (nl->connection) { case PLIP_CN_CLOSING: netif_wake_queue (dev); - /* fall through */ + fallthrough; case PLIP_CN_NONE: case PLIP_CN_SEND: rcv->state = PLIP_PK_TRIGGER; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3c11a77f5709..7959b5c2d11f 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1590,10 +1590,10 @@ static int tun_xdp_act(struct tun_struct *tun, struct bpf_prog *xdp_prog, break; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(tun->dev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: this_cpu_inc(tun->pcpu_stats->rx_dropped); break; @@ -2417,7 +2417,7 @@ static int tun_xdp_one(struct tun_struct *tun, switch (err) { case XDP_REDIRECT: *flush = true; - /* fall through */ + fallthrough; case XDP_TX: return 0; case XDP_PASS: diff --git a/drivers/net/usb/aqc111.c b/drivers/net/usb/aqc111.c index 7e44110746dd..0717c18015c9 100644 --- a/drivers/net/usb/aqc111.c +++ b/drivers/net/usb/aqc111.c @@ -333,13 +333,13 @@ static void aqc111_set_phy_speed(struct usbnet *dev, u8 autoneg, u16 speed) switch (speed) { case SPEED_5000: aqc111_data->phy_cfg |= AQ_ADV_5G; - /* fall-through */ + fallthrough; case SPEED_2500: aqc111_data->phy_cfg |= AQ_ADV_2G5; - /* fall-through */ + fallthrough; case SPEED_1000: aqc111_data->phy_cfg |= AQ_ADV_1G; - /* fall-through */ + fallthrough; case SPEED_100: aqc111_data->phy_cfg |= AQ_ADV_100M; /* fall-through */ diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c index d387bc7ac1b6..97ba67042d12 100644 --- a/drivers/net/usb/catc.c +++ b/drivers/net/usb/catc.c @@ -858,7 +858,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id default: dev_warn(&intf->dev, "Couldn't detect memory size, assuming 32k\n"); - /* fall through */ + fallthrough; case 0x87654321: catc_set_reg(catc, TxBufCount, 4); catc_set_reg(catc, RxBufCount, 16); diff --git a/drivers/net/usb/cdc-phonet.c b/drivers/net/usb/cdc-phonet.c index 9bdbd7b472a0..dba847f28096 100644 --- a/drivers/net/usb/cdc-phonet.c +++ b/drivers/net/usb/cdc-phonet.c @@ -97,7 +97,7 @@ static void tx_complete(struct urb *req) case -ECONNRESET: case -ESHUTDOWN: dev->stats.tx_aborted_errors++; - /* fall through */ + fallthrough; default: dev->stats.tx_errors++; dev_dbg(&dev->dev, "TX error (%d)\n", status); diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 442507f25aad..65b315bc60ab 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -3192,7 +3192,7 @@ static void rx_complete(struct urb *urb) case -EPIPE: dev->net->stats.rx_errors++; lan78xx_defer_kevent(dev, EVENT_RX_HALT); - /* FALLTHROUGH */ + fallthrough; case -ECONNRESET: /* async unlink */ case -ESHUTDOWN: /* hardware gone */ netif_dbg(dev, ifdown, dev->net, @@ -3213,7 +3213,7 @@ static void rx_complete(struct urb *urb) /* data overrun ... flush fifo? */ case -EOVERFLOW: dev->net->stats.rx_over_errors++; - /* FALLTHROUGH */ + fallthrough; default: state = rx_cleanup; diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c index 0ef7e1f443e3..e92cb51a2c77 100644 --- a/drivers/net/usb/pegasus.c +++ b/drivers/net/usb/pegasus.c @@ -629,7 +629,7 @@ static void write_bulk_callback(struct urb *urb) return; default: netif_info(pegasus, tx_err, net, "TX status %d\n", status); - /* FALL THROUGH */ + fallthrough; case 0: break; } @@ -1009,7 +1009,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd) switch (cmd) { case SIOCDEVPRIVATE: data[0] = pegasus->phy; - /* fall through */ + fallthrough; case SIOCDEVPRIVATE + 1: read_mii_word(pegasus, data[0], data[1] & 0x1f, &data[3]); res = 0; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2b02fefd094d..b1770489aca5 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1682,7 +1682,7 @@ static void intr_callback(struct urb *urb) case -ECONNRESET: /* unlink */ case -ESHUTDOWN: netif_device_detach(tp->netdev); - /* fall through */ + fallthrough; case -ENOENT: case -EPROTO: netif_info(tp, intr, tp->netdev, @@ -3251,7 +3251,7 @@ static void r8153b_ups_en(struct r8152 *tp, bool enable) r8152_mdio_write(tp, MII_BMCR, data); data = r8153_phy_status(tp, PHY_STAT_LAN_ON); - /* fall through */ + fallthrough; default: if (data != PHY_STAT_LAN_ON) @@ -4849,7 +4849,7 @@ static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u32 speed, u8 duplex, tp->ups_info.speed_duplex = NWAY_1000M_FULL; break; } - /* fall through */ + fallthrough; default: ret = -EINVAL; goto out; diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index e7c630d37589..733f120c852b 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -843,7 +843,7 @@ static int rtl8150_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) switch (cmd) { case SIOCDEVPRIVATE: data[0] = dev->phy; - /* fall through */ + fallthrough; case SIOCDEVPRIVATE + 1: read_mii_word(dev, dev->phy, (data[1] & 0x1f), &data[3]); break; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index e45935a5856a..2b2a841cd938 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -110,7 +110,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf) if (!usb_endpoint_dir_in(&e->desc)) continue; intr = 1; - /* FALLTHROUGH */ + fallthrough; case USB_ENDPOINT_XFER_BULK: break; default: @@ -628,7 +628,7 @@ block: /* data overrun ... flush fifo? */ case -EOVERFLOW: dev->net->stats.rx_over_errors++; - // FALLTHROUGH + fallthrough; default: state = rx_cleanup; @@ -1530,7 +1530,7 @@ static void usbnet_bh (struct timer_list *t) continue; case tx_done: kfree(entry->urb->sg); - /* fall through */ + fallthrough; case rx_cleanup: usb_free_urb (entry->urb); dev_kfree_skb (skb); diff --git a/drivers/net/veth.c b/drivers/net/veth.c index e56cd562a664..a475f48d43c4 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -610,10 +610,10 @@ static struct sk_buff *veth_xdp_rcv_one(struct veth_rq *rq, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(rq->dev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: stats->xdp_drops++; goto err_xdp; @@ -745,10 +745,10 @@ static struct sk_buff *veth_xdp_rcv_skb(struct veth_rq *rq, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(rq->dev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: stats->xdp_drops++; goto xdp_drop; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 0ada48edf749..263b005981bd 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -724,7 +724,7 @@ static struct sk_buff *receive_small(struct net_device *dev, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(vi->dev, xdp_prog, act); case XDP_DROP: @@ -922,10 +922,10 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, goto xdp_xmit; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(vi->dev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: if (unlikely(xdp_page != page)) __free_pages(xdp_page, 0); diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index def27afa1c69..1014693a5ceb 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c @@ -743,7 +743,7 @@ vmxnet3_get_rss_hash_opts(struct vmxnet3_adapter *adapter, case ESP_V4_FLOW: if (rss_fields & VMXNET3_RSS_FIELDS_ESPIP4) info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ + fallthrough; case SCTP_V4_FLOW: case IPV4_FLOW: info->data |= RXH_IP_SRC | RXH_IP_DST; diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 1ea15f2123ed..8ccd086e06cb 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -173,7 +173,7 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb, case X25_IFACE_DISCONNECT: if ((err = lapb_disconnect_request(dev)) != LAPB_OK) pr_err("lapb_disconnect_request err: %d\n", err); - /* Fall thru */ + fallthrough; default: goto drop; } diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c index 77ccf3672ede..bc2c1c7fb1a4 100644 --- a/drivers/net/wan/sdla.c +++ b/drivers/net/wan/sdla.c @@ -413,7 +413,7 @@ static void sdla_errors(struct net_device *dev, int cmd, int dlci, int ret, int case SDLA_RET_NO_BUFS: if (cmd == SDLA_INFORMATION_WRITE) break; - /* Else, fall through */ + fallthrough; default: netdev_dbg(dev, "Cmd 0x%02X generated return code 0x%02X\n", diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index de7984463595..7ee980575208 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -330,7 +330,7 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb, if (err != LAPB_OK) netdev_err(dev, "lapb_disconnect_request error: %d\n", err); - /* fall through */ + fallthrough; default: kfree_skb(skb); return NETDEV_TX_OK; diff --git a/drivers/net/wimax/i2400m/control.c b/drivers/net/wimax/i2400m/control.c index 4fe7c7e132c4..9afed3b133d3 100644 --- a/drivers/net/wimax/i2400m/control.c +++ b/drivers/net/wimax/i2400m/control.c @@ -352,7 +352,7 @@ void i2400m_report_tlv_system_state(struct i2400m *i2400m, case I2400M_SS_IDLE: d_printf(1, dev, "entering BS-negotiated idle mode\n"); - /* Fall through */ + fallthrough; case I2400M_SS_DISCONNECTING: case I2400M_SS_DATA_PATH_CONNECTED: wimax_state_change(wimax_dev, WIMAX_ST_CONNECTED); diff --git a/drivers/net/wimax/i2400m/usb-fw.c b/drivers/net/wimax/i2400m/usb-fw.c index 1f7709d24f35..27ab233650d5 100644 --- a/drivers/net/wimax/i2400m/usb-fw.c +++ b/drivers/net/wimax/i2400m/usb-fw.c @@ -135,7 +135,7 @@ retry: msleep(10); /* give the device some time */ goto retry; } - /* fall through */ + fallthrough; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ diff --git a/drivers/net/wimax/i2400m/usb-tx.c b/drivers/net/wimax/i2400m/usb-tx.c index 3a0e7226768a..3ba9d70cca1b 100644 --- a/drivers/net/wimax/i2400m/usb-tx.c +++ b/drivers/net/wimax/i2400m/usb-tx.c @@ -136,7 +136,7 @@ retry: msleep(10); /* give the device some time */ goto retry; } - /* fall through */ + fallthrough; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 9659f9e1aaa6..b684e97ac976 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -195,7 +195,7 @@ retry: msleep(10); /* give the device some time */ goto retry; } - /* fall through */ + fallthrough; case -EINVAL: /* while removing driver */ case -ENODEV: /* dev disconnect ... */ case -ENOENT: /* just ignore it */ diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c index 6b7532f7c936..ff96f22648ef 100644 --- a/drivers/net/xen-netback/hash.c +++ b/drivers/net/xen-netback/hash.c @@ -393,7 +393,7 @@ void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m) case XEN_NETIF_CTRL_HASH_ALGORITHM_NONE: seq_puts(m, "Hash Algorithm: NONE\n"); - /* FALLTHRU */ + fallthrough; default: return; } diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 7e62a6ee7622..f1c1624cec8f 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -448,7 +448,7 @@ static void frontend_changed(struct xenbus_device *dev, set_backend_state(be, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; - /* fall through - if not online */ + fallthrough; /* if not online */ case XenbusStateUnknown: set_backend_state(be, XenbusStateClosed); device_unregister(&dev->dev); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 458be6882b98..3e9895bec15f 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -2341,7 +2341,7 @@ static void netback_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* Fall through - Missed the backend's CLOSING state. */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/nfc/pn533/pn533.c b/drivers/nfc/pn533/pn533.c index 346e084387f7..f7464bd6d57c 100644 --- a/drivers/nfc/pn533/pn533.c +++ b/drivers/nfc/pn533/pn533.c @@ -2321,7 +2321,7 @@ static int pn533_transceive(struct nfc_dev *nfc_dev, break; } - /* fall through */ + fallthrough; default: /* jumbo frame ? */ if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) { @@ -2448,7 +2448,7 @@ static void pn533_wq_mi_recv(struct work_struct *work) break; } - /* fall through */ + fallthrough; default: skb_put_u8(skb, 1); /*TG*/ diff --git a/drivers/nfc/st21nfca/dep.c b/drivers/nfc/st21nfca/dep.c index 0b9ca6d20ffa..8874d605b14f 100644 --- a/drivers/nfc/st21nfca/dep.c +++ b/drivers/nfc/st21nfca/dep.c @@ -611,7 +611,7 @@ static void st21nfca_im_recv_dep_res_cb(void *context, struct sk_buff *skb, switch (ST21NFCA_NFC_DEP_PFB_TYPE(dep_res->pfb)) { case ST21NFCA_NFC_DEP_PFB_ACK_NACK_PDU: pr_err("Received a ACK/NACK PDU\n"); - /* fall through */ + fallthrough; case ST21NFCA_NFC_DEP_PFB_I_PDU: info->dep_info.curr_nfc_dep_pni = ST21NFCA_NFC_DEP_PFB_PNI(dep_res->pfb + 1); diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index e46adaac1c63..3bd97c73f983 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c @@ -1153,7 +1153,7 @@ static int trf7970a_switch_rf(struct nfc_digital_dev *ddev, bool on) dev_err(trf->dev, "%s - Invalid request: %d %d\n", __func__, trf->state, on); ret = -EINVAL; - /* FALLTHROUGH */ + fallthrough; case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: case TRF7970A_ST_WAIT_FOR_RX_DATA: @@ -1960,7 +1960,7 @@ static void trf7970a_shutdown(struct trf7970a *trf) case TRF7970A_ST_WAIT_TO_ISSUE_EOF: case TRF7970A_ST_LISTENING: trf7970a_send_err_upstream(trf, -ECANCELED); - /* FALLTHROUGH */ + fallthrough; case TRF7970A_ST_IDLE: case TRF7970A_ST_IDLE_RX_BLOCKED: trf7970a_switch_rf_off(trf); diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index e6d1f5b298f3..4a02561cfb96 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c @@ -1483,7 +1483,7 @@ static void ntb_rx_copy_callback(void *data, case DMA_TRANS_READ_FAILED: case DMA_TRANS_WRITE_FAILED: entry->errors++; - /* fall through */ + fallthrough; case DMA_TRANS_ABORTED: { struct ntb_transport_qp *qp = entry->qp; @@ -1739,7 +1739,7 @@ static void ntb_tx_copy_callback(void *data, case DMA_TRANS_READ_FAILED: case DMA_TRANS_WRITE_FAILED: entry->errors++; - /* fall through */ + fallthrough; case DMA_TRANS_ABORTED: { void __iomem *offset = diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 88cff309d8e4..96ee5a476c4d 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -330,7 +330,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_RESETTING: case NVME_CTRL_CONNECTING: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } @@ -340,7 +340,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_NEW: case NVME_CTRL_LIVE: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } @@ -350,7 +350,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_NEW: case NVME_CTRL_RESETTING: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } @@ -361,7 +361,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_RESETTING: case NVME_CTRL_CONNECTING: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } @@ -371,7 +371,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, case NVME_CTRL_DELETING: case NVME_CTRL_DEAD: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } @@ -380,7 +380,7 @@ bool nvme_change_ctrl_state(struct nvme_ctrl *ctrl, switch (old_state) { case NVME_CTRL_DELETING: changed = true; - /* FALLTHRU */ + fallthrough; default: break; } diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index ba725ae47305..24d174a0623b 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1244,7 +1244,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req, bool reserved) switch (dev->ctrl.state) { case NVME_CTRL_CONNECTING: nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_DELETING); - /* fall through */ + fallthrough; case NVME_CTRL_DELETING: dev_warn_ratelimited(dev->ctrl.device, "I/O %d QID %d timeout, disable controller\n", diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 44c76ffbb264..610e0b6bb6e4 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -1915,7 +1915,7 @@ static int nvme_rdma_cm_handler(struct rdma_cm_id *cm_id, case RDMA_CM_EVENT_CONNECT_ERROR: case RDMA_CM_EVENT_UNREACHABLE: nvme_rdma_destroy_queue_ib(queue); - /* fall through */ + fallthrough; case RDMA_CM_EVENT_ADDR_ERROR: dev_dbg(queue->ctrl->ctrl.device, "CM error event %d\n", ev->event); diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c index 62fbaecdc960..f0c4bb47d22d 100644 --- a/drivers/nvme/host/tcp.c +++ b/drivers/nvme/host/tcp.c @@ -866,7 +866,6 @@ static void nvme_tcp_state_change(struct sock *sk) case TCP_LAST_ACK: case TCP_FIN_WAIT1: case TCP_FIN_WAIT2: - /* fallthrough */ nvme_tcp_error_recovery(&queue->ctrl->ctrl); break; default: diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index b92f45f5cd5b..ca7a58dae275 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -73,7 +73,7 @@ inline u16 errno_to_nvme_status(struct nvmet_req *req, int errno) status = NVME_SC_ACCESS_DENIED; break; case -EIO: - /* FALLTHRU */ + fallthrough; default: req->error_loc = offsetof(struct nvme_common_command, opcode); status = NVME_SC_INTERNAL | NVME_SC_DNR; diff --git a/drivers/nvme/target/fcloop.c b/drivers/nvme/target/fcloop.c index c97e60b71bbc..3da067a8311e 100644 --- a/drivers/nvme/target/fcloop.c +++ b/drivers/nvme/target/fcloop.c @@ -812,7 +812,7 @@ fcloop_fcp_op(struct nvmet_fc_target_port *tgtport, break; /* Fall-Thru to RSP handling */ - /* FALLTHRU */ + fallthrough; case NVMET_FCOP_RSP: if (fcpreq) { diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 3dd6f566a240..125dde3f410e 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -139,7 +139,6 @@ static u16 blk_to_nvme_status(struct nvmet_req *req, blk_status_t blk_sts) req->error_loc = offsetof(struct nvme_rw_command, nsid); break; case BLK_STS_IOERR: - /* fallthru */ default: status = NVME_SC_INTERNAL | NVME_SC_DNR; req->error_loc = offsetof(struct nvme_common_command, opcode); diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index 3ccb59260b4a..ae6620489457 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -1758,7 +1758,7 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id, schedule_delayed_work(&port->repair_work, 0); break; } - /* FALLTHROUGH */ + fallthrough; case RDMA_CM_EVENT_DISCONNECTED: case RDMA_CM_EVENT_TIMEWAIT_EXIT: nvmet_rdma_queue_disconnect(queue); @@ -1769,7 +1769,7 @@ static int nvmet_rdma_cm_handler(struct rdma_cm_id *cm_id, case RDMA_CM_EVENT_REJECTED: pr_debug("Connection rejected: %s\n", rdma_reject_msg(cm_id, event->status)); - /* FALLTHROUGH */ + fallthrough; case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_CONNECT_ERROR: nvmet_rdma_queue_connect_fail(cm_id, queue); diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index f28d6a3c5a68..4547ac44c8d4 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c @@ -260,7 +260,7 @@ static void parport_ieee1284_terminate (struct parport *port) port->ieee1284.phase = IEEE1284_PH_FWD_IDLE; } - /* fall through */ + fallthrough; default: /* Terminate from all other modes. */ @@ -598,7 +598,7 @@ ssize_t parport_write (struct parport *port, const void *buffer, size_t len) case IEEE1284_MODE_NIBBLE: case IEEE1284_MODE_BYTE: parport_negotiate (port, IEEE1284_MODE_COMPAT); - /* fall through */ + fallthrough; case IEEE1284_MODE_COMPAT: pr_debug("%s: Using compatibility mode\n", port->name); fn = port->ops->compat_write_data; @@ -702,7 +702,7 @@ ssize_t parport_read (struct parport *port, void *buffer, size_t len) if (parport_negotiate (port, IEEE1284_MODE_NIBBLE)) { return -EIO; } - /* fall through - to NIBBLE */ + fallthrough; /* to NIBBLE */ case IEEE1284_MODE_NIBBLE: pr_debug("%s: Using nibble mode\n", port->name); fn = port->ops->nibble_read_data; diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 77e37e3cb3a0..eda4ded4d5e5 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1647,7 +1647,7 @@ static int parport_ECP_supported(struct parport *pb) break; default: pr_warn("0x%lx: Unknown implementation ID\n", pb->base); - /* Fall through - Assume 1 */ + fallthrough; /* Assume 1 */ case 1: pword = 1; } diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 90df28c7cb0c..5fef2613b223 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -439,7 +439,7 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0); break; - case IMX6QP: /* FALLTHROUGH */ + case IMX6QP: case IMX6Q: /* power up core phy and enable ref clock */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, @@ -642,7 +642,7 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6SX_GPR12_PCIE_RX_EQ_MASK, IMX6SX_GPR12_PCIE_RX_EQ_2); - /* FALLTHROUGH */ + fallthrough; default: regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); @@ -1105,7 +1105,7 @@ static int imx6_pcie_probe(struct platform_device *pdev) dev_err(dev, "pcie_aux clock source missing or invalid\n"); return PTR_ERR(imx6_pcie->pcie_aux); } - /* fall through */ + fallthrough; case IMX7D: if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) imx6_pcie->controller_id = 1; diff --git a/drivers/pci/controller/pci-rcar-gen2.c b/drivers/pci/controller/pci-rcar-gen2.c index c9530038ca9a..afde4aa8f6dc 100644 --- a/drivers/pci/controller/pci-rcar-gen2.c +++ b/drivers/pci/controller/pci-rcar-gen2.c @@ -223,7 +223,7 @@ static void rcar_pci_setup(struct rcar_pci_priv *priv) pr_warn("unknown window size %ld - defaulting to 256M\n", window_size); window_size = SZ_256M; - /* fall-through */ + fallthrough; case SZ_256M: val |= RCAR_USBCTR_PCIAHB_WIN1_256M; break; diff --git a/drivers/pci/hotplug/ibmphp_res.c b/drivers/pci/hotplug/ibmphp_res.c index 5c93aa14f0de..ae9acc77d14f 100644 --- a/drivers/pci/hotplug/ibmphp_res.c +++ b/drivers/pci/hotplug/ibmphp_res.c @@ -1941,7 +1941,7 @@ static int __init update_bridge_ranges(struct bus_node **bus) break; case PCI_HEADER_TYPE_BRIDGE: function = 0x8; - /* fall through */ + fallthrough; case PCI_HEADER_TYPE_MULTIBRIDGE: /* We assume here that only 1 bus behind the bridge TO DO: add functionality for several: diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 6503d15effbb..9f85815b4f53 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -236,7 +236,7 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) switch (ctrl->state) { case BLINKINGOFF_STATE: cancel_delayed_work(&ctrl->button_work); - /* fall through */ + fallthrough; case ON_STATE: ctrl->state = POWEROFF_STATE; mutex_unlock(&ctrl->state_lock); @@ -265,7 +265,7 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events) switch (ctrl->state) { case BLINKINGON_STATE: cancel_delayed_work(&ctrl->button_work); - /* fall through */ + fallthrough; case OFF_STATE: ctrl->state = POWERON_STATE; mutex_unlock(&ctrl->state_lock); diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index afdc52d1cae7..65502e3f7b4f 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -642,7 +642,7 @@ int shpchp_sysfs_enable_slot(struct slot *p_slot) switch (p_slot->state) { case BLINKINGON_STATE: cancel_delayed_work(&p_slot->work); - /* fall through */ + fallthrough; case STATIC_STATE: p_slot->state = POWERON_STATE; mutex_unlock(&p_slot->lock); @@ -678,7 +678,7 @@ int shpchp_sysfs_disable_slot(struct slot *p_slot) switch (p_slot->state) { case BLINKINGOFF_STATE: cancel_delayed_work(&p_slot->work); - /* fall through */ + fallthrough; case STATIC_STATE: p_slot->state = POWEROFF_STATE; mutex_unlock(&p_slot->lock); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index a458c46d7e39..e39c5499770f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1049,7 +1049,7 @@ static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) need_restore = true; - /* Fall-through - force to D0 */ + fallthrough; /* force to D0 */ default: pmcsr = 0; break; @@ -2541,7 +2541,7 @@ static pci_power_t pci_target_state(struct pci_dev *dev, bool wakeup) case PCI_D2: if (pci_no_d1d2(dev)) break; - /* else, fall through */ + fallthrough; default: target_state = state; } diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c index bd2b691fa7a3..d35186b01d98 100644 --- a/drivers/pci/proc.c +++ b/drivers/pci/proc.c @@ -231,7 +231,7 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd, } /* If arch decided it can't, fall through... */ #endif /* HAVE_PCI_MMAP */ - /* fall through */ + fallthrough; default: ret = -EINVAL; break; diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bdf9b52567e0..2a589b6d6ed8 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1730,7 +1730,7 @@ static void quirk_jmicron_ata(struct pci_dev *pdev) case PCI_DEVICE_ID_JMICRON_JMB366: /* Redirect IDE second PATA port to the right spot */ conf5 |= (1 << 24); - /* Fall through */ + fallthrough; case PCI_DEVICE_ID_JMICRON_JMB361: case PCI_DEVICE_ID_JMICRON_JMB363: case PCI_DEVICE_ID_JMICRON_JMB369: @@ -2224,7 +2224,7 @@ static void quirk_netmos(struct pci_dev *dev) if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && dev->subsystem_device == 0x0299) return; - /* else, fall through */ + fallthrough; case PCI_DEVICE_ID_NETMOS_9735: case PCI_DEVICE_ID_NETMOS_9745: case PCI_DEVICE_ID_NETMOS_9845: diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 3951e02b7ded..2ce636937c6e 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1253,7 +1253,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) additional_mmio_size = pci_hotplug_mmio_size; additional_mmio_pref_size = pci_hotplug_mmio_pref_size; } - /* Fall through */ + fallthrough; default: pbus_size_io(bus, realloc_head ? 0 : additional_io_size, additional_io_size, realloc_head); diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index fab267e359e7..c0e85be598c1 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -1096,7 +1096,7 @@ static void __ref pcifront_backend_changed(struct xenbus_device *xdev, case XenbusStateClosed: if (xdev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state. */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: dev_warn(&xdev->dev, "backend going away!\n"); pcifront_try_disconnect(pdev); diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c index 590e594092f2..a7c7c7cd2326 100644 --- a/drivers/pcmcia/db1xxx_ss.c +++ b/drivers/pcmcia/db1xxx_ss.c @@ -255,10 +255,10 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt, switch (state->Vcc) { case 50: ++v; - /* fall through */ + fallthrough; case 33: ++v; - /* fall through */ + fallthrough; case 0: break; default: @@ -269,11 +269,11 @@ static int db1x_pcmcia_configure(struct pcmcia_socket *skt, switch (state->Vpp) { case 12: ++p; - /* fall through */ + fallthrough; case 33: case 50: ++p; - /* fall through */ + fallthrough; case 0: break; default: diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c index 7b7d23f25713..a0a71c1df042 100644 --- a/drivers/perf/arm-ccn.c +++ b/drivers/perf/arm-ccn.c @@ -1404,7 +1404,7 @@ static int arm_ccn_init_nodes(struct arm_ccn *ccn, int region, break; case CCN_TYPE_SBAS: ccn->sbas_present = 1; - /* Fall-through */ + fallthrough; default: component = &ccn->node[id]; break; diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index e51ddb6d63ed..cc00915ad6d1 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -1002,7 +1002,7 @@ static void __arm_spe_pmu_dev_probe(void *info) default: dev_warn(dev, "unknown PMSIDR_EL1.Interval [%d]; assuming 8\n", fld); - /* Fallthrough */ + fallthrough; case 8: spe_pmu->min_period = 4096; } @@ -1021,7 +1021,7 @@ static void __arm_spe_pmu_dev_probe(void *info) default: dev_warn(dev, "unknown PMSIDR_EL1.CountSize [%d]; assuming 2\n", fld); - /* Fallthrough */ + fallthrough; case 2: spe_pmu->counter_sz = 12; } diff --git a/drivers/phy/qualcomm/phy-qcom-usb-hs.c b/drivers/phy/qualcomm/phy-qcom-usb-hs.c index 61054272a7c8..327df1a99f77 100644 --- a/drivers/phy/qualcomm/phy-qcom-usb-hs.c +++ b/drivers/phy/qualcomm/phy-qcom-usb-hs.c @@ -53,7 +53,7 @@ static int qcom_usb_hs_phy_set_mode(struct phy *phy, case PHY_MODE_USB_OTG: case PHY_MODE_USB_HOST: val |= ULPI_INT_IDGRD; - /* fall through */ + fallthrough; case PHY_MODE_USB_DEVICE: val |= ULPI_INT_SESS_VALID; default: diff --git a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c index a84e9f027fc4..46ebdb1460a3 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-usb2.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-usb2.c @@ -546,7 +546,7 @@ static void rockchip_usb2phy_otg_sm_work(struct work_struct *work) rport->state = OTG_STATE_B_IDLE; if (!vbus_attach) rockchip_usb2phy_power_off(rport->phy); - /* fall through */ + fallthrough; case OTG_STATE_B_IDLE: if (extcon_get_state(rphy->edev, EXTCON_USB_HOST) > 0) { dev_dbg(&rport->phy->dev, "usb otg host connect\n"); @@ -754,11 +754,11 @@ static void rockchip_chg_detect_work(struct work_struct *work) rphy->chg_type = POWER_SUPPLY_TYPE_USB_DCP; else rphy->chg_type = POWER_SUPPLY_TYPE_USB_CDP; - /* fall through */ + fallthrough; case USB_CHG_STATE_SECONDARY_DONE: rphy->chg_state = USB_CHG_STATE_DETECTED; delay = 0; - /* fall through */ + fallthrough; case USB_CHG_STATE_DETECTED: /* put the controller in normal mode */ property_enable(base, &rphy->phy_cfg->chg_det.opmode, true); @@ -835,7 +835,7 @@ static void rockchip_usb2phy_sm_work(struct work_struct *work) dev_dbg(&rport->phy->dev, "FS/LS online\n"); break; } - /* fall through */ + fallthrough; case PHY_STATE_CONNECT: if (rport->suspended) { dev_dbg(&rport->phy->dev, "Connected\n"); diff --git a/drivers/platform/olpc/olpc-xo175-ec.c b/drivers/platform/olpc/olpc-xo175-ec.c index 5e1d14e35f20..0d46706afd2d 100644 --- a/drivers/platform/olpc/olpc-xo175-ec.c +++ b/drivers/platform/olpc/olpc-xo175-ec.c @@ -431,7 +431,7 @@ static void olpc_xo175_ec_complete(void *arg) input_sync(priv->pwrbtn); input_report_key(priv->pwrbtn, KEY_POWER, 0); input_sync(priv->pwrbtn); - /* fall through */ + fallthrough; case EVENT_POWER_PRESS_WAKE: case EVENT_TIMED_HOST_WAKE: pm_wakeup_event(priv->pwrbtn->dev.parent, diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 60c18f21588d..49f4b73be513 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1001,7 +1001,7 @@ static acpi_status WMID_get_u32(u32 *value, u32 cap) *value = tmp & 0x1; return 0; } - /* fall through */ + fallthrough; default: return AE_ERROR; } @@ -1328,7 +1328,7 @@ static acpi_status get_u32(u32 *value, u32 cap) status = AMW0_get_u32(value, cap); break; } - /* fall through */ + fallthrough; case ACER_WMID: status = WMID_get_u32(value, cap); break; @@ -1371,7 +1371,7 @@ static acpi_status set_u32(u32 value, u32 cap) return AMW0_set_u32(value, cap); } - /* fall through */ + fallthrough; case ACER_WMID: return WMID_set_u32(value, cap); case ACER_WMID_v2: @@ -1381,7 +1381,7 @@ static acpi_status set_u32(u32 value, u32 cap) return wmid_v2_set_u32(value, cap); else if (wmi_has_guid(WMID_GUID2)) return WMID_set_u32(value, cap); - /* fall through */ + fallthrough; default: return AE_BAD_PARAMETER; } diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c index 5e9c2296931c..70edc5bb3a14 100644 --- a/drivers/platform/x86/dell-laptop.c +++ b/drivers/platform/x86/dell-laptop.c @@ -1587,10 +1587,10 @@ static ssize_t kbd_led_timeout_store(struct device *dev, switch (unit) { case KBD_TIMEOUT_DAYS: value *= 24; - /* fall through */ + fallthrough; case KBD_TIMEOUT_HOURS: value *= 60; - /* fall through */ + fallthrough; case KBD_TIMEOUT_MINUTES: value *= 60; unit = KBD_TIMEOUT_SECONDS; diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c index ec515223f654..d8afed5db94c 100644 --- a/drivers/platform/x86/surfacepro3_button.c +++ b/drivers/platform/x86/surfacepro3_button.c @@ -84,28 +84,28 @@ static void surface_button_notify(struct acpi_device *device, u32 event) /* Power button press,release handle */ case SURFACE_BUTTON_NOTIFY_PRESS_POWER: pressed = true; - /*fall through*/ + fallthrough; case SURFACE_BUTTON_NOTIFY_RELEASE_POWER: key_code = KEY_POWER; break; /* Home button press,release handle */ case SURFACE_BUTTON_NOTIFY_PRESS_HOME: pressed = true; - /*fall through*/ + fallthrough; case SURFACE_BUTTON_NOTIFY_RELEASE_HOME: key_code = KEY_LEFTMETA; break; /* Volume up button press,release handle */ case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_UP: pressed = true; - /*fall through*/ + fallthrough; case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_UP: key_code = KEY_VOLUMEUP; break; /* Volume down button press,release handle */ case SURFACE_BUTTON_NOTIFY_PRESS_VOLUME_DOWN: pressed = true; - /*fall through*/ + fallthrough; case SURFACE_BUTTON_NOTIFY_RELEASE_VOLUME_DOWN: key_code = KEY_VOLUMEDOWN; break; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 4864a5c189d4..9c4df41687a3 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -4060,7 +4060,7 @@ static bool hotkey_notify_6xxx(const u32 hkey, * AC status changed; can be triggered by plugging or * unplugging AC adapter, docking or undocking. */ - /* fallthrough */ + fallthrough; case TP_HKEY_EV_KEY_NUMLOCK: case TP_HKEY_EV_KEY_FN: @@ -4176,7 +4176,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) known_ev = true; break; } - /* fallthrough - to default */ + fallthrough; /* to default */ default: known_ev = false; } @@ -6266,7 +6266,7 @@ static int thermal_get_sensor(int idx, s32 *value) idx -= 8; } #endif - /* fallthrough */ + fallthrough; case TPACPI_THERMAL_TPEC_8: if (idx <= 7) { if (!acpi_ec_read(t + idx, &tmp)) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 36fff00af9eb..e557d757c647 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -2748,7 +2748,7 @@ static void toshiba_acpi_process_hotkeys(struct toshiba_acpi_dev *dev) result = hci_write(dev, HCI_SYSTEM_EVENT, 1); if (result == TOS_SUCCESS) pr_notice("Re-enabled hotkeys\n"); - /* Fall through */ + fallthrough; default: retries--; break; diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index 9469fe182d02..db65be026920 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -748,7 +748,7 @@ static int ab8500_charger_max_usb_curr(struct ab8500_charger *di, USB_CH_IP_CUR_LVL_1P5; break; } - /* else, fall through */ + fallthrough; case USB_STAT_HM_IDGND: dev_err(di->dev, "USB Type - Charging not allowed\n"); di->max_usb_in_curr.usb_type_max = USB_CH_IP_CUR_LVL_0P05; @@ -2410,7 +2410,7 @@ static void ab8500_charger_usb_state_changed_work(struct work_struct *work) * of 1sec for enabling charging */ msleep(1000); - /* Intentional fall through */ + fallthrough; case AB8500_BM_USB_STATE_CONFIGURED: /* * USB is configured, enable charging with the charging diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 751c4f6c7487..7eec415c82a3 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -1542,7 +1542,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_INITMEASURING); - /* Intentional fallthrough */ + fallthrough; case AB8500_FG_DISCHARGE_INITMEASURING: /* * Discard a number of samples during startup. @@ -1572,7 +1572,7 @@ static void ab8500_fg_algorithm_discharging(struct ab8500_fg *di) ab8500_fg_discharge_state_to(di, AB8500_FG_DISCHARGE_RECOVERY); - /* Intentional fallthrough */ + fallthrough; case AB8500_FG_DISCHARGE_RECOVERY: sleep_time = di->bm->fg_params->recovery_sleep_timer; diff --git a/drivers/power/supply/abx500_chargalg.c b/drivers/power/supply/abx500_chargalg.c index 2fb33a07879a..175c4f3d7955 100644 --- a/drivers/power/supply/abx500_chargalg.c +++ b/drivers/power/supply/abx500_chargalg.c @@ -1419,7 +1419,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) abx500_chargalg_stop_charging(di); di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING; abx500_chargalg_state_to(di, STATE_HANDHELD); - /* Intentional fallthrough */ + fallthrough; case STATE_HANDHELD: break; @@ -1435,7 +1435,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) di->maintenance_chg = false; abx500_chargalg_state_to(di, STATE_SUSPENDED); power_supply_changed(di->chargalg_psy); - /* Intentional fallthrough */ + fallthrough; case STATE_SUSPENDED: /* CHARGING is suspended */ @@ -1444,7 +1444,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_BATT_REMOVED_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_BATT_REMOVED); - /* Intentional fallthrough */ + fallthrough; case STATE_BATT_REMOVED: if (!di->events.batt_rem) @@ -1454,7 +1454,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_HW_TEMP_PROTECT_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_HW_TEMP_PROTECT); - /* Intentional fallthrough */ + fallthrough; case STATE_HW_TEMP_PROTECT: if (!di->events.main_thermal_prot && @@ -1465,7 +1465,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_OVV_PROTECT_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_OVV_PROTECT); - /* Intentional fallthrough */ + fallthrough; case STATE_OVV_PROTECT: if (!di->events.vbus_ovv && @@ -1479,7 +1479,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_CHG_NOT_OK_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_CHG_NOT_OK); - /* Intentional fallthrough */ + fallthrough; case STATE_CHG_NOT_OK: if (!di->events.mainextchnotok && @@ -1490,7 +1490,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_SAFETY_TIMER_EXPIRED_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_SAFETY_TIMER_EXPIRED); - /* Intentional fallthrough */ + fallthrough; case STATE_SAFETY_TIMER_EXPIRED: /* We exit this state when charger is removed */ @@ -1537,7 +1537,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_WAIT_FOR_RECHARGE_INIT: abx500_chargalg_hold_charging(di); abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE); - /* Intentional fallthrough */ + fallthrough; case STATE_WAIT_FOR_RECHARGE: if (di->batt_data.percent <= @@ -1558,7 +1558,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) di->bm->batt_id].maint_a_cur_lvl); abx500_chargalg_state_to(di, STATE_MAINTENANCE_A); power_supply_changed(di->chargalg_psy); - /* Intentional fallthrough*/ + fallthrough; case STATE_MAINTENANCE_A: if (di->events.maintenance_timer_expired) { @@ -1578,7 +1578,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) di->bm->batt_id].maint_b_cur_lvl); abx500_chargalg_state_to(di, STATE_MAINTENANCE_B); power_supply_changed(di->chargalg_psy); - /* Intentional fallthrough*/ + fallthrough; case STATE_MAINTENANCE_B: if (di->events.maintenance_timer_expired) { @@ -1597,7 +1597,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) di->charge_status = POWER_SUPPLY_STATUS_CHARGING; abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH); power_supply_changed(di->chargalg_psy); - /* Intentional fallthrough */ + fallthrough; case STATE_TEMP_LOWHIGH: if (!di->events.btemp_lowhigh) @@ -1607,7 +1607,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_WD_EXPIRED_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_WD_EXPIRED); - /* Intentional fallthrough */ + fallthrough; case STATE_WD_EXPIRED: if (!di->events.ac_wd_expired && @@ -1618,7 +1618,7 @@ static void abx500_chargalg_algorithm(struct abx500_chargalg *di) case STATE_TEMP_UNDEROVER_INIT: abx500_chargalg_stop_charging(di); abx500_chargalg_state_to(di, STATE_TEMP_UNDEROVER); - /* Intentional fallthrough */ + fallthrough; case STATE_TEMP_UNDEROVER: if (!di->events.btemp_underover) diff --git a/drivers/power/supply/axp20x_usb_power.c b/drivers/power/supply/axp20x_usb_power.c index d01dc0332edc..0eaa86c52874 100644 --- a/drivers/power/supply/axp20x_usb_power.c +++ b/drivers/power/supply/axp20x_usb_power.c @@ -349,7 +349,7 @@ static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, case 100000: if (power->axp20x_id == AXP221_ID) return -EINVAL; - /* fall through */ + fallthrough; case 500000: case 900000: val = (900000 - intval) / 400000; diff --git a/drivers/power/supply/cros_usbpd-charger.c b/drivers/power/supply/cros_usbpd-charger.c index 2a45e84447fe..d89e08efd2ad 100644 --- a/drivers/power/supply/cros_usbpd-charger.c +++ b/drivers/power/supply/cros_usbpd-charger.c @@ -383,7 +383,7 @@ static int cros_usbpd_charger_get_prop(struct power_supply *psy, */ if (ec_device->mkbp_event_supported || port->psy_online) break; - /* fall through */ + fallthrough; case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN: case POWER_SUPPLY_PROP_VOLTAGE_NOW: diff --git a/drivers/power/supply/max8925_power.c b/drivers/power/supply/max8925_power.c index 5fca4960f440..8878f9131184 100644 --- a/drivers/power/supply/max8925_power.c +++ b/drivers/power/supply/max8925_power.c @@ -121,7 +121,7 @@ static irqreturn_t max8925_charger_handler(int irq, void *data) case MAX8925_IRQ_VCHG_THM_OK_F: /* Battery is not ready yet */ dev_dbg(chip->dev, "Battery temperature is out of range\n"); - /* Fall through */ + fallthrough; case MAX8925_IRQ_VCHG_DC_OVP: dev_dbg(chip->dev, "Error detection\n"); __set_charger(info, 0); diff --git a/drivers/power/supply/wm831x_power.c b/drivers/power/supply/wm831x_power.c index 65832bc229f6..18b33f14dfee 100644 --- a/drivers/power/supply/wm831x_power.c +++ b/drivers/power/supply/wm831x_power.c @@ -665,7 +665,7 @@ static int wm831x_power_probe(struct platform_device *pdev) break; default: dev_err(&pdev->dev, "Failed to find USB phy: %d\n", ret); - /* fall-through */ + fallthrough; case -EPROBE_DEFER: goto err_bat_irq; break; diff --git a/drivers/power/supply/wm8350_power.c b/drivers/power/supply/wm8350_power.c index 26923af574f4..e05cee457471 100644 --- a/drivers/power/supply/wm8350_power.c +++ b/drivers/power/supply/wm8350_power.c @@ -227,7 +227,7 @@ static irqreturn_t wm8350_charger_handler(int irq, void *data) case WM8350_IRQ_EXT_USB_FB: case WM8350_IRQ_EXT_WALL_FB: wm8350_charger_config(wm8350, policy); - /* Fall through */ + fallthrough; case WM8350_IRQ_EXT_BAT_FB: power_supply_changed(power->battery); power_supply_changed(power->usb); diff --git a/drivers/ps3/ps3av.c b/drivers/ps3/ps3av.c index 24f04ffdd986..9d66257e1da5 100644 --- a/drivers/ps3/ps3av.c +++ b/drivers/ps3/ps3av.c @@ -769,7 +769,7 @@ static int ps3av_auto_videomode(struct ps3av_pkt_av_get_hw_conf *av_hw_conf) switch (info->monitor_type) { case PS3AV_MONITOR_TYPE_DVI: dvi = PS3AV_MODE_DVI; - /* fall through */ + fallthrough; case PS3AV_MONITOR_TYPE_HDMI: id = ps3av_hdmi_get_id(info); break; diff --git a/drivers/ps3/ps3av_cmd.c b/drivers/ps3/ps3av_cmd.c index f0e650cc866e..c22206652f06 100644 --- a/drivers/ps3/ps3av_cmd.c +++ b/drivers/ps3/ps3av_cmd.c @@ -693,11 +693,11 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport, switch (ch) { case PS3AV_CMD_AUDIO_NUM_OF_CH_8: audio->audio_enable[3] = 1; - /* fall through */ + fallthrough; case PS3AV_CMD_AUDIO_NUM_OF_CH_6: audio->audio_enable[2] = 1; audio->audio_enable[1] = 1; - /* fall through */ + fallthrough; case PS3AV_CMD_AUDIO_NUM_OF_CH_2: default: audio->audio_enable[0] = 1; diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index c07ceec3c6d4..a30342942e26 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -2150,7 +2150,7 @@ static void mport_release_mapping(struct kref *ref) switch (map->dir) { case MAP_INBOUND: rio_unmap_inb_region(mport, map->phys_addr); - /* fall through */ + fallthrough; case MAP_DMA: dma_free_coherent(mport->dev.parent, map->size, map->virt_addr, map->phys_addr); diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index fbc95cadaf53..1bacb37e8a99 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -399,7 +399,7 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp) if (rate_count > 0) break; - /* fall through */ + fallthrough; default: /* Not supported for this regulator */ return -ENOTSUPP; @@ -1022,7 +1022,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) * (See include/linux/mfd/axp20x.h) */ reg = AXP803_DCDC_FREQ_CTRL; - /* Fall through - to the check below.*/ + fallthrough; /* to the check below */ case AXP806_ID: /* * AXP806 also have DCDC work frequency setting register at a @@ -1030,7 +1030,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) */ if (axp20x->variant == AXP806_ID) reg = AXP806_DCDC_FREQ_CTRL; - /* Fall through */ + fallthrough; case AXP221_ID: case AXP223_ID: case AXP809_ID: @@ -1118,7 +1118,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work * (See include/linux/mfd/axp20x.h) */ reg = AXP806_DCDC_MODE_CTRL2; - /* Fall through - to the check below. */ + fallthrough; /* to the check below */ case AXP221_ID: case AXP223_ID: case AXP809_ID: diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 75ff7c563c5d..3fd359914690 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1895,7 +1895,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, case EXCLUSIVE_GET: dev_warn(dev, "dummy supplies not allowed for exclusive requests\n"); - /* fall through */ + fallthrough; default: return ERR_PTR(-ENODEV); diff --git a/drivers/regulator/slg51000-regulator.c b/drivers/regulator/slg51000-regulator.c index 44e4cecbf6de..87b020d0b958 100644 --- a/drivers/regulator/slg51000-regulator.c +++ b/drivers/regulator/slg51000-regulator.c @@ -319,7 +319,7 @@ static int slg51000_regulator_init(struct slg51000 *chip) rdesc->linear_min_sel = 0; break; } - /* Fall through - to the check below.*/ + fallthrough; /* to the check below */ default: rdesc->linear_min_sel = vsel_range[0]; diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index f7db250a7583..430265c404d6 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -312,7 +312,7 @@ static int twl6030smps_list_voltage(struct regulator_dev *rdev, unsigned index) switch (info->flags) { case SMPS_OFFSET_EN: voltage = 100000; - /* fall through */ + fallthrough; case 0: switch (index) { case 0: diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 6955fab0a78b..d94b7391bf9d 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -511,7 +511,6 @@ static void omap_rproc_mbox_callback(struct mbox_client *client, void *data) dev_info(dev, "received echo reply from %s\n", name); break; case RP_MBOX_SUSPEND_ACK: - /* Fall through */ case RP_MBOX_SUSPEND_CANCEL: oproc->suspend_acked = msg == RP_MBOX_SUSPEND_ACK; complete(&oproc->pm_comp); diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c index d170fe663210..e8aa8691deb2 100644 --- a/drivers/reset/reset-imx7.c +++ b/drivers/reset/reset-imx7.c @@ -222,7 +222,7 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev, switch (id) { case IMX8MQ_RESET_PCIEPHY: - case IMX8MQ_RESET_PCIEPHY2: /* fallthrough */ + case IMX8MQ_RESET_PCIEPHY2: /* * wait for more than 10us to release phy g_rst and * btnrst @@ -232,12 +232,12 @@ static int imx8mq_reset_set(struct reset_controller_dev *rcdev, break; case IMX8MQ_RESET_PCIE_CTRL_APPS_EN: - case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DSI_RESET_N: /* fallthrough */ - case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: /* fallthrough */ + case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN: + case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N: + case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N: + case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N: + case IMX8MQ_RESET_MIPI_DSI_RESET_N: + case IMX8MQ_RESET_MIPI_DSI_RESET_BYTE_N: value = assert ? 0 : bit; break; } diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 1995f5b3ea67..f40312b16da0 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -553,7 +553,7 @@ static void qcom_glink_receive_version(struct qcom_glink *glink, break; case GLINK_VERSION_1: glink->features &= features; - /* FALLTHROUGH */ + fallthrough; default: qcom_glink_send_version_ack(glink); break; @@ -584,7 +584,7 @@ static void qcom_glink_receive_version_ack(struct qcom_glink *glink, break; glink->features &= features; - /* FALLTHROUGH */ + fallthrough; default: qcom_glink_send_version(glink); break; diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 9b70b371bd0c..8a89bc52b0d4 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -740,7 +740,7 @@ static int wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; wdt_margin = new_margin; wdt_ping(); - /* Fall through */ + fallthrough; case WDIOC_GETTIMEOUT: return put_user(wdt_margin, (int __user *)arg); diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c index ca55ba975aeb..f8b99cb72959 100644 --- a/drivers/rtc/rtc-pcf85063.c +++ b/drivers/rtc/rtc-pcf85063.c @@ -353,7 +353,7 @@ static int pcf85063_load_capacitance(struct pcf85063 *pcf85063, default: dev_warn(&pcf85063->rtc->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 7000", load); - /* fall through */ + fallthrough; case 7000: break; case 12500: diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 47e0f411dd5c..57d351dfe272 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -108,7 +108,7 @@ static int pcf8523_load_capacitance(struct i2c_client *client) default: dev_warn(&client->dev, "Unknown quartz-load-femtofarads value: %d. Assuming 12500", load); - /* fall through */ + fallthrough; case 12500: value |= REG_CONTROL1_CAP_SEL; break; diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index c9bc3d4a1e66..0a969af80af7 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -331,7 +331,7 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) default: dev_warn(&pdev->dev, "invalid crystal-freq specified in device-tree. Assuming no crystal\n"); - /* fall-through */ + fallthrough; case 0: /* keep XTAL on in low-power mode */ pers0_set = STMP3XXX_RTC_PERSISTENT0_XTAL24MHZ_PWRUP; diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 3ce99e4db44d..661d2a49bce9 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -1695,7 +1695,7 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg) grp->changed_side = 2; break; } - /* Else, fall through */ + fallthrough; case MPCG_STATE_XID0IOWAIX: case MPCG_STATE_XID7INITW: case MPCG_STATE_XID7INITX: diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index ab316baa8284..85a1a4533cbe 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -357,7 +357,7 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int)) /*fsm_newstate(grp->fsm, MPCG_STATE_XID2INITW);*/ if (callback) grp->send_qllc_disc = 1; - /* Else, fall through */ + fallthrough; case MPCG_STATE_XID0IOWAIT: fsm_deltimer(&grp->timer); grp->outstanding_xid2 = 0; @@ -1470,7 +1470,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg) if ((fsm_getstate(rch->fsm) == CH_XID0_PENDING) && (fsm_getstate(wch->fsm) == CH_XID0_PENDING)) break; - /* Else, fall through */ + fallthrough; default: fsm_event(grp->fsm, MPCG_EVENT_INOP, dev); } @@ -2089,7 +2089,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev) grp->estconnfunc = NULL; break; } - /* Else, fall through */ + fallthrough; case MPCG_STATE_FLOWC: case MPCG_STATE_READY: grp->send_qllc_disc = 2; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index bba1b54b8aa3..6a7398251423 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -1071,7 +1071,7 @@ static void qeth_issue_next_read_cb(struct qeth_card *card, break; case -EIO: qeth_schedule_recovery(card); - /* fall through */ + fallthrough; default: qeth_clear_ipacmd_list(card); goto err_idx; @@ -2886,7 +2886,7 @@ void qeth_print_status_message(struct qeth_card *card) card->info.mcl_level[3]); break; } - /* fallthrough */ + fallthrough; case QETH_CARD_TYPE_IQD: if (IS_VM_NIC(card) || (card->info.mcl_level[0] & 0x80)) { card->info.mcl_level[0] = (char) _ebcasc[(__u8) diff --git a/drivers/s390/net/qeth_ethtool.c b/drivers/s390/net/qeth_ethtool.c index ebdc03210608..f870c5322bfe 100644 --- a/drivers/s390/net/qeth_ethtool.c +++ b/drivers/s390/net/qeth_ethtool.c @@ -356,7 +356,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, 10000baseT_Full); ethtool_link_ksettings_add_link_mode(cmd, advertising, 10000baseT_Full); - /* fall through */ + fallthrough; case SPEED_1000: ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); @@ -366,7 +366,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, 1000baseT_Half); ethtool_link_ksettings_add_link_mode(cmd, advertising, 1000baseT_Half); - /* fall through */ + fallthrough; case SPEED_100: ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); @@ -376,7 +376,7 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd, 100baseT_Half); ethtool_link_ksettings_add_link_mode(cmd, advertising, 100baseT_Half); - /* fall through */ + fallthrough; case SPEED_10: ethtool_link_ksettings_add_link_mode(cmd, supported, 10baseT_Full); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 8b342a88ff5c..3a94f6cad167 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -488,7 +488,7 @@ static void qeth_l2_rx_mode_work(struct work_struct *work) kfree(mac); break; } - /* fall through */ + fallthrough; default: /* for next call to set_rx_mode(): */ mac->disp_flag = QETH_DISP_ADDR_DELETE; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index fe44b0249e34..4d461960370d 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1235,7 +1235,7 @@ static void qeth_l3_rx_mode_work(struct work_struct *work) break; } addr->ref_counter = 1; - /* fall through */ + fallthrough; default: /* for next call to set_rx_mode(): */ addr->disp_flag = QETH_DISP_ADDR_DELETE; diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index 461b3babb601..84b57a8f86bf 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1832,7 +1832,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *) case REQUEST_SENSE: /* clear the internal sense magic */ SCp->cmnd[6] = 0; - /* fall through */ + fallthrough; default: /* OK, get it from the command */ switch(SCp->sc_data_direction) { diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c index bb49d83cadc7..ccb061ab0a0a 100644 --- a/drivers/scsi/BusLogic.c +++ b/drivers/scsi/BusLogic.c @@ -2635,7 +2635,7 @@ static int blogic_resultcode(struct blogic_adapter *adapter, case BLOGIC_BAD_CMD_PARAM: blogic_warn("BusLogic Driver Protocol Error 0x%02X\n", adapter, adapter_status); - /* fall through */ + fallthrough; case BLOGIC_DATA_UNDERRUN: case BLOGIC_DATA_OVERRUN: case BLOGIC_NOEXPECT_BUSFREE: diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 0f17bd51088a..24ace1824048 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -1034,11 +1034,14 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) temp6 >>= 1; switch (temp & 0x3) { case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ - temp6 |= 0x8000; /* Fall through */ + temp6 |= 0x8000; + fallthrough; case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ - temp5 |= 0x8000; /* Fall through */ + temp5 |= 0x8000; + fallthrough; case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ - temp2 |= 0x8000; /* Fall through */ + temp2 |= 0x8000; + fallthrough; case AUTO_RATE_00: /* Asynchronous */ break; } diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f2f7e6e76c07..d654a6cc4162 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1943,7 +1943,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) return; /* Reject message */ - /* Fall through */ + fallthrough; default: /* * If we get something weird that we aren't expecting, diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 769af4ca9ca9..fd6ae5c38086 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -2809,7 +2809,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) !(dev->raw_io_64) || ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) break; - /* fall through */ + fallthrough; case INQUIRY: case READ_CAPACITY: case TEST_UNIT_READY: @@ -2884,7 +2884,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) /* Issue FIB to tell Firmware to flush it's cache */ if ((aac_cache & 6) != 2) return aac_synchronize(scsicmd); - /* fall through */ + fallthrough; case INQUIRY: { struct inquiry_data inq_data; @@ -3240,7 +3240,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) SCSI_SENSE_BUFFERSIZE)); break; } - /* fall through */ + fallthrough; case RESERVE: case RELEASE: case REZERO_UNIT: @@ -3253,7 +3253,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case START_STOP: return aac_start_stop(scsicmd); - /* FALLTHRU */ + fallthrough; default: /* * Unhandled commands diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index adbdc3b7c7a7..383e74fea6ed 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1431,7 +1431,7 @@ retry_next: "enclosure services event"); scsi_device_set_state(device, SDEV_RUNNING); } - /* FALLTHRU */ + fallthrough; case CHANGE: if ((channel == CONTAINER_CHANNEL) && (!dev->fsa_dev[container].valid)) { diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 8588da0a0655..a3aee146537b 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -765,7 +765,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) !(aac->raw_io_64) || ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) break; - /* fall through */ + fallthrough; case INQUIRY: case READ_CAPACITY: /* diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index c912d29b8bdf..1c617c0d5899 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c @@ -2274,7 +2274,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) switch (scb->hscb->task_management) { case SIU_TASKMGMT_ABORT_TASK: tag = SCB_GET_TAG(scb); - /* fall through */ + fallthrough; case SIU_TASKMGMT_ABORT_TASK_SET: case SIU_TASKMGMT_CLEAR_TASK_SET: lun = scb->hscb->lun; @@ -2285,7 +2285,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat) break; case SIU_TASKMGMT_LUN_RESET: lun = scb->hscb->lun; - /* fall through */ + fallthrough; case SIU_TASKMGMT_TARGET_RESET: { struct ahd_devinfo devinfo; @@ -3791,7 +3791,7 @@ ahd_validate_width(struct ahd_softc *ahd, struct ahd_initiator_tinfo *tinfo, *bus_width = MSG_EXT_WDTR_BUS_16_BIT; break; } - /* FALLTHROUGH */ + fallthrough; case MSG_EXT_WDTR_BUS_8_BIT: *bus_width = MSG_EXT_WDTR_BUS_8_BIT; break; @@ -5104,7 +5104,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) break; case MSG_MESSAGE_REJECT: response = ahd_handle_msg_reject(ahd, devinfo); - /* FALLTHROUGH */ + fallthrough; case MSG_NOOP: done = MSGLOOP_MSGCOMPLETE; break; @@ -5454,7 +5454,7 @@ ahd_parse_msg(struct ahd_softc *ahd, struct ahd_devinfo *devinfo) ahd_name(ahd), ahd_inb(ahd, SCSISIGI)); #endif ahd->msg_flags |= MSG_FLAG_EXPECT_QASREJ_BUSFREE; - /* FALLTHROUGH */ + fallthrough; case MSG_TERM_IO_PROC: default: reject = TRUE; @@ -6117,17 +6117,17 @@ ahd_free(struct ahd_softc *ahd) default: case 5: ahd_shutdown(ahd); - /* FALLTHROUGH */ + fallthrough; case 4: ahd_dmamap_unload(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap); - /* FALLTHROUGH */ + fallthrough; case 3: ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo, ahd->shared_data_map.dmamap); ahd_dmamap_destroy(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap); - /* FALLTHROUGH */ + fallthrough; case 2: ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat); case 1: @@ -6513,7 +6513,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) } ahd_dma_tag_destroy(ahd, scb_data->sense_dmat); } - /* fall through */ + fallthrough; case 6: { struct map_node *sg_map; @@ -6528,7 +6528,7 @@ ahd_fini_scbdata(struct ahd_softc *ahd) } ahd_dma_tag_destroy(ahd, scb_data->sg_dmat); } - /* fall through */ + fallthrough; case 5: { struct map_node *hscb_map; @@ -7171,7 +7171,7 @@ ahd_init(struct ahd_softc *ahd) case FLX_CSTAT_OVER: case FLX_CSTAT_UNDER: warn_user++; - /* fall through */ + fallthrough; case FLX_CSTAT_INVALID: case FLX_CSTAT_OKAY: if (warn_user == 0 && bootverbose == 0) @@ -8175,12 +8175,12 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, if ((scb->flags & SCB_ACTIVE) == 0) printk("Inactive SCB in qinfifo\n"); ahd_done_with_status(ahd, scb, status); - /* FALLTHROUGH */ + fallthrough; case SEARCH_REMOVE: break; case SEARCH_PRINT: printk(" 0x%x", ahd->qinfifo[qinpos]); - /* FALLTHROUGH */ + fallthrough; case SEARCH_COUNT: ahd_qinfifo_requeue(ahd, prev_scb, scb); prev_scb = scb; @@ -8271,7 +8271,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, if ((mk_msg_scb->flags & SCB_ACTIVE) == 0) printk("Inactive SCB pending MK_MSG\n"); ahd_done_with_status(ahd, mk_msg_scb, status); - /* FALLTHROUGH */ + fallthrough; case SEARCH_REMOVE: { u_int tail_offset; @@ -8295,7 +8295,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel, } case SEARCH_PRINT: printk(" 0x%x", SCB_GET_TAG(scb)); - /* FALLTHROUGH */ + fallthrough; case SEARCH_COUNT: break; } @@ -8376,7 +8376,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, if ((scb->flags & SCB_ACTIVE) == 0) printk("Inactive SCB in Waiting List\n"); ahd_done_with_status(ahd, scb, status); - /* fall through */ + fallthrough; case SEARCH_REMOVE: ahd_rem_wscb(ahd, scbid, prev, next, tid); *list_tail = prev; @@ -8385,7 +8385,7 @@ ahd_search_scb_list(struct ahd_softc *ahd, int target, char channel, break; case SEARCH_PRINT: printk("0x%x ", scbid); - /* fall through */ + fallthrough; case SEARCH_COUNT: prev = scbid; break; @@ -9023,7 +9023,7 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb) case SCSI_STATUS_OK: printk("%s: Interrupted for status of 0???\n", ahd_name(ahd)); - /* FALLTHROUGH */ + fallthrough; default: ahd_done(ahd, scb); break; @@ -9512,7 +9512,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) fmt3_ins = &instr.format3; fmt3_ins->address = ahd_resolve_seqaddr(ahd, fmt3_ins->address); } - /* fall through */ + fallthrough; case AIC_OP_OR: case AIC_OP_AND: case AIC_OP_XOR: @@ -9523,7 +9523,7 @@ ahd_download_instr(struct ahd_softc *ahd, u_int instrptr, uint8_t *dconsts) fmt1_ins->immediate = dconsts[fmt1_ins->immediate]; } fmt1_ins->parity = 0; - /* fall through */ + fallthrough; case AIC_OP_ROL: { int i, count; diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index d019e3f2bb9b..7c321303969e 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2035,7 +2035,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) break; case CAM_AUTOSENSE_FAIL: new_status = DID_ERROR; - /* Fallthrough */ + fallthrough; case CAM_SCSI_STATUS_ERROR: scsi_status = ahd_cmd_get_scsi_status(cmd); diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 3d4df906fa4f..2231c4afa531 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c @@ -2404,7 +2404,7 @@ ahc_validate_width(struct ahc_softc *ahc, struct ahc_initiator_tinfo *tinfo, *bus_width = MSG_EXT_WDTR_BUS_16_BIT; break; } - /* FALLTHROUGH */ + fallthrough; case MSG_EXT_WDTR_BUS_8_BIT: *bus_width = MSG_EXT_WDTR_BUS_8_BIT; break; @@ -3599,7 +3599,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo) break; case MSG_MESSAGE_REJECT: response = ahc_handle_msg_reject(ahc, devinfo); - /* FALLTHROUGH */ + fallthrough; case MSG_NOOP: done = MSGLOOP_MSGCOMPLETE; break; @@ -4465,17 +4465,17 @@ ahc_free(struct ahc_softc *ahc) default: case 5: ahc_shutdown(ahc); - /* FALLTHROUGH */ + fallthrough; case 4: ahc_dmamap_unload(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); - /* FALLTHROUGH */ + fallthrough; case 3: ahc_dmamem_free(ahc, ahc->shared_data_dmat, ahc->qoutfifo, ahc->shared_data_dmamap); ahc_dmamap_destroy(ahc, ahc->shared_data_dmat, ahc->shared_data_dmamap); - /* FALLTHROUGH */ + fallthrough; case 2: ahc_dma_tag_destroy(ahc, ahc->shared_data_dmat); case 1: @@ -4893,30 +4893,30 @@ ahc_fini_scbdata(struct ahc_softc *ahc) } ahc_dma_tag_destroy(ahc, scb_data->sg_dmat); } - /* fall through */ + fallthrough; case 6: ahc_dmamap_unload(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); - /* fall through */ + fallthrough; case 5: ahc_dmamem_free(ahc, scb_data->sense_dmat, scb_data->sense, scb_data->sense_dmamap); ahc_dmamap_destroy(ahc, scb_data->sense_dmat, scb_data->sense_dmamap); - /* fall through */ + fallthrough; case 4: ahc_dma_tag_destroy(ahc, scb_data->sense_dmat); - /* fall through */ + fallthrough; case 3: ahc_dmamap_unload(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); - /* fall through */ + fallthrough; case 2: ahc_dmamem_free(ahc, scb_data->hscb_dmat, scb_data->hscbs, scb_data->hscb_dmamap); ahc_dmamap_destroy(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap); - /* fall through */ + fallthrough; case 1: ahc_dma_tag_destroy(ahc, scb_data->hscb_dmat); break; @@ -5981,7 +5981,7 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel, printk("Inactive SCB in Waiting List\n"); ahc_done(ahc, scb); } - /* fall through */ + fallthrough; case SEARCH_REMOVE: next = ahc_rem_wscb(ahc, next, prev); break; @@ -6987,7 +6987,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) address -= address_offset; fmt3_ins->address = address; } - /* fall through */ + fallthrough; case AIC_OP_OR: case AIC_OP_AND: case AIC_OP_XOR: @@ -7013,7 +7013,7 @@ ahc_download_instr(struct ahc_softc *ahc, u_int instrptr, uint8_t *dconsts) fmt1_ins->opcode = AIC_OP_AND; fmt1_ins->immediate = 0xff; } - /* fall through */ + fallthrough; case AIC_OP_ROL: if ((ahc->features & AHC_ULTRA2) != 0) { int i, count; diff --git a/drivers/scsi/aic94xx/aic94xx_scb.c b/drivers/scsi/aic94xx/aic94xx_scb.c index c264b4b56970..e2d880a5f391 100644 --- a/drivers/scsi/aic94xx/aic94xx_scb.c +++ b/drivers/scsi/aic94xx/aic94xx_scb.c @@ -706,11 +706,11 @@ static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd) switch (pd->max_sas_lrate) { case SAS_LINK_RATE_6_0_GBPS: *speed_mask &= ~SAS_SPEED_60_DIS; - /* fall through*/ + fallthrough; default: case SAS_LINK_RATE_3_0_GBPS: *speed_mask &= ~SAS_SPEED_30_DIS; - /* fall through*/ + fallthrough; case SAS_LINK_RATE_1_5_GBPS: *speed_mask &= ~SAS_SPEED_15_DIS; } @@ -718,7 +718,7 @@ static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd) switch (pd->min_sas_lrate) { case SAS_LINK_RATE_6_0_GBPS: *speed_mask |= SAS_SPEED_30_DIS; - /* fall through*/ + fallthrough; case SAS_LINK_RATE_3_0_GBPS: *speed_mask |= SAS_SPEED_15_DIS; default: @@ -730,7 +730,7 @@ static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd) switch (pd->max_sata_lrate) { case SAS_LINK_RATE_3_0_GBPS: *speed_mask &= ~SATA_SPEED_30_DIS; - /* fall through*/ + fallthrough; default: case SAS_LINK_RATE_1_5_GBPS: *speed_mask &= ~SATA_SPEED_15_DIS; @@ -789,7 +789,7 @@ void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc) /* link reset retries, this should be nominal */ control_phy->link_reset_retries = 10; - /* fall through */ + fallthrough; case RELEASE_SPINUP_HOLD: /* 0x02 */ /* decide the func_mask */ diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c index 1fcee65193a3..0eb6e206a2b4 100644 --- a/drivers/scsi/aic94xx/aic94xx_tmf.c +++ b/drivers/scsi/aic94xx/aic94xx_tmf.c @@ -490,7 +490,7 @@ int asd_abort_task(struct sas_task *task) switch (tcs.dl_opcode) { default: res = asd_clear_nexus(task); - /* fallthrough */ + fallthrough; case TC_NO_ERROR: break; /* The task hasn't been sent to the device xor diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index fa562a085600..ec895d0319f0 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -4470,7 +4470,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) case PCI_DEVICE_ID_ARECA_1202: case PCI_DEVICE_ID_ARECA_1210: raid6 = 0; - /*FALLTHRU*/ + fallthrough; case PCI_DEVICE_ID_ARECA_1120: case PCI_DEVICE_ID_ARECA_1130: case PCI_DEVICE_ID_ARECA_1160: diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index 6c68c2303638..2e687ce60753 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -603,7 +603,7 @@ static void fas216_handlesync(FAS216_Info *info, char *msg) msgqueue_flush(&info->scsi.msgs); msgqueue_addmsg(&info->scsi.msgs, 1, MESSAGE_REJECT); info->scsi.phase = PHASE_MSGOUT_EXPECT; - /* fall through */ + fallthrough; case async: dev->period = info->ifcfg.asyncperiod / 4; @@ -916,7 +916,7 @@ static void fas216_disconnect_intr(FAS216_Info *info) fas216_done(info, DID_ABORT); break; } - /* else, fall through */ + fallthrough; default: /* huh? */ printk(KERN_ERR "scsi%d.%c: unexpected disconnect in phase %s\n", @@ -1413,7 +1413,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_STATUS, PHASE_DATAOUT): /* Data Out -> Status */ case STATE(STAT_STATUS, PHASE_DATAIN): /* Data In -> Status */ fas216_stoptransfer(info); - /* fall through */ + fallthrough; case STATE(STAT_STATUS, PHASE_SELSTEPS):/* Sel w/ steps -> Status */ case STATE(STAT_STATUS, PHASE_MSGOUT): /* Message Out -> Status */ @@ -1426,7 +1426,7 @@ static void fas216_busservice_intr(FAS216_Info *info, unsigned int stat, unsigne case STATE(STAT_MESGIN, PHASE_DATAOUT): /* Data Out -> Message In */ case STATE(STAT_MESGIN, PHASE_DATAIN): /* Data In -> Message In */ fas216_stoptransfer(info); - /* fall through */ + fallthrough; case STATE(STAT_MESGIN, PHASE_COMMAND): /* Command -> Message In */ case STATE(STAT_MESGIN, PHASE_SELSTEPS):/* Sel w/ steps -> Message In */ @@ -1581,7 +1581,7 @@ static void fas216_funcdone_intr(FAS216_Info *info, unsigned int stat, unsigned fas216_message(info); break; } - /* else, fall through */ + fallthrough; default: fas216_log(info, 0, "internal phase %s for function done?" @@ -1964,7 +1964,7 @@ static void fas216_kick(FAS216_Info *info) switch (where_from) { case TYPE_QUEUE: fas216_allocate_tag(info, SCpnt); - /* fall through */ + fallthrough; case TYPE_OTHER: fas216_start_command(info, SCpnt); break; diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index 93da6344424d..a13c203ef7a9 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -677,7 +677,7 @@ int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, case ISCSI_PARAM_MAX_XMIT_DLENGTH: if (conn->max_xmit_dlength > 65536) conn->max_xmit_dlength = 65536; - /* fall through */ + fallthrough; default: return 0; } diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 8dc2e0824ad7..5c3513a4b450 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1532,7 +1532,7 @@ beiscsi_hdl_get_handle(struct beiscsi_conn *beiscsi_conn, break; case UNSOL_DATA_DIGEST_ERROR_NOTIFY: error = 1; - /* fall through */ + fallthrough; case UNSOL_DATA_NOTIFY: pasync_handle = pasync_ctx->async_entry[ci].data; break; diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c index 29f99561dfc3..38d1c453074d 100644 --- a/drivers/scsi/bfa/bfa_fcpim.c +++ b/drivers/scsi/bfa/bfa_fcpim.c @@ -2572,7 +2572,7 @@ bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) case FCP_IODIR_RW: bfa_stats(itnim, input_reqs); bfa_stats(itnim, output_reqs); - /* fall through */ + fallthrough; default: bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_fn_lpu(ioim->bfa)); } @@ -2807,7 +2807,7 @@ bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) case BFI_IOIM_STS_TIMEDOUT: bfa_stats(ioim->itnim, iocomp_timedout); - /* fall through */ + fallthrough; case BFI_IOIM_STS_ABORTED: rsp->io_status = BFI_IOIM_STS_ABORTED; bfa_stats(ioim->itnim, iocomp_aborted); @@ -3203,7 +3203,7 @@ bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, switch (event) { case BFA_TSKIM_SM_DONE: bfa_reqq_wcancel(&tskim->reqq_wait); - /* fall through */ + fallthrough; case BFA_TSKIM_SM_QRESUME: bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup); bfa_tskim_send_abort(tskim); diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index 297a77f5806c..3486e402bfc1 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -6422,7 +6422,7 @@ bfa_fcs_vport_sm_logo_for_stop(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); - /* fall through */ + fallthrough; case BFA_FCS_VPORT_SM_RSP_OK: case BFA_FCS_VPORT_SM_RSP_ERROR: @@ -6448,7 +6448,7 @@ bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, switch (event) { case BFA_FCS_VPORT_SM_OFFLINE: bfa_sm_send_event(vport->lps, BFA_LPS_SM_OFFLINE); - /* fall through */ + fallthrough; case BFA_FCS_VPORT_SM_RSP_OK: case BFA_FCS_VPORT_SM_RSP_ERROR: diff --git a/drivers/scsi/bfa/bfa_fcs_rport.c b/drivers/scsi/bfa/bfa_fcs_rport.c index 143c35bd668c..c21aa37b8adb 100644 --- a/drivers/scsi/bfa/bfa_fcs_rport.c +++ b/drivers/scsi/bfa/bfa_fcs_rport.c @@ -419,13 +419,13 @@ bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); - /* fall through */ + fallthrough; case RPSM_EVENT_PRLO_RCVD: if (rport->prlo == BFA_TRUE) bfa_fcs_rport_send_prlo_acc(rport); bfa_fcxp_discard(rport->fcxp); - /* fall through */ + fallthrough; case RPSM_EVENT_FAILED: if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { rport->plogi_retries++; @@ -856,7 +856,7 @@ bfa_fcs_rport_sm_adisc_online(struct bfa_fcs_rport_s *rport, * At least go offline when a PLOGI is received. */ bfa_fcxp_discard(rport->fcxp); - /* fall through */ + fallthrough; case RPSM_EVENT_FAILED: case RPSM_EVENT_ADDRESS_CHANGE: @@ -1042,7 +1042,7 @@ bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); - /* fall through */ + fallthrough; case RPSM_EVENT_PRLO_RCVD: if (rport->prlo == BFA_TRUE) bfa_fcs_rport_send_prlo_acc(rport); @@ -1131,7 +1131,7 @@ bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, bfa_fcs_rport_send_plogiacc(rport, NULL); break; } - /* fall through */ + fallthrough; case RPSM_EVENT_ADDRESS_CHANGE: if (!bfa_fcs_lport_is_online(rport->port)) { @@ -1288,7 +1288,7 @@ bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); - /* fall through */ + fallthrough; case RPSM_EVENT_PRLO_RCVD: if (rport->prlo == BFA_TRUE) bfa_fcs_rport_send_prlo_acc(rport); @@ -1332,7 +1332,7 @@ bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, case RPSM_EVENT_LOGO_RCVD: bfa_fcs_rport_send_logo_acc(rport); - /* fall through */ + fallthrough; case RPSM_EVENT_PRLO_RCVD: if (rport->prlo == BFA_TRUE) bfa_fcs_rport_send_prlo_acc(rport); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index dd5821dfcac2..325ad8a592bb 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -969,7 +969,7 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_INITFAIL: bfa_iocpf_timer_stop(ioc); - /* fall through */ + fallthrough; case IOCPF_E_TIMEOUT: writel(1, ioc->ioc_regs.ioc_sem_reg); @@ -1045,7 +1045,7 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf_s *iocpf, enum iocpf_event event) case IOCPF_E_FAIL: bfa_iocpf_timer_stop(ioc); - /* fall through */ + fallthrough; case IOCPF_E_TIMEOUT: bfa_ioc_set_cur_ioc_fwstate(ioc, BFI_IOC_FAIL); @@ -5988,7 +5988,7 @@ bfa_dconf_sm_final_sync(struct bfa_dconf_mod_s *dconf, case BFA_DCONF_SM_IOCDISABLE: case BFA_DCONF_SM_FLASH_COMP: bfa_timer_stop(&dconf->timer); - /* fall through */ + fallthrough; case BFA_DCONF_SM_TIMEOUT: bfa_sm_set_state(dconf, bfa_dconf_sm_uninit); bfa_fsm_send_event(&dconf->bfa->iocfc, IOCFC_E_DCONF_DONE); diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 1e266c1ef793..11c0c3e6f014 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -6397,7 +6397,7 @@ bfa_dport_sm_starting(struct bfa_dport_s *dport, enum bfa_dport_sm_event event) dport->test_state = BFA_DPORT_ST_INP; bfa_dport_result_start(dport, BFA_DPORT_OPMODE_MANU); } - /* fall thru */ + fallthrough; case BFA_DPORT_SM_REQFAIL: bfa_sm_set_state(dport, bfa_dport_sm_enabled); diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index e72d7bb7f4f4..08992095ce7a 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1404,7 +1404,6 @@ void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[], break; case FCOE_KCQE_OPCODE_FCOE_ERROR: - /* fall thru */ default: printk(KERN_ERR PFX "unknown opcode 0x%x\n", kcqe->op_code); diff --git a/drivers/scsi/csiostor/csio_hw.c b/drivers/scsi/csiostor/csio_hw.c index 98d4d39aaa57..7fa20609d5e7 100644 --- a/drivers/scsi/csiostor/csio_hw.c +++ b/drivers/scsi/csiostor/csio_hw.c @@ -2939,7 +2939,7 @@ csio_hws_quiescing(struct csio_hw *hw, enum csio_hw_ev evt) case CSIO_HWE_FW_DLOAD: csio_set_state(&hw->sm, csio_hws_resetting); /* Download firmware */ - /* Fall through */ + fallthrough; case CSIO_HWE_HBA_RESET: csio_set_state(&hw->sm, csio_hws_resetting); diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c index 61cf54208451..dc98f51f466f 100644 --- a/drivers/scsi/csiostor/csio_lnode.c +++ b/drivers/scsi/csiostor/csio_lnode.c @@ -1187,7 +1187,6 @@ csio_lns_online(struct csio_lnode *ln, enum csio_ln_ev evt) break; case CSIO_LNE_LINK_DOWN: - /* Fall through */ case CSIO_LNE_DOWN_LINK: csio_set_state(&ln->sm, csio_lns_uninit); if (csio_is_phys_ln(ln)) { diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c index 0ca695110f54..9010cb6045dc 100644 --- a/drivers/scsi/csiostor/csio_wr.c +++ b/drivers/scsi/csiostor/csio_wr.c @@ -808,7 +808,7 @@ csio_wr_destroy_queues(struct csio_hw *hw, bool cmd) csio_q_eqid(hw, i) = CSIO_MAX_QID; } - /* fall through */ + fallthrough; case CSIO_INGRESS: if (csio_q_iqid(hw, i) != CSIO_MAX_QID) { csio_wr_cleanup_iq_ftr(hw, i); diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index 2b48954b6b1e..37d99357120f 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -643,7 +643,7 @@ static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason, int *need_rst) { switch (abort_reason) { - case CPL_ERR_BAD_SYN: /* fall through */ + case CPL_ERR_BAD_SYN: case CPL_ERR_CONN_RESET: return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET; case CPL_ERR_XMIT_TIMEDOUT: diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index 4e82c14cb795..2c3491528d42 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -1133,7 +1133,7 @@ static int abort_status_to_errno(struct cxgbi_sock *csk, int abort_reason, int *need_rst) { switch (abort_reason) { - case CPL_ERR_BAD_SYN: /* fall through */ + case CPL_ERR_BAD_SYN: case CPL_ERR_CONN_RESET: return csk->state > CTP_ESTABLISHED ? -EPIPE : -ECONNRESET; diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 94250ebe9e80..e72440d919d2 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -748,16 +748,16 @@ static void term_intr(struct cxlflash_cfg *cfg, enum undo_level level, /* SISL_MSI_ASYNC_ERROR is setup only for the primary HWQ */ if (index == PRIMARY_HWQ) cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 3, hwq); - /* fall through */ + fallthrough; case UNMAP_TWO: cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 2, hwq); - /* fall through */ + fallthrough; case UNMAP_ONE: cfg->ops->unmap_afu_irq(hwq->ctx_cookie, 1, hwq); - /* fall through */ + fallthrough; case FREE_IRQ: cfg->ops->free_afu_irqs(hwq->ctx_cookie); - /* fall through */ + fallthrough; case UNDO_NOOP: /* No action required */ break; @@ -971,18 +971,18 @@ static void cxlflash_remove(struct pci_dev *pdev) switch (cfg->init_state) { case INIT_STATE_CDEV: cxlflash_release_chrdev(cfg); - /* fall through */ + fallthrough; case INIT_STATE_SCSI: cxlflash_term_local_luns(cfg); scsi_remove_host(cfg->host); - /* fall through */ + fallthrough; case INIT_STATE_AFU: term_afu(cfg); - /* fall through */ + fallthrough; case INIT_STATE_PCI: cfg->ops->destroy_afu(cfg->afu_cookie); pci_disable_device(pdev); - /* fall through */ + fallthrough; case INIT_STATE_NONE: free_mem(cfg); scsi_host_put(cfg->host); @@ -2355,11 +2355,11 @@ retry: cxlflash_schedule_async_reset(cfg); break; } - /* fall through - to retry */ + fallthrough; /* to retry */ case -EAGAIN: if (++nretry < 2) goto retry; - /* fall through - to exit */ + fallthrough; /* to exit */ default: break; } @@ -2533,12 +2533,12 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) cfg->state = STATE_NORMAL; wake_up_all(&cfg->reset_waitq); ssleep(1); - /* fall through */ + fallthrough; case STATE_RESET: wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); if (cfg->state == STATE_NORMAL) break; - /* fall through */ + fallthrough; default: rc = FAILED; break; @@ -3019,7 +3019,7 @@ retry: wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); if (cfg->state == STATE_NORMAL) goto retry; - /* else, fall through */ + fallthrough; default: /* Ideally should not happen */ dev_err(dev, "%s: Device is not ready, state=%d\n", @@ -3531,7 +3531,7 @@ static long cxlflash_chr_ioctl(struct file *file, unsigned int cmd, if (likely(do_ioctl)) break; - /* fall through */ + fallthrough; default: rc = -EINVAL; goto out; diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index 593669ac3669..5dddf67dfa24 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c @@ -375,14 +375,13 @@ retry: switch (sshdr.sense_key) { case NO_SENSE: case RECOVERED_ERROR: - /* fall through */ case NOT_READY: result &= ~SAM_STAT_CHECK_CONDITION; break; case UNIT_ATTENTION: switch (sshdr.asc) { case 0x29: /* Power on Reset or Device Reset */ - /* fall through */ + fallthrough; case 0x2A: /* Device capacity changed */ case 0x3F: /* Report LUNs changed */ /* Retry the command once more */ @@ -1791,13 +1790,12 @@ static int process_sense(struct scsi_device *sdev, switch (sshdr.sense_key) { case NO_SENSE: case RECOVERED_ERROR: - /* fall through */ case NOT_READY: break; case UNIT_ATTENTION: switch (sshdr.asc) { case 0x29: /* Power on Reset or Device Reset */ - /* fall through */ + fallthrough; case 0x2A: /* Device settings/capacity changed */ rc = read_cap16(sdev, lli); if (rc) { @@ -2157,7 +2155,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, unsigned int cmd, void __user *arg) if (unlikely(rc)) goto cxlflash_ioctl_exit; - /* fall through */ + fallthrough; case DK_CXLFLASH_MANAGE_LUN: known_ioctl = true; @@ -2168,7 +2166,7 @@ int cxlflash_ioctl(struct scsi_device *sdev, unsigned int cmd, void __user *arg) if (likely(do_ioctl)) break; - /* fall through */ + fallthrough; default: rc = -EINVAL; goto cxlflash_ioctl_exit; diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 8acd4bb9fefb..4a3f7831a2d6 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c @@ -60,7 +60,7 @@ static int tur_done(struct scsi_device *sdev, struct hp_sw_dh_data *h, ret = SCSI_DH_OK; break; } - /* Fallthrough */ + fallthrough; default: sdev_printk(KERN_WARNING, sdev, "%s: sending tur failed, sense %x/%x/%x\n", @@ -147,7 +147,7 @@ retry: rc = SCSI_DH_RETRY; break; } - /* fall through */ + fallthrough; default: sdev_printk(KERN_WARNING, sdev, "%s: sending start_stop_unit failed, " diff --git a/drivers/scsi/esas2r/esas2r_flash.c b/drivers/scsi/esas2r/esas2r_flash.c index b02ac389e6c6..429d64299fe9 100644 --- a/drivers/scsi/esas2r/esas2r_flash.c +++ b/drivers/scsi/esas2r/esas2r_flash.c @@ -1500,7 +1500,7 @@ bool esas2r_fm_api(struct esas2r_adapter *a, struct esas2r_flash_img *fi, return complete_fmapi_req(a, rq, FI_STAT_SUCCESS); } - /* fall through */ + fallthrough; case FI_ACT_UP: /* Upload the components */ default: diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c index eb7d139ffc00..09c5c24bf391 100644 --- a/drivers/scsi/esas2r/esas2r_init.c +++ b/drivers/scsi/esas2r/esas2r_init.c @@ -1236,7 +1236,7 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, a->init_msg = ESAS2R_INIT_MSG_GET_INIT; break; } - /* fall through */ + fallthrough; case ESAS2R_INIT_MSG_GET_INIT: if (msg == ESAS2R_INIT_MSG_GET_INIT) { @@ -1250,7 +1250,7 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a, esas2r_hdebug("FAILED"); } } - /* fall through */ + fallthrough; default: rq->req_stat = RS_SUCCESS; diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 89afa31e33cb..43a1fd11df5e 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -307,7 +307,7 @@ static void esp_reset_esp(struct esp *esp) case FASHME: esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB); - /* fallthrough... */ + fallthrough; case FAS236: case PCSCSI: @@ -1741,7 +1741,7 @@ again: case ESP_EVENT_DATA_IN: write = 1; - /* fallthru */ + fallthrough; case ESP_EVENT_DATA_OUT: { struct esp_cmd_entry *ent = esp->active_cmd; diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 1409c7687853..5ea426effa60 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -450,10 +450,10 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) switch (fip->mode) { default: LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode); - /* fall-through */ + fallthrough; case FIP_MODE_AUTO: LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n"); - /* fall-through */ + fallthrough; case FIP_MODE_FABRIC: case FIP_MODE_NON_FIP: mutex_unlock(&fip->ctlr_mutex); @@ -773,7 +773,7 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, fc_fcoe_set_mac(mac, fh->fh_d_id); fip->update_mac(lport, mac); } - /* fall through */ + fallthrough; case ELS_LS_RJT: op = fr_encaps(fp); if (op) @@ -2439,7 +2439,7 @@ static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip, frport->enode_mac, 0); break; } - /* fall through */ + fallthrough; case FIP_ST_VNMP_START: LIBFCOE_FIP_DBG(fip, "vn_probe_req: " "restart VN2VN negotiation\n"); diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 2cc676e3df6a..29e4cdcade72 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -340,7 +340,7 @@ static int generic_NCR5380_init_one(struct scsi_host_template *tpnt, break; case BOARD_DTC3181E: hostdata->io_width = 2; /* 16-bit PDMA */ - /* fall through */ + fallthrough; case BOARD_NCR53C400A: case BOARD_HP_C2502: hostdata->c400_ctl_status = 9; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 11caa4b0d797..d9d21d23372e 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -1144,7 +1144,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func, hisi_hba->hw->get_events(hisi_hba, phy_no); break; } - /* fallthru */ + fallthrough; case PHY_FUNC_RELEASE_SPINUP_HOLD: default: return -EOPNOTSUPP; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 91794a50b31f..48d5da59262b 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4697,7 +4697,7 @@ static int fixup_ioaccel_cdb(u8 *cdb, int *cdb_len) case WRITE_6: case WRITE_12: is_write = 1; - /* fall through */ + fallthrough; case READ_6: case READ_12: if (*cdb_len == 6) { @@ -5147,7 +5147,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, switch (cmd->cmnd[0]) { case WRITE_6: is_write = 1; - /* fall through */ + fallthrough; case READ_6: first_block = (((cmd->cmnd[1] & 0x1F) << 16) | (cmd->cmnd[2] << 8) | @@ -5158,7 +5158,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, break; case WRITE_10: is_write = 1; - /* fall through */ + fallthrough; case READ_10: first_block = (((u64) cmd->cmnd[2]) << 24) | @@ -5171,7 +5171,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, break; case WRITE_12: is_write = 1; - /* fall through */ + fallthrough; case READ_12: first_block = (((u64) cmd->cmnd[2]) << 24) | @@ -5186,7 +5186,7 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, break; case WRITE_16: is_write = 1; - /* fall through */ + fallthrough; case READ_16: first_block = (((u64) cmd->cmnd[2]) << 56) | diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 77f4d37d5bd6..ea7c8930592d 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1866,7 +1866,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) port_id = (bsg_request->rqst_data.h_els.port_id[0] << 16) | (bsg_request->rqst_data.h_els.port_id[1] << 8) | bsg_request->rqst_data.h_els.port_id[2]; - /* fall through */ + fallthrough; case FC_BSG_RPT_ELS: fc_flags = IBMVFC_FC_ELS; break; @@ -1875,7 +1875,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job) port_id = (bsg_request->rqst_data.h_ct.port_id[0] << 16) | (bsg_request->rqst_data.h_ct.port_id[1] << 8) | bsg_request->rqst_data.h_ct.port_id[2]; - /* fall through */ + fallthrough; case FC_BSG_RPT_CT: fc_flags = IBMVFC_FC_CT_IU; break; @@ -4122,7 +4122,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) return; case IBMVFC_MAD_CRQ_ERROR: ibmvfc_retry_host_init(vhost); - /* fall through */ + fallthrough; case IBMVFC_MAD_DRIVER_FAILED: ibmvfc_free_event(evt); return; diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index d9e94e81da01..cc3908c2d2f9 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -1581,7 +1581,7 @@ static long ibmvscsis_adapter_info(struct scsi_info *vscsi, case H_PERMISSION: if (connection_broken(vscsi)) flag_bits = (RESPONSE_Q_DOWN | CLIENT_FAILED); - /* Fall through */ + fallthrough; default: dev_err(&vscsi->dev, "adapter_info: h_copy_rdma to client failed, rc %ld\n", rc); @@ -2489,10 +2489,10 @@ static long ibmvscsis_ping_response(struct scsi_info *vscsi) break; case H_CLOSED: vscsi->flags |= CLIENT_FAILED; - /* Fall through */ + fallthrough; case H_DROPPED: vscsi->flags |= RESPONSE_Q_DOWN; - /* Fall through */ + fallthrough; case H_REMOTE_PARM: dev_err(&vscsi->dev, "ping_response: h_send_crq failed, rc %ld\n", rc); diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 1459b1467027..862d35a098cf 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -801,7 +801,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) case 1: /* Phase 1 - Connected */ imm_connect(dev, CONNECT_EPP_MAYBE); cmd->SCp.phase++; - /* fall through */ + fallthrough; case 2: /* Phase 2 - We are now talking to the scsi bus */ if (!imm_select(dev, scmd_id(cmd))) { @@ -809,7 +809,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) return 0; } cmd->SCp.phase++; - /* fall through */ + fallthrough; case 3: /* Phase 3 - Ready to accept a command */ w_ctr(ppb, 0x0c); @@ -819,7 +819,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) if (!imm_send_command(cmd)) return 0; cmd->SCp.phase++; - /* fall through */ + fallthrough; case 4: /* Phase 4 - Setup scatter/gather buffers */ if (scsi_bufflen(cmd)) { @@ -835,7 +835,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) cmd->SCp.phase++; if (cmd->SCp.this_residual & 0x01) cmd->SCp.this_residual++; - /* fall through */ + fallthrough; case 5: /* Phase 5 - Pre-Data transfer stage */ /* Spin lock for BUSY */ @@ -852,7 +852,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) if (imm_negotiate(dev)) return 0; cmd->SCp.phase++; - /* fall through */ + fallthrough; case 6: /* Phase 6 - Data transfer stage */ /* Spin lock for BUSY */ @@ -868,7 +868,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) return 1; } cmd->SCp.phase++; - /* fall through */ + fallthrough; case 7: /* Phase 7 - Post data transfer stage */ if ((dev->dp) && (dev->rd)) { @@ -880,7 +880,7 @@ static int imm_engine(imm_struct *dev, struct scsi_cmnd *cmd) } } cmd->SCp.phase++; - /* fall through */ + fallthrough; case 8: /* Phase 8 - Read status/message */ /* Check for data overrun */ diff --git a/drivers/scsi/isci/phy.c b/drivers/scsi/isci/phy.c index 7f9b3f20e5e4..4cacb800b530 100644 --- a/drivers/scsi/isci/phy.c +++ b/drivers/scsi/isci/phy.c @@ -778,7 +778,7 @@ enum sci_status sci_phy_event_handler(struct isci_phy *iphy, u32 event_code) break; case SCU_EVENT_LINK_FAILURE: scu_link_layer_set_txcomsas_timeout(iphy, SCU_SAS_LINK_LAYER_TXCOMSAS_NEGTIME_DEFAULT); - /* fall through */ + fallthrough; case SCU_EVENT_HARD_RESET_RECEIVED: /* Start the oob/sn state machine over again */ sci_change_state(&iphy->sm, SCI_PHY_STARTING); diff --git a/drivers/scsi/isci/remote_device.c b/drivers/scsi/isci/remote_device.c index cd1e4b4d95bb..c3f540b55689 100644 --- a/drivers/scsi/isci/remote_device.c +++ b/drivers/scsi/isci/remote_device.c @@ -310,7 +310,7 @@ static void isci_remote_device_not_ready(struct isci_host *ihost, /* Kill all outstanding requests for the device. */ sci_remote_device_terminate_requests(idev); - /* Fall through - into the default case... */ + fallthrough; /* into the default case */ default: clear_bit(IDEV_IO_READY, &idev->flags); break; @@ -593,7 +593,7 @@ enum sci_status sci_remote_device_event_handler(struct isci_remote_device *idev, break; } - /* fall through - and treat as unhandled... */ + fallthrough; /* and treat as unhandled */ default: dev_dbg(scirdev_to_dev(idev), "%s: device: %p event code: %x: %s\n", diff --git a/drivers/scsi/isci/remote_node_context.c b/drivers/scsi/isci/remote_node_context.c index 474a43460963..68333f523b35 100644 --- a/drivers/scsi/isci/remote_node_context.c +++ b/drivers/scsi/isci/remote_node_context.c @@ -225,7 +225,7 @@ static void sci_remote_node_context_continue_state_transitions(struct sci_remote case RNC_DEST_READY: case RNC_DEST_SUSPENDED_RESUME: rnc->destination_state = RNC_DEST_READY; - /* Fall through... */ + fallthrough; case RNC_DEST_FINAL: sci_remote_node_context_resume(rnc, rnc->user_callback, rnc->user_cookie); @@ -601,9 +601,9 @@ enum sci_status sci_remote_node_context_suspend( __func__, sci_rnc); return SCI_FAILURE_INVALID_STATE; } - /* Fall through - and handle like SCI_RNC_POSTING */ + fallthrough; /* and handle like SCI_RNC_POSTING */ case SCI_RNC_RESUMING: - /* Fall through - and handle like SCI_RNC_POSTING */ + fallthrough; /* and handle like SCI_RNC_POSTING */ case SCI_RNC_POSTING: /* Set the destination state to AWAIT - this signals the * entry into the SCI_RNC_READY state that a suspension diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 6561a07db189..6e0817941fa7 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -894,7 +894,7 @@ sci_io_request_terminate(struct isci_request *ireq) * and don't wait for the task response. */ sci_change_state(&ireq->sm, SCI_REQ_ABORTING); - /* Fall through - and handle like ABORTING... */ + fallthrough; /* and handle like ABORTING */ case SCI_REQ_ABORTING: if (!isci_remote_device_is_safe_to_abort(ireq->target_device)) set_bit(IREQ_PENDING_ABORT, &ireq->flags); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 16eb3b60ed58..96a2952cf626 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -2108,7 +2108,7 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) switch (op) { case ELS_LS_RJT: FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ\n"); - /* fall through */ + fallthrough; case ELS_LS_ACC: goto cleanup; default: @@ -2622,7 +2622,7 @@ void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp) case FC_EOF_T: if (f_ctl & FC_FC_END_SEQ) skb_trim(fp_skb(fp), fr_len(fp) - FC_FC_FILL(f_ctl)); - /* fall through */ + fallthrough; case FC_EOF_N: if (fh->fh_type == FC_TYPE_BLS) fc_exch_recv_bls(ema->mp, fp); diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index e11d4f002bd4..7cfeb6886237 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -752,7 +752,7 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) brp = fc_frame_payload_get(fp, sizeof(*brp)); if (brp && brp->br_reason == FC_BA_RJT_LOG_ERR) break; - /* fall thru */ + fallthrough; default: /* * we will let the command timeout @@ -1536,7 +1536,7 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) "device %x invalid REC reject %d/%d\n", fsp->rport->port_id, rjt->er_reason, rjt->er_explan); - /* fall through */ + fallthrough; case ELS_RJT_UNSUP: FC_FCP_DBG(fsp, "device does not support REC\n"); rpriv = fsp->rport->dd_data; @@ -1668,7 +1668,7 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) FC_FCP_DBG(fsp, "REC %p fid %6.6x error unexpected error %d\n", fsp, fsp->rport->port_id, error); fsp->status_code = FC_CMD_PLOGO; - /* fall through */ + fallthrough; case -FC_EX_TIMEOUT: /* @@ -1830,7 +1830,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) break; case -FC_EX_CLOSED: /* e.g., link failure */ FC_FCP_DBG(fsp, "SRR error, exchange closed\n"); - /* fall through */ + fallthrough; default: fc_fcp_retry_cmd(fsp, FC_ERROR); break; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index b84dbc316df1..6557fda85c5c 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1578,7 +1578,7 @@ static void fc_lport_timeout(struct work_struct *work) case LPORT_ST_DPRT: FC_LPORT_DBG(lport, "Skipping lport state %s to SCR\n", fc_lport_state(lport)); - /* fall thru */ + fallthrough; case LPORT_ST_SCR: fc_lport_enter_scr(lport); break; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 18663a82865f..a60b228d13f1 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1723,7 +1723,7 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, struct fc_frame *fp) kref_put(&rdata->kref, fc_rport_destroy); goto busy; } - /* fall through */ + fallthrough; default: FC_RPORT_DBG(rdata, "Reject ELS 0x%02x while in state %s\n", diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 49c8a1818baf..1e9c3171fa9f 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -248,7 +248,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) hdr_lun = scsilun_to_int(&tmf->lun); if (hdr_lun != task->sc->device->lun) return 0; - /* fall through */ + fallthrough; case ISCSI_TM_FUNC_TARGET_WARM_RESET: /* * Fail all SCSI cmd PDUs @@ -1674,7 +1674,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) sc->result = DID_NO_CONNECT << 16; break; } - /* fall through */ + fallthrough; case ISCSI_STATE_IN_RECOVERY: reason = FAILURE_SESSION_IN_RECOVERY; sc->result = DID_IMM_RETRY << 16; @@ -2239,7 +2239,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) "progress\n"); goto success; } - /* fall through */ + fallthrough; default: conn->tmf_state = TMF_INITIAL; goto failed; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 6ef93c7af954..37e5d4e48c2f 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -772,7 +772,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) iscsi_tcp_data_recv_prep(tcp_conn); return 0; } - /* fall through */ + fallthrough; case ISCSI_OP_LOGOUT_RSP: case ISCSI_OP_NOOP_IN: case ISCSI_OP_SCSI_TMFUNC_RSP: diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 1b93332daa6b..6a521ba7a616 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -324,7 +324,7 @@ static int smp_ata_check_ready(struct ata_link *link) case SAS_END_DEVICE: if (ex_phy->attached_sata_dev) return sas_ata_clear_pending(dev, ex_phy); - /* fall through */ + fallthrough; default: return -ENODEV; } diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c index daf951b0b3f5..cd7c7d269f6f 100644 --- a/drivers/scsi/libsas/sas_discover.c +++ b/drivers/scsi/libsas/sas_discover.c @@ -108,7 +108,7 @@ static int sas_get_port_device(struct asd_sas_port *port) rphy = NULL; break; } - /* fall through */ + fallthrough; case SAS_END_DEVICE: rphy = sas_end_device_alloc(port->port); break; diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index b7d1b1ea185d..8d6bcc19359f 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -1096,7 +1096,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) } else memcpy(dev->port->disc.fanout_sas_addr, ex_phy->attached_sas_addr, SAS_ADDR_SIZE); - /* fallthrough */ + fallthrough; case SAS_EDGE_EXPANDER_DEVICE: child = sas_ex_discover_expander(dev, phy_id); break; diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 9e0975e55c27..1bf939818c98 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -622,7 +622,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * sas_scsi_clear_queue_lu(work_q, cmd); goto Again; } - /* fallthrough */ + fallthrough; case TASK_IS_NOT_AT_LU: case TASK_ABORT_FAILED: pr_notice("task 0x%p is not at LU: I_T recover\n", diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ef2015fad2d5..d0141a23a833 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -3202,7 +3202,7 @@ port_out: case SLI_MGMT_GHAT: case SLI_MGMT_GRPL: rsp_size = FC_MAX_NS_RSP; - /* fall through */ + fallthrough; case SLI_MGMT_DHBA: case SLI_MGMT_DHAT: pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID; @@ -3215,7 +3215,7 @@ port_out: case SLI_MGMT_GPAT: case SLI_MGMT_GPAS: rsp_size = FC_MAX_NS_RSP; - /* fall through */ + fallthrough; case SLI_MGMT_DPRT: case SLI_MGMT_DPA: pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 48dc63f22cca..6aae61d6ee16 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -9134,7 +9134,7 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_nlp_put(ndlp); return; } - /* fall through */ + fallthrough; default: /* Try to recover from this error */ if (phba->sli_rev == LPFC_SLI_REV4) diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 142a02114479..d32c7e7ab09d 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -4728,15 +4728,14 @@ lpfc_check_sli_ndlp(struct lpfc_hba *phba, case CMD_GEN_REQUEST64_CR: if (iocb->context_un.ndlp == ndlp) return 1; - /* fall through */ + fallthrough; case CMD_ELS_REQUEST64_CR: if (icmd->un.elsreq64.remoteID == ndlp->nlp_DID) return 1; - /* fall through */ + fallthrough; case CMD_XMIT_ELS_RSP64_CX: if (iocb->context1 == (uint8_t *) ndlp) return 1; - /* fall through */ } } else if (pring->ringno == LPFC_FCP_RING) { /* Skip match check if waiting to relogin to FCP target */ @@ -6055,7 +6054,7 @@ restart_disc: case LPFC_LINK_UP: lpfc_issue_clear_la(phba, vport); - /* fall through */ + fallthrough; case LPFC_LINK_UNKNOWN: case LPFC_WARM_START: case LPFC_INIT_START: diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index cad53d19cb25..92d6e7b98770 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -464,7 +464,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, case NLP_STE_NPR_NODE: if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) break; - /* fall through */ + fallthrough; case NLP_STE_REG_LOGIN_ISSUE: case NLP_STE_PRLI_ISSUE: case NLP_STE_UNMAPPED_NODE: diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index e5be334d6a11..0c39ed50998c 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -1225,7 +1225,7 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn, lpfc_ncmd, nCmd, lpfc_ncmd->cur_iocbq.sli4_xritag, bf_get(lpfc_wcqe_c_xb, wcqe)); - /* fall through */ + fallthrough; default: out_err: lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR, diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 5e802c8b22a9..983eeb0e3d07 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -1093,7 +1093,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, break; } - /* fall through */ + fallthrough; case SCSI_PROT_WRITE_INSERT: /* * For WRITE_INSERT, force the error @@ -1213,7 +1213,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, rc = BG_ERR_TGT | BG_ERR_CHECK; break; } - /* fall through */ + fallthrough; case SCSI_PROT_WRITE_INSERT: /* * For WRITE_INSERT, force the @@ -1295,7 +1295,7 @@ lpfc_bg_err_inject(struct lpfc_hba *phba, struct scsi_cmnd *sc, switch (op) { case SCSI_PROT_WRITE_PASS: rc = BG_ERR_CHECK; - /* fall through */ + fallthrough; case SCSI_PROT_WRITE_INSERT: /* @@ -3980,7 +3980,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, lpfc_cmd->cur_iocbq.sli4_lxritag, 0, 0); } - /* fall through */ + fallthrough; default: cmd->result = DID_ERROR << 16; break; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4cd7ded656b7..e158cd77d387 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -9339,7 +9339,7 @@ __lpfc_sli_issue_iocb_s3(struct lpfc_hba *phba, uint32_t ring_number, */ if (piocb->iocb_cmpl) piocb->iocb_cmpl = NULL; - /*FALLTHROUGH*/ + fallthrough; case CMD_CREATE_XRI_CR: case CMD_CLOSE_XRI_CN: case CMD_CLOSE_XRI_CX: @@ -9653,7 +9653,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq, cmnd = CMD_XMIT_SEQUENCE64_CR; if (phba->link_flag & LS_LOOPBACK_MODE) bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1); - /* fall through */ + fallthrough; case CMD_XMIT_SEQUENCE64_CR: /* word3 iocb=io_tag32 wqe=reserved */ wqe->xmit_sequence.rsvd3 = 0; @@ -13630,7 +13630,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) case FC_STATUS_RQ_BUF_LEN_EXCEEDED: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "2537 Receive Frame Truncated!!\n"); - /* fall through */ + fallthrough; case FC_STATUS_RQ_SUCCESS: spin_lock_irqsave(&phba->hbalock, iflags); lpfc_sli4_rq_release(hrq, drq); @@ -13678,7 +13678,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe) atomic_read(&tgtp->rcv_fcp_cmd_out), atomic_read(&tgtp->xmt_fcp_release)); } - /* fallthrough */ + fallthrough; case FC_STATUS_INSUFF_BUF_NEED_BUF: hrq->RQ_no_posted_buf++; @@ -14162,7 +14162,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq, case FC_STATUS_RQ_BUF_LEN_EXCEEDED: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "6126 Receive Frame Truncated!!\n"); - /* fall through */ + fallthrough; case FC_STATUS_RQ_SUCCESS: spin_lock_irqsave(&phba->hbalock, iflags); lpfc_sli4_rq_release(hrq, drq); @@ -14209,7 +14209,7 @@ drop: atomic_read(&tgtp->rcv_fcp_cmd_out), atomic_read(&tgtp->xmt_fcp_release)); } - /* fallthrough */ + fallthrough; case FC_STATUS_INSUFF_BUF_NEED_BUF: hrq->RQ_no_posted_buf++; @@ -15096,7 +15096,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest count */ + fallthrough; /* otherwise default to smallest count */ case 256: bf_set(lpfc_eq_context_count, &eq_create->u.request.context, LPFC_EQ_CNT_256); @@ -15238,7 +15238,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, LPFC_CQ_CNT_WORD7); break; } - /* fall through */ + fallthrough; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "0361 Unsupported CQ count: " @@ -15249,7 +15249,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq, status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest count */ + fallthrough; /* otherwise default to smallest count */ case 256: bf_set(lpfc_cq_context_count, &cq_create->u.request.context, LPFC_CQ_CNT_256); @@ -15417,7 +15417,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, LPFC_CQ_CNT_WORD7); break; } - /* fall through */ + fallthrough; default: lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT, "3118 Bad CQ count. (%d)\n", @@ -15426,7 +15426,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp, status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest */ + fallthrough; /* otherwise default to smallest */ case 256: bf_set(lpfc_mbx_cq_create_set_cqe_cnt, &cq_set->u.request, LPFC_CQ_CNT_256); @@ -15702,7 +15702,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq, status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest count */ + fallthrough; /* otherwise default to smallest count */ case 16: bf_set(lpfc_mq_context_ring_size, &mq_create_ext->u.request.context, @@ -16123,7 +16123,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest count */ + fallthrough; /* otherwise default to smallest count */ case 512: bf_set(lpfc_rq_context_rqe_count, &rq_create->u.request.context, @@ -16260,7 +16260,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq, status = -EINVAL; goto out; } - /* fall through - otherwise default to smallest count */ + fallthrough; /* otherwise default to smallest count */ case 512: bf_set(lpfc_rq_context_rqe_count, &rq_create->u.request.context, diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 0484ee52ae80..ac406049e7c8 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -491,9 +491,9 @@ mega_get_ldrv_num(adapter_t *adapter, struct scsi_cmnd *cmd, int channel) if (adapter->support_random_del && adapter->read_ldidmap ) switch (cmd->cmnd[0]) { - case READ_6: /* fall through */ - case WRITE_6: /* fall through */ - case READ_10: /* fall through */ + case READ_6: + case WRITE_6: + case READ_10: case WRITE_10: ldrv_num += 0x80; } @@ -852,7 +852,7 @@ mega_build_cmd(adapter_t *adapter, struct scsi_cmnd *cmd, int *busy) return scb; #if MEGA_HAVE_CLUSTERING - case RESERVE: /* Fall through */ + case RESERVE: case RELEASE: /* @@ -987,7 +987,7 @@ mega_prepare_passthru(adapter_t *adapter, scb_t *scb, struct scsi_cmnd *cmd, adapter->flag |= (1L << cmd->device->channel); } - /* Fall through */ + fallthrough; default: pthru->numsgelements = mega_build_sglist(adapter, scb, &pthru->dataxferaddr, &pthru->dataxferlen); @@ -1050,7 +1050,7 @@ mega_prepare_extpassthru(adapter_t *adapter, scb_t *scb, adapter->flag |= (1L << cmd->device->channel); } - /* Fall through */ + fallthrough; default: epthru->numsgelements = mega_build_sglist(adapter, scb, &epthru->dataxferaddr, &epthru->dataxferlen); diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 19469a2c0ea3..4a27ac869f2e 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c @@ -1581,7 +1581,7 @@ megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy) return NULL; } - /* Fall through */ + fallthrough; case READ_CAPACITY: /* diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 861f7140f52e..2b7e7b5f38ed 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3522,7 +3522,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, megasas_complete_int_cmd(instance, cmd); break; } - /* fall through */ + fallthrough; case MFI_CMD_LD_READ: case MFI_CMD_LD_WRITE: diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 0824410f78f8..883cccb59c2d 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3534,7 +3534,7 @@ complete_cmd_fusion(struct megasas_instance *instance, u32 MSIxIndex, atomic_dec(&lbinfo->scsi_pending_cmds[cmd_fusion->pd_r1_lb]); cmd_fusion->scmd->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; } - /* Fall through - and complete IO */ + fallthrough; /* and complete IO */ case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */ atomic_dec(&instance->fw_outstanding); if (cmd_fusion->r1_alt_dev_handle == MR_DEVHANDLE_INVALID) { diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index fd1d03064079..0a9f4e44ab2c 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1457,7 +1457,7 @@ static void cmd_complete(struct mesh_state *ms) /* huh? we expected a phase mismatch */ ms->n_msgin = 0; ms->msgphase = msg_in; - /* fall through */ + fallthrough; case msg_in: /* should have some message bytes in fifo */ diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 1d64524cd863..5730f32496b6 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -4681,7 +4681,7 @@ _base_update_ioc_page1_inlinewith_perf_mode(struct MPT3SAS_ADAPTER *ioc) ioc_info(ioc, "performance mode: balanced\n"); return; } - /* Fall through */ + fallthrough; case MPT_PERF_MODE_LATENCY: /* * Enable interrupt coalescing on all reply queues diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c index 43260306668c..7c119b904834 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c +++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c @@ -1002,7 +1002,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, } /* drop to default case for posting the request */ } - /* fall through */ + fallthrough; default: ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, data_in_dma, data_in_sz); diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 08fc4b381056..2e2756d8a49b 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -5470,7 +5470,7 @@ _scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: scsi_set_resid(scmd, 0); - /* fall through */ + fallthrough; case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: case MPI2_IOCSTATUS_SUCCESS: scmd->result = (DID_OK << 16) | scsi_status; @@ -6480,7 +6480,7 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, if (!test_bit(handle, ioc->pend_os_device_add)) break; - /* fall through */ + fallthrough; case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: @@ -7208,7 +7208,7 @@ _scsih_pcie_topology_change_event(struct MPT3SAS_ADAPTER *ioc, event_data->PortEntry[i].PortStatus &= 0xF0; event_data->PortEntry[i].PortStatus |= MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED; - /* fall through */ + fallthrough; case MPI26_EVENT_PCIE_TOPO_PS_DEV_ADDED: if (ioc->shost_recovery) break; @@ -10653,7 +10653,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) case MPI26_MFGPAGE_DEVID_CFG_SEC_3916: dev_info(&pdev->dev, "HBA is in Configurable Secure mode\n"); - /* fall through */ + fallthrough; case MPI26_MFGPAGE_DEVID_HARD_SEC_3816: case MPI26_MFGPAGE_DEVID_HARD_SEC_3916: ioc->is_aero_ioc = ioc->is_gen35_ioc = 1; diff --git a/drivers/scsi/myrb.c b/drivers/scsi/myrb.c index d4bd31a75b9d..b2869c5dd7fb 100644 --- a/drivers/scsi/myrb.c +++ b/drivers/scsi/myrb.c @@ -650,7 +650,7 @@ static void myrb_bgi_control(struct myrb_hba *cb) if (sdev && cb->bgi_status.status == MYRB_BGI_INPROGRESS) sdev_printk(KERN_INFO, sdev, "Background Initialization Aborted\n"); - /* Fallthrough */ + fallthrough; case MYRB_STATUS_NO_BGI_INPROGRESS: cb->bgi_status.status = MYRB_BGI_INVALID; break; @@ -1528,7 +1528,7 @@ static int myrb_ldev_queuecommand(struct Scsi_Host *shost, scmd->scsi_done(scmd); return 0; } - /* fall through */ + fallthrough; case WRITE_6: lba = (((scmd->cmnd[1] & 0x1F) << 16) | (scmd->cmnd[2] << 8) | @@ -1545,7 +1545,7 @@ static int myrb_ldev_queuecommand(struct Scsi_Host *shost, scmd->scsi_done(scmd); return 0; } - /* fall through */ + fallthrough; case WRITE_10: case VERIFY: /* 0x2F */ case WRITE_VERIFY: /* 0x2E */ @@ -1562,7 +1562,7 @@ static int myrb_ldev_queuecommand(struct Scsi_Host *shost, scmd->scsi_done(scmd); return 0; } - /* fall through */ + fallthrough; case WRITE_12: case VERIFY_12: /* 0xAF */ case WRITE_VERIFY_12: /* 0xAE */ diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index f88adab3f913..03d70138ad58 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -3640,7 +3640,7 @@ ncr_script_copy_and_bind (struct ncb *np, ncrcmd *src, ncrcmd *dst, int len) new = old; break; } - /* fall through */ + fallthrough; default: panic("ncr_script_copy_and_bind: weird relocation %x\n", old); break; @@ -3910,14 +3910,14 @@ static void __init ncr_prepare_setting(struct ncb *np) np->scsi_mode = SMODE_HVD; break; } - /* fall through */ + fallthrough; case 3: /* SYMBIOS controllers report HVD through GPIO3 */ if (INB(nc_gpreg) & 0x08) break; - /* fall through */ + fallthrough; case 2: /* Set HVD unconditionally */ np->scsi_mode = SMODE_HVD; - /* fall through */ + fallthrough; case 1: /* Trust previous settings for HVD */ if (np->sv_stest2 & 0x20) np->scsi_mode = SMODE_HVD; @@ -4296,7 +4296,7 @@ static int ncr_queue_command (struct ncb *np, struct scsi_cmnd *cmd) break; cp->phys.header.wgoalp = cpu_to_scr(goalp); cp->phys.header.wlastp = cpu_to_scr(lastp); - /* fall through */ + fallthrough; case DMA_FROM_DEVICE: goalp = NCB_SCRIPT_PHYS (np, data_in2) + 8; if (segments <= MAX_SCATTERL) @@ -6717,7 +6717,7 @@ void ncr_int_sir (struct ncb *np) OUTL_DSP (scr_to_cpu(tp->lp[0]->jump_ccb[0])); return; } - /* fall through */ + fallthrough; case SIR_RESEL_BAD_TARGET: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_LUN: /* Will send a TARGET RESET message */ case SIR_RESEL_BAD_I_T_L_Q: /* Will send an ABORT TAG message */ @@ -6825,7 +6825,7 @@ void ncr_int_sir (struct ncb *np) */ OUTB (HS_PRT, HS_BUSY); - /* fall through */ + fallthrough; case SIR_NEGO_PROTO: /*------------------------------------------------------- diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 8655ff1249bb..bc5a623519e7 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1113,7 +1113,7 @@ static irqreturn_t nspintr(int irq, void *dev_id) nsp_scsi_done(tmpSC); return IRQ_HANDLED; } - /* fall thru */ + fallthrough; default: if ((irq_status & (IRQSTATUS_SCSI | IRQSTATUS_FIFO)) == 0) { return IRQ_HANDLED; diff --git a/drivers/scsi/ppa.c b/drivers/scsi/ppa.c index 0ae800c5b739..aa41f7ac91cb 100644 --- a/drivers/scsi/ppa.c +++ b/drivers/scsi/ppa.c @@ -717,7 +717,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) } cmd->SCp.phase++; } - /* fall through */ + fallthrough; case 2: /* Phase 2 - We are now talking to the scsi bus */ if (!ppa_select(dev, scmd_id(cmd))) { @@ -725,7 +725,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) return 0; } cmd->SCp.phase++; - /* fall through */ + fallthrough; case 3: /* Phase 3 - Ready to accept a command */ w_ctr(ppb, 0x0c); @@ -735,7 +735,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) if (!ppa_send_command(cmd)) return 0; cmd->SCp.phase++; - /* fall through */ + fallthrough; case 4: /* Phase 4 - Setup scatter/gather buffers */ if (scsi_bufflen(cmd)) { @@ -749,7 +749,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) } cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1; cmd->SCp.phase++; - /* fall through */ + fallthrough; case 5: /* Phase 5 - Data transfer stage */ w_ctr(ppb, 0x0c); @@ -762,7 +762,7 @@ static int ppa_engine(ppa_struct *dev, struct scsi_cmnd *cmd) if (retv == 0) return 1; cmd->SCp.phase++; - /* fall through */ + fallthrough; case 6: /* Phase 6 - Read status/message */ cmd->result = DID_OK << 16; diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index de9fd7f688d0..b569fd6e96d6 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -177,7 +177,7 @@ qla2x00_chk_ms_status(scsi_qla_host_t *vha, ms_iocb_entry_t *ms_pkt, break; case CS_TIMEOUT: rval = QLA_FUNCTION_TIMEOUT; - /* fall through */ + fallthrough; default: ql_dbg(ql_dbg_disc, vha, 0x2033, "%s failed, completion status (%x) on port_id: " diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 57a2d76aa691..507919d4ab36 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -857,7 +857,7 @@ static void qla24xx_handle_gnl_done_event(scsi_qla_host_t *vha, fcport); break; } - /* fall through */ + fallthrough; default: if (fcport_is_smaller(fcport)) { /* local adapter is bigger */ diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index e3d2dea0b057..0954fa41911c 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -2874,7 +2874,7 @@ static void qla2x00_els_dcmd2_sp_done(srb_t *sp, int res) &vha->dpc_flags); qla2xxx_wake_dpc(vha); } - /* fall through */ + fallthrough; default: ql_dbg(ql_dbg_disc, vha, 0x20eb, "%s %8phC cmd error fw_status 0x%x 0x%x 0x%x\n", diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index ab5275dbc338..25e0a1684763 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1580,11 +1580,11 @@ global_port_update: qla2xxx_wake_dpc(vha); } } - /* fall through */ + fallthrough; case MBA_IDC_COMPLETE: if (ha->notify_lb_portup_comp && !vha->vp_idx) complete(&ha->lb_portup_comp); - /* Fallthru */ + fallthrough; case MBA_IDC_TIME_EXT: if (IS_QLA81XX(vha->hw) || IS_QLA8031(vha->hw) || IS_QLA8044(ha)) @@ -2188,7 +2188,7 @@ qla24xx_logio_entry(scsi_qla_host_t *vha, struct req_que *req, set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags); qla2xxx_wake_dpc(vha); } - /* fall through */ + fallthrough; default: data[0] = MBS_COMMAND_ERROR; break; @@ -2368,7 +2368,7 @@ static void qla24xx_nvme_iocb_entry(scsi_qla_host_t *vha, struct req_que *req, case CS_PORT_UNAVAILABLE: case CS_PORT_LOGGED_OUT: fcport->nvme_flag |= NVME_FLAG_RESETTING; - /* fall through */ + fallthrough; case CS_ABORTED: case CS_PORT_BUSY: fd->transferred_length = 0; @@ -3485,7 +3485,7 @@ process_err: } else { qlt_24xx_process_atio_queue(vha, 1); } - /* fall through */ + fallthrough; case ABTS_RESP_24XX: case CTIO_TYPE7: case CTIO_CRC2: diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index e161c05d7d82..411b8a9ff393 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -2457,7 +2457,7 @@ qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf, sec_mask = 0x10000; break; } - /* Fall through... */ + fallthrough; case 0x1f: /* Atmel flash. */ /* 512k sector size. */ @@ -2466,7 +2466,7 @@ qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf, sec_mask = 0x80000000; break; } - /* Fall through... */ + fallthrough; case 0x01: /* AMD flash. */ if (flash_id == 0x38 || flash_id == 0x40 || @@ -2499,7 +2499,7 @@ qla2x00_write_optrom_data(struct scsi_qla_host *vha, void *buf, sec_mask = 0x1e000; break; } - /* fall through */ + fallthrough; default: /* Default to 16 kb sector size. */ rest_addr = 0x3fff; diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 90289162dbd4..2d445bdb2129 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -442,7 +442,7 @@ void qlt_response_pkt_all_vps(struct scsi_qla_host *vha, ql_dbg(ql_dbg_tgt, vha, 0xe073, "qla_target(%d):%s: CRC2 Response pkt\n", vha->vp_idx, __func__); - /* fall through */ + fallthrough; case CTIO_TYPE7: { struct ctio7_from_24xx *entry = (struct ctio7_from_24xx *)pkt; @@ -4423,7 +4423,7 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun, case QLA_TGT_CLEAR_TS: case QLA_TGT_ABORT_TS: abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id); - /* fall through */ + fallthrough; case QLA_TGT_CLEAR_ACA: h = qlt_find_qphint(vha, mcmd->unpacked_lun); mcmd->qpair = h->qpair; @@ -5057,7 +5057,7 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha, res = 1; break; } - /* fall through */ + fallthrough; case ELS_LOGO: case ELS_PRLO: spin_lock_irqsave(&ha->tgt.sess_lock, flags); diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index bab87e47b238..676778cbc550 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -2907,7 +2907,7 @@ static int qla4xxx_session_get_param(struct iscsi_cls_session *cls_sess, chap_tbl.secret_len); } } - /* fall through */ + fallthrough; default: return iscsi_session_get_param(cls_sess, param, buf); } diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 3790e8b70bba..48ff7d88af86 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -200,15 +200,15 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f /* Write mailbox command registers. */ switch (mbox_param[param[0]] >> 4) { case 6: sbus_writew(param[5], qpti->qregs + MBOX5); - /* Fall through */ + fallthrough; case 5: sbus_writew(param[4], qpti->qregs + MBOX4); - /* Fall through */ + fallthrough; case 4: sbus_writew(param[3], qpti->qregs + MBOX3); - /* Fall through */ + fallthrough; case 3: sbus_writew(param[2], qpti->qregs + MBOX2); - /* Fall through */ + fallthrough; case 2: sbus_writew(param[1], qpti->qregs + MBOX1); - /* Fall through */ + fallthrough; case 1: sbus_writew(param[0], qpti->qregs + MBOX0); } @@ -259,15 +259,15 @@ static int qlogicpti_mbox_command(struct qlogicpti *qpti, u_short param[], int f /* Read back output parameters. */ switch (mbox_param[param[0]] & 0xf) { case 6: param[5] = sbus_readw(qpti->qregs + MBOX5); - /* Fall through */ + fallthrough; case 5: param[4] = sbus_readw(qpti->qregs + MBOX4); - /* Fall through */ + fallthrough; case 4: param[3] = sbus_readw(qpti->qregs + MBOX3); - /* Fall through */ + fallthrough; case 3: param[2] = sbus_readw(qpti->qregs + MBOX2); - /* Fall through */ + fallthrough; case 2: param[1] = sbus_readw(qpti->qregs + MBOX1); - /* Fall through */ + fallthrough; case 1: param[0] = sbus_readw(qpti->qregs + MBOX0); } diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 927b1e641842..7d3571a2bd89 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -599,7 +599,7 @@ int scsi_check_sense(struct scsi_cmnd *scmd) set_host_byte(scmd, DID_ALLOC_FAILURE); return SUCCESS; } - /* FALLTHROUGH */ + fallthrough; case COPY_ABORTED: case VOLUME_OVERFLOW: case MISCOMPARE: @@ -621,7 +621,7 @@ int scsi_check_sense(struct scsi_cmnd *scmd) return ADD_TO_MLQUEUE; else set_host_byte(scmd, DID_TARGET_FAILURE); - /* FALLTHROUGH */ + fallthrough; case ILLEGAL_REQUEST: if (sshdr.asc == 0x20 || /* Invalid command operation code */ @@ -734,7 +734,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) switch (status_byte(scmd->result)) { case GOOD: scsi_handle_queue_ramp_up(scmd->device); - /* FALLTHROUGH */ + fallthrough; case COMMAND_TERMINATED: return SUCCESS; case CHECK_CONDITION: @@ -755,7 +755,7 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd) return FAILED; case QUEUE_FULL: scsi_handle_queue_full(scmd->device); - /* fall through */ + fallthrough; case BUSY: return NEEDS_RETRY; default: @@ -1302,7 +1302,7 @@ retry_tur: case NEEDS_RETRY: if (retry_cnt--) goto retry_tur; - /*FALLTHRU*/ + fallthrough; case SUCCESS: return 0; default: @@ -1739,7 +1739,7 @@ int scsi_noretry_cmd(struct scsi_cmnd *scmd) if (msg_byte(scmd->result) == COMMAND_COMPLETE && status_byte(scmd->result) == RESERVATION_CONFLICT) return 0; - /* fall through */ + fallthrough; case DID_SOFT_ERROR: return (scmd->request->cmd_flags & REQ_FAILFAST_DRIVER); } @@ -1810,7 +1810,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) set_host_byte(scmd, DID_TIME_OUT); return SUCCESS; } - /* FALLTHROUGH */ + fallthrough; case DID_NO_CONNECT: case DID_BAD_TARGET: /* @@ -1854,7 +1854,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) * lower down */ break; - /* fallthrough */ + fallthrough; case DID_BUS_BUSY: case DID_PARITY: goto maybe_retry; @@ -1892,7 +1892,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) * the case of trying to send too many commands to a * tagged queueing device. */ - /* FALLTHROUGH */ + fallthrough; case BUSY: /* * device can't talk to us at the moment. Should only @@ -1905,7 +1905,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) if (scmd->cmnd[0] == REPORT_LUNS) scmd->device->sdev_target->expecting_lun_change = 0; scsi_handle_queue_ramp_up(scmd->device); - /* FALLTHROUGH */ + fallthrough; case COMMAND_TERMINATED: return SUCCESS; case TASK_ABORTED: @@ -2376,22 +2376,22 @@ scsi_ioctl_reset(struct scsi_device *dev, int __user *arg) rtn = scsi_try_bus_device_reset(scmd); if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; - /* FALLTHROUGH */ + fallthrough; case SG_SCSI_RESET_TARGET: rtn = scsi_try_target_reset(scmd); if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; - /* FALLTHROUGH */ + fallthrough; case SG_SCSI_RESET_BUS: rtn = scsi_try_bus_reset(scmd); if (rtn == SUCCESS || (val & SG_SCSI_RESET_NO_ESCALATE)) break; - /* FALLTHROUGH */ + fallthrough; case SG_SCSI_RESET_HOST: rtn = scsi_try_host_reset(scmd); if (rtn == SUCCESS) break; - /* FALLTHROUGH */ + fallthrough; default: rtn = FAILED; break; diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index 45d04b7b2643..14872c9dc78c 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -117,14 +117,14 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable) break; - /* FALLTHROUGH */ + fallthrough; case UNIT_ATTENTION: if (sdev->removable) { sdev->changed = 1; result = 0; /* This is no longer considered an error */ break; } - /* FALLTHROUGH -- for non-removable media */ + fallthrough; /* for non-removable media */ default: sdev_printk(KERN_INFO, sdev, "ioctl_internal_command return code = %x\n", diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 7c6dd6f75190..7affaaf8b98e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -795,7 +795,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) } if (!scsi_end_request(req, blk_stat, blk_rq_err_bytes(req))) return; - /*FALLTHRU*/ + fallthrough; case ACTION_REPREP: scsi_io_completion_reprep(cmd, q); break; diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index bd38c8cea56e..ca1e6cf6a38e 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -516,7 +516,7 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, break; case BMIC_SENSE_DIAG_OPTIONS: cdb_length = 0; - /* fall through */ + fallthrough; case BMIC_IDENTIFY_CONTROLLER: case BMIC_IDENTIFY_PHYSICAL_DEVICE: case BMIC_SENSE_SUBSYSTEM_INFORMATION: @@ -527,7 +527,7 @@ static int pqi_build_raid_path_request(struct pqi_ctrl_info *ctrl_info, break; case BMIC_SET_DIAG_OPTIONS: cdb_length = 0; - /* fall through */ + fallthrough; case BMIC_WRITE_HOST_WELLNESS: request->data_direction = SOP_WRITE_FLAG; cdb[0] = BMIC_WRITE; @@ -2324,7 +2324,7 @@ static int pqi_raid_bypass_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, switch (scmd->cmnd[0]) { case WRITE_6: is_write = true; - /* fall through */ + fallthrough; case READ_6: first_block = (u64)(((scmd->cmnd[1] & 0x1f) << 16) | (scmd->cmnd[2] << 8) | scmd->cmnd[3]); @@ -2334,21 +2334,21 @@ static int pqi_raid_bypass_submit_scsi_cmd(struct pqi_ctrl_info *ctrl_info, break; case WRITE_10: is_write = true; - /* fall through */ + fallthrough; case READ_10: first_block = (u64)get_unaligned_be32(&scmd->cmnd[2]); block_cnt = (u32)get_unaligned_be16(&scmd->cmnd[7]); break; case WRITE_12: is_write = true; - /* fall through */ + fallthrough; case READ_12: first_block = (u64)get_unaligned_be32(&scmd->cmnd[2]); block_cnt = get_unaligned_be32(&scmd->cmnd[6]); break; case WRITE_16: is_write = true; - /* fall through */ + fallthrough; case READ_16: first_block = get_unaligned_be64(&scmd->cmnd[2]); block_cnt = get_unaligned_be32(&scmd->cmnd[10]); @@ -2948,7 +2948,7 @@ static unsigned int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info, case PQI_RESPONSE_IU_AIO_PATH_IO_SUCCESS: if (io_request->scmd) io_request->scmd->result = 0; - /* fall through */ + fallthrough; case PQI_RESPONSE_IU_GENERAL_MANAGEMENT: break; case PQI_RESPONSE_IU_VENDOR_GENERAL: @@ -3115,12 +3115,11 @@ static void pqi_process_soft_reset(struct pqi_ctrl_info *ctrl_info, switch (reset_status) { case RESET_INITIATE_DRIVER: - /* fall through */ case RESET_TIMEDOUT: dev_info(&ctrl_info->pci_dev->dev, "resetting controller %u\n", ctrl_info->ctrl_id); sis_soft_reset(ctrl_info); - /* fall through */ + fallthrough; case RESET_INITIATE_FIRMWARE: rc = pqi_ofa_ctrl_restart(ctrl_info); pqi_ofa_free_host_buffer(ctrl_info); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0c4aa4665a2f..3b3a53c6a0de 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -877,10 +877,10 @@ static void get_sectorsize(struct scsi_cd *cd) case 2340: case 2352: sector_size = 2048; - /* fall through */ + fallthrough; case 2048: cd->capacity *= 4; - /* fall through */ + fallthrough; case 512: break; default: diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 87fbc0ea350b..e2e5356a997d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -339,14 +339,14 @@ static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s) switch (sense[0] & 0x7f) { case 0x71: s->deferred = 1; - /* fall through */ + fallthrough; case 0x70: s->fixed_format = 1; s->flags = sense[2] & 0xe0; break; case 0x73: s->deferred = 1; - /* fall through */ + fallthrough; case 0x72: s->fixed_format = 0; ucp = scsi_sense_desc_find(sense, SCSI_SENSE_BUFFERSIZE, 4); @@ -2723,7 +2723,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon switch (cmd_in) { case MTFSFM: chg_eof = 0; /* Changed from the FSF after this */ - /* fall through */ + fallthrough; case MTFSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ @@ -2738,7 +2738,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon break; case MTBSFM: chg_eof = 0; /* Changed from the FSF after this */ - /* fall through */ + fallthrough; case MTBSF: cmd[0] = SPACE; cmd[1] = 0x01; /* Space FileMarks */ diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 701b842296f0..2e3fbc2fae97 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -397,12 +397,12 @@ static int sun3scsi_dma_finish(int write_flag) case CSR_LEFT_3: *vaddr = (dregs->bpack_lo & 0xff00) >> 8; vaddr--; - /* Fall through */ + fallthrough; case CSR_LEFT_2: *vaddr = (dregs->bpack_hi & 0x00ff); vaddr--; - /* Fall through */ + fallthrough; case CSR_LEFT_1: *vaddr = (dregs->bpack_hi & 0xff00) >> 8; diff --git a/drivers/scsi/sym53c8xx_2/sym_fw.c b/drivers/scsi/sym53c8xx_2/sym_fw.c index 6d7651a7847e..c6db61b61de3 100644 --- a/drivers/scsi/sym53c8xx_2/sym_fw.c +++ b/drivers/scsi/sym53c8xx_2/sym_fw.c @@ -523,7 +523,7 @@ void sym_fw_bind_script(struct sym_hcb *np, u32 *start, int len) new = old; break; } - /* fall through */ + fallthrough; default: new = 0; panic("sym_fw_bind_script: " diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 8410117d5aa4..cc11daa1222b 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -3059,7 +3059,7 @@ static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, struct sym_ccb sym_print_addr(cp->cmd, "%s\n", s_status == S_BUSY ? "BUSY" : "QUEUE FULL\n"); } - /* fall through */ + fallthrough; default: /* S_INT, S_INT_COND_MET, S_CONFLICT */ sym_complete_error (np, cp); break; @@ -4620,7 +4620,7 @@ static void sym_int_sir(struct sym_hcb *np) * Negotiation failed. * Target does not want answer message. */ - /* fall through */ + fallthrough; case SIR_NEGO_PROTO: sym_nego_default(np, tp, cp); goto out; diff --git a/drivers/scsi/sym53c8xx_2/sym_nvram.c b/drivers/scsi/sym53c8xx_2/sym_nvram.c index d37e2a69136a..e13d5351f155 100644 --- a/drivers/scsi/sym53c8xx_2/sym_nvram.c +++ b/drivers/scsi/sym53c8xx_2/sym_nvram.c @@ -695,7 +695,7 @@ static int sym_read_Tekram_nvram (struct sym_device *np, Tekram_nvram *nvram) data, len); if (!x) break; - /* fall through */ + fallthrough; default: x = sym_read_T93C46_nvram(np, nvram); break; diff --git a/drivers/scsi/ufs/ufs_bsg.c b/drivers/scsi/ufs/ufs_bsg.c index bcfbbd0d5c45..5b2bc1a6f922 100644 --- a/drivers/scsi/ufs/ufs_bsg.c +++ b/drivers/scsi/ufs/ufs_bsg.c @@ -110,7 +110,7 @@ static int ufs_bsg_request(struct bsg_job *job) goto out; } - /* fall through */ + fallthrough; case UPIU_TRANSACTION_NOP_OUT: case UPIU_TRANSACTION_TASK_REQ: ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req, diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index da199fa7a3e0..1d157ff58d81 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1612,7 +1612,7 @@ start: * currently running. Hence, fall through to cancel gating * work and to enable clocks. */ - /* fallthrough */ + fallthrough; case CLKS_OFF: ufshcd_scsi_block_requests(hba); hba->clk_gating.state = REQ_CLKS_ON; @@ -1624,7 +1624,7 @@ start: * fall through to check if we should wait for this * work to be done or not. */ - /* fallthrough */ + fallthrough; case REQ_CLKS_ON: if (async) { rc = -EAGAIN; @@ -4737,7 +4737,7 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status) switch (scsi_status) { case SAM_STAT_CHECK_CONDITION: ufshcd_copy_sense_data(lrbp); - /* fallthrough */ + fallthrough; case SAM_STAT_GOOD: result |= DID_OK << 16 | COMMAND_COMPLETE << 8 | @@ -6277,7 +6277,7 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba, switch (msgcode) { case UPIU_TRANSACTION_NOP_OUT: cmd_type = DEV_CMD_TYPE_NOP; - /* fall through */ + fallthrough; case UPIU_TRANSACTION_QUERY_REQ: ufshcd_hold(hba, false); mutex_lock(&hba->dev_cmd.lock); diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index ca1c39b6f631..3b1803432090 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -148,7 +148,7 @@ static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) default: scmd_printk(KERN_WARNING, sc, "Unknown response %d", resp->response); - /* fall through */ + fallthrough; case VIRTIO_SCSI_S_FAILURE: set_host_byte(sc, DID_ERROR); break; diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 8dbb4db6831a..081f54ab7d86 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -607,7 +607,7 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, case BTSTAT_TAGREJECT: case BTSTAT_BADMSG: cmd->result = (DRIVER_INVALID << 24); - /* fall through */ + fallthrough; case BTSTAT_HAHARDWARE: case BTSTAT_INVPHASE: diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index f81046f0e68a..87dafbc942d3 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -1854,7 +1854,7 @@ round_4(unsigned int x) case 1: --x; break; case 2: ++x; - /* fall through */ + fallthrough; case 3: ++x; } return x; diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c index f0068e96a177..259fc248d06c 100644 --- a/drivers/scsi/xen-scsifront.c +++ b/drivers/scsi/xen-scsifront.c @@ -1111,7 +1111,7 @@ static void scsifront_backend_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's Closing state */ + fallthrough; /* Missed the backend's Closing state */ case XenbusStateClosing: scsifront_disconnect(info); break; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index e19102f46302..b25d0f7dac9e 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -353,7 +353,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("nmodem_supported", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.nmodem_supported); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 14): qcom_socinfo->info.num_clusters = __le32_to_cpu(info->num_clusters); qcom_socinfo->info.ncluster_array_offset = __le32_to_cpu(info->ncluster_array_offset); @@ -368,14 +368,14 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, &qcom_socinfo->info.num_defective_parts); debugfs_create_u32("ndefective_parts_array_offset", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.ndefective_parts_array_offset); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 13): qcom_socinfo->info.nproduct_id = __le32_to_cpu(info->nproduct_id); debugfs_create_u32("nproduct_id", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.nproduct_id); DEBUGFS_ADD(info, chip_id); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 12): qcom_socinfo->info.chip_family = __le32_to_cpu(info->chip_family); @@ -392,7 +392,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_x32("raw_device_number", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_device_num); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 11): case SOCINFO_VERSION(0, 10): case SOCINFO_VERSION(0, 9): @@ -400,12 +400,12 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("foundry_id", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.foundry_id); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 8): case SOCINFO_VERSION(0, 7): DEBUGFS_ADD(info, pmic_model); DEBUGFS_ADD(info, pmic_die_rev); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 6): qcom_socinfo->info.hw_plat_subtype = __le32_to_cpu(info->hw_plat_subtype); @@ -413,7 +413,7 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("hardware_platform_subtype", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat_subtype); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 5): qcom_socinfo->info.accessory_chip = __le32_to_cpu(info->accessory_chip); @@ -421,27 +421,27 @@ static void socinfo_debugfs_init(struct qcom_socinfo *qcom_socinfo, debugfs_create_u32("accessory_chip", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.accessory_chip); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 4): qcom_socinfo->info.plat_ver = __le32_to_cpu(info->plat_ver); debugfs_create_u32("platform_version", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.plat_ver); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 3): qcom_socinfo->info.hw_plat = __le32_to_cpu(info->hw_plat); debugfs_create_u32("hardware_platform", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.hw_plat); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 2): qcom_socinfo->info.raw_ver = __le32_to_cpu(info->raw_ver); debugfs_create_u32("raw_version", 0400, qcom_socinfo->dbg_root, &qcom_socinfo->info.raw_ver); - /* Fall through */ + fallthrough; case SOCINFO_VERSION(0, 1): DEBUGFS_ADD(info, build_id); break; diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 42cf37a0556b..d332e5d9abac 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -2229,7 +2229,7 @@ static int tegra_pmc_clk_notify_cb(struct notifier_block *nb, case POST_RATE_CHANGE: pmc->rate = data->new_rate; - /* fall through */ + fallthrough; case ABORT_RATE_CHANGE: mutex_unlock(&pmc->powergates_lock); diff --git a/drivers/spi/spi-bcm2835aux.c b/drivers/spi/spi-bcm2835aux.c index 2f717812c766..03b034c15d2b 100644 --- a/drivers/spi/spi-bcm2835aux.c +++ b/drivers/spi/spi-bcm2835aux.c @@ -164,10 +164,10 @@ static inline void bcm2835aux_rd_fifo(struct bcm2835aux_spi *bs) switch (count) { case 3: *bs->rx_buf++ = (data >> 16) & 0xff; - /* fallthrough */ + fallthrough; case 2: *bs->rx_buf++ = (data >> 8) & 0xff; - /* fallthrough */ + fallthrough; case 1: *bs->rx_buf++ = (data >> 0) & 0xff; /* fallthrough - no default */ diff --git a/drivers/spi/spi-fsl-cpm.c b/drivers/spi/spi-fsl-cpm.c index 54ad0ac121e5..ee905880769e 100644 --- a/drivers/spi/spi-fsl-cpm.c +++ b/drivers/spi/spi-fsl-cpm.c @@ -226,7 +226,7 @@ static void fsl_spi_free_dummy_rx(void) case 1: kfree(fsl_dummy_rx); fsl_dummy_rx = NULL; - /* fall through */ + fallthrough; default: fsl_dummy_rx_refcnt--; break; @@ -294,7 +294,7 @@ int fsl_spi_cpm_init(struct mpc8xxx_spi *mspi) switch (mspi->subblock) { default: dev_warn(dev, "cell-index unspecified, assuming SPI1\n"); - /* fall through */ + fallthrough; case 0: mspi->subblock = QE_CR_SUBBLOCK_SPI1; break; diff --git a/drivers/spi/spi-sprd-adi.c b/drivers/spi/spi-sprd-adi.c index bd23c4689b46..127b8bd25831 100644 --- a/drivers/spi/spi-sprd-adi.c +++ b/drivers/spi/spi-sprd-adi.c @@ -506,7 +506,7 @@ static int sprd_adi_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "failed to find hwlock id, %d\n", ret); - /* fall-through */ + fallthrough; case -EPROBE_DEFER: goto put_ctlr; } diff --git a/drivers/ssb/driver_chipcommon.c b/drivers/ssb/driver_chipcommon.c index 823dc99be46f..a8d2525e7af9 100644 --- a/drivers/ssb/driver_chipcommon.c +++ b/drivers/ssb/driver_chipcommon.c @@ -425,7 +425,7 @@ void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc, *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_M2); break; } - /* Fall through */ + fallthrough; default: *m = chipco_read32(cc, SSB_CHIPCO_CLOCK_SB); } diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index 1ca2ac5ef2b8..354486b7ed3a 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c @@ -342,7 +342,7 @@ void ssb_mipscore_init(struct ssb_mipscore *mcore) set_irq(dev, irq++); break; } - /* fallthrough */ + fallthrough; case SSB_DEV_EXTIF: set_irq(dev, 0); break; diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index b97a5c32d44a..f49ab1aa2149 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -228,7 +228,7 @@ static void __iomem *ssb_ioremap(struct ssb_bus *bus, switch (bus->bustype) { case SSB_BUSTYPE_SSB: /* Only map the first core for now. */ - /* fallthrough... */ + fallthrough; case SSB_BUSTYPE_PCMCIA: mmio = ioremap(baseaddr, SSB_CORE_SIZE); break; diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 8ea65bef35d2..a4e4eef55f35 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -4984,7 +4984,7 @@ enum mipi_port_id __get_mipi_port(struct atomisp_device *isp, if (MIPI_PORT1_ID + 1 != N_MIPI_PORT_ID) { return MIPI_PORT1_ID + 1; } - /* fall through */ + fallthrough; default: dev_err(isp->dev, "unsupported port: %d\n", port); return MIPI_PORT0_ID; diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index cccc5bfa1057..1b2b2c68025b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -704,14 +704,14 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, return false; } - /* fall-through */ + fallthrough; case ATOMISP_RUN_MODE_CONTINUOUS_CAPTURE: if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || pipe_id == IA_CSS_PIPE_ID_PREVIEW) return true; return false; - /* fall-through */ + fallthrough; case ATOMISP_RUN_MODE_VIDEO: if (!asd->continuous_mode->val) { if (pipe_id == IA_CSS_PIPE_ID_VIDEO || @@ -720,7 +720,7 @@ static bool is_pipe_valid_to_current_run_mode(struct atomisp_sub_device *asd, else return false; } - /* fall through */ + fallthrough; case ATOMISP_RUN_MODE_SDV: if (pipe_id == IA_CSS_PIPE_ID_CAPTURE || pipe_id == IA_CSS_PIPE_ID_VIDEO) @@ -2765,7 +2765,7 @@ static unsigned int atomisp_get_pipe_index(struct atomisp_sub_device *asd, if (!atomisp_is_mbuscode_raw(asd->fmt[asd->capture_pad].fmt.code)) { return IA_CSS_PIPE_ID_CAPTURE; } - /* fall through */ + fallthrough; case ATOMISP_SUBDEV_PAD_SOURCE_PREVIEW: if (asd->yuvpp_mode) return IA_CSS_PIPE_ID_YUVPP; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index f8d616f08b51..65b0c8a662a0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1467,7 +1467,6 @@ enum ia_css_pipe_id atomisp_get_css_pipe_id(struct atomisp_sub_device *asd) case ATOMISP_RUN_MODE_VIDEO: return IA_CSS_PIPE_ID_VIDEO; case ATOMISP_RUN_MODE_STILL_CAPTURE: - /* fall through */ default: return IA_CSS_PIPE_ID_CAPTURE; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index a000a1e316f7..0114b040247b 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -1086,7 +1086,7 @@ static int atomisp_subdev_probe(struct atomisp_device *isp) case RAW_CAMERA: dev_dbg(isp->dev, "raw_index: %d\n", raw_index); raw_index = isp->input_cnt; - /* fall through */ + fallthrough; case SOC_CAMERA: dev_dbg(isp->dev, "SOC_INDEX: %d\n", isp->input_cnt); if (isp->input_cnt >= ATOM_ISP_MAX_INPUTS) { diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c b/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c index 4fb9bfdd2f4c..f13af2329f48 100644 --- a/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +++ b/drivers/staging/media/atomisp/pci/hmm/hmm_bo.c @@ -660,7 +660,7 @@ static void free_private_bo_pages(struct hmm_buffer_object *bo, break; } - /* fall through */ + fallthrough; /* * if dynamic memory pool doesn't exist, need to free diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 54434c2dbaf9..a68cbb4995f0 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -4510,7 +4510,7 @@ ia_css_pipe_dequeue_buffer(struct ia_css_pipe *pipe, #endif pipe->stop_requested = false; } - /* fall through */ + fallthrough; case IA_CSS_BUFFER_TYPE_VF_OUTPUT_FRAME: case IA_CSS_BUFFER_TYPE_SEC_VF_OUTPUT_FRAME: frame = (struct ia_css_frame *)HOST_ADDRESS(ddr_buffer.kernel_ptr); diff --git a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c index 24041849384a..6386a3989bfe 100644 --- a/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c +++ b/drivers/staging/media/hantro/hantro_g1_mpeg2_dec.c @@ -110,7 +110,7 @@ hantro_g1_mpeg2_dec_set_buffers(struct hantro_dev *vpu, struct hantro_ctx *ctx, case V4L2_MPEG2_PICTURE_CODING_TYPE_B: backward_addr = hantro_get_ref(ctx, slice_params->backward_ref_ts); - /* fall-through */ + fallthrough; case V4L2_MPEG2_PICTURE_CODING_TYPE_P: forward_addr = hantro_get_ref(ctx, slice_params->forward_ref_ts); diff --git a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c index 7e9aad671489..f610fa5b4335 100644 --- a/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c +++ b/drivers/staging/media/hantro/rk3399_vpu_hw_mpeg2_dec.c @@ -112,7 +112,7 @@ rk3399_vpu_mpeg2_dec_set_buffers(struct hantro_dev *vpu, case V4L2_MPEG2_PICTURE_CODING_TYPE_B: backward_addr = hantro_get_ref(ctx, slice_params->backward_ref_ts); - /* fall-through */ + fallthrough; case V4L2_MPEG2_PICTURE_CODING_TYPE_P: forward_addr = hantro_get_ref(ctx, slice_params->forward_ref_ts); diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index d92fd804488e..21ebf7769696 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -488,7 +488,7 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) passthrough_cycles = incc->cycles; break; } - /* fallthrough - non-passthrough RGB565 (CSI-2 bus) */ + fallthrough; /* non-passthrough RGB565 (CSI-2 bus) */ default: burst_size = (image.pix.width & 0xf) ? 8 : 16; passthrough_bits = 16; diff --git a/drivers/staging/media/usbvision/usbvision-i2c.c b/drivers/staging/media/usbvision/usbvision-i2c.c index 6e4df3335b1b..aa3ff67a3cb1 100644 --- a/drivers/staging/media/usbvision/usbvision-i2c.c +++ b/drivers/staging/media/usbvision/usbvision-i2c.c @@ -303,13 +303,13 @@ usbvision_i2c_read_max4(struct usb_usbvision *usbvision, unsigned char addr, switch (len) { case 4: buf[3] = usbvision_read_reg(usbvision, USBVISION_SER_DAT4); - /* fall through */ + fallthrough; case 3: buf[2] = usbvision_read_reg(usbvision, USBVISION_SER_DAT3); - /* fall through */ + fallthrough; case 2: buf[1] = usbvision_read_reg(usbvision, USBVISION_SER_DAT2); - /* fall through */ + fallthrough; case 1: buf[0] = usbvision_read_reg(usbvision, USBVISION_SER_DAT1); break; diff --git a/drivers/target/iscsi/cxgbit/cxgbit_main.c b/drivers/target/iscsi/cxgbit/cxgbit_main.c index 30ea37e1a3f5..bd37f2afadea 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_main.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_main.c @@ -444,7 +444,7 @@ cxgbit_uld_lro_rx_handler(void *hndl, const __be64 *rsp, case CPL_RX_ISCSI_DDP: case CPL_FW4_ACK: lro_flush = false; - /* fall through */ + fallthrough; case CPL_ABORT_RPL_RSS: case CPL_PASS_ESTABLISH: case CPL_PEER_CLOSE: diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index c9689610e186..cd045dc75a58 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3740,7 +3740,7 @@ check_rsp_state: case ISTATE_SEND_LOGOUTRSP: if (!iscsit_logout_post_handler(cmd, conn)) return -ECONNRESET; - /* fall through */ + fallthrough; case ISTATE_SEND_STATUS: case ISTATE_SEND_ASYNCMSG: case ISTATE_SEND_NOPIN: diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 8fc88654bff6..5f79ea05f9b8 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -345,7 +345,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, break; case PR_TYPE_WRITE_EXCLUSIVE_REGONLY: we = 1; - /* fall through */ + fallthrough; case PR_TYPE_EXCLUSIVE_ACCESS_REGONLY: /* * Some commands are only allowed for registered I_T Nexuses. @@ -354,7 +354,7 @@ static int core_scsi3_pr_seq_non_holder(struct se_cmd *cmd, u32 pr_reg_type, break; case PR_TYPE_WRITE_EXCLUSIVE_ALLREG: we = 1; - /* fall through */ + fallthrough; case PR_TYPE_EXCLUSIVE_ACCESS_ALLREG: /* * Each registered I_T Nexus is a reservation holder. diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index f1e81886122d..6e8b8d30938f 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -734,7 +734,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, } if (!protect) return TCM_NO_SENSE; - /* Fallthrough */ + fallthrough; default: pr_err("Unable to determine pi_prot_type for CDB: 0x%02x " "PROTECT: 0x%02x\n", cdb[0], protect); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 9fb0be0aa620..590eac2df909 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2236,7 +2236,7 @@ static void transport_complete_qf(struct se_cmd *cmd) ret = cmd->se_tfo->queue_data_in(cmd); break; } - /* fall through */ + fallthrough; case DMA_NONE: queue_status: trace_target_cmd_complete(cmd); @@ -2431,7 +2431,7 @@ queue_rsp: goto queue_full; break; } - /* fall through */ + fallthrough; case DMA_NONE: queue_status: trace_target_cmd_complete(cmd); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index e9f0dda5ff92..a7ed56602c6c 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -537,7 +537,7 @@ static void ft_send_work(struct work_struct *work) case FCP_PTA_ACA: task_attr = TCM_ACA_TAG; break; - case FCP_PTA_SIMPLE: /* Fallthrough */ + case FCP_PTA_SIMPLE: default: task_attr = TCM_SIMPLE_TAG; } diff --git a/drivers/thermal/qcom/tsens-v0_1.c b/drivers/thermal/qcom/tsens-v0_1.c index e64db5f80d90..4ffa2e2c0145 100644 --- a/drivers/thermal/qcom/tsens-v0_1.c +++ b/drivers/thermal/qcom/tsens-v0_1.c @@ -220,7 +220,7 @@ static int calibrate_8916(struct tsens_priv *priv) p2[4] = (qfprom_cdata[1] & MSM8916_S4_P2_MASK) >> MSM8916_S4_P2_SHIFT; for (i = 0; i < priv->num_sensors; i++) p2[i] = ((base1 + p2[i]) << 3); - /* Fall through */ + fallthrough; case ONE_PT_CALIB2: base0 = (qfprom_cdata[0] & MSM8916_BASE0_MASK); p1[0] = (qfprom_cdata[0] & MSM8916_S0_P1_MASK) >> MSM8916_S0_P1_SHIFT; @@ -355,7 +355,7 @@ static int calibrate_8974(struct tsens_priv *priv) p2[8] = (calib[5] & S8_P2_BKP_MASK) >> S8_P2_BKP_SHIFT; p2[9] = (calib[5] & S9_P2_BKP_MASK) >> S9_P2_BKP_SHIFT; p2[10] = (calib[5] & S10_P2_BKP_MASK) >> S10_P2_BKP_SHIFT; - /* Fall through */ + fallthrough; case ONE_PT_CALIB: case ONE_PT_CALIB2: base1 = bkp[0] & BASE1_MASK; @@ -390,7 +390,7 @@ static int calibrate_8974(struct tsens_priv *priv) p2[8] = (calib[4] & S8_P2_MASK) >> S8_P2_SHIFT; p2[9] = (calib[4] & S9_P2_MASK) >> S9_P2_SHIFT; p2[10] = (calib[4] & S10_P2_MASK) >> S10_P2_SHIFT; - /* Fall through */ + fallthrough; case ONE_PT_CALIB: case ONE_PT_CALIB2: base1 = calib[0] & BASE1_MASK; @@ -420,7 +420,7 @@ static int calibrate_8974(struct tsens_priv *priv) p2[i] <<= 2; p2[i] |= BIT_APPEND; } - /* Fall through */ + fallthrough; case ONE_PT_CALIB2: for (i = 0; i < priv->num_sensors; i++) { p1[i] += base1; diff --git a/drivers/thermal/qcom/tsens-v1.c b/drivers/thermal/qcom/tsens-v1.c index b682a4df0081..3c19a3800c6d 100644 --- a/drivers/thermal/qcom/tsens-v1.c +++ b/drivers/thermal/qcom/tsens-v1.c @@ -202,7 +202,7 @@ static int calibrate_v1(struct tsens_priv *priv) p2[9] = (qfprom_cdata[3] & S9_P2_MASK) >> S9_P2_SHIFT; for (i = 0; i < priv->num_sensors; i++) p2[i] = ((base1 + p2[i]) << 2); - /* Fall through */ + fallthrough; case ONE_PT_CALIB2: base0 = (qfprom_cdata[4] & BASE0_MASK) >> BASE0_SHIFT; p1[0] = (qfprom_cdata[0] & S0_P1_MASK) >> S0_P1_SHIFT; @@ -263,7 +263,7 @@ static int calibrate_8976(struct tsens_priv *priv) for (i = 0; i < priv->num_sensors; i++) p2[i] = ((base1 + p2[i]) << 2); - /* Fall through */ + fallthrough; case ONE_PT_CALIB2: base0 = qfprom_cdata[0] & MSM8976_BASE0_MASK; p1[0] = (qfprom_cdata[0] & MSM8976_S0_P1_MASK) >> MSM8976_S0_P1_SHIFT; diff --git a/drivers/thunderbolt/ctl.c b/drivers/thunderbolt/ctl.c index f77ceae5c7d7..394a23ce6ca4 100644 --- a/drivers/thunderbolt/ctl.c +++ b/drivers/thunderbolt/ctl.c @@ -453,7 +453,7 @@ static void tb_ctl_rx_callback(struct tb_ring *ring, struct ring_frame *frame, "RX: checksum mismatch, dropping packet\n"); goto rx; } - /* Fall through */ + fallthrough; case TB_CFG_PKG_ICM_EVENT: if (tb_ctl_handle_event(pkg->ctl, frame->eof, pkg, frame->size)) goto rx; diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 712395f518b8..3845db569e4c 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -2092,7 +2092,7 @@ static int tb_switch_add_dma_port(struct tb_switch *sw) if (tb_route(sw)) return 0; - /* fallthrough */ + fallthrough; case 3: ret = tb_switch_set_uuid(sw); if (ret) diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c index 2aae2c76d880..1a7e849840b2 100644 --- a/drivers/thunderbolt/tunnel.c +++ b/drivers/thunderbolt/tunnel.c @@ -315,7 +315,7 @@ static inline u32 tb_dp_cap_set_rate(u32 val, u32 rate) switch (rate) { default: WARN(1, "invalid rate %u passed, defaulting to 1620 MB/s\n", rate); - /* Fallthrough */ + fallthrough; case 1620: val |= DP_COMMON_CAP_RATE_RBR << DP_COMMON_CAP_RATE_SHIFT; break; @@ -355,7 +355,7 @@ static inline u32 tb_dp_cap_set_lanes(u32 val, u32 lanes) default: WARN(1, "invalid number of lanes %u passed, defaulting to 1\n", lanes); - /* Fallthrough */ + fallthrough; case 1: val |= DP_COMMON_CAP_1_LANE << DP_COMMON_CAP_LANES_SHIFT; break; diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 2a0e51a20e34..92c9a476defc 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -492,7 +492,7 @@ static void xencons_backend_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state. */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/tty/mips_ejtag_fdc.c b/drivers/tty/mips_ejtag_fdc.c index 21e76a2ec182..a8e19b4833bf 100644 --- a/drivers/tty/mips_ejtag_fdc.c +++ b/drivers/tty/mips_ejtag_fdc.c @@ -243,7 +243,7 @@ done: /* Fall back to a 3 byte encoding */ word.bytes = 3; word.word &= 0x00ffffff; - /* Fall through */ + fallthrough; case 3: /* 3 byte encoding */ word.word |= 0x82000000; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 0a29a94ec438..35cf12147e39 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1584,7 +1584,7 @@ static void gsm_dlci_data(struct gsm_dlci *dlci, const u8 *data, int clen) gsm_process_modem(tty, dlci, modem, clen); tty_kref_put(tty); } - /* Fall through */ + fallthrough; case 1: /* Line state will go via DLCI 0 controls only */ default: tty_insert_flip_string(port, data, len); @@ -1986,7 +1986,7 @@ static void gsm1_receive(struct gsm_mux *gsm, unsigned char c) gsm->address = 0; gsm->state = GSM_ADDRESS; gsm->fcs = INIT_FCS; - /* Fall through */ + fallthrough; case GSM_ADDRESS: /* Address continuation */ gsm->fcs = gsm_fcs_add(gsm->fcs, c); if (gsm_read_ea(&gsm->address, c)) diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c index b09eac4b6d64..8e975cb29833 100644 --- a/drivers/tty/n_hdlc.c +++ b/drivers/tty/n_hdlc.c @@ -602,7 +602,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file, case TCOFLUSH: flush_tx_queue(tty); } - /* fall through - to default */ + fallthrough; /* to default */ default: error = n_tty_ioctl_helper(tty, file, cmd, arg); diff --git a/drivers/tty/n_r3964.c b/drivers/tty/n_r3964.c index f75696f0ee2d..934dd2fb2ec8 100644 --- a/drivers/tty/n_r3964.c +++ b/drivers/tty/n_r3964.c @@ -605,7 +605,6 @@ static void receive_char(struct r3964_info *pInfo, const unsigned char c) } break; case R3964_WAIT_FOR_RX_REPEAT: - /* FALLTHROUGH */ case R3964_IDLE: if (c == STX) { /* Prevent rx_queue from overflow: */ diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c index db88dee3a399..f8e99995eee9 100644 --- a/drivers/tty/serial/8250/8250_em.c +++ b/drivers/tty/serial/8250/8250_em.c @@ -39,7 +39,7 @@ static void serial8250_em_serial_out(struct uart_port *p, int offset, int value) break; case UART_IER: /* IER @ 0x04 */ value &= 0x0f; /* only 4 valid bits - not Xscale */ - /* fall-through */ + fallthrough; case UART_DLL_EM: /* DLL @ 0x24 (+9) */ case UART_DLM_EM: /* DLM @ 0x28 (+9) */ writel(value, p->membase + (offset << 2)); diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index d1d253c4b518..31c9e83ea3cb 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -255,7 +255,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) case CHIP_ID_F81866: sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, 0); - /* fall through */ + fallthrough; case CHIP_ID_F81865: sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, F81866_IRQ_SHARE); diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 1a74d511b02a..3eb2d485eaeb 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -631,7 +631,7 @@ pci_timedia_setup(struct serial_private *priv, break; case 3: offset = board->uart_offset; - /* FALLTHROUGH */ + fallthrough; case 4: /* BAR 2 */ case 5: /* BAR 3 */ case 6: /* BAR 4 */ diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 09475695effd..06028da9bc6a 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1872,7 +1872,7 @@ static bool handle_rx_dma(struct uart_8250_port *up, unsigned int iir) switch (iir & 0x3f) { case UART_IIR_RX_TIMEOUT: serial8250_rx_dma_flush(up); - /* fall-through */ + fallthrough; case UART_IIR_RLSI: return true; } diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c index e0b73a5402db..a2978abab0db 100644 --- a/drivers/tty/serial/8250/8250_uniphier.c +++ b/drivers/tty/serial/8250/8250_uniphier.c @@ -75,7 +75,7 @@ static unsigned int uniphier_serial_in(struct uart_port *p, int offset) break; case UART_LCR: valshift = 8; - /* fall through */ + fallthrough; case UART_MCR: offset = UNIPHIER_UART_LCR_MCR; break; @@ -101,7 +101,7 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value) case UART_SCR: /* No SCR for this hardware. Use CHAR as a scratch register */ valshift = 8; - /* fall through */ + fallthrough; case UART_FCR: offset = UNIPHIER_UART_CHAR_FCR; break; @@ -109,7 +109,7 @@ static void uniphier_serial_out(struct uart_port *p, int offset, int value) valshift = 8; /* Divisor latch access bit does not exist. */ value &= ~UART_LCR_DLAB; - /* fall through */ + fallthrough; case UART_MCR: offset = UNIPHIER_UART_LCR_MCR; break; diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index e43471b33710..bb5fc8bdd57a 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -1845,7 +1845,7 @@ static void atmel_get_ip_name(struct uart_port *port) version = atmel_uart_readl(port, ATMEL_US_VERSION); switch (version) { case 0x814: /* sama5d2 */ - /* fall through */ + fallthrough; case 0x701: /* sama5d4 */ atmel_port->fidi_min = 3; atmel_port->fidi_max = 65535; diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 8573fc9cb0cd..76b94d0ff586 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -587,7 +587,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) transmit_chars(up, lsr); break; case UART_IIR_RX_TIMEOUT: - /* FALLTHROUGH */ case UART_IIR_RDI: serial_omap_rdi(up, lsr); break; @@ -598,7 +597,6 @@ static irqreturn_t serial_omap_irq(int irq, void *dev_id) /* simply try again */ break; case UART_IIR_XOFF: - /* FALLTHROUGH */ default: break; } diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c index b5ef86ae2746..85366e059258 100644 --- a/drivers/tty/serial/rda-uart.c +++ b/drivers/tty/serial/rda-uart.c @@ -259,7 +259,7 @@ static void rda_uart_set_termios(struct uart_port *port, case CS5: case CS6: dev_warn(port->dev, "bit size not supported, using 7 bits\n"); - /* Fall through */ + fallthrough; case CS7: ctrl &= ~RDA_UART_DBITS_8; break; diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c index b87914ae6da8..bd13014a1c53 100644 --- a/drivers/tty/serial/serial-tegra.c +++ b/drivers/tty/serial/serial-tegra.c @@ -876,7 +876,7 @@ static irqreturn_t tegra_uart_isr(int irq, void *data) tegra_uart_write(tup, ier, UART_IER); break; } - /* Fall through */ + fallthrough; case 2: /* Receive */ if (!tup->use_rx_pio) { is_rx_start = tup->rx_in_progress; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 3403dd790517..f797c971cd82 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2101,7 +2101,7 @@ uart_set_options(struct uart_port *port, struct console *co, switch (parity) { case 'o': case 'O': termios.c_cflag |= PARODD; - /*fall through*/ + fallthrough; case 'e': case 'E': termios.c_cflag |= PARENB; break; diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 8ce9a7a256e5..319e5ceb6130 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -514,7 +514,7 @@ static void receive_kbd_ms_chars(struct uart_sunsu_port *up, int is_break) switch (ret) { case 2: sunsu_change_mouse_baud(up); - /* fallthru */ + fallthrough; case 1: break; diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c index 7ea06bbc6197..001e19d7c17d 100644 --- a/drivers/tty/serial/sunzilog.c +++ b/drivers/tty/serial/sunzilog.c @@ -306,7 +306,7 @@ static void sunzilog_kbdms_receive_chars(struct uart_sunzilog_port *up, switch (ret) { case 2: sunzilog_change_mouse_baud(up); - /* fallthru */ + fallthrough; case 1: break; diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 2833f1418d6d..a9b1ee27183a 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c @@ -544,7 +544,7 @@ static int cdns_uart_clk_notifier_cb(struct notifier_block *nb, cdns_uart->baud = cdns_uart_set_baud_rate(cdns_uart->port, cdns_uart->baud); - /* fall through */ + fallthrough; case ABORT_RATE_CHANGE: if (!locked) spin_lock_irqsave(&cdns_uart->port->lock, flags); diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index 9245fffdbceb..e18f318586ab 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -866,7 +866,7 @@ static int __tty_perform_flush(struct tty_struct *tty, unsigned long arg) ld->ops->flush_buffer(tty); tty_unthrottle(tty); } - /* fall through */ + fallthrough; case TCOFLUSH: tty_driver_flush_buffer(tty); break; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index ccb533fd00a2..d8b9363b81c1 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1553,7 +1553,7 @@ static void csi_J(struct vc_data *vc, int vpar) break; case 3: /* include scrollback */ flush_scrollback(vc); - /* fallthrough */ + fallthrough; case 2: /* erase whole display */ vc_uniscr_clear_lines(vc, 0, vc->vc_rows); count = vc->vc_cols * vc->vc_rows; @@ -2167,7 +2167,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) lf(vc); if (!is_kbd(vc, lnm)) return; - /* fall through */ + fallthrough; case 13: cr(vc); return; @@ -2306,7 +2306,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) return; } vc->vc_priv = EPecma; - /* fall through */ + fallthrough; case ESgetpars: if (c == ';' && vc->vc_npar < NPAR - 1) { vc->vc_npar++; diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index f7f6229082ca..60f4711717d2 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -710,7 +710,8 @@ static int c67x00_add_ctrl_urb(struct c67x00_hcd *c67x00, struct urb *urb) if (ret) return ret; break; - } /* else fallthrough */ + } + fallthrough; case STATUS_STAGE: pid = !usb_pipeout(urb->pipe) ? USB_PID_OUT : USB_PID_IN; ret = c67x00_create_td(c67x00, urb, NULL, 0, pid, 1, diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 052d5accfe9b..5b768b80d1ee 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -727,7 +727,7 @@ static void hub_irq(struct urb *urb) if ((++hub->nerrors < 10) || hub->error) goto resubmit; hub->error = status; - /* FALL THROUGH */ + fallthrough; /* let hub_wq handle things */ case 0: /* we got data: port status changed */ diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 422aea24afcd..2eb34c8b4065 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -646,9 +646,8 @@ static int dwc3_phy_setup(struct dwc3 *dwc) if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) break; } - /* FALLTHROUGH */ + fallthrough; case DWC3_GHWPARAMS3_HSPHY_IFC_ULPI: - /* FALLTHROUGH */ default: break; } @@ -1411,7 +1410,7 @@ static void dwc3_check_params(struct dwc3 *dwc) default: dev_err(dev, "invalid maximum_speed parameter %d\n", dwc->maximum_speed); - /* fall through */ + fallthrough; case USB_SPEED_UNKNOWN: /* default to superspeed */ dwc->maximum_speed = USB_SPEED_SUPER; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index 331c951d72dc..950c9435beec 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -2039,7 +2039,6 @@ static int do_scsi_command(struct fsg_common *common) case RELEASE: case RESERVE: case SEND_DIAGNOSTIC: - fallthrough; default: unknown_cmnd: diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index fa6793065c7c..a6426dd1cfef 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -328,7 +328,7 @@ static int usba_config_fifo_table(struct usba_udc *udc) switch (fifo_mode) { default: fifo_mode = 0; - /* fall through */ + fallthrough; case 0: udc->fifo_cfg = NULL; n = 0; diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c index b2638e83bb49..a6f7b2594c09 100644 --- a/drivers/usb/gadget/udc/fsl_udc_core.c +++ b/drivers/usb/gadget/udc/fsl_udc_core.c @@ -250,7 +250,7 @@ static int dr_controller_setup(struct fsl_udc *udc) break; case FSL_USB2_PHY_UTMI_WIDE: portctrl |= PORTSCX_PTW_16BIT; - /* fall through */ + fallthrough; case FSL_USB2_PHY_UTMI: case FSL_USB2_PHY_UTMI_DUAL: if (udc->pdata->have_sysif_regs) { diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c index cfafdd92c2a8..10324a7334fe 100644 --- a/drivers/usb/gadget/udc/pxa25x_udc.c +++ b/drivers/usb/gadget/udc/pxa25x_udc.c @@ -2340,12 +2340,12 @@ static int pxa25x_udc_probe(struct platform_device *pdev) case PXA250_A0: case PXA250_A1: /* A0/A1 "not released"; ep 13, 15 unusable */ - /* fall through */ + fallthrough; case PXA250_B2: case PXA210_B2: case PXA250_B1: case PXA210_B1: case PXA250_B0: case PXA210_B0: /* OUT-DMA is broken ... */ - /* fall through */ + fallthrough; case PXA250_C0: case PXA210_C0: break; #elif defined(CONFIG_ARCH_IXP4XX) diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index a87c0b26279e..3055d9abfec3 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -1019,7 +1019,7 @@ static int isp116x_hub_control(struct usb_hcd *hcd, spin_lock_irqsave(&isp116x->lock, flags); isp116x_write_reg32(isp116x, HCRHSTATUS, RH_HS_OCIC); spin_unlock_irqrestore(&isp116x->lock, flags); - /* fall through */ + fallthrough; case C_HUB_LOCAL_POWER: DBG("C_HUB_LOCAL_POWER\n"); break; @@ -1421,10 +1421,10 @@ static int isp116x_bus_suspend(struct usb_hcd *hcd) isp116x_write_reg32(isp116x, HCCONTROL, (val & ~HCCONTROL_HCFS) | HCCONTROL_USB_RESET); - /* fall through */ + fallthrough; case HCCONTROL_USB_RESET: ret = -EBUSY; - /* fall through */ + fallthrough; default: /* HCCONTROL_USB_SUSPEND */ spin_unlock_irqrestore(&isp116x->lock, flags); break; diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index b8961c0381cf..8c1bbac6d136 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -957,7 +957,8 @@ static void quirk_usb_disable_ehci(struct pci_dev *pdev) ehci_bios_handoff(pdev, op_reg_base, cap, offset); break; case 0: /* Illegal reserved cap, set cap=0 so we exit */ - cap = 0; /* fall through */ + cap = 0; + fallthrough; default: dev_warn(&pdev->dev, "EHCI: unrecognized capability %02x\n", diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index fcc5ac5ce8b1..ccb0156fcebe 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -699,7 +699,7 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event) switch (comp_code) { case COMP_SUCCESS: remain_length = 0; - /* FALLTHROUGH */ + fallthrough; case COMP_SHORT_PACKET: status = 0; break; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index c3554e37e09f..fe27dfc45270 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -1483,7 +1483,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_C_SUSPEND: bus_state->port_c_suspend &= ~(1 << wIndex); - /* fall through */ + fallthrough; case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_BH_PORT_RESET: case USB_PORT_FEAT_C_CONNECTION: diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 696fad50b478..fe405cd38dbc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1311,7 +1311,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, interval = xhci_parse_microframe_interval(udev, ep); break; } - /* Fall through - SS and HS isoc/int have same decoding */ + fallthrough; /* SS and HS isoc/int have same decoding */ case USB_SPEED_SUPER_PLUS: case USB_SPEED_SUPER: @@ -1331,7 +1331,7 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev, * since it uses the same rules as low speed interrupt * endpoints. */ - /* fall through */ + fallthrough; case USB_SPEED_LOW: if (usb_endpoint_xfer_int(&ep->desc) || diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 2c255d0620b0..a741a38a4c69 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2103,7 +2103,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, break; xhci_dbg(xhci, "TRB error %u, halted endpoint index = %u\n", trb_comp_code, ep_index); - /* else fall through */ + fallthrough; case COMP_STALL_ERROR: /* Did we transfer part of the data (middle) phase? */ if (trb_type == TRB_DATA || trb_type == TRB_NORMAL) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3c41b14ecce7..627c4c510446 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4618,7 +4618,7 @@ static unsigned long long xhci_calculate_intel_u1_timeout( break; } /* Otherwise the calculation is the same as isoc eps */ - /* fall through */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: timeout_ns = xhci_service_interval_to_ns(desc); timeout_ns = DIV_ROUND_UP_ULL(timeout_ns * 105, 100); diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index c545b27ea568..edb5b63d7063 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -975,7 +975,7 @@ static int cppi_channel_program(struct dma_channel *ch, musb_dbg(musb, "%cX DMA%d not allocated!", cppi_ch->transmit ? 'T' : 'R', cppi_ch->index); - /* FALLTHROUGH */ + fallthrough; case MUSB_DMA_STATUS_FREE: break; } diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5a56a03996b1..849e0b770130 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -852,7 +852,7 @@ static void musb_handle_intr_suspend(struct musb *musb, u8 devctl) case OTG_STATE_B_IDLE: if (!musb->is_active) break; - /* fall through */ + fallthrough; case OTG_STATE_B_PERIPHERAL: musb_g_suspend(musb); musb->is_active = musb->g.b_hnp_enable; @@ -972,9 +972,8 @@ static void musb_handle_intr_disconnect(struct musb *musb, u8 devctl) case OTG_STATE_A_PERIPHERAL: musb_hnp_stop(musb); musb_root_disconnect(musb); - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_B_WAIT_ACON: - /* FALLTHROUGH */ case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_IDLE: musb_g_disconnect(musb); @@ -1009,7 +1008,7 @@ static void musb_handle_intr_reset(struct musb *musb) switch (musb->xceiv->otg->state) { case OTG_STATE_A_SUSPEND: musb_g_reset(musb); - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_WAIT_BCON: /* OPT TD.4.7-900ms */ /* never use invalid T(a_wait_bcon) */ musb_dbg(musb, "HNP: in %s, %d msec timeout", @@ -1030,7 +1029,7 @@ static void musb_handle_intr_reset(struct musb *musb) break; case OTG_STATE_B_IDLE: musb->xceiv->otg->state = OTG_STATE_B_PERIPHERAL; - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_B_PERIPHERAL: musb_g_reset(musb); break; @@ -1471,7 +1470,7 @@ static int ep_config_from_table(struct musb *musb) switch (fifo_mode) { default: fifo_mode = 0; - /* FALLTHROUGH */ + fallthrough; case 0: cfg = mode_0_cfg; n = ARRAY_SIZE(mode_0_cfg); @@ -2018,7 +2017,7 @@ static void musb_pm_runtime_check_session(struct musb *musb) musb->quirk_retries--; return; } - /* fall through */ + fallthrough; case MUSB_QUIRK_A_DISCONNECT_19: if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 19556c1a8ae8..30085b2be7b9 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -232,7 +232,7 @@ static int dsps_check_status(struct musb *musb, void *unused) dsps_mod_timer_optional(glue); break; } - /* fall through */ + fallthrough; case OTG_STATE_A_WAIT_BCON: /* keep VBUS on for host-only mode */ @@ -242,7 +242,7 @@ static int dsps_check_status(struct musb *musb, void *unused) } musb_writeb(musb->mregs, MUSB_DEVCTL, 0); skip_session = 1; - /* fall through */ + fallthrough; case OTG_STATE_A_IDLE: case OTG_STATE_B_IDLE: @@ -793,7 +793,7 @@ static int dsps_create_musb_pdev(struct dsps_glue *glue, case USB_SPEED_SUPER: dev_warn(dev, "ignore incorrect maximum_speed " "(super-speed) setting in dts"); - /* fall through */ + fallthrough; default: config->maximum_speed = USB_SPEED_HIGH; } diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 0ae3e0be043e..44d3cb02fa76 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -735,7 +735,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) musb_writeb(mbase, MUSB_TESTMODE, musb->test_mode_nr); } - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_STAGE_STATUSOUT: /* end of sequence #1: write to host (TX state) */ @@ -767,7 +767,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) */ retval = IRQ_HANDLED; musb->ep0_state = MUSB_EP0_STAGE_SETUP; - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_STAGE_SETUP: setup: diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b7d22a0c0fb..30c5e7de0761 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -360,7 +360,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb, qh = first_qh(head); break; } - /* fall through */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_INT: @@ -1019,7 +1019,7 @@ static bool musb_h_ep0_continue(struct musb *musb, u16 len, struct urb *urb) musb->ep0_stage = MUSB_EP0_OUT; more = true; } - /* FALLTHROUGH */ + fallthrough; case MUSB_EP0_OUT: fifo_count = min_t(size_t, qh->maxpacket, urb->transfer_buffer_length - @@ -2222,7 +2222,7 @@ static int musb_urb_enqueue( interval = max_t(u8, epd->bInterval, 1); break; } - /* FALLTHROUGH */ + fallthrough; case USB_ENDPOINT_XFER_ISOC: /* ISO always uses logarithmic encoding */ interval = min_t(u8, epd->bInterval, 16); diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index cb7ae297a3af..cafc69536e1d 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -211,7 +211,7 @@ void musb_root_disconnect(struct musb *musb) musb->g.is_a_peripheral = 1; break; } - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_HOST: musb->xceiv->otg->state = OTG_STATE_A_WAIT_BCON; musb->is_active = 0; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d62c78b97cad..4232f1ce3fbf 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -104,7 +104,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) if (error) break; musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE; - /* Fall through */ + fallthrough; case OTG_STATE_A_WAIT_VRISE: case OTG_STATE_A_WAIT_BCON: case OTG_STATE_A_HOST: diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 99890d1bbfcb..c26683a2702b 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -464,7 +464,7 @@ static void musb_do_idle(struct timer_list *t) dev_dbg(musb->controller, "Nothing connected %s, turning off VBUS\n", usb_otg_state_string(musb->xceiv->otg->state)); } - /* FALLTHROUGH */ + fallthrough; case OTG_STATE_A_IDLE: tusb_musb_set_vbus(musb, 0); default: diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index c8a988d2cfdd..15dc25801cdc 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -592,7 +592,7 @@ static unsigned long sddr55_get_capacity(struct us_data *us) { case 0x64: info->pageshift = 8; info->smallpageshift = 1; - /* fall through */ + fallthrough; case 0x5d: // 5d is a ROM card with pagesize 512. return 0x00200000; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index d592071119ba..08f9296431e9 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -688,7 +688,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, break; case DMA_BIDIRECTIONAL: cmdinfo->state |= ALLOC_DATA_IN_URB | SUBMIT_DATA_IN_URB; - /* fall through */ + fallthrough; case DMA_TO_DEVICE: cmdinfo->state |= ALLOC_DATA_OUT_URB | SUBMIT_DATA_OUT_URB; case DMA_NONE: diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c index f57d91fd0e09..bd80e03b2b6f 100644 --- a/drivers/usb/typec/tcpm/tcpci.c +++ b/drivers/usb/typec/tcpm/tcpci.c @@ -157,7 +157,7 @@ static enum typec_cc_status tcpci_to_typec_cc(unsigned int cc, bool sink) case 0x3: if (sink) return TYPEC_CC_RP_3_0; - /* fall through */ + fallthrough; case 0x0: default: return TYPEC_CC_OPEN; diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 620465c2a1da..1ab1f5cda4ac 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -990,7 +990,7 @@ static long vfio_pci_ioctl(void *device_data, case VFIO_PCI_ERR_IRQ_INDEX: if (pci_is_pcie(vdev->pdev)) break; - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index c992973cc2d5..5fbf0c1f7433 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -2439,7 +2439,7 @@ static void *vfio_iommu_type1_open(unsigned long arg) break; case VFIO_TYPE1_NESTING_IOMMU: iommu->nesting = true; - /* fall through */ + fallthrough; case VFIO_TYPE1v2_IOMMU: iommu->v2 = true; break; diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index ddc7f5f0401f..8ec19425671f 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -681,7 +681,7 @@ static int adp8860_probe(struct i2c_client *client, switch (ADP8860_MANID(reg_val)) { case ADP8863_MANUFID: data->gdwn_dis = !!pdata->gdwn_dis; - /* fall through */ + fallthrough; case ADP8860_MANUFID: data->en_ambl_sens = !!pdata->en_ambl_sens; break; diff --git a/drivers/video/fbdev/acornfb.c b/drivers/video/fbdev/acornfb.c index 09a9ad901dad..bcc92aecf666 100644 --- a/drivers/video/fbdev/acornfb.c +++ b/drivers/video/fbdev/acornfb.c @@ -857,7 +857,7 @@ static void acornfb_parse_dram(char *opt) case 'M': case 'm': size *= 1024; - /* Fall through */ + fallthrough; case 'K': case 'k': size *= 1024; diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c index 6f7838979f0a..ae3d8e8b8d33 100644 --- a/drivers/video/fbdev/arcfb.c +++ b/drivers/video/fbdev/arcfb.c @@ -419,7 +419,7 @@ static int arcfb_ioctl(struct fb_info *info, schedule(); finish_wait(&arcfb_waitq, &wait); } - /* fall through */ + fallthrough; case FBIO_GETCONTROL2: { diff --git a/drivers/video/fbdev/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c index 1e252192569a..bfd2f00b403b 100644 --- a/drivers/video/fbdev/atmel_lcdfb.c +++ b/drivers/video/fbdev/atmel_lcdfb.c @@ -508,7 +508,7 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, case 32: var->transp.offset = 24; var->transp.length = 8; - /* fall through */ + fallthrough; case 24: if (pdata->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { /* RGB:888 mode */ @@ -633,7 +633,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) case 2: value |= ATMEL_LCDC_PIXELSIZE_2; break; case 4: value |= ATMEL_LCDC_PIXELSIZE_4; break; case 8: value |= ATMEL_LCDC_PIXELSIZE_8; break; - case 15: /* fall through */ + case 15: case 16: value |= ATMEL_LCDC_PIXELSIZE_16; break; case 24: value |= ATMEL_LCDC_PIXELSIZE_24; break; case 32: value |= ATMEL_LCDC_PIXELSIZE_32; break; diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c index 7c4483c7f313..f3d8123d7f36 100644 --- a/drivers/video/fbdev/aty/radeon_pm.c +++ b/drivers/video/fbdev/aty/radeon_pm.c @@ -1208,11 +1208,11 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo) case 1: if (mc & 0x4) break; - /* fall through */ + fallthrough; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKB_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKB_RESET; - /* fall through */ + fallthrough; case 0: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKA_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKA_RESET; @@ -1221,7 +1221,7 @@ static void radeon_pm_enable_dll_m10(struct radeonfb_info *rinfo) case 1: if (!(mc & 0x4)) break; - /* fall through */ + fallthrough; case 2: dll_sleep_mask |= MDLL_R300_RDCK__MRDCKD_SLEEP; dll_reset_mask |= MDLL_R300_RDCK__MRDCKD_RESET; diff --git a/drivers/video/fbdev/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c index 3df64a973194..15a9ee7cd734 100644 --- a/drivers/video/fbdev/cirrusfb.c +++ b/drivers/video/fbdev/cirrusfb.c @@ -1476,11 +1476,11 @@ static void init_vgachip(struct fb_info *info) mdelay(100); /* mode */ vga_wgfx(cinfo->regbase, CL_GR31, 0x00); - /* fall through */ + fallthrough; case BT_GD5480: /* from Klaus' NetBSD driver: */ vga_wgfx(cinfo->regbase, CL_GR2F, 0x00); - /* fall through */ + fallthrough; case BT_ALPINE: /* put blitter into 542x compat */ vga_wgfx(cinfo->regbase, CL_GR33, 0x00); diff --git a/drivers/video/fbdev/controlfb.c b/drivers/video/fbdev/controlfb.c index 9c4f1be856ec..a88dcb63eeb4 100644 --- a/drivers/video/fbdev/controlfb.c +++ b/drivers/video/fbdev/controlfb.c @@ -713,7 +713,7 @@ static int controlfb_blank(int blank_mode, struct fb_info *info) break; case FB_BLANK_POWERDOWN: ctrl &= ~0x33; - /* fall through */ + fallthrough; case FB_BLANK_NORMAL: ctrl |= 0x400; break; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index da7c88ffaa6a..6815bfb7f572 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1306,7 +1306,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd, case FBIOGET_CON2FBMAP: case FBIOPUT_CON2FBMAP: arg = (unsigned long) compat_ptr(arg); - /* fall through */ + fallthrough; case FBIOBLANK: ret = do_fb_ioctl(info, cmd, arg); break; diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c index 67ebfe5c9f1d..a547c21c7e92 100644 --- a/drivers/video/fbdev/fsl-diu-fb.c +++ b/drivers/video/fbdev/fsl-diu-fb.c @@ -1287,7 +1287,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, dev_warn(info->dev, "MFB_SET_PIXFMT value of 0x%08x is deprecated.\n", MFB_SET_PIXFMT_OLD); - /* fall through */ + fallthrough; case MFB_SET_PIXFMT: if (copy_from_user(&pix_fmt, buf, sizeof(pix_fmt))) return -EFAULT; @@ -1297,7 +1297,7 @@ static int fsl_diu_ioctl(struct fb_info *info, unsigned int cmd, dev_warn(info->dev, "MFB_GET_PIXFMT value of 0x%08x is deprecated.\n", MFB_GET_PIXFMT_OLD); - /* fall through */ + fallthrough; case MFB_GET_PIXFMT: pix_fmt = ad->pix_fmt; if (copy_to_user(buf, &pix_fmt, sizeof(pix_fmt))) diff --git a/drivers/video/fbdev/gxt4500.c b/drivers/video/fbdev/gxt4500.c index 13ded3a10708..e5475ae1e158 100644 --- a/drivers/video/fbdev/gxt4500.c +++ b/drivers/video/fbdev/gxt4500.c @@ -534,7 +534,7 @@ static int gxt4500_setcolreg(unsigned int reg, unsigned int red, break; case DFA_PIX_32BIT: val |= (reg << 24); - /* fall through */ + fallthrough; case DFA_PIX_24BIT: val |= (reg << 16) | (reg << 8); break; diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index e4c3c8b65da4..02411d89cb46 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -648,13 +648,13 @@ static int synthvid_connect_vsp(struct hv_device *hdev) ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN10); if (!ret) break; - /* Fallthrough */ + fallthrough; case VERSION_WIN8: case VERSION_WIN8_1: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN8); if (!ret) break; - /* Fallthrough */ + fallthrough; case VERSION_WS2008: case VERSION_WIN7: ret = synthvid_negotiate_ver(hdev, SYNTHVID_VERSION_WIN7); diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c index c65ec7386e87..e6f35f8feefc 100644 --- a/drivers/video/fbdev/i740fb.c +++ b/drivers/video/fbdev/i740fb.c @@ -430,7 +430,7 @@ static int i740fb_decode_var(const struct fb_var_screeninfo *var, break; case 9 ... 15: bpp = 15; - /* fall through */ + fallthrough; case 16: if ((1000000 / var->pixclock) > DACSPEED16) { dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n", diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c index 01c75c031cb6..39ebbe026ddf 100644 --- a/drivers/video/fbdev/mmp/fb/mmpfb.c +++ b/drivers/video/fbdev/mmp/fb/mmpfb.c @@ -90,8 +90,6 @@ static int var_to_pixfmt(struct fb_var_screeninfo *var) else return PIXFMT_BGR888UNPACK; } - - /* fall through */ } return -EINVAL; diff --git a/drivers/video/fbdev/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c index 8335da4ca30e..9b0a324bb1b4 100644 --- a/drivers/video/fbdev/nvidia/nv_hw.c +++ b/drivers/video/fbdev/nvidia/nv_hw.c @@ -896,7 +896,7 @@ void NVCalcStateExt(struct nvidia_par *par, if (!par->FlatPanel) state->control = NV_RD32(par->PRAMDAC0, 0x0580) & 0xeffffeff; - /* fallthrough */ + fallthrough; case NV_ARCH_10: case NV_ARCH_20: case NV_ARCH_30: diff --git a/drivers/video/fbdev/offb.c b/drivers/video/fbdev/offb.c index 5cd0f5f6a4ae..4501e848a36f 100644 --- a/drivers/video/fbdev/offb.c +++ b/drivers/video/fbdev/offb.c @@ -141,7 +141,7 @@ static int offb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ out_le32(par->cmap_adr + 0x58, in_le32(par->cmap_adr + 0x58) & ~0x20); - /* fall through */ + fallthrough; case cmap_r128: /* Set palette index & data */ out_8(par->cmap_adr + 0xb0, regno); @@ -211,7 +211,7 @@ static int offb_blank(int blank, struct fb_info *info) /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */ out_le32(par->cmap_adr + 0x58, in_le32(par->cmap_adr + 0x58) & ~0x20); - /* fall through */ + fallthrough; case cmap_r128: /* Set palette index & data */ out_8(par->cmap_adr + 0xb0, i); diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c index fa73acfc1371..7317c9aad677 100644 --- a/drivers/video/fbdev/omap/lcdc.c +++ b/drivers/video/fbdev/omap/lcdc.c @@ -328,13 +328,13 @@ static int omap_lcdc_setup_plane(int plane, int channel_out, lcdc.bpp = 12; break; } - /* fallthrough */ + fallthrough; case OMAPFB_COLOR_YUV422: if (lcdc.ext_mode) { lcdc.bpp = 16; break; } - /* fallthrough */ + fallthrough; default: /* FIXME: other BPPs. * bpp1: code 0, size 256 diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 0cbcc74fa943..3d090d2d9ed9 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -253,7 +253,7 @@ static int _setcolreg(struct fb_info *info, u_int regno, u_int red, u_int green, if (fbdev->ctrl->setcolreg) r = fbdev->ctrl->setcolreg(regno, red, green, blue, transp, update_hw_pal); - /* Fallthrough */ + fallthrough; case OMAPFB_COLOR_RGB565: case OMAPFB_COLOR_RGB444: if (r != 0) @@ -443,7 +443,7 @@ static int set_color_mode(struct omapfb_plane_struct *plane, return 0; case 12: var->bits_per_pixel = 16; - /* fall through */ + fallthrough; case 16: if (plane->fbdev->panel->bpp == 12) plane->color_mode = OMAPFB_COLOR_RGB444; @@ -1531,27 +1531,27 @@ static void omapfb_free_resources(struct omapfb_device *fbdev, int state) case OMAPFB_ACTIVE: for (i = 0; i < fbdev->mem_desc.region_cnt; i++) unregister_framebuffer(fbdev->fb_info[i]); - /* fall through */ + fallthrough; case 7: omapfb_unregister_sysfs(fbdev); - /* fall through */ + fallthrough; case 6: if (fbdev->panel->disable) fbdev->panel->disable(fbdev->panel); - /* fall through */ + fallthrough; case 5: omapfb_set_update_mode(fbdev, OMAPFB_UPDATE_DISABLED); - /* fall through */ + fallthrough; case 4: planes_cleanup(fbdev); - /* fall through */ + fallthrough; case 3: ctrl_cleanup(fbdev); - /* fall through */ + fallthrough; case 2: if (fbdev->panel->cleanup) fbdev->panel->cleanup(fbdev->panel); - /* fall through */ + fallthrough; case 1: dev_set_drvdata(fbdev->dev, NULL); kfree(fbdev); @@ -1854,7 +1854,7 @@ static int __init omapfb_setup(char *options) case 'm': case 'M': vram *= 1024; - /* Fall through */ + fallthrough; case 'k': case 'K': vram *= 1024; diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c index 3920a0db0390..b2d6e6df2161 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c @@ -1861,7 +1861,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY) width = width >> 1; - /* fall through */ + fallthrough; case OMAP_DSS_ROT_90: case OMAP_DSS_ROT_270: *offset1 = 0; @@ -1884,7 +1884,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, if (color_mode == OMAP_DSS_COLOR_YUV2 || color_mode == OMAP_DSS_COLOR_UYVY) width = width >> 1; - /* fall through */ + fallthrough; case OMAP_DSS_ROT_90 + 4: case OMAP_DSS_ROT_270 + 4: *offset1 = 0; diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c index f40be68d5aac..ea8c88aa4477 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c @@ -760,7 +760,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg) r = -ENODEV; break; } - /* FALLTHROUGH */ + fallthrough; case OMAPFB_WAITFORVSYNC: DBG("ioctl WAITFORVSYNC\n"); diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c index 836e7b1639ce..a3decc7fadde 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c @@ -882,7 +882,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl, / (var->bits_per_pixel >> 2); break; } - /* fall through */ + fallthrough; default: screen_width = fix->line_length / (var->bits_per_pixel >> 3); break; diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c index c7c98d8e2359..0642555289e0 100644 --- a/drivers/video/fbdev/pm2fb.c +++ b/drivers/video/fbdev/pm2fb.c @@ -233,10 +233,10 @@ static u32 to3264(u32 timing, int bpp, int is64) switch (bpp) { case 24: timing *= 3; - /* fall through */ + fallthrough; case 8: timing >>= 1; - /* fall through */ + fallthrough; case 16: timing >>= 1; case 32: diff --git a/drivers/video/fbdev/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c index eedfbd3572a8..47e6a1d0d229 100644 --- a/drivers/video/fbdev/pxa168fb.c +++ b/drivers/video/fbdev/pxa168fb.c @@ -60,8 +60,6 @@ static int determine_best_pix_fmt(struct fb_var_screeninfo *var) else return PIX_FMT_BGR1555; } - - /* fall through */ } /* @@ -87,8 +85,6 @@ static int determine_best_pix_fmt(struct fb_var_screeninfo *var) else return PIX_FMT_BGR888UNPACK; } - - /* fall through */ } return -EINVAL; diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index a53d24fb7183..f1551e00eb12 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -1614,7 +1614,7 @@ static void set_ctrlr_state(struct pxafb_info *fbi, u_int state) */ if (old_state != C_DISABLE_PM) break; - /* fall through */ + fallthrough; case C_ENABLE: /* diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c index 9b3493846f4d..ce55b9d2e862 100644 --- a/drivers/video/fbdev/riva/fbdev.c +++ b/drivers/video/fbdev/riva/fbdev.c @@ -1093,7 +1093,7 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) break; case 9 ... 15: var->green.length = 5; - /* fall through */ + fallthrough; case 16: var->bits_per_pixel = 16; /* The Riva128 supports RGB555 only */ diff --git a/drivers/video/fbdev/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c index 9dc925054930..ba316bd56efd 100644 --- a/drivers/video/fbdev/s3c-fb.c +++ b/drivers/video/fbdev/s3c-fb.c @@ -284,7 +284,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, /* 666 with one bit alpha/transparency */ var->transp.offset = 18; var->transp.length = 1; - /* fall through */ + fallthrough; case 18: var->bits_per_pixel = 32; @@ -312,7 +312,7 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var, case 25: var->transp.length = var->bits_per_pixel - 24; var->transp.offset = 24; - /* fall through */ + fallthrough; case 24: /* our 24bpp is unpacked, so 32bpp */ var->bits_per_pixel = 32; @@ -809,7 +809,7 @@ static int s3c_fb_blank(int blank_mode, struct fb_info *info) case FB_BLANK_POWERDOWN: wincon &= ~WINCONx_ENWIN; sfb->enabled &= ~(1 << index); - /* fall through - to FB_BLANK_NORMAL */ + fallthrough; /* to FB_BLANK_NORMAL */ case FB_BLANK_NORMAL: /* disable the DMA and display 0x0 (black) */ diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c index bda6cc313c8b..e31cf63b0a62 100644 --- a/drivers/video/fbdev/sa1100fb.c +++ b/drivers/video/fbdev/sa1100fb.c @@ -935,7 +935,7 @@ static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state) */ if (old_state != C_DISABLE_PM) break; - /* fall through */ + fallthrough; case C_ENABLE: /* diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c index 3fd87aeb6c79..a2442aae7e12 100644 --- a/drivers/video/fbdev/savage/savagefb_driver.c +++ b/drivers/video/fbdev/savage/savagefb_driver.c @@ -1860,7 +1860,7 @@ static int savage_init_hw(struct savagefb_par *par) if ((vga_in8(0x3d5, par) & 0xC0) == (0x01 << 6)) RamSavage4[1] = 8; - /*FALLTHROUGH*/ + fallthrough; case S3_SAVAGE2000: videoRam = RamSavage4[(config1 & 0xE0) >> 5] * 1024; diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c index 8a27d12e6ea8..c1043420dbd3 100644 --- a/drivers/video/fbdev/sh_mobile_lcdcfb.c +++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c @@ -1594,7 +1594,7 @@ sh_mobile_lcdc_overlay_fb_init(struct sh_mobile_lcdc_overlay *ovl) case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: info->fix.ypanstep = 2; - /* Fall through */ + fallthrough; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: info->fix.xpanstep = 2; @@ -2085,7 +2085,7 @@ sh_mobile_lcdc_channel_fb_init(struct sh_mobile_lcdc_chan *ch, case V4L2_PIX_FMT_NV12: case V4L2_PIX_FMT_NV21: info->fix.ypanstep = 2; - /* Fall through */ + fallthrough; case V4L2_PIX_FMT_NV16: case V4L2_PIX_FMT_NV61: info->fix.xpanstep = 2; diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index ac140962b1bf..03c736f6f3d0 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -1739,7 +1739,7 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, if(ivideo->warncount++ < 10) printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); - /* fall through */ + fallthrough; case SISFB_GET_INFO: /* For communication with X driver */ ivideo->sisfb_infoblock.sisfb_id = SISFB_ID; ivideo->sisfb_infoblock.sisfb_version = VER_MAJOR; @@ -1793,7 +1793,7 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, if(ivideo->warncount++ < 10) printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); - /* fall through */ + fallthrough; case SISFB_GET_VBRSTATUS: if(sisfb_CheckVBRetrace(ivideo)) return put_user((u32)1, argp); @@ -1804,7 +1804,7 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, if(ivideo->warncount++ < 10) printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); - /* fall through */ + fallthrough; case SISFB_GET_AUTOMAXIMIZE: if(ivideo->sisfb_max) return put_user((u32)1, argp); @@ -1815,7 +1815,7 @@ static int sisfb_ioctl(struct fb_info *info, unsigned int cmd, if(ivideo->warncount++ < 10) printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n"); - /* fall through */ + fallthrough; case SISFB_SET_AUTOMAXIMIZE: if(get_user(gpu32, argp)) return -EFAULT; diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c index 3dd1b1d76e98..6a52eba64559 100644 --- a/drivers/video/fbdev/sm501fb.c +++ b/drivers/video/fbdev/sm501fb.c @@ -1005,7 +1005,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info) case FB_BLANK_POWERDOWN: ctrl &= ~SM501_DC_CRT_CONTROL_ENABLE; sm501_misc_control(fbi->dev->parent, SM501_MISC_DAC_POWER, 0); - /* fall through */ + fallthrough; case FB_BLANK_NORMAL: ctrl |= SM501_DC_CRT_CONTROL_BLANK; diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index de953ddb6312..265865610edc 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -999,7 +999,7 @@ stifb_blank(int blank_mode, struct fb_info *info) case S9000_ID_HCRX: HYPER_ENABLE_DISABLE_DISPLAY(fb, enable); break; - case S9000_ID_A1659A: /* fall through */ + case S9000_ID_A1659A: case S9000_ID_TIMBER: case CRX24_OVERLAY_PLANES: default: @@ -1157,7 +1157,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) dev_name); goto out_err0; } - /* fall through */ + fallthrough; case S9000_ID_ARTIST: case S9000_ID_HCRX: case S9000_ID_TIMBER: diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c index f73e26c18c09..f056d80f6359 100644 --- a/drivers/video/fbdev/tdfxfb.c +++ b/drivers/video/fbdev/tdfxfb.c @@ -523,7 +523,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) case 32: var->transp.offset = 24; var->transp.length = 8; - /* fall through */ + fallthrough; case 24: var->red.offset = 16; var->green.offset = 8; diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c index 3fea01db58d6..4a869402d120 100644 --- a/drivers/video/fbdev/via/lcd.c +++ b/drivers/video/fbdev/via/lcd.c @@ -744,7 +744,7 @@ static void set_lcd_output_path(int set_iga, int output_interface) viaparinfo->chip_info->gfx_chip_name)) viafb_write_reg_mask(CR97, VIACR, 0x84, BIT7 + BIT2 + BIT1 + BIT0); - /* fall through */ + fallthrough; case INTERFACE_DVP0: case INTERFACE_DVP1: case INTERFACE_DFP_HIGH: diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c index 00307b8693bf..5ec51445bee8 100644 --- a/drivers/video/fbdev/xen-fbfront.c +++ b/drivers/video/fbdev/xen-fbfront.c @@ -677,7 +677,7 @@ static void xenfb_backend_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state. */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 9673eb12dacd..f22ebe89fe13 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -234,7 +234,7 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, return -EINVAL; timeout = new_timeout; sc1200wdt_write_data(WDTO, timeout); - /* fall through - and return the new timeout */ + fallthrough; /* and return the new timeout */ case WDIOC_GETTIMEOUT: return put_user(timeout * 60, p); diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 184a06a74f83..c00627825de8 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c @@ -332,7 +332,7 @@ static long wdrtas_ioctl(struct file *file, unsigned int cmd, wdrtas_interval = i; else wdrtas_interval = wdrtas_get_interval(i); - /* fallthrough */ + fallthrough; case WDIOC_GETTIMEOUT: return put_user(wdrtas_interval, argp); diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index b43b5595e988..72d725a0ab5c 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -1263,7 +1263,7 @@ static void pvcalls_front_changed(struct xenbus_device *dev, if (dev->state == XenbusStateClosed) break; /* Missed the backend's CLOSING state */ - /* fall through */ + fallthrough; case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/drivers/xen/xen-acpi-memhotplug.c b/drivers/xen/xen-acpi-memhotplug.c index 7457213b8915..f914b72557ef 100644 --- a/drivers/xen/xen-acpi-memhotplug.c +++ b/drivers/xen/xen-acpi-memhotplug.c @@ -229,7 +229,7 @@ static void acpi_memory_device_notify(acpi_handle handle, u32 event, void *data) case ACPI_NOTIFY_BUS_CHECK: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "\nReceived BUS CHECK notification for device\n")); - /* Fall Through */ + fallthrough; case ACPI_NOTIFY_DEVICE_CHECK: if (event == ACPI_NOTIFY_DEVICE_CHECK) ACPI_DEBUG_PRINT((ACPI_DB_INFO, diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index f2115587855f..b500466a6c37 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -545,7 +545,7 @@ static void xen_pcibk_frontend_changed(struct xenbus_device *xdev, xenbus_switch_state(xdev, XenbusStateClosed); if (xenbus_dev_is_online(xdev)) break; - /* fall through - if not online */ + fallthrough; /* if not online */ case XenbusStateUnknown: dev_dbg(&xdev->dev, "frontend is gone! unregister device\n"); device_unregister(&xdev->dev); diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c index 75c0a2e9a6db..1e8cfd80a4e6 100644 --- a/drivers/xen/xen-scsiback.c +++ b/drivers/xen/xen-scsiback.c @@ -1185,7 +1185,7 @@ static void scsiback_frontend_changed(struct xenbus_device *dev, xenbus_switch_state(dev, XenbusStateClosed); if (xenbus_dev_is_online(dev)) break; - /* fall through - if not online */ + fallthrough; /* if not online */ case XenbusStateUnknown: device_unregister(&dev->dev); break; diff --git a/drivers/xen/xenbus/xenbus_probe_frontend.c b/drivers/xen/xenbus/xenbus_probe_frontend.c index 15379089853b..480944606a3c 100644 --- a/drivers/xen/xenbus/xenbus_probe_frontend.c +++ b/drivers/xen/xenbus/xenbus_probe_frontend.c @@ -401,12 +401,12 @@ static void xenbus_reset_frontend(char *fe, char *be, int be_state) case XenbusStateConnected: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosing); xenbus_reset_wait_for_backend(be, XenbusStateClosing); - /* fall through */ + fallthrough; case XenbusStateClosing: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateClosed); xenbus_reset_wait_for_backend(be, XenbusStateClosed); - /* fall through */ + fallthrough; case XenbusStateClosed: xenbus_printf(XBT_NIL, fe, "state", "%d", XenbusStateInitialising); diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index 92cd1d80218d..3576123d8299 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -213,7 +213,7 @@ static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) break; default: WARN_ONCE(1, "unknown lock status code: %d\n", status); - /* fall through */ + fallthrough; case P9_LOCK_ERROR: case P9_LOCK_GRACE: res = -ENOLCK; diff --git a/fs/adfs/dir_f.c b/fs/adfs/dir_f.c index 30d526fecc3f..05e963402e25 100644 --- a/fs/adfs/dir_f.c +++ b/fs/adfs/dir_f.c @@ -18,11 +18,11 @@ static inline unsigned int adfs_readval(unsigned char *p, int len) switch (len) { case 4: val |= p[3] << 24; - /* fall through */ + fallthrough; case 3: val |= p[2] << 16; - /* fall through */ + fallthrough; case 2: val |= p[1] << 8; - /* fall through */ + fallthrough; default: val |= p[0]; } return val; @@ -32,11 +32,11 @@ static inline void adfs_writeval(unsigned char *p, int len, unsigned int val) { switch (len) { case 4: p[3] = val >> 24; - /* fall through */ + fallthrough; case 3: p[2] = val >> 16; - /* fall through */ + fallthrough; case 2: p[1] = val >> 8; - /* fall through */ + fallthrough; default: p[0] = val; } } diff --git a/fs/affs/inode.c b/fs/affs/inode.c index a346cf7659f1..044412110b52 100644 --- a/fs/affs/inode.c +++ b/fs/affs/inode.c @@ -93,7 +93,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino) case ST_ROOT: inode->i_uid = sbi->s_uid; inode->i_gid = sbi->s_gid; - /* fall through */ + fallthrough; case ST_USERDIR: if (be32_to_cpu(tail->stype) == ST_USERDIR || affs_test_opt(sbi->s_flags, SF_SETMODE)) { diff --git a/fs/affs/super.c b/fs/affs/super.c index 47107c6712a6..a100cd9950c8 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -474,7 +474,7 @@ got_root: case MUFS_INTLFFS: case MUFS_DCFFS: affs_set_opt(sbi->s_flags, SF_MUFS); - /* fall thru */ + fallthrough; case FS_INTLFFS: case FS_DCFFS: affs_set_opt(sbi->s_flags, SF_INTL); @@ -486,7 +486,7 @@ got_root: break; case MUFS_OFS: affs_set_opt(sbi->s_flags, SF_MUFS); - /* fall through */ + fallthrough; case FS_OFS: affs_set_opt(sbi->s_flags, SF_OFS); sb->s_flags |= SB_NOEXEC; @@ -494,7 +494,7 @@ got_root: case MUFS_DCOFS: case MUFS_INTLOFS: affs_set_opt(sbi->s_flags, SF_MUFS); - /* fall through */ + fallthrough; case FS_DCOFS: case FS_INTLOFS: affs_set_opt(sbi->s_flags, SF_INTL); diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index bef413818af7..a4e9e6e07e93 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -252,7 +252,7 @@ static int afs_deliver_cb_callback(struct afs_call *call) call->unmarshall++; /* extract the FID array and its count in two steps */ - /* fall through */ + fallthrough; case 1: _debug("extract FID count"); ret = afs_extract_data(call, true); @@ -271,7 +271,7 @@ static int afs_deliver_cb_callback(struct afs_call *call) afs_extract_to_buf(call, call->count * 3 * 4); call->unmarshall++; - /* Fall through */ + fallthrough; case 2: _debug("extract FID array"); ret = afs_extract_data(call, true); @@ -297,7 +297,7 @@ static int afs_deliver_cb_callback(struct afs_call *call) call->unmarshall++; /* extract the callback array and its count in two steps */ - /* fall through */ + fallthrough; case 3: _debug("extract CB count"); ret = afs_extract_data(call, true); @@ -312,7 +312,7 @@ static int afs_deliver_cb_callback(struct afs_call *call) iov_iter_discard(&call->def_iter, READ, call->count2 * 3 * 4); call->unmarshall++; - /* Fall through */ + fallthrough; case 4: _debug("extract discard %zu/%u", iov_iter_count(call->iter), call->count2 * 3 * 4); @@ -391,7 +391,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call) afs_extract_to_buf(call, 11 * sizeof(__be32)); call->unmarshall++; - /* Fall through */ + fallthrough; case 1: _debug("extract UUID"); ret = afs_extract_data(call, false); @@ -503,7 +503,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call) afs_extract_to_buf(call, 11 * sizeof(__be32)); call->unmarshall++; - /* Fall through */ + fallthrough; case 1: _debug("extract UUID"); ret = afs_extract_data(call, false); @@ -618,7 +618,7 @@ static int afs_deliver_yfs_cb_callback(struct afs_call *call) call->unmarshall++; /* extract the FID array and its count in two steps */ - /* Fall through */ + fallthrough; case 1: _debug("extract FID count"); ret = afs_extract_data(call, true); @@ -637,7 +637,7 @@ static int afs_deliver_yfs_cb_callback(struct afs_call *call) afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; case 2: _debug("extract FID array"); ret = afs_extract_data(call, false); diff --git a/fs/afs/file.c b/fs/afs/file.c index 6f6ed1605cfe..371d1488cc54 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c @@ -311,7 +311,7 @@ int afs_page_filler(void *data, struct page *page) case -ENOBUFS: _debug("cache said ENOBUFS"); - /* fall through */ + fallthrough; default: go_on: req = kzalloc(struct_size(req, array, 1), GFP_KERNEL); diff --git a/fs/afs/flock.c b/fs/afs/flock.c index ffb8575345ca..eff82a6839e4 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c @@ -376,7 +376,7 @@ again: spin_unlock(&vnode->lock); return; - /* Fall through */ + fallthrough; default: /* Looks like a lock request was withdrawn. */ spin_unlock(&vnode->lock); diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index acb4d0ca2649..1d95ed9dd86e 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c @@ -320,7 +320,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) call->tmp_u = htonl(0); afs_extract_to_tmp(call); } - /* Fall through */ + fallthrough; /* extract the returned data length */ case 1: @@ -348,7 +348,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) call->bvec[0].bv_page = req->pages[req->index]; iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); ASSERTCMP(size, <=, PAGE_SIZE); - /* Fall through */ + fallthrough; /* extract the returned data */ case 2: @@ -375,7 +375,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) /* Discard any excess data the server gave us */ afs_extract_discard(call, req->actual_len - req->len); call->unmarshall = 3; - /* Fall through */ + fallthrough; case 3: _debug("extract discard %zu/%llu", @@ -388,7 +388,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) no_more_data: call->unmarshall = 4; afs_extract_to_buf(call, (21 + 3 + 6) * 4); - /* Fall through */ + fallthrough; /* extract the metadata */ case 4: @@ -1343,7 +1343,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) case 0: call->unmarshall++; afs_extract_to_buf(call, 12 * 4); - /* Fall through */ + fallthrough; /* extract the returned status record */ case 1: @@ -1356,7 +1356,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) xdr_decode_AFSFetchVolumeStatus(&bp, &op->volstatus.vs); call->unmarshall++; afs_extract_to_tmp(call); - /* Fall through */ + fallthrough; /* extract the volume name length */ case 2: @@ -1371,7 +1371,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the volume name */ case 3: @@ -1385,7 +1385,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) _debug("volname '%s'", p); afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the offline message length */ case 4: @@ -1400,7 +1400,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the offline message */ case 5: @@ -1415,7 +1415,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the message of the day length */ case 6: @@ -1430,7 +1430,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the message of the day */ case 7: @@ -1682,7 +1682,7 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call) case 0: afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the capabilities word count */ case 1: @@ -1696,7 +1696,7 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call) call->count2 = count; afs_extract_discard(call, count * sizeof(__be32)); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract capabilities words */ case 2: @@ -1776,7 +1776,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) case 0: afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the file status count and array in two steps */ case 1: @@ -1794,7 +1794,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) call->unmarshall++; more_counts: afs_extract_to_buf(call, 21 * sizeof(__be32)); - /* Fall through */ + fallthrough; case 2: _debug("extract status array %u", call->count); @@ -1824,7 +1824,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) call->count = 0; call->unmarshall++; afs_extract_to_tmp(call); - /* Fall through */ + fallthrough; /* Extract the callback count and array in two steps */ case 3: @@ -1841,7 +1841,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) call->unmarshall++; more_cbs: afs_extract_to_buf(call, 3 * sizeof(__be32)); - /* Fall through */ + fallthrough; case 4: _debug("extract CB array"); @@ -1870,7 +1870,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) afs_extract_to_buf(call, 6 * sizeof(__be32)); call->unmarshall++; - /* Fall through */ + fallthrough; case 5: ret = afs_extract_data(call, false); @@ -1974,7 +1974,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) case 0: afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the returned data length */ case 1: @@ -1992,7 +1992,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) acl->size = call->count2; afs_extract_begin(call, acl->data, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the returned data */ case 2: @@ -2002,7 +2002,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) afs_extract_to_buf(call, (21 + 6) * 4); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the metadata */ case 3: diff --git a/fs/afs/misc.c b/fs/afs/misc.c index 5334f1bd2bca..1d1a8debe472 100644 --- a/fs/afs/misc.c +++ b/fs/afs/misc.c @@ -120,42 +120,42 @@ void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code) if (e->error == -ETIMEDOUT || e->error == -ETIME) return; - /* Fall through */ + fallthrough; case -ETIMEDOUT: case -ETIME: if (e->error == -ENOMEM || e->error == -ENONET) return; - /* Fall through */ + fallthrough; case -ENOMEM: case -ENONET: if (e->error == -ERFKILL) return; - /* Fall through */ + fallthrough; case -ERFKILL: if (e->error == -EADDRNOTAVAIL) return; - /* Fall through */ + fallthrough; case -EADDRNOTAVAIL: if (e->error == -ENETUNREACH) return; - /* Fall through */ + fallthrough; case -ENETUNREACH: if (e->error == -EHOSTUNREACH) return; - /* Fall through */ + fallthrough; case -EHOSTUNREACH: if (e->error == -EHOSTDOWN) return; - /* Fall through */ + fallthrough; case -EHOSTDOWN: if (e->error == -ECONNREFUSED) return; - /* Fall through */ + fallthrough; case -ECONNREFUSED: if (e->error == -ECONNRESET) return; - /* Fall through */ + fallthrough; case -ECONNRESET: /* Responded, but call expired. */ if (e->responded) return; diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 6a0935cb822f..d83f13c44b92 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -281,7 +281,7 @@ bool afs_select_fileserver(struct afs_operation *op) case -ETIME: if (op->error != -EDESTADDRREQ) goto iterate_address; - /* Fall through */ + fallthrough; case -ERFKILL: case -EADDRNOTAVAIL: case -ENETUNREACH: diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 8fc8fb406a5a..8be709cb8542 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -568,7 +568,7 @@ static void afs_deliver_to_call(struct afs_call *call) case -EIO: pr_err("kAFS: Call %u in bad state %u\n", call->debug_id, state); - /* Fall through */ + fallthrough; case -ENODATA: case -EBADMSG: case -EMSGSIZE: @@ -669,7 +669,7 @@ long afs_wait_for_call_to_complete(struct afs_call *call, ret = call->ret0; call->ret0 = 0; - /* Fall through */ + fallthrough; case -ECONNABORTED: ac->responded = true; break; @@ -872,7 +872,7 @@ void afs_send_empty_reply(struct afs_call *call) _debug("oom"); rxrpc_kernel_abort_call(net->socket, call->rxcall, RX_USER_ABORT, -ENOMEM, "KOO"); - /* Fall through */ + fallthrough; default: _leave(" [error]"); return; diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index fd82850cd424..dc9327332f06 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c @@ -196,7 +196,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) /* Extract the returned uuid, uniquifier, nentries and * blkaddrs size */ - /* Fall through */ + fallthrough; case 1: ret = afs_extract_data(call, true); if (ret < 0) @@ -221,7 +221,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) count = min(call->count, 4U); afs_extract_to_buf(call, count * sizeof(__be32)); - /* Fall through - and extract entries */ + fallthrough; /* and extract entries */ case 2: ret = afs_extract_data(call, call->count > 4); if (ret < 0) @@ -324,7 +324,7 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call) afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through - and extract the capabilities word count */ + fallthrough; /* and extract the capabilities word count */ case 1: ret = afs_extract_data(call, true); if (ret < 0) @@ -337,7 +337,7 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call) call->unmarshall++; afs_extract_discard(call, count * sizeof(__be32)); - /* Fall through - and extract capabilities words */ + fallthrough; /* and extract capabilities words */ case 2: ret = afs_extract_data(call, false); if (ret < 0) @@ -436,7 +436,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) /* Extract the returned uuid, uniquifier, fsEndpoints count and * either the first fsEndpoint type or the volEndpoints * count if there are no fsEndpoints. */ - /* Fall through */ + fallthrough; case 1: ret = afs_extract_data(call, true); if (ret < 0) @@ -475,7 +475,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) afs_extract_to_buf(call, size); call->unmarshall = 2; - /* Fall through - and extract fsEndpoints[] entries */ + fallthrough; /* and extract fsEndpoints[] entries */ case 2: ret = afs_extract_data(call, true); if (ret < 0) @@ -526,7 +526,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) * extract the type of the next endpoint when we extract the * data of the current one, but this is the first... */ - /* Fall through */ + fallthrough; case 3: ret = afs_extract_data(call, true); if (ret < 0) @@ -552,7 +552,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) afs_extract_to_buf(call, size); call->unmarshall = 4; - /* Fall through - and extract volEndpoints[] entries */ + fallthrough; /* and extract volEndpoints[] entries */ case 4: ret = afs_extract_data(call, true); if (ret < 0) @@ -587,7 +587,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) afs_extract_discard(call, 0); call->unmarshall = 5; - /* Fall through - Done */ + fallthrough; /* Done */ case 5: ret = afs_extract_data(call, false); if (ret < 0) @@ -663,7 +663,7 @@ static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call) afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through - and extract the cell name length */ + fallthrough; /* and extract the cell name length */ case 1: ret = afs_extract_data(call, true); if (ret < 0) @@ -685,7 +685,7 @@ static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call) afs_extract_begin(call, cell_name, namesz); call->unmarshall++; - /* Fall through - and extract cell name */ + fallthrough; /* and extract cell name */ case 2: ret = afs_extract_data(call, true); if (ret < 0) @@ -694,7 +694,7 @@ static int afs_deliver_yfsvl_get_cell_name(struct afs_call *call) afs_extract_discard(call, call->count2); call->unmarshall++; - /* Fall through - and extract padding */ + fallthrough; /* and extract padding */ case 3: ret = afs_extract_data(call, false); if (ret < 0) diff --git a/fs/afs/write.c b/fs/afs/write.c index a121c247d95a..4b2265cb1891 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -609,7 +609,7 @@ no_more: default: pr_notice("kAFS: Unexpected error from FS.StoreData %d\n", ret); - /* Fall through */ + fallthrough; case -EACCES: case -EPERM: case -ENOKEY: diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c index 8c24fdc899e3..3b1239b7e90d 100644 --- a/fs/afs/yfsclient.c +++ b/fs/afs/yfsclient.c @@ -373,7 +373,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) req->offset = req->pos & (PAGE_SIZE - 1); afs_extract_to_tmp64(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the returned data length */ case 1: @@ -401,7 +401,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) call->bvec[0].bv_page = req->pages[req->index]; iov_iter_bvec(&call->def_iter, READ, call->bvec, 1, size); ASSERTCMP(size, <=, PAGE_SIZE); - /* Fall through */ + fallthrough; /* extract the returned data */ case 2: @@ -428,7 +428,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) /* Discard any excess data the server gave us */ afs_extract_discard(call, req->actual_len - req->len); call->unmarshall = 3; - /* Fall through */ + fallthrough; case 3: _debug("extract discard %zu/%llu", @@ -444,7 +444,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) sizeof(struct yfs_xdr_YFSFetchStatus) + sizeof(struct yfs_xdr_YFSCallBack) + sizeof(struct yfs_xdr_YFSVolSync)); - /* Fall through */ + fallthrough; /* extract the metadata */ case 4: @@ -461,7 +461,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) req->file_size = vp->scb.status.size; call->unmarshall++; - /* Fall through */ + fallthrough; case 5: break; @@ -1262,7 +1262,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) case 0: call->unmarshall++; afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchVolumeStatus)); - /* Fall through */ + fallthrough; /* extract the returned status record */ case 1: @@ -1275,7 +1275,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) xdr_decode_YFSFetchVolumeStatus(&bp, &op->volstatus.vs); call->unmarshall++; afs_extract_to_tmp(call); - /* Fall through */ + fallthrough; /* extract the volume name length */ case 2: @@ -1290,7 +1290,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the volume name */ case 3: @@ -1304,7 +1304,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) _debug("volname '%s'", p); afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the offline message length */ case 4: @@ -1319,7 +1319,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the offline message */ case 5: @@ -1334,7 +1334,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the message of the day length */ case 6: @@ -1349,7 +1349,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) size = (call->count + 3) & ~3; /* It's padded */ afs_extract_to_buf(call, size); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the message of the day */ case 7: @@ -1363,7 +1363,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) _debug("motd '%s'", p); call->unmarshall++; - /* Fall through */ + fallthrough; case 8: break; @@ -1622,7 +1622,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) case 0: afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the file status count and array in two steps */ case 1: @@ -1640,7 +1640,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) call->unmarshall++; more_counts: afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSFetchStatus)); - /* Fall through */ + fallthrough; case 2: _debug("extract status array %u", call->count); @@ -1670,7 +1670,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) call->count = 0; call->unmarshall++; afs_extract_to_tmp(call); - /* Fall through */ + fallthrough; /* Extract the callback count and array in two steps */ case 3: @@ -1687,7 +1687,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) call->unmarshall++; more_cbs: afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSCallBack)); - /* Fall through */ + fallthrough; case 4: _debug("extract CB array"); @@ -1716,7 +1716,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) afs_extract_to_buf(call, sizeof(struct yfs_xdr_YFSVolSync)); call->unmarshall++; - /* Fall through */ + fallthrough; case 5: ret = afs_extract_data(call, false); @@ -1727,7 +1727,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) xdr_decode_YFSVolSync(&bp, &op->volsync); call->unmarshall++; - /* Fall through */ + fallthrough; case 6: break; @@ -1804,7 +1804,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) case 0: afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the file ACL length */ case 1: @@ -1826,7 +1826,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) afs_extract_discard(call, size); } call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the file ACL */ case 2: @@ -1836,7 +1836,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) afs_extract_to_tmp(call); call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the volume ACL length */ case 3: @@ -1858,7 +1858,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) afs_extract_discard(call, size); } call->unmarshall++; - /* Fall through */ + fallthrough; /* Extract the volume ACL */ case 4: @@ -1871,7 +1871,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) sizeof(struct yfs_xdr_YFSFetchStatus) + sizeof(struct yfs_xdr_YFSVolSync)); call->unmarshall++; - /* Fall through */ + fallthrough; /* extract the metadata */ case 5: @@ -1886,7 +1886,7 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) xdr_decode_YFSVolSync(&bp, &op->volsync); call->unmarshall++; - /* Fall through */ + fallthrough; case 6: break; diff --git a/fs/aio.c b/fs/aio.c index 5736bff48e9e..d5ec30385566 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1511,7 +1511,7 @@ static inline void aio_rw_done(struct kiocb *req, ssize_t ret) * may be already running. Just fail this IO with EINTR. */ ret = -EINTR; - /*FALLTHRU*/ + fallthrough; default: req->ki_complete(req, ret, 0); } diff --git a/fs/buffer.c b/fs/buffer.c index d468ed9981e0..50bbc99e3d96 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1958,7 +1958,7 @@ iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, */ set_buffer_new(bh); set_buffer_unwritten(bh); - /* FALLTHRU */ + fallthrough; case IOMAP_MAPPED: if ((iomap->flags & IOMAP_F_NEW) || offset >= i_size_read(inode)) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 060bdcc5ce32..9ff9d10a60ff 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1745,7 +1745,7 @@ static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags) case -ENOENT: if (d_really_is_negative(dentry)) valid = 1; - /* Fallthrough */ + fallthrough; default: break; } diff --git a/fs/ceph/file.c b/fs/ceph/file.c index d51c3f2fdca0..30cd00265181 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -252,7 +252,7 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) case S_IFREG: ceph_fscache_register_inode_cookie(inode); ceph_fscache_file_set_cookie(inode, file); - /* fall through */ + fallthrough; case S_IFDIR: ret = ceph_init_file_info(inode, file, fmode, S_ISDIR(inode->i_mode)); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 0e763d2dcf16..0496934feecb 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -581,7 +581,7 @@ should_set_ext_sec_flag(enum securityEnum sectype) if (global_secflags & (CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)) return true; - /* Fallthrough */ + fallthrough; default: return false; } diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index a275ee399dce..51c6b7880a70 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1378,25 +1378,25 @@ static int cifs_parse_security_flavors(char *value, return 1; case Opt_sec_krb5i: vol->sign = true; - /* Fallthrough */ + fallthrough; case Opt_sec_krb5: vol->sectype = Kerberos; break; case Opt_sec_ntlmsspi: vol->sign = true; - /* Fallthrough */ + fallthrough; case Opt_sec_ntlmssp: vol->sectype = RawNTLMSSP; break; case Opt_sec_ntlmi: vol->sign = true; - /* Fallthrough */ + fallthrough; case Opt_ntlm: vol->sectype = NTLM; break; case Opt_sec_ntlmv2i: vol->sign = true; - /* Fallthrough */ + fallthrough; case Opt_sec_ntlmv2: vol->sectype = NTLMv2; break; @@ -2187,7 +2187,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, vol->password = NULL; break; } - /* Fallthrough - to Opt_pass below.*/ + fallthrough; /* to Opt_pass below */ case Opt_pass: /* Obtain the value string */ value = strchr(data, '='); diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 69cd5856621b..de564368a887 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -798,7 +798,7 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) if ((server->sec_kerberos || server->sec_mskerberos) && (global_secflags & CIFSSEC_MAY_KRB5)) return Kerberos; - /* Fallthrough */ + fallthrough; default: return Unspecified; } @@ -815,7 +815,7 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) default: break; } - /* Fallthrough - to attempt LANMAN authentication next */ + fallthrough; /* to attempt LANMAN authentication next */ case CIFS_NEGFLAVOR_LANMAN: switch (requested) { case LANMAN: @@ -823,7 +823,7 @@ cifs_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) case Unspecified: if (global_secflags & CIFSSEC_MAY_LANMAN) return LANMAN; - /* Fallthrough */ + fallthrough; default: return Unspecified; } diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 667d70aa335f..96c172d94fba 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1101,7 +1101,7 @@ smb2_select_sectype(struct TCP_Server_Info *server, enum securityEnum requested) if ((server->sec_kerberos || server->sec_mskerberos) && (global_secflags & CIFSSEC_MAY_KRB5)) return Kerberos; - /* Fallthrough */ + fallthrough; default: return Unspecified; } diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index cb733652ecca..ca2273727225 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -1688,11 +1688,11 @@ static loff_t configfs_dir_lseek(struct file *file, loff_t offset, int whence) switch (whence) { case 1: offset += file->f_pos; - /* fall through */ + fallthrough; case 0: if (offset >= 0) break; - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/fs/dax.c b/fs/dax.c index 95341af1a966..994ab66a9907 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -1367,7 +1367,7 @@ static vm_fault_t dax_iomap_pte_fault(struct vm_fault *vmf, pfn_t *pfnp, ret = dax_load_hole(&xas, mapping, &entry, vmf); goto finish_iomap; } - /*FALLTHRU*/ + fallthrough; default: WARN_ON_ONCE(1); error = -EIO; diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index 18d81599522f..002123efc6b0 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c @@ -5817,7 +5817,7 @@ int dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, break; case -EAGAIN: error = 0; - /* fall through */ + fallthrough; default: __put_lkb(ls, lkb); goto out; diff --git a/fs/erofs/zmap.c b/fs/erofs/zmap.c index 7d40d78ea864..ae325541884e 100644 --- a/fs/erofs/zmap.c +++ b/fs/erofs/zmap.c @@ -359,7 +359,7 @@ static int z_erofs_extent_lookback(struct z_erofs_maprecorder *m, return z_erofs_extent_lookback(m, m->delta[0]); case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: map->m_la = (lcn << lclusterbits) | m->clusterofs; break; @@ -416,7 +416,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, case Z_EROFS_VLE_CLUSTER_TYPE_PLAIN: if (endoff >= m.clusterofs) map->m_flags &= ~EROFS_MAP_ZIPPED; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_HEAD: if (endoff >= m.clusterofs) { map->m_la = (m.lcn << lclusterbits) | m.clusterofs; @@ -433,7 +433,7 @@ int z_erofs_map_blocks_iter(struct inode *inode, end = (m.lcn << lclusterbits) | m.clusterofs; map->m_flags |= EROFS_MAP_FULL_MAPPED; m.delta[0] = 1; - /* fallthrough */ + fallthrough; case Z_EROFS_VLE_CLUSTER_TYPE_NONHEAD: /* get the correspoinding first chunk */ err = z_erofs_extent_lookback(&m, m.delta[0]); diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 80662e1f7889..415c21f0e750 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -1241,7 +1241,7 @@ do_indirects: mark_inode_dirty(inode); ext2_free_branches(inode, &nr, &nr+1, 1); } - /* fall through */ + fallthrough; case EXT2_IND_BLOCK: nr = i_data[EXT2_DIND_BLOCK]; if (nr) { @@ -1249,7 +1249,7 @@ do_indirects: mark_inode_dirty(inode); ext2_free_branches(inode, &nr, &nr+1, 2); } - /* fall through */ + fallthrough; case EXT2_DIND_BLOCK: nr = i_data[EXT2_TIND_BLOCK]; if (nr) { diff --git a/fs/ext2/super.c b/fs/ext2/super.c index dda860562ca3..7fab2b3b5b39 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -587,7 +587,7 @@ static int parse_options(char *options, struct super_block *sb, case Opt_xip: ext2_msg(sb, KERN_INFO, "use dax instead of xip"); set_opt(opts->s_mount_opt, XIP); - /* Fall through */ + fallthrough; case Opt_dax: #ifdef CONFIG_FS_DAX ext2_msg(sb, KERN_WARNING, diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 16322ea5b463..d9e52a7f3702 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2646,7 +2646,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_NEW_INODE: if (set) return; - /* fall through */ + fallthrough; case FI_DATA_EXIST: case FI_INLINE_DOTS: case FI_PIN_FILE: diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 9bbaa2614679..3ad7bdbda5ca 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -618,10 +618,10 @@ pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) switch (dn->max_level) { case 3: base += 2 * indirect_blks; - /* fall through */ + fallthrough; case 2: base += 2 * direct_blks; - /* fall through */ + fallthrough; case 1: base += direct_index; break; diff --git a/fs/fcntl.c b/fs/fcntl.c index 2e4c0fa2074b..19ac5baad50f 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -362,7 +362,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, case F_OFD_SETLK: case F_OFD_SETLKW: #endif - /* Fallthrough */ + fallthrough; case F_SETLK: case F_SETLKW: if (copy_from_user(&flock, argp, sizeof(flock))) @@ -771,7 +771,7 @@ static void send_sigio_to_task(struct task_struct *p, if (!do_send_sig_info(signum, &si, p, type)) break; } - /* fall-through - fall back on the old plain SIGIO signal */ + fallthrough; /* fall back on the old plain SIGIO signal */ case 0: do_send_sig_info(SIGIO, SEND_SIG_PRIV, p, type); } diff --git a/fs/fs_context.c b/fs/fs_context.c index 7d5c5dd2b1d5..2834d1afa6e8 100644 --- a/fs/fs_context.c +++ b/fs/fs_context.c @@ -521,7 +521,7 @@ static int legacy_parse_param(struct fs_context *fc, struct fs_parameter *param) switch (param->type) { case fs_value_is_string: len = 1 + param->size; - /* Fall through */ + fallthrough; case fs_value_is_flag: len += strlen(param->key); break; diff --git a/fs/fsopen.c b/fs/fsopen.c index 2fa3f241b762..27a890aa493a 100644 --- a/fs/fsopen.c +++ b/fs/fsopen.c @@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsconfig, break; case FSCONFIG_SET_PATH_EMPTY: lookup_flags = LOOKUP_EMPTY; - /* fallthru */ + fallthrough; case FSCONFIG_SET_PATH: param.type = fs_value_is_filename; param.name = getname_flags(_value, lookup_flags, NULL); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 770f3a720db9..0f69fbd4af66 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -746,7 +746,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, } if (n == 0) break; - /* fall through - To branching from existing tree */ + fallthrough; /* To branching from existing tree */ case ALLOC_GROW_DEPTH: if (i > 1 && i < mp->mp_fheight) gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[i-1]); @@ -757,7 +757,7 @@ static int gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, state = ALLOC_DATA; if (n == 0) break; - /* fall through - To tree complete, adding data blocks */ + fallthrough; /* To tree complete, adding data blocks */ case ALLOC_DATA: BUG_ON(n > dblks); BUG_ON(mp->mp_bh[end_of_metadata] == NULL); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 4b67d47a7e00..6e173ae378c4 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1599,7 +1599,7 @@ static int gfs2_quota_get_state(struct super_block *sb, struct qc_state *state) case GFS2_QUOTA_ON: state->s_state[USRQUOTA].flags |= QCI_LIMITS_ENFORCED; state->s_state[GRPQUOTA].flags |= QCI_LIMITS_ENFORCED; - /*FALLTHRU*/ + fallthrough; case GFS2_QUOTA_ACCOUNT: state->s_state[USRQUOTA].flags |= QCI_ACCT_ENABLED | QCI_SYSFILE; diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 61eec628805d..0350dc7821bf 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -195,7 +195,7 @@ reread: switch (sbi->s_vhdr->signature) { case cpu_to_be16(HFSPLUS_VOLHEAD_SIGX): set_bit(HFSPLUS_SB_HFSX, &sbi->flags); - /*FALLTHRU*/ + fallthrough; case cpu_to_be16(HFSPLUS_VOLHEAD_SIG): break; case cpu_to_be16(HFSP_WRAP_MAGIC): diff --git a/fs/io_uring.c b/fs/io_uring.c index 91e2cc8414f9..8a53af8e5fe2 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2563,7 +2563,7 @@ static inline void io_rw_done(struct kiocb *kiocb, ssize_t ret) * IO with EINTR. */ ret = -EINTR; - /* fall through */ + fallthrough; default: kiocb->ki_complete(kiocb, ret, 0); } diff --git a/fs/iomap/seek.c b/fs/iomap/seek.c index 89f61d93c0bc..107ee80c3568 100644 --- a/fs/iomap/seek.c +++ b/fs/iomap/seek.c @@ -127,7 +127,7 @@ iomap_seek_hole_actor(struct inode *inode, loff_t offset, loff_t length, SEEK_HOLE); if (offset < 0) return length; - /* fall through */ + fallthrough; case IOMAP_HOLE: *(loff_t *)data = offset; return 0; @@ -175,7 +175,7 @@ iomap_seek_data_actor(struct inode *inode, loff_t offset, loff_t length, SEEK_DATA); if (offset < 0) return length; - /*FALLTHRU*/ + fallthrough; default: *(loff_t *)data = offset; return 0; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index ab8cdd9e9325..78858f6e9583 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -341,7 +341,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) rdev = old_decode_dev(je16_to_cpu(jdev.old_id)); else rdev = new_decode_dev(je32_to_cpu(jdev.new_id)); - /* fall through */ + fallthrough; case S_IFSOCK: case S_IFIFO: diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index bccfc40b3a74..2f6f0b140c05 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -1273,7 +1273,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, dbg_readinode("symlink's target '%s' cached\n", f->target); } - /* fall through... */ + fallthrough; case S_IFBLK: case S_IFCHR: diff --git a/fs/libfs.c b/fs/libfs.c index 4d08edf19c78..e0d42e977d9a 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -137,11 +137,11 @@ loff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence) switch (whence) { case 1: offset += file->f_pos; - /* fall through */ + fallthrough; case 0: if (offset >= 0) break; - /* fall through */ + fallthrough; default: return -EINVAL; } diff --git a/fs/locks.c b/fs/locks.c index 8fc0542f5132..1f84a03601fe 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1499,7 +1499,7 @@ static void lease_clear_pending(struct file_lock *fl, int arg) switch (arg) { case F_UNLCK: fl->fl_flags &= ~FL_UNLOCK_PENDING; - /* fall through */ + fallthrough; case F_RDLCK: fl->fl_flags &= ~FL_DOWNGRADE_PENDING; } @@ -2525,7 +2525,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, cmd = F_SETLKW; file_lock->fl_flags |= FL_OFDLCK; file_lock->fl_owner = filp; - /* Fallthrough */ + fallthrough; case F_SETLKW: file_lock->fl_flags |= FL_SLEEP; } @@ -2656,7 +2656,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, cmd = F_SETLKW64; file_lock->fl_flags |= FL_OFDLCK; file_lock->fl_owner = filp; - /* Fallthrough */ + fallthrough; case F_SETLKW64: file_lock->fl_flags |= FL_SLEEP; } diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index d1a0e2c8b1b4..08108b6d2fa1 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -753,7 +753,7 @@ out: case -ENODEV: /* Our extent block devices are unavailable */ set_bit(NFS_LSEG_UNAVAILABLE, &lseg->pls_flags); - /* Fall through */ + fallthrough; case 0: return lseg; default: diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a12f42e7d8c7..e732580fe47b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1181,7 +1181,7 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags) /* A NFSv4 OPEN will revalidate later */ if (server->caps & NFS_CAP_ATOMIC_OPEN) goto out; - /* Fallthrough */ + fallthrough; case S_IFDIR: if (server->flags & NFS_MOUNT_NOCTO) break; diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index a13e69009f19..7f5aa0403e16 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c @@ -187,7 +187,7 @@ static int filelayout_async_handle_error(struct rpc_task *task, pnfs_error_mark_layout_for_return(inode, lseg); pnfs_set_lo_fail(lseg); rpc_wake_up(&tbl->slot_tbl_waitq); - /* fall through */ + fallthrough; default: reset: dprintk("%s Retry through MDS. Error %d\n", __func__, diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index 965145592750..ff8965d1a4d4 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c @@ -1133,7 +1133,7 @@ static int ff_layout_async_handle_error_v4(struct rpc_task *task, nfs4_delete_deviceid(devid->ld, devid->nfs_client, &devid->deviceid); rpc_wake_up(&tbl->slot_tbl_waitq); - /* fall through */ + fallthrough; default: if (ff_layout_avoid_mds_available_ds(lseg)) return -NFS4ERR_RESET_TO_PNFS; @@ -1260,7 +1260,7 @@ static void ff_layout_io_track_ds_error(struct pnfs_layout_segment *lseg, */ if (opnum == OP_READ) break; - /* Fallthrough */ + fallthrough; default: pnfs_error_mark_layout_for_return(lseg->pls_layout->plh_inode, lseg); diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index 66949da0e827..524812984e2d 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -651,21 +651,21 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { case Opt_xprt_udp6: protofamily = AF_INET6; - /* fall through */ + fallthrough; case Opt_xprt_udp: ctx->flags &= ~NFS_MOUNT_TCP; ctx->nfs_server.protocol = XPRT_TRANSPORT_UDP; break; case Opt_xprt_tcp6: protofamily = AF_INET6; - /* fall through */ + fallthrough; case Opt_xprt_tcp: ctx->flags |= NFS_MOUNT_TCP; ctx->nfs_server.protocol = XPRT_TRANSPORT_TCP; break; case Opt_xprt_rdma6: protofamily = AF_INET6; - /* fall through */ + fallthrough; case Opt_xprt_rdma: /* vector side protocols to TCP */ ctx->flags |= NFS_MOUNT_TCP; @@ -684,13 +684,13 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, switch (lookup_constant(nfs_xprt_protocol_tokens, param->string, -1)) { case Opt_xprt_udp6: mountfamily = AF_INET6; - /* fall through */ + fallthrough; case Opt_xprt_udp: ctx->mount_server.protocol = XPRT_TRANSPORT_UDP; break; case Opt_xprt_tcp6: mountfamily = AF_INET6; - /* fall through */ + fallthrough; case Opt_xprt_tcp: ctx->mount_server.protocol = XPRT_TRANSPORT_TCP; break; @@ -899,9 +899,11 @@ static int nfs23_parse_monolithic(struct fs_context *fc, ctx->version = NFS_DEFAULT_VERSION; switch (data->version) { case 1: - data->namlen = 0; /* fall through */ + data->namlen = 0; + fallthrough; case 2: - data->bsize = 0; /* fall through */ + data->bsize = 0; + fallthrough; case 3: if (data->flags & NFS_MOUNT_VER3) goto out_no_v3; @@ -909,14 +911,14 @@ static int nfs23_parse_monolithic(struct fs_context *fc, memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); /* Turn off security negotiation */ extra_flags |= NFS_MOUNT_SECFLAVOUR; - /* fall through */ + fallthrough; case 4: if (data->flags & NFS_MOUNT_SECFLAVOUR) goto out_no_sec; - /* fall through */ + fallthrough; case 5: memset(data->context, 0, sizeof(data->context)); - /* fall through */ + fallthrough; case 6: if (data->flags & NFS_MOUNT_VER3) { if (data->root.size > NFS3_FHSIZE || data->root.size == 0) diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 26c94b32d6f4..c6c863382f37 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c @@ -108,7 +108,7 @@ struct posix_acl *nfs3_get_acl(struct inode *inode, int type) case -EPROTONOSUPPORT: dprintk("NFS_V3_ACL extension not supported; disabling\n"); server->caps &= ~NFS_CAP_ACLS; - /* fall through */ + fallthrough; case -ENOTSUPP: status = -EOPNOTSUPP; default: @@ -228,7 +228,7 @@ static int __nfs3_proc_setacls(struct inode *inode, struct posix_acl *acl, dprintk("NFS_V3_ACL SETACL RPC not supported" "(will not retry)\n"); server->caps &= ~NFS_CAP_ACLS; - /* fall through */ + fallthrough; case -ENOTSUPP: status = -EOPNOTSUPP; } diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c index a33970765467..fdfc77486ace 100644 --- a/fs/nfs/nfs4file.c +++ b/fs/nfs/nfs4file.c @@ -211,7 +211,7 @@ static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence) ret = nfs42_proc_llseek(filep, offset, whence); if (ret != -ENOTSUPP) return ret; - /* Fall through */ + fallthrough; default: return nfs_file_llseek(filep, offset, whence); } diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c index 1e7296395d71..62e6eea5c516 100644 --- a/fs/nfs/nfs4idmap.c +++ b/fs/nfs/nfs4idmap.c @@ -520,7 +520,7 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, switch (token) { case Opt_find_uid: im->im_type = IDMAP_TYPE_USER; - /* Fall through */ + fallthrough; case Opt_find_gid: im->im_conv = IDMAP_CONV_NAMETOID; ret = match_strlcpy(im->im_name, &substr, IDMAP_NAMESZ); @@ -528,7 +528,7 @@ static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, case Opt_find_user: im->im_type = IDMAP_TYPE_USER; - /* Fall through */ + fallthrough; case Opt_find_group: im->im_conv = IDMAP_CONV_IDTONAME; ret = match_int(&substr, &im->im_id); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index dbd01548335b..f8946b9468ef 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -483,7 +483,7 @@ static int nfs4_do_handle_exception(struct nfs_server *server, stateid); goto wait_on_recovery; } - /* Fall through */ + fallthrough; case -NFS4ERR_OPENMODE: if (inode) { int err; @@ -534,10 +534,10 @@ static int nfs4_do_handle_exception(struct nfs_server *server, ret = -EBUSY; break; } - /* Fall through */ + fallthrough; case -NFS4ERR_DELAY: nfs_inc_server_stats(server, NFSIOS_DELAY); - /* Fall through */ + fallthrough; case -NFS4ERR_GRACE: case -NFS4ERR_LAYOUTTRYLATER: case -NFS4ERR_RECALLCONFLICT: @@ -1505,7 +1505,7 @@ static int can_open_delegated(struct nfs_delegation *delegation, fmode_t fmode, case NFS4_OPEN_CLAIM_PREVIOUS: if (!test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags)) break; - /* Fall through */ + fallthrough; default: return 0; } @@ -2439,7 +2439,7 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) case NFS4_OPEN_CLAIM_DELEG_CUR_FH: case NFS4_OPEN_CLAIM_DELEG_PREV_FH: data->o_arg.open_bitmap = &nfs4_open_noattr_bitmap[0]; - /* Fall through */ + fallthrough; case NFS4_OPEN_CLAIM_FH: task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_NOATTR]; } @@ -3545,11 +3545,11 @@ static void nfs4_close_done(struct rpc_task *task, void *data) nfs4_free_revoked_stateid(server, &calldata->arg.stateid, task->tk_msg.rpc_cred); - /* Fallthrough */ + fallthrough; case -NFS4ERR_BAD_STATEID: if (calldata->arg.fmode == 0) break; - /* Fallthrough */ + fallthrough; default: task->tk_status = nfs4_async_handle_exception(task, server, task->tk_status, &exception); @@ -6294,7 +6294,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) nfs4_free_revoked_stateid(data->res.server, data->args.stateid, task->tk_msg.rpc_cred); - /* Fallthrough */ + fallthrough; case -NFS4ERR_BAD_STATEID: case -NFS4ERR_STALE_STATEID: case -ETIMEDOUT: @@ -6314,7 +6314,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) data->res.fattr = NULL; goto out_restart; } - /* Fallthrough */ + fallthrough; default: task->tk_status = nfs4_async_handle_exception(task, data->res.server, task->tk_status, @@ -6622,13 +6622,13 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) if (nfs4_update_lock_stateid(calldata->lsp, &calldata->res.stateid)) break; - /* Fall through */ + fallthrough; case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_EXPIRED: nfs4_free_revoked_stateid(calldata->server, &calldata->arg.stateid, task->tk_msg.rpc_cred); - /* Fall through */ + fallthrough; case -NFS4ERR_BAD_STATEID: case -NFS4ERR_STALE_STATEID: if (nfs4_sync_lock_stateid(&calldata->arg.stateid, @@ -8665,7 +8665,7 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata) dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status); rpc_delay(task, NFS4_POLL_RETRY_MIN); task->tk_status = 0; - /* fall through */ + fallthrough; case -NFS4ERR_RETRY_UNCACHED_REP: rpc_restart_call_prepare(task); return; @@ -9113,13 +9113,13 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf switch(task->tk_status) { case 0: wake_up_all(&clp->cl_lock_waitq); - /* Fallthrough */ + fallthrough; case -NFS4ERR_COMPLETE_ALREADY: case -NFS4ERR_WRONG_CRED: /* What to do here? */ break; case -NFS4ERR_DELAY: rpc_delay(task, NFS4_POLL_RETRY_MAX); - /* fall through */ + fallthrough; case -NFS4ERR_RETRY_UNCACHED_REP: return -EAGAIN; case -NFS4ERR_BADSESSION: @@ -9434,10 +9434,10 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) &lrp->args.range, lrp->args.inode)) goto out_restart; - /* Fallthrough */ + fallthrough; default: task->tk_status = 0; - /* Fallthrough */ + fallthrough; case 0: break; case -NFS4ERR_DELAY: diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index b1dba24918f8..4bf10792cb5b 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1530,7 +1530,7 @@ restart: default: pr_err("NFS: %s: unhandled error %d\n", __func__, status); - /* Fall through */ + fallthrough; case -ENOMEM: case -NFS4ERR_DENIED: case -NFS4ERR_RECLAIM_BAD: @@ -1667,7 +1667,7 @@ restart: break; } printk(KERN_ERR "NFS: %s: unhandled error %d\n", __func__, status); - /* Fall through */ + fallthrough; case -ENOENT: case -ENOMEM: case -EACCES: @@ -1683,7 +1683,7 @@ restart: set_bit(ops->state_flag_bit, &state->flags); break; } - /* Fall through */ + fallthrough; case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_OLD_STATEID: @@ -1695,7 +1695,7 @@ restart: case -NFS4ERR_EXPIRED: case -NFS4ERR_NO_GRACE: nfs4_state_mark_reclaim_nograce(sp->so_server->nfs_client, state); - /* Fall through */ + fallthrough; case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_BADSESSION: case -NFS4ERR_BADSLOT: @@ -2273,11 +2273,11 @@ again: case -ETIMEDOUT: if (clnt->cl_softrtry) break; - /* Fall through */ + fallthrough; case -NFS4ERR_DELAY: case -EAGAIN: ssleep(1); - /* Fall through */ + fallthrough; case -NFS4ERR_STALE_CLIENTID: dprintk("NFS: %s after status %d, retrying\n", __func__, status); @@ -2289,7 +2289,7 @@ again: } if (clnt->cl_auth->au_flavor == RPC_AUTH_UNIX) break; - /* Fall through */ + fallthrough; case -NFS4ERR_CLID_INUSE: case -NFS4ERR_WRONGSEC: /* No point in retrying if we already used RPC_AUTH_UNIX */ diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 6ea4cac41e46..6985cacf4700 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -711,7 +711,7 @@ static void nfs_pgio_rpcsetup(struct nfs_pgio_header *hdr, case FLUSH_COND_STABLE: if (nfs_reqs_to_commit(cinfo)) break; - /* fall through */ + fallthrough; default: hdr->args.stable = NFS_FILE_SYNC; } diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 40332c758d84..71f7741126b6 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -1541,7 +1541,7 @@ void pnfs_roc_release(struct nfs4_layoutreturn_args *args, case 0: if (res->lrs_present) res_stateid = &res->stateid; - /* Fallthrough */ + fallthrough; default: arg_stateid = &args->stateid; } diff --git a/fs/nfs_common/nfsacl.c b/fs/nfs_common/nfsacl.c index 8ceb6425e01a..d056ad2fdefd 100644 --- a/fs/nfs_common/nfsacl.c +++ b/fs/nfs_common/nfsacl.c @@ -237,7 +237,7 @@ posix_acl_from_nfsacl(struct posix_acl *acl) break; case ACL_MASK: mask = pa; - /* fall through */ + fallthrough; case ACL_OTHER: break; } diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c index 9bbaa671c079..311e5ce80cfc 100644 --- a/fs/nfsd/blocklayout.c +++ b/fs/nfsd/blocklayout.c @@ -83,13 +83,13 @@ nfsd4_block_proc_layoutget(struct inode *inode, const struct svc_fh *fhp, bex->soff = iomap.addr; break; } - /*FALLTHRU*/ + fallthrough; case IOMAP_HOLE: if (seg->iomode == IOMODE_READ) { bex->es = PNFS_BLOCK_NONE_DATA; break; } - /*FALLTHRU*/ + fallthrough; case IOMAP_DELALLOC: default: WARN(1, "pnfsd: filesystem returned %d extent\n", iomap.type); diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 7fbe9840a03e..052be5bf9ef5 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -1119,7 +1119,7 @@ static bool nfsd4_cb_sequence_done(struct rpc_task *task, struct nfsd4_callback break; case -ESERVERFAULT: ++session->se_cb_seq_nr; - /* Fall through */ + fallthrough; case 1: case -NFS4ERR_BADSESSION: nfsd4_mark_cb_fault(cb->cb_clp, cb->cb_seq_status); diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index e12409eca7cc..a97873f2d22b 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -681,7 +681,7 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task) rpc_delay(task, HZ/100); /* 10 mili-seconds */ return 0; } - /* Fallthrough */ + fallthrough; default: /* * Unknown error or non-responding client, we'll need to fence. diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a527da3d8052..eaf50eafa935 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -428,7 +428,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, goto out; open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; reclaim = true; - /* fall through */ + fallthrough; case NFS4_OPEN_CLAIM_FH: case NFS4_OPEN_CLAIM_DELEG_CUR_FH: status = do_open_fhandle(rqstp, cstate, open); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 81ed8e8bab3f..49a604b1c6a6 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3117,7 +3117,7 @@ nfsd4_exchange_id(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, break; default: /* checked by xdr code */ WARN_ON_ONCE(1); - /* fall through */ + fallthrough; case SP4_SSV: status = nfserr_encr_alg_unsupp; goto out_nolock; @@ -4532,7 +4532,7 @@ static int nfsd4_cb_recall_done(struct nfsd4_callback *cb, rpc_delay(task, 2 * HZ); return 0; } - /*FALLTHRU*/ + fallthrough; default: return 1; } @@ -5652,7 +5652,7 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) break; default: printk("unknown stateid type %x\n", s->sc_type); - /* Fallthrough */ + fallthrough; case NFS4_CLOSED_STID: case NFS4_CLOSED_DELEG_STID: status = nfserr_bad_stateid; @@ -6742,7 +6742,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, case NFS4_READW_LT: if (nfsd4_has_session(cstate)) fl_flags |= FL_SLEEP; - /* Fallthrough */ + fallthrough; case NFS4_READ_LT: spin_lock(&fp->fi_lock); nf = find_readable_file_locked(fp); @@ -6754,7 +6754,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, case NFS4_WRITEW_LT: if (nfsd4_has_session(cstate)) fl_flags |= FL_SLEEP; - /* Fallthrough */ + fallthrough; case NFS4_WRITE_LT: spin_lock(&fp->fi_lock); nf = find_writeable_file_locked(fp); @@ -6816,7 +6816,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, break; case FILE_LOCK_DEFERRED: nbl = NULL; - /* Fallthrough */ + fallthrough; case -EAGAIN: /* conflock holds conflicting lock */ status = nfserr_denied; dprintk("NFSD: nfsd4_lock: conflicting lock found!\n"); diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c index 37bc8f5f4514..c81dbbad8792 100644 --- a/fs/nfsd/nfsfh.c +++ b/fs/nfsd/nfsfh.c @@ -459,7 +459,7 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp) case FSID_DEV: if (!old_valid_dev(exp_sb(exp)->s_dev)) return false; - /* FALL THROUGH */ + fallthrough; case FSID_MAJOR_MINOR: case FSID_ENCODE_DEV: return exp_sb(exp)->s_type->fs_flags & FS_REQUIRES_DEV; @@ -469,7 +469,7 @@ static bool fsid_type_ok_for_exp(u8 fsid_type, struct svc_export *exp) case FSID_UUID16: if (!is_root_export(exp)) return false; - /* fall through */ + fallthrough; case FSID_UUID4_INUM: case FSID_UUID16_INUM: return exp->ex_uuid != NULL; diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index 543bbe0a556e..6e0b066480c5 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -314,7 +314,7 @@ nfsd_proc_create(struct svc_rqst *rqstp) rdev = inode->i_rdev; attr->ia_valid |= ATTR_SIZE; - /* FALLTHROUGH */ + fallthrough; case S_IFIFO: /* this is probably a permission check.. * at least IRIX implements perm checking on diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index b603dfcdd361..f7f6473578af 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -221,7 +221,7 @@ int nfsd_vers(struct nfsd_net *nn, int vers, enum vers_op change) case NFSD_TEST: if (nn->nfsd_versions) return nn->nfsd_versions[vers]; - /* Fallthrough */ + fallthrough; case NFSD_AVAIL: return nfsd_support_version(vers); } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7d2933b85b65..aba5af9df328 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1456,7 +1456,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, *created = true; break; } - /* fall through */ + fallthrough; case NFS4_CREATE_EXCLUSIVE4_1: if ( d_inode(dchild)->i_mtime.tv_sec == v_mtime && d_inode(dchild)->i_atime.tv_sec == v_atime @@ -1465,7 +1465,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, *created = true; goto set_attr; } - /* fall through */ + fallthrough; case NFS3_CREATE_GUARDED: err = nfserr_exist; } diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c index fb5a9a8a13cf..e516ae389ca5 100644 --- a/fs/nilfs2/bmap.c +++ b/fs/nilfs2/bmap.c @@ -519,7 +519,7 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode) break; case NILFS_IFILE_INO: lockdep_set_class(&bmap->b_sem, &nilfs_bmap_mdt_lock_key); - /* Fall through */ + fallthrough; default: bmap->b_ptr_type = NILFS_BMAP_PTR_VM; bmap->b_last_allocated_key = 0; diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c index 0b453ef8fae5..2217f904a7cf 100644 --- a/fs/nilfs2/recovery.c +++ b/fs/nilfs2/recovery.c @@ -626,7 +626,7 @@ static int nilfs_do_roll_forward(struct the_nilfs *nilfs, !(flags & NILFS_SS_SYNDT)) goto try_next_pseg; state = RF_DSYNC_ST; - /* Fall through */ + fallthrough; case RF_DSYNC_ST: if (!(flags & NILFS_SS_SYNDT)) goto confused; diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index a651e821c2de..e3726aca28ed 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1138,7 +1138,8 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) nilfs_sc_cstage_set(sci, NILFS_ST_DAT); goto dat_stage; } - nilfs_sc_cstage_inc(sci); /* Fall through */ + nilfs_sc_cstage_inc(sci); + fallthrough; case NILFS_ST_GC: if (nilfs_doing_gc()) { head = &sci->sc_gc_inodes; @@ -1159,7 +1160,8 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) } sci->sc_stage.gc_inode_ptr = NULL; } - nilfs_sc_cstage_inc(sci); /* Fall through */ + nilfs_sc_cstage_inc(sci); + fallthrough; case NILFS_ST_FILE: head = &sci->sc_dirty_files; ii = list_prepare_entry(sci->sc_stage.dirty_file_ptr, head, @@ -1186,7 +1188,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) } nilfs_sc_cstage_inc(sci); sci->sc_stage.flags |= NILFS_CF_IFILE_STARTED; - /* Fall through */ + fallthrough; case NILFS_ST_IFILE: err = nilfs_segctor_scan_file(sci, sci->sc_root->ifile, &nilfs_sc_file_ops); @@ -1197,13 +1199,14 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) err = nilfs_segctor_create_checkpoint(sci); if (unlikely(err)) break; - /* Fall through */ + fallthrough; case NILFS_ST_CPFILE: err = nilfs_segctor_scan_file(sci, nilfs->ns_cpfile, &nilfs_sc_file_ops); if (unlikely(err)) break; - nilfs_sc_cstage_inc(sci); /* Fall through */ + nilfs_sc_cstage_inc(sci); + fallthrough; case NILFS_ST_SUFILE: err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs, sci->sc_nfreesegs, &ndone); @@ -1219,7 +1222,8 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) &nilfs_sc_file_ops); if (unlikely(err)) break; - nilfs_sc_cstage_inc(sci); /* Fall through */ + nilfs_sc_cstage_inc(sci); + fallthrough; case NILFS_ST_DAT: dat_stage: err = nilfs_segctor_scan_file(sci, nilfs->ns_dat, @@ -1230,7 +1234,8 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode) nilfs_sc_cstage_set(sci, NILFS_ST_DONE); return 0; } - nilfs_sc_cstage_inc(sci); /* Fall through */ + nilfs_sc_cstage_inc(sci); + fallthrough; case NILFS_ST_SR: if (mode == SC_LSEG_SR) { /* Appending a super root */ diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 559de311deca..3e01d8f2ab90 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -1147,7 +1147,7 @@ static int do_fanotify_mark(int fanotify_fd, unsigned int flags, __u64 mask, } switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) { - case FAN_MARK_ADD: /* fallthrough */ + case FAN_MARK_ADD: case FAN_MARK_REMOVE: if (!mask) return -EINVAL; diff --git a/fs/ocfs2/cluster/quorum.c b/fs/ocfs2/cluster/quorum.c index 1ef24574f481..cea739be77c4 100644 --- a/fs/ocfs2/cluster/quorum.c +++ b/fs/ocfs2/cluster/quorum.c @@ -67,7 +67,7 @@ static void o2quo_fence_self(void) default: WARN_ON(o2nm_single_cluster->cl_fence_method >= O2NM_FENCE_METHODS); - /* fall through */ + fallthrough; case O2NM_FENCE_RESET: printk(KERN_ERR "*** ocfs2 is very sorry to be fencing this " "system by restarting ***\n"); diff --git a/fs/pstore/zone.c b/fs/pstore/zone.c index 819428dfa32f..3ce89216670c 100644 --- a/fs/pstore/zone.c +++ b/fs/pstore/zone.c @@ -1081,7 +1081,6 @@ next_zone: readop = psz_ftrace_read; break; case PSTORE_TYPE_CONSOLE: - fallthrough; case PSTORE_TYPE_PMSG: readop = psz_record_read; break; diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 5444d3c4d93f..47f9e151988b 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c @@ -38,7 +38,7 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd, if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) || (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id)))) break; - /*FALLTHROUGH*/ + fallthrough; default: if (!capable(CAP_SYS_ADMIN)) return -EPERM; diff --git a/fs/seq_file.c b/fs/seq_file.c index 4e6239f33c06..31219c1db17d 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -295,7 +295,7 @@ loff_t seq_lseek(struct file *file, loff_t offset, int whence) switch (whence) { case SEEK_CUR: offset += file->f_pos; - /* fall through */ + fallthrough; case SEEK_SET: if (offset < 0) break; diff --git a/fs/signalfd.c b/fs/signalfd.c index 5b78719be445..456046e15873 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c @@ -176,7 +176,7 @@ static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, kernel_siginfo_t *info if (!nonblock) break; ret = -EAGAIN; - /* fall through */ + fallthrough; default: spin_unlock_irq(¤t->sighand->siglock); return ret; diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index 22bfda158f7f..6d6cd85c2b4c 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -269,7 +269,7 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, break; /* No more room on heap so make it un-categorized */ cat = LPROPS_UNCAT; - /* Fall through */ + fallthrough; case LPROPS_UNCAT: list_add(&lprops->list, &c->uncat_list); break; @@ -313,7 +313,7 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, case LPROPS_FREEABLE: c->freeable_cnt -= 1; ubifs_assert(c, c->freeable_cnt >= 0); - /* Fall through */ + fallthrough; case LPROPS_UNCAT: case LPROPS_EMPTY: case LPROPS_FRDI_IDX: diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c index 6023c97c6da2..25ff91c7e94a 100644 --- a/fs/udf/symlink.c +++ b/fs/udf/symlink.c @@ -52,7 +52,7 @@ static int udf_pc_to_char(struct super_block *sb, unsigned char *from, elen += pc->lengthComponentIdent; break; } - /* Fall through */ + fallthrough; case 2: if (tolen == 0) return -ENAMETOOLONG; diff --git a/fs/ufs/util.h b/fs/ufs/util.h index e1f1b2e868a7..4931bec1a01c 100644 --- a/fs/ufs/util.h +++ b/fs/ufs/util.h @@ -42,7 +42,7 @@ ufs_get_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1, case UFS_ST_SUNOS: if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT) return fs32_to_cpu(sb, usb1->fs_u0.fs_sun.fs_state); - /* Fall Through - to UFS_ST_SUN */ + fallthrough; /* to UFS_ST_SUN */ case UFS_ST_SUN: return fs32_to_cpu(sb, usb3->fs_un2.fs_sun.fs_state); case UFS_ST_SUNx86: @@ -63,7 +63,7 @@ ufs_set_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1, usb1->fs_u0.fs_sun.fs_state = cpu_to_fs32(sb, value); break; } - /* Fall Through - to UFS_ST_SUN */ + fallthrough; /* to UFS_ST_SUN */ case UFS_ST_SUN: usb3->fs_un2.fs_sun.fs_state = cpu_to_fs32(sb, value); break; @@ -197,7 +197,7 @@ ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode) case UFS_UID_EFT: if (inode->ui_u1.oldids.ui_suid == 0xFFFF) return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid); - /* Fall through */ + fallthrough; default: return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid); } @@ -215,7 +215,7 @@ ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value) inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value); if (value > 0xFFFF) value = 0xFFFF; - /* Fall through */ + fallthrough; default: inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value); break; @@ -231,7 +231,7 @@ ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode) case UFS_UID_EFT: if (inode->ui_u1.oldids.ui_sgid == 0xFFFF) return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid); - /* Fall through */ + fallthrough; default: return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid); } @@ -249,7 +249,7 @@ ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value) inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value); if (value > 0xFFFF) value = 0xFFFF; - /* Fall through */ + fallthrough; default: inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value); break; diff --git a/fs/vboxsf/utils.c b/fs/vboxsf/utils.c index 96bd160da48b..018057546067 100644 --- a/fs/vboxsf/utils.c +++ b/fs/vboxsf/utils.c @@ -226,7 +226,7 @@ int vboxsf_getattr(const struct path *path, struct kstat *kstat, break; case AT_STATX_FORCE_SYNC: sf_i->force_restat = 1; - /* fall-through */ + fallthrough; default: err = vboxsf_inode_revalidate(dentry); } diff --git a/include/linux/compat.h b/include/linux/compat.h index d38c4d7e83bd..b354ce58966e 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -429,11 +429,11 @@ put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, compat_sigset_t v; switch (_NSIG_WORDS) { case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3]; - /* fall through */ + fallthrough; case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2]; - /* fall through */ + fallthrough; case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1]; - /* fall through */ + fallthrough; case 1: v.sig[1] = (set->sig[0] >> 32); v.sig[0] = set->sig[0]; } return copy_to_user(compat, &v, size) ? -EFAULT : 0; diff --git a/include/linux/filter.h b/include/linux/filter.h index 0a355b005bf4..ebfb7cfb65f1 100644 --- a/include/linux/filter.h +++ b/include/linux/filter.h @@ -1200,7 +1200,7 @@ static inline u16 bpf_anc_helper(const struct sock_filter *ftest) BPF_ANCILLARY(RANDOM); BPF_ANCILLARY(VLAN_TPID); } - /* Fallthrough. */ + fallthrough; default: return ftest->code; } diff --git a/include/linux/jhash.h b/include/linux/jhash.h index 19ddd43aee68..cfb62e9f37be 100644 --- a/include/linux/jhash.h +++ b/include/linux/jhash.h @@ -86,17 +86,17 @@ static inline u32 jhash(const void *key, u32 length, u32 initval) } /* Last block: affect all 32 bits of (c) */ switch (length) { - case 12: c += (u32)k[11]<<24; /* fall through */ - case 11: c += (u32)k[10]<<16; /* fall through */ - case 10: c += (u32)k[9]<<8; /* fall through */ - case 9: c += k[8]; /* fall through */ - case 8: b += (u32)k[7]<<24; /* fall through */ - case 7: b += (u32)k[6]<<16; /* fall through */ - case 6: b += (u32)k[5]<<8; /* fall through */ - case 5: b += k[4]; /* fall through */ - case 4: a += (u32)k[3]<<24; /* fall through */ - case 3: a += (u32)k[2]<<16; /* fall through */ - case 2: a += (u32)k[1]<<8; /* fall through */ + case 12: c += (u32)k[11]<<24; fallthrough; + case 11: c += (u32)k[10]<<16; fallthrough; + case 10: c += (u32)k[9]<<8; fallthrough; + case 9: c += k[8]; fallthrough; + case 8: b += (u32)k[7]<<24; fallthrough; + case 7: b += (u32)k[6]<<16; fallthrough; + case 6: b += (u32)k[5]<<8; fallthrough; + case 5: b += k[4]; fallthrough; + case 4: a += (u32)k[3]<<24; fallthrough; + case 3: a += (u32)k[2]<<16; fallthrough; + case 2: a += (u32)k[1]<<8; fallthrough; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ @@ -132,8 +132,8 @@ static inline u32 jhash2(const u32 *k, u32 length, u32 initval) /* Handle the last 3 u32's */ switch (length) { - case 3: c += k[2]; /* fall through */ - case 2: b += k[1]; /* fall through */ + case 3: c += k[2]; fallthrough; + case 2: b += k[1]; fallthrough; case 1: a += k[0]; __jhash_final(a, b, c); case 0: /* Nothing left to add */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 1983e08f5906..97c83773b6f0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -157,11 +157,14 @@ static inline void __mm_zero_struct_page(struct page *page) switch (sizeof(struct page)) { case 80: - _pp[9] = 0; /* fallthrough */ + _pp[9] = 0; + fallthrough; case 72: - _pp[8] = 0; /* fallthrough */ + _pp[8] = 0; + fallthrough; case 64: - _pp[7] = 0; /* fallthrough */ + _pp[7] = 0; + fallthrough; case 56: _pp[6] = 0; _pp[5] = 0; diff --git a/include/linux/signal.h b/include/linux/signal.h index 6bb1a3f0258c..7bbc0e9cf084 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -137,11 +137,11 @@ static inline void name(sigset_t *r, const sigset_t *a, const sigset_t *b) \ b3 = b->sig[3]; b2 = b->sig[2]; \ r->sig[3] = op(a3, b3); \ r->sig[2] = op(a2, b2); \ - /* fall through */ \ + fallthrough; \ case 2: \ a1 = a->sig[1]; b1 = b->sig[1]; \ r->sig[1] = op(a1, b1); \ - /* fall through */ \ + fallthrough; \ case 1: \ a0 = a->sig[0]; b0 = b->sig[0]; \ r->sig[0] = op(a0, b0); \ @@ -171,9 +171,9 @@ static inline void name(sigset_t *set) \ switch (_NSIG_WORDS) { \ case 4: set->sig[3] = op(set->sig[3]); \ set->sig[2] = op(set->sig[2]); \ - /* fall through */ \ + fallthrough; \ case 2: set->sig[1] = op(set->sig[1]); \ - /* fall through */ \ + fallthrough; \ case 1: set->sig[0] = op(set->sig[0]); \ break; \ default: \ @@ -194,7 +194,7 @@ static inline void sigemptyset(sigset_t *set) memset(set, 0, sizeof(sigset_t)); break; case 2: set->sig[1] = 0; - /* fall through */ + fallthrough; case 1: set->sig[0] = 0; break; } @@ -207,7 +207,7 @@ static inline void sigfillset(sigset_t *set) memset(set, -1, sizeof(sigset_t)); break; case 2: set->sig[1] = -1; - /* fall through */ + fallthrough; case 1: set->sig[0] = -1; break; } diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 46881d902124..ab57cf787c1f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3745,19 +3745,19 @@ static inline bool __skb_metadata_differs(const struct sk_buff *skb_a, #define __it(x, op) (x -= sizeof(u##op)) #define __it_diff(a, b, op) (*(u##op *)__it(a, op)) ^ (*(u##op *)__it(b, op)) case 32: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 24: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 16: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 8: diffs |= __it_diff(a, b, 64); break; case 28: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 20: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 12: diffs |= __it_diff(a, b, 64); - /* fall through */ + fallthrough; case 4: diffs |= __it_diff(a, b, 32); break; } diff --git a/include/math-emu/op-common.h b/include/math-emu/op-common.h index adcc6a97db61..143568d64b20 100644 --- a/include/math-emu/op-common.h +++ b/include/math-emu/op-common.h @@ -308,7 +308,7 @@ do { \ \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ R##_e = X##_e; \ - /* Fall through */ \ + fallthrough; \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ @@ -319,7 +319,7 @@ do { \ \ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \ R##_e = Y##_e; \ - /* Fall through */ \ + fallthrough; \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ @@ -417,7 +417,7 @@ do { \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \ R##_s = X##_s; \ - /* Fall through */ \ + fallthrough; \ \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ @@ -431,7 +431,7 @@ do { \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \ R##_s = Y##_s; \ - /* Fall through */ \ + fallthrough; \ \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ @@ -497,7 +497,7 @@ do { \ \ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \ FP_SET_EXCEPTION(FP_EX_DIVZERO); \ - /* Fall through */ \ + fallthrough; \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \ R##_c = FP_CLS_INF; \ diff --git a/ipc/sem.c b/ipc/sem.c index 8c0244e0365e..f6c30a85dadf 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1691,7 +1691,7 @@ static long ksys_semctl(int semid, int semnum, int cmd, unsigned long arg, int v case IPC_SET: if (copy_semid_from_user(&semid64, p, version)) return -EFAULT; - /* fall through */ + fallthrough; case IPC_RMID: return semctl_down(ns, semid, cmd, &semid64); default: @@ -1805,7 +1805,7 @@ static long compat_ksys_semctl(int semid, int semnum, int cmd, int arg, int vers case IPC_SET: if (copy_compat_semid_from_user(&semid64, p, version)) return -EFAULT; - /* fallthru */ + fallthrough; case IPC_RMID: return semctl_down(ns, semid, cmd, &semid64); default: diff --git a/ipc/shm.c b/ipc/shm.c index f1ed36e3ac9f..e25c7c6106bc 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1179,7 +1179,7 @@ static long ksys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf, int ver case IPC_SET: if (copy_shmid_from_user(&sem64, buf, version)) return -EFAULT; - /* fallthru */ + fallthrough; case IPC_RMID: return shmctl_down(ns, shmid, cmd, &sem64); case SHM_LOCK: @@ -1374,7 +1374,7 @@ static long compat_ksys_shmctl(int shmid, int cmd, void __user *uptr, int versio case IPC_SET: if (copy_compat_shmid_from_user(&sem64, uptr, version)) return -EFAULT; - /* fallthru */ + fallthrough; case IPC_RMID: return shmctl_down(ns, shmid, cmd, &sem64); case SHM_LOCK: diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index a10e2997aa6c..333b3bcfc545 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -681,7 +681,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) data->values[i] = AUDIT_UID_UNSET; break; } - /* fall through - if set */ + fallthrough; /* if set */ default: data->values[i] = f->val; } diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 83ff127ef7ae..e21de4f1754c 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -1794,7 +1794,7 @@ static bool cg_sockopt_is_valid_access(int off, int size, return prog->expected_attach_type == BPF_CGROUP_GETSOCKOPT; case offsetof(struct bpf_sockopt, optname): - /* fallthrough */ + fallthrough; case offsetof(struct bpf_sockopt, level): if (size != size_default) return false; diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c index f1c46529929b..6386b7bb98f2 100644 --- a/kernel/bpf/cpumap.c +++ b/kernel/bpf/cpumap.c @@ -279,7 +279,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu, break; default: bpf_warn_invalid_xdp_action(act); - /* fallthrough */ + fallthrough; case XDP_DROP: xdp_return_frame(xdpf); stats->drop++; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 86299a292214..1bf960aa615c 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -2029,7 +2029,7 @@ bpf_prog_load_check_attach(enum bpf_prog_type prog_type, case BPF_PROG_TYPE_EXT: if (expected_attach_type) return -EINVAL; - /* fallthrough */ + fallthrough; default: return 0; } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index ef938f17b944..47e74f09fa37 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5236,7 +5236,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, off_reg == dst_reg ? dst : src); return -EACCES; } - /* fall-through */ + fallthrough; default: break; } @@ -10988,7 +10988,7 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) default: if (!prog_extension) return -EINVAL; - /* fallthrough */ + fallthrough; case BPF_MODIFY_RETURN: case BPF_LSM_MAC: case BPF_TRACE_FENTRY: diff --git a/kernel/capability.c b/kernel/capability.c index 1444f3954d75..7c59b096c98a 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -93,7 +93,7 @@ static int cap_validate_magic(cap_user_header_t header, unsigned *tocopy) break; case _LINUX_CAPABILITY_VERSION_2: warn_deprecated_v2(); - /* fall through - v3 is otherwise equivalent to v2. */ + fallthrough; /* v3 is otherwise equivalent to v2 */ case _LINUX_CAPABILITY_VERSION_3: *tocopy = _LINUX_CAPABILITY_U32S_3; break; diff --git a/kernel/compat.c b/kernel/compat.c index b8d2800bb4b7..05adfd6fa8bf 100644 --- a/kernel/compat.c +++ b/kernel/compat.c @@ -255,11 +255,11 @@ get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat) return -EFAULT; switch (_NSIG_WORDS) { case 4: set->sig[3] = v.sig[6] | (((long)v.sig[7]) << 32 ); - /* fall through */ + fallthrough; case 3: set->sig[2] = v.sig[4] | (((long)v.sig[5]) << 32 ); - /* fall through */ + fallthrough; case 2: set->sig[1] = v.sig[2] | (((long)v.sig[3]) << 32 ); - /* fall through */ + fallthrough; case 1: set->sig[0] = v.sig[0] | (((long)v.sig[1]) << 32 ); } #else diff --git a/kernel/debug/gdbstub.c b/kernel/debug/gdbstub.c index a790026e42d0..cc3c43dfec44 100644 --- a/kernel/debug/gdbstub.c +++ b/kernel/debug/gdbstub.c @@ -1046,14 +1046,14 @@ int gdb_serial_stub(struct kgdb_state *ks) return DBG_PASS_EVENT; } #endif - /* Fall through */ + fallthrough; case 'C': /* Exception passing */ tmp = gdb_cmd_exception_pass(ks); if (tmp > 0) goto default_handle; if (tmp == 0) break; - /* Fall through - on tmp < 0 */ + fallthrough; /* on tmp < 0 */ case 'c': /* Continue packet */ case 's': /* Single step packet */ if (kgdb_contthread && kgdb_contthread != current) { @@ -1062,7 +1062,7 @@ int gdb_serial_stub(struct kgdb_state *ks) break; } dbg_activate_sw_breakpoints(); - /* Fall through - to default processing */ + fallthrough; /* to default processing */ default: default_handle: error = kgdb_arch_handle_exception(ks->ex_vector, diff --git a/kernel/debug/kdb/kdb_keyboard.c b/kernel/debug/kdb/kdb_keyboard.c index 750497b0003a..f877a0a0d7cf 100644 --- a/kernel/debug/kdb/kdb_keyboard.c +++ b/kernel/debug/kdb/kdb_keyboard.c @@ -173,11 +173,11 @@ int kdb_get_kbd_char(void) case KT_LATIN: if (isprint(keychar)) break; /* printable characters */ - /* fall through */ + fallthrough; case KT_SPEC: if (keychar == K_ENTER) break; - /* fall through */ + fallthrough; default: return -1; /* ignore unprintables */ } diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index 004c5b6c87f8..6226502ce049 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -432,7 +432,7 @@ int kdb_getphysword(unsigned long *word, unsigned long addr, size_t size) *word = w8; break; } - /* fall through */ + fallthrough; default: diag = KDB_BADWIDTH; kdb_printf("kdb_getphysword: bad width %ld\n", (long) size); @@ -481,7 +481,7 @@ int kdb_getword(unsigned long *word, unsigned long addr, size_t size) *word = w8; break; } - /* fall through */ + fallthrough; default: diag = KDB_BADWIDTH; kdb_printf("kdb_getword: bad width %ld\n", (long) size); @@ -525,7 +525,7 @@ int kdb_putword(unsigned long addr, unsigned long word, size_t size) diag = kdb_putarea(addr, w8); break; } - /* fall through */ + fallthrough; default: diag = KDB_BADWIDTH; kdb_printf("kdb_putword: bad width %ld\n", (long) size); diff --git a/kernel/events/core.c b/kernel/events/core.c index 5bfe8e3c6e44..7ed5248f0445 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -10034,7 +10034,7 @@ perf_event_parse_addr_filter(struct perf_event *event, char *fstr, case IF_SRC_KERNELADDR: case IF_SRC_KERNEL: kernel = 1; - /* fall through */ + fallthrough; case IF_SRC_FILEADDR: case IF_SRC_FILE: diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index a8e14c80b405..762a928e18f9 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -173,7 +173,7 @@ irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags __irq_wake_thread(desc, action); - /* Fall through - to add to randomness */ + fallthrough; /* to add to randomness */ case IRQ_HANDLED: *flags |= action->flags; break; diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 52ac5391dcc6..5df903fccb60 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -271,7 +271,7 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, case IRQ_SET_MASK_OK: case IRQ_SET_MASK_OK_DONE: cpumask_copy(desc->irq_common_data.affinity, mask); - /* fall through */ + fallthrough; case IRQ_SET_MASK_OK_NOCOPY: irq_validate_effective_affinity(data); irq_set_thread_affinity(desc); @@ -868,7 +868,7 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned long flags) case IRQ_SET_MASK_OK_DONE: irqd_clear(&desc->irq_data, IRQD_TRIGGER_MASK); irqd_set(&desc->irq_data, flags); - /* fall through */ + fallthrough; case IRQ_SET_MASK_OK_NOCOPY: flags = irqd_get_trigger_type(&desc->irq_data); diff --git a/kernel/kallsyms.c b/kernel/kallsyms.c index 95cb74f73292..4fb15fa96734 100644 --- a/kernel/kallsyms.c +++ b/kernel/kallsyms.c @@ -684,12 +684,12 @@ bool kallsyms_show_value(const struct cred *cred) case 0: if (kallsyms_for_perf()) return true; - /* fallthrough */ + fallthrough; case 1: if (security_capable(cred, &init_user_ns, CAP_SYSLOG, CAP_OPT_NOAUDIT) == 0) return true; - /* fallthrough */ + fallthrough; default: return false; } diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index f33769f97aca..e7aa57fb2fdc 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -659,7 +659,7 @@ static void power_down(void) break; case HIBERNATION_PLATFORM: hibernation_platform_enter(); - /* Fall through */ + fallthrough; case HIBERNATION_SHUTDOWN: if (pm_power_off) kernel_power_off(); diff --git a/kernel/power/qos.c b/kernel/power/qos.c index db0bed2cae26..ec7e1e85923e 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -119,7 +119,7 @@ int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node, * and add, then see if the aggregate has changed. */ plist_del(node, &c->list); - /* fall through */ + fallthrough; case PM_QOS_ADD_REQ: plist_node_init(node, new_value); plist_add(node, &c->list); @@ -188,7 +188,7 @@ bool pm_qos_update_flags(struct pm_qos_flags *pqf, break; case PM_QOS_UPDATE_REQ: pm_qos_flags_remove_req(pqf, req); - /* fall through */ + fallthrough; case PM_QOS_ADD_REQ: req->flags = val; INIT_LIST_HEAD(&req->node); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 8471a0f7eb32..2d95dc3f4644 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2320,7 +2320,7 @@ static int select_fallback_rq(int cpu, struct task_struct *p) state = possible; break; } - /* Fall-through */ + fallthrough; case possible: do_set_cpus_allowed(p, cpu_possible_mask); state = fail; diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 007b0a6b0152..1bd7e3af904f 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1219,13 +1219,13 @@ static void __free_domain_allocs(struct s_data *d, enum s_alloc what, case sa_rootdomain: if (!atomic_read(&d->rd->refcount)) free_rootdomain(&d->rd->rcu); - /* Fall through */ + fallthrough; case sa_sd: free_percpu(d->sd); - /* Fall through */ + fallthrough; case sa_sd_storage: __sdt_free(cpu_map); - /* Fall through */ + fallthrough; case sa_none: break; } diff --git a/kernel/signal.c b/kernel/signal.c index 42b67d2cea37..a38b3edc6851 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -851,7 +851,7 @@ static int check_kill_permission(int sig, struct kernel_siginfo *info, */ if (!sid || sid == task_session(current)) break; - /* fall through */ + fallthrough; default: return -EPERM; } diff --git a/kernel/sys.c b/kernel/sys.c index ca11af9d815d..ab6c409b1159 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1753,7 +1753,7 @@ void getrusage(struct task_struct *p, int who, struct rusage *r) if (who == RUSAGE_CHILDREN) break; - /* fall through */ + fallthrough; case RUSAGE_SELF: thread_group_cputime_adjusted(p, &tgutime, &tgstime); diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index c4038511d5c9..95b6a708b040 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -377,7 +377,7 @@ static bool hrtimer_fixup_activate(void *addr, enum debug_obj_state state) switch (state) { case ODEBUG_STATE_ACTIVE: WARN_ON(1); - /* fall through */ + fallthrough; default: return false; } diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 07709ac30439..bf540f5a4115 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -439,12 +439,12 @@ static struct pid *good_sigevent(sigevent_t * event) rtn = pid_task(pid, PIDTYPE_PID); if (!rtn || !same_thread_group(rtn, current)) return NULL; - /* FALLTHRU */ + fallthrough; case SIGEV_SIGNAL: case SIGEV_THREAD: if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX) return NULL; - /* FALLTHRU */ + fallthrough; case SIGEV_NONE: return pid; default: diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index e51778c312f1..36d7464c8962 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -381,7 +381,7 @@ void tick_broadcast_control(enum tick_broadcast_mode mode) switch (mode) { case TICK_BROADCAST_FORCE: tick_broadcast_forced = 1; - /* fall through */ + fallthrough; case TICK_BROADCAST_ON: cpumask_set_cpu(cpu, tick_broadcast_on); if (!cpumask_test_and_set_cpu(cpu, tick_broadcast_mask)) { diff --git a/kernel/time/timer.c b/kernel/time/timer.c index a16764b0116e..a50364df1054 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -666,7 +666,7 @@ static bool timer_fixup_activate(void *addr, enum debug_obj_state state) case ODEBUG_STATE_ACTIVE: WARN_ON(1); - /* fall through */ + fallthrough; default: return false; } diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 7ba62d68885a..4b3a42fc3b24 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -745,7 +745,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) #endif case BLKTRACESTART: start = 1; - /* fall through */ + fallthrough; case BLKTRACESTOP: ret = __blk_trace_startstop(q, start); break; diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index bf44f6bbd0c3..78a678eeb140 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -499,7 +499,7 @@ predicate_parse(const char *str, int nr_parens, int nr_preds, ptr++; break; } - /* fall through */ + fallthrough; default: parse_error(pe, FILT_ERR_TOO_MANY_PREDS, next - str); @@ -1273,7 +1273,7 @@ static int parse_pred(const char *str, void *data, switch (op) { case OP_NE: pred->not = 1; - /* Fall through */ + fallthrough; case OP_GLOB: case OP_EQ: break; diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c index 58f72b25f8e9..13da529e2e72 100644 --- a/lib/asn1_decoder.c +++ b/lib/asn1_decoder.c @@ -381,7 +381,7 @@ next_op: case ASN1_OP_END_SET_ACT: if (unlikely(!(flags & FLAG_MATCHED))) goto tag_mismatch; - /* fall through */ + fallthrough; case ASN1_OP_END_SEQ: case ASN1_OP_END_SET_OF: @@ -448,7 +448,7 @@ next_op: pc += asn1_op_lengths[op]; goto next_op; } - /* fall through */ + fallthrough; case ASN1_OP_ACT: ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len); diff --git a/lib/assoc_array.c b/lib/assoc_array.c index 6f4bcf524554..04c98799c3ba 100644 --- a/lib/assoc_array.c +++ b/lib/assoc_array.c @@ -1113,7 +1113,7 @@ struct assoc_array_edit *assoc_array_delete(struct assoc_array *array, index_key)) goto found_leaf; } - /* fall through */ + fallthrough; case assoc_array_walk_tree_empty: case assoc_array_walk_found_wrong_shortcut: default: diff --git a/lib/bootconfig.c b/lib/bootconfig.c index a5f701161f6b..1b5de2a45b27 100644 --- a/lib/bootconfig.c +++ b/lib/bootconfig.c @@ -817,7 +817,7 @@ int __init xbc_init(char *buf, const char **emsg, int *epos) q - 2); break; } - /* Fall through */ + fallthrough; case '=': ret = xbc_parse_kv(&p, q, c); break; @@ -826,7 +826,7 @@ int __init xbc_init(char *buf, const char **emsg, int *epos) break; case '#': q = skip_comment(q); - /* fall through */ + fallthrough; case ';': case '\n': ret = xbc_parse_key(&p, q); diff --git a/lib/cmdline.c b/lib/cmdline.c index fbb9981a04a4..55768b4f3f58 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -132,23 +132,23 @@ unsigned long long memparse(const char *ptr, char **retptr) case 'E': case 'e': ret <<= 10; - /* fall through */ + fallthrough; case 'P': case 'p': ret <<= 10; - /* fall through */ + fallthrough; case 'T': case 't': ret <<= 10; - /* fall through */ + fallthrough; case 'G': case 'g': ret <<= 10; - /* fall through */ + fallthrough; case 'M': case 'm': ret <<= 10; - /* fall through */ + fallthrough; case 'K': case 'k': ret <<= 10; diff --git a/lib/dim/net_dim.c b/lib/dim/net_dim.c index a4db51c21266..06811d866775 100644 --- a/lib/dim/net_dim.c +++ b/lib/dim/net_dim.c @@ -233,7 +233,7 @@ void net_dim(struct dim *dim, struct dim_sample end_sample) schedule_work(&dim->work); break; } - /* fall through */ + fallthrough; case DIM_START_MEASURE: dim_update_sample(end_sample.event_ctr, end_sample.pkt_ctr, end_sample.byte_ctr, &dim->start_sample); diff --git a/lib/dim/rdma_dim.c b/lib/dim/rdma_dim.c index f7e26c7b4749..15462d54758d 100644 --- a/lib/dim/rdma_dim.c +++ b/lib/dim/rdma_dim.c @@ -59,7 +59,7 @@ static bool rdma_dim_decision(struct dim_stats *curr_stats, struct dim *dim) break; case DIM_STATS_WORSE: dim_turn(dim); - /* fall through */ + fallthrough; case DIM_STATS_BETTER: step_res = rdma_dim_step(dim); if (step_res == DIM_ON_EDGE) @@ -94,7 +94,7 @@ void rdma_dim(struct dim *dim, u64 completions) schedule_work(&dim->work); break; } - /* fall through */ + fallthrough; case DIM_START_MEASURE: dim->state = DIM_MEASURE_IN_PROGRESS; dim_update_sample_with_comps(curr_sample->event_ctr, 0, 0, diff --git a/lib/glob.c b/lib/glob.c index 0ba3ea86b546..85ecbda45cd8 100644 --- a/lib/glob.c +++ b/lib/glob.c @@ -102,7 +102,7 @@ bool __pure glob_match(char const *pat, char const *str) break; case '\\': d = *pat++; - /*FALLTHROUGH*/ + fallthrough; default: /* Literal character */ literal: if (c == d) { diff --git a/lib/siphash.c b/lib/siphash.c index c47bb6ff2149..a90112ee72a1 100644 --- a/lib/siphash.c +++ b/lib/siphash.c @@ -68,11 +68,11 @@ u64 __siphash_aligned(const void *data, size_t len, const siphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= le32_to_cpup(data); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -101,11 +101,11 @@ u64 __siphash_unaligned(const void *data, size_t len, const siphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= get_unaligned_le32(end); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } @@ -268,11 +268,11 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= le32_to_cpup(data); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -301,11 +301,11 @@ u32 __hsiphash_unaligned(const void *data, size_t len, bytemask_from_count(left))); #else switch (left) { - case 7: b |= ((u64)end[6]) << 48; /* fall through */ - case 6: b |= ((u64)end[5]) << 40; /* fall through */ - case 5: b |= ((u64)end[4]) << 32; /* fall through */ + case 7: b |= ((u64)end[6]) << 48; fallthrough; + case 6: b |= ((u64)end[5]) << 40; fallthrough; + case 5: b |= ((u64)end[4]) << 32; fallthrough; case 4: b |= get_unaligned_le32(end); break; - case 3: b |= ((u64)end[2]) << 16; /* fall through */ + case 3: b |= ((u64)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } @@ -431,7 +431,7 @@ u32 __hsiphash_aligned(const void *data, size_t len, const hsiphash_key_t *key) v0 ^= m; } switch (left) { - case 3: b |= ((u32)end[2]) << 16; /* fall through */ + case 3: b |= ((u32)end[2]) << 16; fallthrough; case 2: b |= le16_to_cpup(data); break; case 1: b |= end[0]; } @@ -454,7 +454,7 @@ u32 __hsiphash_unaligned(const void *data, size_t len, v0 ^= m; } switch (left) { - case 3: b |= ((u32)end[2]) << 16; /* fall through */ + case 3: b |= ((u32)end[2]) << 16; fallthrough; case 2: b |= get_unaligned_le16(end); break; case 1: b |= end[0]; } diff --git a/lib/ts_fsm.c b/lib/ts_fsm.c index ab749ec10ab5..64fd9015ad80 100644 --- a/lib/ts_fsm.c +++ b/lib/ts_fsm.c @@ -193,7 +193,7 @@ startover: TOKEN_MISMATCH(); block_idx++; - /* fall through */ + fallthrough; case TS_FSM_ANY: if (next == NULL) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index c155769559ab..19ebe1b257ec 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1265,7 +1265,7 @@ char *mac_address_string(char *buf, char *end, u8 *addr, case 'R': reversed = true; - /* fall through */ + fallthrough; default: separator = ':'; @@ -1681,7 +1681,8 @@ char *uuid_string(char *buf, char *end, const u8 *addr, switch (*(++fmt)) { case 'L': - uc = true; /* fall-through */ + uc = true; + fallthrough; case 'l': index = guid_index; break; @@ -2218,7 +2219,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, case 'S': case 's': ptr = dereference_symbol_descriptor(ptr); - /* Fallthrough */ + fallthrough; case 'B': return symbol_string(buf, end, ptr, spec, fmt); case 'R': @@ -2449,7 +2450,7 @@ qualifier: case 'x': spec->flags |= SMALL; - /* fall through */ + fallthrough; case 'X': spec->base = 16; @@ -2467,7 +2468,7 @@ qualifier: * utility, treat it as any other invalid or * unsupported format specifier. */ - /* Fall-through */ + fallthrough; default: WARN_ONCE(1, "Please remove unsupported %%%c in format string\n", *fmt); @@ -3410,10 +3411,10 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; case 'i': base = 0; - /* fall through */ + fallthrough; case 'd': is_sign = true; - /* fall through */ + fallthrough; case 'u': break; case '%': diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c index 9f336bc07ed6..ca2603abee08 100644 --- a/lib/xz/xz_dec_lzma2.c +++ b/lib/xz/xz_dec_lzma2.c @@ -1043,7 +1043,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.sequence = SEQ_LZMA_PREPARE; - /* Fall through */ + fallthrough; case SEQ_LZMA_PREPARE: if (s->lzma2.compressed < RC_INIT_BYTES) @@ -1055,7 +1055,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, s->lzma2.compressed -= RC_INIT_BYTES; s->lzma2.sequence = SEQ_LZMA_RUN; - /* Fall through */ + fallthrough; case SEQ_LZMA_RUN: /* diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c index bd1d182419d7..fea86deaaa01 100644 --- a/lib/xz/xz_dec_stream.c +++ b/lib/xz/xz_dec_stream.c @@ -583,7 +583,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) if (ret != XZ_OK) return ret; - /* Fall through */ + fallthrough; case SEQ_BLOCK_START: /* We need one byte of input to continue. */ @@ -608,7 +608,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->temp.pos = 0; s->sequence = SEQ_BLOCK_HEADER; - /* Fall through */ + fallthrough; case SEQ_BLOCK_HEADER: if (!fill_temp(s, b)) @@ -620,7 +620,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_UNCOMPRESS; - /* Fall through */ + fallthrough; case SEQ_BLOCK_UNCOMPRESS: ret = dec_block(s, b); @@ -629,7 +629,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_PADDING; - /* Fall through */ + fallthrough; case SEQ_BLOCK_PADDING: /* @@ -651,7 +651,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_BLOCK_CHECK; - /* Fall through */ + fallthrough; case SEQ_BLOCK_CHECK: if (s->check_type == XZ_CHECK_CRC32) { @@ -675,7 +675,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_INDEX_PADDING; - /* Fall through */ + fallthrough; case SEQ_INDEX_PADDING: while ((s->index.size + (b->in_pos - s->in_start)) @@ -699,7 +699,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->sequence = SEQ_INDEX_CRC32; - /* Fall through */ + fallthrough; case SEQ_INDEX_CRC32: ret = crc32_validate(s, b); @@ -709,7 +709,7 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) s->temp.size = STREAM_HEADER_SIZE; s->sequence = SEQ_STREAM_FOOTER; - /* Fall through */ + fallthrough; case SEQ_STREAM_FOOTER: if (!fill_temp(s, b)) diff --git a/lib/zstd/bitstream.h b/lib/zstd/bitstream.h index 3a49784d5c61..7c65c66e41fd 100644 --- a/lib/zstd/bitstream.h +++ b/lib/zstd/bitstream.h @@ -259,15 +259,15 @@ ZSTD_STATIC size_t BIT_initDStream(BIT_DStream_t *bitD, const void *srcBuffer, s bitD->bitContainer = *(const BYTE *)(bitD->start); switch (srcSize) { case 7: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[6]) << (sizeof(bitD->bitContainer) * 8 - 16); - /* fall through */ + fallthrough; case 6: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[5]) << (sizeof(bitD->bitContainer) * 8 - 24); - /* fall through */ + fallthrough; case 5: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[4]) << (sizeof(bitD->bitContainer) * 8 - 32); - /* fall through */ + fallthrough; case 4: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[3]) << 24; - /* fall through */ + fallthrough; case 3: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[2]) << 16; - /* fall through */ + fallthrough; case 2: bitD->bitContainer += (size_t)(((const BYTE *)(srcBuffer))[1]) << 8; default:; } diff --git a/lib/zstd/compress.c b/lib/zstd/compress.c index 5e0b67003e55..b080264ed3ad 100644 --- a/lib/zstd/compress.c +++ b/lib/zstd/compress.c @@ -3182,7 +3182,7 @@ static size_t ZSTD_compressStream_generic(ZSTD_CStream *zcs, void *dst, size_t * zcs->outBuffFlushedSize = 0; zcs->stage = zcss_flush; /* pass-through to flush stage */ } - /* fall through */ + fallthrough; case zcss_flush: { size_t const toFlush = zcs->outBuffContentSize - zcs->outBuffFlushedSize; diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c index 269ee9a796c1..66cd487a326a 100644 --- a/lib/zstd/decompress.c +++ b/lib/zstd/decompress.c @@ -442,7 +442,7 @@ size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize case set_repeat: if (dctx->litEntropy == 0) return ERROR(dictionary_corrupted); - /* fall-through */ + fallthrough; case set_compressed: if (srcSize < 5) return ERROR(corruption_detected); /* srcSize >= MIN_CBLOCK_SIZE == 3; here we need up to 5 for case 3 */ @@ -1768,7 +1768,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx *dctx, void *dst, size_t dstCapacity, c return 0; } dctx->expected = 0; /* not necessary to copy more */ - /* fall through */ + fallthrough; case ZSTDds_decodeFrameHeader: memcpy(dctx->headerBuffer + ZSTD_frameHeaderSize_prefix, src, dctx->expected); @@ -2309,7 +2309,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB switch (zds->stage) { case zdss_init: ZSTD_resetDStream(zds); /* transparent reset on starting decoding a new frame */ - /* fall-through */ + fallthrough; case zdss_loadHeader: { size_t const hSize = ZSTD_getFrameParams(&zds->fParams, zds->headerBuffer, zds->lhSize); @@ -2376,7 +2376,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB } zds->stage = zdss_read; } - /* fall through */ + fallthrough; case zdss_read: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); @@ -2405,7 +2405,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB zds->stage = zdss_load; /* pass-through */ } - /* fall through */ + fallthrough; case zdss_load: { size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zds->dctx); @@ -2438,7 +2438,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream *zds, ZSTD_outBuffer *output, ZSTD_inB /* pass-through */ } } - /* fall through */ + fallthrough; case zdss_flush: { size_t const toFlushSize = zds->outEnd - zds->outStart; diff --git a/lib/zstd/huf_compress.c b/lib/zstd/huf_compress.c index e727812d12aa..08b4ae80aed4 100644 --- a/lib/zstd/huf_compress.c +++ b/lib/zstd/huf_compress.c @@ -556,9 +556,9 @@ size_t HUF_compress1X_usingCTable(void *dst, size_t dstSize, const void *src, si n = srcSize & ~3; /* join to mod 4 */ switch (srcSize & 3) { case 3: HUF_encodeSymbol(&bitC, ip[n + 2], CTable); HUF_FLUSHBITS_2(&bitC); - /* fall through */ + fallthrough; case 2: HUF_encodeSymbol(&bitC, ip[n + 1], CTable); HUF_FLUSHBITS_1(&bitC); - /* fall through */ + fallthrough; case 1: HUF_encodeSymbol(&bitC, ip[n + 0], CTable); HUF_FLUSHBITS(&bitC); case 0: default:; diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 3dd7c972677b..ec8408d1638f 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -367,7 +367,7 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case SIOCSHWTSTAMP: if (!net_eq(dev_net(dev), &init_net)) break; - /* fall through */ + fallthrough; case SIOCGMIIPHY: case SIOCGMIIREG: case SIOCSMIIREG: diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c index 3debad93be1a..bc8807d9281f 100644 --- a/net/9p/trans_xen.c +++ b/net/9p/trans_xen.c @@ -520,7 +520,7 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev, case XenbusStateClosed: if (dev->state == XenbusStateClosed) break; - /* fall through - Missed the backend's CLOSING state */ + fallthrough; /* Missed the backend's CLOSING state */ case XenbusStateClosing: xenbus_frontend_closed(dev); break; diff --git a/net/atm/common.c b/net/atm/common.c index 84367b844b14..1cfa9bf1d187 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -297,7 +297,7 @@ static int adjust_tp(struct atm_trafprm *tp, unsigned char aal) break; default: pr_warn("AAL problems ... (%d)\n", aal); - /* fall through */ + fallthrough; case ATM_AAL5: max_sdu = ATM_MAX_AAL5_PDU; } @@ -417,7 +417,7 @@ static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi, case ATM_NO_AAL: /* ATM_AAL5 is also used in the "0 for default" case */ vcc->qos.aal = ATM_AAL5; - /* fall through */ + fallthrough; case ATM_AAL5: error = atm_init_aal5(vcc); vcc->stats = &dev->stats.aal5; diff --git a/net/atm/lec.c b/net/atm/lec.c index 875fc0bc1780..b570ef919c28 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -380,7 +380,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) if (mesg->content.normal.no_source_le_narp) break; - /* FALL THROUGH */ + fallthrough; case l_arp_update: lec_arp_update(priv, mesg->content.normal.mac_addr, mesg->content.normal.atm_addr, diff --git a/net/atm/resources.c b/net/atm/resources.c index 94bdc6527ee8..53236986dfe0 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c @@ -266,7 +266,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, goto done; } } - /* fall through */ + fallthrough; case ATM_SETESIF: { unsigned char esi[ESI_LEN]; @@ -288,7 +288,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, error = -EPERM; goto done; } - /* fall through */ + fallthrough; case ATM_GETSTAT: size = sizeof(struct atm_dev_stats); error = fetch_stats(dev, buf, cmd == ATM_GETSTATZ); @@ -361,7 +361,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, error = -EINVAL; goto done; } - /* fall through */ + fallthrough; case ATM_SETCIRANGE: case SONET_GETSTATZ: case SONET_SETDIAG: @@ -371,7 +371,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *buf, int __user *sioc_len, error = -EPERM; goto done; } - /* fall through */ + fallthrough; default: if (IS_ENABLED(CONFIG_COMPAT) && compat) { #ifdef CONFIG_COMPAT diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 99eb8c6c0fbc..a66f211726e7 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -425,7 +425,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, case BPF_PROG_TYPE_SCHED_CLS: case BPF_PROG_TYPE_SCHED_ACT: is_l2 = true; - /* fall through */ + fallthrough; case BPF_PROG_TYPE_LWT_IN: case BPF_PROG_TYPE_LWT_OUT: case BPF_PROG_TYPE_LWT_XMIT: diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c index b93876c57fc4..1be4c898b2fa 100644 --- a/net/can/j1939/socket.c +++ b/net/can/j1939/socket.c @@ -1086,7 +1086,7 @@ static int j1939_sk_send_loop(struct j1939_priv *priv, struct sock *sk, break; case -ERESTARTSYS: ret = -EINTR; - /* fall through */ + fallthrough; case -EAGAIN: /* OK */ if (todo_size != size) ret = size - todo_size; diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index a8dd956b5e8e..0cec4152f979 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -860,7 +860,7 @@ static int j1939_xtp_txnext_transmiter(struct j1939_session *session) return ret; } - /* fall through */ + fallthrough; case J1939_TP_CMD_CTS: case 0xff: /* did some data */ case J1939_ETP_CMD_DPO: @@ -1764,12 +1764,12 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, case J1939_ETP_CMD_DPO: if (skcb->addr.type == J1939_ETP) break; - /* fall through */ - case J1939_TP_CMD_BAM: /* fall through */ + fallthrough; + case J1939_TP_CMD_BAM: case J1939_TP_CMD_CTS: /* fall through */ if (skcb->addr.type != J1939_ETP) break; - /* fall through */ + fallthrough; default: netdev_info(priv->ndev, "%s: 0x%p: last %02x\n", __func__, session, session->last_cmd); @@ -1965,8 +1965,8 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) switch (cmd) { case J1939_ETP_CMD_RTS: extd = J1939_ETP; - /* fall through */ - case J1939_TP_CMD_BAM: /* fall through */ + fallthrough; + case J1939_TP_CMD_BAM: case J1939_TP_CMD_RTS: /* fall through */ if (skcb->addr.type != extd) return; @@ -1987,7 +1987,7 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) case J1939_ETP_CMD_CTS: extd = J1939_ETP; - /* fall through */ + fallthrough; case J1939_TP_CMD_CTS: if (skcb->addr.type != extd) return; @@ -2014,7 +2014,7 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) case J1939_ETP_CMD_EOMA: extd = J1939_ETP; - /* fall through */ + fallthrough; case J1939_TP_CMD_EOMA: if (skcb->addr.type != extd) return; @@ -2050,14 +2050,14 @@ int j1939_tp_recv(struct j1939_priv *priv, struct sk_buff *skb) switch (skcb->addr.pgn) { case J1939_ETP_PGN_DAT: skcb->addr.type = J1939_ETP; - /* fall through */ + fallthrough; case J1939_TP_PGN_DAT: j1939_xtp_rx_dat(priv, skb); break; case J1939_ETP_PGN_CTL: skcb->addr.type = J1939_ETP; - /* fall through */ + fallthrough; case J1939_TP_PGN_CTL: if (skb->len < 8) return 0; /* Don't care. Nothing to extract here */ diff --git a/net/ceph/ceph_hash.c b/net/ceph/ceph_hash.c index 81e1e006c540..16a47c0eef37 100644 --- a/net/ceph/ceph_hash.c +++ b/net/ceph/ceph_hash.c @@ -50,35 +50,35 @@ unsigned int ceph_str_hash_rjenkins(const char *str, unsigned int length) switch (len) { case 11: c = c + ((__u32)k[10] << 24); - /* fall through */ + fallthrough; case 10: c = c + ((__u32)k[9] << 16); - /* fall through */ + fallthrough; case 9: c = c + ((__u32)k[8] << 8); /* the first byte of c is reserved for the length */ - /* fall through */ + fallthrough; case 8: b = b + ((__u32)k[7] << 24); - /* fall through */ + fallthrough; case 7: b = b + ((__u32)k[6] << 16); - /* fall through */ + fallthrough; case 6: b = b + ((__u32)k[5] << 8); - /* fall through */ + fallthrough; case 5: b = b + k[4]; - /* fall through */ + fallthrough; case 4: a = a + ((__u32)k[3] << 24); - /* fall through */ + fallthrough; case 3: a = a + ((__u32)k[2] << 16); - /* fall through */ + fallthrough; case 2: a = a + ((__u32)k[1] << 8); - /* fall through */ + fallthrough; case 1: a = a + k[0]; /* case 0: nothing left to add */ diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index 07e5614eb3f1..7057f8db4f99 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -987,7 +987,7 @@ int crush_do_rule(const struct crush_map *map, case CRUSH_RULE_CHOOSELEAF_FIRSTN: case CRUSH_RULE_CHOOSE_FIRSTN: firstn = 1; - /* fall through */ + fallthrough; case CRUSH_RULE_CHOOSELEAF_INDEP: case CRUSH_RULE_CHOOSE_INDEP: if (wsize == 0) diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 27d6ab11f9ee..bdfd66ba3843 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -412,7 +412,7 @@ static void ceph_sock_state_change(struct sock *sk) switch (sk->sk_state) { case TCP_CLOSE: dout("%s TCP_CLOSE\n", __func__); - /* fall through */ + fallthrough; case TCP_CLOSE_WAIT: dout("%s TCP_CLOSE_WAIT\n", __func__); con_sock_state_closing(con); @@ -2751,7 +2751,7 @@ more: switch (ret) { case -EBADMSG: con->error_msg = "bad crc/signature"; - /* fall through */ + fallthrough; case -EBADE: ret = -EIO; break; diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 3d8c8015e976..d633a0aeaa55 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -1307,7 +1307,7 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, * request had a non-zero tid. Work around this weirdness * by allocating a new message. */ - /* fall through */ + fallthrough; case CEPH_MSG_MON_MAP: case CEPH_MSG_MDS_MAP: case CEPH_MSG_OSD_MAP: diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index e4fbcad6e7d8..7901ab6c79fd 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -3854,7 +3854,7 @@ static void scan_requests(struct ceph_osd *osd, if (!force_resend && !force_resend_writes) break; - /* fall through */ + fallthrough; case CALC_TARGET_NEED_RESEND: cancel_linger_map_check(lreq); /* @@ -3891,7 +3891,7 @@ static void scan_requests(struct ceph_osd *osd, !force_resend_writes)) break; - /* fall through */ + fallthrough; case CALC_TARGET_NEED_RESEND: cancel_map_check(req); unlink_request(osd, req); diff --git a/net/core/dev.c b/net/core/dev.c index d42c9ea0c3c0..b9c6f31ae96e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4690,10 +4690,10 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, break; default: bpf_warn_invalid_xdp_action(act); - /* fall through */ + fallthrough; case XDP_ABORTED: trace_xdp_exception(skb->dev, xdp_prog, act); - /* fall through */ + fallthrough; case XDP_DROP: do_drop: kfree_skb(skb); diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c index b2cf9b7bb7b8..205e92e604ef 100644 --- a/net/core/dev_ioctl.c +++ b/net/core/dev_ioctl.c @@ -322,7 +322,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) err = net_hwtstamp_validate(ifr); if (err) return err; - /* fall through */ + fallthrough; /* * Unknown or private ioctl @@ -478,7 +478,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_c case SIOCSIFTXQLEN: if (!capable(CAP_NET_ADMIN)) return -EPERM; - /* fall through */ + fallthrough; /* * These ioctl calls: * - require local superuser power. @@ -503,7 +503,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_c case SIOCSHWTSTAMP: if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) return -EPERM; - /* fall through */ + fallthrough; case SIOCBONDSLAVEINFOQUERY: case SIOCBONDINFOQUERY: dev_load(net, ifr->ifr_name); diff --git a/net/core/devlink.c b/net/core/devlink.c index e5feb87beca7..80ec1cd81c64 100644 --- a/net/core/devlink.c +++ b/net/core/devlink.c @@ -6196,8 +6196,8 @@ devlink_trap_action_get_from_info(struct genl_info *info, val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]); switch (val) { - case DEVLINK_TRAP_ACTION_DROP: /* fall-through */ - case DEVLINK_TRAP_ACTION_TRAP: /* fall-through */ + case DEVLINK_TRAP_ACTION_DROP: + case DEVLINK_TRAP_ACTION_TRAP: case DEVLINK_TRAP_ACTION_MIRROR: *p_trap_action = val; break; diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b09bebeadf0b..9704522b0872 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -1189,7 +1189,7 @@ static int net_dm_alert_mode_get_from_info(struct genl_info *info, val = nla_get_u8(info->attrs[NET_DM_ATTR_ALERT_MODE]); switch (val) { - case NET_DM_ALERT_MODE_SUMMARY: /* fall-through */ + case NET_DM_ALERT_MODE_SUMMARY: case NET_DM_ALERT_MODE_PACKET: *p_alert_mode = val; break; diff --git a/net/core/filter.c b/net/core/filter.c index b2df52086445..1f647ab986b6 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -9223,7 +9223,7 @@ sk_reuseport_is_valid_access(int off, int size, case bpf_ctx_range(struct sk_reuseport_md, eth_protocol): if (size < sizeof_field(struct sk_buff, protocol)) return false; - /* fall through */ + fallthrough; case bpf_ctx_range(struct sk_reuseport_md, ip_protocol): case bpf_ctx_range(struct sk_reuseport_md, bind_inany): case bpf_ctx_range(struct sk_reuseport_md, len): diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b53b6d38c4df..95f4c6b8f51a 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3430,7 +3430,7 @@ xmit_more: net_info_ratelimited("%s xmit error: %d\n", pkt_dev->odevname, ret); pkt_dev->errors++; - /* fall through */ + fallthrough; case NETDEV_TX_BUSY: /* Retry it next time */ refcount_dec(&(pkt_dev->skb->users)); diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 6a32a1fd34f8..649583158983 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -772,7 +772,6 @@ static void sk_psock_verdict_apply(struct sk_psock *psock, sk_psock_skb_redirect(skb); break; case __SK_DROP: - /* fall-through */ default: out_free: kfree_skb(skb); diff --git a/net/core/sock.c b/net/core/sock.c index e4f40b175acb..f8e5ccc45272 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1008,7 +1008,7 @@ set_sndbuf: break; case SO_TIMESTAMPING_NEW: sock_set_flag(sk, SOCK_TSTAMP_NEW); - /* fall through */ + fallthrough; case SO_TIMESTAMPING_OLD: if (val & ~SOF_TIMESTAMPING_MASK) { ret = -EINVAL; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index aef72f6a2829..b9ee1a4a8955 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -608,7 +608,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, */ if (hc->rx_x_recv > 0) break; - /* fall through */ + fallthrough; case CCID3_FBACK_PERIODIC: delta = ktime_us_delta(now, hc->rx_tstamp_last_feedback); if (delta <= 0) diff --git a/net/dccp/feat.c b/net/dccp/feat.c index afc071ea1271..788dd629c420 100644 --- a/net/dccp/feat.c +++ b/net/dccp/feat.c @@ -1407,7 +1407,8 @@ int dccp_feat_parse_options(struct sock *sk, struct dccp_request_sock *dreq, * Negotiation during connection setup */ case DCCP_LISTEN: - server = true; /* fall through */ + server = true; + fallthrough; case DCCP_REQUESTING: switch (opt) { case DCCPO_CHANGE_L: diff --git a/net/dccp/input.c b/net/dccp/input.c index bd9cfdb67436..2cbb757a894f 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -64,7 +64,7 @@ static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb) */ if (dccp_sk(sk)->dccps_role != DCCP_ROLE_CLIENT) break; - /* fall through */ + fallthrough; case DCCP_REQUESTING: case DCCP_ACTIVE_CLOSEREQ: dccp_send_reset(sk, DCCP_RESET_CODE_CLOSED); @@ -76,7 +76,7 @@ static int dccp_rcv_close(struct sock *sk, struct sk_buff *skb) queued = 1; dccp_fin(sk, skb); dccp_set_state(sk, DCCP_PASSIVE_CLOSE); - /* fall through */ + fallthrough; case DCCP_PASSIVE_CLOSE: /* * Retransmitted Close: we have already enqueued the first one. @@ -113,7 +113,7 @@ static int dccp_rcv_closereq(struct sock *sk, struct sk_buff *skb) queued = 1; dccp_fin(sk, skb); dccp_set_state(sk, DCCP_PASSIVE_CLOSEREQ); - /* fall through */ + fallthrough; case DCCP_PASSIVE_CLOSEREQ: sk_wake_async(sk, SOCK_WAKE_WAITD, POLL_HUP); } @@ -530,7 +530,7 @@ static int dccp_rcv_respond_partopen_state_process(struct sock *sk, case DCCP_PKT_DATA: if (sk->sk_state == DCCP_RESPOND) break; - /* fall through */ + fallthrough; case DCCP_PKT_DATAACK: case DCCP_PKT_ACK: /* @@ -684,7 +684,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* Step 8: if using Ack Vectors, mark packet acknowledgeable */ dccp_handle_ackvec_processing(sk, skb); dccp_deliver_input_to_ccids(sk, skb); - /* fall through */ + fallthrough; case DCCP_RESPOND: queued = dccp_rcv_respond_partopen_state_process(sk, skb, dh, len); diff --git a/net/dccp/options.c b/net/dccp/options.c index 51aaba7a5d45..d24cad05001e 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c @@ -225,7 +225,7 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, * interested. The RX CCID need not parse Ack Vectors, * since it is only interested in clearing old state. */ - /* fall through */ + fallthrough; case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC: if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, pkt_type, opt, value, len)) diff --git a/net/dccp/output.c b/net/dccp/output.c index 6433187a5cc4..50e6d5699bb2 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c @@ -62,7 +62,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) switch (dcb->dccpd_type) { case DCCP_PKT_DATA: set_ack = 0; - /* fall through */ + fallthrough; case DCCP_PKT_DATAACK: case DCCP_PKT_RESET: break; @@ -72,12 +72,12 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) /* Use ISS on the first (non-retransmitted) Request. */ if (icsk->icsk_retransmits == 0) dcb->dccpd_seq = dp->dccps_iss; - /* fall through */ + fallthrough; case DCCP_PKT_SYNC: case DCCP_PKT_SYNCACK: ackno = dcb->dccpd_ack_seq; - /* fall through */ + fallthrough; default: /* * Set owner/destructor: some skbs are allocated via @@ -481,7 +481,7 @@ struct sk_buff *dccp_ctl_make_reset(struct sock *sk, struct sk_buff *rcv_skb) case DCCP_RESET_CODE_PACKET_ERROR: dhr->dccph_reset_data[0] = rxdh->dccph_type; break; - case DCCP_RESET_CODE_OPTION_ERROR: /* fall through */ + case DCCP_RESET_CODE_OPTION_ERROR: case DCCP_RESET_CODE_MANDATORY_ERROR: memcpy(dhr->dccph_reset_data, dcb->dccpd_reset_data, 3); break; diff --git a/net/dccp/proto.c b/net/dccp/proto.c index d148ab1530e5..6d705d90c614 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -101,7 +101,7 @@ void dccp_set_state(struct sock *sk, const int state) if (inet_csk(sk)->icsk_bind_hash != NULL && !(sk->sk_userlocks & SOCK_BINDPORT_LOCK)) inet_put_port(sk); - /* fall through */ + fallthrough; default: if (oldstate == DCCP_OPEN) DCCP_DEC_STATS(DCCP_MIB_CURRESTAB); @@ -834,7 +834,7 @@ int dccp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock, case DCCP_PKT_CLOSEREQ: if (!(flags & MSG_PEEK)) dccp_finish_passive_close(sk); - /* fall through */ + fallthrough; case DCCP_PKT_RESET: dccp_pr_debug("found fin (%s) ok!\n", dccp_packet_name(dh->dccph_type)); @@ -960,7 +960,7 @@ static void dccp_terminate_connection(struct sock *sk) case DCCP_PARTOPEN: dccp_pr_debug("Stop PARTOPEN timer (%p)\n", sk); inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); - /* fall through */ + fallthrough; case DCCP_OPEN: dccp_send_close(sk, 1); @@ -969,7 +969,7 @@ static void dccp_terminate_connection(struct sock *sk) next_state = DCCP_ACTIVE_CLOSEREQ; else next_state = DCCP_CLOSING; - /* fall through */ + fallthrough; default: dccp_set_state(sk, next_state); } diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 3b53d766789d..5dbd45dc35ad 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -623,12 +623,12 @@ static void dn_destroy_sock(struct sock *sk) goto disc_reject; case DN_RUN: scp->state = DN_DI; - /* fall through */ + fallthrough; case DN_DI: case DN_DR: disc_reject: dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation); - /* fall through */ + fallthrough; case DN_NC: case DN_NR: case DN_RJ: @@ -642,7 +642,7 @@ disc_reject: break; default: printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n"); - /* fall through */ + fallthrough; case DN_O: dn_stop_slow_timer(sk); diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index c68503a18025..c97bdca5ec30 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c @@ -483,7 +483,7 @@ static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb) break; case DN_RUN: sk->sk_shutdown |= SHUTDOWN_MASK; - /* fall through */ + fallthrough; case DN_CC: scp->state = DN_CN; } diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 33fefb0aebca..4086f9c746af 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c @@ -156,7 +156,7 @@ static void dn_rehash_zone(struct dn_zone *dz) default: printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n", old_divisor); - /* fall through */ + fallthrough; case 256: new_divisor = 1024; new_hashmask = 0x3FF; diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index deae519bdeec..67b5ab2657b7 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c @@ -75,7 +75,7 @@ static void strip_it(char *str) case '\r': case ':': *str = 0; - /* Fallthrough */ + fallthrough; case 0: return; } diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 41d60eeefdbd..9af1a2d0cec4 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -2009,7 +2009,7 @@ static int dsa_slave_switchdev_event(struct notifier_block *unused, switchdev_work->event = event; switch (event) { - case SWITCHDEV_FDB_ADD_TO_DEVICE: /* fall through */ + case SWITCHDEV_FDB_ADD_TO_DEVICE: case SWITCHDEV_FDB_DEL_TO_DEVICE: if (dsa_slave_switchdev_fdb_work_init(switchdev_work, ptr)) goto err_fdb_work_init; diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index bbe9b3b2d395..be6f06adefe0 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c @@ -195,7 +195,7 @@ static int lowpan_frag_rx_handlers_result(struct sk_buff *skb, net_warn_ratelimited("%s: received unknown dispatch\n", __func__); - /* fall-through */ + fallthrough; default: /* all others failure */ return NET_RX_DROP; diff --git a/net/ieee802154/6lowpan/rx.c b/net/ieee802154/6lowpan/rx.c index b34d050c9687..517e6493f5d1 100644 --- a/net/ieee802154/6lowpan/rx.c +++ b/net/ieee802154/6lowpan/rx.c @@ -35,11 +35,11 @@ static int lowpan_rx_handlers_result(struct sk_buff *skb, lowpan_rx_result res) net_warn_ratelimited("%s: received unknown dispatch\n", __func__); - /* fall-through */ + fallthrough; case RX_DROP_UNUSABLE: kfree_skb(skb); - /* fall-through */ + fallthrough; case RX_DROP: return NET_RX_DROP; case RX_QUEUED: diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 6ee9851ac7c6..a95af62acb52 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -418,7 +418,7 @@ static void iucv_sock_close(struct sock *sk) sk->sk_state = IUCV_DISCONN; sk->sk_state_change(sk); } - /* fall through */ + fallthrough; case IUCV_DISCONN: sk->sk_state = IUCV_CLOSING; @@ -433,7 +433,7 @@ static void iucv_sock_close(struct sock *sk) iucv_sock_in_state(sk, IUCV_CLOSED, 0), timeo); } - /* fall through */ + fallthrough; case IUCV_CLOSING: sk->sk_state = IUCV_CLOSED; @@ -444,7 +444,7 @@ static void iucv_sock_close(struct sock *sk) skb_queue_purge(&iucv->send_skb_q); skb_queue_purge(&iucv->backlog_skb_q); - /* fall through */ + fallthrough; default: iucv_sever_path(sk, 1); @@ -2111,10 +2111,10 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, kfree_skb(skb); break; } - /* fall through - and receive non-zero length data */ + fallthrough; /* and receive non-zero length data */ case (AF_IUCV_FLAG_SHT): /* shutdown request */ - /* fall through - and receive zero length data */ + fallthrough; /* and receive zero length data */ case 0: /* plain data frame */ IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class; diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c index 6fdd0c9f865a..f2868a8a50c3 100644 --- a/net/mpls/af_mpls.c +++ b/net/mpls/af_mpls.c @@ -1516,7 +1516,7 @@ static void mpls_ifdown(struct net_device *dev, int event) case NETDEV_DOWN: case NETDEV_UNREGISTER: nh_flags |= RTNH_F_DEAD; - /* fall through */ + fallthrough; case NETDEV_CHANGE: nh_flags |= RTNH_F_LINKDOWN; break; diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 1aad411a0e46..49b815023986 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -193,7 +193,6 @@ static void mptcp_check_data_fin_ack(struct sock *sk) sk->sk_state_change(sk); break; case TCP_CLOSING: - fallthrough; case TCP_LAST_ACK: inet_sk_state_store(sk, TCP_CLOSE); sk->sk_state_change(sk); @@ -1541,7 +1540,7 @@ static void mptcp_subflow_shutdown(struct sock *sk, struct sock *ssk, int how) case TCP_LISTEN: if (!(how & RCV_SHUTDOWN)) break; - /* fall through */ + fallthrough; case TCP_SYN_SENT: tcp_disconnect(ssk, O_NONBLOCK); break; diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index 1f387be7827b..f1be3e3f6425 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c @@ -474,7 +474,7 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp) switch (nd->state) { case ncsi_dev_state_suspend: nd->state = ncsi_dev_state_suspend_select; - /* Fall through */ + fallthrough; case ncsi_dev_state_suspend_select: ndp->pending_req_num = 1; @@ -1302,7 +1302,7 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp) switch (nd->state) { case ncsi_dev_state_probe: nd->state = ncsi_dev_state_probe_deselect; - /* Fall through */ + fallthrough; case ncsi_dev_state_probe_deselect: ndp->pending_req_num = 8; diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c index 32b028853a7c..dc2e7da2742a 100644 --- a/net/netfilter/ipvs/ip_vs_proto_tcp.c +++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c @@ -315,7 +315,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) switch (skb->ip_summed) { case CHECKSUM_NONE: skb->csum = skb_checksum(skb, tcphoff, skb->len - tcphoff, 0); - /* fall through */ + fallthrough; case CHECKSUM_COMPLETE: #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { diff --git a/net/netfilter/ipvs/ip_vs_proto_udp.c b/net/netfilter/ipvs/ip_vs_proto_udp.c index 153d89647c87..68260d91c988 100644 --- a/net/netfilter/ipvs/ip_vs_proto_udp.c +++ b/net/netfilter/ipvs/ip_vs_proto_udp.c @@ -318,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp) case CHECKSUM_NONE: skb->csum = skb_checksum(skb, udphoff, skb->len - udphoff, 0); - /* fall through */ + fallthrough; case CHECKSUM_COMPLETE: #ifdef CONFIG_IP_VS_IPV6 if (af == AF_INET6) { diff --git a/net/netlink/policy.c b/net/netlink/policy.c index 2b3e26f7496f..641ffbdd977a 100644 --- a/net/netlink/policy.c +++ b/net/netlink/policy.c @@ -188,7 +188,7 @@ send_attribute: goto next; case NLA_NESTED: type = NL_ATTR_TYPE_NESTED; - /* fall through */ + fallthrough; case NLA_NESTED_ARRAY: if (pt->type == NLA_NESTED_ARRAY) type = NL_ATTR_TYPE_NESTED_ARRAY; diff --git a/net/netrom/nr_in.c b/net/netrom/nr_in.c index 2bef3779f893..69e58906c32b 100644 --- a/net/netrom/nr_in.c +++ b/net/netrom/nr_in.c @@ -122,7 +122,7 @@ static int nr_state2_machine(struct sock *sk, struct sk_buff *skb, case NR_DISCREQ: nr_write_internal(sk, NR_DISCACK); - /* fall through */ + fallthrough; case NR_DISCACK: nr_disconnect(sk, 0); break; diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index 0891ee02ca4f..78da5eab252a 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -263,7 +263,7 @@ static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic, case 3: re_sort_routes(nr_node, 0, 1); re_sort_routes(nr_node, 1, 2); - /* fall through */ + fallthrough; case 2: re_sort_routes(nr_node, 0, 1); case 1: @@ -356,7 +356,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n switch (i) { case 0: nr_node->routes[0] = nr_node->routes[1]; - /* fall through */ + fallthrough; case 1: nr_node->routes[1] = nr_node->routes[2]; case 2: @@ -479,7 +479,7 @@ static int nr_dec_obs(void) switch (i) { case 0: s->routes[0] = s->routes[1]; - /* Fallthrough */ + fallthrough; case 1: s->routes[1] = s->routes[2]; case 2: @@ -526,7 +526,7 @@ void nr_rt_device_down(struct net_device *dev) switch (i) { case 0: t->routes[0] = t->routes[1]; - /* fall through */ + fallthrough; case 1: t->routes[1] = t->routes[2]; case 2: diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 98d393e70de3..a3f1204f1ed2 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -778,7 +778,7 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct, } } /* Non-ICMP, fall thru to initialize if needed. */ - /* fall through */ + fallthrough; case IP_CT_NEW: /* Seen it before? This can happen for loopback, retrans, * or local packets. @@ -1540,7 +1540,7 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, switch (type) { case OVS_CT_ATTR_FORCE_COMMIT: info->force = true; - /* fall through. */ + fallthrough; case OVS_CT_ATTR_COMMIT: info->commit = true; break; diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index 03942c30d83e..b03d142ec82e 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c @@ -675,7 +675,7 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) case -EINVAL: memset(&key->ip, 0, sizeof(key->ip)); memset(&key->ipv6.addr, 0, sizeof(key->ipv6.addr)); - /* fall-through */ + fallthrough; case -EPROTO: skb->transport_header = skb->network_header; error = 0; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 479c257ded73..da8254e680f9 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -4061,7 +4061,7 @@ static int packet_notifier(struct notifier_block *this, case NETDEV_UNREGISTER: if (po->mclist) packet_dev_mclist_delete(dev, &po->mclist); - /* fallthrough */ + fallthrough; case NETDEV_DOWN: if (dev->ifindex == po->ifindex) { diff --git a/net/phonet/pep.c b/net/phonet/pep.c index e47d09aca4af..a1525916885a 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -368,7 +368,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) err = -EINVAL; goto out; } - /* fall through */ + fallthrough; case PNS_PEP_DISABLE_REQ: atomic_set(&pn->tx_credits, 0); pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC); @@ -385,7 +385,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) case PNS_PIPE_ALIGNED_DATA: __skb_pull(skb, 1); - /* fall through */ + fallthrough; case PNS_PIPE_DATA: __skb_pull(skb, 3); /* Pipe data header */ if (!pn_flow_safe(pn->rx_fc)) { @@ -417,11 +417,11 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb) err = pipe_rcv_created(sk, skb); if (err) break; - /* fall through */ + fallthrough; case PNS_PIPE_RESET_IND: if (!pn->init_enable) break; - /* fall through */ + fallthrough; case PNS_PIPE_ENABLED_IND: if (!pn_flow_safe(pn->tx_fc)) { atomic_set(&pn->tx_credits, 1); @@ -555,7 +555,7 @@ static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) switch (hdr->message_id) { case PNS_PIPE_ALIGNED_DATA: __skb_pull(skb, 1); - /* fall through */ + fallthrough; case PNS_PIPE_DATA: __skb_pull(skb, 3); /* Pipe data header */ if (!pn_flow_safe(pn->rx_fc)) { diff --git a/net/rds/send.c b/net/rds/send.c index 9a529a01cdc6..985d0b7713ac 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -934,7 +934,7 @@ static int rds_rm_size(struct msghdr *msg, int num_sgs, case RDS_CMSG_ZCOPY_COOKIE: zcopy_cookie = true; - /* fall through */ + fallthrough; case RDS_CMSG_RDMA_DEST: case RDS_CMSG_RDMA_MAP: diff --git a/net/rose/rose_in.c b/net/rose/rose_in.c index 0d4fab2be82b..6af786d66b03 100644 --- a/net/rose/rose_in.c +++ b/net/rose/rose_in.c @@ -216,7 +216,7 @@ static int rose_state4_machine(struct sock *sk, struct sk_buff *skb, int framety switch (frametype) { case ROSE_RESET_REQUEST: rose_write_internal(sk, ROSE_RESET_CONFIRMATION); - /* fall through */ + fallthrough; case ROSE_RESET_CONFIRMATION: rose_stop_timer(sk); rose_start_idletimer(sk); diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 5277631fa14c..6e35703ff353 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -343,7 +343,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, case 0: rose_node->neighbour[0] = rose_node->neighbour[1]; - /* fall through */ + fallthrough; case 1: rose_node->neighbour[1] = rose_node->neighbour[2]; @@ -505,7 +505,7 @@ void rose_rt_device_down(struct net_device *dev) switch (i) { case 0: t->neighbour[0] = t->neighbour[1]; - /* fall through */ + fallthrough; case 1: t->neighbour[1] = t->neighbour[2]; case 2: diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index e6725a6de015..186c8a889b16 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -246,7 +246,7 @@ static int rxrpc_listen(struct socket *sock, int backlog) ret = 0; break; } - /* Fall through */ + fallthrough; default: ret = -EBUSY; break; @@ -545,7 +545,7 @@ static int rxrpc_sendmsg(struct socket *sock, struct msghdr *m, size_t len) rx->local = local; rx->sk.sk_state = RXRPC_CLIENT_BOUND; - /* Fall through */ + fallthrough; case RXRPC_CLIENT_BOUND: if (!m->msg_name && @@ -553,7 +553,7 @@ static int rxrpc_sendmsg(struct socket *sock, struct msghdr *m, size_t len) m->msg_name = &rx->connect_srx; m->msg_namelen = sizeof(rx->connect_srx); } - /* Fall through */ + fallthrough; case RXRPC_SERVER_BOUND: case RXRPC_SERVER_LISTENING: ret = rxrpc_do_sendmsg(rx, m, len); diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c index 032ed76c0166..ef160566aa9a 100644 --- a/net/rxrpc/call_accept.c +++ b/net/rxrpc/call_accept.c @@ -622,7 +622,7 @@ int rxrpc_reject_call(struct rxrpc_sock *rx) case RXRPC_CALL_SERVER_ACCEPTING: __rxrpc_abort_call("REJ", call, 1, RX_USER_ABORT, -ECONNABORTED); abort = true; - /* fall through */ + fallthrough; case RXRPC_CALL_COMPLETE: ret = call->error; goto out_discard; diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index f2a1a5dbb5a7..159e3eda7914 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c @@ -881,7 +881,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *call) conn->cache_state = RXRPC_CONN_CLIENT_ACTIVE; rxrpc_activate_channels_locked(conn); } - /* fall through */ + fallthrough; case RXRPC_CONN_CLIENT_ACTIVE: if (list_empty(&conn->waiting_calls)) { rxrpc_deactivate_one_channel(conn, channel); diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 767579328a06..fbde8b824e23 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c @@ -1084,7 +1084,7 @@ static void rxrpc_input_implicit_end_call(struct rxrpc_sock *rx, switch (READ_ONCE(call->state)) { case RXRPC_CALL_SERVER_AWAIT_ACK: rxrpc_call_completed(call); - /* Fall through */ + fallthrough; case RXRPC_CALL_COMPLETE: break; default: @@ -1243,12 +1243,12 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) case RXRPC_PACKET_TYPE_BUSY: if (rxrpc_to_server(sp)) goto discard; - /* Fall through */ + fallthrough; case RXRPC_PACKET_TYPE_ACK: case RXRPC_PACKET_TYPE_ACKALL: if (sp->hdr.callNumber == 0) goto bad_message; - /* Fall through */ + fallthrough; case RXRPC_PACKET_TYPE_ABORT: break; diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index c8b2097f499c..ede058f9cc15 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c @@ -162,7 +162,7 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net) /* Fall through and set IPv4 options too otherwise we don't get * errors from IPv4 packets sent through the IPv6 socket. */ - /* Fall through */ + fallthrough; case AF_INET: /* we want to receive ICMP errors */ ip_sock_set_recverr(local->socket->sk); diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index a852f46d5234..be032850ae8c 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c @@ -273,7 +273,7 @@ static void rxrpc_store_error(struct rxrpc_peer *peer, case SO_EE_ORIGIN_ICMP6: if (err == EACCES) err = EHOSTUNREACH; - /* Fall through */ + fallthrough; default: _proto("Rx Received error report { orig=%u }", ee->ee_origin); break; diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index efecc5a8f67d..c4684dde1f16 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -776,7 +776,7 @@ out: case RXRPC_ACK_DELAY: if (ret != -EAGAIN) break; - /* Fall through */ + fallthrough; default: rxrpc_send_ack_packet(call, false, NULL); } diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index f3f6da6e4ad2..0824e103d037 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -241,7 +241,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, trace_rxrpc_timer(call, rxrpc_timer_init_for_send_reply, now); if (!last) break; - /* Fall through */ + fallthrough; case RXRPC_CALL_SERVER_SEND_REPLY: call->state = RXRPC_CALL_SERVER_AWAIT_ACK; rxrpc_notify_end_tx(rx, call, notify_end_tx); @@ -721,13 +721,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) if (p.call.timeouts.normal > 0 && j == 0) j = 1; WRITE_ONCE(call->next_rx_timo, j); - /* Fall through */ + fallthrough; case 2: j = msecs_to_jiffies(p.call.timeouts.idle); if (p.call.timeouts.idle > 0 && j == 0) j = 1; WRITE_ONCE(call->next_req_timo, j); - /* Fall through */ + fallthrough; case 1: if (p.call.timeouts.hard > 0) { j = msecs_to_jiffies(p.call.timeouts.hard); diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c index 0618b63f87c4..7d37638ee1c7 100644 --- a/net/sched/sch_cake.c +++ b/net/sched/sch_cake.c @@ -1670,7 +1670,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, case TC_ACT_QUEUED: case TC_ACT_TRAP: *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; - /* fall through */ + fallthrough; case TC_ACT_SHOT: return 0; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index aea2a982984d..8a58f42d6d19 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -875,7 +875,7 @@ static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp) case AF_INET: if (!__ipv6_only_sock(sctp_opt2sk(sp))) return 1; - /* fallthru */ + fallthrough; default: return 0; } diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 577e3bc4ee6f..3fd06a27105d 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -912,7 +912,7 @@ static void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx) case SCTP_CID_ABORT: if (sctp_test_T_bit(chunk)) ctx->packet->vtag = ctx->asoc->c.my_vtag; - /* fallthru */ + fallthrough; /* The following chunks are "response" chunks, i.e. * they are generated in response to something we @@ -927,7 +927,7 @@ static void sctp_outq_flush_ctrl(struct sctp_flush_ctx *ctx) case SCTP_CID_ECN_CWR: case SCTP_CID_ASCONF_ACK: one_packet = 1; - /* Fall through */ + fallthrough; case SCTP_CID_SACK: case SCTP_CID_HEARTBEAT: @@ -1030,7 +1030,7 @@ static void sctp_outq_flush_data(struct sctp_flush_ctx *ctx, if (!ctx->packet || !ctx->packet->has_cookie_echo) return; - /* fall through */ + fallthrough; case SCTP_STATE_ESTABLISHED: case SCTP_STATE_SHUTDOWN_PENDING: case SCTP_STATE_SHUTDOWN_RECEIVED: diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 47910470e532..c11c24524652 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2077,7 +2077,7 @@ static enum sctp_ierror sctp_process_unk_param( break; case SCTP_PARAM_ACTION_DISCARD_ERR: retval = SCTP_IERROR_ERROR; - /* Fall through */ + fallthrough; case SCTP_PARAM_ACTION_SKIP_ERR: /* Make an ERROR chunk, preparing enough room for * returning multiple unknown parameters. diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 9f36fe911d08..aa821e71f05e 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1516,7 +1516,7 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type, if (timer_pending(timer)) break; - /* fall through */ + fallthrough; case SCTP_CMD_TIMER_START: timer = &asoc->timers[cmd->obj.to]; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index e86620fbd90f..c669f8bd1eab 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -4315,7 +4315,7 @@ enum sctp_disposition sctp_sf_eat_auth(struct net *net, sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(err_chunk)); } - /* Fall Through */ + fallthrough; case SCTP_IERROR_AUTH_BAD_KEYID: case SCTP_IERROR_BAD_SIG: return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); diff --git a/net/smc/smc_close.c b/net/smc/smc_close.c index 290270c821ca..3b5c374c6d2c 100644 --- a/net/smc/smc_close.c +++ b/net/smc/smc_close.c @@ -372,7 +372,7 @@ static void smc_close_passive_work(struct work_struct *work) case SMC_PEERCLOSEWAIT1: if (rxflags->peer_done_writing) sk->sk_state = SMC_PEERCLOSEWAIT2; - /* fall through */ + fallthrough; /* to check for closing */ case SMC_PEERCLOSEWAIT2: if (!smc_cdc_rxed_any_close(conn)) diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 90b8329fef82..8b300b74a722 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -137,7 +137,7 @@ gss_krb5_make_confounder(char *p, u32 conflen) switch (conflen) { case 16: *q++ = i++; - /* fall through */ + fallthrough; case 8: *q++ = i++; break; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index a91d1cdad9d7..62e0b6c1e8cf 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1702,7 +1702,7 @@ call_reserveresult(struct rpc_task *task) switch (status) { case -ENOMEM: rpc_delay(task, HZ >> 2); - /* fall through */ + fallthrough; case -EAGAIN: /* woken up; retry */ task->tk_action = call_retry_reserve; return; @@ -1759,13 +1759,13 @@ call_refreshresult(struct rpc_task *task) /* Use rate-limiting and a max number of retries if refresh * had status 0 but failed to update the cred. */ - /* fall through */ + fallthrough; case -ETIMEDOUT: rpc_delay(task, 3*HZ); - /* fall through */ + fallthrough; case -EAGAIN: status = -EACCES; - /* fall through */ + fallthrough; case -EKEYEXPIRED: if (!task->tk_cred_retry) break; @@ -2132,7 +2132,7 @@ call_connect_status(struct rpc_task *task) rpc_force_rebind(clnt); goto out_retry; } - /* fall through */ + fallthrough; case -ECONNRESET: case -ECONNABORTED: case -ENETDOWN: @@ -2146,7 +2146,7 @@ call_connect_status(struct rpc_task *task) break; /* retry with existing socket, after a delay */ rpc_delay(task, 3*HZ); - /* fall through */ + fallthrough; case -EADDRINUSE: case -ENOTCONN: case -EAGAIN: @@ -2228,7 +2228,7 @@ call_transmit_status(struct rpc_task *task) */ case -ENOBUFS: rpc_delay(task, HZ>>2); - /* fall through */ + fallthrough; case -EBADSLT: case -EAGAIN: task->tk_action = call_transmit; @@ -2247,7 +2247,7 @@ call_transmit_status(struct rpc_task *task) rpc_call_rpcerror(task, task->tk_status); return; } - /* fall through */ + fallthrough; case -ECONNRESET: case -ECONNABORTED: case -EADDRINUSE: @@ -2313,7 +2313,7 @@ call_bc_transmit_status(struct rpc_task *task) break; case -ENOBUFS: rpc_delay(task, HZ>>2); - /* fall through */ + fallthrough; case -EBADSLT: case -EAGAIN: task->tk_status = 0; @@ -2380,7 +2380,7 @@ call_status(struct rpc_task *task) * were a timeout. */ rpc_delay(task, 3*HZ); - /* fall through */ + fallthrough; case -ETIMEDOUT: break; case -ECONNREFUSED: @@ -2391,7 +2391,7 @@ call_status(struct rpc_task *task) break; case -EADDRINUSE: rpc_delay(task, 3*HZ); - /* fall through */ + fallthrough; case -EPIPE: case -EAGAIN: break; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 6ba9d5842629..5a8e47bbfb9f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -1623,7 +1623,7 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) case -EAGAIN: xprt_add_backlog(xprt, task); dprintk("RPC: waiting for request slot\n"); - /* fall through */ + fallthrough; default: task->tk_status = -EAGAIN; } diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 75c646743df3..3f86d039875c 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c @@ -268,7 +268,7 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) case RDMA_CM_EVENT_DEVICE_REMOVAL: pr_info("rpcrdma: removing device %s for %pISpc\n", ep->re_id->device->name, sap); - /* fall through */ + fallthrough; case RDMA_CM_EVENT_ADDR_CHANGE: ep->re_connect_status = -ENODEV; goto disconnected; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c57aef829403..554e1bb4c1c7 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -885,7 +885,7 @@ static int xs_local_send_request(struct rpc_rqst *req) default: dprintk("RPC: sendmsg returned unrecognized error %d\n", -status); - /* fall through */ + fallthrough; case -EPIPE: xs_close(xprt); status = -ENOTCONN; @@ -1436,7 +1436,7 @@ static void xs_tcp_state_change(struct sock *sk) xprt->connect_cookie++; clear_bit(XPRT_CONNECTED, &xprt->state); xs_run_error_worker(transport, XPRT_SOCK_WAKE_DISCONNECT); - /* fall through */ + fallthrough; case TCP_CLOSING: /* * If the server closed down the connection, make sure that @@ -2202,7 +2202,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) switch (ret) { case 0: xs_set_srcport(transport, sock); - /* fall through */ + fallthrough; case -EINPROGRESS: /* SYN_SENT! */ if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO) @@ -2255,7 +2255,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) default: printk("%s: connect returned unhandled error %d\n", __func__, status); - /* fall through */ + fallthrough; case -EADDRNOTAVAIL: /* We're probably in TIME_WAIT. Get rid of existing socket, * and retry diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 808b147df7d5..650414110452 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c @@ -652,7 +652,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, test_and_set_bit_lock(0, &b->up); break; } - /* fall through */ + fallthrough; case NETDEV_GOING_DOWN: clear_bit_unlock(0, &b->up); tipc_reset_bearer(net, b); diff --git a/net/tipc/group.c b/net/tipc/group.c index 89257e2a980d..588c2d2b0c69 100644 --- a/net/tipc/group.c +++ b/net/tipc/group.c @@ -536,7 +536,7 @@ void tipc_group_filter_msg(struct tipc_group *grp, struct sk_buff_head *inputq, update = true; deliver = false; } - /* Fall thru */ + fallthrough; case TIPC_GRP_BCAST_MSG: m->bc_rcv_nxt++; ack = msg_grp_bc_ack_req(hdr); diff --git a/net/tipc/link.c b/net/tipc/link.c index 107578122973..b7362556da95 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -1239,7 +1239,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb, skb_queue_tail(mc_inputq, skb); return true; } - /* fall through */ + fallthrough; case CONN_MANAGER: skb_queue_tail(inputq, skb); return true; diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 07419f36116a..2679e97e0389 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -783,7 +783,7 @@ static __poll_t tipc_poll(struct file *file, struct socket *sock, case TIPC_ESTABLISHED: if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk)) revents |= EPOLLOUT; - /* fall through */ + fallthrough; case TIPC_LISTEN: case TIPC_CONNECTING: if (!skb_queue_empty_lockless(&sk->sk_receive_queue)) @@ -2597,7 +2597,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest, * case is EINPROGRESS, rather than EALREADY. */ res = -EINPROGRESS; - /* fall through */ + fallthrough; case TIPC_CONNECTING: if (!timeout) { if (previous == TIPC_CONNECTING) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 181ea6fb56a6..92784e51ee7d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -837,7 +837,7 @@ static int unix_create(struct net *net, struct socket *sock, int protocol, */ case SOCK_RAW: sock->type = SOCK_DGRAM; - /* fall through */ + fallthrough; case SOCK_DGRAM: sock->ops = &unix_dgram_ops; break; diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 90f0f82cd9ca..e97a4f0c32a3 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -957,7 +957,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, if (!ht_cap->ht_supported && chandef->chan->band != NL80211_BAND_6GHZ) return false; - /* fall through */ + fallthrough; case NL80211_CHAN_WIDTH_20_NOHT: prohibited_flags |= IEEE80211_CHAN_NO_20MHZ; width = 20; @@ -983,7 +983,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy, if (chandef->chan->band != NL80211_BAND_6GHZ && cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) return false; - /* fall through */ + fallthrough; case NL80211_CHAN_WIDTH_80: prohibited_flags |= IEEE80211_CHAN_NO_80MHZ; width = 80; diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index a6c61a2e6569..db7333e20dd7 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c @@ -941,7 +941,7 @@ void cfg80211_cac_event(struct net_device *netdev, sizeof(struct cfg80211_chan_def)); queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); cfg80211_sched_dfs_chan_update(rdev); - /* fall through */ + fallthrough; case NL80211_RADAR_CAC_ABORTED: wdev->cac_started = false; break; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index c04fc6cf6583..fde420af3f00 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2107,7 +2107,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 1: if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES, sizeof(u32) * rdev->wiphy.n_cipher_suites, @@ -2154,7 +2154,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 2: if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, rdev->wiphy.interface_modes)) @@ -2162,7 +2162,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 3: nl_bands = nla_nest_start_noflag(msg, NL80211_ATTR_WIPHY_BANDS); @@ -2189,7 +2189,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->chan_start++; if (state->split) break; - /* fall through */ + fallthrough; default: /* add frequencies */ nl_freqs = nla_nest_start_noflag(msg, @@ -2244,7 +2244,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 4: nl_cmds = nla_nest_start_noflag(msg, NL80211_ATTR_SUPPORTED_COMMANDS); @@ -2273,7 +2273,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 5: if (rdev->ops->remain_on_channel && (rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) && @@ -2291,7 +2291,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 6: #ifdef CONFIG_PM if (nl80211_send_wowlan(msg, rdev, state->split)) @@ -2302,7 +2302,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, #else state->split_start++; #endif - /* fall through */ + fallthrough; case 7: if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, rdev->wiphy.software_iftypes)) @@ -2315,7 +2315,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev, state->split_start++; if (state->split) break; - /* fall through */ + fallthrough; case 8: if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) && nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME, @@ -5207,7 +5207,7 @@ bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, int attr) break; default: WARN_ON(1); - /* fall through */ + fallthrough; case RATE_INFO_BW_20: rate_flg = 0; break; diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e67a74488bbe..04f2d198c215 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -1433,7 +1433,7 @@ cfg80211_inform_single_bss_data(struct wiphy *wiphy, switch (ftype) { case CFG80211_BSS_FTYPE_BEACON: ies->from_beacon = true; - /* fall through */ + fallthrough; case CFG80211_BSS_FTYPE_UNKNOWN: rcu_assign_pointer(tmp.pub.beacon_ies, ies); break; diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 985f3c23f054..079ce320dc1e 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -205,7 +205,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev, return err; case CFG80211_CONN_ASSOC_FAILED_TIMEOUT: *treason = NL80211_TIMEOUT_ASSOC; - /* fall through */ + fallthrough; case CFG80211_CONN_ASSOC_FAILED: cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, @@ -215,7 +215,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev, cfg80211_mlme_deauth(rdev, wdev->netdev, params->bssid, NULL, 0, WLAN_REASON_DEAUTH_LEAVING, false); - /* fall through */ + fallthrough; case CFG80211_CONN_ABANDON: /* free directly, disconnected event already sent */ cfg80211_sme_free(wdev); diff --git a/net/wireless/util.c b/net/wireless/util.c index dfad1c0f57ad..7c5d5365a5eb 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -198,7 +198,7 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband) sband->bitrates[i].flags |= IEEE80211_RATE_MANDATORY_G; want--; - /* fall through */ + fallthrough; default: sband->bitrates[i].flags |= IEEE80211_RATE_ERP_G; @@ -1008,7 +1008,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_STATION: if (dev->ieee80211_ptr->use_4addr) break; - /* fall through */ + fallthrough; case NL80211_IFTYPE_OCB: case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_ADHOC: diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index aa918d7ff6bd..4d2160c989a3 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c @@ -1334,7 +1334,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) wstats.qual.qual = sig + 110; break; } - /* fall through */ + fallthrough; case CFG80211_SIGNAL_TYPE_UNSPEC: if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_SIGNAL)) { wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; @@ -1343,7 +1343,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev) wstats.qual.qual = sinfo.signal; break; } - /* fall through */ + fallthrough; default: wstats.qual.updated |= IW_QUAL_LEVEL_INVALID; wstats.qual.updated |= IW_QUAL_QUAL_INVALID; diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 7fb327632272..8e1a49b0c0dc 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -98,7 +98,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, *vc_fac_mask |= X25_MASK_REVERSE; break; } - /*fall through */ + fallthrough; case X25_FAC_THROUGHPUT: facilities->throughput = p[1]; *vc_fac_mask |= X25_MASK_THROUGHPUT; diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 4d3bb46aaae0..e1c4197af468 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -349,7 +349,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp case X25_RESET_REQUEST: x25_write_internal(sk, X25_RESET_CONFIRMATION); - /* fall through */ + fallthrough; case X25_RESET_CONFIRMATION: { x25_stop_timer(sk); x25->condition = 0x00; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d5280fd6f9c1..d622c2548d22 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -3410,7 +3410,7 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse) switch (nexthdr) { case NEXTHDR_FRAGMENT: onlyproto = 1; - /* fall through */ + fallthrough; case NEXTHDR_ROUTING: case NEXTHDR_HOP: case NEXTHDR_DEST: diff --git a/samples/bpf/hbm.c b/samples/bpf/hbm.c index 7d7153777678..4b22ace52f80 100644 --- a/samples/bpf/hbm.c +++ b/samples/bpf/hbm.c @@ -483,7 +483,7 @@ int main(int argc, char **argv) "Option -%c requires an argument.\n\n", optopt); case 'h': - // fallthrough + fallthrough; default: Usage(); return 0; diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c index 7b0e13ce7dc7..f919ebd042fd 100644 --- a/security/apparmor/domain.c +++ b/security/apparmor/domain.c @@ -577,7 +577,7 @@ static struct aa_label *x_to_label(struct aa_profile *profile, stack = NULL; break; } - /* fall through - to X_NAME */ + fallthrough; /* to X_NAME */ case AA_X_NAME: if (xindex & AA_X_CHILD) /* released by caller */ diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index 30c246a9d440..fa49b81eb54c 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -292,13 +292,13 @@ void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) switch (AUDIT_MODE(profile)) { case AUDIT_ALL: perms->audit = ALL_PERMS_MASK; - /* fall through */ + fallthrough; case AUDIT_NOQUIET: perms->quiet = 0; break; case AUDIT_QUIET: perms->audit = 0; - /* fall through */ + fallthrough; case AUDIT_QUIET_DENIED: perms->quiet = ALL_PERMS_MASK; break; diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 372d16382960..b8848f53c8cc 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -223,7 +223,7 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, case IMA_XATTR_DIGEST_NG: /* first byte contains algorithm id */ hash_start = 1; - /* fall through */ + fallthrough; case IMA_XATTR_DIGEST: if (iint->flags & IMA_DIGSIG_REQUIRED) { *cause = "IMA-signature-required"; @@ -395,7 +395,7 @@ int ima_appraise_measurement(enum ima_hooks func, /* It's fine not to have xattrs when using a modsig. */ if (try_modsig) break; - /* fall through */ + fallthrough; case INTEGRITY_NOLABEL: /* No security.evm xattr. */ cause = "missing-HMAC"; goto out; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 07f033634b27..b4de33074b37 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -1279,12 +1279,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) case Opt_uid_gt: case Opt_euid_gt: entry->uid_op = &uid_gt; - /* fall through */ + fallthrough; case Opt_uid_lt: case Opt_euid_lt: if ((token == Opt_uid_lt) || (token == Opt_euid_lt)) entry->uid_op = &uid_lt; - /* fall through */ + fallthrough; case Opt_uid_eq: case Opt_euid_eq: uid_token = (token == Opt_uid_eq) || @@ -1313,11 +1313,11 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) break; case Opt_fowner_gt: entry->fowner_op = &uid_gt; - /* fall through */ + fallthrough; case Opt_fowner_lt: if (token == Opt_fowner_lt) entry->fowner_op = &uid_lt; - /* fall through */ + fallthrough; case Opt_fowner_eq: ima_log_string_op(ab, "fowner", args[0].from, entry->fowner_op); diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 41a5f435b793..c022ee9e2a4e 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -77,7 +77,7 @@ static void ima_show_template_data_ascii(struct seq_file *m, /* skip ':' and '\0' */ buf_ptr += 2; buflen -= buf_ptr - field_data->data; - /* fall through */ + fallthrough; case DATA_FMT_DIGEST: case DATA_FMT_HEX: if (!buflen) diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 7e0232db1707..1fe8b934f656 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -465,7 +465,7 @@ key_ref_t search_cred_keyrings_rcu(struct keyring_search_context *ctx) case -EAGAIN: /* no key */ if (ret) break; - /* fall through */ + fallthrough; case -ENOKEY: /* negative key */ ret = key_ref; break; @@ -487,7 +487,7 @@ key_ref_t search_cred_keyrings_rcu(struct keyring_search_context *ctx) case -EAGAIN: /* no key */ if (ret) break; - /* fall through */ + fallthrough; case -ENOKEY: /* negative key */ ret = key_ref; break; @@ -509,7 +509,7 @@ key_ref_t search_cred_keyrings_rcu(struct keyring_search_context *ctx) case -EAGAIN: /* no key */ if (ret) break; - /* fall through */ + fallthrough; case -ENOKEY: /* negative key */ ret = key_ref; break; diff --git a/security/keys/request_key.c b/security/keys/request_key.c index e1b9f1a80676..2da4404276f0 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c @@ -295,26 +295,26 @@ static int construct_get_dest_keyring(struct key **_dest_keyring) } } - /* fall through */ + fallthrough; case KEY_REQKEY_DEFL_THREAD_KEYRING: dest_keyring = key_get(cred->thread_keyring); if (dest_keyring) break; - /* fall through */ + fallthrough; case KEY_REQKEY_DEFL_PROCESS_KEYRING: dest_keyring = key_get(cred->process_keyring); if (dest_keyring) break; - /* fall through */ + fallthrough; case KEY_REQKEY_DEFL_SESSION_KEYRING: dest_keyring = key_get(cred->session_keyring); if (dest_keyring) break; - /* fall through */ + fallthrough; case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: ret = look_up_user_keyrings(NULL, &dest_keyring); if (ret < 0) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index ca901025802a..a340986aa92e 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3606,26 +3606,20 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, switch (cmd) { case FIONREAD: - /* fall through */ case FIBMAP: - /* fall through */ case FIGETBSZ: - /* fall through */ case FS_IOC_GETFLAGS: - /* fall through */ case FS_IOC_GETVERSION: error = file_has_perm(cred, file, FILE__GETATTR); break; case FS_IOC_SETFLAGS: - /* fall through */ case FS_IOC_SETVERSION: error = file_has_perm(cred, file, FILE__SETATTR); break; /* sys_ioctl() checks */ case FIONBIO: - /* fall through */ case FIOASYNC: error = file_has_perm(cred, file, 0); break; @@ -3783,7 +3777,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd, err = file_has_perm(cred, file, FILE__WRITE); break; } - /* fall through */ + fallthrough; case F_SETOWN: case F_SETSIG: case F_GETFL: diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index 408d306895f8..d338962fb0c4 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c @@ -535,7 +535,7 @@ int mls_compute_sid(struct policydb *p, scontext, tcontext); } - /* Fallthrough */ + fallthrough; case AVTAB_CHANGE: if ((tclass == p->process_class) || sock) /* Use the process MLS attributes. */ @@ -546,8 +546,6 @@ int mls_compute_sid(struct policydb *p, case AVTAB_MEMBER: /* Use the process effective MLS attributes. */ return mls_context_cpy_low(newcontext, scontext); - - /* fall through */ } return -EINVAL; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8ffbf951b7ed..8c0893eb5aa8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3365,7 +3365,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * to set mount options simulate setting the * superblock default. */ - /* Fall through */ + fallthrough; default: /* * This isn't an understood special case. diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index c16b8c1b03e7..4bee32bfe16d 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -1240,7 +1240,7 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, tomoyo_set_space(head); tomoyo_set_string(head, cond->transit->name); } - /* fall through */ + fallthrough; case 1: { const u16 condc = cond->condc; @@ -1345,12 +1345,12 @@ static bool tomoyo_print_condition(struct tomoyo_io_buffer *head, } } head->r.cond_step++; - /* fall through */ + fallthrough; case 2: if (!tomoyo_flush(head)) break; head->r.cond_step++; - /* fall through */ + fallthrough; case 3: if (cond->grant_log != TOMOYO_GRANTLOG_AUTO) tomoyo_io_printf(head, " grant_log=%s", @@ -1639,7 +1639,7 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) tomoyo_set_string(head, tomoyo_dif[i]); head->r.index = 0; head->r.step++; - /* fall through */ + fallthrough; case 1: while (head->r.index < TOMOYO_MAX_ACL_GROUPS) { i = head->r.index++; @@ -1652,14 +1652,14 @@ static void tomoyo_read_domain(struct tomoyo_io_buffer *head) head->r.index = 0; head->r.step++; tomoyo_set_lf(head); - /* fall through */ + fallthrough; case 2: if (!tomoyo_read_domain2(head, &domain->acl_info_list)) return; head->r.step++; if (!tomoyo_set_lf(head)) return; - /* fall through */ + fallthrough; case 3: head->r.step = 0; if (head->r.print_this_domain_only) @@ -2088,7 +2088,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) /* Check max_learning_entry parameter. */ if (tomoyo_domain_quota_is_ok(r)) break; - /* fall through */ + fallthrough; default: return 0; } @@ -2710,13 +2710,13 @@ ssize_t tomoyo_write_control(struct tomoyo_io_buffer *head, case TOMOYO_DOMAINPOLICY: if (tomoyo_select_domain(head, cp0)) continue; - /* fall through */ + fallthrough; case TOMOYO_EXCEPTIONPOLICY: if (!strcmp(cp0, "select transition_only")) { head->r.print_transition_related_only = true; continue; } - /* fall through */ + fallthrough; default: if (!tomoyo_manager()) { error = -EPERM; diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 86f7d1b90212..051f7297877c 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c @@ -927,7 +927,7 @@ int tomoyo_path2_perm(const u8 operation, const struct path *path1, case TOMOYO_TYPE_LINK: if (!d_is_dir(path1->dentry)) break; - /* fall through */ + fallthrough; case TOMOYO_TYPE_PIVOT_ROOT: tomoyo_add_slash(&buf1); tomoyo_add_slash(&buf2); diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c index b8161a08f2ca..58bb49fff184 100644 --- a/sound/ppc/snd_ps3.c +++ b/sound/ppc/snd_ps3.c @@ -227,14 +227,14 @@ static int snd_ps3_program_dma(struct snd_ps3_card_info *card, switch (filltype) { case SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL: silent = 1; - /* intentionally fall thru */ + fallthrough; case SND_PS3_DMA_FILLTYPE_FIRSTFILL: ch0_kick_event = PS3_AUDIO_KICK_EVENT_ALWAYS; break; case SND_PS3_DMA_FILLTYPE_SILENT_RUNNING: silent = 1; - /* intentionally fall thru */ + fallthrough; case SND_PS3_DMA_FILLTYPE_RUNNING: ch0_kick_event = PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY; break; diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 3cb63886195f..04acc18f2d72 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -536,7 +536,7 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, /* cpu is BCLK master */ mrb |= MCHP_I2SMCC_MRB_CLKSEL_INT; set_divs = 1; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_CBM_CFM: /* cpu is slave */ mra |= MCHP_I2SMCC_MRA_MODE_SLAVE; diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index c0a28f06b09a..298689a07168 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -202,7 +202,7 @@ static int jz4770_codec_set_bias_level(struct snd_soc_component *codec, REG_CR_VIC_SB_SLEEP, REG_CR_VIC_SB_SLEEP); regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC, REG_CR_VIC_SB, REG_CR_VIC_SB); - /* fall-through */ + fallthrough; default: break; } diff --git a/sound/soc/codecs/pcm186x.c b/sound/soc/codecs/pcm186x.c index f0da55901dcb..b8845f45549e 100644 --- a/sound/soc/codecs/pcm186x.c +++ b/sound/soc/codecs/pcm186x.c @@ -401,7 +401,7 @@ static int pcm186x_set_fmt(struct snd_soc_dai *dai, unsigned int format) break; case SND_SOC_DAIFMT_DSP_A: priv->tdm_offset += 1; - /* fall through */ + fallthrough; /* DSP_A uses the same basic config as DSP_B * except we need to shift the TDM output by one BCK cycle */ diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index d8b9c6547142..404be27c15fe 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -898,7 +898,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) "missing baudclk for master mode\n"); return -EINVAL; } - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_CBM_CFS: ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER; break; diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index fd5dcd6b9f85..907f5f1f7b44 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -261,13 +261,13 @@ static int hi6210_i2s_hw_params(struct snd_pcm_substream *substream, switch (params_format(params)) { case SNDRV_PCM_FORMAT_U16_LE: signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; - /* fall through */ + fallthrough; case SNDRV_PCM_FORMAT_S16_LE: bits = HII2S_BITS_16; break; case SNDRV_PCM_FORMAT_U24_LE: signed_data = HII2S_I2S_CFG__S2_CODEC_DATA_FORMAT; - /* fall through */ + fallthrough; case SNDRV_PCM_FORMAT_S24_LE: bits = HII2S_BITS_24; break; diff --git a/sound/soc/intel/baytrail/sst-baytrail-pcm.c b/sound/soc/intel/baytrail/sst-baytrail-pcm.c index 54a66cc6db89..d2cda33b65d5 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-pcm.c +++ b/sound/soc/intel/baytrail/sst-baytrail-pcm.c @@ -181,7 +181,7 @@ static int sst_byt_pcm_trigger(struct snd_soc_component *component, break; case SNDRV_PCM_TRIGGER_SUSPEND: pdata->restore_stream = false; - /* fallthrough */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: sst_byt_stream_pause(byt, pcm_data->stream); break; diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 414ae4bb5224..7ae34b49815c 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -573,7 +573,7 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) break; default: dev_err(dev, "get speaker GPIO failed: %d\n", ret); - /* fall through */ + fallthrough; case -EPROBE_DEFER: return ret; } diff --git a/sound/soc/intel/boards/bytcr_rt5651.c b/sound/soc/intel/boards/bytcr_rt5651.c index 4e2897596cea..688b5e0a49e3 100644 --- a/sound/soc/intel/boards/bytcr_rt5651.c +++ b/sound/soc/intel/boards/bytcr_rt5651.c @@ -1009,7 +1009,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Failed to get ext-amp-enable GPIO: %d\n", ret_val); - /* fall through */ + fallthrough; case -EPROBE_DEFER: put_device(codec_dev); return ret_val; @@ -1029,7 +1029,7 @@ static int snd_byt_rt5651_mc_probe(struct platform_device *pdev) default: dev_err(&pdev->dev, "Failed to get hp-detect GPIO: %d\n", ret_val); - /* fall through */ + fallthrough; case -EPROBE_DEFER: put_device(codec_dev); return ret_val; diff --git a/sound/soc/intel/skylake/skl-pcm.c b/sound/soc/intel/skylake/skl-pcm.c index 5dee55e9546b..bbe8d782e0af 100644 --- a/sound/soc/intel/skylake/skl-pcm.c +++ b/sound/soc/intel/skylake/skl-pcm.c @@ -488,7 +488,7 @@ static int skl_pcm_trigger(struct snd_pcm_substream *substream, int cmd, stream->lpib); snd_hdac_ext_stream_set_lpib(stream, stream->lpib); } - /* fall through */ + fallthrough; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: diff --git a/sound/soc/meson/axg-tdm-interface.c b/sound/soc/meson/axg-tdm-interface.c index 36df30915378..c8664ab80d45 100644 --- a/sound/soc/meson/axg-tdm-interface.c +++ b/sound/soc/meson/axg-tdm-interface.c @@ -58,17 +58,17 @@ int axg_tdm_set_tdm_slots(struct snd_soc_dai *dai, u32 *tx_mask, switch (slot_width) { case 0: slot_width = 32; - /* Fall-through */ + fallthrough; case 32: fmt |= SNDRV_PCM_FMTBIT_S32_LE; - /* Fall-through */ + fallthrough; case 24: fmt |= SNDRV_PCM_FMTBIT_S24_LE; fmt |= SNDRV_PCM_FMTBIT_S20_LE; - /* Fall-through */ + fallthrough; case 16: fmt |= SNDRV_PCM_FMTBIT_S16_LE; - /* Fall-through */ + fallthrough; case 8: fmt |= SNDRV_PCM_FMTBIT_S8; break; @@ -133,7 +133,7 @@ static int axg_tdm_iface_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_CBS_CFM: case SND_SOC_DAIFMT_CBM_CFS: dev_err(dai->dev, "only CBS_CFS and CBM_CFM are supported\n"); - /* Fall-through */ + fallthrough; default: return -EINVAL; } diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c index d1e09ade0190..c4e7307a4437 100644 --- a/sound/soc/pxa/pxa-ssp.c +++ b/sound/soc/pxa/pxa-ssp.c @@ -488,7 +488,7 @@ static int pxa_ssp_configure_dai_fmt(struct ssp_priv *priv) case SND_SOC_DAIFMT_DSP_A: sspsp |= SSPSP_FSRT; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_B: sscr0 |= SSCR0_MOD | SSCR0_PSP; sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c index 1707414cfa92..5adb293d0435 100644 --- a/sound/soc/rockchip/rockchip_pdm.c +++ b/sound/soc/rockchip/rockchip_pdm.c @@ -229,13 +229,13 @@ static int rockchip_pdm_hw_params(struct snd_pcm_substream *substream, switch (params_channels(params)) { case 8: val |= PDM_PATH3_EN; - /* fallthrough */ + fallthrough; case 6: val |= PDM_PATH2_EN; - /* fallthrough */ + fallthrough; case 4: val |= PDM_PATH1_EN; - /* fallthrough */ + fallthrough; case 2: val |= PDM_PATH0_EN; break; diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index 80ecb5c7fed0..df53d4ea808f 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -733,7 +733,7 @@ static int i2s_hw_params(struct snd_pcm_substream *substream, switch (params_channels(params)) { case 6: val |= MOD_DC2_EN; - /* Fall through */ + fallthrough; case 4: val |= MOD_DC1_EN; break; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 2fe1b2ec7c8f..663e3839f251 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -618,7 +618,7 @@ int snd_soc_suspend(struct device *dev) "ASoC: idle_bias_off CODEC on over suspend\n"); break; } - /* fall through */ + fallthrough; case SND_SOC_BIAS_OFF: snd_soc_component_suspend(component); diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index cee998671318..5b60379237bf 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1057,7 +1057,7 @@ static int soc_tplg_denum_create(struct soc_tplg *tplg, unsigned int count, ec->hdr.name); goto err_denum; } - /* fall through */ + fallthrough; case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: @@ -1445,7 +1445,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create( ec->hdr.name); goto err_se; } - /* fall through */ + fallthrough; case SND_SOC_TPLG_CTL_ENUM: case SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE: case SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT: diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index df1c6997cb4e..c6cb8c212eca 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -310,7 +310,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, return ret; } - /* fallthrough */ + fallthrough; case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_hdac_ext_link_stream_start(link_dev); @@ -333,7 +333,7 @@ static int hda_link_pcm_trigger(struct snd_pcm_substream *substream, link_dev->link_prepared = 0; - /* fallthrough */ + fallthrough; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_hdac_ext_link_stream_clear(link_dev); break; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d730e437e4ba..71c3f29057a7 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -361,7 +361,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, return ret; } - /* fallthrough */ + fallthrough; case SNDRV_PCM_TRIGGER_START: if (spcm->stream[substream->stream].suspend_ignored) { /* @@ -386,7 +386,7 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = true; return 0; } - /* fallthrough */ + fallthrough; case SNDRV_PCM_TRIGGER_STOP: stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; ipc_first = true; diff --git a/sound/soc/ti/davinci-i2s.c b/sound/soc/ti/davinci-i2s.c index d89b5c928c4d..dd34504c09ba 100644 --- a/sound/soc/ti/davinci-i2s.c +++ b/sound/soc/ti/davinci-i2s.c @@ -289,7 +289,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, * rate is lowered. */ inv_fs = true; - /* fall through */ + fallthrough; case SND_SOC_DAIFMT_DSP_A: dev->mode = MOD_DSP_A; break; diff --git a/sound/soc/ti/n810.c b/sound/soc/ti/n810.c index 2802a33b9c5f..ed217b34f846 100644 --- a/sound/soc/ti/n810.c +++ b/sound/soc/ti/n810.c @@ -46,7 +46,7 @@ static void n810_ext_control(struct snd_soc_dapm_context *dapm) switch (n810_jack_func) { case N810_JACK_HS: line1l = 1; - /* fall through */ + fallthrough; case N810_JACK_HP: hp = 1; break; diff --git a/sound/soc/ti/omap-dmic.c b/sound/soc/ti/omap-dmic.c index 01abf1be5d78..a26588e9c3bc 100644 --- a/sound/soc/ti/omap-dmic.c +++ b/sound/soc/ti/omap-dmic.c @@ -203,10 +203,10 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, switch (channels) { case 6: dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE; - /* fall through */ + fallthrough; case 4: dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE; - /* fall through */ + fallthrough; case 2: dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE; break; diff --git a/sound/soc/ti/omap-mcpdm.c b/sound/soc/ti/omap-mcpdm.c index d482b62f314a..fafb2998ad0d 100644 --- a/sound/soc/ti/omap-mcpdm.c +++ b/sound/soc/ti/omap-mcpdm.c @@ -309,19 +309,19 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, /* up to 3 channels for capture */ return -EINVAL; link_mask |= 1 << 4; - /* fall through */ + fallthrough; case 4: if (stream == SNDRV_PCM_STREAM_CAPTURE) /* up to 3 channels for capture */ return -EINVAL; link_mask |= 1 << 3; - /* fall through */ + fallthrough; case 3: link_mask |= 1 << 2; - /* fall through */ + fallthrough; case 2: link_mask |= 1 << 1; - /* fall through */ + fallthrough; case 1: link_mask |= 1 << 0; break; diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c index 2176a95201bf..a2629ccc1dc8 100644 --- a/sound/soc/ti/rx51.c +++ b/sound/soc/ti/rx51.c @@ -55,7 +55,7 @@ static void rx51_ext_control(struct snd_soc_dapm_context *dapm) break; case RX51_JACK_HS: hs = 1; - /* fall through */ + fallthrough; case RX51_JACK_HP: hp = 1; break; diff --git a/sound/soc/zte/zx-i2s.c b/sound/soc/zte/zx-i2s.c index 568cde64ff8b..1c1a44e08a67 100644 --- a/sound/soc/zte/zx-i2s.c +++ b/sound/soc/zte/zx-i2s.c @@ -294,7 +294,7 @@ static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, zx_i2s_rx_dma_en(zx_i2s->reg_base, true); else zx_i2s_tx_dma_en(zx_i2s->reg_base, true); - /* fall thru */ + fallthrough; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: if (capture) @@ -308,7 +308,7 @@ static int zx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, zx_i2s_rx_dma_en(zx_i2s->reg_base, false); else zx_i2s_tx_dma_en(zx_i2s->reg_base, false); - /* fall thru */ + fallthrough; case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_PAUSE_PUSH: if (capture) diff --git a/sound/soc/zte/zx-spdif.c b/sound/soc/zte/zx-spdif.c index a3a07c0730e6..b4168bd532b7 100644 --- a/sound/soc/zte/zx-spdif.c +++ b/sound/soc/zte/zx-spdif.c @@ -218,7 +218,7 @@ static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd, val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL); val |= ZX_FIFOCTRL_TX_FIFO_RST; writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL); - /* fall thru */ + fallthrough; case SNDRV_PCM_TRIGGER_RESUME: case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: zx_spdif_cfg_tx(zx_spdif->reg_base, true); -- cgit v1.2.3 From 2c5bf028ef34745e7b3fe768f9c9355ecc7df101 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sun, 23 Aug 2020 21:09:22 +0200 Subject: drm/etnaviv: fix external abort seen on GC600 rev 0x19 It looks like that this GPU core triggers an abort when reading VIVS_HI_CHIP_PRODUCT_ID and/or VIVS_HI_CHIP_ECO_ID. I looked at different versions of Vivante's kernel driver and did not found anything about this issue or what feature flag can be used. So go the simplest route and do not read these two registers on the affected GPU core. Signed-off-by: Christian Gmeiner Reported-by: Josua Mayer Fixes: 815e45bbd4d3 ("drm/etnaviv: determine product, customer and eco id") Cc: stable@vger.kernel.org Tested-by: Josua Mayer Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index d5a4cd85a0f6..c6404b8d067f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -337,9 +337,16 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL); gpu->identity.revision = gpu_read(gpu, VIVS_HI_CHIP_REV); - gpu->identity.product_id = gpu_read(gpu, VIVS_HI_CHIP_PRODUCT_ID); gpu->identity.customer_id = gpu_read(gpu, VIVS_HI_CHIP_CUSTOMER_ID); - gpu->identity.eco_id = gpu_read(gpu, VIVS_HI_CHIP_ECO_ID); + + /* + * Reading these two registers on GC600 rev 0x19 result in a + * unhandled fault: external abort on non-linefetch + */ + if (!etnaviv_is_model_rev(gpu, GC600, 0x19)) { + gpu->identity.product_id = gpu_read(gpu, VIVS_HI_CHIP_PRODUCT_ID); + gpu->identity.eco_id = gpu_read(gpu, VIVS_HI_CHIP_ECO_ID); + } /* * !!!! HACK ALERT !!!! -- cgit v1.2.3 From 50248a3ec0f5e5debd18033eb2a29f0b793a7000 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 24 Aug 2020 12:55:37 +0200 Subject: drm/etnaviv: always start/stop scheduler in timeout processing The drm scheduler currently expects that the stop/start sequence is always executed in the timeout handling, as the job at the head of the hardware execution list is always removed from the ring mirror before the driver function is called and only inserted back into the list when starting the scheduler. This adds some unnecessary overhead if the timeout handler determines that the GPU is still executing jobs normally and just wished to extend the timeout, but a better solution requires a major rearchitecture of the scheduler, which is not applicable as a fix. Fixes: 135517d3565b ("drm/scheduler: Avoid accessing freed bad job.") Signed-off-by: Lucas Stach Tested-by: Russell King --- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 4e3e95dce6d8..cd46c882269c 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -89,12 +89,15 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) u32 dma_addr; int change; + /* block scheduler */ + drm_sched_stop(&gpu->sched, sched_job); + /* * If the GPU managed to complete this jobs fence, the timout is * spurious. Bail out. */ if (dma_fence_is_signaled(submit->out_fence)) - return; + goto out_no_timeout; /* * If the GPU is still making forward progress on the front-end (which @@ -105,12 +108,9 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) change = dma_addr - gpu->hangcheck_dma_addr; if (change < 0 || change > 16) { gpu->hangcheck_dma_addr = dma_addr; - return; + goto out_no_timeout; } - /* block scheduler */ - drm_sched_stop(&gpu->sched, sched_job); - if(sched_job) drm_sched_increase_karma(sched_job); @@ -120,6 +120,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job) drm_sched_resubmit_jobs(&gpu->sched); +out_no_timeout: /* restart scheduler after GPU is usable again */ drm_sched_start(&gpu->sched, true); } -- cgit v1.2.3 From 818b032433a345b2f5466660ae054806343263e5 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Tue, 18 Aug 2020 14:51:41 -0400 Subject: drm/amdkfd: sparse: Fix warning in reading SDMA counters Add __user annotation to fix related sparse warning while reading SDMA counters from userland. Also, rework the read SDMA counters function by removing redundant checks. Reported-by: kernel test robot Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 28 ++-------------------- .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 8 ++++++- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 6 ++--- 3 files changed, 12 insertions(+), 30 deletions(-) (limited to 'drivers/gpu') 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..560adc57a050 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -153,30 +153,6 @@ static void decrement_queue_count(struct device_queue_manager *dqm, dqm->active_cp_queue_count--; } -int read_sdma_queue_counter(uint64_t q_rptr, uint64_t *val) -{ - int ret; - uint64_t tmp = 0; - - if (!val) - return -EINVAL; - /* - * SDMA activity counter is stored at queue's RPTR + 0x8 location. - */ - if (!access_ok((const void __user *)(q_rptr + - sizeof(uint64_t)), sizeof(uint64_t))) { - pr_err("Can't access sdma queue activity counter\n"); - return -EFAULT; - } - - ret = get_user(tmp, (uint64_t *)(q_rptr + sizeof(uint64_t))); - if (!ret) { - *val = tmp; - } - - return ret; -} - static int allocate_doorbell(struct qcm_process_device *qpd, struct queue *q) { struct kfd_dev *dev = qpd->dqm->dev; @@ -552,7 +528,7 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { - retval = read_sdma_queue_counter((uint64_t)q->properties.read_ptr, + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, &sdma_val); if (retval) pr_err("Failed to read SDMA queue counter for queue: %d\n", @@ -1473,7 +1449,7 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || (q->properties.type == KFD_QUEUE_TYPE_SDMA_XGMI)) { - retval = read_sdma_queue_counter((uint64_t)q->properties.read_ptr, + retval = read_sdma_queue_counter((uint64_t __user *)q->properties.read_ptr, &sdma_val); if (retval) pr_err("Failed to read SDMA queue counter for queue: %d\n", diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 49d8e324c636..16262e5d93f5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -251,5 +251,11 @@ static inline void dqm_unlock(struct device_queue_manager *dqm) mutex_unlock(&dqm->lock_hidden); } -int read_sdma_queue_counter(uint64_t q_rptr, uint64_t *val); +static inline int read_sdma_queue_counter(uint64_t __user *q_rptr, uint64_t *val) +{ + /* + * SDMA activity counter is stored at queue's RPTR + 0x8 location. + */ + return get_user(*val, q_rptr + 1); +} #endif /* KFD_DEVICE_QUEUE_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index ddd192e3197c..a0e12a79ab7d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -87,7 +87,7 @@ struct kfd_sdma_activity_handler_workarea { }; struct temp_sdma_queue_list { - uint64_t rptr; + uint64_t __user *rptr; uint64_t sdma_val; unsigned int queue_id; struct list_head list; @@ -159,7 +159,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work) } INIT_LIST_HEAD(&sdma_q->list); - sdma_q->rptr = (uint64_t)q->properties.read_ptr; + sdma_q->rptr = (uint64_t __user *)q->properties.read_ptr; sdma_q->queue_id = q->properties.queue_id; list_add_tail(&sdma_q->list, &sdma_q_list.list); } @@ -218,7 +218,7 @@ static void kfd_sdma_activity_worker(struct work_struct *work) continue; list_for_each_entry_safe(sdma_q, next, &sdma_q_list.list, list) { - if (((uint64_t)q->properties.read_ptr == sdma_q->rptr) && + if (((uint64_t __user *)q->properties.read_ptr == sdma_q->rptr) && (sdma_q->queue_id == q->properties.queue_id)) { list_del(&sdma_q->list); kfree(sdma_q); -- cgit v1.2.3 From c9977dffcc7e0f728e82209c140991c5bd27c491 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 19 Aug 2020 13:37:54 -0400 Subject: drm/amd/display: Reject overlay plane configurations in multi-display scenarios [Why] These aren't stable on some platform configurations when driving multiple displays, especially on higher resolution. In particular the delay in asserting p-state and validating from x86 outweights any power or performance benefit from the hardware composition. Under some configurations this will manifest itself as extreme stutter or unresponsiveness especially when combined with cursor movement. [How] Disable these for now. Exposing overlays to userspace doesn't guarantee that they'll be able to use them in any and all configurations and it's part of the DRM contract to have userspace gracefully handle validation failures when they occur. Valdiation occurs as part of DC and this in particular affects RV, so disable this in dcn10_global_validation. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 07571f84e0f8..1abd81e17f09 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1213,6 +1213,7 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont bool video_large = false; bool desktop_large = false; bool dcc_disabled = false; + bool mpo_enabled = false; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -1221,6 +1222,9 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont if (context->stream_status[i].plane_count > 2) return DC_FAIL_UNSUPPORTED_1; + if (context->stream_status[i].plane_count > 1) + mpo_enabled = true; + for (j = 0; j < context->stream_status[i].plane_count; j++) { struct dc_plane_state *plane = context->stream_status[i].plane_states[j]; @@ -1244,6 +1248,10 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont } } + /* Disable MPO in multi-display configurations. */ + if (context->stream_count > 1 && mpo_enabled) + return DC_FAIL_UNSUPPORTED_1; + /* * Workaround: On DCN10 there is UMC issue that causes underflow when * playing 4k video on 4k desktop with video downscaled and single channel -- cgit v1.2.3 From 53b3f8f40e6cff36ae12b11e6d6b308af3c7e53f Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Wed, 19 Aug 2020 17:23:03 +0800 Subject: drm/amdgpu: refine codes to avoid reentering GPU recovery if other threads have holden the reset lock, recovery will fail to try_lock. Therefore we introduce atomic hive->in_reset and adev->in_gpu_reset, to avoid reentering GPU recovery. v2: drop "? true : false" in the definition of amdgpu_in_reset Reviewed-by: Hawking Zhang Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 6 +- 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_debugfs.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 37 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 3 +- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 10 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 4 +- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 4 +- drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 4 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 116 ++++++++++----------- .../gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c | 2 +- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 +- 28 files changed, 127 insertions(+), 122 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 54666eea1863..72f2a9aeaf0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -949,7 +949,7 @@ struct amdgpu_device { bool in_suspend; bool in_hibernate; - bool in_gpu_reset; + atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; struct mutex lock_reset; struct amdgpu_doorbell_index doorbell_index; @@ -1267,4 +1267,8 @@ static inline bool amdgpu_is_tmz(struct amdgpu_device *adev) return adev->gmc.tmz_enabled; } +static inline int amdgpu_in_reset(struct amdgpu_device *adev) +{ + return atomic_read(&adev->in_gpu_reset); +} #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index 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 a755f63514e1..d08839d9491f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -552,7 +552,7 @@ int kgd_gfx_v9_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t temp; struct v9_mqd *m = get_mqd(mqd); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; acquire_queue(kgd, pipe_id, queue_id); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 35fed75a4397..79b397800cbc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -127,7 +127,7 @@ static unsigned int amdgpu_debugfs_autodump_poll(struct file *file, struct poll_ poll_wait(file, &adev->autodump.gpu_hang, poll_table); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return POLLIN | POLLRDNORM | POLLWRNORM; return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6573e1112462..78fd2c9a7b7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1940,7 +1940,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) if (adev->ip_blocks[i].status.hw == true) break; - if (adev->in_gpu_reset || adev->in_suspend) { + if (amdgpu_in_reset(adev) || adev->in_suspend) { r = adev->ip_blocks[i].version->funcs->resume(adev); if (r) { DRM_ERROR("resume of IP block <%s> failed %d\n", @@ -2117,7 +2117,7 @@ static bool amdgpu_device_check_vram_lost(struct amdgpu_device *adev) AMDGPU_RESET_MAGIC_NUM)) return true; - if (!adev->in_gpu_reset) + if (!amdgpu_in_reset(adev)) return false; /* @@ -3053,6 +3053,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->mn_lock); mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); + atomic_set(&adev->in_gpu_reset, 0); mutex_init(&adev->lock_reset); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4200,16 +4201,14 @@ 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; + + mutex_lock(&adev->lock_reset); atomic_inc(&adev->gpu_reset_counter); - adev->in_gpu_reset = true; switch (amdgpu_asic_reset_method(adev)) { case AMD_RESET_METHOD_MODE1: adev->mp1_state = PP_MP1_STATE_SHUTDOWN; @@ -4229,7 +4228,7 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) { amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } @@ -4340,12 +4339,14 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, true); - if (hive && !mutex_trylock(&hive->reset_lock)) { - DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", - job ? job->base.id : -1, hive->hive_id); - mutex_unlock(&hive->hive_lock); - return 0; + hive = amdgpu_get_xgmi_hive(adev, false); + if (hive) { + if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { + DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", + job ? job->base.id : -1, hive->hive_id); + return 0; + } + mutex_lock(&hive->hive_lock); } /* @@ -4367,7 +4368,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev, !hive)) { + if (!amdgpu_device_lock_adev(tmp_adev)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); mutex_unlock(&hive->hive_lock); @@ -4505,7 +4506,7 @@ skip_sched_resume: } if (hive) { - mutex_unlock(&hive->reset_lock); + atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index a819360a4b6a..ebea3f655826 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -719,7 +719,7 @@ uint32_t amdgpu_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); @@ -777,7 +777,7 @@ void amdgpu_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_write; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index aa1e77c60c0a..116a89990f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -1869,7 +1869,7 @@ static int psp_load_smu_fw(struct psp_context *psp) return 0; - if (adev->in_gpu_reset && ras && ras->supported) { + if (amdgpu_in_reset(adev) && ras && ras->supported) { ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD); if (ret) { DRM_WARN("Failed to set MP1 state prepare for reload\n"); @@ -1984,7 +1984,7 @@ static int psp_load_fw(struct amdgpu_device *adev) int ret; struct psp_context *psp = &adev->psp; - if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset) { + if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) { psp_ring_stop(psp, PSP_RING_TYPE__KM); /* should not destroy ring, only stop */ goto skip_memalloc; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 866373c95cae..fa2c28ae9785 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -2081,7 +2081,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, amdgpu_ras_request_reset_on_boot(adev, ras_block->block); return 0; - } else if (adev->in_suspend || adev->in_gpu_reset) { + } else if (adev->in_suspend || amdgpu_in_reset(adev)) { /* in resume phase, if fail to enable ras, * clean up all ras fs nodes, and disable ras */ goto cleanup; @@ -2090,7 +2090,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev, } /* in resume phase, no need to create ras fs node */ - if (adev->in_suspend || adev->in_gpu_reset) + if (adev->in_suspend || amdgpu_in_reset(adev)) return 0; if (ih_info->cb) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 3d2712a4cf4d..97449ab24c20 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2098,7 +2098,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) uint64_t size; int r; - if (!adev->mman.initialized || adev->in_gpu_reset || + if (!adev->mman.initialized || amdgpu_in_reset(adev) || adev->mman.buffer_funcs_enabled == enable) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 183743c5fb7b..5f851d17eef4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -628,7 +628,7 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) struct amdgpu_firmware_info *ucode = NULL; /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */ - if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend)) + if (!amdgpu_sriov_vf(adev) && (amdgpu_in_reset(adev) || adev->in_suspend)) return 0; /* * if SMU loaded firmware, it needn't add SMC, UVD, and VCE diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index 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 cd6e6eb7d966..7a61dc6738eb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -372,7 +372,7 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lo tmp->hive_id = adev->gmc.xgmi.hive_id; INIT_LIST_HEAD(&tmp->device_list); mutex_init(&tmp->hive_lock); - mutex_init(&tmp->reset_lock); + atomic_set(&tmp->in_reset, 0); task_barrier_init(&tmp->tb); if (lock) @@ -594,7 +594,6 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) if(!(--hive->number_devices)){ amdgpu_xgmi_sysfs_destroy(adev, hive); mutex_destroy(&hive->hive_lock); - mutex_destroy(&hive->reset_lock); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 6999eab16a72..453336ca9675 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -30,10 +30,11 @@ struct amdgpu_hive_info { uint64_t hive_id; struct list_head device_list; int number_devices; - struct mutex hive_lock, reset_lock; + struct mutex hive_lock; struct kobject *kobj; struct device_attribute dev_attr; struct amdgpu_device *adev; + atomic_t in_reset; int hi_req_count; struct amdgpu_device *hi_req_gpu; struct task_barrier tb; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index e527be22a3d5..d851fe80eaf4 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6198,7 +6198,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) struct v10_gfx_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.gfx_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6210,7 +6210,7 @@ static int gfx_v10_0_gfx_init_queue(struct amdgpu_ring *ring) mutex_unlock(&adev->srbm_mutex); if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(adev->gfx.me.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { + } else if (amdgpu_in_reset(adev)) { /* reset mqd with the backup copy */ if (adev->gfx.me.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.me.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6563,7 +6563,7 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v10_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); @@ -6599,7 +6599,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) struct v10_compute_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(*mqd)); mutex_lock(&adev->srbm_mutex); nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0); @@ -6609,7 +6609,7 @@ static int gfx_v10_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(*mqd)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(*mqd)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 3b7127202420..d5843e8a6e17 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -4633,7 +4633,7 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v8_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); @@ -4670,7 +4670,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) struct vi_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation)); ((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -4682,7 +4682,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct vi_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct vi_mqd_allocation)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 2c5bb282cc01..93c63ff3b35e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3686,7 +3686,7 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring) gfx_v9_0_kiq_setting(ring); - if (adev->in_gpu_reset) { /* for GPU_RESET case */ + if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3724,7 +3724,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) struct v9_mqd *mqd = ring->mqd_ptr; int mqd_idx = ring - &adev->gfx.compute_ring[0]; - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation)); ((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF; ((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF; @@ -3736,7 +3736,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring) if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(adev->gfx.mec.mqd_backup[mqd_idx], mqd, sizeof(struct v9_mqd_allocation)); - } else if (adev->in_gpu_reset) { /* for GPU_RESET case */ + } else if (amdgpu_in_reset(adev)) { /* for GPU_RESET case */ /* reset MQD to a clean status */ if (adev->gfx.mec.mqd_backup[mqd_idx]) memcpy(mqd, adev->gfx.mec.mqd_backup[mqd_idx], sizeof(struct v9_mqd_allocation)); @@ -3930,7 +3930,7 @@ static int gfx_v9_0_hw_fini(void *handle) /* Use deinitialize sequence from CAIL when unbinding device from driver, * otherwise KIQ is hanging when binding back */ - if (!adev->in_gpu_reset && !adev->in_suspend) { + if (!amdgpu_in_reset(adev) && !adev->in_suspend) { mutex_lock(&adev->srbm_mutex); soc15_grbm_select(adev, adev->gfx.kiq.ring.me, adev->gfx.kiq.ring.pipe, @@ -4088,7 +4088,7 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev) * * also don't wait anymore for IRQ context * */ - if (r < 1 && (adev->in_gpu_reset || in_interrupt())) + if (r < 1 && (amdgpu_in_reset(adev) || in_interrupt())) goto failed_kiq_read; might_sleep(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index ec8c0af39553..9d3b1245a339 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,7 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; @@ -312,7 +312,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, if (!adev->mman.buffer_funcs_enabled || !adev->ib_pool_ready || - adev->in_gpu_reset || + amdgpu_in_reset(adev) || ring->sched.ready == false) { gmc_v10_0_flush_vm_hub(adev, vmid, AMDGPU_GFXHUB_0, 0); mutex_unlock(&adev->mman.gtt_window_lock); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 3ce5c1d2fdf2..80c146df338a 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 3e6615f9d39c..9ab65ca7df77 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 6a780b674018..86f20426c4af 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -501,7 +501,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !adev->in_gpu_reset) { + !amdgpu_in_reset(adev)) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; @@ -596,7 +596,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, struct amdgpu_ring *ring = &adev->gfx.kiq.ring; struct amdgpu_kiq *kiq = &adev->gfx.kiq; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EIO; if (ring->sched.ready) { diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 475ff5df8c87..f27d83f2de78 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -250,7 +250,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) */ locked = mutex_trylock(&adev->lock_reset); if (locked) - adev->in_gpu_reset = true; + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -262,7 +262,7 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) flr_done: if (locked) { - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 9cf695c05db3..3cb10ab943a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -271,7 +271,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) */ locked = mutex_trylock(&adev->lock_reset); if (locked) - adev->in_gpu_reset = true; + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -283,7 +283,7 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) flr_done: if (locked) { - adev->in_gpu_reset = false; + atomic_set(&adev->in_gpu_reset, 0); mutex_unlock(&adev->lock_reset); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0a1e53fda08a..b8f36cbcff7b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1658,7 +1658,7 @@ static int dm_suspend(void *handle) struct amdgpu_display_manager *dm = &adev->dm; int ret = 0; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { mutex_lock(&dm->dc_lock); dm->cached_dc_state = dc_copy_state(dm->dc->current_state); @@ -1844,7 +1844,7 @@ static int dm_resume(void *handle) struct dc_state *dc_state; int i, r, j; - if (adev->in_gpu_reset) { + if (amdgpu_in_reset(adev)) { dc_state = dm->cached_dc_state; r = dm_dmub_hw_init(adev); diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index a77f7347fdfc..e469de005451 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -121,7 +121,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, enum amd_pm_state_type pm; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -159,7 +159,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, enum amd_pm_state_type state; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("battery", buf, strlen("battery")) == 0) @@ -265,7 +265,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level level = 0xff; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -307,7 +307,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, enum amd_dpm_forced_level current_level = 0xff; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strncmp("low", buf, strlen("low")) == 0) { @@ -411,7 +411,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, struct pp_states_info data; int i, buf_len, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -455,7 +455,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, enum amd_pm_state_type pm = 0; int i = 0, ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -496,7 +496,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->pp_force_state_enabled) @@ -516,7 +516,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, unsigned long idx; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (strlen(buf) == 1) @@ -576,7 +576,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *table = NULL; int size, ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -620,7 +620,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int ret = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -773,7 +773,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, const char delimiter[3] = {' ', '\n', '\0'}; uint32_t type; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (count > 127) @@ -867,7 +867,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -921,7 +921,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, uint64_t featuremask; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtou64(buf, 0, &featuremask); @@ -966,7 +966,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1027,7 +1027,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1095,7 +1095,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1131,7 +1131,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1163,7 +1163,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, uint32_t mask = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1199,7 +1199,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1231,7 +1231,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1269,7 +1269,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1301,7 +1301,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1339,7 +1339,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1371,7 +1371,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1409,7 +1409,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1441,7 +1441,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, int ret; uint32_t mask = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = amdgpu_read_mask(buf, count, &mask); @@ -1479,7 +1479,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1509,7 +1509,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1552,7 +1552,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, uint32_t value = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1582,7 +1582,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, int ret; long int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = kstrtol(buf, 0, &value); @@ -1645,7 +1645,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, ssize_t size; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -1685,7 +1685,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, long int profile_mode = 0; const char delimiter[3] = {' ', '\n', '\0'}; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; tmp[0] = *(buf); @@ -1749,7 +1749,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1787,7 +1787,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, struct amdgpu_device *adev = ddev->dev_private; int r, value, size = sizeof(value); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(ddev->dev); @@ -1830,7 +1830,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, uint64_t count0 = 0, count1 = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->flags & AMD_IS_APU) @@ -1871,7 +1871,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (adev->unique_id) @@ -1969,7 +1969,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, ssize_t size = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(ddev->dev); @@ -2193,7 +2193,7 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, int channel = to_sensor_dev_attr(attr)->index; int r, temp = 0, size = sizeof(temp); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (channel >= PP_TEMP_MAX) @@ -2329,7 +2329,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2365,7 +2365,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err, ret; int value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2419,7 +2419,7 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2473,7 +2473,7 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2508,7 +2508,7 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, int err; u32 speed = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2542,7 +2542,7 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, u32 size = sizeof(min_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2572,7 +2572,7 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, u32 size = sizeof(max_rpm); int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2601,7 +2601,7 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, int err; u32 rpm = 0; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2635,7 +2635,7 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, u32 value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = pm_runtime_get_sync(adev->ddev->dev); @@ -2686,7 +2686,7 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, u32 pwm_mode = 0; int ret; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; ret = pm_runtime_get_sync(adev->ddev->dev); @@ -2723,7 +2723,7 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, int value; u32 pwm_mode; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; err = kstrtoint(buf, 10, &value); @@ -2768,7 +2768,7 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, u32 vddgfx; int r, size = sizeof(vddgfx); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2805,7 +2805,7 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, u32 vddnb; int r, size = sizeof(vddnb); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; /* only APUs have vddnb */ @@ -2847,7 +2847,7 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, int r, size = sizeof(u32); unsigned uw; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2888,7 +2888,7 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2922,7 +2922,7 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, ssize_t size; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -2957,7 +2957,7 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, int err; u32 value; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; if (amdgpu_sriov_vf(adev)) @@ -3000,7 +3000,7 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, uint32_t sclk; int r, size = sizeof(sclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3037,7 +3037,7 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, uint32_t mclk; int r, size = sizeof(mclk); - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(adev->ddev->dev); @@ -3558,7 +3558,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) u32 flags = 0; int r; - if (adev->in_gpu_reset) + if (amdgpu_in_reset(adev)) return -EPERM; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c index c7216362b68d..da84012b7fd5 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c @@ -489,7 +489,7 @@ static int vega20_setup_asic_task(struct pp_hwmgr *hwmgr) { struct amdgpu_device *adev = (struct amdgpu_device *)(hwmgr->adev); int ret = 0; - bool use_baco = (adev->in_gpu_reset && + bool use_baco = (amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || (adev->in_runpm && amdgpu_asic_supports_baco(adev)); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8eb5b92903cd..8462b30f4fe3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -1110,7 +1110,7 @@ static int smu_disable_dpms(struct smu_context *smu) struct amdgpu_device *adev = smu->adev; int ret = 0; bool use_baco = !smu->is_apu && - ((adev->in_gpu_reset && + ((amdgpu_in_reset(adev) && (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)) || ((adev->in_runpm || adev->in_hibernate) && amdgpu_asic_supports_baco(adev))); -- cgit v1.2.3 From 5049a0526988d575c777db20a52eba5efaadbd2a Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Wed, 19 Aug 2020 10:18:08 +0200 Subject: drm/amd/display: remove unintended executable mode Besides the intended change, commit 4cc1178e166a ("drm/amdgpu: replace DRM prefix with PCI device info for gfx/mmhub") also set the source files mmhub_v1_0.c and gfx_v9_4.c to be executable, i.e., changed fromold mode 644 to new mode 755. Commit 241b2ec9317e ("drm/amd/display: Add dcn30 Headers (v2)") added the four header files {dpcs,dcn}_3_0_0_{offset,sh_mask}.h as executable, i.e., mode 755. Set to the usual modes for source and headers files and clean up those mistakes. No functional change. Reviewed-by: Christian König Signed-off-by: Lukas Bulwahn Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 0 drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h | 0 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h | 0 6 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c mode change 100755 => 100644 drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h mode change 100755 => 100644 drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_offset.h old mode 100755 new mode 100644 diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dpcs_3_0_0_sh_mask.h old mode 100755 new mode 100644 -- cgit v1.2.3 From 26902e8c58c8e147ca126c83a9ba3f3ac8c5cc7b Mon Sep 17 00:00:00 2001 From: Wang Hai Date: Wed, 19 Aug 2020 19:34:09 +0800 Subject: drm/amd/powerplay: remove duplicate include Remove asic_reg/nbio/nbio_6_1_offset.h which is included more than once Reviewed-by: Evan Quan Reported-by: Hulk Robot Signed-off-by: Wang Hai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h index e6d9e84059e1..0d08c57d3bca 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_inc.h @@ -34,7 +34,6 @@ #include "asic_reg/gc/gc_9_2_1_offset.h" #include "asic_reg/gc/gc_9_2_1_sh_mask.h" -#include "asic_reg/nbio/nbio_6_1_offset.h" #include "asic_reg/nbio/nbio_6_1_offset.h" #include "asic_reg/nbio/nbio_6_1_sh_mask.h" -- cgit v1.2.3 From 4c319bbebef5491c1305d7b56e708f566f83d14a Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Thu, 20 Aug 2020 18:58:06 +0100 Subject: drm/amd/pm: Remove unnecessary cast In init_powerplay_table_information() the value returned from kmalloc() is cast unnecessarily. Remove cast. Issue identified with Coccinelle. Signed-off-by: Alex Dewar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c index 195d8539fbb4..740e2fc7a034 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_processpptables.c @@ -252,7 +252,7 @@ static int init_powerplay_table_information( phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT); phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT); - pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; -- cgit v1.2.3 From ba1bab14b61752a9b37d749735f4ce8889e3397a Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Thu, 20 Aug 2020 00:52:41 -0700 Subject: drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in amdgpu_dm_update_backlight_caps In `amdgpu_dm_update_backlight_caps()`, there is a local `amdgpu_dm_backlight_caps` object that is filled in by `amdgpu_acpi_get_backlight_caps()`. However, this object is uninitialized before the call and hence the subsequent check for aux_support can fail since it is not initialized by `amdgpu_acpi_get_backlight_caps()` as well. This change initializes this local `amdgpu_dm_backlight_caps` object to 0. Reviewed-by: Christian König Signed-off-by: Furquan Shaikh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') 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 b8f36cbcff7b..075960864e12 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2927,6 +2927,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) #if defined(CONFIG_ACPI) struct amdgpu_dm_backlight_caps caps; + memset(&caps, 0, sizeof(caps)); + if (dm->backlight_caps.caps_valid) return; -- cgit v1.2.3 From 66b8a9c0a747b9d05509d480f5054a65ac327515 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Fri, 21 Aug 2020 11:30:19 +0800 Subject: drm/amd/pm: enable run_btc callback for sienna_cichlid DC BTC support for sienna_cichlid is added, it provides the DC tolerance and aging measurements. Signed-off-by: Jiansong Chen Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 8ffa8b71b75f..d2320ce7ef0d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -95,6 +95,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), @@ -1735,6 +1736,11 @@ static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, return ret; } +static int sienna_cichlid_run_btc(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); +} + static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -2792,6 +2798,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .mode1_reset = smu_v11_0_mode1_reset, .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .run_btc = sienna_cichlid_run_btc, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, .get_gpu_metrics = sienna_cichlid_get_gpu_metrics, -- cgit v1.2.3 From 6049db43d6dd9cbb9d7f897839d15b0bc600e23c Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Thu, 20 Aug 2020 10:06:32 +0800 Subject: drm/amdgpu: change reset lock from mutex to rw_semaphore clients don't need reset-lock for synchronization when no GPU recovery. v2: change to return the return value of down_read_killable. v3: if GPU recovery begin, VF ignore FLR notification. Reviewed-by: Monk Liu Acked-by: Christian König Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 23 ++++++++++++++++------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c | 18 ++++++------------ drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c | 18 ++++++------------ 5 files changed, 32 insertions(+), 35 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 72f2a9aeaf0e..ba5e8635ca5f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -951,7 +951,7 @@ struct amdgpu_device { atomic_t in_gpu_reset; enum pp_mp1_state mp1_state; - struct mutex lock_reset; + struct rw_semaphore reset_sem; struct amdgpu_doorbell_index doorbell_index; struct mutex notifier_lock; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 79b397800cbc..cc5c7f81c540 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -101,14 +101,18 @@ static int amdgpu_debugfs_autodump_open(struct inode *inode, struct file *file) file->private_data = adev; - mutex_lock(&adev->lock_reset); + ret = down_read_killable(&adev->reset_sem); + if (ret) + return ret; + if (adev->autodump.dumping.done) { reinit_completion(&adev->autodump.dumping); ret = 0; } else { ret = -EBUSY; } - mutex_unlock(&adev->lock_reset); + + up_read(&adev->reset_sem); return ret; } @@ -1242,7 +1246,9 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) } /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + r = down_read_killable(&adev->reset_sem); + if (r) + return r; /* hold on the scheduler */ for (i = 0; i < AMDGPU_MAX_RINGS; i++) { @@ -1269,7 +1275,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) kthread_unpark(ring->sched.thread); } - mutex_unlock(&adev->lock_reset); + up_read(&adev->reset_sem); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1459,7 +1465,9 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) return -ENOMEM; /* Avoid accidently unparking the sched thread during GPU reset */ - mutex_lock(&adev->lock_reset); + r = down_read_killable(&adev->reset_sem); + if (r) + goto pro_end; /* stop the scheduler */ kthread_park(ring->sched.thread); @@ -1500,13 +1508,14 @@ 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); +pro_end: kfree(fences); - return 0; + return r; } static int amdgpu_debugfs_sclk_set(void *data, u64 val) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 78fd2c9a7b7d..82242e2f5658 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3054,7 +3054,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); atomic_set(&adev->in_gpu_reset, 0); - mutex_init(&adev->lock_reset); + init_rwsem(&adev->reset_sem); mutex_init(&adev->psp.mutex); mutex_init(&adev->notifier_lock); @@ -4206,7 +4206,7 @@ static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - mutex_lock(&adev->lock_reset); + down_write(&adev->reset_sem); atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4229,7 +4229,7 @@ static void amdgpu_device_unlock_adev(struct amdgpu_device *adev) amdgpu_vf_error_trans_all(adev); adev->mp1_state = PP_MP1_STATE_NONE; atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); + up_write(&adev->reset_sem); } static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index f27d83f2de78..9c07014d9bd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -238,19 +238,15 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = AI_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. - * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" - * to run gpu_recover() after FLR_NOTIFICATION_CMPL received - * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - atomic_set(&adev->in_gpu_reset, 1); + if (!down_read_trylock(&adev->reset_sem)) + return; + + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_ai_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -261,10 +257,8 @@ static void xgpu_ai_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); - } + atomic_set(&adev->in_gpu_reset, 0); + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c index 3cb10ab943a6..9c23abf9b140 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_nv.c @@ -259,19 +259,15 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) struct amdgpu_virt *virt = container_of(work, struct amdgpu_virt, flr_work); struct amdgpu_device *adev = container_of(virt, struct amdgpu_device, virt); int timeout = NV_MAILBOX_POLL_FLR_TIMEDOUT; - int locked; /* block amdgpu_gpu_recover till msg FLR COMPLETE received, * otherwise the mailbox msg will be ruined/reseted by * the VF FLR. - * - * we can unlock the lock_reset to allow "amdgpu_job_timedout" - * to run gpu_recover() after FLR_NOTIFICATION_CMPL received - * which means host side had finished this VF's FLR. */ - locked = mutex_trylock(&adev->lock_reset); - if (locked) - atomic_set(&adev->in_gpu_reset, 1); + if (!down_read_trylock(&adev->reset_sem)) + return; + + atomic_set(&adev->in_gpu_reset, 1); do { if (xgpu_nv_mailbox_peek_msg(adev) == IDH_FLR_NOTIFICATION_CMPL) @@ -282,10 +278,8 @@ static void xgpu_nv_mailbox_flr_work(struct work_struct *work) } while (timeout > 1); flr_done: - if (locked) { - atomic_set(&adev->in_gpu_reset, 0); - mutex_unlock(&adev->lock_reset); - } + atomic_set(&adev->in_gpu_reset, 0); + up_read(&adev->reset_sem); /* Trigger recovery for world switch failure if no TDR */ if (amdgpu_device_should_recover_gpu(adev) -- cgit v1.2.3 From cbfd17f7ba405d143c0db5ebcddc978cb4153762 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Thu, 20 Aug 2020 10:17:39 +0800 Subject: drm/amdgpu: fix the nullptr issue when reenter GPU recovery in single gpu system, if driver reenter gpu recovery, amdgpu_device_lock_adev will return false, but hive is nullptr now. Reviewed-by: Hawking Zhang Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 82242e2f5658..81b1d9a1dca0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4371,8 +4371,8 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, if (!amdgpu_device_lock_adev(tmp_adev)) { DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); - mutex_unlock(&hive->hive_lock); - return 0; + r = 0; + goto skip_recovery; } /* @@ -4505,6 +4505,7 @@ skip_sched_resume: amdgpu_device_unlock_adev(tmp_adev); } +skip_recovery: if (hive) { atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); -- cgit v1.2.3 From aac891685da661aeb97691e8724df231130bb452 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Thu, 20 Aug 2020 10:40:53 +0800 Subject: drm/amdgpu: refine message print for devices of hive Using dev_xxx instead of DRM_xxx/pr_xxx to indicate which device of a hive is the message for. Reviewed-by: Christian König Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 32 +++++++++++++++--------------- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 81b1d9a1dca0..08548e051cc0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3370,7 +3370,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) { int r; - DRM_INFO("amdgpu: finishing device.\n"); + dev_info(adev->dev, "amdgpu: finishing device.\n"); flush_delayed_work(&adev->delayed_init_work); adev->shutdown = true; @@ -3555,12 +3555,12 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) if (amdgpu_device_need_post(adev)) { r = amdgpu_atom_asic_init(adev->mode_info.atom_context); if (r) - DRM_ERROR("amdgpu asic init failed\n"); + dev_err(adev->dev, "amdgpu asic init failed\n"); } r = amdgpu_device_ip_resume(adev); if (r) { - DRM_ERROR("amdgpu_device_ip_resume failed (%d).\n", r); + dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r); return r; } amdgpu_fence_driver_resume(adev); @@ -3584,7 +3584,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) if (r == 0) { r = amdgpu_bo_pin(aobj, AMDGPU_GEM_DOMAIN_VRAM); if (r != 0) - DRM_ERROR("Failed to pin cursor BO (%d)\n", r); + dev_err(adev->dev, "Failed to pin cursor BO (%d)\n", r); amdgpu_crtc->cursor_addr = amdgpu_bo_gpu_offset(aobj); amdgpu_bo_unreserve(aobj); } @@ -3674,7 +3674,7 @@ static bool amdgpu_device_ip_check_soft_reset(struct amdgpu_device *adev) adev->ip_blocks[i].status.hang = adev->ip_blocks[i].version->funcs->check_soft_reset(adev); if (adev->ip_blocks[i].status.hang) { - DRM_INFO("IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name); + dev_info(adev->dev, "IP block:%s is hung!\n", adev->ip_blocks[i].version->funcs->name); asic_hang = true; } } @@ -3735,7 +3735,7 @@ static bool amdgpu_device_ip_need_full_reset(struct amdgpu_device *adev) (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) || adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) { if (adev->ip_blocks[i].status.hang) { - DRM_INFO("Some block need full reset!\n"); + dev_info(adev->dev, "Some block need full reset!\n"); return true; } } @@ -3823,7 +3823,7 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) else tmo = msecs_to_jiffies(100); - DRM_INFO("recover vram bo from shadow start\n"); + dev_info(adev->dev, "recover vram bo from shadow start\n"); mutex_lock(&adev->shadow_list_lock); list_for_each_entry(shadow, &adev->shadow_list, shadow_list) { @@ -3859,11 +3859,11 @@ static int amdgpu_device_recover_vram(struct amdgpu_device *adev) dma_fence_put(fence); if (r < 0 || tmo <= 0) { - DRM_ERROR("recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo); + dev_err(adev->dev, "recover vram bo from shadow failed, r is %ld, tmo is %ld\n", r, tmo); return -EIO; } - DRM_INFO("recover vram bo from shadow done\n"); + dev_info(adev->dev, "recover vram bo from shadow done\n"); return 0; } @@ -3962,7 +3962,7 @@ bool amdgpu_device_has_job_running(struct amdgpu_device *adev) bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) { if (!amdgpu_device_ip_check_soft_reset(adev)) { - DRM_INFO("Timeout, but no hardware hang detected.\n"); + dev_info(adev->dev, "Timeout, but no hardware hang detected.\n"); return false; } @@ -4002,7 +4002,7 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev) return true; disabled: - DRM_INFO("GPU recovery disabled.\n"); + dev_info(adev->dev, "GPU recovery disabled.\n"); return false; } @@ -4041,7 +4041,7 @@ static int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev, r = amdgpu_device_ip_soft_reset(adev); amdgpu_device_ip_post_soft_reset(adev); if (r || amdgpu_device_ip_check_soft_reset(adev)) { - DRM_INFO("soft reset failed, will fallback to full reset!\n"); + dev_info(adev->dev, "soft reset failed, will fallback to full reset!\n"); need_full_reset = true; } } @@ -4077,7 +4077,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, r = amdgpu_asic_reset(tmp_adev); if (r) { - DRM_ERROR("ASIC reset failed with error, %d for drm dev, %s", + dev_err(tmp_adev->dev, "ASIC reset failed with error, %d for drm dev, %s", r, tmp_adev->ddev->unique); break; } @@ -4111,7 +4111,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, if (need_full_reset) { /* post card */ if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) - DRM_WARN("asic atom init failed!"); + dev_warn(tmp_adev->dev, "asic atom init failed!"); if (!r) { dev_info(tmp_adev->dev, "GPU reset succeeded, trying to resume\n"); @@ -4369,7 +4369,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (!amdgpu_device_lock_adev(tmp_adev)) { - DRM_INFO("Bailing on TDR for s_job:%llx, as another already in progress", + dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; goto skip_recovery; @@ -4444,7 +4444,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ &need_full_reset); /*TODO Should we stop ?*/ if (r) { - DRM_ERROR("GPU pre asic reset failed with err, %d for drm dev, %s ", + dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ", r, tmp_adev->ddev->unique); tmp_adev->asic_reset_res = r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index ebea3f655826..d6981425ec51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -743,7 +743,7 @@ failed_unlock: failed_kiq_read: if (reg_val_offs) amdgpu_device_wb_free(adev, reg_val_offs); - pr_err("failed to read reg:%x\n", reg); + dev_err(adev->dev, "failed to read reg:%x\n", reg); return ~0; } @@ -796,5 +796,5 @@ 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_err(adev->dev, "failed to write reg:%x\n", reg); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ae720a6dc5a0..d84649b4d51a 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_err(adev->dev, "failed to write reg %x wait reg %x\n", reg0, reg1); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index 9d3b1245a339..ad9ad622ccce 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -390,7 +390,7 @@ static int gmc_v10_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); return -ETIME; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 86f20426c4af..e1a0ae327cf5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -633,7 +633,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, spin_unlock(&adev->gfx.kiq.ring_lock); r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); return -ETIME; } -- cgit v1.2.3 From d95e8e97e2d522b7ebb1d5a64c01d8de307621dc Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Tue, 18 Aug 2020 18:44:17 +0800 Subject: drm/amdgpu: refine create and release logic of hive info Change to dynamically create and release hive info object, which help driver support more hives in the future. v2: Change to save hive object pointer in adev, to avoid locking xgmi_mutex every time when calling amdgpu_get_xgmi_hive. v3: 1. Change type of hive object pointer in adev from void* to amdgpu_hive_info*. 2. remove unnecessary variable initialization. Reviewed-by: Hawking Zhang Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 7 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 208 ++++++++++++++++------------- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h | 14 +- 5 files changed, 131 insertions(+), 106 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ba5e8635ca5f..486113b2bfd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -251,6 +251,7 @@ struct amdgpu_fpriv; struct amdgpu_bo_va_mapping; struct amdgpu_atif; struct kfd_vm_fault_info; +struct amdgpu_hive_info; enum amdgpu_cp_irq { AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP = 0, @@ -727,7 +728,7 @@ struct amdgpu_device { #ifdef CONFIG_DRM_AMD_ACP struct amdgpu_acp acp; #endif - + struct amdgpu_hive_info *hive; /* ASIC */ enum amd_asic_type asic_type; uint32_t family; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 08548e051cc0..a4300af5797b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2857,7 +2857,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) { struct amdgpu_device *adev = container_of(__work, struct amdgpu_device, xgmi_reset_work); - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); /* It's a bug to not have a hive within this function */ if (WARN_ON(!hive)) @@ -2895,6 +2895,7 @@ fail: if (adev->asic_reset_res) DRM_WARN("ASIC reset failed with error, %d for drm dev, %s", adev->asic_reset_res, adev->ddev->unique); + amdgpu_put_xgmi_hive(hive); } static int amdgpu_device_get_job_timeout_settings(struct amdgpu_device *adev) @@ -4339,11 +4340,12 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, * We always reset all schedulers for device and all devices for XGMI * hive so that should take care of them too. */ - hive = amdgpu_get_xgmi_hive(adev, false); + hive = amdgpu_get_xgmi_hive(adev); if (hive) { if (atomic_cmpxchg(&hive->in_reset, 0, 1) != 0) { DRM_INFO("Bailing on TDR for s_job:%llx, hive: %llx as another already in progress", job ? job->base.id : -1, hive->hive_id); + amdgpu_put_xgmi_hive(hive); return 0; } mutex_lock(&hive->hive_lock); @@ -4509,6 +4511,7 @@ skip_recovery: if (hive) { atomic_set(&hive->in_reset, 0); mutex_unlock(&hive->hive_lock); + amdgpu_put_xgmi_hive(hive); } if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index fa2c28ae9785..ec377a8147a2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1554,9 +1554,10 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) struct amdgpu_device *remote_adev = NULL; struct amdgpu_device *adev = ras->adev; struct list_head device_list, *device_list_handle = NULL; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, false); if (!ras->disable_ras_err_cnt_harvest) { + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); + /* Build list of devices to query RAS related errors */ if (hive && adev->gmc.xgmi.num_physical_nodes > 1) { device_list_handle = &hive->device_list; @@ -1569,6 +1570,8 @@ static void amdgpu_ras_do_recovery(struct work_struct *work) list_for_each_entry(remote_adev, device_list_handle, gmc.xgmi.head) amdgpu_ras_log_on_err_counter(remote_adev); + + amdgpu_put_xgmi_hive(hive); } if (amdgpu_device_should_recover_gpu(ras->adev)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 7a61dc6738eb..08ed4dddfaf1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -35,11 +35,9 @@ static DEFINE_MUTEX(xgmi_mutex); -#define AMDGPU_MAX_XGMI_HIVE 8 #define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4 -static struct amdgpu_hive_info xgmi_hives[AMDGPU_MAX_XGMI_HIVE]; -static unsigned hive_count = 0; +static LIST_HEAD(xgmi_hive_list); static const int xgmi_pcs_err_status_reg_vg20[] = { smnXGMI0_PCS_GOPX16_PCS_ERROR_STATUS, @@ -171,59 +169,47 @@ static const struct amdgpu_pcs_ras_field wafl_pcs_ras_fields[] = { * */ +static struct attribute amdgpu_xgmi_hive_id = { + .name = "xgmi_hive_id", + .mode = S_IRUGO +}; -static ssize_t amdgpu_xgmi_show_hive_id(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct amdgpu_hive_info *hive = - container_of(attr, struct amdgpu_hive_info, dev_attr); - - return snprintf(buf, PAGE_SIZE, "%llu\n", hive->hive_id); -} +static struct attribute *amdgpu_xgmi_hive_attrs[] = { + &amdgpu_xgmi_hive_id, + NULL +}; -static int amdgpu_xgmi_sysfs_create(struct amdgpu_device *adev, - struct amdgpu_hive_info *hive) +static ssize_t amdgpu_xgmi_show_attrs(struct kobject *kobj, + struct attribute *attr, char *buf) { - int ret = 0; - - if (WARN_ON(hive->kobj)) - return -EINVAL; - - hive->kobj = kobject_create_and_add("xgmi_hive_info", &adev->dev->kobj); - if (!hive->kobj) { - dev_err(adev->dev, "XGMI: Failed to allocate sysfs entry!\n"); - return -EINVAL; - } - - hive->dev_attr = (struct device_attribute) { - .attr = { - .name = "xgmi_hive_id", - .mode = S_IRUGO, + struct amdgpu_hive_info *hive = container_of( + kobj, struct amdgpu_hive_info, kobj); - }, - .show = amdgpu_xgmi_show_hive_id, - }; - - ret = sysfs_create_file(hive->kobj, &hive->dev_attr.attr); - if (ret) { - dev_err(adev->dev, "XGMI: Failed to create device file xgmi_hive_id\n"); - kobject_del(hive->kobj); - kobject_put(hive->kobj); - hive->kobj = NULL; - } + if (attr == &amdgpu_xgmi_hive_id) + return snprintf(buf, PAGE_SIZE, "%llu\n", hive->hive_id); - return ret; + return 0; } -static void amdgpu_xgmi_sysfs_destroy(struct amdgpu_device *adev, - struct amdgpu_hive_info *hive) +static void amdgpu_xgmi_hive_release(struct kobject *kobj) { - sysfs_remove_file(hive->kobj, &hive->dev_attr.attr); - kobject_del(hive->kobj); - kobject_put(hive->kobj); - hive->kobj = NULL; + struct amdgpu_hive_info *hive = container_of( + kobj, struct amdgpu_hive_info, kobj); + + mutex_destroy(&hive->hive_lock); + kfree(hive); } +static const struct sysfs_ops amdgpu_xgmi_hive_ops = { + .show = amdgpu_xgmi_show_attrs, +}; + +struct kobj_type amdgpu_xgmi_hive_type = { + .release = amdgpu_xgmi_hive_release, + .sysfs_ops = &amdgpu_xgmi_hive_ops, + .default_attrs = amdgpu_xgmi_hive_attrs, +}; + static ssize_t amdgpu_xgmi_show_device_id(struct device *dev, struct device_attribute *attr, char *buf) @@ -287,8 +273,8 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, /* Create sysfs link to hive info folder on the first device */ - if (adev != hive->adev) { - ret = sysfs_create_link(&adev->dev->kobj, hive->kobj, + if (hive->kobj.parent != (&adev->dev->kobj)) { + ret = sysfs_create_link(&adev->dev->kobj, &hive->kobj, "xgmi_hive_info"); if (ret) { dev_err(adev->dev, "XGMI: Failed to create link to hive info"); @@ -296,9 +282,9 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, } } - sprintf(node, "node%d", hive->number_devices); + sprintf(node, "node%d", atomic_read(&hive->number_devices)); /* Create sysfs link form the hive folder to yourself */ - ret = sysfs_create_link(hive->kobj, &adev->dev->kobj, node); + ret = sysfs_create_link(&hive->kobj, &adev->dev->kobj, node); if (ret) { dev_err(adev->dev, "XGMI: Failed to create link from hive info"); goto remove_link; @@ -326,78 +312,96 @@ static void amdgpu_xgmi_sysfs_rem_dev_info(struct amdgpu_device *adev, device_remove_file(adev->dev, &dev_attr_xgmi_device_id); device_remove_file(adev->dev, &dev_attr_xgmi_error); - if (adev != hive->adev) + if (hive->kobj.parent != (&adev->dev->kobj)) sysfs_remove_link(&adev->dev->kobj,"xgmi_hive_info"); - sprintf(node, "node%d", hive->number_devices); - sysfs_remove_link(hive->kobj, node); + sprintf(node, "node%d", atomic_read(&hive->number_devices)); + sysfs_remove_link(&hive->kobj, node); } -struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock) +struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev) { - int i; - struct amdgpu_hive_info *tmp; + struct amdgpu_hive_info *hive = NULL, *tmp = NULL; + int ret; if (!adev->gmc.xgmi.hive_id) return NULL; + if (adev->hive) { + kobject_get(&adev->hive->kobj); + return adev->hive; + } + mutex_lock(&xgmi_mutex); - for (i = 0 ; i < hive_count; ++i) { - tmp = &xgmi_hives[i]; - if (tmp->hive_id == adev->gmc.xgmi.hive_id) { - if (lock) - mutex_lock(&tmp->hive_lock); - mutex_unlock(&xgmi_mutex); - return tmp; + if (!list_empty(&xgmi_hive_list)) { + list_for_each_entry_safe(hive, tmp, &xgmi_hive_list, node) { + if (hive->hive_id == adev->gmc.xgmi.hive_id) + goto pro_end; } } - if (i >= AMDGPU_MAX_XGMI_HIVE) { - mutex_unlock(&xgmi_mutex); - return NULL; + + hive = kzalloc(sizeof(*hive), GFP_KERNEL); + if (!hive) { + dev_err(adev->dev, "XGMI: allocation failed\n"); + hive = NULL; + goto pro_end; } /* initialize new hive if not exist */ - tmp = &xgmi_hives[hive_count++]; - - if (amdgpu_xgmi_sysfs_create(adev, tmp)) { - mutex_unlock(&xgmi_mutex); - return NULL; + ret = kobject_init_and_add(&hive->kobj, + &amdgpu_xgmi_hive_type, + &adev->dev->kobj, + "%s", "xgmi_hive_info"); + if (ret) { + dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n"); + kfree(hive); + hive = NULL; + goto pro_end; } - tmp->adev = adev; - tmp->hive_id = adev->gmc.xgmi.hive_id; - INIT_LIST_HEAD(&tmp->device_list); - mutex_init(&tmp->hive_lock); - atomic_set(&tmp->in_reset, 0); - task_barrier_init(&tmp->tb); - - if (lock) - mutex_lock(&tmp->hive_lock); - tmp->pstate = AMDGPU_XGMI_PSTATE_UNKNOWN; - tmp->hi_req_gpu = NULL; + hive->hive_id = adev->gmc.xgmi.hive_id; + INIT_LIST_HEAD(&hive->device_list); + INIT_LIST_HEAD(&hive->node); + mutex_init(&hive->hive_lock); + atomic_set(&hive->in_reset, 0); + atomic_set(&hive->number_devices, 0); + task_barrier_init(&hive->tb); + hive->pstate = AMDGPU_XGMI_PSTATE_UNKNOWN; + hive->hi_req_gpu = NULL; /* * hive pstate on boot is high in vega20 so we have to go to low * pstate on after boot. */ - tmp->hi_req_count = AMDGPU_MAX_XGMI_DEVICE_PER_HIVE; + hive->hi_req_count = AMDGPU_MAX_XGMI_DEVICE_PER_HIVE; + list_add_tail(&hive->node, &xgmi_hive_list); + +pro_end: + if (hive) + kobject_get(&hive->kobj); mutex_unlock(&xgmi_mutex); + return hive; +} - return tmp; +void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive) +{ + if (hive) + kobject_put(&hive->kobj); } int amdgpu_xgmi_set_pstate(struct amdgpu_device *adev, int pstate) { int ret = 0; - struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev, 0); + struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev); struct amdgpu_device *request_adev = hive->hi_req_gpu ? hive->hi_req_gpu : adev; bool is_hi_req = pstate == AMDGPU_XGMI_PSTATE_MAX_VEGA20; bool init_low = hive->pstate == AMDGPU_XGMI_PSTATE_UNKNOWN; + amdgpu_put_xgmi_hive(hive); /* fw bug so temporarily disable pstate switching */ return 0; @@ -449,7 +453,7 @@ int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_dev /* Each psp need to set the latest topology */ ret = psp_xgmi_set_topology_info(&adev->psp, - hive->number_devices, + atomic_read(&hive->number_devices), &adev->psp.xgmi_context.top_info); if (ret) dev_err(adev->dev, @@ -511,7 +515,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) adev->gmc.xgmi.node_id = adev->gmc.xgmi.physical_node_id + 16; } - hive = amdgpu_get_xgmi_hive(adev, 1); + hive = amdgpu_get_xgmi_hive(adev); if (!hive) { ret = -EINVAL; dev_err(adev->dev, @@ -519,6 +523,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) adev->gmc.xgmi.node_id, adev->gmc.xgmi.hive_id); goto exit; } + mutex_lock(&hive->hive_lock); top_info = &adev->psp.xgmi_context.top_info; @@ -526,7 +531,7 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) list_for_each_entry(entry, &hive->device_list, head) top_info->nodes[count++].node_id = entry->node_id; top_info->num_nodes = count; - hive->number_devices = count; + atomic_set(&hive->number_devices, count); task_barrier_add_task(&hive->tb); @@ -565,35 +570,48 @@ int amdgpu_xgmi_add_device(struct amdgpu_device *adev) exit_unlock: mutex_unlock(&hive->hive_lock); exit: - if (!ret) + if (!ret) { + adev->hive = hive; dev_info(adev->dev, "XGMI: Add node %d, hive 0x%llx.\n", adev->gmc.xgmi.physical_node_id, adev->gmc.xgmi.hive_id); - else + } else { + amdgpu_put_xgmi_hive(hive); dev_err(adev->dev, "XGMI: Failed to add node %d, hive 0x%llx ret: %d\n", adev->gmc.xgmi.physical_node_id, adev->gmc.xgmi.hive_id, ret); + } return ret; } int amdgpu_xgmi_remove_device(struct amdgpu_device *adev) { - struct amdgpu_hive_info *hive; + struct amdgpu_hive_info *hive = adev->hive; if (!adev->gmc.xgmi.supported) return -EINVAL; - hive = amdgpu_get_xgmi_hive(adev, 1); if (!hive) return -EINVAL; + mutex_lock(&hive->hive_lock); task_barrier_rem_task(&hive->tb); amdgpu_xgmi_sysfs_rem_dev_info(adev, hive); + if (hive->hi_req_gpu == adev) + hive->hi_req_gpu = NULL; + list_del(&adev->gmc.xgmi.head); mutex_unlock(&hive->hive_lock); - if(!(--hive->number_devices)){ - amdgpu_xgmi_sysfs_destroy(adev, hive); - mutex_destroy(&hive->hive_lock); + amdgpu_put_xgmi_hive(hive); + adev->hive = NULL; + + if (atomic_dec_return(&hive->number_devices) == 0) { + /* Remove the hive from global hive list */ + mutex_lock(&xgmi_mutex); + list_del(&hive->node); + mutex_unlock(&xgmi_mutex); + + amdgpu_put_xgmi_hive(hive); } return psp_xgmi_terminate(&adev->psp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h index 453336ca9675..148560d63554 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h @@ -27,13 +27,12 @@ struct amdgpu_hive_info { - uint64_t hive_id; - struct list_head device_list; - int number_devices; + struct kobject kobj; + uint64_t hive_id; + struct list_head device_list; + struct list_head node; + atomic_t number_devices; struct mutex hive_lock; - struct kobject *kobj; - struct device_attribute dev_attr; - struct amdgpu_device *adev; atomic_t in_reset; int hi_req_count; struct amdgpu_device *hi_req_gpu; @@ -51,7 +50,8 @@ struct amdgpu_pcs_ras_field { uint32_t pcs_err_shift; }; -struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev, int lock); +struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev); +void amdgpu_put_xgmi_hive(struct amdgpu_hive_info *hive); int amdgpu_xgmi_update_topology(struct amdgpu_hive_info *hive, struct amdgpu_device *adev); int amdgpu_xgmi_add_device(struct amdgpu_device *adev); int amdgpu_xgmi_remove_device(struct amdgpu_device *adev); -- cgit v1.2.3 From 08ebb485f0ee8ba1c9ca3f83c9cdbda32b357869 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Thu, 6 Aug 2020 14:48:15 +0800 Subject: drm/amdgpu: annotate a false positive recursive locking Re-apply commit 72e14ebf9fc09e33b28b70f00a2ed9821c198633 [ 584.110304] ============================================ [ 584.110590] WARNING: possible recursive locking detected [ 584.110876] 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 Tainted: G OE [ 584.111164] -------------------------------------------- [ 584.111456] kworker/38:1/553 is trying to acquire lock: [ 584.111721] ffff9b15ff0a47a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.112112] but task is already holding lock: [ 584.112673] ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.113068] other info that might help us debug this: [ 584.113689] Possible unsafe locking scenario: [ 584.114350] CPU0 [ 584.114685] ---- [ 584.115014] lock(&adev->reset_sem); [ 584.115349] lock(&adev->reset_sem); [ 584.115678] *** DEADLOCK *** [ 584.116624] May be due to missing lock nesting notation [ 584.117284] 4 locks held by kworker/38:1/553: [ 584.117616] #0: ffff9ad635c1d348 ((wq_completion)events){+.+.}, at: process_one_work+0x21f/0x630 [ 584.117967] #1: ffffac708e1c3e58 ((work_completion)(&con->recovery_work)){+.+.}, at: process_one_work+0x21f/0x630 [ 584.118358] #2: ffffffffc1c2a5d0 (&tmp->hive_lock){+.+.}, at: amdgpu_device_gpu_recover+0xae/0x1030 [amdgpu] [ 584.118786] #3: ffff9b1603d247a0 (&adev->reset_sem){++++}, at: amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.119222] stack backtrace: [ 584.119990] CPU: 38 PID: 553 Comm: kworker/38:1 Kdump: loaded Tainted: G OE 5.6.0-deli-v5.6-2848-g3f3109b0e75f #1 [ 584.120782] Hardware name: Supermicro SYS-7049GP-TRT/X11DPG-QT, BIOS 3.1 05/23/2019 [ 584.121223] Workqueue: events amdgpu_ras_do_recovery [amdgpu] [ 584.121638] Call Trace: [ 584.122050] dump_stack+0x98/0xd5 [ 584.122499] __lock_acquire+0x1139/0x16e0 [ 584.122931] ? trace_hardirqs_on+0x3b/0xf0 [ 584.123358] ? cancel_delayed_work+0xa6/0xc0 [ 584.123771] lock_acquire+0xb8/0x1c0 [ 584.124197] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.124599] down_write+0x49/0x120 [ 584.125032] ? amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125472] amdgpu_device_gpu_recover+0x262/0x1030 [amdgpu] [ 584.125910] ? amdgpu_ras_error_query+0x1b8/0x2a0 [amdgpu] [ 584.126367] amdgpu_ras_do_recovery+0x159/0x190 [amdgpu] [ 584.126789] process_one_work+0x29e/0x630 [ 584.127208] worker_thread+0x3c/0x3f0 [ 584.127621] ? __kthread_parkme+0x61/0x90 [ 584.128014] kthread+0x12f/0x150 [ 584.128402] ? process_one_work+0x630/0x630 [ 584.128790] ? kthread_park+0x90/0x90 [ 584.129174] ret_from_fork+0x3a/0x50 Each adev has owned lock_class_key to avoid false positive recursive locking. v2: 1. register adev->lock_key into lockdep, otherwise lockdep will report the below warning [ 1216.705820] BUG: key ffff890183b647d0 has not been registered! [ 1216.705924] ------------[ cut here ]------------ [ 1216.705972] DEBUG_LOCKS_WARN_ON(1) [ 1216.705997] WARNING: CPU: 20 PID: 541 at kernel/locking/lockdep.c:3743 lockdep_init_map+0x150/0x210 v3: change to use down_write_nest_lock to annotate the false dead-lock warning. Reviewed-by: Daniel Vetter Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index a4300af5797b..172dc47b7f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -4202,12 +4202,17 @@ end: return r; } -static bool amdgpu_device_lock_adev(struct amdgpu_device *adev) +static bool amdgpu_device_lock_adev(struct amdgpu_device *adev, + struct amdgpu_hive_info *hive) { if (atomic_cmpxchg(&adev->in_gpu_reset, 0, 1) != 0) return false; - down_write(&adev->reset_sem); + if (hive) { + down_write_nest_lock(&adev->reset_sem, &hive->hive_lock); + } else { + down_write(&adev->reset_sem); + } atomic_inc(&adev->gpu_reset_counter); switch (amdgpu_asic_reset_method(adev)) { @@ -4370,7 +4375,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, /* block all schedulers and reset given job's ring */ list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { - if (!amdgpu_device_lock_adev(tmp_adev)) { + if (!amdgpu_device_lock_adev(tmp_adev, hive)) { dev_info(tmp_adev->dev, "Bailing on TDR for s_job:%llx, as another already in progress", job ? job->base.id : -1); r = 0; -- cgit v1.2.3 From 6ec46653eb80d4d97b18298d81a80cf2ca81066c Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Fri, 21 Aug 2020 16:20:47 +0800 Subject: drm/amd/pm: set VCN pg per instances When deciding whether to set pg for vcn1, instances number is more generic than chip name. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index d2320ce7ef0d..66d655958a78 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -783,7 +783,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0x10000, NULL); if (ret) @@ -795,7 +795,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0x10000, NULL); if (ret) -- cgit v1.2.3 From d844812b28421c3409215a128a48ecfdaa82b91e Mon Sep 17 00:00:00 2001 From: Prike.Liang Date: Mon, 1 Jun 2020 14:07:13 +0800 Subject: drm/amdgpu: enable ATHUB clock gatting Enable ATHUB clock gatting set in Renoir series. Signed-off-by: Prike.Liang Reviewed-by: Evan Quan Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/athub_v1_0.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c index 847ca9b3ce4e..3ea557864320 100644 --- a/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/athub_v1_0.c @@ -73,6 +73,7 @@ int athub_v1_0_set_clockgating(struct amdgpu_device *adev, case CHIP_VEGA12: case CHIP_VEGA20: case CHIP_RAVEN: + case CHIP_RENOIR: athub_update_medium_grain_clock_gating(adev, state == AMD_CG_STATE_GATE); athub_update_medium_grain_light_sleep(adev, -- cgit v1.2.3 From 50166d1ce59e8f78660102ac07fea515ed695234 Mon Sep 17 00:00:00 2001 From: Prike.Liang Date: Mon, 1 Jun 2020 14:10:54 +0800 Subject: drm/amdgpu: enable HDP clock gatting Enabe HDP SD/DS clock gatting in Renoir series. Signed-off-by: Prike.Liang Reviewed-by: Evan Quan Reviewed-by: Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/soc15.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3cd98c144bc6..3c3a7adad024 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1452,7 +1452,8 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable uint32_t def, data; if (adev->asic_type == CHIP_VEGA20 || - adev->asic_type == CHIP_ARCTURUS) { + adev->asic_type == CHIP_ARCTURUS || + adev->asic_type == CHIP_RENOIR) { def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL)); if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) -- cgit v1.2.3 From 1348969ab68cb864034ec4fe48a86c157cc4e10d Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Mon, 24 Aug 2020 12:27:47 -0400 Subject: drm/amdgpu: drm_device to amdgpu_device by inline-f (v2) Get the amdgpu_device from the DRM device by use of an inline function, drm_to_adev(). The inline function resolves a pointer to struct drm_device to a pointer to struct amdgpu_device. v2: Use a typed visible static inline function instead of an invisible macro. Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 18 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 8 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 12 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 12 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 16 ++--- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c | 10 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 4 +- drivers/gpu/drm/amd/amdgpu/atombios_crtc.c | 22 +++--- drivers/gpu/drm/amd/amdgpu/atombios_dp.c | 6 +- drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 34 ++++----- drivers/gpu/drm/amd/amdgpu/atombios_i2c.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 48 ++++++------- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 50 +++++++------- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 58 ++++++++-------- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 48 ++++++------- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 4 +- drivers/gpu/drm/amd/amdgpu/df_v3_6.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 61 ++++++++--------- .../drm/amd/display/amdgpu_dm/amdgpu_dm_color.c | 3 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c | 2 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 80 +++++++++++----------- 44 files changed, 303 insertions(+), 300 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 486113b2bfd4..f33a1f372681 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -986,6 +986,11 @@ struct amdgpu_device { struct ratelimit_state throttling_logging_rs; }; +static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) +{ + return ddev->dev_private; +} + static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) { return container_of(bdev, struct amdgpu_device, mman.bdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 0effc1d46824..b74846fc3933 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -483,7 +483,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, /* Can't handle buffers from different drivers */ goto out_put; - adev = obj->dev->dev_private; + adev = drm_to_adev(obj->dev); bo = gem_to_amdgpu_bo(obj); if (!(bo->preferred_domains & (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT))) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 62cb510e2cc4..517eb00b836a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1674,7 +1674,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct kgd_dev *kgd, return -EINVAL; obj = dma_buf->priv; - if (obj->dev->dev_private != adev) + if (drm_to_adev(obj->dev) != adev) /* Can't handle buffers from other devices */ return -EINVAL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index e33f63712b46..662cc414ceec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1882,7 +1882,7 @@ static void cail_mc_write(struct card_info *info, uint32_t reg, uint32_t val) */ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); WREG32(reg, val); } @@ -1898,7 +1898,7 @@ static void cail_reg_write(struct card_info *info, uint32_t reg, uint32_t val) */ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); uint32_t r; r = RREG32(reg); @@ -1916,7 +1916,7 @@ static uint32_t cail_reg_read(struct card_info *info, uint32_t reg) */ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); WREG32_IO(reg, val); } @@ -1932,7 +1932,7 @@ static void cail_ioreg_write(struct card_info *info, uint32_t reg, uint32_t val) */ static uint32_t cail_ioreg_read(struct card_info *info, uint32_t reg) { - struct amdgpu_device *adev = info->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(info->dev); uint32_t r; r = RREG32_IO(reg); @@ -1944,7 +1944,7 @@ static ssize_t amdgpu_atombios_get_vbios_version(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct atom_context *ctx = adev->mode_info.atom_context; return snprintf(buf, PAGE_SIZE, "%s\n", ctx->vbios_version); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c index 4053597b3af2..15c45b2a3983 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.c @@ -265,7 +265,7 @@ error_free: int amdgpu_bo_list_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; union drm_amdgpu_bo_list *args = data; uint32_t handle = args->in.list_handle; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index a1aec205435d..3bce625189ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -41,7 +41,7 @@ void amdgpu_connector_hotplug(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); /* bail if the connector does not have hpd pin, e.g., @@ -279,7 +279,7 @@ amdgpu_connector_get_hardcoded_edid(struct amdgpu_device *adev) static void amdgpu_connector_get_edid(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); if (amdgpu_connector->edid) @@ -463,7 +463,7 @@ static int amdgpu_connector_set_property(struct drm_connector *connector, uint64_t val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; @@ -834,7 +834,7 @@ static enum drm_mode_status amdgpu_connector_vga_mode_valid(struct drm_connector struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* XXX check mode bandwidth */ @@ -941,7 +941,7 @@ static bool amdgpu_connector_check_hpd_status_unchanged(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); enum drm_connector_status status; @@ -972,7 +972,7 @@ static enum drm_connector_status amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); const struct drm_encoder_helper_funcs *encoder_funcs; int r; @@ -1159,7 +1159,7 @@ static enum drm_mode_status amdgpu_connector_dvi_mode_valid(struct drm_connector struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); /* XXX check mode bandwidth */ @@ -1311,7 +1311,7 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector) bool amdgpu_connector_is_dp12_capable(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if ((adev->clock.default_dispclk >= 53900) && amdgpu_connector_encoder_is_hbr2(connector)) { @@ -1325,7 +1325,7 @@ static enum drm_connector_status amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); enum drm_connector_status ret = connector_status_disconnected; struct amdgpu_connector_atom_dig *amdgpu_dig_connector = amdgpu_connector->con_priv; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index e84a6e0bc784..690648785b3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -1288,7 +1288,7 @@ static void trace_amdgpu_cs_ibs(struct amdgpu_cs_parser *parser) int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser parser = {}; bool reserved_buffers = false; @@ -1432,7 +1432,7 @@ static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev, int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_fence_to_handle *info = data; struct dma_fence *fence; struct drm_syncobj *syncobj; @@ -1608,7 +1608,7 @@ err_free_fence_array: int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union drm_amdgpu_wait_fences *wait = data; uint32_t fence_count = wait->in.fence_count; struct drm_amdgpu_fence *fences_user; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index ba243cc8f585..59032c26fc82 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -385,7 +385,7 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, enum drm_sched_priority priority; union drm_amdgpu_ctx *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; id = args->in.ctx_id; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index cc5c7f81c540..37eb8e77d61e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1236,7 +1236,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r = 0, i; r = pm_runtime_get_sync(dev->dev); @@ -1287,7 +1287,7 @@ static int amdgpu_debugfs_get_vbios_dump(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); seq_write(m, adev->bios, adev->bios_size); return 0; @@ -1297,7 +1297,7 @@ static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); @@ -1318,7 +1318,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 172dc47b7f39..06aa0a98f4a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -132,7 +132,7 @@ static ssize_t amdgpu_device_get_pcie_replay_count(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t cnt = amdgpu_asic_get_pcie_replay_count(adev); return snprintf(buf, PAGE_SIZE, "%llu\n", cnt); @@ -157,7 +157,7 @@ static ssize_t amdgpu_device_get_product_name(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_name); } @@ -179,7 +179,7 @@ static ssize_t amdgpu_device_get_product_number(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->product_number); } @@ -201,7 +201,7 @@ static ssize_t amdgpu_device_get_serial_number(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s\n", adev->serial); } @@ -219,7 +219,7 @@ static DEVICE_ATTR(serial_number, S_IRUGO, */ bool amdgpu_device_supports_boco(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (adev->flags & AMD_IS_PX) return true; @@ -236,7 +236,7 @@ bool amdgpu_device_supports_boco(struct drm_device *dev) */ bool amdgpu_device_supports_baco(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_asic_supports_baco(adev); } @@ -3457,7 +3457,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) return -ENODEV; } - adev = dev->dev_private; + adev = drm_to_adev(dev); if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; @@ -3545,7 +3545,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) { struct drm_connector *connector; struct drm_connector_list_iter iter; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_crtc *crtc; int r = 0; @@ -4662,7 +4662,7 @@ static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev) int amdgpu_device_baco_enter(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); if (!amdgpu_device_supports_baco(adev->ddev)) @@ -4676,7 +4676,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev) int amdgpu_device_baco_exit(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); int ret = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index d76172965199..e7ebc7bb70de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -152,7 +152,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_gem_object *obj; struct amdgpu_flip_work *work; @@ -292,7 +292,7 @@ int amdgpu_display_crtc_set_config(struct drm_mode_set *set, pm_runtime_mark_last_busy(dev->dev); - adev = dev->dev_private; + adev = drm_to_adev(dev); /* if we have active crtcs and we don't have a power ref, take the current one */ if (active && !adev->have_disp_power_ref) { @@ -813,7 +813,7 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, int vbl_start, vbl_end, vtotal, ret = 0; bool in_vbl = true; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index b3a62d5ba4e2..9c297300291f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -455,7 +455,7 @@ static struct drm_gem_object * amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf) { struct dma_resv *resv = dma_buf->resv; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_bo *bo; struct amdgpu_bo_param bp; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 92d0368217a2..651b51ab14cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1167,7 +1167,7 @@ retry_init: } else if (ret) goto err_pci; - adev = dev->dev_private; + adev = drm_to_adev(dev); ret = amdgpu_debugfs_init(adev); if (ret) DRM_ERROR("Creating debugfs files failed (%d).\n", ret); @@ -1201,7 +1201,7 @@ static void amdgpu_pci_shutdown(struct pci_dev *pdev) { struct drm_device *dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (amdgpu_ras_intr_triggered()) return; @@ -1234,7 +1234,7 @@ static int amdgpu_pmops_resume(struct device *dev) static int amdgpu_pmops_freeze(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int r; adev->in_hibernate = true; @@ -1270,7 +1270,7 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int ret, i; if (!adev->runpm) { @@ -1321,7 +1321,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct drm_device *drm_dev = pci_get_drvdata(pdev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); int ret; if (!adev->runpm) @@ -1357,7 +1357,7 @@ static int amdgpu_pmops_runtime_resume(struct device *dev) static int amdgpu_pmops_runtime_idle(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); /* we don't want the main rpm_idle to call suspend - we want to autosuspend */ int ret = 1; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c index 61fcf247a638..af4ef84e27a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_encoders.c @@ -35,7 +35,7 @@ void amdgpu_link_encoder_connector(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_connector *connector; struct drm_connector_list_iter iter; struct amdgpu_connector *amdgpu_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 58d4c219178a..cfccd3d33341 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -700,7 +700,7 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int i; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { @@ -749,7 +749,7 @@ static int amdgpu_debugfs_gpu_recover(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int r; r = pm_runtime_get_sync(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7f9e50247413..8371a8724087 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -217,7 +217,7 @@ out_unlock: int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; union drm_amdgpu_gem_create *args = data; @@ -298,7 +298,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct ttm_operation_ctx ctx = { true, false }; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_gem_userptr *args = data; struct drm_gem_object *gobj; struct amdgpu_bo *bo; @@ -587,7 +587,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, struct drm_amdgpu_gem_va *args = data; struct drm_gem_object *gobj; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; struct amdgpu_bo *abo; struct amdgpu_bo_va *bo_va; @@ -711,7 +711,7 @@ error_unref: int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_gem_op *args = data; struct drm_gem_object *gobj; struct amdgpu_vm_bo_base *base; @@ -788,7 +788,7 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_gem_object *gobj; uint32_t handle; u64 flags = AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index bc01a06546aa..ba3027c1d7a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -47,7 +47,7 @@ static ssize_t amdgpu_mem_info_gtt_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", (adev->mman.bdev.man[TTM_PL_TT].size) * PAGE_SIZE); @@ -65,7 +65,7 @@ static ssize_t amdgpu_mem_info_gtt_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_gtt_mgr_usage(&adev->mman.bdev.man[TTM_PL_TT])); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index 70dbe343f51d..411c84194f97 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c @@ -40,7 +40,7 @@ static int amdgpu_i2c_pre_xfer(struct i2c_adapter *i2c_adap) { struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; @@ -82,7 +82,7 @@ static int amdgpu_i2c_pre_xfer(struct i2c_adapter *i2c_adap) static void amdgpu_i2c_post_xfer(struct i2c_adapter *i2c_adap) { struct amdgpu_i2c_chan *i2c = i2c_get_adapdata(i2c_adap); - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t temp; @@ -101,7 +101,7 @@ static void amdgpu_i2c_post_xfer(struct i2c_adapter *i2c_adap) static int amdgpu_i2c_get_clock(void *i2c_priv) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -116,7 +116,7 @@ static int amdgpu_i2c_get_clock(void *i2c_priv) static int amdgpu_i2c_get_data(void *i2c_priv) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -130,7 +130,7 @@ static int amdgpu_i2c_get_data(void *i2c_priv) static void amdgpu_i2c_set_clock(void *i2c_priv, int clock) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; @@ -143,7 +143,7 @@ static void amdgpu_i2c_set_clock(void *i2c_priv, int clock) static void amdgpu_i2c_set_data(void *i2c_priv, int data) { struct amdgpu_i2c_chan *i2c = i2c_priv; - struct amdgpu_device *adev = i2c->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(i2c->dev); struct amdgpu_i2c_bus_rec *rec = &i2c->rec; uint32_t val; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index dcd492170598..2f53fa0ae9a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -445,7 +445,7 @@ static int amdgpu_debugfs_sa_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); seq_printf(m, "--------------------- DELAYED --------------------- \n"); amdgpu_sa_bo_dump_debug_info(&adev->ib_pools[AMDGPU_IB_POOL_DELAYED], diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 0cc4c67f95f7..508cb34a9142 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -151,7 +151,7 @@ void amdgpu_irq_disable_all(struct amdgpu_device *adev) irqreturn_t amdgpu_irq_handler(int irq, void *arg) { struct drm_device *dev = (struct drm_device *) arg; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); irqreturn_t ret; ret = amdgpu_ih_process(adev, &adev->irq.ih); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 7619f1c3084d..c2a697d3f830 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -78,7 +78,7 @@ void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev) */ void amdgpu_driver_unload_kms(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (adev == NULL) return; @@ -479,7 +479,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev, */ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_info *info = data; struct amdgpu_mode_info *minfo = &adev->mode_info; void __user *out = (void __user *)(uintptr_t)info->return_pointer; @@ -992,7 +992,7 @@ void amdgpu_driver_lastclose_kms(struct drm_device *dev) */ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv; int r, pasid; @@ -1077,7 +1077,7 @@ pm_put: void amdgpu_driver_postclose_kms(struct drm_device *dev, struct drm_file *file_priv) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = file_priv->driver_priv; struct amdgpu_bo_list *list; struct amdgpu_bo *pd; @@ -1142,7 +1142,7 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int vpos, hpos, stat; u32 count; @@ -1210,7 +1210,7 @@ int amdgpu_enable_vblank_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe); return amdgpu_irq_get(adev, &adev->crtc_irq, idx); @@ -1227,7 +1227,7 @@ void amdgpu_disable_vblank_kms(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int idx = amdgpu_display_crtc_idx_to_irq_type(adev, pipe); amdgpu_irq_put(adev, &adev->crtc_irq, idx); @@ -1263,7 +1263,7 @@ static int amdgpu_debugfs_firmware_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_amdgpu_info_firmware fw_info; struct drm_amdgpu_query_fw query_fw; struct atom_context *ctx = adev->mode_info.atom_context; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 116a89990f39..c22fb0194df7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -2604,7 +2604,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t fw_ver; int ret; @@ -2631,7 +2631,7 @@ static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); void *cpu_addr; dma_addr_t dma_addr; int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c index 9581283a4c78..0da0a0d98672 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -123,7 +123,7 @@ int amdgpu_sched_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { union drm_amdgpu_sched *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); enum drm_sched_priority priority; int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 97449ab24c20..245d9352ef51 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2134,7 +2134,7 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; - struct amdgpu_device *adev = file_priv->minor->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); if (adev == NULL) return -EINVAL; @@ -2315,7 +2315,7 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *)m->private; unsigned ttm_pl = (uintptr_t)node->info_ent->data; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct ttm_mem_type_manager *man = &adev->mman.bdev.man[ttm_pl]; struct drm_printer p = drm_seq_file_printer(m); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 5f851d17eef4..55fe19a2f332 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c @@ -408,7 +408,7 @@ static ssize_t show_##name(struct device *dev, \ char *buf) \ { \ struct drm_device *ddev = dev_get_drvdata(dev); \ - struct amdgpu_device *adev = ddev->dev_private; \ + struct amdgpu_device *adev = drm_to_adev(ddev); \ \ return snprintf(buf, PAGE_SIZE, "0x%08x\n", adev->field); \ } \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 771c27478bb1..620472a70460 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -3222,7 +3222,7 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev) int amdgpu_vm_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { union drm_amdgpu_vm *args = data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_fpriv *fpriv = filp->driver_priv; long timeout = msecs_to_jiffies(2000); int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index be6a7ec22de4..543f3d28be17 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -47,7 +47,7 @@ static ssize_t amdgpu_mem_info_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.real_vram_size); } @@ -64,7 +64,7 @@ static ssize_t amdgpu_mem_info_vis_vram_total_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.visible_vram_size); } @@ -81,7 +81,7 @@ static ssize_t amdgpu_mem_info_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); @@ -99,7 +99,7 @@ static ssize_t amdgpu_mem_info_vis_vram_used_show(struct device *dev, struct device_attribute *attr, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", amdgpu_vram_mgr_vis_usage(&adev->mman.bdev.man[TTM_PL_VRAM])); @@ -110,7 +110,7 @@ static ssize_t amdgpu_mem_info_vram_vendor(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); switch (adev->gmc.vram_vendor) { case SAMSUNG: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index 08ed4dddfaf1..bda3f709a8e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -215,7 +215,7 @@ static ssize_t amdgpu_xgmi_show_device_id(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%llu\n", adev->gmc.xgmi.node_id); @@ -227,7 +227,7 @@ static ssize_t amdgpu_xgmi_show_error(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t ficaa_pie_ctl_in, ficaa_pie_status_in; uint64_t fica_out; unsigned int error_count = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c index 213e62a28ba0..159a2a4385a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_crtc.c @@ -41,7 +41,7 @@ void amdgpu_atombios_crtc_overscan_setup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); SET_CRTC_OVERSCAN_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_OverScan); @@ -84,7 +84,7 @@ void amdgpu_atombios_crtc_overscan_setup(struct drm_crtc *crtc, void amdgpu_atombios_crtc_scaler_setup(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); ENABLE_SCALER_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, EnableScaler); @@ -114,7 +114,7 @@ void amdgpu_atombios_crtc_lock(struct drm_crtc *crtc, int lock) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, UpdateCRTC_DoubleBufferRegisters); ENABLE_CRTC_PS_ALLOCATION args; @@ -131,7 +131,7 @@ void amdgpu_atombios_crtc_enable(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, EnableCRTC); ENABLE_CRTC_PS_ALLOCATION args; @@ -147,7 +147,7 @@ void amdgpu_atombios_crtc_blank(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, BlankCRTC); BLANK_CRTC_PS_ALLOCATION args; @@ -163,7 +163,7 @@ void amdgpu_atombios_crtc_powergate(struct drm_crtc *crtc, int state) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int index = GetIndexIntoMasterTable(COMMAND, EnableDispPowerGating); ENABLE_DISP_POWER_GATING_PS_ALLOCATION args; @@ -192,7 +192,7 @@ void amdgpu_atombios_crtc_set_dtd_timing(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); SET_CRTC_USING_DTD_TIMING_PARAMETERS args; int index = GetIndexIntoMasterTable(COMMAND, SetCRTC_UsingDTDTiming); u16 misc = 0; @@ -307,7 +307,7 @@ static u32 amdgpu_atombios_crtc_adjust_pll(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_encoder *encoder = amdgpu_crtc->encoder; struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -588,7 +588,7 @@ void amdgpu_atombios_crtc_program_pll(struct drm_crtc *crtc, struct amdgpu_atom_ss *ss) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u8 frev, crev; int index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); union set_pixel_clock args; @@ -749,7 +749,7 @@ int amdgpu_atombios_crtc_prepare_pll(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); int encoder_mode = amdgpu_atombios_encoder_get_encoder_mode(amdgpu_crtc->encoder); @@ -818,7 +818,7 @@ void amdgpu_atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(amdgpu_crtc->encoder); u32 pll_clock = mode->clock; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 9b74cfdba7b8..cc2494671f9d 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -60,7 +60,7 @@ static int amdgpu_atombios_dp_process_aux_ch(struct amdgpu_i2c_chan *chan, u8 delay, u8 *ack) { struct drm_device *dev = chan->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union aux_channel_transaction args; int index = GetIndexIntoMasterTable(COMMAND, ProcessAuxChannelTransaction); unsigned char *base; @@ -305,7 +305,7 @@ static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev, u8 amdgpu_atombios_dp_get_sinktype(struct amdgpu_connector *amdgpu_connector) { struct drm_device *dev = amdgpu_connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_atombios_dp_encoder_service(adev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, amdgpu_connector->ddc_bus->rec.i2c_id, 0); @@ -702,7 +702,7 @@ void amdgpu_atombios_dp_link_train(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector; struct amdgpu_connector_atom_dig *dig_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index 1e94a9b652f7..a7466f3562bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -70,7 +70,7 @@ u8 amdgpu_atombios_encoder_get_backlight_level(struct amdgpu_encoder *amdgpu_encoder) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) return 0; @@ -84,7 +84,7 @@ amdgpu_atombios_encoder_set_backlight_level(struct amdgpu_encoder *amdgpu_encode { struct drm_encoder *encoder = &amdgpu_encoder->base; struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder_atom_dig *dig; if (!(adev->mode_info.firmware_flags & ATOM_BIOS_INFO_BL_CONTROLLED_BY_GPU)) @@ -152,7 +152,7 @@ amdgpu_atombios_encoder_get_backlight_brightness(struct backlight_device *bd) struct amdgpu_backlight_privdata *pdata = bl_get_data(bd); struct amdgpu_encoder *amdgpu_encoder = pdata->encoder; struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); return amdgpu_atombios_encoder_get_backlight_level_from_reg(adev); } @@ -166,7 +166,7 @@ void amdgpu_atombios_encoder_init_backlight(struct amdgpu_encoder *amdgpu_encode struct drm_connector *drm_connector) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct backlight_device *bd; struct backlight_properties props; struct amdgpu_backlight_privdata *pdata; @@ -229,7 +229,7 @@ void amdgpu_atombios_encoder_fini_backlight(struct amdgpu_encoder *amdgpu_encoder) { struct drm_device *dev = amdgpu_encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct backlight_device *bd = NULL; struct amdgpu_encoder_atom_dig *dig; @@ -319,7 +319,7 @@ static void amdgpu_atombios_encoder_setup_dac(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); DAC_ENCODER_CONTROL_PS_ALLOCATION args; int index = 0; @@ -382,7 +382,7 @@ static void amdgpu_atombios_encoder_setup_dvo(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); union dvo_encoder_control args; int index = GetIndexIntoMasterTable(COMMAND, DVOEncoderControl); @@ -573,7 +573,7 @@ amdgpu_atombios_encoder_setup_dig_encoder(struct drm_encoder *encoder, int action, int panel_mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -762,7 +762,7 @@ amdgpu_atombios_encoder_setup_dig_transmitter(struct drm_encoder *encoder, int a uint8_t lane_num, uint8_t lane_set) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1178,7 +1178,7 @@ amdgpu_atombios_encoder_set_edp_panel_power(struct drm_connector *connector, { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_device *dev = amdgpu_connector->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); union dig_transmitter_control args; int index = GetIndexIntoMasterTable(COMMAND, UNIPHYTransmitterControl); uint8_t frev, crev; @@ -1225,7 +1225,7 @@ amdgpu_atombios_encoder_setup_external_encoder(struct drm_encoder *encoder, int action) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder *ext_amdgpu_encoder = to_amdgpu_encoder(ext_encoder); union external_encoder_control args; @@ -1466,7 +1466,7 @@ void amdgpu_atombios_encoder_set_crtc_source(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); union crtc_source_param args; @@ -1701,7 +1701,7 @@ amdgpu_atombios_encoder_dac_load_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); @@ -1751,7 +1751,7 @@ amdgpu_atombios_encoder_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); uint32_t bios_0_scratch; @@ -1790,7 +1790,7 @@ amdgpu_atombios_encoder_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct drm_encoder *ext_encoder = amdgpu_get_external_encoder(encoder); @@ -1848,7 +1848,7 @@ amdgpu_atombios_encoder_set_bios_scratch_regs(struct drm_connector *connector, bool connected) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); @@ -1999,7 +1999,7 @@ struct amdgpu_encoder_atom_dig * amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder) { struct drm_device *dev = encoder->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_mode_info *mode_info = &adev->mode_info; int index = GetIndexIntoMasterTable(DATA, LVDS_Info); uint16_t data_offset, misc; diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c index b4cc7c55fa16..09a538465ffd 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_i2c.c @@ -40,7 +40,7 @@ static int amdgpu_atombios_i2c_process_i2c_ch(struct amdgpu_i2c_chan *chan, u8 *buf, u8 num) { struct drm_device *dev = chan->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); PROCESS_I2C_CHANNEL_TRANSACTION_PS_ALLOCATION args; int index = GetIndexIntoMasterTable(COMMAND, ProcessI2cChannelTransaction); unsigned char *base; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 84b45a019a36..65301a56344b 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -504,7 +504,7 @@ void dce_v10_0_disable_dce(struct amdgpu_device *adev) static void dce_v10_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1209,7 +1209,7 @@ static struct amdgpu_audio_pin *dce_v10_0_audio_get_pin(struct amdgpu_device *ad static void dce_v10_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1226,7 +1226,7 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1272,7 +1272,7 @@ static void dce_v10_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1328,7 +1328,7 @@ static void dce_v10_0_audio_write_speaker_allocation(struct drm_encoder *encoder static void dce_v10_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1483,7 +1483,7 @@ static void dce_v10_0_audio_fini(struct amdgpu_device *adev) static void dce_v10_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1519,7 +1519,7 @@ static void dce_v10_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint8_t *frame = buffer + 3; @@ -1538,7 +1538,7 @@ static void dce_v10_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v10_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1569,7 +1569,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1749,7 +1749,7 @@ static void dce_v10_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v10_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1822,7 +1822,7 @@ static void dce_v10_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1836,7 +1836,7 @@ static void dce_v10_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1850,7 +1850,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2095,7 +2095,7 @@ static void dce_v10_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); u32 tmp; @@ -2111,7 +2111,7 @@ static void dce_v10_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; u32 tmp; @@ -2250,7 +2250,7 @@ static u32 dce_v10_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2285,7 +2285,7 @@ static u32 dce_v10_0_pick_pll(struct drm_crtc *crtc) static void dce_v10_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2300,7 +2300,7 @@ static void dce_v10_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v10_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; tmp = RREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset); @@ -2311,7 +2311,7 @@ static void dce_v10_0_hide_cursor(struct drm_crtc *crtc) static void dce_v10_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, @@ -2329,7 +2329,7 @@ static int dce_v10_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2503,7 +2503,7 @@ static const struct drm_crtc_funcs dce_v10_0_crtc_funcs = { static void dce_v10_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2557,7 +2557,7 @@ static void dce_v10_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3345,7 +3345,7 @@ dce_v10_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v10_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3385,7 +3385,7 @@ static void dce_v10_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v10_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 01ce52266966..0847fb6485de 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -530,7 +530,7 @@ void dce_v11_0_disable_dce(struct amdgpu_device *adev) static void dce_v11_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1235,7 +1235,7 @@ static struct amdgpu_audio_pin *dce_v11_0_audio_get_pin(struct amdgpu_device *ad static void dce_v11_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1252,7 +1252,7 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1298,7 +1298,7 @@ static void dce_v11_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1354,7 +1354,7 @@ static void dce_v11_0_audio_write_speaker_allocation(struct drm_encoder *encoder static void dce_v11_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1525,7 +1525,7 @@ static void dce_v11_0_audio_fini(struct amdgpu_device *adev) static void dce_v11_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1561,7 +1561,7 @@ static void dce_v11_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint8_t *frame = buffer + 3; @@ -1580,7 +1580,7 @@ static void dce_v11_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v11_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1611,7 +1611,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1791,7 +1791,7 @@ static void dce_v11_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v11_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1864,7 +1864,7 @@ static void dce_v11_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1878,7 +1878,7 @@ static void dce_v11_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1892,7 +1892,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2137,7 +2137,7 @@ static void dce_v11_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); u32 tmp; @@ -2153,7 +2153,7 @@ static void dce_v11_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; u32 tmp; @@ -2283,7 +2283,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2364,7 +2364,7 @@ static u32 dce_v11_0_pick_pll(struct drm_crtc *crtc) static void dce_v11_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2379,7 +2379,7 @@ static void dce_v11_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v11_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; tmp = RREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset); @@ -2390,7 +2390,7 @@ static void dce_v11_0_hide_cursor(struct drm_crtc *crtc) static void dce_v11_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); u32 tmp; WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, @@ -2408,7 +2408,7 @@ static int dce_v11_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2582,7 +2582,7 @@ static const struct drm_crtc_funcs dce_v11_0_crtc_funcs = { static void dce_v11_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2636,7 +2636,7 @@ static void dce_v11_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -2706,7 +2706,7 @@ static int dce_v11_0_crtc_mode_set(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (!amdgpu_crtc->adjusted_clock) return -EINVAL; @@ -3471,7 +3471,7 @@ dce_v11_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v11_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3511,7 +3511,7 @@ static void dce_v11_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v11_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index cbddead3dafb..e234d6fb49ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -401,7 +401,7 @@ static void dce_v6_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1114,7 +1114,7 @@ static struct amdgpu_audio_pin *dce_v6_0_audio_get_pin(struct amdgpu_device *ade static void dce_v6_0_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1130,7 +1130,7 @@ static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1174,7 +1174,7 @@ static void dce_v6_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1235,7 +1235,7 @@ static void dce_v6_0_audio_write_speaker_allocation(struct drm_encoder *encoder) static void dce_v6_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1392,7 +1392,7 @@ static void dce_v6_0_audio_fini(struct amdgpu_device *adev) static void dce_v6_0_audio_set_vbi_packet(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1408,7 +1408,7 @@ static void dce_v6_0_audio_set_acr(struct drm_encoder *encoder, uint32_t clock, int bpc) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1446,7 +1446,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1488,7 +1488,7 @@ static void dce_v6_0_audio_set_avi_infoframe(struct drm_encoder *encoder, static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); int em = amdgpu_atombios_encoder_get_encoder_mode(encoder); u32 tmp; @@ -1522,7 +1522,7 @@ static void dce_v6_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1566,7 +1566,7 @@ static void dce_v6_0_audio_set_packet(struct drm_encoder *encoder) static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool mute) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1579,7 +1579,7 @@ static void dce_v6_0_audio_set_mute(struct drm_encoder *encoder, bool mute) static void dce_v6_0_audio_hdmi_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1616,7 +1616,7 @@ static void dce_v6_0_audio_hdmi_enable(struct drm_encoder *encoder, bool enable) static void dce_v6_0_audio_dp_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 tmp; @@ -1645,7 +1645,7 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1714,7 +1714,7 @@ static void dce_v6_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v6_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1788,7 +1788,7 @@ static void dce_v6_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1799,7 +1799,7 @@ static void dce_v6_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, enable ? 1 : 0); } @@ -1810,7 +1810,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2033,7 +2033,7 @@ static void dce_v6_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2048,7 +2048,7 @@ static void dce_v6_0_crtc_load_lut(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; @@ -2148,7 +2148,7 @@ static u32 dce_v6_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2177,7 +2177,7 @@ static u32 dce_v6_0_pick_pll(struct drm_crtc *crtc) static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2192,7 +2192,7 @@ static void dce_v6_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v6_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) | @@ -2204,7 +2204,7 @@ static void dce_v6_0_hide_cursor(struct drm_crtc *crtc) static void dce_v6_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, upper_32_bits(amdgpu_crtc->cursor_addr)); @@ -2222,7 +2222,7 @@ static int dce_v6_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; int w = amdgpu_crtc->cursor_width; @@ -2397,7 +2397,7 @@ static const struct drm_crtc_funcs dce_v6_0_crtc_funcs = { static void dce_v6_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2447,7 +2447,7 @@ static void dce_v6_0_crtc_disable(struct drm_crtc *crtc) struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3146,7 +3146,7 @@ dce_v6_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v6_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3187,7 +3187,7 @@ static void dce_v6_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index fa0ad50b628c..7cc8f7c4bc1f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -444,7 +444,7 @@ void dce_v8_0_disable_dce(struct amdgpu_device *adev) static void dce_v8_0_program_fmt(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1146,7 +1146,7 @@ static struct amdgpu_audio_pin *dce_v8_0_audio_get_pin(struct amdgpu_device *ade static void dce_v8_0_afmt_audio_select_pin(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 offset; @@ -1164,7 +1164,7 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1225,7 +1225,7 @@ static void dce_v8_0_audio_write_latency_fields(struct drm_encoder *encoder, static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector; @@ -1278,7 +1278,7 @@ static void dce_v8_0_audio_write_speaker_allocation(struct drm_encoder *encoder) static void dce_v8_0_audio_write_sad_regs(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; u32 offset; @@ -1446,7 +1446,7 @@ static void dce_v8_0_audio_fini(struct amdgpu_device *adev) static void dce_v8_0_afmt_update_ACR(struct drm_encoder *encoder, uint32_t clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_afmt_acr acr = amdgpu_afmt_acr(clock); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1469,7 +1469,7 @@ static void dce_v8_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, void *buffer, size_t size) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; uint32_t offset = dig->afmt->offset; @@ -1489,7 +1489,7 @@ static void dce_v8_0_afmt_update_avi_infoframe(struct drm_encoder *encoder, static void dce_v8_0_audio_set_dto(struct drm_encoder *encoder, u32 clock) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(encoder->crtc); @@ -1516,7 +1516,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -1678,7 +1678,7 @@ static void dce_v8_0_afmt_setmode(struct drm_encoder *encoder, static void dce_v8_0_afmt_enable(struct drm_encoder *encoder, bool enable) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct amdgpu_encoder_atom_dig *dig = amdgpu_encoder->enc_priv; @@ -1751,7 +1751,7 @@ static void dce_v8_0_vga_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 vga_control; vga_control = RREG32(vga_control_regs[amdgpu_crtc->crtc_id]) & ~1; @@ -1765,7 +1765,7 @@ static void dce_v8_0_grph_enable(struct drm_crtc *crtc, bool enable) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); if (enable) WREG32(mmGRPH_ENABLE + amdgpu_crtc->crtc_offset, 1); @@ -1779,7 +1779,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_framebuffer *target_fb; struct drm_gem_object *obj; struct amdgpu_bo *abo; @@ -2004,7 +2004,7 @@ static void dce_v8_0_set_interleave(struct drm_crtc *crtc, struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); if (mode->flags & DRM_MODE_FLAG_INTERLACE) @@ -2018,7 +2018,7 @@ static void dce_v8_0_crtc_load_lut(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u16 *r, *g, *b; int i; @@ -2140,7 +2140,7 @@ static u32 dce_v8_0_pick_pll(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 pll_in_use; int pll; @@ -2188,7 +2188,7 @@ static u32 dce_v8_0_pick_pll(struct drm_crtc *crtc) static void dce_v8_0_lock_cursor(struct drm_crtc *crtc, bool lock) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); uint32_t cur_lock; @@ -2203,7 +2203,7 @@ static void dce_v8_0_lock_cursor(struct drm_crtc *crtc, bool lock) static void dce_v8_0_hide_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_CONTROL + amdgpu_crtc->crtc_offset, (CURSOR_24_8_PRE_MULT << CUR_CONTROL__CURSOR_MODE__SHIFT) | @@ -2213,7 +2213,7 @@ static void dce_v8_0_hide_cursor(struct drm_crtc *crtc) static void dce_v8_0_show_cursor(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); WREG32(mmCUR_SURFACE_ADDRESS_HIGH + amdgpu_crtc->crtc_offset, upper_32_bits(amdgpu_crtc->cursor_addr)); @@ -2230,7 +2230,7 @@ static int dce_v8_0_cursor_move_locked(struct drm_crtc *crtc, int x, int y) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int xorigin = 0, yorigin = 0; amdgpu_crtc->cursor_x = x; @@ -2404,7 +2404,7 @@ static const struct drm_crtc_funcs dce_v8_0_crtc_funcs = { static void dce_v8_0_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -2458,7 +2458,7 @@ static void dce_v8_0_crtc_disable(struct drm_crtc *crtc) { struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_atom_ss ss; int i; @@ -3233,7 +3233,7 @@ dce_v8_0_encoder_mode_set(struct drm_encoder *encoder, static void dce_v8_0_encoder_prepare(struct drm_encoder *encoder) { - struct amdgpu_device *adev = encoder->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(encoder->dev); struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); struct drm_connector *connector = amdgpu_get_connector_for_encoder(encoder); @@ -3273,7 +3273,7 @@ static void dce_v8_0_encoder_prepare(struct drm_encoder *encoder) static void dce_v8_0_encoder_commit(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); /* need to call this here as we need the crtc set up */ amdgpu_atombios_encoder_dpms(encoder, DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index d5ff7b6331ff..5bc784531e65 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -132,7 +132,7 @@ static const struct drm_crtc_funcs dce_virtual_crtc_funcs = { static void dce_virtual_crtc_dpms(struct drm_crtc *crtc, int mode) { struct drm_device *dev = crtc->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc); unsigned type; @@ -697,7 +697,7 @@ static enum hrtimer_restart dce_virtual_vblank_timer_handle(struct hrtimer *vbla struct amdgpu_crtc *amdgpu_crtc = container_of(vblank_timer, struct amdgpu_crtc, vblank_timer); struct drm_device *ddev = amdgpu_crtc->base.dev; - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); drm_handle_vblank(ddev, amdgpu_crtc->crtc_id); dce_virtual_pageflip(adev, amdgpu_crtc->crtc_id); diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c index 0aa1ac1accd6..2eab808fffeb 100644 --- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c +++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c @@ -251,7 +251,7 @@ static ssize_t df_v3_6_get_df_cntr_avail(struct device *dev, int i, count; ddev = dev_get_drvdata(dev); - adev = ddev->dev_private; + adev = drm_to_adev(ddev); count = 0; for (i = 0; i < DF_V3_6_MAX_COUNTERS; i++) { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 075960864e12..a81c74f32209 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -544,7 +544,7 @@ static int dm_early_init(void* handle); static void amdgpu_dm_fbc_init(struct drm_connector *connector) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_comressor_info *compressor = &adev->dm.compressor; struct amdgpu_dm_connector *aconn = to_amdgpu_dm_connector(connector); struct drm_display_mode *mode; @@ -586,7 +586,7 @@ static int amdgpu_dm_audio_component_get_eld(struct device *kdev, int port, unsigned char *buf, int max_bytes) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_connector *connector; struct drm_connector_list_iter conn_iter; struct amdgpu_dm_connector *aconnector; @@ -625,7 +625,7 @@ static int amdgpu_dm_audio_component_bind(struct device *kdev, struct device *hda_kdev, void *data) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_audio_component *acomp = data; acomp->ops = &amdgpu_dm_audio_component_ops; @@ -639,7 +639,7 @@ static void amdgpu_dm_audio_component_unbind(struct device *kdev, struct device *hda_kdev, void *data) { struct drm_device *dev = dev_get_drvdata(kdev); - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct drm_audio_component *acomp = data; acomp->ops = NULL; @@ -2050,7 +2050,7 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector) return; conn_base = &aconnector->base; - adev = conn_base->dev->dev_private; + adev = drm_to_adev(conn_base->dev); dm = &adev->dm; caps = &dm->backlight_caps; caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps; @@ -2239,7 +2239,7 @@ static void handle_hpd_irq(void *param) struct drm_device *dev = connector->dev; enum dc_connection_type new_connection_type = dc_connection_none; #ifdef CONFIG_DRM_AMD_DC_HDCP - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); #endif /* @@ -2372,7 +2372,7 @@ static void handle_hpd_rx_irq(void *param) enum dc_connection_type new_connection_type = dc_connection_none; #ifdef CONFIG_DRM_AMD_DC_HDCP union hpd_irq_data hpd_irq_data; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); memset(&hpd_irq_data, 0, sizeof(hpd_irq_data)); #endif @@ -2793,7 +2793,7 @@ static int dm_atomic_get_state(struct drm_atomic_state *state, struct dm_atomic_state **dm_state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct drm_private_state *priv_state; @@ -2813,7 +2813,7 @@ static struct dm_atomic_state * dm_atomic_get_new_state(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct drm_private_obj *obj; struct drm_private_state *new_obj_state; @@ -3388,7 +3388,7 @@ static ssize_t s3_debug_store(struct device *device, int ret; int s3_state; struct drm_device *drm_dev = dev_get_drvdata(device); - struct amdgpu_device *adev = drm_dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(drm_dev); ret = kstrtoint(buf, 0, &s3_state); @@ -4785,7 +4785,7 @@ static inline int dm_set_vupdate_irq(struct drm_crtc *crtc, bool enable) { enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); int rc; irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst; @@ -4801,7 +4801,7 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) { enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); int rc = 0; @@ -4878,7 +4878,7 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector, uint64_t val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_connector_state *dm_old_state = to_dm_connector_state(connector->state); struct dm_connector_state *dm_new_state = @@ -4933,7 +4933,7 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector, uint64_t *val) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_connector_state *dm_state = to_dm_connector_state(state); int ret = -EINVAL; @@ -4983,7 +4983,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); const struct dc_link *link = aconnector->dc_link; - struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ @@ -5168,7 +5168,7 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector, const struct dc_stream_state *old_stream) { struct drm_connector *connector = &aconnector->base; - struct amdgpu_device *adev = connector->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(connector->dev); struct dc_stream_state *stream; const struct drm_connector_state *drm_state = dm_state ? &dm_state->base : NULL; int requested_bpc = drm_state ? drm_state->max_requested_bpc : 8; @@ -5445,7 +5445,7 @@ static void dm_update_crtc_active_planes(struct drm_crtc *crtc, static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dc *dc = adev->dm.dc; struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(state); int ret = -EINVAL; @@ -5817,7 +5817,7 @@ static int dm_plane_helper_check_state(struct drm_plane_state *state, static int dm_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { - struct amdgpu_device *adev = plane->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(plane->dev); struct dc *dc = adev->dm.dc; struct dm_plane_state *dm_plane_state; struct dc_scaling_info scaling_info; @@ -6292,7 +6292,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm, struct dc_link *link, int link_index) { - struct amdgpu_device *adev = dm->ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dm->ddev); /* * Some of the properties below require access to state, like bpc. @@ -6543,7 +6543,7 @@ static int amdgpu_dm_encoder_init(struct drm_device *dev, struct amdgpu_encoder *aencoder, uint32_t link_index) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int res = drm_encoder_init(dev, &aencoder->base, @@ -6728,7 +6728,7 @@ static int get_cursor_position(struct drm_plane *plane, struct drm_crtc *crtc, static void handle_cursor_update(struct drm_plane *plane, struct drm_plane_state *old_plane_state) { - struct amdgpu_device *adev = plane->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(plane->dev); struct amdgpu_framebuffer *afb = to_amdgpu_framebuffer(plane->state->fb); struct drm_crtc *crtc = afb ? plane->state->crtc : old_plane_state->crtc; struct dm_crtc_state *crtc_state = crtc ? to_dm_crtc_state(crtc->state) : NULL; @@ -7265,9 +7265,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * on some ASICs). */ if (dm_old_crtc_state->active_planes != acrtc_state->active_planes) - dm_update_pflip_irq_state( - (struct amdgpu_device *)dev->dev_private, - acrtc_attach); + dm_update_pflip_irq_state(drm_to_adev(dev), + acrtc_attach); if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && @@ -7297,7 +7296,7 @@ cleanup: static void amdgpu_dm_commit_audio(struct drm_device *dev, struct drm_atomic_state *state) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; struct drm_connector_state *old_con_state, *new_con_state; @@ -7389,7 +7388,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, { struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); int i; /* @@ -7436,7 +7435,7 @@ static int amdgpu_dm_atomic_commit(struct drm_device *dev, static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) { struct drm_device *dev = state->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; struct dm_atomic_state *dm_state; struct dc_state *dc_state = NULL, *dc_state_temp = NULL; @@ -8410,7 +8409,7 @@ static int dm_update_plane_state(struct dc *dc, plane->base.id, new_plane_crtc->base.id); ret = fill_dc_plane_attributes( - new_plane_crtc->dev->dev_private, + drm_to_adev(new_plane_crtc->dev), dc_new_plane_state, new_plane_state, new_crtc_state); @@ -8508,7 +8507,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm static int amdgpu_dm_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dm_atomic_state *dm_state = NULL; struct dc *dc = adev->dm.dc; struct drm_connector *connector; @@ -8861,7 +8860,7 @@ void amdgpu_dm_update_freesync_caps(struct drm_connector *connector, struct dm_connector_state *dm_con_state = NULL; struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); bool freesync_capable = false; if (!connector->state) { @@ -9075,7 +9074,7 @@ static bool amdgpu_dm_psr_disable_all(struct amdgpu_display_manager *dm) void amdgpu_dm_trigger_timing_sync(struct drm_device *dev) { - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct dc *dc = adev->dm.dc; int i; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index b321ff654df4..5df05f0d18bc 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -308,8 +308,7 @@ static int __set_input_tf(struct dc_transfer_func *func, int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) { struct dc_stream_state *stream = crtc->stream; - struct amdgpu_device *adev = - (struct amdgpu_device *)crtc->base.state->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->base.state->dev); bool has_rom = adev->asic_type <= CHIP_RAVEN; struct drm_color_ctm *ctm = NULL; const struct drm_color_lut *degamma_lut, *regamma_lut; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c index eaad9099bc0b..d0699e98db92 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c @@ -101,7 +101,7 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc, struct dm_crtc_state *dm_crtc_state, enum amdgpu_dm_pipe_crc_source source) { - struct amdgpu_device *adev = crtc->dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dc_stream_state *stream_state = dm_crtc_state->stream; bool enable = amdgpu_dm_is_valid_crc_source(source); int ret = 0; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index ae6b1313403e..5703a68d8302 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2127,7 +2127,7 @@ static int current_backlight_read(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; unsigned int backlight = dc_link_get_backlight_level(dm->backlight_link); @@ -2145,7 +2145,7 @@ static int target_backlight_read(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_display_manager *dm = &adev->dm; unsigned int backlight = dc_link_get_target_backlight_pwm(dm->backlight_link); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index a222335133e0..8aba40345b54 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -241,7 +241,7 @@ dm_mst_atomic_best_encoder(struct drm_connector *connector, struct drm_connector_state *connector_state) { struct drm_device *dev = connector->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_crtc *acrtc = to_amdgpu_crtc(connector_state->crtc); return &adev->dm.mst_encoders[acrtc->crtc_id].base; @@ -337,7 +337,7 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, { struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); struct drm_device *dev = master->base.dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; int i; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index e469de005451..ea00c4b0e74b 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -117,7 +117,7 @@ static ssize_t amdgpu_get_power_dpm_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type pm; int ret; @@ -155,7 +155,7 @@ static ssize_t amdgpu_set_power_dpm_state(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state; int ret; @@ -261,7 +261,7 @@ static ssize_t amdgpu_get_power_dpm_force_performance_level(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level = 0xff; int ret; @@ -302,7 +302,7 @@ static ssize_t amdgpu_set_power_dpm_force_performance_level(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_dpm_forced_level level; enum amd_dpm_forced_level current_level = 0xff; int ret = 0; @@ -407,7 +407,7 @@ static ssize_t amdgpu_get_pp_num_states(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct pp_states_info data; int i, buf_len, ret; @@ -449,7 +449,7 @@ static ssize_t amdgpu_get_pp_cur_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); struct pp_states_info data; struct smu_context *smu = &adev->smu; enum amd_pm_state_type pm = 0; @@ -494,7 +494,7 @@ static ssize_t amdgpu_get_pp_force_state(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); if (amdgpu_in_reset(adev)) return -EPERM; @@ -511,7 +511,7 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); enum amd_pm_state_type state = 0; unsigned long idx; int ret; @@ -572,7 +572,7 @@ static ssize_t amdgpu_get_pp_table(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); char *table = NULL; int size, ret; @@ -617,7 +617,7 @@ static ssize_t amdgpu_set_pp_table(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret = 0; if (amdgpu_in_reset(adev)) @@ -763,7 +763,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t parameter_size = 0; long parameter[64]; @@ -863,7 +863,7 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -917,7 +917,7 @@ static ssize_t amdgpu_set_pp_features(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t featuremask; int ret; @@ -962,7 +962,7 @@ static ssize_t amdgpu_get_pp_features(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1023,7 +1023,7 @@ static ssize_t amdgpu_get_pp_dpm_sclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1091,7 +1091,7 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1127,7 +1127,7 @@ static ssize_t amdgpu_get_pp_dpm_mclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1159,7 +1159,7 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t mask = 0; int ret; @@ -1195,7 +1195,7 @@ static ssize_t amdgpu_get_pp_dpm_socclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1227,7 +1227,7 @@ static ssize_t amdgpu_set_pp_dpm_socclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1265,7 +1265,7 @@ static ssize_t amdgpu_get_pp_dpm_fclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1297,7 +1297,7 @@ static ssize_t amdgpu_set_pp_dpm_fclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1335,7 +1335,7 @@ static ssize_t amdgpu_get_pp_dpm_dcefclk(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1367,7 +1367,7 @@ static ssize_t amdgpu_set_pp_dpm_dcefclk(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1405,7 +1405,7 @@ static ssize_t amdgpu_get_pp_dpm_pcie(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1437,7 +1437,7 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; uint32_t mask = 0; @@ -1475,7 +1475,7 @@ static ssize_t amdgpu_get_pp_sclk_od(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t value = 0; int ret; @@ -1505,7 +1505,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; long int value; @@ -1548,7 +1548,7 @@ static ssize_t amdgpu_get_pp_mclk_od(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t value = 0; int ret; @@ -1578,7 +1578,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int ret; long int value; @@ -1641,7 +1641,7 @@ static ssize_t amdgpu_get_pp_power_profile_mode(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); ssize_t size; int ret; @@ -1675,7 +1675,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, { int ret; struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint32_t parameter_size = 0; long parameter[64]; char *sub_str, buf_cpy[128]; @@ -1746,7 +1746,7 @@ static ssize_t amdgpu_get_gpu_busy_percent(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int r, value, size = sizeof(value); if (amdgpu_in_reset(adev)) @@ -1784,7 +1784,7 @@ static ssize_t amdgpu_get_mem_busy_percent(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); int r, value, size = sizeof(value); if (amdgpu_in_reset(adev)) @@ -1826,7 +1826,7 @@ static ssize_t amdgpu_get_pcie_bw(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); uint64_t count0 = 0, count1 = 0; int ret; @@ -1869,7 +1869,7 @@ static ssize_t amdgpu_get_unique_id(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); if (amdgpu_in_reset(adev)) return -EPERM; @@ -1900,7 +1900,7 @@ static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", adev->ddev->unique, @@ -1914,7 +1914,7 @@ static ssize_t amdgpu_set_thermal_throttling_logging(struct device *dev, size_t count) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); long throttling_logging_interval; unsigned long flags; int ret = 0; @@ -1964,7 +1964,7 @@ static ssize_t amdgpu_get_gpu_metrics(struct device *dev, char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); - struct amdgpu_device *adev = ddev->dev_private; + struct amdgpu_device *adev = drm_to_adev(ddev); void *gpu_metrics; ssize_t size = 0; int ret; @@ -3554,7 +3554,7 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; struct drm_device *dev = node->minor->dev; - struct amdgpu_device *adev = dev->dev_private; + struct amdgpu_device *adev = drm_to_adev(dev); u32 flags = 0; int r; -- cgit v1.2.3 From 4a580877bdcb837e7a3754ae20798dcfccb44e80 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Mon, 24 Aug 2020 12:29:45 -0400 Subject: drm/amdgpu: Get DRM dev from adev by inline-f Add a static inline adev_to_drm() to obtain the DRM device pointer from an amdgpu_device pointer. Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 5 + drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 178 +++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 30 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c | 20 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c | 18 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c | 2 +- drivers/gpu/drm/amd/amdgpu/atombios_encoders.c | 2 +- drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v6_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_v8_0.c | 46 ++--- drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 36 ++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 84 ++++----- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 4 +- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 4 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 6 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 194 ++++++++++----------- 33 files changed, 428 insertions(+), 423 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index f33a1f372681..9d93b3170cd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -991,6 +991,11 @@ static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) return ddev->dev_private; } +static inline struct drm_device *adev_to_drm(struct amdgpu_device *adev) +{ + return adev->ddev; +} + static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) { return container_of(bdev, struct amdgpu_device, mman.bdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index 913c8f0513bd..4a93b880c6bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -463,11 +463,11 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev, if (req.pending & ATIF_DGPU_DISPLAY_EVENT) { if (adev->flags & AMD_IS_PX) { - pm_runtime_get_sync(adev->ddev->dev); + pm_runtime_get_sync(adev_to_drm(adev)->dev); /* Just fire off a uevent and let userspace tell us what to do */ - drm_helper_hpd_irq_event(adev->ddev); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + drm_helper_hpd_irq_event(adev_to_drm(adev)); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); } } /* TODO: check other events */ @@ -817,7 +817,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev) struct drm_encoder *tmp; /* Find the encoder controlling the brightness */ - list_for_each_entry(tmp, &adev->ddev->mode_config.encoder_list, + list_for_each_entry(tmp, &adev_to_drm(adev)->mode_config.encoder_list, head) { struct amdgpu_encoder *enc = to_amdgpu_encoder(tmp); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index b74846fc3933..d58148f455dd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -119,7 +119,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) .gpuvm_size = min(adev->vm_manager.max_pfn << AMDGPU_GPU_PAGE_SHIFT, AMDGPU_GMC_HOLE_START), - .drm_render_minor = adev->ddev->render->index, + .drm_render_minor = adev_to_drm(adev)->render->index, .sdma_doorbell_idx = adev->doorbell_index.sdma_engine, }; @@ -160,7 +160,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev) adev->doorbell_index.last_non_cp; } - kgd2kfd_device_init(adev->kfd.dev, adev->ddev, &gpu_resources); + kgd2kfd_device_init(adev->kfd.dev, adev_to_drm(adev), &gpu_resources); } } @@ -479,7 +479,7 @@ int amdgpu_amdkfd_get_dmabuf_info(struct kgd_dev *kgd, int dma_buf_fd, goto out_put; obj = dma_buf->priv; - if (obj->dev->driver != adev->ddev->driver) + if (obj->dev->driver != adev_to_drm(adev)->driver) /* Can't handle buffers from different drivers */ goto out_put; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index 662cc414ceec..469352e2d6ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -148,7 +148,7 @@ void amdgpu_atombios_i2c_init(struct amdgpu_device *adev) if (i2c.valid) { sprintf(stmp, "0x%x", i2c.i2c_id); - adev->i2c_bus[i] = amdgpu_i2c_create(adev->ddev, &i2c, stmp); + adev->i2c_bus[i] = amdgpu_i2c_create(adev_to_drm(adev), &i2c, stmp); } gpio = (ATOM_GPIO_I2C_ASSIGMENT *) ((u8 *)gpio + sizeof(ATOM_GPIO_I2C_ASSIGMENT)); @@ -541,7 +541,7 @@ bool amdgpu_atombios_get_connector_info_from_object_table(struct amdgpu_device * } } - amdgpu_link_encoder_connector(adev->ddev); + amdgpu_link_encoder_connector(adev_to_drm(adev)); return true; } @@ -1995,7 +1995,7 @@ int amdgpu_atombios_init(struct amdgpu_device *adev) return -ENOMEM; adev->mode_info.atom_card_info = atom_card_info; - atom_card_info->dev = adev->ddev; + atom_card_info->dev = adev_to_drm(adev); atom_card_info->reg_read = cail_reg_read; atom_card_info->reg_write = cail_reg_write; /* needed for iio ops */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 3bce625189ce..3d7508788eb5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -1521,7 +1521,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, struct amdgpu_hpd *hpd, struct amdgpu_router *router) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; struct amdgpu_connector *amdgpu_connector; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 37eb8e77d61e..abe0c2729e1c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -69,8 +69,8 @@ int amdgpu_debugfs_add_files(struct amdgpu_device *adev, adev->debugfs_count = i; #if defined(CONFIG_DEBUG_FS) drm_debugfs_create_files(files, nfiles, - adev->ddev->primary->debugfs_root, - adev->ddev->primary); + adev_to_drm(adev)->primary->debugfs_root, + adev_to_drm(adev)->primary); #endif return 0; } @@ -151,7 +151,7 @@ static void amdgpu_debugfs_autodump_init(struct amdgpu_device *adev) init_waitqueue_head(&adev->autodump.gpu_hang); debugfs_create_file("amdgpu_autodump", 0600, - adev->ddev->primary->debugfs_root, + adev_to_drm(adev)->primary->debugfs_root, adev, &autodump_debug_fops); } @@ -227,23 +227,23 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f, *pos &= (1UL << 22) - 1; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } if (use_bank) { if ((sh_bank != 0xFFFFFFFF && sh_bank >= adev->gfx.config.max_sh_per_se) || (se_bank != 0xFFFFFFFF && se_bank >= adev->gfx.config.max_shader_engines)) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return -EINVAL; } @@ -292,8 +292,8 @@ end: if (pm_pg_lock) mutex_unlock(&adev->pm.mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -340,15 +340,15 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -358,8 +358,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, value = RREG32_PCIE(*pos >> 2); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -370,8 +370,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -399,15 +399,15 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -416,8 +416,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -430,8 +430,8 @@ static ssize_t amdgpu_debugfs_regs_pcie_write(struct file *f, const char __user size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -459,15 +459,15 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -477,8 +477,8 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, value = RREG32_DIDT(*pos >> 2); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -489,8 +489,8 @@ static ssize_t amdgpu_debugfs_regs_didt_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -518,15 +518,15 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -535,8 +535,8 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -549,8 +549,8 @@ static ssize_t amdgpu_debugfs_regs_didt_write(struct file *f, const char __user size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -578,15 +578,15 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -596,8 +596,8 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, value = RREG32_SMC(*pos); r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -608,8 +608,8 @@ static ssize_t amdgpu_debugfs_regs_smc_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -637,15 +637,15 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -654,8 +654,8 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return r; } @@ -668,8 +668,8 @@ static ssize_t amdgpu_debugfs_regs_smc_write(struct file *f, const char __user * size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); amdgpu_virt_disable_access_debugfs(adev); return result; @@ -796,22 +796,22 @@ static ssize_t amdgpu_debugfs_sensor_read(struct file *f, char __user *buf, valuesize = sizeof(values); - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, idx, &values[0], &valuesize); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) { amdgpu_virt_disable_access_debugfs(adev); @@ -878,15 +878,15 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, wave = (*pos & GENMASK_ULL(36, 31)) >> 31; simd = (*pos & GENMASK_ULL(44, 37)) >> 37; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_virt_enable_access_debugfs(adev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -901,8 +901,8 @@ static ssize_t amdgpu_debugfs_wave_read(struct file *f, char __user *buf, amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (!x) { amdgpu_virt_disable_access_debugfs(adev); @@ -976,7 +976,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, if (!data) return -ENOMEM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) goto err; @@ -999,8 +999,8 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, amdgpu_gfx_select_se_sh(adev, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF); mutex_unlock(&adev->grbm_idx_mutex); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); while (size) { uint32_t value; @@ -1022,7 +1022,7 @@ static ssize_t amdgpu_debugfs_gpr_read(struct file *f, char __user *buf, return result; err: - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); kfree(data); return r; } @@ -1047,9 +1047,9 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1058,8 +1058,8 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu r = get_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1071,8 +1071,8 @@ static ssize_t amdgpu_debugfs_gfxoff_write(struct file *f, const char __user *bu size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return result; } @@ -1096,7 +1096,7 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, if (size & 0x3 || *pos & 0x3) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) return r; @@ -1105,15 +1105,15 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, r = amdgpu_get_gfx_off_status(adev, &value); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = put_user(value, (uint32_t *)buf); if (r) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1123,8 +1123,8 @@ static ssize_t amdgpu_debugfs_gfxoff_read(struct file *f, char __user *buf, size -= 4; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return result; } @@ -1216,7 +1216,7 @@ static const char *debugfs_regs_names[] = { */ int amdgpu_debugfs_regs_init(struct amdgpu_device *adev) { - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; unsigned int i; @@ -1241,7 +1241,7 @@ static int amdgpu_debugfs_test_ib(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1302,7 +1302,7 @@ static int amdgpu_debugfs_evict_vram(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1323,7 +1323,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) r = pm_runtime_get_sync(dev->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -1527,9 +1527,9 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val) if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) return -EINVAL; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -1542,8 +1542,8 @@ static int amdgpu_debugfs_sclk_set(void *data, u64 val) return 0; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (ret) return -EINVAL; @@ -1563,7 +1563,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) adev->debugfs_preempt = debugfs_create_file("amdgpu_preempt_ib", 0600, - adev->ddev->primary->debugfs_root, adev, + adev_to_drm(adev)->primary->debugfs_root, adev, &fops_ib_preempt); if (!(adev->debugfs_preempt)) { DRM_ERROR("unable to create amdgpu_preempt_ib debugsfs file\n"); @@ -1572,7 +1572,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev) adev->smu.debugfs_sclk = debugfs_create_file("amdgpu_force_sclk", 0200, - adev->ddev->primary->debugfs_root, adev, + adev_to_drm(adev)->primary->debugfs_root, adev, &fops_sclk_set); if (!(adev->smu.debugfs_sclk)) { DRM_ERROR("unable to create amdgpu_set_sclk debugsfs file\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 06aa0a98f4a5..afe8cb37d5b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1509,7 +1509,7 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev) adev->enable_virtual_display = false; if (amdgpu_virtual_display) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); const char *pci_address_name = pci_name(ddev->pdev); char *pciaddstr, *pciaddstr_tmp, *pciaddname_tmp, *pciaddname; @@ -2872,13 +2872,13 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) if (amdgpu_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) { task_barrier_enter(&hive->tb); - adev->asic_reset_res = amdgpu_device_baco_enter(adev->ddev); + adev->asic_reset_res = amdgpu_device_baco_enter(adev_to_drm(adev)); if (adev->asic_reset_res) goto fail; task_barrier_exit(&hive->tb); - adev->asic_reset_res = amdgpu_device_baco_exit(adev->ddev); + adev->asic_reset_res = amdgpu_device_baco_exit(adev_to_drm(adev)); if (adev->asic_reset_res) goto fail; @@ -2894,7 +2894,7 @@ static void amdgpu_device_xgmi_reset_func(struct work_struct *__work) fail: if (adev->asic_reset_res) DRM_WARN("ASIC reset failed with error, %d for drm dev, %s", - adev->asic_reset_res, adev->ddev->unique); + adev->asic_reset_res, adev_to_drm(adev)->unique); amdgpu_put_xgmi_hive(hive); } @@ -3243,7 +3243,7 @@ fence_driver_init: } /* init the mode config */ - drm_mode_config_init(adev->ddev); + drm_mode_config_init(adev_to_drm(adev)); r = amdgpu_device_ip_init(adev); if (r) { @@ -3385,9 +3385,9 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_irq_disable_all(adev); if (adev->mode_info.mode_config_initialized){ if (!amdgpu_device_has_dc_support(adev)) - drm_helper_force_disable_all(adev->ddev); + drm_helper_force_disable_all(adev_to_drm(adev)); else - drm_atomic_helper_shutdown(adev->ddev); + drm_atomic_helper_shutdown(adev_to_drm(adev)); } amdgpu_fence_driver_fini(adev); if (adev->pm_sysfs_en) @@ -3411,7 +3411,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) amdgpu_has_atpx_dgpu_power_cntl()) && !pci_is_thunderbolt_attached(adev->pdev)) vga_switcheroo_unregister_client(adev->pdev); - if (amdgpu_device_supports_boco(adev->ddev)) + if (amdgpu_device_supports_boco(adev_to_drm(adev))) vga_switcheroo_fini_domain_pm_ops(adev->dev); vga_client_register(adev->pdev, NULL, NULL, NULL); if (adev->rio_mem) @@ -4079,7 +4079,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, if (r) { dev_err(tmp_adev->dev, "ASIC reset failed with error, %d for drm dev, %s", - r, tmp_adev->ddev->unique); + r, adev_to_drm(tmp_adev)->unique); break; } } @@ -4452,7 +4452,7 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */ /*TODO Should we stop ?*/ if (r) { dev_err(tmp_adev->dev, "GPU pre asic reset failed with err, %d for drm dev, %s ", - r, tmp_adev->ddev->unique); + r, adev_to_drm(tmp_adev)->unique); tmp_adev->asic_reset_res = r; } } @@ -4488,7 +4488,7 @@ skip_hw_reset: } if (!amdgpu_device_has_dc_support(tmp_adev) && !job_signaled) { - drm_helper_resume_force_mode(tmp_adev->ddev); + drm_helper_resume_force_mode(adev_to_drm(tmp_adev)); } tmp_adev->asic_reset_res = 0; @@ -4665,7 +4665,7 @@ int amdgpu_device_baco_enter(struct drm_device *dev) struct amdgpu_device *adev = drm_to_adev(dev); struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); - if (!amdgpu_device_supports_baco(adev->ddev)) + if (!amdgpu_device_supports_baco(adev_to_drm(adev))) return -ENOTSUPP; if (ras && ras->supported) @@ -4680,7 +4680,7 @@ int amdgpu_device_baco_exit(struct drm_device *dev) struct amdgpu_ras *ras = amdgpu_ras_get_context(adev); int ret = 0; - if (!amdgpu_device_supports_baco(adev->ddev)) + if (!amdgpu_device_supports_baco(adev_to_drm(adev))) return -ENOTSUPP; ret = amdgpu_dpm_baco_exit(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index e7ebc7bb70de..c81206e6096f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -93,7 +93,7 @@ static void amdgpu_display_flip_work_func(struct work_struct *__work) * targeted by the flip */ if (amdgpu_crtc->enabled && - (amdgpu_display_get_crtc_scanoutpos(adev->ddev, work->crtc_id, 0, + (amdgpu_display_get_crtc_scanoutpos(adev_to_drm(adev), work->crtc_id, 0, &vpos, &hpos, NULL, NULL, &crtc->hwmode) & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == @@ -619,51 +619,51 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev) int sz; adev->mode_info.coherent_mode_property = - drm_property_create_range(adev->ddev, 0 , "coherent", 0, 1); + drm_property_create_range(adev_to_drm(adev), 0, "coherent", 0, 1); if (!adev->mode_info.coherent_mode_property) return -ENOMEM; adev->mode_info.load_detect_property = - drm_property_create_range(adev->ddev, 0, "load detection", 0, 1); + drm_property_create_range(adev_to_drm(adev), 0, "load detection", 0, 1); if (!adev->mode_info.load_detect_property) return -ENOMEM; - drm_mode_create_scaling_mode_property(adev->ddev); + drm_mode_create_scaling_mode_property(adev_to_drm(adev)); sz = ARRAY_SIZE(amdgpu_underscan_enum_list); adev->mode_info.underscan_property = - drm_property_create_enum(adev->ddev, 0, - "underscan", - amdgpu_underscan_enum_list, sz); + drm_property_create_enum(adev_to_drm(adev), 0, + "underscan", + amdgpu_underscan_enum_list, sz); adev->mode_info.underscan_hborder_property = - drm_property_create_range(adev->ddev, 0, - "underscan hborder", 0, 128); + drm_property_create_range(adev_to_drm(adev), 0, + "underscan hborder", 0, 128); if (!adev->mode_info.underscan_hborder_property) return -ENOMEM; adev->mode_info.underscan_vborder_property = - drm_property_create_range(adev->ddev, 0, - "underscan vborder", 0, 128); + drm_property_create_range(adev_to_drm(adev), 0, + "underscan vborder", 0, 128); if (!adev->mode_info.underscan_vborder_property) return -ENOMEM; sz = ARRAY_SIZE(amdgpu_audio_enum_list); adev->mode_info.audio_property = - drm_property_create_enum(adev->ddev, 0, + drm_property_create_enum(adev_to_drm(adev), 0, "audio", amdgpu_audio_enum_list, sz); sz = ARRAY_SIZE(amdgpu_dither_enum_list); adev->mode_info.dither_property = - drm_property_create_enum(adev->ddev, 0, + drm_property_create_enum(adev_to_drm(adev), 0, "dither", amdgpu_dither_enum_list, sz); if (amdgpu_device_has_dc_support(adev)) { adev->mode_info.abm_level_property = - drm_property_create_range(adev->ddev, 0, - "abm level", 0, 4); + drm_property_create_range(adev_to_drm(adev), 0, + "abm level", 0, 4); if (!adev->mode_info.abm_level_property) return -ENOMEM; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index db731f573f98..e2c2eb45a793 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -135,7 +135,7 @@ static int amdgpufb_create_pinned_object(struct amdgpu_fbdev *rfbdev, AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | AMDGPU_GEM_CREATE_VRAM_CLEARED; - info = drm_get_format_info(adev->ddev, mode_cmd); + info = drm_get_format_info(adev_to_drm(adev), mode_cmd); cpp = info->cpp[0]; /* need to align pitch with crtc limits */ @@ -231,7 +231,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, goto out; } - ret = amdgpu_display_framebuffer_init(adev->ddev, &rfbdev->rfb, + ret = amdgpu_display_framebuffer_init(adev_to_drm(adev), &rfbdev->rfb, &mode_cmd, gobj); if (ret) { DRM_ERROR("failed to initialize framebuffer %d\n", ret); @@ -254,7 +254,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, drm_fb_helper_fill_info(info, &rfbdev->helper, sizes); /* setup aperture base/size for vesafb takeover */ - info->apertures->ranges[0].base = adev->ddev->mode_config.fb_base; + info->apertures->ranges[0].base = adev_to_drm(adev)->mode_config.fb_base; info->apertures->ranges[0].size = adev->gmc.aper_size; /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ @@ -270,7 +270,7 @@ static int amdgpufb_create(struct drm_fb_helper *helper, DRM_INFO("fb depth is %d\n", fb->format->depth); DRM_INFO(" pitch is %d\n", fb->pitches[0]); - vga_switcheroo_client_fb_set(adev->ddev->pdev, info); + vga_switcheroo_client_fb_set(adev_to_drm(adev)->pdev, info); return 0; out: @@ -318,7 +318,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) return 0; /* don't init fbdev if there are no connectors */ - if (list_empty(&adev->ddev->mode_config.connector_list)) + if (list_empty(&adev_to_drm(adev)->mode_config.connector_list)) return 0; /* select 8 bpp console on low vram cards */ @@ -332,10 +332,10 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) rfbdev->adev = adev; adev->mode_info.rfbdev = rfbdev; - drm_fb_helper_prepare(adev->ddev, &rfbdev->helper, - &amdgpu_fb_helper_funcs); + drm_fb_helper_prepare(adev_to_drm(adev), &rfbdev->helper, + &amdgpu_fb_helper_funcs); - ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper); + ret = drm_fb_helper_init(adev_to_drm(adev), &rfbdev->helper); if (ret) { kfree(rfbdev); return ret; @@ -343,7 +343,7 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) /* disable all the possible outputs/crtcs before entering KMS mode */ if (!amdgpu_device_has_dc_support(adev)) - drm_helper_disable_unused_functions(adev->ddev); + drm_helper_disable_unused_functions(adev_to_drm(adev)); drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); return 0; @@ -354,7 +354,7 @@ void amdgpu_fbdev_fini(struct amdgpu_device *adev) if (!adev->mode_info.rfbdev) return; - amdgpu_fbdev_destroy(adev->ddev, adev->mode_info.rfbdev); + amdgpu_fbdev_destroy(adev_to_drm(adev), adev->mode_info.rfbdev); kfree(adev->mode_info.rfbdev); adev->mode_info.rfbdev = NULL; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index cfccd3d33341..fe2d495d08ab 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -155,7 +155,7 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, seq); amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, seq, flags | AMDGPU_FENCE_FLAG_INT); - pm_runtime_get_noresume(adev->ddev->dev); + pm_runtime_get_noresume(adev_to_drm(adev)->dev); ptr = &ring->fence_drv.fences[seq & ring->fence_drv.num_fences_mask]; if (unlikely(rcu_dereference_protected(*ptr, 1))) { struct dma_fence *old; @@ -284,8 +284,8 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring) BUG(); dma_fence_put(fence); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); } while (last_seq != seq); return true; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 8371a8724087..f4c2e2e75b8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -93,7 +93,7 @@ retry: void amdgpu_gem_force_release(struct amdgpu_device *adev) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct drm_file *file; mutex_lock(&ddev->filelist_mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index 411c84194f97..47cad23a6b9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c @@ -253,7 +253,7 @@ void amdgpu_i2c_add(struct amdgpu_device *adev, const struct amdgpu_i2c_bus_rec *rec, const char *name) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); int i; for (i = 0; i < AMDGPU_MAX_I2C_BUS; i++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 508cb34a9142..300ac73b4738 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -85,7 +85,7 @@ static void amdgpu_hotplug_work_func(struct work_struct *work) { struct amdgpu_device *adev = container_of(work, struct amdgpu_device, hotplug_work); - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_mode_config *mode_config = &dev->mode_config; struct drm_connector *connector; struct drm_connector_list_iter iter; @@ -268,9 +268,9 @@ int amdgpu_irq_init(struct amdgpu_device *adev) if (!adev->enable_virtual_display) /* Disable vblank IRQs aggressively for power-saving */ /* XXX: can this be enabled for DC? */ - adev->ddev->vblank_disable_immediate = true; + adev_to_drm(adev)->vblank_disable_immediate = true; - r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc); + r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc); if (r) return r; @@ -284,14 +284,14 @@ int amdgpu_irq_init(struct amdgpu_device *adev) adev->irq.installed = true; /* Use vector 0 for MSI-X */ - r = drm_irq_install(adev->ddev, pci_irq_vector(adev->pdev, 0)); + r = drm_irq_install(adev_to_drm(adev), pci_irq_vector(adev->pdev, 0)); if (r) { adev->irq.installed = false; if (!amdgpu_device_has_dc_support(adev)) flush_work(&adev->hotplug_work); return r; } - adev->ddev->max_vblank_count = 0x00ffffff; + adev_to_drm(adev)->max_vblank_count = 0x00ffffff; DRM_DEBUG("amdgpu: irq initialized.\n"); return 0; @@ -311,7 +311,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev) unsigned i, j; if (adev->irq.installed) { - drm_irq_uninstall(adev->ddev); + drm_irq_uninstall(adev_to_drm(adev)); adev->irq.installed = false; if (adev->irq.msi_enabled) pci_free_irq_vectors(adev->pdev); @@ -522,7 +522,7 @@ void amdgpu_irq_gpu_reset_resume_helper(struct amdgpu_device *adev) int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return -ENOENT; if (type >= src->num_types) @@ -552,7 +552,7 @@ int amdgpu_irq_get(struct amdgpu_device *adev, struct amdgpu_irq_src *src, int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return -ENOENT; if (type >= src->num_types) @@ -583,7 +583,7 @@ int amdgpu_irq_put(struct amdgpu_device *adev, struct amdgpu_irq_src *src, bool amdgpu_irq_enabled(struct amdgpu_device *adev, struct amdgpu_irq_src *src, unsigned type) { - if (!adev->ddev->irq_enabled) + if (!adev_to_drm(adev)->irq_enabled) return false; if (type >= src->num_types) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 3080b5644121..92fbbfb16cff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -555,7 +555,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; - drm_gem_private_object_init(adev->ddev, &bo->tbo.base, size); + drm_gem_private_object_init(adev_to_drm(adev), &bo->tbo.base, size); INIT_LIST_HEAD(&bo->shadow_list); bo->vm_bo = NULL; bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c index 1311d6aec5d4..69af462db34d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pmu.c @@ -226,7 +226,7 @@ static int init_pmu_by_type(struct amdgpu_device *adev, pmu_entry->pmu.attr_groups = attr_groups; pmu_entry->pmu_perf_type = pmu_perf_type; snprintf(pmu_name, PMU_NAME_SIZE, "%s_%d", - pmu_file_prefix, adev->ddev->primary->index); + pmu_file_prefix, adev_to_drm(adev)->primary->index); ret = perf_pmu_register(&pmu_entry->pmu, pmu_name, -1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c index 87cbc9011b2d..8da5356c36f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_rap.c @@ -46,7 +46,7 @@ static ssize_t amdgpu_rap_debugfs_write(struct file *f, const char __user *buf, struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(f)->i_private; struct ta_rap_shared_memory *rap_shared_mem; struct ta_rap_cmd_output_data *rap_cmd_output; - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); uint32_t op; int ret; @@ -116,7 +116,7 @@ static const struct file_operations amdgpu_rap_debugfs_ops = { void amdgpu_rap_debugfs_init(struct amdgpu_device *adev) { #if defined(CONFIG_DEBUG_FS) - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; if (!adev->psp.rap_context.rap_initialized) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index ec377a8147a2..9b718749919a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1197,7 +1197,7 @@ static int amdgpu_ras_sysfs_remove_all(struct amdgpu_device *adev) static void amdgpu_ras_debugfs_create_ctrl_node(struct amdgpu_device *adev) { struct amdgpu_ras *con = amdgpu_ras_get_context(adev); - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; con->dir = debugfs_create_dir(RAS_FS_NAME, minor->debugfs_root); debugfs_create_file("ras_ctrl", S_IWUGO | S_IRUGO, con->dir, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 6d4fc79bf84a..15ee13c3bd9e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -420,7 +420,7 @@ int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring) { #if defined(CONFIG_DEBUG_FS) - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; char name[32]; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 245d9352ef51..798985b94685 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1921,8 +1921,8 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) /* No others user of address space so set it to 0 */ r = ttm_bo_device_init(&adev->mman.bdev, &amdgpu_bo_driver, - adev->ddev->anon_inode->i_mapping, - adev->ddev->vma_offset_manager, + adev_to_drm(adev)->anon_inode->i_mapping, + adev_to_drm(adev)->vma_offset_manager, dma_addressing_limited(adev->dev)); if (r) { DRM_ERROR("failed initializing buffer object driver(%d).\n", r); @@ -2606,7 +2606,7 @@ int amdgpu_ttm_debugfs_init(struct amdgpu_device *adev) #if defined(CONFIG_DEBUG_FS) unsigned count; - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *ent, *root = minor->debugfs_root; for (count = 0; count < ARRAY_SIZE(ttm_debugfs_entries); count++) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index d84649b4d51a..f76961d17246 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -45,7 +45,7 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) if (adev->mode_info.num_crtc == 0) adev->mode_info.num_crtc = 1; adev->enable_virtual_display = true; - adev->ddev->driver->driver_features &= ~DRIVER_ATOMIC; + adev_to_drm(adev)->driver->driver_features &= ~DRIVER_ATOMIC; adev->cg_flags = 0; adev->pg_flags = 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c index bda3f709a8e1..1162913c8bf4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c @@ -294,7 +294,7 @@ static int amdgpu_xgmi_sysfs_add_dev_info(struct amdgpu_device *adev, remove_link: - sysfs_remove_link(&adev->dev->kobj, adev->ddev->unique); + sysfs_remove_link(&adev->dev->kobj, adev_to_drm(adev)->unique); remove_file: device_remove_file(adev->dev, &dev_attr_xgmi_device_id); diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c index a7466f3562bc..8339c8c3a328 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c @@ -1673,7 +1673,7 @@ amdgpu_atombios_encoder_set_crtc_source(struct drm_encoder *encoder) void amdgpu_atombios_encoder_init_dig(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 65301a56344b..5963cbe0d455 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -328,7 +328,7 @@ static void dce_v10_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -383,7 +383,7 @@ static void dce_v10_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v10_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2701,7 +2701,7 @@ static int dce_v10_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v10_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v10_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2709,8 +2709,8 @@ static int dce_v10_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = 128; amdgpu_crtc->max_cursor_height = 128; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; switch (amdgpu_crtc->crtc_id) { case 0: @@ -2792,24 +2792,24 @@ static int dce_v10_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2819,7 +2819,7 @@ static int dce_v10_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2832,7 +2832,7 @@ static int dce_v10_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2844,13 +2844,13 @@ static int dce_v10_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v10_0_audio_fini(adev); dce_v10_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3157,14 +3157,14 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3176,7 +3176,7 @@ static int dce_v10_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3245,7 +3245,7 @@ static int dce_v10_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); @@ -3485,7 +3485,7 @@ static void dce_v10_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 0847fb6485de..1954472c8e8f 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -346,7 +346,7 @@ static void dce_v11_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -400,7 +400,7 @@ static void dce_v11_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v11_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2809,7 +2809,7 @@ static int dce_v11_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v11_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v11_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2817,8 +2817,8 @@ static int dce_v11_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = 128; amdgpu_crtc->max_cursor_height = 128; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; switch (amdgpu_crtc->crtc_id) { case 0: @@ -2913,24 +2913,24 @@ static int dce_v11_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ @@ -2941,7 +2941,7 @@ static int dce_v11_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2954,7 +2954,7 @@ static int dce_v11_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2966,13 +2966,13 @@ static int dce_v11_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v11_0_audio_fini(adev); dce_v11_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3283,14 +3283,14 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev, if(amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3302,7 +3302,7 @@ static int dce_v11_0_pageflip_irq(struct amdgpu_device *adev, if(works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3372,7 +3372,7 @@ static int dce_v11_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); @@ -3611,7 +3611,7 @@ static void dce_v11_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index e234d6fb49ab..3a44753a80d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -279,7 +279,7 @@ static void dce_v6_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -324,7 +324,7 @@ static void dce_v6_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v6_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2591,7 +2591,7 @@ static int dce_v6_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v6_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v6_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2599,8 +2599,8 @@ static int dce_v6_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = CURSOR_WIDTH; amdgpu_crtc->max_cursor_height = CURSOR_HEIGHT; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; amdgpu_crtc->crtc_offset = crtc_offsets[amdgpu_crtc->crtc_id]; @@ -2669,20 +2669,20 @@ static int dce_v6_0_sw_init(void *handle) adev->mode_info.mode_config_initialized = true; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2693,7 +2693,7 @@ static int dce_v6_0_sw_init(void *handle) ret = amdgpu_atombios_get_connector_info_from_object_table(adev); if (ret) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2706,7 +2706,7 @@ static int dce_v6_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); return r; } @@ -2717,12 +2717,12 @@ static int dce_v6_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v6_0_audio_fini(adev); dce_v6_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -2967,7 +2967,7 @@ static int dce_v6_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); break; @@ -3036,14 +3036,14 @@ static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3055,7 +3055,7 @@ static int dce_v6_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3297,7 +3297,7 @@ static void dce_v6_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 7cc8f7c4bc1f..3603e5f13077 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -273,7 +273,7 @@ static void dce_v8_0_hpd_set_polarity(struct amdgpu_device *adev, */ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -318,7 +318,7 @@ static void dce_v8_0_hpd_init(struct amdgpu_device *adev) */ static void dce_v8_0_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; u32 tmp; @@ -2609,7 +2609,7 @@ static int dce_v8_0_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_v8_0_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_v8_0_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -2617,8 +2617,8 @@ static int dce_v8_0_crtc_init(struct amdgpu_device *adev, int index) amdgpu_crtc->max_cursor_width = CIK_CURSOR_WIDTH; amdgpu_crtc->max_cursor_height = CIK_CURSOR_HEIGHT; - adev->ddev->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; - adev->ddev->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; + adev_to_drm(adev)->mode_config.cursor_width = amdgpu_crtc->max_cursor_width; + adev_to_drm(adev)->mode_config.cursor_height = amdgpu_crtc->max_cursor_height; amdgpu_crtc->crtc_offset = crtc_offsets[amdgpu_crtc->crtc_id]; @@ -2689,24 +2689,24 @@ static int dce_v8_0_sw_init(void *handle) if (r) return r; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -2716,7 +2716,7 @@ static int dce_v8_0_sw_init(void *handle) } if (amdgpu_atombios_get_connector_info_from_object_table(adev)) - amdgpu_display_print_display_setup(adev->ddev); + amdgpu_display_print_display_setup(adev_to_drm(adev)); else return -EINVAL; @@ -2729,7 +2729,7 @@ static int dce_v8_0_sw_init(void *handle) if (r) return r; - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -2741,13 +2741,13 @@ static int dce_v8_0_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); dce_v8_0_audio_fini(adev); dce_v8_0_afmt_fini(adev); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = false; return 0; @@ -3057,7 +3057,7 @@ static int dce_v8_0_crtc_irq(struct amdgpu_device *adev, DRM_DEBUG("IH: IH event w/o asserted irq bit?\n"); if (amdgpu_irq_enabled(adev, source, irq_type)) { - drm_handle_vblank(adev->ddev, crtc); + drm_handle_vblank(adev_to_drm(adev), crtc); } DRM_DEBUG("IH: D%d vblank\n", crtc + 1); break; @@ -3126,14 +3126,14 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -3145,7 +3145,7 @@ static int dce_v8_0_pageflip_irq(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); schedule_work(&works->unpin_work); @@ -3373,7 +3373,7 @@ static void dce_v8_0_encoder_add(struct amdgpu_device *adev, uint32_t supported_device, u16 caps) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index 5bc784531e65..cc93577dee03 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -235,7 +235,7 @@ static int dce_virtual_crtc_init(struct amdgpu_device *adev, int index) if (amdgpu_crtc == NULL) return -ENOMEM; - drm_crtc_init(adev->ddev, &amdgpu_crtc->base, &dce_virtual_crtc_funcs); + drm_crtc_init(adev_to_drm(adev), &amdgpu_crtc->base, &dce_virtual_crtc_funcs); drm_mode_crtc_set_gamma_size(&amdgpu_crtc->base, 256); amdgpu_crtc->crtc_id = index; @@ -374,24 +374,24 @@ static int dce_virtual_sw_init(void *handle) if (r) return r; - adev->ddev->max_vblank_count = 0; + adev_to_drm(adev)->max_vblank_count = 0; - adev->ddev->mode_config.funcs = &amdgpu_mode_funcs; + adev_to_drm(adev)->mode_config.funcs = &amdgpu_mode_funcs; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; r = amdgpu_display_modeset_create_props(adev); if (r) return r; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; /* allocate crtcs, encoders, connectors */ for (i = 0; i < adev->mode_info.num_crtc; i++) { @@ -403,7 +403,7 @@ static int dce_virtual_sw_init(void *handle) return r; } - drm_kms_helper_poll_init(adev->ddev); + drm_kms_helper_poll_init(adev_to_drm(adev)); adev->mode_info.mode_config_initialized = true; return 0; @@ -415,9 +415,9 @@ static int dce_virtual_sw_fini(void *handle) kfree(adev->mode_info.bios_hardcoded_edid); - drm_kms_helper_poll_fini(adev->ddev); + drm_kms_helper_poll_fini(adev_to_drm(adev)); - drm_mode_config_cleanup(adev->ddev); + drm_mode_config_cleanup(adev_to_drm(adev)); /* clear crtcs pointer to avoid dce irq finish routine access freed data */ memset(adev->mode_info.crtcs, 0, sizeof(adev->mode_info.crtcs[0]) * AMDGPU_MAX_CRTCS); adev->mode_info.mode_config_initialized = false; @@ -602,7 +602,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, if (!encoder) return -ENOMEM; encoder->possible_crtcs = 1 << index; - drm_encoder_init(adev->ddev, encoder, &dce_virtual_encoder_funcs, + drm_encoder_init(adev_to_drm(adev), encoder, &dce_virtual_encoder_funcs, DRM_MODE_ENCODER_VIRTUAL, NULL); drm_encoder_helper_add(encoder, &dce_virtual_encoder_helper_funcs); @@ -613,7 +613,7 @@ static int dce_virtual_connector_encoder_init(struct amdgpu_device *adev, } /* add a new connector */ - drm_connector_init(adev->ddev, connector, &dce_virtual_connector_funcs, + drm_connector_init(adev_to_drm(adev), connector, &dce_virtual_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); drm_connector_helper_add(connector, &dce_virtual_connector_helper_funcs); connector->display_info.subpixel_order = SubPixelHorizontalRGB; @@ -663,14 +663,14 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, if (amdgpu_crtc == NULL) return 0; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); works = amdgpu_crtc->pflip_works; if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) { DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d != " "AMDGPU_FLIP_SUBMITTED(%d)\n", amdgpu_crtc->pflip_status, AMDGPU_FLIP_SUBMITTED); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return 0; } @@ -682,7 +682,7 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev, if (works->event) drm_crtc_send_vblank_event(&amdgpu_crtc->base, works->event); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); drm_crtc_vblank_put(&amdgpu_crtc->base); amdgpu_bo_unref(&works->old_abo); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index a81c74f32209..ec6710f6c873 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -268,7 +268,7 @@ static struct amdgpu_crtc * get_crtc_by_otg_inst(struct amdgpu_device *adev, int otg_inst) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; @@ -320,7 +320,7 @@ static void dm_pflip_high_irq(void *interrupt_params) return; } - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){ DRM_DEBUG_DRIVER("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n", @@ -328,7 +328,7 @@ static void dm_pflip_high_irq(void *interrupt_params) AMDGPU_FLIP_SUBMITTED, amdgpu_crtc->crtc_id, amdgpu_crtc); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); return; } @@ -380,7 +380,7 @@ static void dm_pflip_high_irq(void *interrupt_params) e->sequence = drm_crtc_vblank_count(&amdgpu_crtc->base); e->pipe = amdgpu_crtc->crtc_id; - list_add_tail(&e->base.link, &adev->ddev->vblank_event_list); + list_add_tail(&e->base.link, &adev_to_drm(adev)->vblank_event_list); e = NULL; } @@ -393,7 +393,7 @@ static void dm_pflip_high_irq(void *interrupt_params) amdgpu_get_vblank_counter_kms(&amdgpu_crtc->base); amdgpu_crtc->pflip_status = AMDGPU_FLIP_NONE; - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_NONE, vrr[%d]-fp %d\n", amdgpu_crtc->crtc_id, amdgpu_crtc, @@ -429,7 +429,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) /* BTR processing for pre-DCE12 ASICs */ if (acrtc_state->stream && adev->family < AMDGPU_FAMILY_AI) { - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); mod_freesync_handle_v_update( adev->dm.freesync_module, acrtc_state->stream, @@ -439,7 +439,7 @@ static void dm_vupdate_high_irq(void *interrupt_params) adev->dm.dc, acrtc_state->stream, &acrtc_state->vrr_params.adjust); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } } } @@ -489,7 +489,7 @@ static void dm_crtc_high_irq(void *interrupt_params) if (adev->family < AMDGPU_FAMILY_AI) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); if (acrtc_state->stream && acrtc_state->vrr_params.supported && acrtc_state->freesync_config.state == VRR_STATE_ACTIVE_VARIABLE) { @@ -522,7 +522,7 @@ static void dm_crtc_high_irq(void *interrupt_params) acrtc->pflip_status = AMDGPU_FLIP_NONE; } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static int dm_set_clockgating_state(void *handle, @@ -850,7 +850,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) #endif int r; - adev->dm.ddev = adev->ddev; + adev->dm.ddev = adev_to_drm(adev); adev->dm.adev = adev; /* Zero all the fields */ @@ -986,10 +986,10 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) /* TODO: Add_display_info? */ /* TODO use dynamic cursor width */ - adev->ddev->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; - adev->ddev->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; + adev_to_drm(adev)->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size; + adev_to_drm(adev)->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size; - if (drm_vblank_init(adev->ddev, adev->dm.display_indexes_num)) { + if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) { DRM_ERROR( "amdgpu: failed to initialize sw for display support.\n"); goto error; @@ -1390,7 +1390,7 @@ static int dm_late_init(void *handle) bool ret = true; if (!adev->dm.fw_dmcu) - return detect_mst_link_for_all_connectors(adev->ddev); + return detect_mst_link_for_all_connectors(adev_to_drm(adev)); dmcu = adev->dm.dc->res_pool->dmcu; @@ -1420,7 +1420,7 @@ static int dm_late_init(void *handle) if (!ret) return -EINVAL; - return detect_mst_link_for_all_connectors(adev->ddev); + return detect_mst_link_for_all_connectors(adev_to_drm(adev)); } static void s3_handle_mst(struct drm_device *dev, bool suspend) @@ -1672,9 +1672,9 @@ static int dm_suspend(void *handle) } WARN_ON(adev->dm.cached_state); - adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev); + adev->dm.cached_state = drm_atomic_helper_suspend(adev_to_drm(adev)); - s3_handle_mst(adev->ddev, true); + s3_handle_mst(adev_to_drm(adev), true); amdgpu_dm_irq_suspend(adev); @@ -1828,7 +1828,7 @@ cleanup: static int dm_resume(void *handle) { struct amdgpu_device *adev = handle; - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct amdgpu_display_manager *dm = &adev->dm; struct amdgpu_dm_connector *aconnector; struct drm_connector *connector; @@ -2443,7 +2443,7 @@ static void handle_hpd_rx_irq(void *param) static void register_hpd_handlers(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct amdgpu_dm_connector *aconnector; const struct dc_link *dc_link; @@ -2874,18 +2874,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) adev->mode_info.mode_config_initialized = true; - adev->ddev->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; - adev->ddev->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; + adev_to_drm(adev)->mode_config.funcs = (void *)&amdgpu_dm_mode_funcs; + adev_to_drm(adev)->mode_config.helper_private = &amdgpu_dm_mode_config_helperfuncs; - adev->ddev->mode_config.max_width = 16384; - adev->ddev->mode_config.max_height = 16384; + adev_to_drm(adev)->mode_config.max_width = 16384; + adev_to_drm(adev)->mode_config.max_height = 16384; - adev->ddev->mode_config.preferred_depth = 24; - adev->ddev->mode_config.prefer_shadow = 1; + adev_to_drm(adev)->mode_config.preferred_depth = 24; + adev_to_drm(adev)->mode_config.prefer_shadow = 1; /* indicates support for immediate flip */ - adev->ddev->mode_config.async_page_flip = true; + adev_to_drm(adev)->mode_config.async_page_flip = true; - adev->ddev->mode_config.fb_base = adev->gmc.aper_base; + adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base; state = kzalloc(sizeof(*state), GFP_KERNEL); if (!state) @@ -2899,7 +2899,7 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) dc_resource_state_copy_construct_current(adev->dm.dc, state->context); - drm_atomic_private_obj_init(adev->ddev, + drm_atomic_private_obj_init(adev_to_drm(adev), &adev->dm.atomic_obj, &state->base, &dm_atomic_state_funcs); @@ -3065,13 +3065,13 @@ amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm) props.type = BACKLIGHT_RAW; snprintf(bl_name, sizeof(bl_name), "amdgpu_bl%d", - dm->adev->ddev->primary->index); + adev_to_drm(dm->adev)->primary->index); dm->backlight_dev = backlight_device_register(bl_name, - dm->adev->ddev->dev, - dm, - &amdgpu_dm_backlight_ops, - &props); + adev_to_drm(dm->adev)->dev, + dm, + &amdgpu_dm_backlight_ops, + &props); if (IS_ERR(dm->backlight_dev)) DRM_ERROR("DM: Backlight registration failed!\n"); @@ -3395,7 +3395,7 @@ static ssize_t s3_debug_store(struct device *device, if (ret == 0) { if (s3_state) { dm_resume(adev); - drm_kms_helper_hotplug_event(adev->ddev); + drm_kms_helper_hotplug_event(adev_to_drm(adev)); } else dm_suspend(adev); } @@ -3522,7 +3522,7 @@ static int dm_early_init(void *handle) */ #if defined(CONFIG_DEBUG_KERNEL_DC) device_create_file( - adev->ddev->dev, + adev_to_drm(adev)->dev, &dev_attr_s3_debug); #endif @@ -5986,7 +5986,7 @@ static int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm, num_formats = get_plane_formats(plane, plane_cap, formats, ARRAY_SIZE(formats)); - res = drm_universal_plane_init(dm->adev->ddev, plane, possible_crtcs, + res = drm_universal_plane_init(adev_to_drm(dm->adev), plane, possible_crtcs, &dm_plane_funcs, formats, num_formats, NULL, plane->type, NULL); if (res) @@ -6830,7 +6830,7 @@ static void update_freesync_state_on_stream( if (!new_stream->timing.h_total || !new_stream->timing.v_total) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); vrr_params = new_crtc_state->vrr_params; if (surface) { @@ -6883,7 +6883,7 @@ static void update_freesync_state_on_stream( (int)new_crtc_state->base.vrr_enabled, (int)vrr_params.state); - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static void pre_update_freesync_state_on_stream( @@ -6906,7 +6906,7 @@ static void pre_update_freesync_state_on_stream( if (!new_stream->timing.h_total || !new_stream->timing.v_total) return; - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); vrr_params = new_crtc_state->vrr_params; if (new_crtc_state->vrr_supported && @@ -6929,7 +6929,7 @@ static void pre_update_freesync_state_on_stream( sizeof(vrr_params.adjust)) != 0); new_crtc_state->vrr_params = vrr_params; - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); } static void amdgpu_dm_handle_vrr_transition(struct dm_crtc_state *old_state, @@ -7741,7 +7741,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) * send vblank event on all events not handled in flip and * mark consumed event for drm_atomic_helper_commit_hw_done */ - spin_lock_irqsave(&adev->ddev->event_lock, flags); + spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags); for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->event) @@ -7749,7 +7749,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) new_crtc_state->event = NULL; } - spin_unlock_irqrestore(&adev->ddev->event_lock, flags); + spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags); /* Signal HW programming completion */ drm_atomic_helper_commit_hw_done(state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 5703a68d8302..f878575d17bb 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -2194,7 +2194,7 @@ static int force_timing_sync_set(void *data, u64 val) adev->dm.force_timing_sync = (bool)val; - amdgpu_dm_trigger_timing_sync(adev->ddev); + amdgpu_dm_trigger_timing_sync(adev_to_drm(adev)); return 0; } @@ -2253,7 +2253,7 @@ int dtn_debugfs_init(struct amdgpu_device *adev) .llseek = default_llseek }; - struct drm_minor *minor = adev->ddev->primary; + struct drm_minor *minor = adev_to_drm(adev)->primary; struct dentry *root = minor->debugfs_root; int ret; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c index cbcf504f73a5..357778556b06 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c @@ -719,7 +719,7 @@ void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev) */ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; @@ -755,7 +755,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev) */ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_connector *connector; struct drm_connector_list_iter iter; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 8aba40345b54..bbc20834c643 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -310,7 +310,7 @@ static const struct drm_encoder_funcs amdgpu_dm_encoder_funcs = { void dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); int i; for (i = 0; i < adev->dm.display_indexes_num; i++) { @@ -426,7 +426,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, aconnector->mst_mgr.cbs = &dm_mst_cbs; drm_dp_mst_topology_mgr_init( &aconnector->mst_mgr, - dm->adev->ddev, + adev_to_drm(dm->adev), &aconnector->dm_dp_aux.aux, 16, 4, diff --git a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c index ca3fb32979d4..17a45baff638 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_dpm.c @@ -122,7 +122,7 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) { - struct drm_device *ddev = adev->ddev; + struct drm_device *ddev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; @@ -143,7 +143,7 @@ void amdgpu_dpm_get_active_displays(struct amdgpu_device *adev) u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; u32 vblank_in_pixels; @@ -170,7 +170,7 @@ u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev) { - struct drm_device *dev = adev->ddev; + struct drm_device *dev = adev_to_drm(adev); struct drm_crtc *crtc; struct amdgpu_crtc *amdgpu_crtc; u32 vrefresh = 0; diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index ea00c4b0e74b..2d924e88a215 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1903,7 +1903,7 @@ static ssize_t amdgpu_get_thermal_throttling_logging(struct device *dev, struct amdgpu_device *adev = drm_to_adev(ddev); return snprintf(buf, PAGE_SIZE, "%s: thermal throttling logging %s, with interval %d seconds\n", - adev->ddev->unique, + adev_to_drm(adev)->unique, atomic_read(&adev->throttling_logging_enabled) ? "enabled" : "disabled", adev->throttling_logging_rs.interval / HZ + 1); } @@ -2199,9 +2199,9 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, if (channel >= PP_TEMP_MAX) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2226,8 +2226,8 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, break; } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2332,9 +2332,9 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2342,16 +2342,16 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return sprintf(buf, "%i\n", pwm_mode); } @@ -2372,9 +2372,9 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, if (err) return err; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2382,16 +2382,16 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, smu_set_fan_control_mode(&adev->smu, value); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, value); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return count; } @@ -2422,9 +2422,9 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2435,15 +2435,15 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, if (pwm_mode != AMD_FAN_CTRL_MANUAL) { pr_info("manual fan speed control should be enabled first\n"); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } err = kstrtou32(buf, 10, &value); if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2456,8 +2456,8 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2476,9 +2476,9 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2489,8 +2489,8 @@ static ssize_t amdgpu_hwmon_get_pwm1(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2511,9 +2511,9 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2524,8 +2524,8 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2545,17 +2545,17 @@ static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM, (void *)&min_rpm, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2575,17 +2575,17 @@ static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM, (void *)&max_rpm, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2604,9 +2604,9 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2617,8 +2617,8 @@ static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2638,9 +2638,9 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2650,15 +2650,15 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); if (pwm_mode != AMD_FAN_CTRL_MANUAL) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -ENODATA; } err = kstrtou32(buf, 10, &value); if (err) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2669,8 +2669,8 @@ static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -2689,9 +2689,9 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - ret = pm_runtime_get_sync(adev->ddev->dev); + ret = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (ret < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return ret; } @@ -2699,16 +2699,16 @@ static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev, pwm_mode = smu_get_fan_control_mode(&adev->smu); } else { if (!adev->powerplay.pp_funcs->get_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1); } @@ -2737,9 +2737,9 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, else return -EINVAL; - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2747,15 +2747,15 @@ static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev, smu_set_fan_control_mode(&adev->smu, pwm_mode); } else { if (!adev->powerplay.pp_funcs->set_fan_control_mode) { - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return -EINVAL; } amdgpu_dpm_set_fan_control_mode(adev, pwm_mode); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return count; } @@ -2771,9 +2771,9 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2781,8 +2781,8 @@ static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDGFX, (void *)&vddgfx, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2812,9 +2812,9 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, if (!(adev->flags & AMD_IS_APU)) return -EINVAL; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2822,8 +2822,8 @@ static ssize_t amdgpu_hwmon_show_vddnb(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VDDNB, (void *)&vddnb, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2850,9 +2850,9 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2860,8 +2860,8 @@ static ssize_t amdgpu_hwmon_show_power_avg(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GPU_POWER, (void *)&query, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -2891,9 +2891,9 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2907,8 +2907,8 @@ static ssize_t amdgpu_hwmon_show_power_cap_max(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return size; } @@ -2925,9 +2925,9 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -2941,8 +2941,8 @@ static ssize_t amdgpu_hwmon_show_power_cap(struct device *dev, size = snprintf(buf, PAGE_SIZE, "\n"); } - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return size; } @@ -2970,9 +2970,9 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, value = value / 1000000; /* convert to Watt */ - err = pm_runtime_get_sync(adev->ddev->dev); + err = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (err < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return err; } @@ -2983,8 +2983,8 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev, else err = -EINVAL; - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (err) return err; @@ -3003,9 +3003,9 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -3013,8 +3013,8 @@ static ssize_t amdgpu_hwmon_show_sclk(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_SCLK, (void *)&sclk, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; @@ -3040,9 +3040,9 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, if (amdgpu_in_reset(adev)) return -EPERM; - r = pm_runtime_get_sync(adev->ddev->dev); + r = pm_runtime_get_sync(adev_to_drm(adev)->dev); if (r < 0) { - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); return r; } @@ -3050,8 +3050,8 @@ static ssize_t amdgpu_hwmon_show_mclk(struct device *dev, r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_GFX_MCLK, (void *)&mclk, &size); - pm_runtime_mark_last_busy(adev->ddev->dev); - pm_runtime_put_autosuspend(adev->ddev->dev); + pm_runtime_mark_last_busy(adev_to_drm(adev)->dev); + pm_runtime_put_autosuspend(adev_to_drm(adev)->dev); if (r) return r; -- cgit v1.2.3 From ced026e959bec5046afa310d6474e147b6294da2 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Mon, 24 Aug 2020 14:26:38 -0400 Subject: drm/i915: Update DRIVER_DATE to 20200824 Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4b5c25a018b7..1314e0e92c41 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -108,8 +108,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20200715" -#define DRIVER_TIMESTAMP 1594811881 +#define DRIVER_DATE "20200824" +#define DRIVER_TIMESTAMP 1598293597 struct drm_i915_gem_object; -- cgit v1.2.3 From e5f10d6385cda083037915c12b130887c8831d2b Mon Sep 17 00:00:00 2001 From: Mika Kuoppala Date: Mon, 17 Aug 2020 22:59:26 +0300 Subject: drm/i915: Fix cmd parser desc matching with masks Our variety of defined gpu commands have the actual command id field and possibly length and flags applied. We did start to apply the mask during initialization of the cmd descriptors but forgot to also apply it on comparisons. Fix comparisons in order to properly deny access with associated commands. v2: fix lri with correct mask (Chris) References: 926abff21a8f ("drm/i915/cmdparser: Ignore Length operands during command matching") Reported-by: Nicolai Stange Cc: stable@vger.kernel.org # v5.4+ Cc: Miroslav Benes Cc: Takashi Iwai Cc: Tyler Hicks Cc: Jon Bloomfield Cc: Chris Wilson Signed-off-by: Mika Kuoppala Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20200817195926.12671-1-mika.kuoppala@linux.intel.com (cherry picked from commit 3b4efa148da36f158cce3f662e831af2834b8e0f) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_cmd_parser.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 372354d33f55..5ac4a999f05a 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1204,6 +1204,12 @@ static u32 *copy_batch(struct drm_i915_gem_object *dst_obj, return dst; } +static inline bool cmd_desc_is(const struct drm_i915_cmd_descriptor * const desc, + const u32 cmd) +{ + return desc->cmd.value == (cmd & desc->cmd.mask); +} + static bool check_cmd(const struct intel_engine_cs *engine, const struct drm_i915_cmd_descriptor *desc, const u32 *cmd, u32 length) @@ -1242,19 +1248,19 @@ static bool check_cmd(const struct intel_engine_cs *engine, * allowed mask/value pair given in the whitelist entry. */ if (reg->mask) { - if (desc->cmd.value == MI_LOAD_REGISTER_MEM) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_MEM)) { DRM_DEBUG("CMD: Rejected LRM to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_REG) { + if (cmd_desc_is(desc, MI_LOAD_REGISTER_REG)) { DRM_DEBUG("CMD: Rejected LRR to masked register 0x%08X\n", reg_addr); return false; } - if (desc->cmd.value == MI_LOAD_REGISTER_IMM(1) && + if (cmd_desc_is(desc, MI_LOAD_REGISTER_IMM(1)) && (offset + 2 > length || (cmd[offset + 1] & reg->mask) != reg->value)) { DRM_DEBUG("CMD: Rejected LRI to masked register 0x%08X\n", @@ -1478,7 +1484,7 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, break; } - if (desc->cmd.value == MI_BATCH_BUFFER_START) { + if (cmd_desc_is(desc, MI_BATCH_BUFFER_START)) { ret = check_bbstart(cmd, offset, length, batch_length, batch_addr, shadow_addr, jump_whitelist); -- cgit v1.2.3 From 7fd5b25499bcec157dd4de9a713425efcf4571cd Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 19 Aug 2020 13:30:21 +0300 Subject: drm/omap: fix incorrect lock state After commit 92cc68e35863c1c61c449efa2b2daef6e9926048 ("drm/vblank: Use spin_(un)lock_irq() in drm_crtc_vblank_on()") omapdrm locking is broken: WARNING: inconsistent lock state 5.8.0-rc2-00483-g92cc68e35863 #13 Tainted: G W -------------------------------- inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. swapper/0/0 [HC1[1]:SC0[0]:HE0:SE1] takes: ea98222c (&dev->event_lock#2){?.+.}-{2:2}, at: drm_handle_vblank+0x4c/0x520 [drm] {HARDIRQ-ON-W} state was registered at: trace_hardirqs_on+0x9c/0x1ec _raw_spin_unlock_irq+0x20/0x58 omap_crtc_atomic_enable+0x54/0xa0 [omapdrm] drm_atomic_helper_commit_modeset_enables+0x218/0x270 [drm_kms_helper] omap_atomic_commit_tail+0x48/0xc4 [omapdrm] commit_tail+0x9c/0x190 [drm_kms_helper] drm_atomic_helper_commit+0x154/0x188 [drm_kms_helper] drm_client_modeset_commit_atomic+0x228/0x268 [drm] drm_client_modeset_commit_locked+0x60/0x1d0 [drm] drm_client_modeset_commit+0x24/0x40 [drm] drm_fb_helper_restore_fbdev_mode_unlocked+0x54/0xa8 [drm_kms_helper] drm_fb_helper_set_par+0x2c/0x5c [drm_kms_helper] drm_fb_helper_hotplug_event.part.0+0xa0/0xbc [drm_kms_helper] drm_kms_helper_hotplug_event+0x24/0x30 [drm_kms_helper] output_poll_execute+0x1a8/0x1c0 [drm_kms_helper] process_one_work+0x268/0x800 worker_thread+0x30/0x4e0 kthread+0x164/0x190 ret_from_fork+0x14/0x20 The reason for this is that omapdrm calls drm_crtc_vblank_on() while holding event_lock taken with spin_lock_irq(). It is not clear why drm_crtc_vblank_on() and drm_crtc_vblank_get() are called while holding event_lock. I don't see any problem with moving those calls outside the lock, which is what this patch does. Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20200819103021.440288-1-tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/omap_crtc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 6d40914675da..328a4a74f534 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -451,11 +451,12 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc, if (omap_state->manually_updated) return; - spin_lock_irq(&crtc->dev->event_lock); drm_crtc_vblank_on(crtc); + ret = drm_crtc_vblank_get(crtc); WARN_ON(ret != 0); + spin_lock_irq(&crtc->dev->event_lock); omap_crtc_arm_event(crtc); spin_unlock_irq(&crtc->dev->event_lock); } -- cgit v1.2.3 From 460f26d3ee70ec25b3bf8d08e0c79936212d36b6 Mon Sep 17 00:00:00 2001 From: Gurchetan Singh Date: Mon, 15 Jun 2020 16:05:00 -0700 Subject: drm/virtio: Revert "drm/virtio: Call the right shmem helpers" This reverts commit d323bb44e4d23802eb25d13de1f93f2335bd60d0. Fixes a double-free regression: [ 4.357928] drm_gem_shmem_free_object+0xb4/0x100 [ 4.358983] virtio_gpu_dequeue_ctrl_func+0xd9/0x290 [ 4.360343] process_one_work+0x1d2/0x3a0 [ 4.361581] worker_thread+0x45/0x3c0 [ 4.362645] kthread+0xf6/0x130 [ 4.363543] ? process_one_work+0x3a0/0x3a0 [ 4.364770] ? kthread_park+0x80/0x80 [ 4.365799] ret_from_fork+0x35/0x40 [ 4.367103] Modules linked in: [ 4.367958] CR2: 0000000000000018 [ 4.368857] ---[ end trace db84f7a2974d5c79 ]--- [ 4.370118] RIP: 0010:dma_direct_unmap_sg+0x1f/0x60 In addition, virtio has it's own set of dma-ops so there's not an obviously clean way to transition to shmem helpers. Fixes: d323bb44e4d2 ("drm/virtio: Call the right shmem helpers") Signed-off-by: Gurchetan Singh Link: http://patchwork.freedesktop.org/patch/msgid/20200615230500.551-1-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann (cherry picked from commit 51c3b0cc32d2e17581fce5b487ee95bbe9e8270a) --- drivers/gpu/drm/virtio/virtgpu_object.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/virtio/virtgpu_object.c b/drivers/gpu/drm/virtio/virtgpu_object.c index e83651b7747d..842f8b61aa89 100644 --- a/drivers/gpu/drm/virtio/virtgpu_object.c +++ b/drivers/gpu/drm/virtio/virtgpu_object.c @@ -151,7 +151,13 @@ static int virtio_gpu_object_shmem_init(struct virtio_gpu_device *vgdev, if (ret < 0) return -EINVAL; - shmem->pages = drm_gem_shmem_get_pages_sgt(&bo->base.base); + /* + * virtio_gpu uses drm_gem_shmem_get_sg_table instead of + * drm_gem_shmem_get_pages_sgt because virtio has it's own set of + * dma-ops. This is discouraged for other drivers, but should be fine + * since virtio_gpu doesn't support dma-buf import from other devices. + */ + shmem->pages = drm_gem_shmem_get_sg_table(&bo->base.base); if (!shmem->pages) { drm_gem_shmem_unpin(&bo->base.base); return -EINVAL; -- cgit v1.2.3 From d4035d104313cc43b34381b585a7407f069a5132 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Mon, 13 Jul 2020 09:07:08 +0200 Subject: drm/exynos: gem: Fix sparse warning kvaddr element of the exynos_gem object points to a memory buffer, thus it should not have a __iomem annotation. Then, to avoid a warning or casting on assignment to fbi structure, the screen_buffer element of the union should be used instead of the screen_base. Reported-by: kernel test robot Suggested-by: Sam Ravnborg Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sam Ravnborg Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 56a2b47e1af7..5147f5929be7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -92,7 +92,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, offset = fbi->var.xoffset * fb->format->cpp[0]; offset += fbi->var.yoffset * fb->pitches[0]; - fbi->screen_base = exynos_gem->kvaddr + offset; + fbi->screen_buffer = exynos_gem->kvaddr + offset; fbi->screen_size = size; fbi->fix.smem_len = size; diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 7445748288da..74e926abeff0 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -40,7 +40,7 @@ struct exynos_drm_gem { unsigned int flags; unsigned long size; void *cookie; - void __iomem *kvaddr; + void *kvaddr; dma_addr_t dma_addr; unsigned long dma_attrs; struct sg_table *sgt; -- cgit v1.2.3 From ed9ab229fea24cbcab17f484297dc8344afb7ea9 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Sun, 16 Aug 2020 03:32:12 -0400 Subject: drm/amd/display: should check error using DC_OK core_link_read_dpcd returns only DC_OK(1) and DC_ERROR_UNEXPECTED(-1), the caller should check error using DC_OK instead of checking against 0 Signed-off-by: Tong Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') 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 9bc03f26efda..b2be6ad5101d 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 @@ -4409,9 +4409,9 @@ bool dc_link_get_backlight_level_nits(struct dc_link *link, link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_CURRENT_PEAK, dpcd_backlight_get.raw, - sizeof(union dpcd_source_backlight_get))) + sizeof(union dpcd_source_backlight_get)) != DC_OK) return false; *backlight_millinits_avg = @@ -4450,9 +4450,9 @@ bool dc_link_read_default_bl_aux(struct dc_link *link, uint32_t *backlight_milli link->connector_signal != SIGNAL_TYPE_DISPLAY_PORT)) return false; - if (!core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, + if (core_link_read_dpcd(link, DP_SOURCE_BACKLIGHT_LEVEL, (uint8_t *) backlight_millinits, - sizeof(uint32_t))) + sizeof(uint32_t)) != DC_OK) return false; return true; -- cgit v1.2.3 From 69d9f4278d0f9d24607645f10e5ac5c59c77a4ac Mon Sep 17 00:00:00 2001 From: Alexander Monakov Date: Tue, 4 Aug 2020 23:13:13 +0300 Subject: drm/amd/display: use correct scale for actual_brightness Documentation for sysfs backlight level interface requires that values in both 'brightness' and 'actual_brightness' files are interpreted to be in range from 0 to the value given in the 'max_brightness' file. With amdgpu, max_brightness gives 255, and values written by the user into 'brightness' are internally rescaled to a wider range. However, reading from 'actual_brightness' gives the raw register value without inverse rescaling. This causes issues for various userspace tools such as PowerTop and systemd that expect the value to be in the correct range. Introduce a helper to retrieve internal backlight range. Use it to reimplement 'convert_brightness' as 'convert_brightness_from_user' and introduce 'convert_brightness_to_user'. Bug: https://bugzilla.kernel.org/show_bug.cgi?id=203905 Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1242 Cc: Alex Deucher Cc: Nicholas Kazlauskas Reviewed-by: Alex Deucher Signed-off-by: Alexander Monakov Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 81 +++++++++++------------ 1 file changed, 40 insertions(+), 41 deletions(-) (limited to 'drivers/gpu') 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 df9338257ae0..4c8a69283698 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2894,51 +2894,50 @@ static int set_backlight_via_aux(struct dc_link *link, uint32_t brightness) return rc ? 0 : 1; } -static u32 convert_brightness(const struct amdgpu_dm_backlight_caps *caps, - const uint32_t user_brightness) +static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps, + unsigned *min, unsigned *max) { - u32 min, max, conversion_pace; - u32 brightness = user_brightness; - if (!caps) - goto out; + return 0; - if (!caps->aux_support) { - max = caps->max_input_signal; - min = caps->min_input_signal; - /* - * The brightness input is in the range 0-255 - * It needs to be rescaled to be between the - * requested min and max input signal - * It also needs to be scaled up by 0x101 to - * match the DC interface which has a range of - * 0 to 0xffff - */ - conversion_pace = 0x101; - brightness = - user_brightness - * conversion_pace - * (max - min) - / AMDGPU_MAX_BL_LEVEL - + min * conversion_pace; + if (caps->aux_support) { + // Firmware limits are in nits, DC API wants millinits. + *max = 1000 * caps->aux_max_input_signal; + *min = 1000 * caps->aux_min_input_signal; } else { - /* TODO - * We are doing a linear interpolation here, which is OK but - * does not provide the optimal result. We probably want - * something close to the Perceptual Quantizer (PQ) curve. - */ - max = caps->aux_max_input_signal; - min = caps->aux_min_input_signal; - - brightness = (AMDGPU_MAX_BL_LEVEL - user_brightness) * min - + user_brightness * max; - // Multiple the value by 1000 since we use millinits - brightness *= 1000; - brightness = DIV_ROUND_CLOSEST(brightness, AMDGPU_MAX_BL_LEVEL); + // Firmware limits are 8-bit, PWM control is 16-bit. + *max = 0x101 * caps->max_input_signal; + *min = 0x101 * caps->min_input_signal; } + return 1; +} + +static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; -out: - return brightness; + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + // Rescale 0..255 to min..max + return min + DIV_ROUND_CLOSEST((max - min) * brightness, + AMDGPU_MAX_BL_LEVEL); +} + +static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps, + uint32_t brightness) +{ + unsigned min, max; + + if (!get_brightness_range(caps, &min, &max)) + return brightness; + + if (brightness < min) + return 0; + // Rescale min..max to 0..255 + return DIV_ROUND_CLOSEST(AMDGPU_MAX_BL_LEVEL * (brightness - min), + max - min); } static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) @@ -2954,7 +2953,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) link = (struct dc_link *)dm->backlight_link; - brightness = convert_brightness(&caps, bd->props.brightness); + brightness = convert_brightness_from_user(&caps, bd->props.brightness); // Change brightness based on AUX property if (caps.aux_support) return set_backlight_via_aux(link, brightness); @@ -2971,7 +2970,7 @@ static int amdgpu_dm_backlight_get_brightness(struct backlight_device *bd) if (ret == DC_ERROR_UNEXPECTED) return bd->props.brightness; - return ret; + return convert_brightness_to_user(&dm->backlight_caps, ret); } static const struct backlight_ops amdgpu_dm_backlight_ops = { -- cgit v1.2.3 From 168f09cdadbd547c2b202246ef9a8183da725f13 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Wed, 19 Aug 2020 13:37:54 -0400 Subject: drm/amd/display: Reject overlay plane configurations in multi-display scenarios [Why] These aren't stable on some platform configurations when driving multiple displays, especially on higher resolution. In particular the delay in asserting p-state and validating from x86 outweights any power or performance benefit from the hardware composition. Under some configurations this will manifest itself as extreme stutter or unresponsiveness especially when combined with cursor movement. [How] Disable these for now. Exposing overlays to userspace doesn't guarantee that they'll be able to use them in any and all configurations and it's part of the DRM contract to have userspace gracefully handle validation failures when they occur. Valdiation occurs as part of DC and this in particular affects RV, so disable this in dcn10_global_validation. Signed-off-by: Nicholas Kazlauskas Reviewed-by: Hersen Wu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c index 17d5cb422025..8939541ad7af 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c @@ -1213,6 +1213,7 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont bool video_large = false; bool desktop_large = false; bool dcc_disabled = false; + bool mpo_enabled = false; for (i = 0; i < context->stream_count; i++) { if (context->stream_status[i].plane_count == 0) @@ -1221,6 +1222,9 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont if (context->stream_status[i].plane_count > 2) return DC_FAIL_UNSUPPORTED_1; + if (context->stream_status[i].plane_count > 1) + mpo_enabled = true; + for (j = 0; j < context->stream_status[i].plane_count; j++) { struct dc_plane_state *plane = context->stream_status[i].plane_states[j]; @@ -1244,6 +1248,10 @@ static enum dc_status dcn10_validate_global(struct dc *dc, struct dc_state *cont } } + /* Disable MPO in multi-display configurations. */ + if (context->stream_count > 1 && mpo_enabled) + return DC_FAIL_UNSUPPORTED_1; + /* * Workaround: On DCN10 there is UMC issue that causes underflow when * playing 4k video on 4k desktop with video downscaled and single channel -- cgit v1.2.3 From 5896585512e5156482335e902f7c7393b940da51 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Thu, 20 Aug 2020 00:52:41 -0700 Subject: drivers: gpu: amd: Initialize amdgpu_dm_backlight_caps object to 0 in amdgpu_dm_update_backlight_caps In `amdgpu_dm_update_backlight_caps()`, there is a local `amdgpu_dm_backlight_caps` object that is filled in by `amdgpu_acpi_get_backlight_caps()`. However, this object is uninitialized before the call and hence the subsequent check for aux_support can fail since it is not initialized by `amdgpu_acpi_get_backlight_caps()` as well. This change initializes this local `amdgpu_dm_backlight_caps` object to 0. Reviewed-by: Christian König Signed-off-by: Furquan Shaikh Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') 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 4c8a69283698..778edf427b94 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2856,6 +2856,8 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm) #if defined(CONFIG_ACPI) struct amdgpu_dm_backlight_caps caps; + memset(&caps, 0, sizeof(caps)); + if (dm->backlight_caps.caps_valid) return; -- cgit v1.2.3 From f2cdef66dcef44bc26c06a2c070617272b1360a1 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Fri, 21 Aug 2020 11:30:19 +0800 Subject: drm/amd/pm: enable run_btc callback for sienna_cichlid DC BTC support for sienna_cichlid is added, it provides the DC tolerance and aging measurements. Signed-off-by: Jiansong Chen Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 3865dbed5f93..d722bf0c98be 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -95,6 +95,7 @@ static struct cmn2asic_msg_mapping sienna_cichlid_message_map[SMU_MSG_MAX_COUNT] MSG_MAP(TransferTableSmu2Dram, PPSMC_MSG_TransferTableSmu2Dram, 0), MSG_MAP(TransferTableDram2Smu, PPSMC_MSG_TransferTableDram2Smu, 0), MSG_MAP(UseDefaultPPTable, PPSMC_MSG_UseDefaultPPTable, 0), + MSG_MAP(RunDcBtc, PPSMC_MSG_RunDcBtc, 0), MSG_MAP(EnterBaco, PPSMC_MSG_EnterBaco, 0), MSG_MAP(SetSoftMinByFreq, PPSMC_MSG_SetSoftMinByFreq, 0), MSG_MAP(SetSoftMaxByFreq, PPSMC_MSG_SetSoftMaxByFreq, 0), @@ -1732,6 +1733,11 @@ static int sienna_cichlid_get_dpm_ultimate_freq(struct smu_context *smu, return ret; } +static int sienna_cichlid_run_btc(struct smu_context *smu) +{ + return smu_cmn_send_smc_msg(smu, SMU_MSG_RunDcBtc, NULL); +} + static bool sienna_cichlid_is_baco_supported(struct smu_context *smu) { struct amdgpu_device *adev = smu->adev; @@ -2719,6 +2725,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .mode1_reset = smu_v11_0_mode1_reset, .get_dpm_ultimate_freq = sienna_cichlid_get_dpm_ultimate_freq, .set_soft_freq_limited_range = smu_v11_0_set_soft_freq_limited_range, + .run_btc = sienna_cichlid_run_btc, .get_pp_feature_mask = smu_cmn_get_pp_feature_mask, .set_pp_feature_mask = smu_cmn_set_pp_feature_mask, }; -- cgit v1.2.3 From 317951ee922cb561c0da62f6bbc568c96b2ad0d1 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Fri, 21 Aug 2020 16:20:47 +0800 Subject: drm/amd/pm: set VCN pg per instances When deciding whether to set pg for vcn1, instances number is more generic than chip name. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index d722bf0c98be..638760839c15 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -776,7 +776,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerUpVcn, 0x10000, NULL); if (ret) @@ -788,7 +788,7 @@ static int sienna_cichlid_dpm_set_vcn_enable(struct smu_context *smu, bool enabl ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0, NULL); if (ret) return ret; - if (adev->asic_type == CHIP_SIENNA_CICHLID) { + if (adev->vcn.num_vcn_inst > 1) { ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_PowerDownVcn, 0x10000, NULL); if (ret) -- cgit v1.2.3 From b05d71b51078fc428c6b72582126d9d75d3c1f4c Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:05:03 +0800 Subject: drm/amd/pm: correct Vega10 swctf limit setting Correct the Vega10 thermal swctf limit. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1267 Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index 468bdd6f6697..ce9514c881ec 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -363,6 +363,9 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -372,8 +375,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; if (low > high) return -EINVAL; -- cgit v1.2.3 From e0ffd340249699ad27a6c91abdfa3e89f7823941 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:18:58 +0800 Subject: drm/amd/pm: correct Vega12 swctf limit setting Correct the Vega12 thermal swctf limit. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c index c15b9756025d..e755fc0c9886 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c @@ -170,6 +170,8 @@ int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -179,8 +181,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- cgit v1.2.3 From 9b51c4b2ba31396f3894ccc7df8bdf067243e9f5 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:21:30 +0800 Subject: drm/amd/pm: correct Vega20 swctf limit setting Correct the Vega20 thermal swctf limit. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c index 7add2f60f49c..a9bc9d16641a 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c @@ -240,6 +240,8 @@ int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -249,8 +251,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- cgit v1.2.3 From de7a1b0b8753e1b0000084f0e339ffab295d27ef Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Mon, 24 Aug 2020 18:44:09 +0800 Subject: drm/amdgpu/gfx10: refine mgcg setting 1. enable ENABLE_CGTS_LEGACY to fix specviewperf11 random hang. 2. remove obsolete RLC_CGTT_SCLK_OVERRIDE workaround. Signed-off-by: Jiansong Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 65997ffaed45..037a187aa42f 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7263,10 +7263,8 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | - RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK); - - /* only for Vega10 & Raven1 */ - data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK; + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK); if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); -- cgit v1.2.3 From d2ce14fd99e91f3de667e5dba5b9affa3e40e725 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Tue, 11 Aug 2020 17:23:20 -0400 Subject: drm/amd/display: Send DISPLAY_OFF after power down on boot [WHY] update_clocks might not be called on headless adapters. This means DISPLAY_OFF may not be sent in headless cases. [HOW] If hardware is powered down on boot because it is headless (mode set does not happen on that adapter) also send DISPLAY_OFF notification. Signed-off-by: Sung Lee Reviewed-by: Yongqiang Sun Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 10 ++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 +++++++++++++--------- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 2 + 3 files changed, 43 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c664404a75d4..543afa34d87a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -94,6 +94,15 @@ int rn_get_active_display_cnt_wa( return display_count; } +void rn_set_low_power_state(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); + /* update power state */ + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; +} + void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) @@ -516,6 +525,7 @@ static struct clk_mgr_funcs dcn21_funcs = { .init_clocks = rn_init_clocks, .enable_pme_wa = rn_enable_pme_wa, .are_clock_states_equal = rn_are_clock_states_equal, + .set_low_power_state = rn_set_low_power_state, .notify_wm_ranges = rn_notify_wm_ranges, .notify_link_rate_change = rn_notify_link_rate_change, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index a643927e272b..fa643ec5a876 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1450,33 +1450,42 @@ void dcn10_init_hw(struct dc *dc) void dcn10_power_down_on_boot(struct dc *dc) { int i = 0; + struct dc_link *edp_link; - if (dc->config.power_down_display_on_boot) { - struct dc_link *edp_link = get_edp_link(dc); - - if (edp_link && - edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwseq->funcs.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwseq->funcs.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); - } else { - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - - if (link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc) && - dc->hwss.power_down) { - dc->hwss.power_down(dc); - break; - } + if (!dc->config.power_down_display_on_boot) + return; + + edp_link = get_edp_link(dc); + if (edp_link && + edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwseq->funcs.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwseq->funcs.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwss.power_down) { + dc->hwss.power_down(dc); + break; } + } } + + /* + * Call update_clocks with empty context + * to send DISPLAY_OFF + * Otherwise DISPLAY_OFF may not be asserted + */ + if (dc->clk_mgr->funcs->set_low_power_state) + dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); } void dcn10_reset_hw_ctx_wrap( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 5994d2a33c40..947d6106f341 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -230,6 +230,8 @@ struct clk_mgr_funcs { int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr); + void (*set_low_power_state)(struct clk_mgr *clk_mgr); + void (*init_clocks)(struct clk_mgr *clk_mgr); void (*enable_pme_wa) (struct clk_mgr *clk_mgr); -- cgit v1.2.3 From b61f05622ace5b9498ae279cdfd1c9f0c1ce3f75 Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Mon, 10 Aug 2020 16:02:47 -0400 Subject: drm/amd/display: Revert HDCP disable sequence change [Why] Revert HDCP disable sequence change that blanks stream before disabling HDCP. PSP and HW teams are currently investigating the root cause of why HDCP cannot be disabled before stream blank, which is expected to work without issues. Signed-off-by: Jaehyun Chung Reviewed-by: Wenjing Liu Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 117d8aaf2a9b..405452b736e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,10 +3286,10 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } - dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif + dc->hwss.blank_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- cgit v1.2.3 From efbde23a3b0164cef27fd394e7d548f46af5b51d Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Thu, 13 Aug 2020 10:50:21 -0400 Subject: drm/amd/display: Fix passive dongle mistaken as active dongle in EDID emulation [Why] dongle_type is set during dongle connection but for passive dongles, dongle_type is not set. If user starts with an active dongle and then switches to a passive dongle, it will still report as an active dongle. Trying to emulate the wrong connecter type results in display not lighting up. [How] Set dpcd_caps.dongle_type for passive dongles in detect_dp(). Signed-off-by: Samson Tam Reviewed-by: Joshua Aberback Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 405452b736e1..437d1a7a16fe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -763,6 +763,7 @@ static bool detect_dp(struct dc_link *link, sink_caps->signal = dp_passive_dongle_detection(link->ddc, sink_caps, audio_support); + link->dpcd_caps.dongle_type = sink_caps->dongle_type; } return true; -- cgit v1.2.3 From cba4b52e431e5de3d8012281cfe194f1c39a9052 Mon Sep 17 00:00:00 2001 From: Brandon Syu Date: Wed, 10 Jun 2020 16:44:33 +0800 Subject: drm/amd/display: Keep current gain when ABM disable immediately [Why] When system enters s3/s0i3, backlight PWM would set user level. [How] ABM disable function add keep current gain to avoid it. Signed-off-by: Brandon Syu Reviewed-by: Josip Pavic Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 633442bc7ef2..d9888f316da6 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -233,7 +233,7 @@ struct dc_stream_state { union stream_update_flags update_flags; }; -#define ABM_LEVEL_IMMEDIATE_DISABLE 0xFFFFFFFF +#define ABM_LEVEL_IMMEDIATE_DISABLE 255 struct dc_stream_update { struct dc_stream_state *stream; -- cgit v1.2.3 From 14e4f3bd818a216dc85ab5ec9a33c49357a6369b Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 28 Jul 2020 12:44:59 +0800 Subject: drm/amdgpu: add asd fw check before loading asd asd is not ready for some ASICs in early stage, and psp->asd_fw is more generic than ASIC name in the check. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Reviewed-by: Jiansong Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index 7fe564275457..d8c6520ff74a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -522,8 +522,7 @@ static int psp_asd_load(struct psp_context *psp) * add workaround to bypass it for sriov now. * TODO: add version check to make it common */ - if (amdgpu_sriov_vf(psp->adev) || - (psp->adev->asic_type == CHIP_NAVY_FLOUNDER)) + if (amdgpu_sriov_vf(psp->adev) || !psp->asd_fw) return 0; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); -- cgit v1.2.3 From 28e628645333b7e581c4a7b04d958e4804ea10fe Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Aug 2020 10:35:11 +0800 Subject: drm/amd/pm: correct the thermal alert temperature limit settings Do the maths in celsius degree. This can fix the issues caused by the changes below: drm/amd/pm: correct Vega20 swctf limit setting drm/amd/pm: correct Vega12 swctf limit setting drm/amd/pm: correct Vega10 swctf limit setting Signed-off-by: Evan Quan Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c | 15 +++++++-------- 3 files changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index ce9514c881ec..d572ba4ec9b1 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -367,14 +367,13 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, (struct phm_ppt_v2_information *)(hwmgr->pptable); struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > tdp_table->usSoftwareShutdownTemp) high = tdp_table->usSoftwareShutdownTemp; @@ -385,8 +384,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c index e755fc0c9886..7ace439dcde7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_thermal.c @@ -173,14 +173,13 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -191,8 +190,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c index a9bc9d16641a..364162ddaa9c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c @@ -243,14 +243,13 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -261,8 +260,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); -- cgit v1.2.3 From 75947544c8abd380064c817e2a2f043914d49e55 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Tue, 25 Aug 2020 15:39:57 +0800 Subject: drm/amdgpu: use MODE1 reset for navy_flounder by default Switch default gpu reset method to MODE1 for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index da8024c2826e..ca11253e787c 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -364,6 +364,7 @@ nv_asic_reset_method(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: return AMD_RESET_METHOD_MODE1; default: if (smu_baco_is_support(smu)) -- cgit v1.2.3 From e2bf3723db563457c0abe4eaeedac25bbbbd1d76 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 14 Aug 2020 11:49:13 -0400 Subject: drm/amd/powerplay: Fix hardmins not being sent to SMU for RV [Why] DC uses these to raise the voltage as needed for higher dispclk/dppclk and to ensure that we have enough bandwidth to drive the displays. There's a bug preventing these from actuially sending messages since it's checking the actual clock (which is 0) instead of the incoming clock (which shouldn't be 0) when deciding to send the hardmin. [How] Check the clocks != 0 instead of the actual clocks. Fixes: 9ed9203c3ee7 ("drm/amd/powerplay: rv dal-pplib interface refactor powerplay part") Signed-off-by: Nicholas Kazlauskas Reviewed-by: Alex Deucher Reviewed-by: Evan Quan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c index c9cfe90a2947..9ee8cf8267c8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c @@ -204,8 +204,7 @@ static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clo { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->need_min_deep_sleep_dcefclk && - smu10_data->deep_sleep_dcefclk != clock) { + if (clock && smu10_data->deep_sleep_dcefclk != clock) { smu10_data->deep_sleep_dcefclk = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, @@ -219,8 +218,7 @@ static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t c { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->dcf_actual_hard_min_freq && - smu10_data->dcf_actual_hard_min_freq != clock) { + if (clock && smu10_data->dcf_actual_hard_min_freq != clock) { smu10_data->dcf_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinDcefclkByFreq, @@ -234,8 +232,7 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t cloc { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->f_actual_hard_min_freq && - smu10_data->f_actual_hard_min_freq != clock) { + if (clock && smu10_data->f_actual_hard_min_freq != clock) { smu10_data->f_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinFclkByFreq, -- cgit v1.2.3 From b5b97cab55eb71daba3283c8b1d2cce456d511a1 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Aug 2020 11:43:45 -0400 Subject: drm/amdgpu: Fix buffer overflow in INFO ioctl The values for "se_num" and "sh_num" come from the user in the ioctl. They can be in the 0-255 range but if they're more than AMDGPU_GFX_MAX_SE (4) or AMDGPU_GFX_MAX_SH_PER_SE (2) then it results in an out of bounds read. Reported-by: Dan Carpenter Acked-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 0047da06041f..a1706b9f6467 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -678,8 +678,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file * in the bitfields */ if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) se_num = 0xffffffff; + else if (se_num >= AMDGPU_GFX_MAX_SE) + return -EINVAL; if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) sh_num = 0xffffffff; + else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) + return -EINVAL; if (info->read_mmr_reg.count > 128) return -EINVAL; -- cgit v1.2.3 From ef67d792a2fc578319399f605fbec2f99ecc06ea Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 18 Aug 2020 11:19:42 +0800 Subject: drm/amd/display: Retry AUX write when fail occurs [Why] In dm_dp_aux_transfer() now, we forget to handle AUX_WR fail cases. We suppose every write wil get done successfully and hence some AUX commands might not sent out indeed. [How] Check if AUX_WR success. If not, retry it. Signed-off-by: Wayne Lin Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index e85b58f0f416..336aaa09be46 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -67,7 +67,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, &operation_result); - if (payload.write) + if (payload.write && result >= 0) result = msg->size; if (result < 0) -- cgit v1.2.3 From 82dff839c9b4adad6980cc9aa6ea18c16db49013 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Wed, 26 Aug 2020 14:11:52 +0800 Subject: drm/amdgpu: disable runtime pm for navy_flounder Disable runtime pm for navy_flounder temporarily. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index a1706b9f6467..414548064648 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -179,6 +179,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) case CHIP_VEGA20: case CHIP_ARCTURUS: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: /* enable runpm if runpm=1 */ if (amdgpu_runtime_pm > 0) adev->runpm = true; -- cgit v1.2.3 From b67a468a4ccef593cd8df6a02ba3d167b77f0c81 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Wed, 26 Aug 2020 21:24:58 +0800 Subject: drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init When amdgpu_display_modeset_create_props() fails, state and state->context should be freed to prevent memleak. It's the same when amdgpu_dm_audio_init() fails. Signed-off-by: Dinghao Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 778edf427b94..b51c527a3f0d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2834,12 +2834,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) &dm_atomic_state_funcs); r = amdgpu_display_modeset_create_props(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } r = amdgpu_dm_audio_init(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } return 0; } -- cgit v1.2.3 From 8aba21b75136c39c4bf63345d699d97dc477ce0e Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Fri, 14 Aug 2020 20:41:55 -0400 Subject: drm/amdgpu: Embed drm_device into amdgpu_device (v3) a) Embed struct drm_device into struct amdgpu_device. b) Modify the inline-f drm_to_adev() accordingly. c) Modify the inline-f adev_to_drm() accordingly. d) Eliminate the use of drm_device.dev_private, in amdgpu. e) Switch from using drm_dev_alloc() to drm_dev_init(). f) Add a DRM driver release function, which frees the container amdgpu_device after all krefs on the contained drm_device have been released. v2: Split out adding adev_to_drm() into its own patch (previous commit), making this patch more succinct and clear. More detailed commit description. v3: squash in fix to call drmm_add_final_kfree() to avoid a warning. Signed-off-by: Luben Tuikov Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 10 +++---- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 15 ++++------ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 45 ++++++++++++++++++++---------- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 ++++---------- 4 files changed, 45 insertions(+), 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 9d93b3170cd6..2509b1e302c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -722,8 +722,8 @@ struct amd_powerplay { #define AMDGPU_MAX_DF_PERFMONS 4 struct amdgpu_device { struct device *dev; - struct drm_device *ddev; struct pci_dev *pdev; + struct drm_device ddev; #ifdef CONFIG_DRM_AMD_ACP struct amdgpu_acp acp; @@ -988,12 +988,12 @@ struct amdgpu_device { static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) { - return ddev->dev_private; + return container_of(ddev, struct amdgpu_device, ddev); } static inline struct drm_device *adev_to_drm(struct amdgpu_device *adev) { - return adev->ddev; + return &adev->ddev; } static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) @@ -1002,8 +1002,6 @@ static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev) } int amdgpu_device_init(struct amdgpu_device *adev, - struct drm_device *ddev, - struct pci_dev *pdev, uint32_t flags); void amdgpu_device_fini(struct amdgpu_device *adev); int amdgpu_gpu_wait_for_idle(struct amdgpu_device *adev); @@ -1194,7 +1192,7 @@ static inline void *amdgpu_atpx_get_dhandle(void) { return NULL; } extern const struct drm_ioctl_desc amdgpu_ioctls_kms[]; extern const int amdgpu_max_kms_ioctl; -int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags); +int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags); void amdgpu_driver_unload_kms(struct drm_device *dev); void amdgpu_driver_lastclose_kms(struct drm_device *dev); int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index afe8cb37d5b4..64d6e58bcb0a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1216,7 +1216,8 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev) * Callback for the switcheroo driver. Suspends or resumes the * the asics before or after it is powered up using ACPI methods. */ -static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state) +static void amdgpu_switcheroo_set_state(struct pci_dev *pdev, + enum vga_switcheroo_state state) { struct drm_device *dev = pci_get_drvdata(pdev); int r; @@ -2978,8 +2979,6 @@ static const struct attribute *amdgpu_dev_attributes[] = { * amdgpu_device_init - initialize the driver * * @adev: amdgpu_device pointer - * @ddev: drm dev pointer - * @pdev: pci dev pointer * @flags: driver flags * * Initializes the driver info and hw (all asics). @@ -2987,18 +2986,15 @@ static const struct attribute *amdgpu_dev_attributes[] = { * Called at driver startup. */ int amdgpu_device_init(struct amdgpu_device *adev, - struct drm_device *ddev, - struct pci_dev *pdev, uint32_t flags) { + struct drm_device *ddev = adev_to_drm(adev); + struct pci_dev *pdev = adev->pdev; int r, i; bool boco = false; u32 max_MBps; adev->shutdown = false; - adev->dev = &pdev->dev; - adev->ddev = ddev; - adev->pdev = pdev; adev->flags = flags; if (amdgpu_force_asic_type >= 0 && amdgpu_force_asic_type < CHIP_LAST) @@ -3453,9 +3449,8 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) struct drm_connector_list_iter iter; int r; - if (dev == NULL || dev->dev_private == NULL) { + if (!dev) return -ENODEV; - } adev = drm_to_adev(dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 651b51ab14cb..ed29f0ce007c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "amdgpu_drv.h" #include @@ -1082,7 +1083,7 @@ static struct drm_driver kms_driver; static int amdgpu_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct drm_device *dev; + struct drm_device *ddev; struct amdgpu_device *adev; unsigned long flags = ent->driver_data; int ret, retry = 0; @@ -1138,36 +1139,44 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, if (ret) return ret; - dev = drm_dev_alloc(&kms_driver, &pdev->dev); - if (IS_ERR(dev)) - return PTR_ERR(dev); + adev = kzalloc(sizeof(*adev), GFP_KERNEL); + if (!adev) + return -ENOMEM; + + adev->dev = &pdev->dev; + adev->pdev = pdev; + ddev = adev_to_drm(adev); + ret = drm_dev_init(ddev, &kms_driver, &pdev->dev); + if (ret) + goto err_free; + + drmm_add_final_kfree(ddev, ddev); if (!supports_atomic) - dev->driver_features &= ~DRIVER_ATOMIC; + ddev->driver_features &= ~DRIVER_ATOMIC; ret = pci_enable_device(pdev); if (ret) goto err_free; - dev->pdev = pdev; - - pci_set_drvdata(pdev, dev); + ddev->pdev = pdev; + pci_set_drvdata(pdev, ddev); - ret = amdgpu_driver_load_kms(dev, ent->driver_data); + ret = amdgpu_driver_load_kms(adev, ent->driver_data); if (ret) goto err_pci; retry_init: - ret = drm_dev_register(dev, ent->driver_data); + ret = drm_dev_register(ddev, ent->driver_data); if (ret == -EAGAIN && ++retry <= 3) { DRM_INFO("retry init %d\n", retry); /* Don't request EX mode too frequently which is attacking */ msleep(5000); goto retry_init; - } else if (ret) + } else if (ret) { goto err_pci; + } - adev = drm_to_adev(dev); ret = amdgpu_debugfs_init(adev); if (ret) DRM_ERROR("Creating debugfs files failed (%d).\n", ret); @@ -1177,7 +1186,7 @@ retry_init: err_pci: pci_disable_device(pdev); err_free: - drm_dev_put(dev); + drm_dev_put(ddev); return ret; } @@ -1197,6 +1206,13 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_dev_put(dev); } +static void amdgpu_driver_release(struct drm_device *ddev) +{ + struct amdgpu_device *adev = drm_to_adev(ddev); + + kfree(adev); +} + static void amdgpu_pci_shutdown(struct pci_dev *pdev) { @@ -1491,6 +1507,7 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, + .release = amdgpu_driver_release, .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, .gem_free_object_unlocked = amdgpu_gem_object_free, @@ -1525,8 +1542,6 @@ static struct pci_driver amdgpu_kms_pci_driver = { .driver.pm = &amdgpu_pm_ops, }; - - static int __init amdgpu_init(void) { int r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c2a697d3f830..d125c4b2af53 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -86,7 +86,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) amdgpu_unregister_gpu_instance(adev); if (adev->rmmio == NULL) - goto done_free; + return; if (adev->runpm) { pm_runtime_get_sync(dev->dev); @@ -94,12 +94,7 @@ void amdgpu_driver_unload_kms(struct drm_device *dev) } amdgpu_acpi_fini(adev); - amdgpu_device_fini(adev); - -done_free: - kfree(adev); - dev->dev_private = NULL; } void amdgpu_register_gpu_instance(struct amdgpu_device *adev) @@ -130,22 +125,18 @@ void amdgpu_register_gpu_instance(struct amdgpu_device *adev) /** * amdgpu_driver_load_kms - Main load function for KMS. * - * @dev: drm dev pointer + * @adev: pointer to struct amdgpu_device * @flags: device flags * * This is the main load function for KMS (all asics). * Returns 0 on success, error on failure. */ -int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) +int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) { - struct amdgpu_device *adev; + struct drm_device *dev; int r, acpi_status; - adev = kzalloc(sizeof(struct amdgpu_device), GFP_KERNEL); - if (adev == NULL) { - return -ENOMEM; - } - dev->dev_private = (void *)adev; + dev = adev_to_drm(adev); if (amdgpu_has_atpx() && (amdgpu_is_atpx_hybrid() || @@ -160,7 +151,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) * properly initialize the GPU MC controller and permit * VRAM allocation */ - r = amdgpu_device_init(adev, dev, dev->pdev, flags); + r = amdgpu_device_init(adev, flags); if (r) { dev_err(&dev->pdev->dev, "Fatal error during GPU init\n"); goto out; -- cgit v1.2.3 From 7323923260cd6f72c3b38c4da3fcc7909df48ac0 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:05:03 +0800 Subject: drm/amd/pm: correct Vega10 swctf limit setting Correct the Vega10 thermal swctf limit. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1267 Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index 468bdd6f6697..ce9514c881ec 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -363,6 +363,9 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v2_information *pp_table_info = + (struct phm_ppt_v2_information *)(hwmgr->pptable); + struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -372,8 +375,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; if (low > high) return -EINVAL; -- cgit v1.2.3 From b23f9f60424732ce517cc6f02d7c34cf2f25ac50 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:18:58 +0800 Subject: drm/amd/pm: correct Vega12 swctf limit setting Correct the Vega12 thermal swctf limit. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index c15b9756025d..e755fc0c9886 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -170,6 +170,8 @@ int vega12_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -179,8 +181,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- cgit v1.2.3 From bfcc0c162a6ad3c8025fea0e966b2a09add80b8e Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Fri, 21 Aug 2020 12:21:30 +0800 Subject: drm/amd/pm: correct Vega20 swctf limit setting Correct the Vega20 thermal swctf limit. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index 7add2f60f49c..a9bc9d16641a 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -240,6 +240,8 @@ int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range) { + struct phm_ppt_v3_information *pptable_information = + (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; @@ -249,8 +251,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, if (low < range->min) low = range->min; - if (high > range->max) - high = range->max; + if (high > pptable_information->us_software_shutdown_temp) + high = pptable_information->us_software_shutdown_temp; if (low > high) return -EINVAL; -- cgit v1.2.3 From 6127896f4a272578a62d1b439e86e64721296d65 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Tue, 18 Aug 2020 14:54:23 +0800 Subject: drm/amdkfd: implement the dGPU fallback path for apu (v6) We still have a few iommu issues which need to address, so force raven as "dgpu" path for the moment. This is to add the fallback path to bypass IOMMU if IOMMU v2 is disabled or ACPI CRAT table not correct. v2: Use ignore_crat parameter to decide whether it will go with IOMMUv2. v3: Align with existed thunk, don't change the way of raven, only renoir will use "dgpu" path by default. v4: don't update global ignore_crat in the driver, and revise fallback function if CRAT is broken. v5: refine acpi crat good but no iommu support case, and rename the title. v6: fix the issue of dGPU initialized firstly, just modify the report value in the node_show(). Signed-off-by: Huang Rui Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 5 +++- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_crat.c | 18 +++++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 5 +++- .../drm/amd/amdkfd/kfd_device_queue_manager_v9.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c | 4 +-- drivers/gpu/drm/amd/amdkfd/kfd_iommu.c | 10 ++++---- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 4 +++ drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 29 +++++++++++++++++++--- 9 files changed, 64 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index ed29f0ce007c..dfc1a9721867 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -680,11 +680,14 @@ MODULE_PARM_DESC(debug_largebar, * Ignore CRAT table during KFD initialization. By default, KFD uses the ACPI CRAT * table to get information about AMD APUs. This option can serve as a workaround on * systems with a broken CRAT table. + * + * Default is auto (according to asic type, iommu_v2, and crat table, to decide + * whehter use CRAT) */ int ignore_crat; module_param(ignore_crat, int, 0444); MODULE_PARM_DESC(ignore_crat, - "Ignore CRAT table during KFD initialization (0 = use CRAT (default), 1 = ignore CRAT)"); + "Ignore CRAT table during KFD initialization (0 = auto (default), 1 = ignore CRAT)"); /** * DOC: halt_if_hws_hang (int) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index e9b96ad3d9a5..b7b16adb0615 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1254,7 +1254,7 @@ bool kfd_dev_is_large_bar(struct kfd_dev *dev) return true; } - if (dev->device_info->needs_iommu_device) + if (dev->use_iommu_v2) return false; amdgpu_amdkfd_get_local_mem_info(dev->kgd, &mem_info); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index 6a250f8fcfb8..3fac06b281ce 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -742,6 +742,22 @@ static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev, return 0; } +static bool kfd_ignore_crat(void) +{ + bool ret; + + if (ignore_crat) + return true; + +#ifndef KFD_SUPPORT_IOMMU_V2 + ret = true; +#else + ret = false; +#endif + + return ret; +} + /* * kfd_create_crat_image_acpi - Allocates memory for CRAT image and * copies CRAT from ACPI (if available). @@ -776,7 +792,7 @@ int kfd_create_crat_image_acpi(void **crat_image, size_t *size) return -EINVAL; } - if (ignore_crat) { + if (kfd_ignore_crat()) { pr_info("CRAT table disabled by module option\n"); return -ENODATA; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index d5e790f046b4..b15b620e731b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -116,6 +116,7 @@ static const struct kfd_device_info carrizo_device_info = { .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, }; +#endif static const struct kfd_device_info raven_device_info = { .asic_family = CHIP_RAVEN, @@ -134,7 +135,6 @@ static const struct kfd_device_info raven_device_info = { .num_xgmi_sdma_engines = 0, .num_sdma_queues_per_engine = 2, }; -#endif static const struct kfd_device_info hawaii_device_info = { .asic_family = CHIP_HAWAII, @@ -738,6 +738,9 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto gws_error; } + /* If CRAT is broken, won't set iommu enabled */ + kfd_double_confirm_iommu_support(kfd); + if (kfd_iommu_device_init(kfd)) { dev_err(kfd_device, "Error initializing iommuv2\n"); goto device_iommu_error; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c index 95a82ac455f2..309f63a0b34a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_v9.c @@ -62,7 +62,7 @@ static int update_qpd_v9(struct device_queue_manager *dqm, SH_MEM_ALIGNMENT_MODE_UNALIGNED << SH_MEM_CONFIG__ALIGNMENT_MODE__SHIFT; if (amdgpu_noretry && - !dqm->dev->device_info->needs_iommu_device) + !dqm->dev->use_iommu_v2) qpd->sh_mem_config |= 1 << SH_MEM_CONFIG__RETRY_DISABLE__SHIFT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c index c1166c40ac15..3c22909470f2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_flat_memory.c @@ -321,7 +321,7 @@ static void kfd_init_apertures_vi(struct kfd_process_device *pdd, uint8_t id) pdd->lds_base = MAKE_LDS_APP_BASE_VI(); pdd->lds_limit = MAKE_LDS_APP_LIMIT(pdd->lds_base); - if (!pdd->dev->device_info->needs_iommu_device) { + if (!pdd->dev->use_iommu_v2) { /* dGPUs: SVM aperture starting at 0 * with small reserved space for kernel. * Set them to CANONICAL addresses. @@ -425,7 +425,7 @@ int kfd_init_apertures(struct kfd_process *process) return -EINVAL; } - if (!dev->device_info->needs_iommu_device) { + if (!dev->use_iommu_v2) { /* dGPUs: the reserved space for kernel * before SVM */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c index 7c8786b9eb0a..5a64915abaf7 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c @@ -41,7 +41,7 @@ int kfd_iommu_check_device(struct kfd_dev *kfd) struct amd_iommu_device_info iommu_info; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return -ENODEV; iommu_info.flags = 0; @@ -63,7 +63,7 @@ int kfd_iommu_device_init(struct kfd_dev *kfd) unsigned int pasid_limit; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return 0; iommu_info.flags = 0; @@ -109,7 +109,7 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd) struct kfd_process *p = pdd->process; int err; - if (!dev->device_info->needs_iommu_device || pdd->bound == PDD_BOUND) + if (!dev->use_iommu_v2 || pdd->bound == PDD_BOUND) return 0; if (unlikely(pdd->bound == PDD_BOUND_SUSPENDED)) { @@ -284,7 +284,7 @@ static void kfd_unbind_processes_from_device(struct kfd_dev *kfd) */ void kfd_iommu_suspend(struct kfd_dev *kfd) { - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return; kfd_unbind_processes_from_device(kfd); @@ -304,7 +304,7 @@ int kfd_iommu_resume(struct kfd_dev *kfd) unsigned int pasid_limit; int err; - if (!kfd->device_info->needs_iommu_device) + if (!kfd->use_iommu_v2) return 0; pasid_limit = kfd_get_pasid_limit(); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 6727e9de5b8b..f14beb93acb4 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -297,6 +297,9 @@ struct kfd_dev { bool pci_atomic_requested; + /* Use IOMMU v2 flag */ + bool use_iommu_v2; + /* SRAM ECC flag */ atomic_t sram_ecc_flag; @@ -892,6 +895,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev); struct kfd_dev *kfd_device_by_kgd(const struct kgd_dev *kgd); int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev); int kfd_numa_node_to_apic_id(int numa_node_id); +void kfd_double_confirm_iommu_support(struct kfd_dev *gpu); /* Interrupts */ int kfd_interrupt_init(struct kfd_dev *dev); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index f185f6cbc05c..5e8eb783d2d5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -446,7 +446,7 @@ static ssize_t node_show(struct kobject *kobj, struct attribute *attr, sysfs_show_32bit_prop(buffer, offs, "cpu_cores_count", dev->node_props.cpu_cores_count); sysfs_show_32bit_prop(buffer, offs, "simd_count", - dev->node_props.simd_count); + dev->gpu ? dev->node_props.simd_count : 0); sysfs_show_32bit_prop(buffer, offs, "mem_banks_count", dev->node_props.mem_banks_count); sysfs_show_32bit_prop(buffer, offs, "caches_count", @@ -1139,7 +1139,7 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu) /* Discrete GPUs need their own topology device list * entries. Don't assign them to CPU/APU nodes. */ - if (!gpu->device_info->needs_iommu_device && + if (!gpu->use_iommu_v2 && dev->node_props.cpu_cores_count) continue; @@ -1388,7 +1388,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) * Overwrite ATS capability according to needs_iommu_device to fix * potential missing corresponding bit in CRAT of BIOS. */ - if (dev->gpu->device_info->needs_iommu_device) + if (dev->gpu->use_iommu_v2) dev->node_props.capability |= HSA_CAP_ATS_PRESENT; else dev->node_props.capability &= ~HSA_CAP_ATS_PRESENT; @@ -1515,6 +1515,29 @@ int kfd_numa_node_to_apic_id(int numa_node_id) return kfd_cpumask_to_apic_id(cpumask_of_node(numa_node_id)); } +void kfd_double_confirm_iommu_support(struct kfd_dev *gpu) +{ + struct kfd_topology_device *dev; + + gpu->use_iommu_v2 = false; + + if (!gpu->device_info->needs_iommu_device) + return; + + down_read(&topology_lock); + + /* Only use IOMMUv2 if there is an APU topology node with no GPU + * assigned yet. This GPU will be assigned to it. + */ + list_for_each_entry(dev, &topology_device_list, list) + if (dev->node_props.cpu_cores_count && + dev->node_props.simd_count && + !dev->gpu) + gpu->use_iommu_v2 = true; + + up_read(&topology_lock); +} + #if defined(CONFIG_DEBUG_FS) int kfd_debugfs_hqds_by_device(struct seq_file *m, void *data) -- cgit v1.2.3 From d3bbba79eb83e8356cd3ac7b250fdd0cc4f85c01 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Mon, 24 Aug 2020 18:44:09 +0800 Subject: drm/amdgpu/gfx10: refine mgcg setting 1. enable ENABLE_CGTS_LEGACY to fix specviewperf11 random hang. 2. remove obsolete RLC_CGTT_SCLK_OVERRIDE workaround. Signed-off-by: Jiansong Chen Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index d851fe80eaf4..2db195ec8d0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7285,10 +7285,8 @@ static void gfx_v10_0_update_medium_grain_clock_gating(struct amdgpu_device *ade def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE); data &= ~(RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK | RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK | - RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK); - - /* only for Vega10 & Raven1 */ - data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK; + RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK | + RLC_CGTT_MGCG_OVERRIDE__ENABLE_CGTS_LEGACY_MASK); if (def != data) WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data); -- cgit v1.2.3 From 387f3a30cc895abcdad0791fa6c6f3c1f1a69c83 Mon Sep 17 00:00:00 2001 From: Sung Lee Date: Tue, 11 Aug 2020 17:23:20 -0400 Subject: drm/amd/display: Send DISPLAY_OFF after power down on boot [WHY] update_clocks might not be called on headless adapters. This means DISPLAY_OFF may not be sent in headless cases. [HOW] If hardware is powered down on boot because it is headless (mode set does not happen on that adapter) also send DISPLAY_OFF notification. Signed-off-by: Sung Lee Reviewed-by: Yongqiang Sun Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 10 ++++ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 53 +++++++++++++--------- drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h | 2 + 3 files changed, 43 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c index c664404a75d4..543afa34d87a 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c @@ -94,6 +94,15 @@ int rn_get_active_display_cnt_wa( return display_count; } +void rn_set_low_power_state(struct clk_mgr *clk_mgr_base) +{ + struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); + + rn_vbios_smu_set_dcn_low_power_state(clk_mgr, DCN_PWR_STATE_LOW_POWER); + /* update power state */ + clk_mgr_base->clks.pwr_state = DCN_PWR_STATE_LOW_POWER; +} + void rn_update_clocks(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) @@ -516,6 +525,7 @@ static struct clk_mgr_funcs dcn21_funcs = { .init_clocks = rn_init_clocks, .enable_pme_wa = rn_enable_pme_wa, .are_clock_states_equal = rn_are_clock_states_equal, + .set_low_power_state = rn_set_low_power_state, .notify_wm_ranges = rn_notify_wm_ranges, .notify_link_rate_change = rn_notify_link_rate_change, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 95e9d05f884b..8ca94f506195 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -1450,33 +1450,42 @@ void dcn10_init_hw(struct dc *dc) void dcn10_power_down_on_boot(struct dc *dc) { int i = 0; + struct dc_link *edp_link; - if (dc->config.power_down_display_on_boot) { - struct dc_link *edp_link = get_edp_link(dc); - - if (edp_link && - edp_link->link_enc->funcs->is_dig_enabled && - edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && - dc->hwseq->funcs.edp_backlight_control && - dc->hwss.power_down && - dc->hwss.edp_power_control) { - dc->hwseq->funcs.edp_backlight_control(edp_link, false); - dc->hwss.power_down(dc); - dc->hwss.edp_power_control(edp_link, false); - } else { - for (i = 0; i < dc->link_count; i++) { - struct dc_link *link = dc->links[i]; - - if (link->link_enc->funcs->is_dig_enabled && - link->link_enc->funcs->is_dig_enabled(link->link_enc) && - dc->hwss.power_down) { - dc->hwss.power_down(dc); - break; - } + if (!dc->config.power_down_display_on_boot) + return; + + edp_link = get_edp_link(dc); + if (edp_link && + edp_link->link_enc->funcs->is_dig_enabled && + edp_link->link_enc->funcs->is_dig_enabled(edp_link->link_enc) && + dc->hwseq->funcs.edp_backlight_control && + dc->hwss.power_down && + dc->hwss.edp_power_control) { + dc->hwseq->funcs.edp_backlight_control(edp_link, false); + dc->hwss.power_down(dc); + dc->hwss.edp_power_control(edp_link, false); + } else { + for (i = 0; i < dc->link_count; i++) { + struct dc_link *link = dc->links[i]; + if (link->link_enc->funcs->is_dig_enabled && + link->link_enc->funcs->is_dig_enabled(link->link_enc) && + dc->hwss.power_down) { + dc->hwss.power_down(dc); + break; } + } } + + /* + * Call update_clocks with empty context + * to send DISPLAY_OFF + * Otherwise DISPLAY_OFF may not be asserted + */ + if (dc->clk_mgr->funcs->set_low_power_state) + dc->clk_mgr->funcs->set_low_power_state(dc->clk_mgr); } void dcn10_reset_hw_ctx_wrap( diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h index 5994d2a33c40..947d6106f341 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h @@ -230,6 +230,8 @@ struct clk_mgr_funcs { int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr); + void (*set_low_power_state)(struct clk_mgr *clk_mgr); + void (*init_clocks)(struct clk_mgr *clk_mgr); void (*enable_pme_wa) (struct clk_mgr *clk_mgr); -- cgit v1.2.3 From f8c000a59fd7ec86e20d17cbc22bb90e00ca1f23 Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Mon, 10 Aug 2020 10:19:04 -0400 Subject: drm/amd/display: 3.2.99 Signed-off-by: Aric Cyr Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index f3ac9e3df760..1d9c8e09c08b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -42,7 +42,7 @@ #include "inc/hw/dmcu.h" #include "dml/display_mode_lib.h" -#define DC_VER "3.2.98" +#define DC_VER "3.2.99" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- cgit v1.2.3 From 8e1f47e6bb44d148ca53cfd557f5aa1430fe6a47 Mon Sep 17 00:00:00 2001 From: Chris Park Date: Mon, 10 Aug 2020 14:20:16 -0400 Subject: drm/amd/display: Call DMUB for eDP power control [Why] If DMUB is used, LVTMA VBIOS call can be used to control eDP instead of tranditional transmitter control. Interface is agreed with VBIOS for eDP to use this new path to program LVTMA registers. [How] Expose DAL interface to send DMUB command for LVTMA control that VBIOS currently uses. Signed-off-by: Chris Park Reviewed-by: Nicholas Kazlauskas Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/bios/command_table2.c | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c index a91d7be5d86e..25bdf1c38e0a 100644 --- a/drivers/gpu/drm/amd/display/dc/bios/command_table2.c +++ b/drivers/gpu/drm/amd/display/dc/bios/command_table2.c @@ -920,11 +920,39 @@ static void init_enable_lvtma_control(struct bios_parser *bp) } +static void enable_lvtma_control_dmcub( + struct dc_dmub_srv *dmcub, + uint8_t uc_pwr_on) +{ + + union dmub_rb_cmd cmd; + + memset(&cmd, 0, sizeof(cmd)); + + cmd.cmd_common.header.type = DMUB_CMD__VBIOS; + cmd.cmd_common.header.sub_type = + DMUB_CMD__VBIOS_LVTMA_CONTROL; + cmd.cmd_common.cmd_buffer[0] = + uc_pwr_on; + + dc_dmub_srv_cmd_queue(dmcub, &cmd); + dc_dmub_srv_cmd_execute(dmcub); + dc_dmub_srv_wait_idle(dmcub); + +} + static enum bp_result enable_lvtma_control( struct bios_parser *bp, uint8_t uc_pwr_on) { enum bp_result result = BP_RESULT_FAILURE; + + if (bp->base.ctx->dc->ctx->dmub_srv && + bp->base.ctx->dc->debug.dmub_command_table) { + enable_lvtma_control_dmcub(bp->base.ctx->dmub_srv, + uc_pwr_on); + return BP_RESULT_OK; + } return result; } -- cgit v1.2.3 From 75f77aafe281c5d971ca876a025093ee62c8a2a8 Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Wed, 15 Jul 2020 16:45:09 +0800 Subject: drm/amd/display: Send H14b-VSIF specified in HDMI [Why] Current function excludes the logic to generate H14b-VSIF. Now it constructs HF-VSIF only and causes HDMI compliace test fail. [How] According to HDMI spec, source devices shall utilize the H14b-VSIF whenever the signaling capabilities of the H14b-VSIF allow this. Here keep the logic for HF-VSIF and add H14b-VSIF construction part. Signed-off-by: Wayne Lin Reviewed-by: Roman Li Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- .../gpu/drm/amd/display/modules/inc/mod_info_packet.h | 2 +- .../drm/amd/display/modules/info_packet/info_packet.c | 16 ++-------------- 3 files changed, 5 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') 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 ec6710f6c873..785f21ea35df 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4685,7 +4685,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, update_stream_signal(stream, sink); if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) - mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket, false, false); + mod_build_hf_vsif_infopacket(stream, &stream->vsp_infopacket); + if (stream->link->psr_settings.psr_feature_enabled) { // // should decide stream support vsc sdp colorimetry capability diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h index 13c57ff2abdc..1ab813b4fd14 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h @@ -37,6 +37,6 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, struct dc_info_packet *info_packet); void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue); + struct dc_info_packet *info_packet); #endif diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c index 7cd8a43d1889..0fdf7a3e96de 100644 --- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c +++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c @@ -421,15 +421,13 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream, ***************************************************************************** */ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, - struct dc_info_packet *info_packet, int ALLMEnabled, int ALLMValue) + struct dc_info_packet *info_packet) { unsigned int length = 5; bool hdmi_vic_mode = false; uint8_t checksum = 0; uint32_t i = 0; enum dc_timing_3d_format format; - bool bALLM = (bool)ALLMEnabled; - bool bALLMVal = (bool)ALLMValue; info_packet->valid = false; format = stream->timing.timing_3d_format; @@ -442,20 +440,13 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, && format == TIMING_3D_FORMAT_NONE) hdmi_vic_mode = true; - if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode && !bALLM) + if ((format == TIMING_3D_FORMAT_NONE) && !hdmi_vic_mode) return; info_packet->sb[1] = 0x03; info_packet->sb[2] = 0x0C; info_packet->sb[3] = 0x00; - if (bALLM) { - info_packet->sb[1] = 0xD8; - info_packet->sb[2] = 0x5D; - info_packet->sb[3] = 0xC4; - info_packet->sb[4] = HF_VSIF_VERSION; - } - if (format != TIMING_3D_FORMAT_NONE) info_packet->sb[4] = (2 << 5); @@ -490,9 +481,6 @@ void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream, info_packet->hb1 = 0x01; info_packet->hb2 = (uint8_t) (length); - if (bALLM) - info_packet->sb[5] = (info_packet->sb[5] & ~0x02) | (bALLMVal << 1); - checksum += info_packet->hb0; checksum += info_packet->hb1; checksum += info_packet->hb2; -- cgit v1.2.3 From 2d6870d31484a24e864b1649b6d28b2c9b25bf0f Mon Sep 17 00:00:00 2001 From: Jaehyun Chung Date: Mon, 10 Aug 2020 16:02:47 -0400 Subject: drm/amd/display: Revert HDCP disable sequence change [Why] Revert HDCP disable sequence change that blanks stream before disabling HDCP. PSP and HW teams are currently investigating the root cause of why HDCP cannot be disabled before stream blank, which is expected to work without issues. Signed-off-by: Jaehyun Chung Reviewed-by: Wenjing Liu Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 117d8aaf2a9b..405452b736e1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -3286,10 +3286,10 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx) core_link_set_avmute(pipe_ctx, true); } - dc->hwss.blank_stream(pipe_ctx); #if defined(CONFIG_DRM_AMD_DC_HDCP) update_psp_stream_config(pipe_ctx, true); #endif + dc->hwss.blank_stream(pipe_ctx); if (pipe_ctx->stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) deallocate_mst_payload(pipe_ctx); -- cgit v1.2.3 From 237070fd12967aa3a778aa46fe8eadffa7c5ab68 Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Mon, 10 Aug 2020 14:02:55 -0400 Subject: drm/amd/display: Add debugfs for connector's FEC & DSC capabilities [why & how] Useful entry to understand if link has DSC or FEC capabilities, implemented to read DPCD caps stored on the link. Better than manually reading the registers with aux dpcd helper. Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 73 +++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') 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 f878575d17bb..e097a6059630 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -49,6 +49,10 @@ struct dmub_debugfs_trace_entry { uint32_t param1; }; +static inline const char *yesno(bool v) +{ + return v ? "yes" : "no"; +} /* parse_write_buffer_into_params - Helper function to parse debugfs write buffer into an array * @@ -980,6 +984,71 @@ static ssize_t dp_dpcd_data_read(struct file *f, char __user *buf, return read_size - r; } +/* function: Read link's DSC & FEC capabilities + * + * + * Access it with the following command (you need to specify + * connector like DP-1): + * + * cat /sys/kernel/debug/dri/0/DP-X/dp_dsc_fec_support + * + */ +static int dp_dsc_fec_support_show(struct seq_file *m, void *data) +{ + struct drm_connector *connector = m->private; + struct drm_modeset_acquire_ctx ctx; + struct drm_device *dev = connector->dev; + struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); + int ret = 0; + bool try_again = false; + bool is_fec_supported = false; + bool is_dsc_supported = false; + struct dpcd_caps dpcd_caps; + + drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE); + do { + try_again = false; + ret = drm_modeset_lock(&dev->mode_config.connection_mutex, &ctx); + if (ret) { + if (ret == -EDEADLK) { + ret = drm_modeset_backoff(&ctx); + if (!ret) { + try_again = true; + continue; + } + } + break; + } + if (connector->status != connector_status_connected) { + ret = -ENODEV; + break; + } + dpcd_caps = aconnector->dc_link->dpcd_caps; + if (aconnector->port) { + /* aconnector sets dsc_aux during get_modes call + * if MST connector has it means it can either + * enable DSC on the sink device or on MST branch + * its connected to. + */ + if (aconnector->dsc_aux) { + is_fec_supported = true; + is_dsc_supported = true; + } + } else { + is_fec_supported = dpcd_caps.fec_cap.raw & 0x1; + is_dsc_supported = dpcd_caps.dsc_caps.dsc_basic_caps.raw[0] & 0x1; + } + } while (try_again); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + seq_printf(m, "FEC_Sink_Support: %s\n", yesno(is_fec_supported)); + seq_printf(m, "DSC_Sink_Support: %s\n", yesno(is_dsc_supported)); + + return ret; +} + /* function: read DSC status on the connector * * The read function: dp_dsc_clock_en_read @@ -1838,6 +1907,7 @@ static ssize_t dp_dsc_slice_bpg_offset_read(struct file *f, char __user *buf, return result; } +DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support); DEFINE_SHOW_ATTRIBUTE(dmub_fw_state); DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer); DEFINE_SHOW_ATTRIBUTE(output_bpc); @@ -1963,7 +2033,8 @@ static const struct { {"dsc_pic_width", &dp_dsc_pic_width_debugfs_fops}, {"dsc_pic_height", &dp_dsc_pic_height_debugfs_fops}, {"dsc_chunk_size", &dp_dsc_chunk_size_debugfs_fops}, - {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops} + {"dsc_slice_bpg", &dp_dsc_slice_bpg_offset_debugfs_fops}, + {"dp_dsc_fec_support", &dp_dsc_fec_support_fops} }; #ifdef CONFIG_DRM_AMD_DC_HDCP -- cgit v1.2.3 From 6f77b2ac628073f647041a92b36c824ae3aef16e Mon Sep 17 00:00:00 2001 From: Eryk Brol Date: Mon, 10 Aug 2020 14:08:11 -0400 Subject: drm/amd/display: Add connector HPD trigger debugfs entry [why] Need a tool to retrigger a virtual hotplug for testing purposes with force redetection in both DC and DM. [how] Emulate handle_hpd_irq for connector as if usermode would trigger a hotplug. Perform DC link discovery, DM connector update, and DM force atomic commit. In order to trigger HPD on the connector user needs to echo 1 into "trigger_hotplug" debugfs entry on its respective connector. Signed-off-by: Eryk Brol Signed-off-by: Mikita Lipski Reviewed-by: Mikita Lipski Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 81 ++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'drivers/gpu') 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 e097a6059630..94fcb086154c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -1049,6 +1049,81 @@ static int dp_dsc_fec_support_show(struct seq_file *m, void *data) return ret; } +/* function: Trigger virtual HPD redetection on connector + * + * This function will perform link rediscovery, link disable + * and enable, and dm connector state update. + * + * Retrigger HPD on an existing connector by echoing 1 into + * its respectful "trigger_hotplug" debugfs entry: + * + * echo 1 > /sys/kernel/debug/dri/0/DP-X/trigger_hotplug + * + */ +static ssize_t dp_trigger_hotplug(struct file *f, const char __user *buf, + size_t size, loff_t *pos) +{ + struct amdgpu_dm_connector *aconnector = file_inode(f)->i_private; + struct drm_connector *connector = &aconnector->base; + struct drm_device *dev = connector->dev; + enum dc_connection_type new_connection_type = dc_connection_none; + char *wr_buf = NULL; + uint32_t wr_buf_size = 42; + int max_param_num = 1; + long param[1] = {0}; + uint8_t param_nums = 0; + + if (!aconnector || !aconnector->dc_link) + return -EINVAL; + + if (size == 0) + return -EINVAL; + + wr_buf = kcalloc(wr_buf_size, sizeof(char), GFP_KERNEL); + + if (!wr_buf) { + DRM_DEBUG_DRIVER("no memory to allocate write buffer\n"); + return -ENOSPC; + } + + if (parse_write_buffer_into_params(wr_buf, wr_buf_size, + (long *)param, buf, + max_param_num, + ¶m_nums)) + return -EINVAL; + + if (param_nums <= 0) { + DRM_DEBUG_DRIVER("user data not be read\n"); + kfree(wr_buf); + return -EINVAL; + } + + if (param[0] == 1) { + mutex_lock(&aconnector->hpd_lock); + + if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type) && + new_connection_type != dc_connection_none) + goto unlock; + + if (!dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) + goto unlock; + + amdgpu_dm_update_connector_after_detect(aconnector); + + drm_modeset_lock_all(dev); + dm_restore_drm_connector_state(dev, connector); + drm_modeset_unlock_all(dev); + + drm_kms_helper_hotplug_event(dev); + +unlock: + mutex_unlock(&aconnector->hpd_lock); + } + + kfree(wr_buf); + return size; +} + /* function: read DSC status on the connector * * The read function: dp_dsc_clock_en_read @@ -1967,6 +2042,12 @@ static const struct file_operations dp_dsc_slice_bpg_offset_debugfs_fops = { .llseek = default_llseek }; +static const struct file_operations dp_trigger_hotplug_debugfs_fops = { + .owner = THIS_MODULE, + .write = dp_trigger_hotplug, + .llseek = default_llseek +}; + static const struct file_operations dp_link_settings_debugfs_fops = { .owner = THIS_MODULE, .read = dp_link_settings_read, -- cgit v1.2.3 From 5019d8f1034324f284bd3fdb26aee6e7f34b83f9 Mon Sep 17 00:00:00 2001 From: Samson Tam Date: Thu, 13 Aug 2020 10:50:21 -0400 Subject: drm/amd/display: Fix passive dongle mistaken as active dongle in EDID emulation [Why] dongle_type is set during dongle connection but for passive dongles, dongle_type is not set. If user starts with an active dongle and then switches to a passive dongle, it will still report as an active dongle. Trying to emulate the wrong connecter type results in display not lighting up. [How] Set dpcd_caps.dongle_type for passive dongles in detect_dp(). Signed-off-by: Samson Tam Reviewed-by: Joshua Aberback Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/core/dc_link.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index 405452b736e1..437d1a7a16fe 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -763,6 +763,7 @@ static bool detect_dp(struct dc_link *link, sink_caps->signal = dp_passive_dongle_detection(link->ddc, sink_caps, audio_support); + link->dpcd_caps.dongle_type = sink_caps->dongle_type; } return true; -- cgit v1.2.3 From f0372d4f3f8d27599ee78fb036ca5404b954b944 Mon Sep 17 00:00:00 2001 From: Brandon Syu Date: Wed, 10 Jun 2020 16:44:33 +0800 Subject: drm/amd/display: Keep current gain when ABM disable immediately [Why] When system enters s3/s0i3, backlight PWM would set user level. [How] ABM disable function add keep current gain to avoid it. Signed-off-by: Brandon Syu Reviewed-by: Josip Pavic Acked-by: Eryk Brol Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc_stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h index 37743073772b..c246af7c584b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_stream.h +++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h @@ -233,7 +233,7 @@ struct dc_stream_state { union stream_update_flags update_flags; }; -#define ABM_LEVEL_IMMEDIATE_DISABLE 0xFFFFFFFF +#define ABM_LEVEL_IMMEDIATE_DISABLE 255 struct dc_stream_update { struct dc_stream_state *stream; -- cgit v1.2.3 From a590a83d74fd4804e95f1e485d552ed7feda9ae1 Mon Sep 17 00:00:00 2001 From: Youling Tang Date: Sat, 22 Aug 2020 16:27:23 +0800 Subject: gpu: amd: Remove duplicate semicolons at the end of line Remove duplicate semicolons at the end of line. Signed-off-by: Youling Tang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 2 +- drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 2719ef9de3bd..139fac0d8e76 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -1103,7 +1103,7 @@ static int vcn_v2_5_mmsch_start(struct amdgpu_device *adev, { uint32_t data = 0, loop = 0, size = 0; uint64_t addr = table->gpu_addr; - struct mmsch_v1_1_init_header *header = NULL;; + struct mmsch_v1_1_init_header *header = NULL; header = (struct mmsch_v1_1_init_header *)table->cpu_addr; size = header->total_size; diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c index afdd4f0d9d71..b32093136089 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c +++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.c @@ -467,7 +467,7 @@ static void fetch_pipe_params(struct display_mode_lib *mode_lib) mode_lib->vba.AudioSampleLayout[mode_lib->vba.NumberOfActivePlanes] = 1; mode_lib->vba.DRAMClockChangeLatencyOverride = 0.0; - mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable;; + mode_lib->vba.DSCEnabled[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.DSCEnable[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_enable; mode_lib->vba.NumberOfDSCSlices[mode_lib->vba.NumberOfActivePlanes] = dout->dsc_slices; -- cgit v1.2.3 From 817154c1a2035fdecead78873245f5b528da451e Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Mon, 24 Aug 2020 09:55:16 -0400 Subject: drm/amdkfd: call amdgpu_amdkfd_get_unique_id directly No need to use a function pointer because the implementation is not ASIC-specific. This fixes missing support due to a missing function pointer on Arcturus. Signed-off-by: Felix Kuehling Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 +-- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 4 ---- 4 files changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/gpu') 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 b0dcc800251e..e9aee50a0790 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -777,5 +777,4 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, - .get_unique_id = amdgpu_amdkfd_get_unique_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index d08839d9491f..1769cd4b6cef 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -727,5 +727,4 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, .get_hive_id = amdgpu_amdkfd_get_hive_id, - .get_unique_id = amdgpu_amdkfd_get_unique_id, }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index b15b620e731b..5ffd03685722 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -715,8 +715,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, if (kfd->kfd2kgd->get_hive_id) kfd->hive_id = kfd->kfd2kgd->get_hive_id(kfd->kgd); - if (kfd->kfd2kgd->get_unique_id) - kfd->unique_id = kfd->kfd2kgd->get_unique_id(kfd->kgd); + kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd); if (kfd_interrupt_init(kfd)) { dev_err(kfd_device, "Error initializing interrupts\n"); diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index a3c238c39ef5..017f97394344 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -214,8 +214,6 @@ struct tile_config { * * @get_hive_id: Returns hive id of current device, 0 if xgmi is not enabled * - * @get_unique_id: Returns uuid id of current device - * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -291,8 +289,6 @@ struct kfd2kgd_calls { uint32_t vmid, uint64_t page_table_base); uint32_t (*read_vmid_from_vmfault_reg)(struct kgd_dev *kgd); uint64_t (*get_hive_id)(struct kgd_dev *kgd); - uint64_t (*get_unique_id)(struct kgd_dev *kgd); - }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ -- cgit v1.2.3 From 332f6e1e9880c75b0c7287b8af2547ad28f389cd Mon Sep 17 00:00:00 2001 From: Felix Kuehling Date: Mon, 24 Aug 2020 10:18:37 -0400 Subject: drm/amdkfd: call amdgpu_amdkfd_get_hive_id directly No need to use a function pointer because the implementation is not ASIC-specific. Signed-off-by: Felix Kuehling Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c | 1 - drivers/gpu/drm/amd/amdkfd/kfd_device.c | 3 +-- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 3 --- 6 files changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c index a2cb31737378..1afa8f122e7d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_arcturus.c @@ -304,5 +304,4 @@ const struct kfd2kgd_calls arcturus_kfd2kgd = { kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c index e9aee50a0790..df0aab0fc67e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10.c @@ -776,5 +776,4 @@ const struct kfd2kgd_calls gfx_v10_kfd2kgd = { .get_atc_vmid_pasid_mapping_info = get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c index 7e59e473a190..e12623a9f7c2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c @@ -822,7 +822,6 @@ const struct kfd2kgd_calls gfx_v10_3_kfd2kgd = { .address_watch_get_offset = address_watch_get_offset_v10_3, .get_atc_vmid_pasid_mapping_info = NULL, .set_vm_context_page_table_base = set_vm_context_page_table_base_v10_3, - .get_hive_id = amdgpu_amdkfd_get_hive_id, #if 0 .enable_debug_trap = enable_debug_trap_v10_3, .disable_debug_trap = disable_debug_trap_v10_3, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c index 1769cd4b6cef..e6aede725197 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c @@ -726,5 +726,4 @@ const struct kfd2kgd_calls gfx_v9_kfd2kgd = { .get_atc_vmid_pasid_mapping_info = kgd_gfx_v9_get_atc_vmid_pasid_mapping_info, .set_vm_context_page_table_base = kgd_gfx_v9_set_vm_context_page_table_base, - .get_hive_id = amdgpu_amdkfd_get_hive_id, }; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 5ffd03685722..e1cd6599529f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -712,8 +712,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto kfd_doorbell_error; } - if (kfd->kfd2kgd->get_hive_id) - kfd->hive_id = kfd->kfd2kgd->get_hive_id(kfd->kgd); + kfd->hive_id = amdgpu_amdkfd_get_hive_id(kfd->kgd); kfd->unique_id = amdgpu_amdkfd_get_unique_id(kfd->kgd); diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 017f97394344..fc592f60e6a0 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -212,8 +212,6 @@ struct tile_config { * IH ring entry. This function allows the KFD ISR to get the VMID * from the fault status register as early as possible. * - * @get_hive_id: Returns hive id of current device, 0 if xgmi is not enabled - * * This structure contains function pointers to services that the kgd driver * provides to amdkfd driver. * @@ -288,7 +286,6 @@ struct kfd2kgd_calls { void (*set_vm_context_page_table_base)(struct kgd_dev *kgd, uint32_t vmid, uint64_t page_table_base); uint32_t (*read_vmid_from_vmfault_reg)(struct kgd_dev *kgd); - uint64_t (*get_hive_id)(struct kgd_dev *kgd); }; #endif /* KGD_KFD_INTERFACE_H_INCLUDED */ -- cgit v1.2.3 From b04e48bcac08ae900b5ea77a86f90356f51cf26c Mon Sep 17 00:00:00 2001 From: Bhawanpreet Lakha Date: Fri, 21 Aug 2020 11:57:15 -0400 Subject: drm/amd/display: Add DPCS regs for dcn3 link encoder dpcs reg are missing for dcn3 link encoder regs list, so add them. Also remove DPCSTX_DEBUG_CONFIG and RDPCSTX_DEBUG_CONFIG as they are unused and cause compile errors for dcn3 Signed-off-by: Bhawanpreet Lakha Reviewed-by: Nicholas Kazlauskas Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h | 2 -- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h index dcbf28dd72d4..864acd695cbb 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_link_encoder.h @@ -231,8 +231,6 @@ SRI(RDPCSTX_PHY_FUSE3, RDPCSTX, id), \ SRI(DPCSTX_TX_CLOCK_CNTL, DPCSTX, id), \ SRI(DPCSTX_TX_CNTL, DPCSTX, id), \ - SRI(DPCSTX_DEBUG_CONFIG, DPCSTX, id), \ - SRI(RDPCSTX_DEBUG_CONFIG, RDPCSTX, id), \ SR(RDPCSTX0_RDPCSTX_SCRATCH) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c index 957fc37b971e..8be4f21169d0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c @@ -491,6 +491,7 @@ static const struct dcn10_link_enc_hpd_registers link_enc_hpd_regs[] = { [id] = {\ LE_DCN3_REG_LIST(id), \ UNIPHY_DCN2_REG_LIST(phyid), \ + DPCS_DCN2_REG_LIST(id), \ SRI(DP_DPHY_INTERNAL_CTRL, DP, id) \ } -- cgit v1.2.3 From f8646661f713fb7d33ebe404d418bd3fa55c383e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 18 Aug 2020 19:24:03 -0400 Subject: drm/amdgpu: fix up DCHUBBUB_SDPIF_MMIO_CNTRL_0 handling Properly define this register using a relative offset rather than an absolute offset and use the proper SOC15 macros to access it. It's also DCN, not DCE, so remove it from the DCE12 header. No functional change. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 7 +++++-- drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index e1a0ae327cf5..a858912eb094 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -67,6 +67,9 @@ #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT__SHIFT 0x10 #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_WIDTH_MASK 0x00003FFFL #define HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION__PRI_VIEWPORT_HEIGHT_MASK 0x3FFF0000L +#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x049d +#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 + static const u32 golden_settings_vega10_hdp[] = { @@ -1282,7 +1285,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) static void gmc_v9_0_restore_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) - WREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); + WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); } /** @@ -1394,7 +1397,7 @@ static int gmc_v9_0_hw_init(void *handle) static void gmc_v9_0_save_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) - adev->gmc.sdpif_register = RREG32(mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); + adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); } /** diff --git a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h index 27bb8c1ab858..b6f74bf4af02 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/dce/dce_12_0_offset.h @@ -7376,8 +7376,6 @@ #define mmCRTC4_CRTC_DRR_CONTROL 0x0f3e #define mmCRTC4_CRTC_DRR_CONTROL_BASE_IDX 2 -#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0 0x395d -#define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 // addressBlock: dce_dc_fmt4_dispdec // base address: 0x2000 -- cgit v1.2.3 From 9737a923c91b70779f770e7a9ab69231ea8e946a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 13:40:56 -0400 Subject: drm/amdgpu: add an asic callback for pre asic init This callback can be used by asics that need to do something special prior to calling atom asic init. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 2509b1e302c0..3a9d10220ec1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -618,6 +618,8 @@ struct amdgpu_asic_funcs { uint64_t (*get_pcie_replay_count)(struct amdgpu_device *adev); /* device supports BACO */ bool (*supports_baco)(struct amdgpu_device *adev); + /* pre asic_init quirks */ + void (*pre_asic_init)(struct amdgpu_device *adev); }; /* @@ -1138,6 +1140,7 @@ int emu_soc_asic_init(struct amdgpu_device *adev); #define amdgpu_asic_need_reset_on_init(adev) (adev)->asic_funcs->need_reset_on_init((adev)) #define amdgpu_asic_get_pcie_replay_count(adev) ((adev)->asic_funcs->get_pcie_replay_count((adev))) #define amdgpu_asic_supports_baco(adev) (adev)->asic_funcs->supports_baco((adev)) +#define amdgpu_asic_pre_asic_init(adev) (adev)->asic_funcs->pre_asic_init((adev)) #define amdgpu_inc_vram_lost(adev) atomic_inc(&((adev)->vram_lost_counter)); -- cgit v1.2.3 From 632d9f9492a9e62a85447ba3203f8f4ca6a5de0e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 17:02:41 -0400 Subject: drm/amdgpu: add pre_asic_init callback for SI Nothing to do for this family. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/si.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index eaa2f071b139..455d5e366c69 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1871,6 +1871,10 @@ static int si_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk) return 0; } +static void si_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs si_asic_funcs = { .read_disabled_bios = &si_read_disabled_bios, @@ -1892,6 +1896,7 @@ static const struct amdgpu_asic_funcs si_asic_funcs = .need_reset_on_init = &si_need_reset_on_init, .get_pcie_replay_count = &si_get_pcie_replay_count, .supports_baco = &si_asic_supports_baco, + .pre_asic_init = &si_pre_asic_init, }; static uint32_t si_get_rev_id(struct amdgpu_device *adev) -- cgit v1.2.3 From 819515c7f30555a970559bedf1aece461dd463a6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 17:03:39 -0400 Subject: drm/amdgpu: add pre_asic_init callback for CIK Nothing to do for this family. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/cik.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 7e71ffbca93d..03ff8bd1fee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -1921,6 +1921,10 @@ static uint64_t cik_get_pcie_replay_count(struct amdgpu_device *adev) return (nak_r + nak_g); } +static void cik_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs cik_asic_funcs = { .read_disabled_bios = &cik_read_disabled_bios, @@ -1941,6 +1945,7 @@ static const struct amdgpu_asic_funcs cik_asic_funcs = .need_reset_on_init = &cik_need_reset_on_init, .get_pcie_replay_count = &cik_get_pcie_replay_count, .supports_baco = &cik_asic_supports_baco, + .pre_asic_init = &cik_pre_asic_init, }; static int cik_common_early_init(void *handle) -- cgit v1.2.3 From cff6c7f91a340788dde3b95f471885f7bf36c6c4 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 17:04:31 -0400 Subject: drm/amdgpu: add pre_asic_init callback for VI Nothing to do for this family. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index a92880c67841..9bcd0eebc6d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1068,6 +1068,10 @@ static bool vi_need_reset_on_init(struct amdgpu_device *adev) return false; } +static void vi_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs vi_asic_funcs = { .read_disabled_bios = &vi_read_disabled_bios, @@ -1088,6 +1092,7 @@ static const struct amdgpu_asic_funcs vi_asic_funcs = .need_reset_on_init = &vi_need_reset_on_init, .get_pcie_replay_count = &vi_get_pcie_replay_count, .supports_baco = &vi_asic_supports_baco, + .pre_asic_init = &vi_pre_asic_init, }; #define CZ_REV_BRISTOL(rev) \ -- cgit v1.2.3 From b0a2db9b482f16a91b2d67bac6b4977dc471fcab Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 16:48:17 -0400 Subject: drm/amdgpu: add pre_asic_init callback for SOC15 We need to restore some registers prior to running asic init to work around a firmware bug. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 35 +++++++++++++++++------------------ drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h | 2 ++ drivers/gpu/drm/amd/amdgpu/soc15.c | 7 +++++++ 3 files changed, 26 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index a858912eb094..1ca79030e95e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -1075,6 +1075,20 @@ static int gmc_v9_0_gart_init(struct amdgpu_device *adev) return amdgpu_gart_table_vram_alloc(adev); } +/** + * gmc_v9_0_save_registers - saves regs + * + * @adev: amdgpu_device pointer + * + * This saves potential register values that should be + * restored upon resume + */ +static void gmc_v9_0_save_registers(struct amdgpu_device *adev) +{ + if (adev->asic_type == CHIP_RAVEN) + adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); +} + static int gmc_v9_0_sw_init(void *handle) { int r, vram_width = 0, vram_type = 0, vram_vendor = 0; @@ -1229,6 +1243,8 @@ static int gmc_v9_0_sw_init(void *handle) amdgpu_vm_manager_init(adev); + gmc_v9_0_save_registers(adev); + return 0; } @@ -1282,7 +1298,7 @@ static void gmc_v9_0_init_golden_registers(struct amdgpu_device *adev) * * This restores register values, saved at suspend. */ -static void gmc_v9_0_restore_registers(struct amdgpu_device *adev) +void gmc_v9_0_restore_registers(struct amdgpu_device *adev) { if (adev->asic_type == CHIP_RAVEN) WREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0, adev->gmc.sdpif_register); @@ -1386,20 +1402,6 @@ static int gmc_v9_0_hw_init(void *handle) return r; } -/** - * gmc_v9_0_save_registers - saves regs - * - * @adev: amdgpu_device pointer - * - * This saves potential register values that should be - * restored upon resume - */ -static void gmc_v9_0_save_registers(struct amdgpu_device *adev) -{ - if (adev->asic_type == CHIP_RAVEN) - adev->gmc.sdpif_register = RREG32_SOC15(DCE, 0, mmDCHUBBUB_SDPIF_MMIO_CNTRL_0); -} - /** * gmc_v9_0_gart_disable - gart disable * @@ -1440,8 +1442,6 @@ static int gmc_v9_0_suspend(void *handle) if (r) return r; - gmc_v9_0_save_registers(adev); - return 0; } @@ -1450,7 +1450,6 @@ static int gmc_v9_0_resume(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - gmc_v9_0_restore_registers(adev); r = gmc_v9_0_hw_init(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h index e0585e8c6c1b..c415c439f690 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.h @@ -26,4 +26,6 @@ extern const struct amd_ip_funcs gmc_v9_0_ip_funcs; extern const struct amdgpu_ip_block_version gmc_v9_0_ip_block; + +void gmc_v9_0_restore_registers(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 3c3a7adad024..2f93c475d6d8 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -1029,6 +1029,11 @@ static uint64_t soc15_get_pcie_replay_count(struct amdgpu_device *adev) return (nak_r + nak_g); } +static void soc15_pre_asic_init(struct amdgpu_device *adev) +{ + gmc_v9_0_restore_registers(adev); +} + static const struct amdgpu_asic_funcs soc15_asic_funcs = { .read_disabled_bios = &soc15_read_disabled_bios, @@ -1049,6 +1054,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs = .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, .supports_baco = &soc15_supports_baco, + .pre_asic_init = &soc15_pre_asic_init, }; static const struct amdgpu_asic_funcs vega20_asic_funcs = @@ -1072,6 +1078,7 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs = .need_reset_on_init = &soc15_need_reset_on_init, .get_pcie_replay_count = &soc15_get_pcie_replay_count, .supports_baco = &soc15_supports_baco, + .pre_asic_init = &soc15_pre_asic_init, }; static int soc15_common_early_init(void *handle) -- cgit v1.2.3 From a71737313e57a1885c5cba7e006be24cce0f27c2 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 19 Aug 2020 17:04:47 -0400 Subject: drm/amdgpu: add pre_asic_init callback for navi Nothing to do for this family. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 54e941e0db60..33a6d2d5fc16 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -691,6 +691,10 @@ static void nv_init_doorbell_index(struct amdgpu_device *adev) adev->doorbell_index.sdma_doorbell_range = 20; } +static void nv_pre_asic_init(struct amdgpu_device *adev) +{ +} + static const struct amdgpu_asic_funcs nv_asic_funcs = { .read_disabled_bios = &nv_read_disabled_bios, @@ -710,6 +714,7 @@ static const struct amdgpu_asic_funcs nv_asic_funcs = .need_reset_on_init = &nv_need_reset_on_init, .get_pcie_replay_count = &nv_get_pcie_replay_count, .supports_baco = &nv_asic_supports_baco, + .pre_asic_init = &nv_pre_asic_init, }; static int nv_common_early_init(void *handle) -- cgit v1.2.3 From 4d2997ab2182fc58e93d33819ea2e2a0a87e6bb9 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Aug 2020 12:34:10 -0400 Subject: drm/amdgpu: add a wrapper for atom asic_init This allows us to add asic specific workarounds for atom asic init while keeping the adev specifics out of the atombios parser code. Acked-by: Nirmoy Das Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 64d6e58bcb0a..5a948edcc93c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -653,6 +653,20 @@ static void amdgpu_block_invalid_wreg(struct amdgpu_device *adev, BUG(); } +/** + * amdgpu_device_asic_init - Wrapper for atom asic_init + * + * @dev: drm_device pointer + * + * Does any asic specific work and then calls atom asic init. + */ +static int amdgpu_device_asic_init(struct amdgpu_device *adev) +{ + amdgpu_asic_pre_asic_init(adev); + + return amdgpu_atom_asic_init(adev->mode_info.atom_context); +} + /** * amdgpu_device_vram_scratch_init - allocate the VRAM scratch page * @@ -3201,7 +3215,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, goto failed; } DRM_INFO("GPU posting now...\n"); - r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + r = amdgpu_device_asic_init(adev); if (r) { dev_err(adev->dev, "gpu post error!\n"); goto failed; @@ -3549,7 +3563,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon) /* post card */ if (amdgpu_device_need_post(adev)) { - r = amdgpu_atom_asic_init(adev->mode_info.atom_context); + r = amdgpu_device_asic_init(adev); if (r) dev_err(adev->dev, "amdgpu asic init failed\n"); } @@ -4106,7 +4120,7 @@ static int amdgpu_do_asic_reset(struct amdgpu_hive_info *hive, list_for_each_entry(tmp_adev, device_list_handle, gmc.xgmi.head) { if (need_full_reset) { /* post card */ - if (amdgpu_atom_asic_init(tmp_adev->mode_info.atom_context)) + if (amdgpu_device_asic_init(tmp_adev)) dev_warn(tmp_adev->dev, "asic atom init failed!"); if (!r) { -- cgit v1.2.3 From 9ddcbf1f4c2d8dadd577c7ee5ae3a5168ebfae96 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Mon, 24 Aug 2020 22:15:25 +0100 Subject: drm/amd/pm: use kmemdup() rather than kmalloc+memcpy Issue identified with Coccinelle. Signed-off-by: Alex Dewar Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c index f56a3cbdfa3b..1f9082539457 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_processpptables.c @@ -890,14 +890,12 @@ static int init_powerplay_table_information( power_saving_clock_count); } - pptable_information->smc_pptable = kmalloc(sizeof(PPTable_t), GFP_KERNEL); + pptable_information->smc_pptable = kmemdup(&(powerplay_table->smcPPTable), + sizeof(PPTable_t), + GFP_KERNEL); if (pptable_information->smc_pptable == NULL) return -ENOMEM; - memcpy(pptable_information->smc_pptable, - &(powerplay_table->smcPPTable), - sizeof(PPTable_t)); - result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); if (result) -- cgit v1.2.3 From c56c90f41343c0ec9606d7d297110ecc84c7f891 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 28 Jul 2020 12:44:59 +0800 Subject: drm/amdgpu: add asd fw check before loading asd asd is not ready for some ASICs in early stage, and psp->asd_fw is more generic than ASIC name in the check. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Reviewed-by: Jiansong Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c index c22fb0194df7..d6c38e24f130 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c @@ -522,8 +522,7 @@ static int psp_asd_load(struct psp_context *psp) * add workaround to bypass it for sriov now. * TODO: add version check to make it common */ - if (amdgpu_sriov_vf(psp->adev) || - (psp->adev->asic_type == CHIP_NAVY_FLOUNDER)) + if (amdgpu_sriov_vf(psp->adev) || !psp->asd_fw) return 0; cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL); -- cgit v1.2.3 From 1887544d4ddd89fab8a76d150b46c329e7925da1 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Aug 2020 10:35:11 +0800 Subject: drm/amd/pm: correct the thermal alert temperature limit settings Do the maths in celsius degree. This can fix the issues caused by the changes below: drm/amd/pm: correct Vega20 swctf limit setting drm/amd/pm: correct Vega12 swctf limit setting drm/amd/pm: correct Vega10 swctf limit setting Signed-off-by: Evan Quan Reviewed-by: Kenneth Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c | 15 +++++++-------- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c | 15 +++++++-------- 3 files changed, 21 insertions(+), 24 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index ce9514c881ec..d572ba4ec9b1 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -367,14 +367,13 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, (struct phm_ppt_v2_information *)(hwmgr->pptable); struct phm_tdp_table *tdp_table = pp_table_info->tdp_table; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA10_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA10_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > tdp_table->usSoftwareShutdownTemp) high = tdp_table->usSoftwareShutdownTemp; @@ -385,8 +384,8 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val &= (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK) & (~THM_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c index e755fc0c9886..7ace439dcde7 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega12_thermal.c @@ -173,14 +173,13 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA12_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA12_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -191,8 +190,8 @@ static int vega12_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c index a9bc9d16641a..364162ddaa9c 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_thermal.c @@ -243,14 +243,13 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, struct phm_ppt_v3_information *pptable_information = (struct phm_ppt_v3_information *)hwmgr->pptable; struct amdgpu_device *adev = hwmgr->adev; - int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP * - PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + int low = VEGA20_THERMAL_MINIMUM_ALERT_TEMP; + int high = VEGA20_THERMAL_MAXIMUM_ALERT_TEMP; uint32_t val; - if (low < range->min) - low = range->min; + /* compare them in unit celsius degree */ + if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) + low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; if (high > pptable_information->us_software_shutdown_temp) high = pptable_information->us_software_shutdown_temp; @@ -261,8 +260,8 @@ static int vega20_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5); val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); - val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, high); + val = CGS_REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, low); val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK); WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val); -- cgit v1.2.3 From 5436ab94cd946006271f4e80de90b9a2276e93e3 Mon Sep 17 00:00:00 2001 From: Stanley.Yang Date: Mon, 17 Aug 2020 15:48:21 +0800 Subject: drm/amdkfd: fix set kfd node ras properties value The ctx->features are new RAS implementation which is only available for Vega20 and onwards, it is not available for vega10, vega10 should follow legacy ECC implementation. Changed from V1: wrap function to initialize kfd node properties Changed from V2: remove wrap function and SDMA SRAM ECC check Signed-off-by: Stanley.Yang Reviewed-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 28 +++++++++++++++++++--------- drivers/gpu/drm/amd/amdkfd/kfd_topology.c | 24 +++++++++++------------- 3 files changed, 31 insertions(+), 22 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 3a9d10220ec1..4009d2e30727 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -986,6 +986,7 @@ struct amdgpu_device { atomic_t throttling_logging_enabled; struct ratelimit_state throttling_logging_rs; + uint32_t ras_features; }; static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 9b718749919a..e5ea14774c0c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -1963,6 +1963,17 @@ int amdgpu_ras_request_reset_on_boot(struct amdgpu_device *adev, return 0; } +static int amdgpu_ras_check_asic_type(struct amdgpu_device *adev) +{ + if (adev->asic_type != CHIP_VEGA10 && + adev->asic_type != CHIP_VEGA20 && + adev->asic_type != CHIP_ARCTURUS && + adev->asic_type != CHIP_SIENNA_CICHLID) + return 1; + else + return 0; +} + /* * check hardware's ras ability which will be saved in hw_supported. * if hardware does not support ras, we can skip some ras initializtion and @@ -1979,9 +1990,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = 0; if (amdgpu_sriov_vf(adev) || !adev->is_atom_fw || - (adev->asic_type != CHIP_VEGA20 && - adev->asic_type != CHIP_ARCTURUS && - adev->asic_type != CHIP_SIENNA_CICHLID)) + amdgpu_ras_check_asic_type(adev)) return; if (amdgpu_atomfirmware_mem_ecc_supported(adev)) { @@ -2003,6 +2012,7 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev, *supported = amdgpu_ras_enable == 0 ? 0 : *hw_supported & amdgpu_ras_mask; + adev->ras_features = *supported; } int amdgpu_ras_init(struct amdgpu_device *adev) @@ -2025,9 +2035,9 @@ int amdgpu_ras_init(struct amdgpu_device *adev) amdgpu_ras_check_supported(adev, &con->hw_supported, &con->supported); - if (!con->hw_supported) { + if (!con->hw_supported || (adev->asic_type == CHIP_VEGA10)) { r = 0; - goto err_out; + goto release_con; } con->features = 0; @@ -2038,25 +2048,25 @@ int amdgpu_ras_init(struct amdgpu_device *adev) if (adev->nbio.funcs->init_ras_controller_interrupt) { r = adev->nbio.funcs->init_ras_controller_interrupt(adev); if (r) - goto err_out; + goto release_con; } if (adev->nbio.funcs->init_ras_err_event_athub_interrupt) { r = adev->nbio.funcs->init_ras_err_event_athub_interrupt(adev); if (r) - goto err_out; + goto release_con; } if (amdgpu_ras_fs_init(adev)) { r = -EINVAL; - goto err_out; + goto release_con; } dev_info(adev->dev, "RAS INFO: ras initialized successfully, " "hardware ability[%x] ras_mask[%x]\n", con->hw_supported, con->supported); return 0; -err_out: +release_con: amdgpu_ras_set_context(adev, NULL); kfree(con); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 5e8eb783d2d5..2b31c3066aaa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -1239,7 +1239,7 @@ int kfd_topology_add_device(struct kfd_dev *gpu) void *crat_image = NULL; size_t image_size = 0; int proximity_domain; - struct amdgpu_ras *ctx; + struct amdgpu_device *adev; INIT_LIST_HEAD(&temp_topology_device_list); @@ -1404,19 +1404,17 @@ int kfd_topology_add_device(struct kfd_dev *gpu) dev->node_props.max_waves_per_simd = 10; } - ctx = amdgpu_ras_get_context((struct amdgpu_device *)(dev->gpu->kgd)); - if (ctx) { - /* kfd only concerns sram ecc on GFX/SDMA and HBM ecc on UMC */ - dev->node_props.capability |= - (((ctx->features & BIT(AMDGPU_RAS_BLOCK__SDMA)) != 0) || - ((ctx->features & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0)) ? - HSA_CAP_SRAM_EDCSUPPORTED : 0; - dev->node_props.capability |= ((ctx->features & BIT(AMDGPU_RAS_BLOCK__UMC)) != 0) ? - HSA_CAP_MEM_EDCSUPPORTED : 0; - - dev->node_props.capability |= (ctx->features != 0) ? + adev = (struct amdgpu_device *)(dev->gpu->kgd); + /* kfd only concerns sram ecc on GFX and HBM ecc on UMC */ + dev->node_props.capability |= + ((adev->ras_features & BIT(AMDGPU_RAS_BLOCK__GFX)) != 0) ? + HSA_CAP_SRAM_EDCSUPPORTED : 0; + dev->node_props.capability |= ((adev->ras_features & BIT(AMDGPU_RAS_BLOCK__UMC)) != 0) ? + HSA_CAP_MEM_EDCSUPPORTED : 0; + + if (adev->asic_type != CHIP_VEGA10) + dev->node_props.capability |= (adev->ras_features != 0) ? HSA_CAP_RASEVENTNOTIFY : 0; - } kfd_debug_print_topology(); -- cgit v1.2.3 From 22dd44f47cf74c2891c359976f308941a3736605 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Tue, 25 Aug 2020 15:39:57 +0800 Subject: drm/amdgpu: use MODE1 reset for navy_flounder by default Switch default gpu reset method to MODE1 for navy_flounder. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/nv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index 33a6d2d5fc16..4d1402356262 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -364,6 +364,7 @@ nv_asic_reset_method(struct amdgpu_device *adev) switch (adev->asic_type) { case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: return AMD_RESET_METHOD_MODE1; default: if (smu_baco_is_support(smu)) -- cgit v1.2.3 From 6178aed011a31b7d242b80ed3e83fcc9b67444e1 Mon Sep 17 00:00:00 2001 From: Nicholas Kazlauskas Date: Fri, 14 Aug 2020 11:49:13 -0400 Subject: drm/amd/powerplay: Fix hardmins not being sent to SMU for RV [Why] DC uses these to raise the voltage as needed for higher dispclk/dppclk and to ensure that we have enough bandwidth to drive the displays. There's a bug preventing these from actuially sending messages since it's checking the actual clock (which is 0) instead of the incoming clock (which shouldn't be 0) when deciding to send the hardmin. [How] Check the clocks != 0 instead of the actual clocks. Fixes: 9ed9203c3ee7 ("drm/amd/powerplay: rv dal-pplib interface refactor powerplay part") Signed-off-by: Nicholas Kazlauskas Reviewed-by: Alex Deucher Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c index c9cfe90a2947..9ee8cf8267c8 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu10_hwmgr.c @@ -204,8 +204,7 @@ static int smu10_set_min_deep_sleep_dcefclk(struct pp_hwmgr *hwmgr, uint32_t clo { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->need_min_deep_sleep_dcefclk && - smu10_data->deep_sleep_dcefclk != clock) { + if (clock && smu10_data->deep_sleep_dcefclk != clock) { smu10_data->deep_sleep_dcefclk = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetMinDeepSleepDcefclk, @@ -219,8 +218,7 @@ static int smu10_set_hard_min_dcefclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t c { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->dcf_actual_hard_min_freq && - smu10_data->dcf_actual_hard_min_freq != clock) { + if (clock && smu10_data->dcf_actual_hard_min_freq != clock) { smu10_data->dcf_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinDcefclkByFreq, @@ -234,8 +232,7 @@ static int smu10_set_hard_min_fclk_by_freq(struct pp_hwmgr *hwmgr, uint32_t cloc { struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend); - if (smu10_data->f_actual_hard_min_freq && - smu10_data->f_actual_hard_min_freq != clock) { + if (clock && smu10_data->f_actual_hard_min_freq != clock) { smu10_data->f_actual_hard_min_freq = clock; smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetHardMinFclkByFreq, -- cgit v1.2.3 From c997e8e26c001c1a92200f44027f6c915c8f5487 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 24 Aug 2020 20:17:30 -0400 Subject: drm/amdgpu: report DC not supported if virtual display is enabled (v2) Virtual display is non-atomic so report false to avoid checking atomic state and other atomic things at runtime. v2: squash into the sr-iov check Acked-by: Nirmoy Das Acked-by: Guchun Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 5a948edcc93c..8f37f9f99105 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2861,7 +2861,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type) */ bool amdgpu_device_has_dc_support(struct amdgpu_device *adev) { - if (amdgpu_sriov_vf(adev)) + if (amdgpu_sriov_vf(adev) || adev->enable_virtual_display) return false; return amdgpu_device_asic_has_dc_support(adev->asic_type); -- cgit v1.2.3 From cf851f3ff891ff8cb204e7118682d55429c6fb96 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Aug 2020 11:43:45 -0400 Subject: drm/amdgpu: Fix buffer overflow in INFO ioctl The values for "se_num" and "sh_num" come from the user in the ioctl. They can be in the 0-255 range but if they're more than AMDGPU_GFX_MAX_SE (4) or AMDGPU_GFX_MAX_SH_PER_SE (2) then it results in an out of bounds read. Reported-by: Dan Carpenter Acked-by: Dan Carpenter Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d125c4b2af53..deba6873bfea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -669,8 +669,12 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file * in the bitfields */ if (se_num == AMDGPU_INFO_MMR_SE_INDEX_MASK) se_num = 0xffffffff; + else if (se_num >= AMDGPU_GFX_MAX_SE) + return -EINVAL; if (sh_num == AMDGPU_INFO_MMR_SH_INDEX_MASK) sh_num = 0xffffffff; + else if (sh_num >= AMDGPU_GFX_MAX_SH_PER_SE) + return -EINVAL; if (info->read_mmr_reg.count > 128) return -EINVAL; -- cgit v1.2.3 From ec314c4612653aaf6e8d6a7c23fed9b3f7a0039f Mon Sep 17 00:00:00 2001 From: Wayne Lin Date: Tue, 18 Aug 2020 11:19:42 +0800 Subject: drm/amd/display: Retry AUX write when fail occurs [Why] In dm_dp_aux_transfer() now, we forget to handle AUX_WR fail cases. We suppose every write wil get done successfully and hence some AUX commands might not sent out indeed. [How] Check if AUX_WR success. If not, retry it. Signed-off-by: Wayne Lin Reviewed-by: Hersen Wu Acked-by: Rodrigo Siqueira Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index bbc20834c643..bd477a166015 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -67,7 +67,7 @@ static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, result = dc_link_aux_transfer_raw(TO_DM_AUX(aux)->ddc_service, &payload, &operation_result); - if (payload.write) + if (payload.write && result >= 0) result = msg->size; if (result < 0) -- cgit v1.2.3 From faeefe4e54d65c06dd23e5486e5423c564c4a12a Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Wed, 26 Aug 2020 14:11:52 +0800 Subject: drm/amdgpu: disable runtime pm for navy_flounder Disable runtime pm for navy_flounder temporarily. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index deba6873bfea..b4077be9ba69 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -170,6 +170,7 @@ int amdgpu_driver_load_kms(struct amdgpu_device *adev, unsigned long flags) case CHIP_VEGA20: case CHIP_ARCTURUS: case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: /* enable runpm if runpm=1 */ if (amdgpu_runtime_pm > 0) adev->runpm = true; -- cgit v1.2.3 From 08572451b4b1783fdff787b0188c4d50fdf96b81 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Wed, 26 Aug 2020 21:24:58 +0800 Subject: drm/amd/display: Fix memleak in amdgpu_dm_mode_config_init When amdgpu_display_modeset_create_props() fails, state and state->context should be freed to prevent memleak. It's the same when amdgpu_dm_audio_init() fails. Signed-off-by: Dinghao Liu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') 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 785f21ea35df..e2e7138c4e3f 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2905,12 +2905,18 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev) &dm_atomic_state_funcs); r = amdgpu_display_modeset_create_props(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } r = amdgpu_dm_audio_init(adev); - if (r) + if (r) { + dc_release_state(state->context); + kfree(state); return r; + } return 0; } -- cgit v1.2.3 From 0bbb5462d30cb1a99d442a7d4b4bc5302fe24821 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Wed, 26 Aug 2020 15:43:42 +0800 Subject: drm/amdgpu: correct SE number for arcturus gfx ras When resetting EDC related register, all CUs needs to be visited, otherwise, garbage data from EDC register of missed SEs would present. Signed-off-by: Guchun Chen Reviewed-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c index 46351db36922..bd85aed3523a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4.c @@ -57,10 +57,10 @@ static const struct soc15_reg_entry gfx_v9_4_edc_counter_regs[] = { /* SPI */ { SOC15_REG_ENTRY(GC, 0, mmSPI_EDC_CNT), 0, 4, 1 }, /* SQ */ - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO), 0, 4, 16 }, - { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT), 0, 4, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_CNT), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_DED_CNT), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_INFO), 0, 8, 16 }, + { SOC15_REG_ENTRY(GC, 0, mmSQ_EDC_SEC_CNT), 0, 8, 16 }, /* SQC */ { SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT), 0, 4, 6 }, { SOC15_REG_ENTRY(GC, 0, mmSQC_EDC_CNT2), 0, 4, 6 }, -- cgit v1.2.3 From 3d14a79b5134173ced9364411800ea60029e785e Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 24 Aug 2020 16:50:12 +0800 Subject: drm/amd/pm: fix is_dpm_running() run error on 32bit system v1: the C type "unsigned long" size is 32bit on 32bit system, it will cause code logic error, so replace it with "uint64_t". v2: remove duplicate cast operation. Signed-off-by: Kevin Suggest-by: Jiansong Chen Reviewed-by: Jiansong Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 10 +++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 10 +++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 8347b1f2509f..59b245c6c4d7 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1844,10 +1844,14 @@ static bool arcturus_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 72f3d68691d8..cc67d5c60f3d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1345,10 +1345,14 @@ static bool navi10_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 66d655958a78..b48ac591db8b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1150,10 +1150,14 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } -- cgit v1.2.3 From e1b08ae52b25f7d77a030bbaff745d4818344598 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Aug 2020 13:51:29 +0800 Subject: drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting Normally softwareshutdowntemp should be greater than Thotspotlimit. However, on some VEGA10 ASIC, the softwareshutdowntemp is 91C while Thotspotlimit is 105C. This seems not right and may trigger some false alarms. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c index d572ba4ec9b1..952cd3d7240e 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_thermal.c @@ -374,8 +374,18 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, /* compare them in unit celsius degree */ if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - if (high > tdp_table->usSoftwareShutdownTemp) - high = tdp_table->usSoftwareShutdownTemp; + + /* + * As a common sense, usSoftwareShutdownTemp should be bigger + * than ThotspotLimit. For any invalid usSoftwareShutdownTemp, + * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP + * to avoid false alarms. + */ + if ((tdp_table->usSoftwareShutdownTemp > + range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) { + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; + } if (low > high) return -EINVAL; -- cgit v1.2.3 From 6c4d1f43ed0edeee7f38069619cc8c43459a6171 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Wed, 26 Aug 2020 11:28:19 +0800 Subject: drm/amd/pm: suppress static checker warning Suppress the warning below: drivers/gpu/drm/amd/amdgpu/../pm/powerplay/hwmgr/hardwaremanager.c:274 phm_check_smc_update_required_for_display_configuration() warn: signedness bug returning '(-22)' Reported-by: Dan Carpenter Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c index 9454ab50f9a1..1f9b9facdf1f 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/hardwaremanager.c @@ -271,7 +271,10 @@ int phm_start_thermal_controller(struct pp_hwmgr *hwmgr) bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) { - PHM_FUNC_CHECK(hwmgr); + if (hwmgr == NULL || + hwmgr->hwmgr_func == NULL) + return false; + if (hwmgr->pp_one_vf) return false; -- cgit v1.2.3 From 4cd2a96d3a0ac6b07c443e904f5b8a52f2471571 Mon Sep 17 00:00:00 2001 From: Jiawei Date: Thu, 27 Aug 2020 10:07:52 +0800 Subject: drm/amdgpu: simplify hw status clear/set logic Optimize code to iterate less loops in amdgpu_device_ip_reinit_early_sriov() Signed-off-by: Jiawei Reviewed-by: Emily.Deng Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 8f37f9f99105..696a61cc3ac6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2598,17 +2598,16 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; - for (i = 0; i < adev->num_ip_blocks; i++) - adev->ip_blocks[i].status.hw = false; - - for (i = 0; i < ARRAY_SIZE(ip_order); i++) { + for (i = 0; i < adev->num_ip_blocks; i++) { int j; struct amdgpu_ip_block *block; - for (j = 0; j < adev->num_ip_blocks; j++) { - block = &adev->ip_blocks[j]; + block = &adev->ip_blocks[i]; + block->status.hw = false; - if (block->version->type != ip_order[i] || + for (j = 0; j < ARRAY_SIZE(ip_order); j++) { + + if (block->version->type != ip_order[j] || !block->status.valid) continue; -- cgit v1.2.3 From ce7e5a6e130d4fe76e09bd082e98b65f630aa474 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Thu, 27 Aug 2020 14:31:20 +0800 Subject: drm/amd/pm: enable MP0 DPM for sienna_cichlid Enable MP0 clock DPM for sienna_cichlid. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index b48ac591db8b..b67931fd64b4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -68,7 +68,8 @@ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) + FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)) #define SMU_11_0_7_GFX_BUSY_THRESHOLD 15 @@ -230,6 +231,7 @@ sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) + | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) | FEATURE_MASK(FEATURE_DS_FCLK_BIT) -- cgit v1.2.3 From 177e38a48168f9e70faaec34df053d2f8134ede6 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman Date: Thu, 27 Aug 2020 17:07:33 +0530 Subject: drm/amdgpu: Specify get_argument function for ci_smu_funcs Starting in Linux 5.8, the graphics and memory clock frequency were not being reported for CIK cards. This is a regression, since they were reported correctly in Linux 5.7. After investigation, I discovered that the smum_send_msg_to_smc() function, attempts to call the corresponding get_argument() function of ci_smu_funcs. However, the get_argument() function is not defined in ci_smu_funcs. This patch fixes the bug by specifying the correct get_argument() function. Fixes: a0ec225633d9f6 ("drm/amd/powerplay: unified interfaces for message issuing and response checking") Signed-off-by: Sandeep Raghuraman Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c index c18169aa59ce..e4d1f3d66ef4 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -37,6 +37,7 @@ #include "cgs_common.h" #include "atombios.h" #include "pppcielanes.h" +#include "smu7_smumgr.h" #include "smu/smu_7_0_1_d.h" #include "smu/smu_7_0_1_sh_mask.h" @@ -2948,6 +2949,7 @@ const struct pp_smumgr_func ci_smu_funcs = { .request_smu_load_specific_fw = NULL, .send_msg_to_smc = ci_send_msg_to_smc, .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, .download_pptable_settings = NULL, .upload_pptable_settings = NULL, .get_offsetof = ci_get_offsetof, -- cgit v1.2.3 From 3425740adf97b2258966ee3f0d871fd5cc314028 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman Date: Thu, 27 Aug 2020 18:43:37 +0530 Subject: drm/amdgpu: Fix bug in reporting voltage for CIK On my R9 390, the voltage was reported as a constant 1000 mV. This was due to a bug in smu7_hwmgr.c, in the smu7_read_sensor() function, where some magic constants were used in a condition, to determine whether the voltage should be read from PLANE2_VID or PLANE1_VID. The VDDC mask was incorrectly used, instead of the VDDGFX mask. This patch changes the code to use the correct defined constants (and apply the correct bitshift), thus resulting in correct voltage reporting. Signed-off-by: Sandeep Raghuraman Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index ffe05b7cc1f0..4a3b64aa21ce 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -3581,7 +3581,8 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, case AMDGPU_PP_SENSOR_GPU_POWER: return smu7_get_gpu_power(hwmgr, (uint32_t *)value); case AMDGPU_PP_SENSOR_VDDGFX: - if ((data->vr_config & 0xff) == 0x2) + if ((data->vr_config & VRCONF_VDDGFX_MASK) == + (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT)) val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); else -- cgit v1.2.3 From 5150dd85bdfa08143cacf1b4249121651bed3c35 Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 26 Aug 2020 01:33:48 +0800 Subject: drm/radeon: Prefer lower feedback dividers Commit 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") fixed screen flicker for HP Compaq nx9420 but breaks other laptops like Asus X50SL. Turns out we also need to favor lower feedback dividers. Users confirmed this change fixes the regression and doesn't regress the original fix. Fixes: 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") BugLink: https://bugs.launchpad.net/bugs/1791312 BugLink: https://bugs.launchpad.net/bugs/1861554 Reviewed-by: Christian König Signed-off-by: Kai-Heng Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e0ae911ef427..7b69d6dfe44a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -933,7 +933,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, /* get matching reference and feedback divider */ *ref_div = min(max(den/post_div, 1u), ref_div_max); - *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); + *fb_div = max(nom * *ref_div * post_div / den, 1u); /* limit fb divider to its maximum */ if (*fb_div > fb_div_max) { -- cgit v1.2.3 From 07b5b12d97dc9f47ff3dff46c4f944a15bd762e5 Mon Sep 17 00:00:00 2001 From: Yu Kuai Date: Wed, 26 Aug 2020 09:08:26 +0800 Subject: drm/sun4i: add missing put_device() call in sun8i_r40_tcon_tv_set_mux() If sun8i_r40_tcon_tv_set_mux() succeed, sun8i_r40_tcon_tv_set_mux() doesn't have a corresponding put_device(). Thus add put_device() to fix the exception handling for this function implementation. Fixes: 0305189afb32 ("drm/sun4i: tcon: Add support for R40 TCON") Signed-off-by: Yu Kuai Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20200826010826.1785487-1-yukuai3@huawei.com --- drivers/gpu/drm/sun4i/sun4i_tcon.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 359b56e43b83..24d95f058918 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -1433,14 +1433,18 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon, if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) && encoder->encoder_type == DRM_MODE_ENCODER_TMDS) { ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id); - if (ret) + if (ret) { + put_device(&pdev->dev); return ret; + } } if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) { ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id); - if (ret) + if (ret) { + put_device(&pdev->dev); return ret; + } } return 0; -- cgit v1.2.3 From e230ac11182b3d9f8448498e925e479bcd1e79f7 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Thu, 27 Aug 2020 17:50:36 +0200 Subject: drm/amdgpu: fix compiler warnings Fixes below compiler warnings: CC [M] drivers/gpu/drm/amd/amdgpu/amdgpu_device.o drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:381:1: warning: ‘static’ is not at beginning of declaration [-Wold-style-declaration] 381 | void static inline amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) | ^~~~ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:381:1: warning: ‘inline’ is not at beginning of declaration [-Wold-style-declaration] drivers/gpu/drm/amd/amdgpu/amdgpu_device.c: In function ‘amdgpu_device_fini’: drivers/gpu/drm/amd/amdgpu/amdgpu_device.c:3381:6: warning: variable ‘r’ set but not used [-Wunused-but-set-variable] 3381 | int r; | ^ Signed-off-by: Nirmoy Das Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 696a61cc3ac6..6518e444bead 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -378,7 +378,9 @@ void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value) BUG(); } -void static inline amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) +static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, + uint32_t reg, uint32_t v, + uint32_t acc_flags) { trace_amdgpu_mm_wreg(adev->pdev->device, reg, v); @@ -3378,8 +3380,6 @@ failed: */ void amdgpu_device_fini(struct amdgpu_device *adev) { - int r; - dev_info(adev->dev, "amdgpu: finishing device.\n"); flush_delayed_work(&adev->delayed_init_work); adev->shutdown = true; @@ -3402,7 +3402,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) if (adev->pm_sysfs_en) amdgpu_pm_sysfs_fini(adev); amdgpu_fbdev_fini(adev); - r = amdgpu_device_ip_fini(adev); + amdgpu_device_ip_fini(adev); release_firmware(adev->firmware.gpu_info_fw); adev->firmware.gpu_info_fw = NULL; adev->accel_working = false; -- cgit v1.2.3 From 1a21e5b930e8454438ebb707f558b256e4b06ec7 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Thu, 27 Aug 2020 13:44:03 +0200 Subject: drm/ingenic: Fix leak of device_node pointer of_graph_get_remote_node() requires of_node_put() to be called on the device_node pointer when it's no more in use. Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU") Signed-off-by: Paul Cercueil Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200827114404.36748-1-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index ada990a7f911..c1bcb93aed2d 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -978,6 +978,7 @@ static int ingenic_drm_probe(struct platform_device *pdev) } drm_of_component_match_add(dev, &match, compare_of, np); + of_node_put(np); return component_master_add_with_match(dev, &ingenic_master_ops, match); } -- cgit v1.2.3 From 3b5b005ef7d9e2ff1693c1d14a0f4459dcedb4e0 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Thu, 27 Aug 2020 13:44:04 +0200 Subject: drm/ingenic: Fix driver not probing when IPU port is missing Even if support for the IPU was compiled in, we may run on a device (e.g. the Qi LB60) where the IPU is not available, or simply with an old devicetree without the IPU node. In that case the ingenic-drm refused to probe. Fix the driver so that it will probe even if the IPU node is not present in devicetree (but then IPU support is disabled of course). v2: Take a different approach Fixes: fc1acf317b01 ("drm/ingenic: Add support for the IPU") Signed-off-by: Paul Cercueil Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20200827114404.36748-2-paul@crapouillou.net --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index c1bcb93aed2d..b7074161ccf0 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -673,7 +673,7 @@ static void ingenic_drm_unbind_all(void *d) component_unbind_all(priv->dev, &priv->drm); } -static int ingenic_drm_bind(struct device *dev) +static int ingenic_drm_bind(struct device *dev, bool has_components) { struct platform_device *pdev = to_platform_device(dev); const struct jz_soc_info *soc_info; @@ -808,7 +808,7 @@ static int ingenic_drm_bind(struct device *dev) return ret; } - if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) { + if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && has_components) { ret = component_bind_all(dev, drm); if (ret) { if (ret != -EPROBE_DEFER) @@ -939,6 +939,11 @@ err_pixclk_disable: return ret; } +static int ingenic_drm_bind_with_components(struct device *dev) +{ + return ingenic_drm_bind(dev, true); +} + static int compare_of(struct device *dev, void *data) { return dev->of_node == data; @@ -957,7 +962,7 @@ static void ingenic_drm_unbind(struct device *dev) } static const struct component_master_ops ingenic_master_ops = { - .bind = ingenic_drm_bind, + .bind = ingenic_drm_bind_with_components, .unbind = ingenic_drm_unbind, }; @@ -968,14 +973,12 @@ static int ingenic_drm_probe(struct platform_device *pdev) struct device_node *np; if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) - return ingenic_drm_bind(dev); + return ingenic_drm_bind(dev, false); /* IPU is at port address 8 */ np = of_graph_get_remote_node(dev->of_node, 8, 0); - if (!np) { - dev_err(dev, "Unable to get IPU node\n"); - return -EINVAL; - } + if (!np) + return ingenic_drm_bind(dev, false); drm_of_component_match_add(dev, &match, compare_of, np); of_node_put(np); -- cgit v1.2.3 From fd90e3808fd2c207560270c39b86b71af2231aa1 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Fri, 28 Aug 2020 14:50:32 +0200 Subject: drm/sun4i: Fix dsi dcs long write function It's writing too much data. regmap_bulk_write expects number of register sized chunks to write, not a byte sized length of the bounce buffer. Bounce buffer needs to be padded too, so that regmap_bulk_write will not read past the end of the buffer. Fixes: 133add5b5ad4 ("drm/sun4i: Add Allwinner A31 MIPI-DSI controller support") Signed-off-by: Ondrej Jirman Signed-off-by: Maxime Ripard Reviewed-by: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20200828125032.937148-1-megous@megous.com --- drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index aa67cb037e9d..32d4c3f7fc4e 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -889,7 +889,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi, regmap_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(0), sun6i_dsi_dcs_build_pkt_hdr(dsi, msg)); - bounce = kzalloc(msg->tx_len + sizeof(crc), GFP_KERNEL); + bounce = kzalloc(ALIGN(msg->tx_len + sizeof(crc), 4), GFP_KERNEL); if (!bounce) return -ENOMEM; @@ -900,7 +900,7 @@ static int sun6i_dsi_dcs_write_long(struct sun6i_dsi *dsi, memcpy((u8 *)bounce + msg->tx_len, &crc, sizeof(crc)); len += sizeof(crc); - regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, len); + regmap_bulk_write(dsi->regs, SUN6I_DSI_CMD_TX_REG(1), bounce, DIV_ROUND_UP(len, 4)); regmap_write(dsi->regs, SUN6I_DSI_CMD_CTL_REG, len + 4 - 1); kfree(bounce); -- cgit v1.2.3 From 55977744f9d862512a524fea93fc5226b09e76a9 Mon Sep 17 00:00:00 2001 From: Mukul Joshi Date: Fri, 28 Aug 2020 18:50:42 -0400 Subject: drm/amdkfd: Add GPU reset SMI event Add support for reporting GPU reset events through SMI. KFD would report both pre and post GPU reset events. Signed-off-by: Mukul Joshi Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 4 ++++ drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 2 ++ drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c | 34 +++++++++++++++++++++++++++-- drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h | 1 + include/uapi/linux/kfd_ioctl.h | 2 ++ 5 files changed, 41 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index e1cd6599529f..0e71a0543f98 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -812,6 +812,8 @@ int kgd2kfd_pre_reset(struct kfd_dev *kfd) if (!kfd->init_complete) return 0; + kfd_smi_event_update_gpu_reset(kfd, false); + kfd->dqm->ops.pre_reset(kfd->dqm); kgd2kfd_suspend(kfd, false); @@ -840,6 +842,8 @@ int kgd2kfd_post_reset(struct kfd_dev *kfd) atomic_set(&kfd->sram_ecc_flag, 0); + kfd_smi_event_update_gpu_reset(kfd, true); + return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f14beb93acb4..023629f28495 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -312,6 +312,8 @@ struct kfd_dev { /* Clients watching SMI events */ struct list_head smi_clients; spinlock_t smi_lock; + + uint32_t reset_seq_num; }; enum kfd_mempool { diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 4d4b6e3ab697..17d1736367ea 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -174,6 +174,36 @@ static void add_event_to_kfifo(struct kfd_dev *dev, unsigned int smi_event, rcu_read_unlock(); } +void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset) +{ + /* + * GpuReset msg = Reset seq number (incremented for + * every reset message sent before GPU reset). + * 1 byte event + 1 byte space + 8 bytes seq num + + * 1 byte \n + 1 byte \0 = 12 + */ + char fifo_in[12]; + int len; + unsigned int event; + + if (list_empty(&dev->smi_clients)) + return; + + memset(fifo_in, 0x0, sizeof(fifo_in)); + + if (post_reset) { + event = KFD_SMI_EVENT_GPU_POST_RESET; + } else { + event = KFD_SMI_EVENT_GPU_PRE_RESET; + ++(dev->reset_seq_num); + } + + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x\n", event, + dev->reset_seq_num); + + add_event_to_kfifo(dev, event, fifo_in, len); +} + void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, uint32_t throttle_bitmask) { @@ -191,7 +221,7 @@ void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, if (list_empty(&dev->smi_clients)) return; - len = snprintf(fifo_in, 29, "%x %x:%llx\n", + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%llx\n", KFD_SMI_EVENT_THERMAL_THROTTLE, throttle_bitmask, atomic64_read(&adev->smu.throttle_int_counter)); @@ -218,7 +248,7 @@ void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid) if (!task_info.pid) return; - len = snprintf(fifo_in, 29, "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, + len = snprintf(fifo_in, sizeof(fifo_in), "%x %x:%s\n", KFD_SMI_EVENT_VMFAULT, task_info.pid, task_info.task_name); add_event_to_kfifo(dev, KFD_SMI_EVENT_VMFAULT, fifo_in, len); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h index 15537b2cccb5..b9b0438202e2 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.h @@ -27,5 +27,6 @@ int kfd_smi_event_open(struct kfd_dev *dev, uint32_t *fd); void kfd_smi_event_update_vmfault(struct kfd_dev *dev, uint16_t pasid); void kfd_smi_event_update_thermal_throttling(struct kfd_dev *dev, uint32_t throttle_bitmask); +void kfd_smi_event_update_gpu_reset(struct kfd_dev *dev, bool post_reset); #endif diff --git a/include/uapi/linux/kfd_ioctl.h b/include/uapi/linux/kfd_ioctl.h index cb1f963a84e0..8b7368bfbd84 100644 --- a/include/uapi/linux/kfd_ioctl.h +++ b/include/uapi/linux/kfd_ioctl.h @@ -453,6 +453,8 @@ enum kfd_smi_event { KFD_SMI_EVENT_NONE = 0, /* not used */ KFD_SMI_EVENT_VMFAULT = 1, /* event start counting at 1 */ KFD_SMI_EVENT_THERMAL_THROTTLE = 2, + KFD_SMI_EVENT_GPU_PRE_RESET = 3, + KFD_SMI_EVENT_GPU_POST_RESET = 4, }; #define KFD_SMI_EVENT_MASK_FROM_INDEX(i) (1ULL << ((i) - 1)) -- cgit v1.2.3 From bbcd521e1495056e939a37d0ac996d963a5ac32d Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:37 -0400 Subject: drm/nouveau/kms: Fix some indenting in nouveau_dp_detect() Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-2-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 8a0f7994e1ae..ee778ddc95fa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -76,10 +76,10 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); NV_DEBUG(drm, "encoder: %dx%d\n", - nv_encoder->dcb->dpconf.link_nr, - nv_encoder->dcb->dpconf.link_bw); + nv_encoder->dcb->dpconf.link_nr, + nv_encoder->dcb->dpconf.link_bw); if (nv_encoder->dcb->dpconf.link_nr < nv_encoder->dp.link_nr) nv_encoder->dp.link_nr = nv_encoder->dcb->dpconf.link_nr; @@ -87,7 +87,7 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; NV_DEBUG(drm, "maximum: %dx%d\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); nouveau_dp_probe_oui(dev, aux, dpcd); -- cgit v1.2.3 From 6ba1193255ebf7eadf60f79c1555e507d0879ac3 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:38 -0400 Subject: drm/nouveau/kms/nv50-: Remove open-coded drm_dp_read_desc() Noticed this while going through our DP code - we use an open-coded version of drm_dp_read_desc() instead of just using the helper, so change that. This will also let us use quirks in the future if we end up needing them. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-3-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 3 ++- drivers/gpu/drm/nouveau/nouveau_dp.c | 30 +++++++++-------------------- drivers/gpu/drm/nouveau/nouveau_encoder.h | 4 +++- 3 files changed, 14 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7674025a4bfe..e12957e6faa7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -435,7 +435,8 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) switch (nv_encoder->dcb->type) { case DCB_OUTPUT_DP: - ret = nouveau_dp_detect(nv_encoder); + ret = nouveau_dp_detect(nouveau_connector(connector), + nv_encoder); if (ret == NOUVEAU_DP_MST) return NULL; else if (ret == NOUVEAU_DP_SST) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index ee778ddc95fa..c4e9c21d4dd2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,27 +36,9 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); -static void -nouveau_dp_probe_oui(struct drm_device *dev, struct nvkm_i2c_aux *aux, u8 *dpcd) -{ - struct nouveau_drm *drm = nouveau_drm(dev); - u8 buf[3]; - - if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) - return; - - if (!nvkm_rdaux(aux, DP_SINK_OUI, buf, 3)) - NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n", - buf[0], buf[1], buf[2]); - - if (!nvkm_rdaux(aux, DP_BRANCH_OUI, buf, 3)) - NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n", - buf[0], buf[1], buf[2]); - -} - int -nouveau_dp_detect(struct nouveau_encoder *nv_encoder) +nouveau_dp_detect(struct nouveau_connector *nv_connector, + struct nouveau_encoder *nv_encoder) { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); @@ -89,7 +71,13 @@ nouveau_dp_detect(struct nouveau_encoder *nv_encoder) NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - nouveau_dp_probe_oui(dev, aux, dpcd); + ret = drm_dp_read_desc(&nv_connector->aux, &nv_encoder->dp.desc, + drm_dp_is_branch(dpcd)); + if (ret) { + NV_ERROR(drm, "Failed to read DP descriptor on %s: %d\n", + nv_connector->base.name, ret); + return ret; + } ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst); if (ret == 1) diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index a72c412ac8b1..6424cdcb4913 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -33,6 +33,7 @@ #include #include "dispnv04/disp.h" struct nv50_head_atom; +struct nouveau_connector; #define NV_DPMS_CLEARED 0x80 @@ -64,6 +65,7 @@ struct nouveau_encoder { struct nv50_mstm *mstm; int link_nr; int link_bw; + struct drm_dp_desc desc; } dp; }; @@ -104,7 +106,7 @@ enum nouveau_dp_status { NOUVEAU_DP_MST, }; -int nouveau_dp_detect(struct nouveau_encoder *); +int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, struct nouveau_encoder *, const struct drm_display_mode *, -- cgit v1.2.3 From 73596dbfde6c827756bd696599989d200f04bf69 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:39 -0400 Subject: drm/nouveau/kms/nv50-: Just use drm_dp_dpcd_read() in nouveau_dp.c Since this actually logs accesses, we should probably always be using this imho… Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-4-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index c4e9c21d4dd2..8db9216d52c6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -42,16 +42,12 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct nvkm_i2c_aux *aux; - u8 dpcd[8]; + struct drm_dp_aux *aux = &nv_connector->aux; + u8 dpcd[DP_RECEIVER_CAP_SIZE]; int ret; - aux = nv_encoder->aux; - if (!aux) - return -ENODEV; - - ret = nvkm_rdaux(aux, DP_DPCD_REV, dpcd, sizeof(dpcd)); - if (ret) + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret != sizeof(dpcd)) return ret; nv_encoder->dp.link_bw = 27000 * dpcd[1]; -- cgit v1.2.3 From 57940402b58b0efe70fd276a7a0fbc394bdb587c Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:40 -0400 Subject: drm/nouveau/kms/nv50-: Use macros for DP registers in nouveau_dp.c No functional changes. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-5-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 8db9216d52c6..4030806e3522 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -50,11 +50,13 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, if (ret != sizeof(dpcd)) return ret; - nv_encoder->dp.link_bw = 27000 * dpcd[1]; - nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; + nv_encoder->dp.link_bw = 27000 * dpcd[DP_MAX_LINK_RATE]; + nv_encoder->dp.link_nr = + dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK; NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", - nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); + nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, + dpcd[DP_DPCD_REV]); NV_DEBUG(drm, "encoder: %dx%d\n", nv_encoder->dcb->dpconf.link_nr, nv_encoder->dcb->dpconf.link_bw); -- cgit v1.2.3 From 254e7e3bfcfcae829e120e53e21050e2fe5ce1d7 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:41 -0400 Subject: drm/nouveau/kms: Don't clear DP_MST_CTRL DPCD in nv50_mstm_new() Since commit fa3cdf8d0b09 ("drm/nouveau: Reset MST branching unit before enabling") we've been clearing DP_MST_CTRL before we start enabling MST. Since then clearing DP_MST_CTRL in nv50_mstm_new() has been unnecessary and redundant, so let's remove it. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-6-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index e7874877da85..c4d138f0ca05 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1535,17 +1535,6 @@ nv50_mstm_new(struct nouveau_encoder *outp, struct drm_dp_aux *aux, int aux_max, struct drm_device *dev = outp->base.base.dev; struct nv50_mstm *mstm; int ret; - u8 dpcd; - - /* This is a workaround for some monitors not functioning - * correctly in MST mode on initial module load. I think - * some bad interaction with the VBIOS may be responsible. - * - * A good ol' off and on again seems to work here ;) - */ - ret = drm_dp_dpcd_readb(aux, DP_DPCD_REV, &dpcd); - if (ret >= 0 && dpcd >= 0x12) - drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0); if (!(mstm = *pmstm = kzalloc(sizeof(*mstm), GFP_KERNEL))) return -ENOMEM; -- cgit v1.2.3 From 09838c4efe9afb6fefa889d92c3571d49029af26 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:42 -0400 Subject: drm/nouveau/kms: Search for encoders' connectors properly While the way we find the associated connector for an encoder is just fine for legacy modesetting, it's not correct for nv50+ since that uses atomic modesetting. For reference, see the drm_encoder kdocs. Fix this by removing nouveau_encoder_connector_get(), and replacing it with nv04_encoder_get_connector(), nv50_outp_get_old_connector(), and nv50_outp_get_new_connector(). v2: * Don't line-wrap for_each_(old|new)_connector_in_state in nv50_outp_get_(old|new)_connector() - sravn v3: * Fix potential uninitialized usage of nv_connector (needs to be initialized to NULL at the start). Thanks kernel test robot! v4: * Actually fix uninitialized nv_connector usage in nv50_audio_component_get_eld(). The previous fix wouldn't have worked since we would have started out with nv_connector == NULL, but wouldn't clear it after a single drm_for_each_encoder() iteration. Thanks again Kernel bot! Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-7-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv04/dac.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/dfp.c | 7 ++- drivers/gpu/drm/nouveau/dispnv04/disp.c | 18 ++++++ drivers/gpu/drm/nouveau/dispnv04/disp.h | 4 ++ drivers/gpu/drm/nouveau/dispnv04/tvnv04.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 88 +++++++++++++++++++++++------ drivers/gpu/drm/nouveau/nouveau_connector.c | 14 ----- drivers/gpu/drm/nouveau/nouveau_encoder.h | 6 +- 9 files changed, 105 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv04/dac.c b/drivers/gpu/drm/nouveau/dispnv04/dac.c index ffdd447d8706..22d10f328559 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dac.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dac.c @@ -419,7 +419,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/dfp.c b/drivers/gpu/drm/nouveau/dispnv04/dfp.c index f9f4482c79b5..42687ea2a4ca 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/dfp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/dfp.c @@ -184,7 +184,8 @@ static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *adjusted_mode) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); + struct nouveau_connector *nv_connector = + nv04_encoder_get_connector(nv_encoder); if (!nv_connector->native_mode || nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || @@ -478,7 +479,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -591,7 +592,7 @@ static void nv04_dfp_restore(struct drm_encoder *encoder) if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS) { struct nouveau_connector *connector = - nouveau_encoder_connector_get(nv_encoder); + nv04_encoder_get_connector(nv_encoder); if (connector && connector->native_mode) call_lvds_script(dev, nv_encoder->dcb, head, diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 900ab69df7e8..3f046b917c85 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -35,6 +35,24 @@ #include +struct nouveau_connector * +nv04_encoder_get_connector(struct nouveau_encoder *encoder) +{ + struct drm_device *dev = to_drm_encoder(encoder)->dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + struct nouveau_connector *nv_connector = NULL; + + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->encoder == to_drm_encoder(encoder)) + nv_connector = nouveau_connector(connector); + } + drm_connector_list_iter_end(&conn_iter); + + return nv_connector; +} + static void nv04_display_fini(struct drm_device *dev, bool suspend) { diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h index 495d3284e876..5ace5e906949 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.h +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h @@ -6,6 +6,8 @@ #include "nouveau_display.h" +struct nouveau_encoder; + enum nv04_fp_display_regs { FP_DISPLAY_END, FP_TOTAL, @@ -93,6 +95,8 @@ nv04_display(struct drm_device *dev) /* nv04_display.c */ int nv04_display_create(struct drm_device *); +struct nouveau_connector * +nv04_encoder_get_connector(struct nouveau_encoder *nv_encoder); /* nv04_crtc.c */ int nv04_crtc_create(struct drm_device *, int index); diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c index b701a4d8fe76..3ba7b59580d5 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv04.c @@ -172,7 +172,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 3a9489ed6544..be28e7bd7490 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -599,7 +599,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", - nouveau_encoder_connector_get(nv_encoder)->base.name, + nv04_encoder_get_connector(nv_encoder)->base.name, nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index c4d138f0ca05..255a281249bc 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -411,6 +411,40 @@ nv50_outp_atomic_check(struct drm_encoder *encoder, return 0; } +struct nouveau_connector * +nv50_outp_get_new_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *connector_state; + struct drm_encoder *encoder = to_drm_encoder(outp); + int i; + + for_each_new_connector_in_state(state, connector, connector_state, i) { + if (connector_state->best_encoder == encoder) + return nouveau_connector(connector); + } + + return NULL; +} + +struct nouveau_connector * +nv50_outp_get_old_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *connector_state; + struct drm_encoder *encoder = to_drm_encoder(outp); + int i; + + for_each_old_connector_in_state(state, connector, connector_state, i) { + if (connector_state->best_encoder == encoder) + return nouveau_connector(connector); + } + + return NULL; +} + /****************************************************************************** * DAC *****************************************************************************/ @@ -552,16 +586,31 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, struct nouveau_drm *drm = nouveau_drm(drm_dev); struct drm_encoder *encoder; struct nouveau_encoder *nv_encoder; - struct nouveau_connector *nv_connector; + struct drm_connector *connector; struct nouveau_crtc *nv_crtc; + struct drm_connector_list_iter conn_iter; int ret = 0; *enabled = false; + drm_for_each_encoder(encoder, drm->dev) { + struct nouveau_connector *nv_connector = NULL; + nv_encoder = nouveau_encoder(encoder); - nv_connector = nouveau_encoder_connector_get(nv_encoder); + + drm_connector_list_iter_begin(drm_dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->state->best_encoder == encoder) { + nv_connector = nouveau_connector(connector); + break; + } + } + drm_connector_list_iter_end(&conn_iter); + if (!nv_connector) + continue; + nv_crtc = nouveau_crtc(encoder->crtc); - if (!nv_connector || !nv_crtc || nv_encoder->or != port || + if (!nv_crtc || nv_encoder->or != port || nv_crtc->index != dev_id) continue; *enabled = nv_encoder->audio; @@ -572,6 +621,7 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id, } break; } + return ret; } @@ -665,7 +715,8 @@ nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) } static void -nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_audio_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, + struct drm_display_mode *mode) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -686,7 +737,7 @@ nv50_audio_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) (0x0100 << nv_crtc->index), }; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); if (!drm_detect_monitor_audio(nv_connector->edid)) return; @@ -723,7 +774,8 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) } static void -nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) +nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, + struct drm_display_mode *mode) { struct nouveau_drm *drm = nouveau_drm(encoder->dev); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -752,7 +804,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) int ret; int size; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); if (!drm_detect_hdmi_monitor(nv_connector->edid)) return; @@ -798,7 +850,7 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode) + args.pwr.vendor_infoframe_length; nvif_mthd(&disp->disp->object, 0, &args, size); - nv50_audio_enable(encoder, mode); + nv50_audio_enable(encoder, state, mode); /* If SCDC is supported by the downstream monitor, update * divider / scrambling settings to what we programmed above. @@ -1573,7 +1625,8 @@ nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head, } static void -nv50_sor_disable(struct drm_encoder *encoder) +nv50_sor_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); @@ -1601,7 +1654,8 @@ nv50_sor_disable(struct drm_encoder *encoder) } static void -nv50_sor_enable(struct drm_encoder *encoder) +nv50_sor_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); @@ -1625,7 +1679,7 @@ nv50_sor_enable(struct drm_encoder *encoder) u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM; u8 depth = NV837D_SOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT; - nv_connector = nouveau_encoder_connector_get(nv_encoder); + nv_connector = nv50_outp_get_new_connector(nv_encoder, state); nv_encoder->crtc = encoder->crtc; if ((disp->disp->object.oclass == GT214_DISP || @@ -1652,7 +1706,7 @@ nv50_sor_enable(struct drm_encoder *encoder) proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B; } - nv50_hdmi_enable(&nv_encoder->base.base, mode); + nv50_hdmi_enable(&nv_encoder->base.base, state, mode); break; case DCB_OUTPUT_LVDS: proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM; @@ -1693,7 +1747,7 @@ nv50_sor_enable(struct drm_encoder *encoder) else proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B; - nv50_audio_enable(encoder, mode); + nv50_audio_enable(encoder, state, mode); break; default: BUG(); @@ -1706,8 +1760,8 @@ nv50_sor_enable(struct drm_encoder *encoder) static const struct drm_encoder_helper_funcs nv50_sor_help = { .atomic_check = nv50_outp_atomic_check, - .enable = nv50_sor_enable, - .disable = nv50_sor_disable, + .atomic_enable = nv50_sor_enable, + .atomic_disable = nv50_sor_disable, }; static void @@ -2066,7 +2120,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) outp->clr.mask, outp->set.mask); if (outp->clr.mask) { - help->disable(encoder); + help->atomic_disable(encoder, state); interlock[NV50_DISP_INTERLOCK_CORE] |= 1; if (outp->flush_disable) { nv50_disp_atomic_commit_wndw(state, interlock); @@ -2105,7 +2159,7 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state) outp->set.mask, outp->clr.mask); if (outp->set.mask) { - help->enable(encoder); + help->atomic_enable(encoder, state); interlock[NV50_DISP_INTERLOCK_CORE] = 1; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index e12957e6faa7..1d5696c39792 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -391,20 +391,6 @@ find_encoder(struct drm_connector *connector, int type) return NULL; } -struct nouveau_connector * -nouveau_encoder_connector_get(struct nouveau_encoder *encoder) -{ - struct drm_device *dev = to_drm_encoder(encoder)->dev; - struct drm_connector *drm_connector; - - list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head) { - if (drm_connector->encoder == to_drm_encoder(encoder)) - return nouveau_connector(drm_connector); - } - - return NULL; -} - static void nouveau_connector_destroy(struct drm_connector *connector) { diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index 6424cdcb4913..b0e1dad2367d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -113,7 +113,11 @@ enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, unsigned *clock); struct nouveau_connector * -nouveau_encoder_connector_get(struct nouveau_encoder *encoder); +nv50_outp_get_new_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state); +struct nouveau_connector * +nv50_outp_get_old_connector(struct nouveau_encoder *outp, + struct drm_atomic_state *state); int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow); void nv50_mstm_remove(struct nv50_mstm *); -- cgit v1.2.3 From 4944245cebb9daaf740d388fb61e2a824befbdb5 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:43 -0400 Subject: drm/nouveau/kms/nv50-: Use drm_dp_dpcd_(readb|writeb)() in nv50_sor_disable() Just use drm_dp_dpcd_(readb|writeb)() so we get automatic DPCD logging Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-8-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 255a281249bc..612d98fa0a2d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1630,19 +1630,22 @@ nv50_sor_disable(struct drm_encoder *encoder, { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); + struct nouveau_connector *nv_connector = + nv50_outp_get_old_connector(nv_encoder, state); nv_encoder->crtc = NULL; if (nv_crtc) { - struct nvkm_i2c_aux *aux = nv_encoder->aux; + struct drm_dp_aux *aux = &nv_connector->aux; u8 pwr; - if (aux) { - int ret = nvkm_rdaux(aux, DP_SET_POWER, &pwr, 1); + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { + int ret = drm_dp_dpcd_readb(aux, DP_SET_POWER, &pwr); + if (ret == 0) { pwr &= ~DP_SET_POWER_MASK; pwr |= DP_SET_POWER_D3; - nvkm_wraux(aux, DP_SET_POWER, &pwr, 1); + drm_dp_dpcd_writeb(aux, DP_SET_POWER, pwr); } } -- cgit v1.2.3 From a0922278f83eae085fdf73d06f71bbdfb9d6789e Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:44 -0400 Subject: drm/nouveau/kms/nv50-: Refactor and cleanup DP HPD handling First some backstory here: Currently, we keep track of whether or not we've enabled MST or not by trying to piggy-back off the MST helpers. This means that in order to check whether MST is enabled or not, we actually need to grab drm_dp_mst_topology_mgr.lock. Back when I originally wrote this, I did this piggy-backing with the intention that I'd eventually be teaching our MST helpers how to recover when an MST device has stopped responding, which in turn would require the MST helpers having a way of disabling MST independently of the driver. Note that this was before I reworked locking in the MST helpers, so at the time we were sticking random things under &mgr->lock - which grabbing this lock was meant to protect against. This never came to fruition because doing such a reset safely turned out to be a lot more painful and impossible then it sounds, and also just risks us working around issues with our MST handlers that should be properly fixed instead. Even if it did though, simply calling drm_dp_mst_topology_mgr_set_mst() from the MST helpers (with the exception of when we're tearing down our MST managers, that's always OK) wouldn't have been a bad idea, since drivers like nouveau and i915 need to do their own book keeping immediately after disabling MST. So-implementing that would likely require adding a hook for helper-triggered MST disables anyway. So, fast forward to now - we want to start adding support for all of the miscellaneous bits of the DP protocol (for both SST and MST) we're missing before moving on to supporting more complicated features like supporting different BPP values on MST, DSC, etc. Since many of these features only exist on SST and make use of DP HPD IRQs, we want to be able to atomically check whether we're servicing an MST IRQ or SST IRQ in nouveau_connector_hotplug(). Currently we literally don't do this at all, and just handle any kind of possible DP IRQ we could get including ESIs - even if MST isn't actually enabled. This would be very complicated and difficult to fix if we need to hold &mgr->lock while handling SST IRQs to ensure that the MST topology state doesn't change under us. What we really want here is to do our own tracking of whether MST is enabled or not, similar to drivers like i915, and define our own locking order to decomplicate things and avoid hitting locking issues in the future. So, let's do this by refactoring our MST probing/enabling code to use our own MST bookkeeping, along with adding a lock for protecting DP state that needs to be checked outside of our connector probing functions. While we're at it, we also remove a bunch of unneeded steps we perform when probing/enabling MST: * Enabling bits in MSTM_CTRL before calling drm_dp_mst_topology_mgr_set_mst(). I don't think these ever actually did anything, since the nvif methods for enabling MST don't actually do anything DPCD related and merely indicate to nvkm that we've turned on MST. * Checking the MSTM_CTRL bit is intact when checking the state of an enabled MST topology in nv50_mstm_detect(). I just added this to be safe originally, but now that we try reading the DPCD when probing DP connectors it shouldn't be needed as that will abort our hotplug probing if the device was removed well before we start checking for MST.. * All of the duplicate DPCD version checks. This leaves us with much nicer looking code, a much more sensible locking scheme, and an easy way of checking whether MST is enabled or not for handling DP HPD IRQs. v2: * Get rid of accidental newlines v4: * Fix uninitialized usage of mstm in nv50_mstm_detect() - thanks kernel bot! Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-9-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv04/disp.c | 6 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 192 +++++++++++++--------------- drivers/gpu/drm/nouveau/nouveau_connector.c | 14 +- drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/nouveau/nouveau_display.h | 2 +- drivers/gpu/drm/nouveau/nouveau_dp.c | 132 ++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_encoder.h | 33 ++++- 7 files changed, 244 insertions(+), 137 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 3f046b917c85..3ee836dc5058 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -54,8 +54,9 @@ nv04_encoder_get_connector(struct nouveau_encoder *encoder) } static void -nv04_display_fini(struct drm_device *dev, bool suspend) +nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend) { + struct nouveau_drm *drm = nouveau_drm(dev); struct nv04_display *disp = nv04_display(dev); struct drm_crtc *crtc; @@ -67,6 +68,9 @@ nv04_display_fini(struct drm_device *dev, bool suspend) if (nv_two_heads(dev)) NVWriteCRTC(dev, 1, NV_PCRTC_INTR_EN_0, 0); + if (!runtime) + cancel_work_sync(&drm->hpd_work); + if (!suspend) return; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 612d98fa0a2d..8e1effb10425 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -879,16 +879,6 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_atomic_state *state, #define nv50_mstc(p) container_of((p), struct nv50_mstc, connector) #define nv50_msto(p) container_of((p), struct nv50_msto, encoder) -struct nv50_mstm { - struct nouveau_encoder *outp; - - struct drm_dp_mst_topology_mgr mgr; - - bool modified; - bool disabled; - int links; -}; - struct nv50_mstc { struct nv50_mstm *mstm; struct drm_dp_mst_port *port; @@ -1417,41 +1407,51 @@ nv50_mstm = { .add_connector = nv50_mstm_add_connector, }; -void -nv50_mstm_service(struct nv50_mstm *mstm) +bool +nv50_mstm_service(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector, + struct nv50_mstm *mstm) { - struct drm_dp_aux *aux = mstm ? mstm->mgr.aux : NULL; - bool handled = true; - int ret; + struct drm_dp_aux *aux = &nv_connector->aux; + bool handled = true, ret = true; + int rc; u8 esi[8] = {}; - if (!aux) - return; - while (handled) { - ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8); - if (ret != 8) { - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); - return; + rc = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8); + if (rc != 8) { + ret = false; + break; } drm_dp_mst_hpd_irq(&mstm->mgr, esi, &handled); if (!handled) break; - drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], 3); + rc = drm_dp_dpcd_write(aux, DP_SINK_COUNT_ESI + 1, &esi[1], + 3); + if (rc != 3) { + ret = false; + break; + } } + + if (!ret) + NV_DEBUG(drm, "Failed to handle ESI on %s: %d\n", + nv_connector->base.name, rc); + + return ret; } void nv50_mstm_remove(struct nv50_mstm *mstm) { - if (mstm) - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); + mstm->is_mst = false; + drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); } static int -nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state) +nv50_mstm_enable(struct nv50_mstm *mstm, int state) { struct nouveau_encoder *outp = mstm->outp; struct { @@ -1466,106 +1466,85 @@ nv50_mstm_enable(struct nv50_mstm *mstm, u8 dpcd, int state) }; struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev); struct nvif_object *disp = &drm->display->disp.object; - int ret; - - if (dpcd >= 0x12) { - /* Even if we're enabling MST, start with disabling the - * branching unit to clear any sink-side MST topology state - * that wasn't set by us - */ - ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, 0); - if (ret < 0) - return ret; - - if (state) { - /* Now, start initializing */ - ret = drm_dp_dpcd_writeb(mstm->mgr.aux, DP_MSTM_CTRL, - DP_MST_EN); - if (ret < 0) - return ret; - } - } return nvif_mthd(disp, 0, &args, sizeof(args)); } int -nv50_mstm_detect(struct nv50_mstm *mstm, u8 dpcd[8], int allow) +nv50_mstm_detect(struct nouveau_encoder *outp) { + struct nv50_mstm *mstm = outp->dp.mstm; struct drm_dp_aux *aux; int ret; - bool old_state, new_state; - u8 mstm_ctrl; - if (!mstm) + if (!mstm || !mstm->can_mst) return 0; - mutex_lock(&mstm->mgr.lock); - - old_state = mstm->mgr.mst_state; - new_state = old_state; aux = mstm->mgr.aux; - if (old_state) { - /* Just check that the MST hub is still as we expect it */ - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CTRL, &mstm_ctrl); - if (ret < 0 || !(mstm_ctrl & DP_MST_EN)) { - DRM_DEBUG_KMS("Hub gone, disabling MST topology\n"); - new_state = false; - } - } else if (dpcd[0] >= 0x12) { - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &dpcd[1]); - if (ret < 0) - goto probe_error; - - if (!(dpcd[1] & DP_MST_CAP)) - dpcd[0] = 0x11; - else - new_state = allow; - } - - if (new_state == old_state) { - mutex_unlock(&mstm->mgr.lock); - return new_state; - } - - ret = nv50_mstm_enable(mstm, dpcd[0], new_state); - if (ret) - goto probe_error; - - mutex_unlock(&mstm->mgr.lock); + /* Clear any leftover MST state we didn't set ourselves by first + * disabling MST if it was already enabled + */ + ret = drm_dp_dpcd_writeb(aux, DP_MSTM_CTRL, 0); + if (ret < 0) + return ret; - ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, new_state); + /* And start enabling */ + ret = nv50_mstm_enable(mstm, true); if (ret) - return nv50_mstm_enable(mstm, dpcd[0], 0); + return ret; - return new_state; + ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, true); + if (ret) { + nv50_mstm_enable(mstm, false); + return ret; + } -probe_error: - mutex_unlock(&mstm->mgr.lock); - return ret; + mstm->is_mst = true; + return 1; } static void -nv50_mstm_fini(struct nv50_mstm *mstm) +nv50_mstm_fini(struct nouveau_encoder *outp) { - if (mstm && mstm->mgr.mst_state) + struct nv50_mstm *mstm = outp->dp.mstm; + + if (!mstm) + return; + + /* Don't change the MST state of this connector until we've finished + * resuming, since we can't safely grab hpd_irq_lock in our resume + * path to protect mstm->is_mst without potentially deadlocking + */ + mutex_lock(&outp->dp.hpd_irq_lock); + mstm->suspended = true; + mutex_unlock(&outp->dp.hpd_irq_lock); + + if (mstm->is_mst) drm_dp_mst_topology_mgr_suspend(&mstm->mgr); } static void -nv50_mstm_init(struct nv50_mstm *mstm, bool runtime) +nv50_mstm_init(struct nouveau_encoder *outp, bool runtime) { - int ret; + struct nv50_mstm *mstm = outp->dp.mstm; + int ret = 0; - if (!mstm || !mstm->mgr.mst_state) + if (!mstm) return; - ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr, !runtime); - if (ret == -1) { - drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false); - drm_kms_helper_hotplug_event(mstm->mgr.dev); + if (mstm->is_mst) { + ret = drm_dp_mst_topology_mgr_resume(&mstm->mgr, !runtime); + if (ret == -1) + nv50_mstm_remove(mstm); } + + mutex_lock(&outp->dp.hpd_irq_lock); + mstm->suspended = false; + mutex_unlock(&outp->dp.hpd_irq_lock); + + if (ret == -1) + drm_kms_helper_hotplug_event(mstm->mgr.dev); } static void @@ -1773,6 +1752,10 @@ nv50_sor_destroy(struct drm_encoder *encoder) struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); nv50_mstm_del(&nv_encoder->dp.mstm); drm_encoder_cleanup(encoder); + + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) + mutex_destroy(&nv_encoder->dp.hpd_irq_lock); + kfree(encoder); } @@ -1832,6 +1815,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) struct nvkm_i2c_aux *aux = nvkm_i2c_aux_find(i2c, dcbe->i2c_index); + mutex_init(&nv_encoder->dp.hpd_irq_lock); + if (aux) { if (disp->disp->object.oclass < GF110_DISP) { /* HW has no support for address-only @@ -2530,9 +2515,9 @@ nv50_disp_func = { *****************************************************************************/ static void -nv50_display_fini(struct drm_device *dev, bool suspend) +nv50_display_fini(struct drm_device *dev, bool runtime, bool suspend) { - struct nouveau_encoder *nv_encoder; + struct nouveau_drm *drm = nouveau_drm(dev); struct drm_encoder *encoder; struct drm_plane *plane; @@ -2544,11 +2529,12 @@ nv50_display_fini(struct drm_device *dev, bool suspend) } list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { - if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { - nv_encoder = nouveau_encoder(encoder); - nv50_mstm_fini(nv_encoder->dp.mstm); - } + if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) + nv50_mstm_fini(nouveau_encoder(encoder)); } + + if (!runtime) + cancel_work_sync(&drm->hpd_work); } static int @@ -2565,7 +2551,7 @@ nv50_display_init(struct drm_device *dev, bool resume, bool runtime) if (encoder->encoder_type != DRM_MODE_ENCODER_DPMST) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv50_mstm_init(nv_encoder->dp.mstm, runtime); + nv50_mstm_init(nv_encoder, runtime); } } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1d5696c39792..b90591114faa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1143,19 +1143,15 @@ nouveau_connector_hotplug(struct nvif_notify *notify) struct nouveau_connector *nv_connector = container_of(notify, typeof(*nv_connector), hpd); struct drm_connector *connector = &nv_connector->base; - struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct drm_device *dev = connector->dev; + struct nouveau_drm *drm = nouveau_drm(dev); const struct nvif_notify_conn_rep_v0 *rep = notify->data; const char *name = connector->name; - struct nouveau_encoder *nv_encoder; int ret; bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { - NV_DEBUG(drm, "service %s\n", name); - drm_dp_cec_irq(&nv_connector->aux); - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) - nv50_mstm_service(nv_encoder->dp.mstm); - + nouveau_dp_irq(drm, nv_connector); return NVIF_NOTIFY_KEEP; } @@ -1181,10 +1177,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) if (!plugged) drm_dp_cec_unset_edid(&nv_connector->aux); NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); - if ((nv_encoder = find_encoder(connector, DCB_OUTPUT_DP))) { - if (!plugged) - nv50_mstm_remove(nv_encoder->dp.mstm); - } drm_helper_hpd_irq_event(connector->dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 5f31b11ac2e7..13016769a194 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -569,7 +569,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime) cancel_work_sync(&drm->hpd_work); drm_kms_helper_poll_disable(dev); - disp->fini(dev, suspend); + disp->fini(dev, runtime, suspend); } static void diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 6e0d900441d6..76ba93e01aff 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -18,7 +18,7 @@ struct nouveau_display { void *priv; void (*dtor)(struct drm_device *); int (*init)(struct drm_device *, bool resume, bool runtime); - void (*fini)(struct drm_device *, bool suspend); + void (*fini)(struct drm_device *, bool suspend, bool runtime); struct nvif_disp disp; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 4030806e3522..032afc73e2a3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,19 +36,89 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); +static enum drm_connector_status +nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, + struct nouveau_encoder *outp) +{ + struct drm_dp_aux *aux = &nv_connector->aux; + struct nv50_mstm *mstm = NULL; + int ret; + u8 *dpcd = outp->dp.dpcd; + u8 tmp; + + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { + ret = drm_dp_read_desc(aux, &outp->dp.desc, + drm_dp_is_branch(dpcd)); + if (ret < 0) + return connector_status_disconnected; + } else { + return connector_status_disconnected; + } + + if (nouveau_mst) + mstm = outp->dp.mstm; + + if (mstm) { + if (dpcd[DP_DPCD_REV] >= DP_DPCD_REV_12) { + ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &tmp); + if (ret < 0) + return connector_status_disconnected; + + mstm->can_mst = !!(tmp & DP_MST_CAP); + } else { + mstm->can_mst = false; + } + } + + return connector_status_connected; +} + int nouveau_dp_detect(struct nouveau_connector *nv_connector, struct nouveau_encoder *nv_encoder) { struct drm_device *dev = nv_encoder->base.base.dev; struct nouveau_drm *drm = nouveau_drm(dev); - struct drm_dp_aux *aux = &nv_connector->aux; - u8 dpcd[DP_RECEIVER_CAP_SIZE]; - int ret; + struct drm_connector *connector = &nv_connector->base; + struct nv50_mstm *mstm = nv_encoder->dp.mstm; + enum drm_connector_status status; + u8 *dpcd = nv_encoder->dp.dpcd; + int ret = NOUVEAU_DP_NONE; + + /* If we've already read the DPCD on an eDP device, we don't need to + * reread it as it won't change + */ + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && + dpcd[DP_DPCD_REV] != 0) + return NOUVEAU_DP_SST; - ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); - if (ret != sizeof(dpcd)) - return ret; + mutex_lock(&nv_encoder->dp.hpd_irq_lock); + if (mstm) { + /* If we're not ready to handle MST state changes yet, just + * report the last status of the connector. We'll reprobe it + * once we've resumed. + */ + if (mstm->suspended) { + if (mstm->is_mst) + ret = NOUVEAU_DP_MST; + else if (connector->status == + connector_status_connected) + ret = NOUVEAU_DP_SST; + + goto out; + } + } + + status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder); + if (status == connector_status_disconnected) + goto out; + + /* If we're in MST mode, we're done here */ + if (mstm && mstm->can_mst && mstm->is_mst) { + ret = NOUVEAU_DP_MST; + goto out; + } nv_encoder->dp.link_bw = 27000 * dpcd[DP_MAX_LINK_RATE]; nv_encoder->dp.link_nr = @@ -69,22 +139,50 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, NV_DEBUG(drm, "maximum: %dx%d\n", nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); - ret = drm_dp_read_desc(&nv_connector->aux, &nv_encoder->dp.desc, - drm_dp_is_branch(dpcd)); - if (ret) { - NV_ERROR(drm, "Failed to read DP descriptor on %s: %d\n", - nv_connector->base.name, ret); - return ret; + if (mstm && mstm->can_mst) { + ret = nv50_mstm_detect(nv_encoder); + if (ret == 1) { + ret = NOUVEAU_DP_MST; + goto out; + } else if (ret != 0) { + goto out; + } } + ret = NOUVEAU_DP_SST; - ret = nv50_mstm_detect(nv_encoder->dp.mstm, dpcd, nouveau_mst); - if (ret == 1) - return NOUVEAU_DP_MST; - if (ret == 0) - return NOUVEAU_DP_SST; +out: + if (mstm && !mstm->suspended && ret != NOUVEAU_DP_MST) + nv50_mstm_remove(mstm); + + mutex_unlock(&nv_encoder->dp.hpd_irq_lock); return ret; } +void nouveau_dp_irq(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector) +{ + struct drm_connector *connector = &nv_connector->base; + struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); + struct nv50_mstm *mstm; + + if (!outp) + return; + + mstm = outp->dp.mstm; + NV_DEBUG(drm, "service %s\n", connector->name); + + mutex_lock(&outp->dp.hpd_irq_lock); + + if (mstm && mstm->is_mst) { + if (!nv50_mstm_service(drm, nv_connector, mstm)) + schedule_work(&drm->hpd_work); + } else { + drm_dp_cec_irq(&nv_connector->aux); + } + + mutex_unlock(&outp->dp.hpd_irq_lock); +} + /* TODO: * - Use the minimum possible BPC here, once we add support for the max bpc * property. diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index b0e1dad2367d..eef4643f5f98 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -65,6 +65,13 @@ struct nouveau_encoder { struct nv50_mstm *mstm; int link_nr; int link_bw; + + /* Protects DP state that needs to be accessed outside + * connector reprobing contexts + */ + struct mutex hpd_irq_lock; + + u8 dpcd[DP_RECEIVER_CAP_SIZE]; struct drm_dp_desc desc; } dp; }; @@ -79,6 +86,21 @@ struct nouveau_encoder { struct nv50_head_atom *, u8 proto, u8 depth); }; +struct nv50_mstm { + struct nouveau_encoder *outp; + + struct drm_dp_mst_topology_mgr mgr; + + /* Protected under nouveau_encoder->dp.hpd_irq_lock */ + bool can_mst; + bool is_mst; + bool suspended; + + bool modified; + bool disabled; + int links; +}; + struct nouveau_encoder * find_encoder(struct drm_connector *connector, int type); @@ -102,11 +124,14 @@ get_slave_funcs(struct drm_encoder *enc) /* nouveau_dp.c */ enum nouveau_dp_status { + NOUVEAU_DP_NONE, NOUVEAU_DP_SST, NOUVEAU_DP_MST, }; int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *); +void nouveau_dp_irq(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector); enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *, struct nouveau_encoder *, const struct drm_display_mode *, @@ -119,7 +144,9 @@ struct nouveau_connector * nv50_outp_get_old_connector(struct nouveau_encoder *outp, struct drm_atomic_state *state); -int nv50_mstm_detect(struct nv50_mstm *, u8 dpcd[8], int allow); -void nv50_mstm_remove(struct nv50_mstm *); -void nv50_mstm_service(struct nv50_mstm *); +int nv50_mstm_detect(struct nouveau_encoder *encoder); +void nv50_mstm_remove(struct nv50_mstm *mstm); +bool nv50_mstm_service(struct nouveau_drm *drm, + struct nouveau_connector *nv_connector, + struct nv50_mstm *mstm); #endif /* __NOUVEAU_ENCODER_H__ */ -- cgit v1.2.3 From 4b4659128e634ce65dc02acf297d623f5bc97497 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:45 -0400 Subject: drm/i915/dp: Extract drm_dp_read_mst_cap() Just a tiny drive-by cleanup, we can consolidate i915's code for checking for MST support into a helper to be shared across drivers. v5: * Drop !!() * Move drm_dp_has_mst() out of header * Change name from drm_dp_has_mst() to drm_dp_read_mst_cap() Signed-off-by: Lyude Paul Reviewed-by: Sean Paul Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-10-lyude@redhat.com --- drivers/gpu/drm/drm_dp_mst_topology.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 18 ++---------------- include/drm/drm_dp_mst_helper.h | 3 +-- 3 files changed, 25 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index b23cb2fec3f3..61755c26fac0 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -3486,6 +3486,28 @@ static int drm_dp_get_vc_payload_bw(u8 dp_link_bw, u8 dp_link_count) return dp_link_bw * dp_link_count / 2; } +/** + * drm_dp_read_mst_cap() - check whether or not a sink supports MST + * @aux: The DP AUX channel to use + * @dpcd: A cached copy of the DPCD capabilities for this sink + * + * Returns: %True if the sink supports MST, %false otherwise + */ +bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 mstm_cap; + + if (dpcd[DP_DPCD_REV] < DP_DPCD_REV_12) + return false; + + if (drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &mstm_cap) != 1) + return false; + + return mstm_cap & DP_MST_CAP; +} +EXPORT_SYMBOL(drm_dp_read_mst_cap); + /** * drm_dp_mst_topology_mgr_set_mst() - Set the MST state for a topology manager * @mgr: manager to set state for diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 79c27f91f42c..4c7314b7a84e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4699,20 +4699,6 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return true; } -static bool -intel_dp_sink_can_mst(struct intel_dp *intel_dp) -{ - u8 mstm_cap; - - if (intel_dp->dpcd[DP_DPCD_REV] < 0x12) - return false; - - if (drm_dp_dpcd_readb(&intel_dp->aux, DP_MSTM_CAP, &mstm_cap) != 1) - return false; - - return mstm_cap & DP_MST_CAP; -} - static bool intel_dp_can_mst(struct intel_dp *intel_dp) { @@ -4720,7 +4706,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) return i915->params.enable_dp_mst && intel_dp->can_mst && - intel_dp_sink_can_mst(intel_dp); + drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); } static void @@ -4729,7 +4715,7 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) struct drm_i915_private *i915 = dp_to_i915(intel_dp); struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - bool sink_can_mst = intel_dp_sink_can_mst(intel_dp); + bool sink_can_mst = drm_dp_read_mst_cap(&intel_dp->aux, intel_dp->dpcd); drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n", diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 8b9eb4db3381..6ae5860d8644 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -728,10 +728,9 @@ int drm_dp_mst_topology_mgr_init(struct drm_dp_mst_topology_mgr *mgr, void drm_dp_mst_topology_mgr_destroy(struct drm_dp_mst_topology_mgr *mgr); - +bool drm_dp_read_mst_cap(struct drm_dp_aux *aux, const u8 dpcd[DP_RECEIVER_CAP_SIZE]); int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool mst_state); - int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handled); -- cgit v1.2.3 From 8b75e83e9c94dbf619cf2499ec85656eed9d0320 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:46 -0400 Subject: drm/nouveau/kms: Use new drm_dp_read_mst_cap() helper for checking MST caps Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-11-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 032afc73e2a3..a5934064a75e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -44,7 +44,6 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, struct nv50_mstm *mstm = NULL; int ret; u8 *dpcd = outp->dp.dpcd; - u8 tmp; ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { @@ -56,19 +55,10 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, return connector_status_disconnected; } - if (nouveau_mst) + if (nouveau_mst) { mstm = outp->dp.mstm; - - if (mstm) { - if (dpcd[DP_DPCD_REV] >= DP_DPCD_REV_12) { - ret = drm_dp_dpcd_readb(aux, DP_MSTM_CAP, &tmp); - if (ret < 0) - return connector_status_disconnected; - - mstm->can_mst = !!(tmp & DP_MST_CAP); - } else { - mstm->can_mst = false; - } + if (mstm) + mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } return connector_status_connected; -- cgit v1.2.3 From 02bb7fe2d3eacb5ca1cec597ad16eff93ae8d769 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:47 -0400 Subject: drm/nouveau/kms: Move drm_dp_cec_unset_edid() into nouveau_connector_detect() For whatever reason we currently unset the EDID for DP CEC support when responding to the connector being unplugged, instead of just doing it in nouveau_connector_detect() where we set the CEC EDID. This isn't really needed and could even potentially cause us to forget to unset the EDID if the connector is removed without a corresponding hpd event, so let's fix that. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-12-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index b90591114faa..4a29f691c08e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -633,10 +633,11 @@ detect_analog: conn_status = connector_status_connected; goto out; } - } out: + if (!nv_connector->edid) + drm_dp_cec_unset_edid(&nv_connector->aux); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); @@ -1174,8 +1175,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) return NVIF_NOTIFY_DROP; } - if (!plugged) - drm_dp_cec_unset_edid(&nv_connector->aux); NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); drm_helper_hpd_irq_event(connector->dev); -- cgit v1.2.3 From d297ce4b5d490eab60bede36bfd5da6fbcd416cf Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:48 -0400 Subject: drm/nouveau/kms: Only use hpd_work for reprobing in HPD paths Currently we perform both short IRQ handling for DP, and connector reprobing in the HPD IRQ handler. However since we need to grab connection_mutex in order to reprobe a connector, in theory we could accidentally block ourselves from handling any short IRQs until after a modeset completes if a connector hotplug happens to occur in parallel with a modeset. I haven't seen this actually happen yet, but since we're cleaning up nouveau's hotplug handling code anyway and we already have a hpd worker, we can simply fix this by only relying on the HPD worker to actually reprobe connectors when we receive a HPD IRQ. We also add a mask to nouveau_drm to keep track of which connectors are waiting to be reprobed in response to an HPD IRQ. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-13-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 42 +++++++---------- drivers/gpu/drm/nouveau/nouveau_connector.h | 1 + drivers/gpu/drm/nouveau/nouveau_display.c | 70 ++++++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_display.h | 1 + drivers/gpu/drm/nouveau/nouveau_dp.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drm.c | 4 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 2 + 7 files changed, 86 insertions(+), 36 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 4a29f691c08e..637e91594fbe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1138,6 +1138,20 @@ nouveau_connector_funcs_lvds = { .early_unregister = nouveau_connector_early_unregister, }; +void +nouveau_connector_hpd(struct drm_connector *connector) +{ + struct nouveau_drm *drm = nouveau_drm(connector->dev); + u32 mask = drm_connector_mask(connector); + + mutex_lock(&drm->hpd_lock); + if (!(drm->hpd_pending & mask)) { + drm->hpd_pending |= mask; + schedule_work(&drm->hpd_work); + } + mutex_unlock(&drm->hpd_lock); +} + static int nouveau_connector_hotplug(struct nvif_notify *notify) { @@ -1147,8 +1161,6 @@ nouveau_connector_hotplug(struct nvif_notify *notify) struct drm_device *dev = connector->dev; struct nouveau_drm *drm = nouveau_drm(dev); const struct nvif_notify_conn_rep_v0 *rep = notify->data; - const char *name = connector->name; - int ret; bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG); if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) { @@ -1156,31 +1168,9 @@ nouveau_connector_hotplug(struct nvif_notify *notify) return NVIF_NOTIFY_KEEP; } - ret = pm_runtime_get(drm->dev->dev); - if (ret == 0) { - /* We can't block here if there's a pending PM request - * running, as we'll deadlock nouveau_display_fini() when it - * calls nvif_put() on our nvif_notify struct. So, simply - * defer the hotplug event until the device finishes resuming - */ - NV_DEBUG(drm, "Deferring HPD on %s until runtime resume\n", - name); - schedule_work(&drm->hpd_work); - - pm_runtime_put_noidle(drm->dev->dev); - return NVIF_NOTIFY_KEEP; - } else if (ret != 1 && ret != -EACCES) { - NV_WARN(drm, "HPD on %s dropped due to RPM failure: %d\n", - name, ret); - return NVIF_NOTIFY_DROP; - } - - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); - - drm_helper_hpd_irq_event(connector->dev); + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name); + nouveau_connector_hpd(connector); - pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_autosuspend(drm->dev->dev); return NVIF_NOTIFY_KEEP; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index d6de5cb8e223..d0b859c4a80e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -187,6 +187,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) struct drm_connector * nouveau_connector_create(struct drm_device *, const struct dcb_output *); +void nouveau_connector_hpd(struct drm_connector *connector); extern int nouveau_tv_disable; extern int nouveau_ignorelid; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 13016769a194..bceb48a2dfca 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -457,16 +457,70 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = { } \ } while(0) +void +nouveau_display_hpd_resume(struct drm_device *dev) +{ + struct nouveau_drm *drm = nouveau_drm(dev); + + mutex_lock(&drm->hpd_lock); + drm->hpd_pending = ~0; + mutex_unlock(&drm->hpd_lock); + + schedule_work(&drm->hpd_work); +} + static void nouveau_display_hpd_work(struct work_struct *work) { struct nouveau_drm *drm = container_of(work, typeof(*drm), hpd_work); + struct drm_device *dev = drm->dev; + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + u32 pending; + bool changed = false; + + pm_runtime_get_sync(dev->dev); - pm_runtime_get_sync(drm->dev->dev); + mutex_lock(&drm->hpd_lock); + pending = drm->hpd_pending; + drm->hpd_pending = 0; + mutex_unlock(&drm->hpd_lock); - drm_helper_hpd_irq_event(drm->dev); + /* Nothing to do, exit early without updating the last busy counter */ + if (!pending) + goto noop; + + mutex_lock(&dev->mode_config.mutex); + drm_connector_list_iter_begin(dev, &conn_iter); + + nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) { + enum drm_connector_status old_status = connector->status; + u64 old_epoch_counter = connector->epoch_counter; + + if (!(pending & drm_connector_mask(connector))) + continue; + + connector->status = drm_helper_probe_detect(connector, NULL, + false); + if (old_epoch_counter == connector->epoch_counter) + continue; + + changed = true; + drm_dbg_kms(dev, "[CONNECTOR:%d:%s] status updated from %s to %s (epoch counter %llu->%llu)\n", + connector->base.id, connector->name, + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status), + old_epoch_counter, connector->epoch_counter); + } + + drm_connector_list_iter_end(&conn_iter); + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); pm_runtime_mark_last_busy(drm->dev->dev); +noop: pm_runtime_put_sync(drm->dev->dev); } @@ -490,12 +544,11 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, */ pm_runtime_put_autosuspend(drm->dev->dev); } else if (ret == 0) { - /* This may be the only indication we receive - * of a connector hotplug on a runtime - * suspended GPU, schedule hpd_work to check. + /* We've started resuming the GPU already, so + * it will handle scheduling a full reprobe + * itself */ NV_DEBUG(drm, "ACPI requested connector reprobe\n"); - schedule_work(&drm->hpd_work); pm_runtime_put_noidle(drm->dev->dev); } else { NV_WARN(drm, "Dropped ACPI reprobe event due to RPM error: %d\n", @@ -686,6 +739,7 @@ nouveau_display_create(struct drm_device *dev) } INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work); + mutex_init(&drm->hpd_lock); #ifdef CONFIG_ACPI drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy; register_acpi_notifier(&drm->acpi_nb); @@ -705,9 +759,10 @@ void nouveau_display_destroy(struct drm_device *dev) { struct nouveau_display *disp = nouveau_display(dev); + struct nouveau_drm *drm = nouveau_drm(dev); #ifdef CONFIG_ACPI - unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb); + unregister_acpi_notifier(&drm->acpi_nb); #endif drm_kms_helper_poll_fini(dev); @@ -719,6 +774,7 @@ nouveau_display_destroy(struct drm_device *dev) nvif_disp_dtor(&disp->disp); nouveau_drm(dev)->display = NULL; + mutex_destroy(&drm->hpd_lock); kfree(disp); } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 76ba93e01aff..616c43427059 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -45,6 +45,7 @@ nouveau_display(struct drm_device *dev) int nouveau_display_create(struct drm_device *dev); void nouveau_display_destroy(struct drm_device *dev); int nouveau_display_init(struct drm_device *dev, bool resume, bool runtime); +void nouveau_display_hpd_resume(struct drm_device *dev); void nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime); int nouveau_display_suspend(struct drm_device *dev, bool runtime); void nouveau_display_resume(struct drm_device *dev, bool runtime); diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index a5934064a75e..005750aeb6d4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -165,7 +165,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - schedule_work(&drm->hpd_work); + nouveau_connector_hpd(connector); } else { drm_dp_cec_irq(&nv_connector->aux); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 22d246acc5e5..42fc5c813a9b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -953,7 +953,7 @@ nouveau_pmops_resume(struct device *dev) ret = nouveau_do_resume(drm_dev, false); /* Monitors may have been connected / disconnected during suspend */ - schedule_work(&nouveau_drm(drm_dev)->hpd_work); + nouveau_display_hpd_resume(drm_dev); return ret; } @@ -1036,7 +1036,7 @@ nouveau_pmops_runtime_resume(struct device *dev) drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; /* Monitors may have been connected / disconnected during suspend */ - schedule_work(&nouveau_drm(drm_dev)->hpd_work); + nouveau_display_hpd_resume(drm_dev); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index f63ac72aa556..73ebf5fba2fc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -198,6 +198,8 @@ struct nouveau_drm { struct nvbios vbios; struct nouveau_display *display; struct work_struct hpd_work; + struct mutex hpd_lock; + u32 hpd_pending; struct work_struct fbcon_work; int fbcon_new_state; #ifdef CONFIG_ACPI -- cgit v1.2.3 From 3d3721ccb18a3dcec874c44120e2df7ec1c1db99 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:49 -0400 Subject: drm/i915/dp: Extract drm_dp_read_downstream_info() We're going to be doing the same probing process in nouveau for determining downstream DP port capabilities, so let's deduplicate the work by moving i915's code for handling this into a shared helper: drm_dp_read_downstream_info(). Note that when we do this, we also do make some functional changes while we're at it: * We always clear the downstream port info before trying to read it, just to make things easier for the caller * We skip reading downstream port info if the DPCD indicates that we don't support downstream port info * We only read as many bytes as needed for the reported number of downstream ports, no sense in reading the whole thing every time v2: * Fixup logic for calculating the downstream port length to account for the fact that downstream port caps can be either 1 byte or 4 bytes long. We can actually skip fixing the max_clock/max_bpc helpers here since they all check for DP_DETAILED_CAP_INFO_AVAILABLE anyway. * Fix ret code check for drm_dp_dpcd_read v5: * Change name from drm_dp_downstream_read_info() to drm_dp_read_downstream_info() * Also, add "See Also" sections for the various downstream info functions (drm_dp_read_downstream_info(), drm_dp_downstream_max_clock(), drm_dp_downstream_max_bpc()) Reviewed-by: Sean Paul Signed-off-by: Lyude Paul Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-14-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 62 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_dp.c | 14 ++------ include/drm/drm_dp_helper.h | 3 ++ 3 files changed, 65 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 4c21cf69dad5..f3643894ad95 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -423,6 +423,56 @@ bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, } EXPORT_SYMBOL(drm_dp_send_real_edid_checksum); +static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 port_count = dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_PORT_COUNT_MASK; + + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE && port_count > 4) + port_count = 4; + + return port_count; +} + +/** + * drm_dp_read_downstream_info() - read DPCD downstream port info if available + * @aux: DisplayPort AUX channel + * @dpcd: A cached copy of the port's DPCD + * @downstream_ports: buffer to store the downstream port info in + * + * See also: + * drm_dp_downstream_max_clock() + * drm_dp_downstream_max_bpc() + * + * Returns: 0 if either the downstream port info was read successfully or + * there was no downstream info to read, or a negative error code otherwise. + */ +int drm_dp_read_downstream_info(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]) +{ + int ret; + u8 len; + + memset(downstream_ports, 0, DP_MAX_DOWNSTREAM_PORTS); + + /* No downstream info to read */ + if (!drm_dp_is_branch(dpcd) || + dpcd[DP_DPCD_REV] < DP_DPCD_REV_10 || + !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) + return 0; + + len = drm_dp_downstream_port_count(dpcd); + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) + len *= 4; + + ret = drm_dp_dpcd_read(aux, DP_DOWNSTREAM_PORT_0, downstream_ports, len); + if (ret < 0) + return ret; + + return ret == len ? 0 : -EIO; +} +EXPORT_SYMBOL(drm_dp_read_downstream_info); + /** * drm_dp_downstream_max_clock() - extract branch device max * pixel rate for legacy VGA @@ -431,7 +481,11 @@ EXPORT_SYMBOL(drm_dp_send_real_edid_checksum); * @dpcd: DisplayPort configuration data * @port_cap: port capabilities * - * Returns max clock in kHz on success or 0 if max clock not defined + * See also: + * drm_dp_read_downstream_info() + * drm_dp_downstream_max_bpc() + * + * Returns: Max clock in kHz on success or 0 if max clock not defined */ int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]) @@ -462,7 +516,11 @@ EXPORT_SYMBOL(drm_dp_downstream_max_clock); * @dpcd: DisplayPort configuration data * @port_cap: port capabilities * - * Returns max bpc on success or 0 if max bpc not defined + * See also: + * drm_dp_read_downstream_info() + * drm_dp_downstream_max_clock() + * + * Returns: Max bpc on success or 0 if max bpc not defined */ int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 4c7314b7a84e..9c4b806af8c7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4685,18 +4685,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) return false; } - if (!drm_dp_is_branch(intel_dp->dpcd)) - return true; /* native DP sink */ - - if (intel_dp->dpcd[DP_DPCD_REV] == 0x10) - return true; /* no per-port downstream info */ - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_DOWNSTREAM_PORT_0, - intel_dp->downstream_ports, - DP_MAX_DOWNSTREAM_PORTS) < 0) - return false; /* downstream port status fetch failed */ - - return true; + return drm_dp_read_downstream_info(&intel_dp->aux, intel_dp->dpcd, + intel_dp->downstream_ports) == 0; } static bool diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 5c2819924862..b8716b200666 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1613,6 +1613,9 @@ int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, bool drm_dp_send_real_edid_checksum(struct drm_dp_aux *aux, u8 real_edid_checksum); +int drm_dp_read_downstream_info(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]); int drm_dp_downstream_max_clock(const u8 dpcd[DP_RECEIVER_CAP_SIZE], const u8 port_cap[4]); int drm_dp_downstream_max_bpc(const u8 dpcd[DP_RECEIVER_CAP_SIZE], -- cgit v1.2.3 From 409d38139b42f2c3d3e6012a060c498fbb5067fc Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:50 -0400 Subject: drm/nouveau/kms/nv50-: Use downstream DP clock limits for mode validation This adds support for querying the maximum clock rate of a downstream port on a DisplayPort connection. Generally, downstream ports refer to active dongles which can have their own pixel clock limits. Note as well, we also start marking the connector as disconnected if we can't read the DPCD, since we wouldn't be able to do anything without DPCD access anyway. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-15-lyude@redhat.com --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 3 +++ drivers/gpu/drm/nouveau/nouveau_dp.c | 15 +++++++++++---- drivers/gpu/drm/nouveau/nouveau_encoder.h | 1 + 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 8e1effb10425..d2141ca16107 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1258,7 +1258,10 @@ nv50_mstc_detect(struct drm_connector *connector, ret = drm_dp_mst_detect_port(connector, ctx, mstc->port->mgr, mstc->port); + if (ret != connector_status_connected) + goto out; +out: pm_runtime_mark_last_busy(connector->dev->dev); pm_runtime_put_autosuspend(connector->dev->dev); return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 005750aeb6d4..ad852e572cfe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -61,6 +61,11 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } + ret = drm_dp_read_downstream_info(aux, dpcd, + outp->dp.downstream_ports); + if (ret < 0) + return connector_status_disconnected; + return connector_status_connected; } @@ -176,8 +181,6 @@ void nouveau_dp_irq(struct nouveau_drm *drm, /* TODO: * - Use the minimum possible BPC here, once we add support for the max bpc * property. - * - Validate the mode against downstream port caps (see - * drm_dp_downstream_max_clock()) * - Validate against the DP caps advertised by the GPU (we don't check these * yet) */ @@ -188,15 +191,19 @@ nv50_dp_mode_valid(struct drm_connector *connector, unsigned *out_clock) { const unsigned min_clock = 25000; - unsigned max_clock, clock; + unsigned max_clock, ds_clock, clock; enum drm_mode_status ret; if (mode->flags & DRM_MODE_FLAG_INTERLACE && !outp->caps.dp_interlace) return MODE_NO_INTERLACE; max_clock = outp->dp.link_nr * outp->dp.link_bw; - clock = mode->clock * (connector->display_info.bpc * 3) / 10; + ds_clock = drm_dp_downstream_max_clock(outp->dp.dpcd, + outp->dp.downstream_ports); + if (ds_clock) + max_clock = min(max_clock, ds_clock); + clock = mode->clock * (connector->display_info.bpc * 3) / 10; ret = nouveau_conn_mode_clock_valid(mode, min_clock, max_clock, &clock); if (out_clock) diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index eef4643f5f98..c1924a4529a7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -72,6 +72,7 @@ struct nouveau_encoder { struct mutex hpd_irq_lock; u8 dpcd[DP_RECEIVER_CAP_SIZE]; + u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct drm_dp_desc desc; } dp; }; -- cgit v1.2.3 From 693c3ec5976eb4b66cbd4f3f1c701a6f0ae1c9b9 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:51 -0400 Subject: drm/i915/dp: Extract drm_dp_read_sink_count_cap() Since other drivers are also going to need to be aware of the sink count in order to do proper dongle detection, we might as well steal i915's DP_SINK_COUNT helpers and move them into DRM helpers so that other dirvers can use them as well. Note that this also starts using intel_dp_has_sink_count() in intel_dp_detect_dpcd(), which is a functional change. v5: * Change name from drm_dp_has_sink_count() to drm_dp_read_sink_count_cap() Signed-off-by: Lyude Paul Reviewed-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-16-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 22 ++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 21 ++++++++++++--------- include/drm/drm_dp_helper.h | 8 +++++++- 3 files changed, 41 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index f3643894ad95..65ff21ae0c27 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -726,6 +726,28 @@ void drm_dp_set_subconnector_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_dp_set_subconnector_property); +/** + * drm_dp_read_sink_count_cap() - Check whether a given connector has a valid sink + * count + * @connector: The DRM connector to check + * @dpcd: A cached copy of the connector's DPCD RX capabilities + * @desc: A cached copy of the connector's DP descriptor + * + * Returns: %True if the (e)DP connector has a valid sink count that should + * be probed, %false otherwise. + */ +bool drm_dp_read_sink_count_cap(struct drm_connector *connector, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const struct drm_dp_desc *desc) +{ + /* Some eDP panels don't set a valid value for the sink count */ + return connector->connector_type != DRM_MODE_CONNECTOR_eDP && + dpcd[DP_DPCD_REV] >= DP_DPCD_REV_11 && + dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT && + !drm_dp_has_quirk(desc, 0, DP_DPCD_QUIRK_NO_SINK_COUNT); +} +EXPORT_SYMBOL(drm_dp_read_sink_count_cap); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9c4b806af8c7..38318ae935f8 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4634,6 +4634,16 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) return true; } +static bool +intel_dp_has_sink_count(struct intel_dp *intel_dp) +{ + if (!intel_dp->attached_connector) + return false; + + return drm_dp_read_sink_count_cap(&intel_dp->attached_connector->base, + intel_dp->dpcd, + &intel_dp->desc); +} static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) @@ -4653,13 +4663,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) intel_dp_set_common_rates(intel_dp); } - /* - * Some eDP panels do not set a valid value for sink count, that is why - * it don't care about read it here and in intel_edp_init_dpcd(). - */ - if (!intel_dp_is_edp(intel_dp) && - !drm_dp_has_quirk(&intel_dp->desc, 0, - DP_DPCD_QUIRK_NO_SINK_COUNT)) { + if (intel_dp_has_sink_count(intel_dp)) { u8 count; ssize_t r; @@ -5939,9 +5943,8 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp) return connector_status_connected; /* If we're HPD-aware, SINK_COUNT changes dynamically */ - if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && + if (intel_dp_has_sink_count(intel_dp) && intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) { - return intel_dp->sink_count ? connector_status_connected : connector_status_disconnected; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b8716b200666..4c56ce4dc54f 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1631,6 +1631,11 @@ void drm_dp_set_subconnector_property(struct drm_connector *connector, const u8 *dpcd, const u8 port_cap[4]); +struct drm_dp_desc; +bool drm_dp_read_sink_count_cap(struct drm_connector *connector, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], + const struct drm_dp_desc *desc); + void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); int drm_dp_aux_register(struct drm_dp_aux *aux); @@ -1689,7 +1694,8 @@ enum drm_dp_quirk { * @DP_DPCD_QUIRK_NO_SINK_COUNT: * * The device does not set SINK_COUNT to a non-zero value. - * The driver should ignore SINK_COUNT during detection. + * The driver should ignore SINK_COUNT during detection. Note that + * drm_dp_read_sink_count_cap() automatically checks for this quirk. */ DP_DPCD_QUIRK_NO_SINK_COUNT, /** -- cgit v1.2.3 From 4778ff052812029bc076f5e78eff3ba1851cbea7 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:52 -0400 Subject: drm/i915/dp: Extract drm_dp_read_sink_count() And of course, we'll also need to read the sink count from other drivers as well if we're checking whether or not it's supported. So, let's extract the code for this into another helper. v2: * Fix drm_dp_dpcd_readb() ret check * Add back comment and move back sink_count assignment in intel_dp_get_dpcd() v5: * Change name from drm_dp_get_sink_count() to drm_dp_read_sink_count() * Also, add "See also:" section to kdocs Signed-off-by: Lyude Paul Reviewed-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-17-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 26 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 11 +++++------ include/drm/drm_dp_helper.h | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 65ff21ae0c27..46d88ef4f59a 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -733,6 +733,8 @@ EXPORT_SYMBOL(drm_dp_set_subconnector_property); * @dpcd: A cached copy of the connector's DPCD RX capabilities * @desc: A cached copy of the connector's DP descriptor * + * See also: drm_dp_read_sink_count() + * * Returns: %True if the (e)DP connector has a valid sink count that should * be probed, %false otherwise. */ @@ -748,6 +750,30 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector, } EXPORT_SYMBOL(drm_dp_read_sink_count_cap); +/** + * drm_dp_read_sink_count() - Retrieve the sink count for a given sink + * @aux: The DP AUX channel to use + * + * See also: drm_dp_read_sink_count_cap() + * + * Returns: The current sink count reported by @aux, or a negative error code + * otherwise. + */ +int drm_dp_read_sink_count(struct drm_dp_aux *aux) +{ + u8 count; + int ret; + + ret = drm_dp_dpcd_readb(aux, DP_SINK_COUNT, &count); + if (ret < 0) + return ret; + if (ret != 1) + return -EIO; + + return DP_GET_SINK_COUNT(count); +} +EXPORT_SYMBOL(drm_dp_read_sink_count); + /* * I2C-over-AUX implementation */ diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 38318ae935f8..0de94fc6289b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4648,6 +4648,8 @@ intel_dp_has_sink_count(struct intel_dp *intel_dp) static bool intel_dp_get_dpcd(struct intel_dp *intel_dp) { + int ret; + if (!intel_dp_read_dpcd(intel_dp)) return false; @@ -4664,11 +4666,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) } if (intel_dp_has_sink_count(intel_dp)) { - u8 count; - ssize_t r; - - r = drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_COUNT, &count); - if (r < 1) + ret = drm_dp_read_sink_count(&intel_dp->aux); + if (ret < 0) return false; /* @@ -4676,7 +4675,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) * a member variable in intel_dp will track any changes * between short pulse interrupts. */ - intel_dp->sink_count = DP_GET_SINK_COUNT(count); + intel_dp->sink_count = ret; /* * SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index 4c56ce4dc54f..bc5cb8c503fb 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1635,6 +1635,7 @@ struct drm_dp_desc; bool drm_dp_read_sink_count_cap(struct drm_connector *connector, const u8 dpcd[DP_RECEIVER_CAP_SIZE], const struct drm_dp_desc *desc); +int drm_dp_read_sink_count(struct drm_dp_aux *aux); void drm_dp_remote_aux_init(struct drm_dp_aux *aux); void drm_dp_aux_init(struct drm_dp_aux *aux); -- cgit v1.2.3 From a4efad354cf1b9d5275adc85f67fcaaa1c2912d8 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:53 -0400 Subject: drm/nouveau/kms/nv50-: Add support for DP_SINK_COUNT This is another bit that we never implemented for nouveau: dongle detection. When a "dongle", e.g. an active display adaptor, is hooked up to the system and causes an HPD to be fired, we don't actually know whether or not there's anything plugged into the dongle without checking the sink count. As a result, plugging in a dongle without anything plugged into it currently results in a bogus EDID retrieval error in the kernel log. Additionally, most dongles won't send another long HPD signal if the user suddenly plugs something in, they'll only send a short HPD IRQ with the expectation that the source will check the sink count and reprobe the connector if it's changed - something we don't actually do. As a result, nothing will happen if the user plugs the dongle in before plugging something into the dongle. So, let's fix this by checking the sink count in both nouveau_dp_probe_dpcd() and nouveau_dp_irq(), and reprobing the connector if things change. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-18-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 53 ++++++++++++++++++++++++++++--- drivers/gpu/drm/nouveau/nouveau_encoder.h | 2 ++ 2 files changed, 50 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index ad852e572cfe..59be357b17e0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -36,12 +36,21 @@ MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)"); static int nouveau_mst = 1; module_param_named(mst, nouveau_mst, int, 0400); +static bool +nouveau_dp_has_sink_count(struct drm_connector *connector, + struct nouveau_encoder *outp) +{ + return drm_dp_read_sink_count_cap(connector, outp->dp.dpcd, &outp->dp.desc); +} + static enum drm_connector_status nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, struct nouveau_encoder *outp) { + struct drm_connector *connector = &nv_connector->base; struct drm_dp_aux *aux = &nv_connector->aux; struct nv50_mstm *mstm = NULL; + enum drm_connector_status status = connector_status_disconnected; int ret; u8 *dpcd = outp->dp.dpcd; @@ -50,9 +59,9 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd)); if (ret < 0) - return connector_status_disconnected; + goto out; } else { - return connector_status_disconnected; + goto out; } if (nouveau_mst) { @@ -61,12 +70,33 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, mstm->can_mst = drm_dp_read_mst_cap(aux, dpcd); } + if (nouveau_dp_has_sink_count(connector, outp)) { + ret = drm_dp_read_sink_count(aux); + if (ret < 0) + goto out; + + outp->dp.sink_count = ret; + + /* + * Dongle connected, but no display. Don't bother reading + * downstream port info + */ + if (!outp->dp.sink_count) + return connector_status_disconnected; + } + ret = drm_dp_read_downstream_info(aux, dpcd, outp->dp.downstream_ports); if (ret < 0) - return connector_status_disconnected; + goto out; - return connector_status_connected; + status = connector_status_connected; +out: + if (status != connector_status_connected) { + /* Clear any cached info */ + outp->dp.sink_count = 0; + } + return status; } int @@ -159,6 +189,8 @@ void nouveau_dp_irq(struct nouveau_drm *drm, struct drm_connector *connector = &nv_connector->base; struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP); struct nv50_mstm *mstm; + int ret; + bool send_hpd = false; if (!outp) return; @@ -170,12 +202,23 @@ void nouveau_dp_irq(struct nouveau_drm *drm, if (mstm && mstm->is_mst) { if (!nv50_mstm_service(drm, nv_connector, mstm)) - nouveau_connector_hpd(connector); + send_hpd = true; } else { drm_dp_cec_irq(&nv_connector->aux); + + if (nouveau_dp_has_sink_count(connector, outp)) { + ret = drm_dp_read_sink_count(&nv_connector->aux); + if (ret != outp->dp.sink_count) + send_hpd = true; + if (ret >= 0) + outp->dp.sink_count = ret; + } } mutex_unlock(&outp->dp.hpd_irq_lock); + + if (send_hpd) + nouveau_connector_hpd(connector); } /* TODO: diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index c1924a4529a7..21937f1c7dd9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -74,6 +74,8 @@ struct nouveau_encoder { u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct drm_dp_desc desc; + + u8 sink_count; } dp; }; -- cgit v1.2.3 From f28e32d3906eac2e1cb3291b448f0d528ec93996 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:54 -0400 Subject: drm/nouveau/kms: Don't change EDID when it hasn't actually changed Currently in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds(), we start the connector probing process by releasing the previous EDID and informing DRM of the change. However, since commit 5186421cbfe2 ("drm: Introduce epoch counter to drm_connector") drm_connector_update_edid_property() actually checks whether the new EDID we've specified is different from the previous one, and updates the connector's epoch accordingly if it is. But, because we always set the EDID to NULL first in nouveau_connector_ddc_detect() and nouveau_connector_detect_lvds() we end up making DRM think that the EDID changes every single time we do a connector probe - which isn't needed. So, let's fix this by not clearing the EDID at the start of the connector probing process, and instead simply changing or removing it once near the end of the probing process. This will help prevent us from sending unneeded hotplug events to userspace when nothing has actually changed. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-19-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_connector.c | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 637e91594fbe..49dd0cbc332f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -528,6 +528,17 @@ nouveau_connector_set_encoder(struct drm_connector *connector, } } +static void +nouveau_connector_set_edid(struct nouveau_connector *nv_connector, + struct edid *edid) +{ + struct edid *old_edid = nv_connector->edid; + + drm_connector_update_edid_property(&nv_connector->base, edid); + kfree(old_edid); + nv_connector->edid = edid; +} + static enum drm_connector_status nouveau_connector_detect(struct drm_connector *connector, bool force) { @@ -541,13 +552,6 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) int ret; enum drm_connector_status conn_status = connector_status_disconnected; - /* Cleanup the previous EDID block. */ - if (nv_connector->edid) { - drm_connector_update_edid_property(connector, NULL); - kfree(nv_connector->edid); - nv_connector->edid = NULL; - } - /* Outputs are only polled while runtime active, so resuming the * device here is unnecessary (and would deadlock upon runtime suspend * because it waits for polling to finish). We do however, want to @@ -560,22 +564,23 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ret = pm_runtime_get_sync(dev->dev); if (ret < 0 && ret != -EACCES) { pm_runtime_put_autosuspend(dev->dev); + nouveau_connector_set_edid(nv_connector, NULL); return conn_status; } } nv_encoder = nouveau_connector_ddc_detect(connector); if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { + struct edid *new_edid; + if ((vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC) && nv_connector->type == DCB_CONNECTOR_LVDS) - nv_connector->edid = drm_get_edid_switcheroo(connector, - i2c); + new_edid = drm_get_edid_switcheroo(connector, i2c); else - nv_connector->edid = drm_get_edid(connector, i2c); + new_edid = drm_get_edid(connector, i2c); - drm_connector_update_edid_property(connector, - nv_connector->edid); + nouveau_connector_set_edid(nv_connector, new_edid); if (!nv_connector->edid) { NV_ERROR(drm, "DDC responded, but no EDID for %s\n", connector->name); @@ -609,6 +614,8 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) conn_status = connector_status_connected; drm_dp_cec_set_edid(&nv_connector->aux, nv_connector->edid); goto out; + } else { + nouveau_connector_set_edid(nv_connector, NULL); } nv_encoder = nouveau_connector_of_detect(connector); @@ -652,18 +659,12 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = NULL; + struct edid *edid = NULL; enum drm_connector_status status = connector_status_disconnected; - /* Cleanup the previous EDID block. */ - if (nv_connector->edid) { - drm_connector_update_edid_property(connector, NULL); - kfree(nv_connector->edid); - nv_connector->edid = NULL; - } - nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS); if (!nv_encoder) - return connector_status_disconnected; + goto out; /* Try retrieving EDID via DDC */ if (!drm->vbios.fp_no_ddc) { @@ -682,7 +683,8 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * valid - it's not (rh#613284) */ if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) { - if ((nv_connector->edid = nouveau_acpi_edid(dev, connector))) { + edid = nouveau_acpi_edid(dev, connector); + if (edid) { status = connector_status_connected; goto out; } @@ -702,12 +704,10 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) * stored for the panel stored in them. */ if (!drm->vbios.fp_no_ddc) { - struct edid *edid = - (struct edid *)nouveau_bios_embedded_edid(dev); + edid = (struct edid *)nouveau_bios_embedded_edid(dev); if (edid) { - nv_connector->edid = - kmemdup(edid, EDID_LENGTH, GFP_KERNEL); - if (nv_connector->edid) + edid = kmemdup(edid, EDID_LENGTH, GFP_KERNEL); + if (edid) status = connector_status_connected; } } @@ -720,7 +720,7 @@ out: status = connector_status_unknown; #endif - drm_connector_update_edid_property(connector, nv_connector->edid); + nouveau_connector_set_edid(nv_connector, edid); nouveau_connector_set_encoder(connector, nv_encoder); return status; } -- cgit v1.2.3 From b9936121d95b0127d34fa6c25678994582d1b17c Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:55 -0400 Subject: drm/i915/dp: Extract drm_dp_read_dpcd_caps() Since DP 1.3, it's been possible for DP receivers to specify an additional set of DPCD capabilities, which can take precedence over the capabilities reported at DP_DPCD_REV. Basically any device supporting DP is going to need to read these in an identical manner, in particular nouveau, so let's go ahead and just move this code out of i915 into a shared DRM DP helper that we can use in other drivers. v2: * Remove redundant dpcd[DP_DPCD_REV] == 0 check * Fix drm_dp_dpcd_read() ret checks Signed-off-by: Lyude Paul Reviewed-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-20-lyude@redhat.com --- drivers/gpu/drm/drm_dp_helper.c | 77 +++++++++++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dp.c | 60 +--------------------- drivers/gpu/drm/i915/display/intel_dp.h | 1 - drivers/gpu/drm/i915/display/intel_lspcon.c | 2 +- include/drm/drm_dp_helper.h | 3 ++ 5 files changed, 83 insertions(+), 60 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 46d88ef4f59a..9ca88e6c7882 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -433,6 +433,83 @@ static u8 drm_dp_downstream_port_count(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) return port_count; } +static int drm_dp_read_extended_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + u8 dpcd_ext[6]; + int ret; + + /* + * Prior to DP1.3 the bit represented by + * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. + * If it is set DP_DPCD_REV at 0000h could be at a value less than + * the true capability of the panel. The only way to check is to + * then compare 0000h and 2200h. + */ + if (!(dpcd[DP_TRAINING_AUX_RD_INTERVAL] & + DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) + return 0; + + ret = drm_dp_dpcd_read(aux, DP_DP13_DPCD_REV, &dpcd_ext, + sizeof(dpcd_ext)); + if (ret < 0) + return ret; + if (ret != sizeof(dpcd_ext)) + return -EIO; + + if (dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { + DRM_DEBUG_KMS("%s: Extended DPCD rev less than base DPCD rev (%d > %d)\n", + aux->name, dpcd[DP_DPCD_REV], + dpcd_ext[DP_DPCD_REV]); + return 0; + } + + if (!memcmp(dpcd, dpcd_ext, sizeof(dpcd_ext))) + return 0; + + DRM_DEBUG_KMS("%s: Base DPCD: %*ph\n", + aux->name, DP_RECEIVER_CAP_SIZE, dpcd); + + memcpy(dpcd, dpcd_ext, sizeof(dpcd_ext)); + + return 0; +} + +/** + * drm_dp_read_dpcd_caps() - read DPCD caps and extended DPCD caps if + * available + * @aux: DisplayPort AUX channel + * @dpcd: Buffer to store the resulting DPCD in + * + * Attempts to read the base DPCD caps for @aux. Additionally, this function + * checks for and reads the extended DPRX caps (%DP_DP13_DPCD_REV) if + * present. + * + * Returns: %0 if the DPCD was read successfully, negative error code + * otherwise. + */ +int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]) +{ + int ret; + + ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); + if (ret < 0) + return ret; + if (ret != DP_RECEIVER_CAP_SIZE || dpcd[DP_DPCD_REV] == 0) + return -EIO; + + ret = drm_dp_read_extended_dpcd_caps(aux, dpcd); + if (ret < 0) + return ret; + + DRM_DEBUG_KMS("%s: DPCD: %*ph\n", + aux->name, DP_RECEIVER_CAP_SIZE, dpcd); + + return ret; +} +EXPORT_SYMBOL(drm_dp_read_dpcd_caps); + /** * drm_dp_read_downstream_info() - read DPCD downstream port info if available * @aux: DisplayPort AUX channel diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 0de94fc6289b..284b15f84592 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4449,62 +4449,6 @@ intel_dp_link_down(struct intel_encoder *encoder, } } -static void -intel_dp_extended_receiver_capabilities(struct intel_dp *intel_dp) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - u8 dpcd_ext[6]; - - /* - * Prior to DP1.3 the bit represented by - * DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved. - * if it is set DP_DPCD_REV at 0000h could be at a value less than - * the true capability of the panel. The only way to check is to - * then compare 0000h and 2200h. - */ - if (!(intel_dp->dpcd[DP_TRAINING_AUX_RD_INTERVAL] & - DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT)) - return; - - if (drm_dp_dpcd_read(&intel_dp->aux, DP_DP13_DPCD_REV, - &dpcd_ext, sizeof(dpcd_ext)) != sizeof(dpcd_ext)) { - drm_err(&i915->drm, - "DPCD failed read at extended capabilities\n"); - return; - } - - if (intel_dp->dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) { - drm_dbg_kms(&i915->drm, - "DPCD extended DPCD rev less than base DPCD rev\n"); - return; - } - - if (!memcmp(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext))) - return; - - drm_dbg_kms(&i915->drm, "Base DPCD: %*ph\n", - (int)sizeof(intel_dp->dpcd), intel_dp->dpcd); - - memcpy(intel_dp->dpcd, dpcd_ext, sizeof(dpcd_ext)); -} - -bool -intel_dp_read_dpcd(struct intel_dp *intel_dp) -{ - struct drm_i915_private *i915 = dp_to_i915(intel_dp); - - if (drm_dp_dpcd_read(&intel_dp->aux, 0x000, intel_dp->dpcd, - sizeof(intel_dp->dpcd)) < 0) - return false; /* aux transfer failed */ - - intel_dp_extended_receiver_capabilities(intel_dp); - - drm_dbg_kms(&i915->drm, "DPCD: %*ph\n", (int)sizeof(intel_dp->dpcd), - intel_dp->dpcd); - - return intel_dp->dpcd[DP_DPCD_REV] != 0; -} - bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp) { u8 dprx = 0; @@ -4563,7 +4507,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) /* this function is meant to be called only once */ drm_WARN_ON(&dev_priv->drm, intel_dp->dpcd[DP_DPCD_REV] != 0); - if (!intel_dp_read_dpcd(intel_dp)) + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd) != 0) return false; drm_dp_read_desc(&intel_dp->aux, &intel_dp->desc, @@ -4650,7 +4594,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp) { int ret; - if (!intel_dp_read_dpcd(intel_dp)) + if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) return false; /* diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h index b901ab850cbd..0a3af3410d52 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.h +++ b/drivers/gpu/drm/i915/display/intel_dp.h @@ -99,7 +99,6 @@ bool intel_dp_source_supports_hbr3(struct intel_dp *intel_dp); bool intel_dp_get_link_status(struct intel_dp *intel_dp, u8 *link_status); -bool intel_dp_read_dpcd(struct intel_dp *intel_dp); bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp); int intel_dp_link_required(int pixel_clock, int bpp); int intel_dp_max_data_rate(int max_link_clock, int max_lanes); diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c index b781bf469644..dc1b35559afd 100644 --- a/drivers/gpu/drm/i915/display/intel_lspcon.c +++ b/drivers/gpu/drm/i915/display/intel_lspcon.c @@ -571,7 +571,7 @@ bool lspcon_init(struct intel_digital_port *dig_port) return false; } - if (!intel_dp_read_dpcd(dp)) { + if (drm_dp_read_dpcd_caps(&dp->aux, dp->dpcd) != 0) { DRM_ERROR("LSPCON DPCD read failed\n"); return false; } diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index bc5cb8c503fb..85513eeb2196 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1607,6 +1607,9 @@ static inline ssize_t drm_dp_dpcd_writeb(struct drm_dp_aux *aux, return drm_dp_dpcd_write(aux, offset, &value, 1); } +int drm_dp_read_dpcd_caps(struct drm_dp_aux *aux, + u8 dpcd[DP_RECEIVER_CAP_SIZE]); + int drm_dp_dpcd_read_link_status(struct drm_dp_aux *aux, u8 status[DP_LINK_STATUS_SIZE]); -- cgit v1.2.3 From 79416e97dda0118b137302575a70a14259a27d7d Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 26 Aug 2020 14:24:56 -0400 Subject: drm/nouveau/kms: Start using drm_dp_read_dpcd_caps() Now that we've extracted i915's code for reading both the normal DPCD caps and extended DPCD caps into a shared helper, let's start using this in nouveau to enable us to start checking extended DPCD caps for free. Signed-off-by: Lyude Paul Reviewed-by: Ben Skeggs Link: https://patchwork.freedesktop.org/patch/msgid/20200826182456.322681-21-lyude@redhat.com --- drivers/gpu/drm/nouveau/nouveau_dp.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 59be357b17e0..810bf6956568 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -54,15 +54,13 @@ nouveau_dp_probe_dpcd(struct nouveau_connector *nv_connector, int ret; u8 *dpcd = outp->dp.dpcd; - ret = drm_dp_dpcd_read(aux, DP_DPCD_REV, dpcd, DP_RECEIVER_CAP_SIZE); - if (ret == DP_RECEIVER_CAP_SIZE && dpcd[DP_DPCD_REV]) { - ret = drm_dp_read_desc(aux, &outp->dp.desc, - drm_dp_is_branch(dpcd)); - if (ret < 0) - goto out; - } else { + ret = drm_dp_read_dpcd_caps(aux, dpcd); + if (ret < 0) + goto out; + + ret = drm_dp_read_desc(aux, &outp->dp.desc, drm_dp_is_branch(dpcd)); + if (ret < 0) goto out; - } if (nouveau_mst) { mstm = outp->dp.mstm; -- cgit v1.2.3 From c6016c6e39c3ee8fd671532520be3cc13e439db2 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Aug 2020 09:25:10 +0200 Subject: drm/virtio: fix unblank When going through a disable/enable cycle without changing the framebuffer the optimization added by commit 3954ff10e06e ("drm/virtio: skip set_scanout if framebuffer didn't change") causes the screen stay blank. Add a bool to force an update to fix that. v2: use drm_atomic_crtc_needs_modeset() (Daniel). Cc: 1882851@bugs.launchpad.net Fixes: 3954ff10e06e ("drm/virtio: skip set_scanout if framebuffer didn't change") Signed-off-by: Gerd Hoffmann Tested-by: Jiri Slaby Tested-by: Diego Viola Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20200818072511.6745-2-kraxel@redhat.com (cherry picked from commit 1bc371cd0ec907bab870cacb6e898105f9c41dc8) --- drivers/gpu/drm/virtio/virtgpu_display.c | 11 +++++++++++ drivers/gpu/drm/virtio/virtgpu_drv.h | 1 + drivers/gpu/drm/virtio/virtgpu_plane.c | 4 +++- 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index af55b334be2f..97170998cd0e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -123,6 +123,17 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, static void virtio_gpu_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { + struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); + + /* + * virtio-gpu can't do modeset and plane update operations + * independent from each other. So the actual modeset happens + * in the plane update callback, and here we just check + * whenever we must force the modeset. + */ + if (drm_atomic_crtc_needs_modeset(crtc->state)) { + output->needs_modeset = true; + } } static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9ff9f4ac0522..4ab1b0ba2925 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -138,6 +138,7 @@ struct virtio_gpu_output { int cur_x; int cur_y; bool enabled; + bool needs_modeset; }; #define drm_crtc_to_virtio_gpu_output(x) \ container_of(x, struct virtio_gpu_output, crtc) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 52d24179bcec..65757409d9ed 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -163,7 +163,9 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, plane->state->src_w != old_state->src_w || plane->state->src_h != old_state->src_h || plane->state->src_x != old_state->src_x || - plane->state->src_y != old_state->src_y) { + plane->state->src_y != old_state->src_y || + output->needs_modeset) { + output->needs_modeset = false; DRM_DEBUG("handle 0x%x, crtc %dx%d+%d+%d, src %dx%d+%d+%d\n", bo->hw_res_handle, plane->state->crtc_w, plane->state->crtc_h, -- cgit v1.2.3 From 6baa2e0c8ab89664285bb0780bfd39276bc27a88 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Fri, 28 Aug 2020 13:28:30 -0700 Subject: drm/i915/display: Ensure that ret is always initialized in icl_combo_phy_verify_state Clang warns: drivers/gpu/drm/i915/display/intel_combo_phy.c:268:3: warning: variable 'ret' is uninitialized when used here [-Wuninitialized] ret &= check_phy_reg(dev_priv, phy, ICL_PORT_TX_DW8_LN0(phy), ^~~ drivers/gpu/drm/i915/display/intel_combo_phy.c:261:10: note: initialize the variable 'ret' to silence this warning bool ret; ^ = 0 1 warning generated. In practice, the bug this warning appears to be concerned with would not actually matter because ret gets initialized to the return value of cnl_verify_procmon_ref_values. However, that does appear to be a bug since it means the first hunk of the patch this fixes won't actually do anything (since the values of check_phy_reg won't factor into the final ret value). Initialize ret to true then make all of the assignments a bitwise AND with itself so that the function always does what it should do. Fixes: 239bef676d8e ("drm/i915/display: Implement new combo phy initialization step") Link: https://github.com/ClangBuiltLinux/linux/issues/1094 Signed-off-by: Nathan Chancellor Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20200828202830.7165-1-jose.souza@intel.com Signed-off-by: José Roberto de Souza (cherry picked from commit 2034c2129bc4a91d471815d4dc7a2a69eaa5338d) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_combo_phy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 6968de4f3477..157d8c8c605a 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -258,7 +258,7 @@ static bool phy_is_master(struct drm_i915_private *dev_priv, enum phy phy) static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, enum phy phy) { - bool ret; + bool ret = true; u32 expected_val = 0; if (!icl_combo_phy_enabled(dev_priv, phy)) @@ -276,7 +276,7 @@ static bool icl_combo_phy_verify_state(struct drm_i915_private *dev_priv, DCC_MODE_SELECT_CONTINUOSLY); } - ret = cnl_verify_procmon_ref_values(dev_priv, phy); + ret &= cnl_verify_procmon_ref_values(dev_priv, phy); if (phy_is_master(dev_priv, phy)) { ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW8(phy), -- cgit v1.2.3 From 9ab57658a608f879469ffa22b723c4539c05a58f Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Tue, 18 Aug 2020 11:38:49 -0400 Subject: drm/i915: Fix sha_text population code This patch fixes a few bugs: 1- We weren't taking into account sha_leftovers when adding multiple ksvs to sha_text. As such, we were or'ing the end of ksv[j - 1] with the beginning of ksv[j] 2- In the sha_leftovers == 2 and sha_leftovers == 3 case, bstatus was being placed on the wrong half of sha_text, overlapping the leftover ksv value 3- In the sha_leftovers == 2 case, we need to manually terminate the byte stream with 0x80 since the hardware doesn't have enough room to add it after writing M0 The upside is that all of the HDCP supported HDMI repeaters I could find on Amazon just strip HDCP anyways, so it turns out to be _really_ hard to hit any of these cases without an MST hub, which is not (yet) supported. Oh, and the sha_leftovers == 1 case works perfectly! Fixes: ee5e5e7a5e0f ("drm/i915: Add HDCP framework + base implementation") Cc: Chris Wilson Cc: Ramalingam C Cc: Daniel Vetter Cc: Sean Paul Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Cc: # v4.17+ Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Signed-off-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-2-sean@poorly.run (cherry picked from commit 1f0882214fd0037b74f245d9be75c31516fed040) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp.c | 26 ++++++++++++++++++++------ include/drm/drm_hdcp.h | 3 +++ 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 89a4d294822d..6189b7583277 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -336,8 +336,10 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Fill up the empty slots in sha_text and write it out */ sha_empty = sizeof(sha_text) - sha_leftovers; - for (j = 0; j < sha_empty; j++) - sha_text |= ksv[j] << ((sizeof(sha_text) - j - 1) * 8); + for (j = 0; j < sha_empty; j++) { + u8 off = ((sizeof(sha_text) - j - 1 - sha_leftovers) * 8); + sha_text |= ksv[j] << off; + } ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) @@ -435,7 +437,7 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, /* Write 32 bits of text */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24 | bstatus[1] << 16; + sha_text |= bstatus[0] << 8 | bstatus[1]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; @@ -450,17 +452,29 @@ int intel_hdcp_validate_v_prime(struct intel_connector *connector, return ret; sha_idx += sizeof(sha_text); } + + /* + * Terminate the SHA-1 stream by hand. For the other leftover + * cases this is appended by the hardware. + */ + intel_de_write(dev_priv, HDCP_REP_CTL, + rep_ctl | HDCP_SHA1_TEXT_32); + sha_text = DRM_HDCP_SHA1_TERMINATOR << 24; + ret = intel_write_sha_text(dev_priv, sha_text); + if (ret < 0) + return ret; + sha_idx += sizeof(sha_text); } else if (sha_leftovers == 3) { - /* Write 32 bits of text */ + /* Write 32 bits of text (filled from LSB) */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_32); - sha_text |= bstatus[0] << 24; + sha_text |= bstatus[0]; ret = intel_write_sha_text(dev_priv, sha_text); if (ret < 0) return ret; sha_idx += sizeof(sha_text); - /* Write 8 bits of text, 24 bits of M0 */ + /* Write 8 bits of text (filled from LSB), 24 bits of M0 */ intel_de_write(dev_priv, HDCP_REP_CTL, rep_ctl | HDCP_SHA1_TEXT_8); ret = intel_write_sha_text(dev_priv, bstatus[1]); diff --git a/include/drm/drm_hdcp.h b/include/drm/drm_hdcp.h index c6bab4986a65..fe58dbb46962 100644 --- a/include/drm/drm_hdcp.h +++ b/include/drm/drm_hdcp.h @@ -29,6 +29,9 @@ /* Slave address for the HDCP registers in the receiver */ #define DRM_HDCP_DDC_ADDR 0x3A +/* Value to use at the end of the SHA-1 bytestream used for repeaters */ +#define DRM_HDCP_SHA1_TERMINATOR 0x80 + /* HDCP register offsets for HDMI/DVI devices */ #define DRM_HDCP_DDC_BKSV 0x00 #define DRM_HDCP_DDC_RI_PRIME 0x08 -- cgit v1.2.3 From 57537b4e1d37002ed8cbd0a9be082104749e9d8f Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Tue, 18 Aug 2020 11:38:50 -0400 Subject: drm/i915: Clear the repeater bit on HDCP disable On HDCP disable, clear the repeater bit. This ensures if we connect a non-repeater sink after a repeater, the bit is in the state we expect. Fixes: ee5e5e7a5e0f ("drm/i915: Add HDCP framework + base implementation") Cc: Chris Wilson Cc: Ramalingam C Cc: Daniel Vetter Cc: Sean Paul Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: intel-gfx@lists.freedesktop.org Cc: # v4.17+ Reviewed-by: Ramalingam C Signed-off-by: Sean Paul Signed-off-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20200818153910.27894-3-sean@poorly.run (cherry picked from commit 2cc0c7b520bf8ea20ec42285d4e3d37b467eb7f9) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_hdcp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 6189b7583277..1a0d49af2a08 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -795,6 +795,7 @@ static int _intel_hdcp_disable(struct intel_connector *connector) struct intel_hdcp *hdcp = &connector->hdcp; enum port port = dig_port->base.port; enum transcoder cpu_transcoder = hdcp->cpu_transcoder; + u32 repeater_ctl; int ret; drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP is being disabled...\n", @@ -810,6 +811,11 @@ static int _intel_hdcp_disable(struct intel_connector *connector) return -ETIMEDOUT; } + repeater_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, + port); + intel_de_write(dev_priv, HDCP_REP_CTL, + intel_de_read(dev_priv, HDCP_REP_CTL) & ~repeater_ctl); + ret = hdcp->shim->toggle_signalling(dig_port, false); if (ret) { drm_err(&dev_priv->drm, "Failed to disable HDCP signalling\n"); -- cgit v1.2.3 From 7c62235b95db29210814b771a05279121400af5e Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Mon, 24 Aug 2020 16:50:12 +0800 Subject: drm/amd/pm: fix is_dpm_running() run error on 32bit system v1: the C type "unsigned long" size is 32bit on 32bit system, it will cause code logic error, so replace it with "uint64_t". v2: remove duplicate cast operation. Signed-off-by: Kevin Suggest-by: Jiansong Chen Reviewed-by: Jiansong Chen Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 10 +++++++--- drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 10 +++++++--- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 10 +++++++--- 3 files changed, 21 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c index fb962b9ceffb..9582b38162f0 100644 --- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c @@ -1840,10 +1840,14 @@ static bool arcturus_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c index 9f62af9abd23..3d5eae956a23 100644 --- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c @@ -1331,10 +1331,14 @@ static bool navi10_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 638760839c15..1df03a35de82 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -1147,10 +1147,14 @@ static bool sienna_cichlid_is_dpm_running(struct smu_context *smu) { int ret = 0; uint32_t feature_mask[2]; - unsigned long feature_enabled; + uint64_t feature_enabled; + ret = smu_cmn_get_enabled_mask(smu, feature_mask, 2); - feature_enabled = (unsigned long)((uint64_t)feature_mask[0] | - ((uint64_t)feature_mask[1] << 32)); + if (ret) + return false; + + feature_enabled = (uint64_t)feature_mask[1] << 32 | feature_mask[0]; + return !!(feature_enabled & SMC_DPM_FEATURE); } -- cgit v1.2.3 From 971df65cbf32da9bc9af52c1196ca504dd316086 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 25 Aug 2020 13:51:29 +0800 Subject: drm/amd/pm: avoid false alarm due to confusing softwareshutdowntemp setting Normally softwareshutdowntemp should be greater than Thotspotlimit. However, on some VEGA10 ASIC, the softwareshutdowntemp is 91C while Thotspotlimit is 105C. This seems not right and may trigger some false alarms. Signed-off-by: Evan Quan Acked-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index d572ba4ec9b1..952cd3d7240e 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -374,8 +374,18 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, /* compare them in unit celsius degree */ if (low < range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) low = range->min / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - if (high > tdp_table->usSoftwareShutdownTemp) - high = tdp_table->usSoftwareShutdownTemp; + + /* + * As a common sense, usSoftwareShutdownTemp should be bigger + * than ThotspotLimit. For any invalid usSoftwareShutdownTemp, + * we will just use the max possible setting VEGA10_THERMAL_MAXIMUM_ALERT_TEMP + * to avoid false alarms. + */ + if ((tdp_table->usSoftwareShutdownTemp > + range->hotspot_crit_max / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)) { + if (high > tdp_table->usSoftwareShutdownTemp) + high = tdp_table->usSoftwareShutdownTemp; + } if (low > high) return -EINVAL; -- cgit v1.2.3 From 33286b793b079c237ee73f7264294769ea0e8076 Mon Sep 17 00:00:00 2001 From: Jiansong Chen Date: Thu, 27 Aug 2020 14:31:20 +0800 Subject: drm/amd/pm: enable MP0 DPM for sienna_cichlid Enable MP0 clock DPM for sienna_cichlid. Signed-off-by: Jiansong Chen Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c index 1df03a35de82..61f4ddae262d 100644 --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c @@ -68,7 +68,8 @@ FEATURE_MASK(FEATURE_DPM_LINK_BIT) | \ FEATURE_MASK(FEATURE_DPM_SOCCLK_BIT) | \ FEATURE_MASK(FEATURE_DPM_FCLK_BIT) | \ - FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT)) + FEATURE_MASK(FEATURE_DPM_DCEFCLK_BIT) | \ + FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT)) #define SMU_11_0_7_GFX_BUSY_THRESHOLD 15 @@ -229,6 +230,7 @@ sienna_cichlid_get_allowed_feature_mask(struct smu_context *smu, *(uint64_t *)feature_mask |= FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | FEATURE_MASK(FEATURE_DPM_FCLK_BIT) + | FEATURE_MASK(FEATURE_DPM_MP0CLK_BIT) | FEATURE_MASK(FEATURE_DS_SOCCLK_BIT) | FEATURE_MASK(FEATURE_DS_DCEFCLK_BIT) | FEATURE_MASK(FEATURE_DS_FCLK_BIT) -- cgit v1.2.3 From f7b2e34b4afb8d712913dc199d3292ea9e078637 Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman Date: Thu, 27 Aug 2020 17:07:33 +0530 Subject: drm/amdgpu: Specify get_argument function for ci_smu_funcs Starting in Linux 5.8, the graphics and memory clock frequency were not being reported for CIK cards. This is a regression, since they were reported correctly in Linux 5.7. After investigation, I discovered that the smum_send_msg_to_smc() function, attempts to call the corresponding get_argument() function of ci_smu_funcs. However, the get_argument() function is not defined in ci_smu_funcs. This patch fixes the bug by specifying the correct get_argument() function. Fixes: a0ec225633d9f6 ("drm/amd/powerplay: unified interfaces for message issuing and response checking") Signed-off-by: Sandeep Raghuraman Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index c18169aa59ce..e4d1f3d66ef4 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -37,6 +37,7 @@ #include "cgs_common.h" #include "atombios.h" #include "pppcielanes.h" +#include "smu7_smumgr.h" #include "smu/smu_7_0_1_d.h" #include "smu/smu_7_0_1_sh_mask.h" @@ -2948,6 +2949,7 @@ const struct pp_smumgr_func ci_smu_funcs = { .request_smu_load_specific_fw = NULL, .send_msg_to_smc = ci_send_msg_to_smc, .send_msg_to_smc_with_parameter = ci_send_msg_to_smc_with_parameter, + .get_argument = smu7_get_argument, .download_pptable_settings = NULL, .upload_pptable_settings = NULL, .get_offsetof = ci_get_offsetof, -- cgit v1.2.3 From d98299885c9ea140c1108545186593deba36c4ac Mon Sep 17 00:00:00 2001 From: Sandeep Raghuraman Date: Thu, 27 Aug 2020 18:43:37 +0530 Subject: drm/amdgpu: Fix bug in reporting voltage for CIK On my R9 390, the voltage was reported as a constant 1000 mV. This was due to a bug in smu7_hwmgr.c, in the smu7_read_sensor() function, where some magic constants were used in a condition, to determine whether the voltage should be read from PLANE2_VID or PLANE1_VID. The VDDC mask was incorrectly used, instead of the VDDGFX mask. This patch changes the code to use the correct defined constants (and apply the correct bitshift), thus resulting in correct voltage reporting. Signed-off-by: Sandeep Raghuraman Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index ffe05b7cc1f0..4a3b64aa21ce 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -3581,7 +3581,8 @@ static int smu7_read_sensor(struct pp_hwmgr *hwmgr, int idx, case AMDGPU_PP_SENSOR_GPU_POWER: return smu7_get_gpu_power(hwmgr, (uint32_t *)value); case AMDGPU_PP_SENSOR_VDDGFX: - if ((data->vr_config & 0xff) == 0x2) + if ((data->vr_config & VRCONF_VDDGFX_MASK) == + (VR_SVI2_PLANE_2 << VRCONF_VDDGFX_SHIFT)) val_vid = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_SVI2_STATUS, PLANE2_VID); else -- cgit v1.2.3 From fc8c70526bd30733ea8667adb8b8ffebea30a8ed Mon Sep 17 00:00:00 2001 From: Kai-Heng Feng Date: Wed, 26 Aug 2020 01:33:48 +0800 Subject: drm/radeon: Prefer lower feedback dividers Commit 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") fixed screen flicker for HP Compaq nx9420 but breaks other laptops like Asus X50SL. Turns out we also need to favor lower feedback dividers. Users confirmed this change fixes the regression and doesn't regress the original fix. Fixes: 2e26ccb119bd ("drm/radeon: prefer lower reference dividers") BugLink: https://bugs.launchpad.net/bugs/1791312 BugLink: https://bugs.launchpad.net/bugs/1861554 Reviewed-by: Christian König Signed-off-by: Kai-Heng Feng Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e0ae911ef427..7b69d6dfe44a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -933,7 +933,7 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, /* get matching reference and feedback divider */ *ref_div = min(max(den/post_div, 1u), ref_div_max); - *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); + *fb_div = max(nom * *ref_div * post_div / den, 1u); /* limit fb divider to its maximum */ if (*fb_div > fb_div_max) { -- cgit v1.2.3 From a255e9c8694d3ed240480d1b4d95d325a37358b3 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Mon, 10 Aug 2020 17:18:37 -0400 Subject: drm/nouveau/kms/gv100-: Include correct push header in crcc37d.c Looks like when we converted everything over to Nvidia's class headers, we mistakenly included the nvif/push507b.h instead of nvif/pushc37b.h, which resulted in breaking CRC reporting for volta+: nouveau 0000:1f:00.0: disp: chid 0 stat 10003361 reason 3 [RESERVED_METHOD] mthd 0d84 data 00000000 code 00000000 nouveau 0000:1f:00.0: disp: chid 0 stat 10003360 reason 3 [RESERVED_METHOD] mthd 0d80 data 00000000 code 00000000 nouveau 0000:1f:00.0: DRM: CRC notifier ctx for head 3 not finished after 50ms So, fix that. Signed-off-by: Lyude Paul Fixes: c4b27bc8682c ("drm/nouveau/kms/nv50-: convert core crc_set_src() to new push macros") Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/crcc37d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c index 9afe9a87bde0..814e5bd97446 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crcc37d.c @@ -6,7 +6,7 @@ #include "disp.h" #include "head.h" -#include +#include #include -- cgit v1.2.3 From 35dde8d406369486e54cd628b0b3e6547bfb93a6 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Mon, 10 Aug 2020 10:48:20 +1000 Subject: drm/nouveau/kms/nv50-: add some whitespace before debug message Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/include/nvif/push507c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/include/nvif/push507c.h b/drivers/gpu/drm/nouveau/include/nvif/push507c.h index 889467f13fd9..7917bead4845 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/push507c.h +++ b/drivers/gpu/drm/nouveau/include/nvif/push507c.h @@ -20,6 +20,6 @@ PUSH_ASSERT(!((o) & ~DRF_SMASK(NV507C_DMA_JUMP_OFFSET)), "offset"); \ PUSH_DATA__((p), NVDEF(NV507C, DMA, OPCODE, JUMP) | \ NVVAL(NV507C, DMA, JUMP_OFFSET, (o) >> 2), \ - "jump 0x%08x - %s", (u32)(o), __func__); \ + " jump 0x%08x - %s", (u32)(o), __func__); \ } while(0) #endif -- cgit v1.2.3 From a9cfcfcad50c7bf4ef7335a3eefba8d989d15c06 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 11 Aug 2020 10:11:38 +1000 Subject: drm/nouveau/kms/nv50-gp1xx: disable notifies again after core update This was lost during the header conversion. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/dispnv50/core507d.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c index ad1f09a143aa..248edf69e168 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c @@ -50,7 +50,10 @@ core507d_update(struct nv50_core *core, u32 *interlock, bool ntfy) interlock[NV50_DISP_INTERLOCK_OVLY] | NVDEF(NV507D, UPDATE, NOT_DRIVER_FRIENDLY, FALSE) | NVDEF(NV507D, UPDATE, NOT_DRIVER_UNFRIENDLY, FALSE) | - NVDEF(NV507D, UPDATE, INHIBIT_INTERRUPTS, FALSE)); + NVDEF(NV507D, UPDATE, INHIBIT_INTERRUPTS, FALSE), + + SET_NOTIFIER_CONTROL, + NVDEF(NV507D, SET_NOTIFIER_CONTROL, NOTIFY, DISABLE)); return PUSH_KICK(push); } -- cgit v1.2.3 From ca386aa7155a5467fa7b2b8376f4da8f8e59be4d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 2 Sep 2020 15:30:33 +1000 Subject: drm/nouveau/kms/nv50-gp1xx: add WAR for EVO push buffer HW bug Thanks to NVIDIA for confirming this workaround, and clarifying which HW is affected. Signed-off-by: Ben Skeggs Tested-by: Alexander Kapshuk --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index e7874877da85..1ed242070001 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -257,6 +257,12 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, dmac->push->end = dmac->push->bgn; dmac->max = 0x1000/4 - 1; + /* EVO channels are affected by a HW bug where the last 12 DWORDs + * of the push buffer aren't able to be used safely. + */ + if (disp->oclass < GV100_DISP) + dmac->max -= 12; + args->pushbuf = nvif_handle(&dmac->_push.mem.object); ret = nv50_chan_create(device, disp, oclass, head, data, size, -- cgit v1.2.3 From bc21585f3ff050f3fc7faaefc5e5c0541cec7aae Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Sat, 29 Aug 2020 06:51:41 +0200 Subject: drm/amdgpu: disable gpu-sched load balance for uvd On hardware with multiple uvd instances, dependent uvd jobs may get scheduled to different uvd instances. Because uvd_enc jobs retain hw context, dependent jobs should always run on the same uvd instance. This patch disables GPU scheduler's load balancer for a context that binds jobs from the same context to a uvd instance. v2: Squash in uvd_enc fix Signed-off-by: Nirmoy Das Reviewed-by: Christian König Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 59032c26fc82..c80d8339f58c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -114,7 +114,11 @@ static int amdgpu_ctx_init_entity(struct amdgpu_ctx *ctx, u32 hw_ip, scheds = adev->gpu_sched[hw_ip][hw_prio].sched; num_scheds = adev->gpu_sched[hw_ip][hw_prio].num_scheds; - if (hw_ip == AMDGPU_HW_IP_VCN_ENC || hw_ip == AMDGPU_HW_IP_VCN_DEC) { + /* disable load balance if the hw engine retains context among dependent jobs */ + if (hw_ip == AMDGPU_HW_IP_VCN_ENC || + hw_ip == AMDGPU_HW_IP_VCN_DEC || + hw_ip == AMDGPU_HW_IP_UVD_ENC || + hw_ip == AMDGPU_HW_IP_UVD) { sched = drm_sched_pick_best(scheds, num_scheds); scheds = &sched; num_scheds = 1; -- cgit v1.2.3 From 337b57aecb3e11294b0e547aac871a5481fd42ed Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Aug 2020 23:22:24 -0400 Subject: drm/amdgpu/swsmu: add new callback for getting fan parameters To fetch the max rpm from pptable. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 4 ++++ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 2 ++ drivers/gpu/drm/amd/pm/swsmu/smu_internal.h | 1 + 3 files changed, 7 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 4c5c041af4ee..787fc682e0a5 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -452,6 +452,9 @@ struct smu_context struct work_struct throttling_logging_work; atomic64_t throttle_int_counter; + + unsigned fan_max_rpm; + unsigned manual_fan_speed_rpm; }; struct i2c_adapter; @@ -598,6 +601,7 @@ struct pptable_funcs { int (*enable_mgpu_fan_boost)(struct smu_context *smu); int (*gfx_ulv_control)(struct smu_context *smu, bool enablement); int (*deep_sleep_control)(struct smu_context *smu, bool enablement); + int (*get_fan_parameters)(struct smu_context *smu); }; typedef enum { diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 8462b30f4fe3..114e85613e24 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -504,6 +504,8 @@ static int smu_late_init(void *handle) smu_get_unique_id(smu); + smu_get_fan_parameters(smu); + smu_handle_task(&adev->smu, smu->smu_dpm.dpm_level, AMD_PP_TASK_COMPLETE_INIT, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h index c88f8fab1bae..38c10177ed21 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h +++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h @@ -94,6 +94,7 @@ #define smu_set_pp_feature_mask(smu, new_mask) smu_ppt_funcs(set_pp_feature_mask, 0, smu, new_mask) #define smu_gfx_ulv_control(smu, enablement) smu_ppt_funcs(gfx_ulv_control, 0, smu, enablement) #define smu_deep_sleep_control(smu, enablement) smu_ppt_funcs(deep_sleep_control, 0, smu, enablement) +#define smu_get_fan_parameters(smu) smu_ppt_funcs(get_fan_parameters, 0, smu) #endif #endif -- cgit v1.2.3 From 3204ff3e08f2c1bf7f7c93a15bae77d0043587d6 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Aug 2020 23:34:57 -0400 Subject: drm/amdgpu/swsmu: add get_fan_parameters callbacks for smu11 asics grab the value from the pptable. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 10 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 10 ++++++++++ drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 10 ++++++++++ 3 files changed, 30 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 59b245c6c4d7..198fc1185b2d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1148,6 +1148,15 @@ static int arcturus_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int arcturus_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int arcturus_get_power_limit(struct smu_context *smu) { struct smu_11_0_powerplay_table *powerplay_table = @@ -2397,6 +2406,7 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .get_gpu_metrics = arcturus_get_gpu_metrics, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = arcturus_get_fan_parameters, }; void arcturus_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index cc67d5c60f3d..3a9500dcb436 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1385,6 +1385,15 @@ static int navi10_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int navi10_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf) { DpmActivityMonitorCoeffInt_t activity_monitor; @@ -2666,6 +2675,7 @@ static const struct pptable_funcs navi10_ppt_funcs = { .enable_mgpu_fan_boost = navi10_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = navi10_get_fan_parameters, }; void navi10_set_ppt_funcs(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index b67931fd64b4..2ac942b13bad 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1192,6 +1192,15 @@ static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, return ret; } +static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) +{ + PPTable_t *pptable = smu->smu_table.driver_pptable; + + smu->fan_max_rpm = pptable->FanMaximumRpm; + + return 0; +} + static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *buf) { DpmActivityMonitorCoeffInt_t activity_monitor; @@ -2811,6 +2820,7 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .enable_mgpu_fan_boost = sienna_cichlid_enable_mgpu_fan_boost, .gfx_ulv_control = smu_v11_0_gfx_ulv_control, .deep_sleep_control = smu_v11_0_deep_sleep_control, + .get_fan_parameters = sienna_cichlid_get_fan_parameters, }; void sienna_cichlid_set_ppt_funcs(struct smu_context *smu) -- cgit v1.2.3 From eff6474260028d7293ac23234f33b49cde0f85f0 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 26 Aug 2020 23:49:37 -0400 Subject: drm/amdgpu/swsmu: drop get_fan_speed_percent (v2) No longer needed as we can calculate it based on the fan's max rpm. v2: rework code to avoid possible uninitialized variable use. Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 12 ++++++++++-- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 21 --------------------- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 19 ------------------- .../gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 19 ------------------- 5 files changed, 10 insertions(+), 62 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 787fc682e0a5..0ca997f83fb6 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -498,7 +498,6 @@ struct pptable_funcs { int (*notify_smc_display_config)(struct smu_context *smu); int (*set_cpu_power_state)(struct smu_context *smu); bool (*is_dpm_running)(struct smu_context *smu); - int (*get_fan_speed_percent)(struct smu_context *smu, uint32_t *speed); int (*get_fan_speed_rpm)(struct smu_context *smu, uint32_t *speed); int (*set_watermarks_table)(struct smu_context *smu, struct dm_pp_wm_sets_with_clock_ranges_soc15 *clock_ranges); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 114e85613e24..53e2051432bf 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2192,17 +2192,25 @@ int smu_set_fan_control_mode(struct smu_context *smu, int value) int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) { int ret = 0; + uint32_t percent; + uint32_t current_rpm; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->get_fan_speed_percent) - ret = smu->ppt_funcs->get_fan_speed_percent(smu, speed); + if (smu->ppt_funcs->get_fan_speed_rpm) { + ret = smu->ppt_funcs->get_fan_speed_rpm(smu, ¤t_rpm); + if (!ret) { + percent = current_rpm * 100 / smu->fan_max_rpm; + *speed = percent > 100 ? 100 : percent; + } + } mutex_unlock(&smu->mutex); + return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 198fc1185b2d..1998e7916fef 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1128,26 +1128,6 @@ static int arcturus_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int arcturus_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - PPTable_t *pptable = smu->smu_table.driver_pptable; - uint32_t percent, current_rpm; - int ret = 0; - - if (!speed) - return -EINVAL; - - ret = arcturus_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int arcturus_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2338,7 +2318,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .print_clk_levels = arcturus_print_clk_levels, .force_clk_levels = arcturus_force_clk_levels, .read_sensor = arcturus_read_sensor, - .get_fan_speed_percent = arcturus_get_fan_speed_percent, .get_fan_speed_rpm = arcturus_get_fan_speed_rpm, .get_power_profile_mode = arcturus_get_power_profile_mode, .set_power_profile_mode = arcturus_set_power_profile_mode, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 3a9500dcb436..d5c25e538a03 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1367,24 +1367,6 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int navi10_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = navi10_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int navi10_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2606,7 +2588,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .display_config_changed = navi10_display_config_changed, .notify_smc_display_config = navi10_notify_smc_display_config, .is_dpm_running = navi10_is_dpm_running, - .get_fan_speed_percent = navi10_get_fan_speed_percent, .get_fan_speed_rpm = navi10_get_fan_speed_rpm, .get_power_profile_mode = navi10_get_power_profile_mode, .set_power_profile_mode = navi10_set_power_profile_mode, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 2ac942b13bad..97e54d382862 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1174,24 +1174,6 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, speed); } -static int sienna_cichlid_get_fan_speed_percent(struct smu_context *smu, - uint32_t *speed) -{ - int ret = 0; - uint32_t percent = 0; - uint32_t current_rpm; - PPTable_t *pptable = smu->smu_table.driver_pptable; - - ret = sienna_cichlid_get_fan_speed_rpm(smu, ¤t_rpm); - if (ret) - return ret; - - percent = current_rpm * 100 / pptable->FanMaximumRpm; - *speed = percent > 100 ? 100 : percent; - - return ret; -} - static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) { PPTable_t *pptable = smu->smu_table.driver_pptable; @@ -2753,7 +2735,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .display_config_changed = sienna_cichlid_display_config_changed, .notify_smc_display_config = sienna_cichlid_notify_smc_display_config, .is_dpm_running = sienna_cichlid_is_dpm_running, - .get_fan_speed_percent = sienna_cichlid_get_fan_speed_percent, .get_fan_speed_rpm = sienna_cichlid_get_fan_speed_rpm, .get_power_profile_mode = sienna_cichlid_get_power_profile_mode, .set_power_profile_mode = sienna_cichlid_set_power_profile_mode, -- cgit v1.2.3 From 8d6e65adc25e23fabbc5293b6cd320195c708dca Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 27 Aug 2020 00:04:24 -0400 Subject: drm/amdgpu/swsmu: drop set_fan_speed_percent (v2) No longer needed as we can calculate it based on the fan's max rpm. v2: minor code rework Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h | 1 - drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 --- drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 9 +++++-- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 1 - drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 1 - .../drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 1 - drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 31 +--------------------- 7 files changed, 8 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h index 0ca997f83fb6..d22a759b6b43 100644 --- a/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h +++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_smu.h @@ -573,7 +573,6 @@ struct pptable_funcs { int (*conv_power_profile_to_pplib_workload)(int power_profile); uint32_t (*get_fan_control_mode)(struct smu_context *smu); int (*set_fan_control_mode)(struct smu_context *smu, uint32_t mode); - int (*set_fan_speed_percent)(struct smu_context *smu, uint32_t speed); int (*set_fan_speed_rpm)(struct smu_context *smu, uint32_t speed); int (*set_xgmi_pstate)(struct smu_context *smu, uint32_t pstate); int (*gfx_off_control)(struct smu_context *smu, bool enable); diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 2a3f1ee4a50b..8307e2b790da 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -200,9 +200,6 @@ int smu_v11_0_set_fan_control_mode(struct smu_context *smu, uint32_t mode); -int -smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed); - int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 53e2051432bf..7a55ece1f124 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -2217,14 +2217,19 @@ int smu_get_fan_speed_percent(struct smu_context *smu, uint32_t *speed) int smu_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) { int ret = 0; + uint32_t rpm; if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) return -EOPNOTSUPP; mutex_lock(&smu->mutex); - if (smu->ppt_funcs->set_fan_speed_percent) - ret = smu->ppt_funcs->set_fan_speed_percent(smu, speed); + if (smu->ppt_funcs->set_fan_speed_rpm) { + if (speed > 100) + speed = 100; + rpm = speed * smu->fan_max_rpm / 100; + ret = smu->ppt_funcs->set_fan_speed_rpm(smu, rpm); + } mutex_unlock(&smu->mutex); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index 1998e7916fef..f6d9b0db3e82 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -2363,7 +2363,6 @@ static const struct pptable_funcs arcturus_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index d5c25e538a03..87b5f9ff4021 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -2631,7 +2631,6 @@ static const struct pptable_funcs navi10_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 97e54d382862..863372436b98 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -2778,7 +2778,6 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = { .display_clock_voltage_request = smu_v11_0_display_clock_voltage_request, .get_fan_control_mode = smu_v11_0_get_fan_control_mode, .set_fan_control_mode = smu_v11_0_set_fan_control_mode, - .set_fan_speed_percent = smu_v11_0_set_fan_speed_percent, .set_fan_speed_rpm = smu_v11_0_set_fan_speed_rpm, .set_xgmi_pstate = smu_v11_0_set_xgmi_pstate, .gfx_off_control = smu_v11_0_gfx_off_control, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index ec20e839f555..5abc06f7c9f3 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1099,35 +1099,6 @@ smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode) return 0; } -int -smu_v11_0_set_fan_speed_percent(struct smu_context *smu, uint32_t speed) -{ - struct amdgpu_device *adev = smu->adev; - uint32_t duty100, duty; - uint64_t tmp64; - - if (speed > 100) - speed = 100; - - if (smu_v11_0_auto_fan_control(smu, 0)) - return -EINVAL; - - duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1), - CG_FDO_CTRL1, FMAX_DUTY100); - if (!duty100) - return -EINVAL; - - tmp64 = (uint64_t)speed * duty100; - do_div(tmp64, 100); - duty = (uint32_t)tmp64; - - WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0, - REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0), - CG_FDO_CTRL0, FDO_STATIC_DUTY, duty)); - - return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC); -} - int smu_v11_0_set_fan_control_mode(struct smu_context *smu, uint32_t mode) @@ -1136,7 +1107,7 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu, switch (mode) { case AMD_FAN_CTRL_NONE: - ret = smu_v11_0_set_fan_speed_percent(smu, 100); + ret = smu_v11_0_set_fan_speed_rpm(smu, smu->fan_max_rpm); break; case AMD_FAN_CTRL_MANUAL: ret = smu_v11_0_auto_fan_control(smu, 0); -- cgit v1.2.3 From 9a7fd01384c3fdb16e303e2b13810d3f72835d2a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 25 Aug 2020 14:35:50 -0400 Subject: drm/amdgpu/swsmu: add smu11 helper to get manual fan speed (v2) Will be used to fetch the fan speeds when manual fan mode is set. v2: squash in a Coverity fix from Colin Ian King Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/inc/smu_v11_0.h | 3 +++ drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h index 8307e2b790da..1f9575a4dfe7 100644 --- a/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h +++ b/drivers/gpu/drm/amd/pm/inc/smu_v11_0.h @@ -203,6 +203,9 @@ smu_v11_0_set_fan_control_mode(struct smu_context *smu, int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, uint32_t speed); +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed); + int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, uint32_t pstate); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c index 5abc06f7c9f3..f5aeb0b5cf97 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c @@ -1153,6 +1153,27 @@ int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu, return ret; } +int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu, + uint32_t *speed) +{ + struct amdgpu_device *adev = smu->adev; + uint32_t tach_period, crystal_clock_freq; + uint64_t tmp64; + + tach_period = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL), + CG_TACH_CTRL, TARGET_PERIOD); + if (!tach_period) + return -EINVAL; + + crystal_clock_freq = amdgpu_asic_get_xclk(adev); + + tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000; + do_div(tmp64, (tach_period * 8)); + *speed = (uint32_t)tmp64; + + return 0; +} + int smu_v11_0_set_xgmi_pstate(struct smu_context *smu, uint32_t pstate) { -- cgit v1.2.3 From f6eb433954bf32ab582208d9b58ec397f7814e5a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 27 Aug 2020 00:12:38 -0400 Subject: drm/amdgpu/swsmu: handle manual fan readback on SMU11 Need to read back from registers for manual mode rather than using the metrics table. Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1164 Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c | 11 ++++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c | 11 ++++++++--- drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c | 11 ++++++++--- 3 files changed, 24 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c index f6d9b0db3e82..2ce6ad9c6609 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c @@ -1123,9 +1123,14 @@ static int arcturus_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return arcturus_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return arcturus_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int arcturus_get_fan_parameters(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index 87b5f9ff4021..42d53cca7360 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -1362,9 +1362,14 @@ static int navi10_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return navi10_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return navi10_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int navi10_get_fan_parameters(struct smu_context *smu) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c index 863372436b98..5c22611d5878 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c @@ -1169,9 +1169,14 @@ static int sienna_cichlid_get_fan_speed_rpm(struct smu_context *smu, if (!speed) return -EINVAL; - return sienna_cichlid_get_smu_metrics_data(smu, - METRICS_CURR_FANSPEED, - speed); + switch (smu_v11_0_get_fan_control_mode(smu)) { + case AMD_FAN_CTRL_AUTO: + return sienna_cichlid_get_smu_metrics_data(smu, + METRICS_CURR_FANSPEED, + speed); + default: + return smu_v11_0_get_fan_speed_rpm(smu, speed); + } } static int sienna_cichlid_get_fan_parameters(struct smu_context *smu) -- cgit v1.2.3 From 81202807ae6096bfbbfa28c2bc83cae1841bba38 Mon Sep 17 00:00:00 2001 From: Dennis Li Date: Tue, 1 Sep 2020 09:03:53 +0800 Subject: drm/amdgpu: block ring buffer access during GPU recovery When GPU is in reset, its status isn't stable and ring buffer also need be reset when resuming. Therefore driver should protect GPU recovery thread from ring buffer accessed by other threads. Otherwise GPU will randomly hang during recovery. v2: correct indent Reviewed-by: Hawking Zhang Reviewed-by: Christian König Signed-off-by: Dennis Li Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 17 +++++++++++++---- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 5 +++-- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 11 +++++++---- 3 files changed, 23 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 6518e444bead..c4900471beb0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -319,8 +319,12 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, { uint32_t ret; - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) - return amdgpu_kiq_rreg(adev, reg); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + ret = amdgpu_kiq_rreg(adev, reg); + up_read(&adev->reset_sem); + return ret; + } if ((reg * 4) < adev->rmmio_size) ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); @@ -332,6 +336,7 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, ret = readl(((void __iomem *)adev->rmmio) + (mmMM_DATA * 4)); spin_unlock_irqrestore(&adev->mmio_idx_lock, flags); } + trace_amdgpu_mm_rreg(adev->pdev->device, reg, ret); return ret; } @@ -409,8 +414,12 @@ static inline void amdgpu_mm_wreg_mmio(struct amdgpu_device *adev, void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, uint32_t acc_flags) { - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) - return amdgpu_kiq_wreg(adev, reg, v); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev) && + down_read_trylock(&adev->reset_sem)) { + amdgpu_kiq_wreg(adev, reg, v); + up_read(&adev->reset_sem); + return; + } amdgpu_mm_wreg_mmio(adev, reg, v, acc_flags); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index ad9ad622ccce..31359e519d69 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -287,8 +287,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, */ if (adev->gfx.kiq.ring.sched.ready && (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { - + down_read_trylock(&adev->reset_sem)) { struct amdgpu_vmhub *hub = &adev->vmhub[vmhub]; const unsigned eng = 17; u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type); @@ -297,6 +296,8 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid); + + up_read(&adev->reset_sem); return; } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 1ca79030e95e..93ee77b14cc9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -503,13 +503,14 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid, * as GFXOFF under bare metal */ if (adev->gfx.kiq.ring.sched.ready && - (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && - !amdgpu_in_reset(adev)) { + (amdgpu_sriov_runtime(adev) || !amdgpu_sriov_vf(adev)) && + down_read_trylock(&adev->reset_sem)) { uint32_t req = hub->vm_inv_eng0_req + hub->eng_distance * eng; uint32_t ack = hub->vm_inv_eng0_ack + hub->eng_distance * eng; amdgpu_virt_kiq_reg_write_reg_wait(adev, req, ack, inv_req, 1 << vmid); + up_read(&adev->reset_sem); return; } @@ -602,7 +603,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, if (amdgpu_in_reset(adev)) return -EIO; - if (ring->sched.ready) { + if (ring->sched.ready && down_read_trylock(&adev->reset_sem)) { /* Vega20+XGMI caches PTEs in TC and TLB. Add a * heavy-weight TLB flush (type 2), which flushes * both. Due to a race condition with concurrent @@ -629,6 +630,7 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, if (r) { amdgpu_ring_undo(ring); spin_unlock(&adev->gfx.kiq.ring_lock); + up_read(&adev->reset_sem); return -ETIME; } @@ -637,9 +639,10 @@ static int gmc_v9_0_flush_gpu_tlb_pasid(struct amdgpu_device *adev, r = amdgpu_fence_wait_polling(ring, seq, adev->usec_timeout); if (r < 1) { dev_err(adev->dev, "wait for kiq fence error: %ld.\n", r); + up_read(&adev->reset_sem); return -ETIME; } - + up_read(&adev->reset_sem); return 0; } -- cgit v1.2.3 From 3d7248d7cee40ced0ac27517f1678beac67502f5 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Tue, 1 Sep 2020 15:28:06 +0800 Subject: drm/amdgpu: Fix a redundant kfree drm_dev_alloc() alloc *dev* and set managed.final_kfree to dev to free itself. Now from commit 5cdd68498918("drm/amdgpu: Embed drm_device into amdgpu_device (v3)") we alloc *adev* and ddev is just a member of it. So drm_dev_release try to free a wrong pointer then. Also driver's release trys to free adev, but drm_dev_release will access dev after call drvier's release. To fix it, remove driver's release and set managed.final_kfree to adev. [ 36.269348] BUG: unable to handle page fault for address: ffffa0c279940028 [ 36.276841] #PF: supervisor read access in kernel mode [ 36.282434] #PF: error_code(0x0000) - not-present page [ 36.288053] PGD 676601067 P4D 676601067 PUD 86a414067 PMD 86a247067 PTE 800ffff8066bf060 [ 36.296868] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC NOPTI [ 36.302409] CPU: 4 PID: 1375 Comm: bash Tainted: G O 5.9.0-rc2+ #46 [ 36.310670] Hardware name: System manufacturer System Product Name/PRIME Z390-A, BIOS 1401 11/26/2019 [ 36.320725] RIP: 0010:drm_managed_release+0x25/0x110 [drm] [ 36.326741] Code: 80 00 00 00 00 0f 1f 44 00 00 55 48 c7 c2 5a 9f 41 c0 be 00 02 00 00 48 89 e5 41 57 41 56 41 55 41 54 49 89 fc 53 48 83 ec 08 <48> 8b 7f 18 e8 c2 10 ff ff 4d 8b 74 24 20 49 8d 44 24 5 [ 36.347217] RSP: 0018:ffffb9424141fce0 EFLAGS: 00010282 [ 36.352931] RAX: 0000000000000006 RBX: ffffa0c279940010 RCX: 0000000000000006 [ 36.360718] RDX: ffffffffc0419f5a RSI: 0000000000000200 RDI: ffffa0c279940010 [ 36.368503] RBP: ffffb9424141fd10 R08: 0000000000000001 R09: 0000000000000001 [ 36.376304] R10: 0000000000000000 R11: 0000000000000000 R12: ffffa0c279940010 [ 36.384070] R13: ffffffffc0e2a000 R14: ffffa0c26924e220 R15: fffffffffffffff2 [ 36.391845] FS: 00007fc4a277b740(0000) GS:ffffa0c288e00000(0000) knlGS:0000000000000000 [ 36.400669] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 36.406937] CR2: ffffa0c279940028 CR3: 0000000792304006 CR4: 00000000003706e0 [ 36.414732] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 36.422550] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 36.430354] Call Trace: [ 36.433044] drm_dev_put.part.0+0x40/0x60 [drm] [ 36.438017] drm_dev_put+0x13/0x20 [drm] [ 36.442398] amdgpu_pci_remove+0x56/0x60 [amdgpu] [ 36.447528] pci_device_remove+0x3e/0xb0 [ 36.451807] device_release_driver_internal+0xff/0x1d0 [ 36.457416] device_release_driver+0x12/0x20 [ 36.462094] pci_stop_bus_device+0x70/0xa0 [ 36.466588] pci_stop_and_remove_bus_device_locked+0x1b/0x30 [ 36.472786] remove_store+0x7b/0x90 [ 36.476614] dev_attr_store+0x17/0x30 [ 36.480646] sysfs_kf_write+0x4b/0x60 [ 36.484655] kernfs_fop_write+0xe8/0x1d0 [ 36.488952] vfs_write+0xf5/0x230 [ 36.492562] ksys_write+0x70/0xf0 [ 36.496206] __x64_sys_write+0x1a/0x20 [ 36.500292] do_syscall_64+0x38/0x90 [ 36.504219] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: xinhui pan Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index dfc1a9721867..979950133906 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1153,7 +1153,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, if (ret) goto err_free; - drmm_add_final_kfree(ddev, ddev); + drmm_add_final_kfree(ddev, adev); if (!supports_atomic) ddev->driver_features &= ~DRIVER_ATOMIC; @@ -1209,13 +1209,6 @@ amdgpu_pci_remove(struct pci_dev *pdev) drm_dev_put(dev); } -static void amdgpu_driver_release(struct drm_device *ddev) -{ - struct amdgpu_device *adev = drm_to_adev(ddev); - - kfree(adev); -} - static void amdgpu_pci_shutdown(struct pci_dev *pdev) { @@ -1510,7 +1503,6 @@ static struct drm_driver kms_driver = { .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, .lastclose = amdgpu_driver_lastclose_kms, - .release = amdgpu_driver_release, .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, .gem_free_object_unlocked = amdgpu_gem_object_free, -- cgit v1.2.3 From 1545fbf97eafc1dbdc2923e58b4186b16a834784 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Tue, 1 Sep 2020 15:49:36 +0800 Subject: drm/amd/display: Fix a list corruption Remove the private obj from the internal list before we free aconnector. [ 56.925828] BUG: unable to handle page fault for address: ffff8f84a870a560 [ 56.933272] #PF: supervisor read access in kernel mode [ 56.938801] #PF: error_code(0x0000) - not-present page [ 56.944376] PGD 18e605067 P4D 18e605067 PUD 86a614067 PMD 86a4d0067 PTE 800ffff8578f5060 [ 56.953260] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC NOPTI [ 56.958815] CPU: 6 PID: 1407 Comm: bash Tainted: G O 5.9.0-rc2+ #46 [ 56.967092] Hardware name: System manufacturer System Product Name/PRIME Z390-A, BIOS 1401 11/26/2019 [ 56.977162] RIP: 0010:__list_del_entry_valid+0x31/0xa0 [ 56.982768] Code: 00 ad de 55 48 8b 17 4c 8b 47 08 48 89 e5 48 39 c2 74 27 48 b8 22 01 00 00 00 00 ad de 49 39 c0 74 2d 49 8b 30 48 39 fe 75 3d <48> 8b 52 08 48 39 f2 75 4c b8 01 00 00 00 5d c3 48 89 7 [ 57.003327] RSP: 0018:ffffb40c81687c90 EFLAGS: 00010246 [ 57.009048] RAX: dead000000000122 RBX: ffff8f84ea41f4f0 RCX: 0000000000000006 [ 57.016871] RDX: ffff8f84a870a558 RSI: ffff8f84ea41f4f0 RDI: ffff8f84ea41f4f0 [ 57.024672] RBP: ffffb40c81687c90 R08: ffff8f84ea400998 R09: 0000000000000001 [ 57.032490] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000006 [ 57.040287] R13: ffff8f84ea422a90 R14: ffff8f84b4129a20 R15: fffffffffffffff2 [ 57.048105] FS: 00007f550d885740(0000) GS:ffff8f8509600000(0000) knlGS:0000000000000000 [ 57.056979] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 57.063260] CR2: ffff8f84a870a560 CR3: 00000007e5144001 CR4: 00000000003706e0 [ 57.071053] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 57.078849] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 57.086684] Call Trace: [ 57.089381] drm_atomic_private_obj_fini+0x29/0x82 [drm] [ 57.095247] amdgpu_dm_fini+0x83/0x170 [amdgpu] [ 57.100264] dm_hw_fini+0x23/0x30 [amdgpu] [ 57.104814] amdgpu_device_fini+0x1df/0x4fe [amdgpu] [ 57.110271] amdgpu_driver_unload_kms+0x43/0x70 [amdgpu] [ 57.116136] amdgpu_pci_remove+0x3b/0x60 [amdgpu] [ 57.121291] pci_device_remove+0x3e/0xb0 [ 57.125583] device_release_driver_internal+0xff/0x1d0 [ 57.131223] device_release_driver+0x12/0x20 [ 57.135903] pci_stop_bus_device+0x70/0xa0 [ 57.140401] pci_stop_and_remove_bus_device_locked+0x1b/0x30 [ 57.146571] remove_store+0x7b/0x90 [ 57.150429] dev_attr_store+0x17/0x30 [ 57.154441] sysfs_kf_write+0x4b/0x60 [ 57.158479] kernfs_fop_write+0xe8/0x1d0 [ 57.162788] vfs_write+0xf5/0x230 [ 57.166426] ksys_write+0x70/0xf0 [ 57.170087] __x64_sys_write+0x1a/0x20 [ 57.174219] do_syscall_64+0x38/0x90 [ 57.178145] entry_SYSCALL_64_after_hwframe+0x44/0xa9 Signed-off-by: xinhui pan Acked-by: Feifei Xu Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') 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 e2e7138c4e3f..b91ae0feda27 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4993,6 +4993,7 @@ static void amdgpu_dm_connector_destroy(struct drm_connector *connector) struct amdgpu_device *adev = drm_to_adev(connector->dev); struct amdgpu_display_manager *dm = &adev->dm; + drm_atomic_private_obj_fini(&aconnector->mst_mgr.base); #if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) ||\ defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE) -- cgit v1.2.3 From abb6fccbb4e5bab30ff9b96e27acdd9107426f28 Mon Sep 17 00:00:00 2001 From: Alex Sierra Date: Tue, 1 Sep 2020 23:24:56 -0500 Subject: drm/amdgpu: enable ih1 ih2 for Arcturus only Enable multi-ring ih1 and ih2 for Arcturus only. For Navi10 family multi-ring has been disabled. Apparently, having multi-ring enabled in Navi was causing continus page fault interrupts. Further investigation is needed to get to the root cause. Related issue link: https://gitlab.freedesktop.org/drm/amd/-/issues/1279 Signed-off-by: Alex Sierra Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/navi10_ih.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c index 350f1bf063c6..74b1e7dc49a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/navi10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/navi10_ih.c @@ -306,7 +306,8 @@ static int navi10_ih_irq_init(struct amdgpu_device *adev) } else { WREG32_SOC15(OSSSYS, 0, mmIH_RB_CNTL, ih_rb_cntl); } - navi10_ih_reroute_ih(adev); + if (adev->irq.ih1.ring_size) + navi10_ih_reroute_ih(adev); if (unlikely(adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT)) { if (ih->use_bus_addr) { @@ -668,19 +669,26 @@ static int navi10_ih_sw_init(void *handle) adev->irq.ih.use_doorbell = true; adev->irq.ih.doorbell_index = adev->doorbell_index.ih << 1; - r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true); - if (r) - return r; + adev->irq.ih1.ring_size = 0; + adev->irq.ih2.ring_size = 0; - adev->irq.ih1.use_doorbell = true; - adev->irq.ih1.doorbell_index = (adev->doorbell_index.ih + 1) << 1; + if (adev->asic_type < CHIP_NAVI10) { + r = amdgpu_ih_ring_init(adev, &adev->irq.ih1, PAGE_SIZE, true); + if (r) + return r; - r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true); - if (r) - return r; + adev->irq.ih1.use_doorbell = true; + adev->irq.ih1.doorbell_index = + (adev->doorbell_index.ih + 1) << 1; + + r = amdgpu_ih_ring_init(adev, &adev->irq.ih2, PAGE_SIZE, true); + if (r) + return r; - adev->irq.ih2.use_doorbell = true; - adev->irq.ih2.doorbell_index = (adev->doorbell_index.ih + 2) << 1; + adev->irq.ih2.use_doorbell = true; + adev->irq.ih2.doorbell_index = + (adev->doorbell_index.ih + 2) << 1; + } r = amdgpu_irq_init(adev); -- cgit v1.2.3 From 1625951a3a7bdd776d38f2cdd35f72a795e82df0 Mon Sep 17 00:00:00 2001 From: Luben Tuikov Date: Tue, 1 Sep 2020 19:10:32 -0400 Subject: drm/amdgpu: Remove superfluous NULL check The DRM device is a static member of the amdgpu device structure and as such always exists, so long as the PCI and thus the amdgpu device exist. Signed-off-by: Luben Tuikov Acked-by: Daniel Vetter Acked-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index c4900471beb0..6dcc256b9ebc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3471,9 +3471,6 @@ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon) struct drm_connector_list_iter iter; int r; - if (!dev) - return -ENODEV; - adev = drm_to_adev(dev); if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) -- cgit v1.2.3 From ee354ff1c7c210fb41952ebf0a820fb714eae7b1 Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 2 Sep 2020 11:07:14 +0200 Subject: drm/amdgpu: fix max_entries calculation v4 Calculate the correct value for max_entries or we might run after the page_address array. v2: Xinhui pointed out we don't need the shift v3: use local copy of start and simplify some calculation v4: fix the case that we map less VA range than BO size Signed-off-by: Christian König Fixes: 1e691e244487 drm/amdgpu: stop allocating dummy GTT nodes Reviewed-by: xinhui pan Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 620472a70460..37221b99ca96 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1693,13 +1693,13 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, uint64_t max_entries; uint64_t addr, last; + max_entries = mapping->last - start + 1; if (nodes) { addr = nodes->start << PAGE_SHIFT; - max_entries = (nodes->size - pfn) * - AMDGPU_GPU_PAGES_IN_CPU_PAGE; + max_entries = min((nodes->size - pfn) * + AMDGPU_GPU_PAGES_IN_CPU_PAGE, max_entries); } else { addr = 0; - max_entries = S64_MAX; } if (pages_addr) { @@ -1729,7 +1729,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, addr += pfn << PAGE_SHIFT; } - last = min((uint64_t)mapping->last, start + max_entries - 1); + last = start + max_entries - 1; r = amdgpu_vm_bo_update_mapping(adev, vm, false, false, resv, start, last, flags, addr, dma_addr, fence); -- cgit v1.2.3 From 6627d1c1a82ba72d6595a10d7453b6d30e288467 Mon Sep 17 00:00:00 2001 From: Changfeng Date: Tue, 1 Sep 2020 16:17:01 +0800 Subject: drm/amdgpu: add ta firmware load in psp_v12_0 for renoir It needs to load renoir_ta firmware because hdcp is enabled by default for renoir now. This can avoid error:DTM TA is not initialized Signed-off-by: Changfeng Reviewed-by: Bhawanpreet Lakha Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/psp_v12_0.c | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c index 6c9614f77d33..75489313dbad 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c @@ -38,6 +38,8 @@ #include "oss/osssys_4_0_sh_mask.h" MODULE_FIRMWARE("amdgpu/renoir_asd.bin"); +MODULE_FIRMWARE("amdgpu/renoir_ta.bin"); + /* address block */ #define smnMP1_FIRMWARE_FLAGS 0x3010024 @@ -45,7 +47,10 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) { struct amdgpu_device *adev = psp->adev; const char *chip_name; + char fw_name[30]; int err = 0; + const struct ta_firmware_header_v1_0 *ta_hdr; + DRM_DEBUG("\n"); switch (adev->asic_type) { case CHIP_RENOIR: @@ -56,6 +61,55 @@ static int psp_v12_0_init_microcode(struct psp_context *psp) } err = psp_init_asd_microcode(psp, chip_name); + if (err) + goto out; + + snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name); + err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev); + if (err) { + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; + dev_info(adev->dev, + "psp v12.0: Failed to load firmware \"%s\"\n", + fw_name); + } else { + err = amdgpu_ucode_validate(adev->psp.ta_fw); + if (err) + goto out2; + + ta_hdr = (const struct ta_firmware_header_v1_0 *) + adev->psp.ta_fw->data; + adev->psp.ta_hdcp_ucode_version = + le32_to_cpu(ta_hdr->ta_hdcp_ucode_version); + adev->psp.ta_hdcp_ucode_size = + le32_to_cpu(ta_hdr->ta_hdcp_size_bytes); + adev->psp.ta_hdcp_start_addr = + (uint8_t *)ta_hdr + + le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes); + + adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version); + + adev->psp.ta_dtm_ucode_version = + le32_to_cpu(ta_hdr->ta_dtm_ucode_version); + adev->psp.ta_dtm_ucode_size = + le32_to_cpu(ta_hdr->ta_dtm_size_bytes); + adev->psp.ta_dtm_start_addr = + (uint8_t *)adev->psp.ta_hdcp_start_addr + + le32_to_cpu(ta_hdr->ta_dtm_offset_bytes); + } + + return 0; + +out2: + release_firmware(adev->psp.ta_fw); + adev->psp.ta_fw = NULL; +out: + if (err) { + dev_err(adev->dev, + "psp v12.0: Failed to load firmware \"%s\"\n", + fw_name); + } + return err; } -- cgit v1.2.3 From 2d37949dc3bacf3523b97ec84eb16a26574fe5b3 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 3 Sep 2020 10:17:56 +0800 Subject: drm/amdgpu/gfx10: Delete some duplicated argument to '|' 1. gfx_v10_0_soft_reset GRBM_STATUS__SPI_BUSY_MASK 2. gfx_v10_0_update_gfx_clock_gating AMD_CG_SUPPORT_GFX_CGLS Reviewed-by: Huang Rui Signed-off-by: Ye Bin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 2db195ec8d0c..d502e30f67d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -7055,8 +7055,7 @@ static int gfx_v10_0_soft_reset(void *handle) GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK | GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__DB_BUSY_MASK | GRBM_STATUS__CB_BUSY_MASK | GRBM_STATUS__GDS_BUSY_MASK | - GRBM_STATUS__SPI_BUSY_MASK | GRBM_STATUS__GE_BUSY_NO_DMA_MASK - | GRBM_STATUS__BCI_BUSY_MASK)) { + GRBM_STATUS__SPI_BUSY_MASK | GRBM_STATUS__GE_BUSY_NO_DMA_MASK)) { grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_CP, 1); @@ -7449,7 +7448,6 @@ static int gfx_v10_0_update_gfx_clock_gating(struct amdgpu_device *adev, (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_CGCG | - AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) gfx_v10_0_enable_gui_idle_interrupt(adev, enable); -- cgit v1.2.3 From be99ecbfff4e3603994ebfcc37072270b0734ab7 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Sep 2020 17:48:23 -0400 Subject: drm/amdgpu/gmc9: print client id string for gfxhub Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Felix Kuehling Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 93ee77b14cc9..6a0ac57d75ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -71,6 +71,22 @@ #define mmDCHUBBUB_SDPIF_MMIO_CNTRL_0_BASE_IDX 2 +static const char *gfxhub_client_ids[] = { + "CB", + "DB", + "IA", + "WD", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "PA", +}; + static const u32 golden_settings_vega10_hdp[] = { 0xf64, 0x0fffffff, 0x00000000, @@ -303,7 +319,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, { struct amdgpu_vmhub *hub; bool retry_fault = !!(entry->src_data[1] & 0x80); - uint32_t status = 0; + uint32_t status = 0, cid = 0; u64 addr; char hub_name[10]; @@ -340,6 +356,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, RREG32(hub->vm_l2_pro_fault_status); status = RREG32(hub->vm_l2_pro_fault_status); + cid = REG_GET_FIELD(status, + VM_L2_PROTECTION_FAULT_STATUS, CID); WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); } @@ -362,9 +380,13 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - VM_L2_PROTECTION_FAULT_STATUS, CID)); + if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); + else + dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%x\n", + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); -- cgit v1.2.3 From 93fabd84c90683199a294b6696559772f3e43e3a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 1 Sep 2020 17:49:47 -0400 Subject: drm/amdgpu/gmc10: print client id string for gfxhub Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Felix Kuehling Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c | 30 +++++++++++++++++++++++++++--- drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c | 30 +++++++++++++++++++++++++++--- 2 files changed, 54 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c index 76acd7f7723e..b882ac59879a 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_0.c @@ -31,6 +31,27 @@ #include "soc15_common.h" +static const char *gfxhub_client_ids[] = { + "CB/DB", + "Reserved", + "GE1", + "GE2", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "Reserved", + "SDMA0", + "SDMA1", + "GCR", + "SDMA2", + "SDMA3", +}; + static uint32_t gfxhub_v2_0_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -55,12 +76,15 @@ static void gfxhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + u32 cid = REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID); + dev_err(adev->dev, "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c index 80c906a0383f..237a9ff5afa0 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c @@ -31,6 +31,27 @@ #include "soc15_common.h" +static const char *gfxhub_client_ids[] = { + "CB/DB", + "Reserved", + "GE1", + "GE2", + "CPF", + "CPC", + "CPG", + "RLC", + "TCP", + "SQC (inst)", + "SQC (data)", + "SQG", + "Reserved", + "SDMA0", + "SDMA1", + "GCR", + "SDMA2", + "SDMA3", +}; + static uint32_t gfxhub_v2_1_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -55,12 +76,15 @@ static void gfxhub_v2_1_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + u32 cid = REG_GET_FIELD(status, + GCVM_L2_PROTECTION_FAULT_STATUS, CID); + dev_err(adev->dev, "GCVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - GCVM_L2_PROTECTION_FAULT_STATUS, CID)); + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], + cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, GCVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); -- cgit v1.2.3 From 02f23f5f7c4bad0bea5ed1685d78280df0295478 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Sep 2020 13:07:47 -0400 Subject: drm/amdgpu/gmc9: print client id string for mmhub Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 239 ++++++++++++++++++++++++++++++++-- 1 file changed, 230 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 6a0ac57d75ea..d0645ad3446e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -87,6 +87,203 @@ static const char *gfxhub_client_ids[] = { "PA", }; +static const char *mmhub_client_ids_raven[][2] = { + [0][0] = "MP1", + [1][0] = "MP0", + [2][0] = "VCN", + [3][0] = "VCNU", + [4][0] = "HDP", + [5][0] = "DCE", + [13][0] = "UTCL2", + [19][0] = "TLS", + [26][0] = "OSS", + [27][0] = "SDMA0", + [0][1] = "MP1", + [1][1] = "MP0", + [2][1] = "VCN", + [3][1] = "VCNU", + [4][1] = "HDP", + [5][1] = "XDP", + [6][1] = "DBGU0", + [7][1] = "DCE", + [8][1] = "DCEDWB0", + [9][1] = "DCEDWB1", + [26][1] = "OSS", + [27][1] = "SDMA0", +}; + +static const char *mmhub_client_ids_renoir[][2] = { + [0][0] = "MP1", + [1][0] = "MP0", + [2][0] = "HDP", + [4][0] = "DCEDMC", + [5][0] = "DCEVGA", + [13][0] = "UTCL2", + [19][0] = "TLS", + [26][0] = "OSS", + [27][0] = "SDMA0", + [28][0] = "VCN", + [29][0] = "VCNU", + [30][0] = "JPEG", + [0][1] = "MP1", + [1][1] = "MP0", + [2][1] = "HDP", + [3][1] = "XDP", + [6][1] = "DBGU0", + [7][1] = "DCEDMC", + [8][1] = "DCEVGA", + [9][1] = "DCEDWB", + [26][1] = "OSS", + [27][1] = "SDMA0", + [28][1] = "VCN", + [29][1] = "VCNU", + [30][1] = "JPEG", +}; + +static const char *mmhub_client_ids_vega10[][2] = { + [0][0] = "MP0", + [1][0] = "UVD", + [2][0] = "UVDU", + [3][0] = "HDP", + [13][0] = "UTCL2", + [14][0] = "OSS", + [15][0] = "SDMA1", + [32+0][0] = "VCE0", + [32+1][0] = "VCE0U", + [32+2][0] = "XDMA", + [32+3][0] = "DCE", + [32+4][0] = "MP1", + [32+14][0] = "SDMA0", + [0][1] = "MP0", + [1][1] = "UVD", + [2][1] = "UVDU", + [3][1] = "DBGU0", + [4][1] = "HDP", + [5][1] = "XDP", + [14][1] = "OSS", + [15][1] = "SDMA0", + [32+0][1] = "VCE0", + [32+1][1] = "VCE0U", + [32+2][1] = "XDMA", + [32+3][1] = "DCE", + [32+4][1] = "DCEDWB", + [32+5][1] = "MP1", + [32+6][1] = "DBGU1", + [32+14][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_vega12[][2] = { + [0][0] = "MP0", + [1][0] = "VCE0", + [2][0] = "VCE0U", + [3][0] = "HDP", + [13][0] = "UTCL2", + [14][0] = "OSS", + [15][0] = "SDMA1", + [32+0][0] = "DCE", + [32+1][0] = "XDMA", + [32+2][0] = "UVD", + [32+3][0] = "UVDU", + [32+4][0] = "MP1", + [32+15][0] = "SDMA0", + [0][1] = "MP0", + [1][1] = "VCE0", + [2][1] = "VCE0U", + [3][1] = "DBGU0", + [4][1] = "HDP", + [5][1] = "XDP", + [14][1] = "OSS", + [15][1] = "SDMA0", + [32+0][1] = "DCE", + [32+1][1] = "DCEDWB", + [32+2][1] = "XDMA", + [32+3][1] = "UVD", + [32+4][1] = "UVDU", + [32+5][1] = "MP1", + [32+6][1] = "DBGU1", + [32+15][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_vega20[][2] = { + [0][0] = "XDMA", + [1][0] = "DCE", + [2][0] = "VCE0", + [3][0] = "VCE0U", + [4][0] = "UVD", + [5][0] = "UVD1U", + [13][0] = "OSS", + [14][0] = "HDP", + [15][0] = "SDMA0", + [32+0][0] = "UVD", + [32+1][0] = "UVDU", + [32+2][0] = "MP1", + [32+3][0] = "MP0", + [32+12][0] = "UTCL2", + [32+14][0] = "SDMA1", + [0][1] = "XDMA", + [1][1] = "DCE", + [2][1] = "DCEDWB", + [3][1] = "VCE0", + [4][1] = "VCE0U", + [5][1] = "UVD1", + [6][1] = "UVD1U", + [7][1] = "DBGU0", + [8][1] = "XDP", + [13][1] = "OSS", + [14][1] = "HDP", + [15][1] = "SDMA0", + [32+0][1] = "UVD", + [32+1][1] = "UVDU", + [32+2][1] = "DBGU1", + [32+3][1] = "MP1", + [32+4][1] = "MP0", + [32+14][1] = "SDMA1", +}; + +static const char *mmhub_client_ids_arcturus[][2] = { + [2][0] = "MP1", + [3][0] = "MP0", + [10][0] = "UTCL2", + [13][0] = "OSS", + [14][0] = "HDP", + [15][0] = "SDMA0", + [32+15][0] = "SDMA1", + [64+15][0] = "SDMA2", + [96+15][0] = "SDMA3", + [128+15][0] = "SDMA4", + [160+11][0] = "JPEG", + [160+12][0] = "VCN", + [160+13][0] = "VCNU", + [160+15][0] = "SDMA5", + [192+10][0] = "UTCL2", + [192+11][0] = "JPEG1", + [192+12][0] = "VCN1", + [192+13][0] = "VCN1U", + [192+15][0] = "SDMA6", + [224+15][0] = "SDMA7", + [0][1] = "DBGU1", + [1][1] = "XDP", + [2][1] = "MP1", + [3][1] = "MP0", + [13][1] = "OSS", + [14][1] = "HDP", + [15][1] = "SDMA0", + [32+15][1] = "SDMA1", + [32+15][1] = "SDMA1", + [64+15][1] = "SDMA2", + [96+15][1] = "SDMA3", + [128+15][1] = "SDMA4", + [160+11][1] = "JPEG", + [160+12][1] = "VCN", + [160+13][1] = "VCNU", + [160+15][1] = "SDMA5", + [192+11][1] = "JPEG1", + [192+12][1] = "VCN1", + [192+13][1] = "VCN1U", + [192+15][1] = "SDMA6", + [224+15][1] = "SDMA7", +}; + static const u32 golden_settings_vega10_hdp[] = { 0xf64, 0x0fffffff, 0x00000000, @@ -319,9 +516,10 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, { struct amdgpu_vmhub *hub; bool retry_fault = !!(entry->src_data[1] & 0x80); - uint32_t status = 0, cid = 0; + uint32_t status = 0, cid = 0, rw = 0; u64 addr; char hub_name[10]; + const char *mmhub_cid; addr = (u64)entry->src_data[0] << 12; addr |= ((u64)entry->src_data[1] & 0xf) << 44; @@ -358,6 +556,8 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, status = RREG32(hub->vm_l2_pro_fault_status); cid = REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, CID); + rw = REG_GET_FIELD(status, + VM_L2_PROTECTION_FAULT_STATUS, RW); WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); } @@ -380,13 +580,37 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "VM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) + if (hub == &adev->vmhub[AMDGPU_GFXHUB_0]) { dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", cid >= ARRAY_SIZE(gfxhub_client_ids) ? "unknown" : gfxhub_client_ids[cid], cid); - else - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%x\n", - cid); + } else { + switch (adev->asic_type) { + case CHIP_VEGA10: + mmhub_cid = mmhub_client_ids_vega10[cid][rw]; + break; + case CHIP_VEGA12: + mmhub_cid = mmhub_client_ids_vega12[cid][rw]; + break; + case CHIP_VEGA20: + mmhub_cid = mmhub_client_ids_vega20[cid][rw]; + break; + case CHIP_ARCTURUS: + mmhub_cid = mmhub_client_ids_arcturus[cid][rw]; + break; + case CHIP_RAVEN: + mmhub_cid = mmhub_client_ids_raven[cid][rw]; + break; + case CHIP_RENOIR: + mmhub_cid = mmhub_client_ids_renoir[cid][rw]; + break; + default: + mmhub_cid = NULL; + break; + } + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + mmhub_cid ? mmhub_cid : "unknown", cid); + } dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); @@ -399,10 +623,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); - dev_err(adev->dev, "\t RW: 0x%lx\n", - REG_GET_FIELD(status, - VM_L2_PROTECTION_FAULT_STATUS, RW)); - + dev_err(adev->dev, "\t RW: 0x%x\n", rw); } } -- cgit v1.2.3 From 11bc98bd71fe2e0cb572988519e51bca9d58a18a Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 2 Sep 2020 13:38:00 -0400 Subject: drm/amdgpu/mmhub2.0: print client id string for mmhub Print the name of the client rather than the number. This makes it easier to debug what block is causing the fault. Reviewed-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c | 88 ++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c index 5baf899417d8..2d88278c50bf 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c @@ -36,6 +36,63 @@ #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid 0x0070 #define mmDAGB0_CNTL_MISC2_Sienna_Cichlid_BASE_IDX 0 +static const char *mmhub_client_ids_navi1x[][2] = { + [3][0] = "DCEDMC", + [4][0] = "DCEVGA", + [5][0] = "MP0", + [6][0] = "MP1", + [13][0] = "VMC", + [14][0] = "HDP", + [15][0] = "OSS", + [16][0] = "VCNU", + [17][0] = "JPEG", + [18][0] = "VCN", + [3][1] = "DCEDMC", + [4][1] = "DCEXFC", + [5][1] = "DCEVGA", + [6][1] = "DCEDWB", + [7][1] = "MP0", + [8][1] = "MP1", + [9][1] = "DBGU1", + [10][1] = "DBGU0", + [11][1] = "XDP", + [14][1] = "HDP", + [15][1] = "OSS", + [16][1] = "VCNU", + [17][1] = "JPEG", + [18][1] = "VCN", +}; + +static const char *mmhub_client_ids_sienna_cichlid[][2] = { + [3][0] = "DCEDMC", + [4][0] = "DCEVGA", + [5][0] = "MP0", + [6][0] = "MP1", + [8][0] = "VMC", + [9][0] = "VCNU0", + [10][0] = "JPEG", + [12][0] = "VCNU1", + [13][0] = "VCN1", + [14][0] = "HDP", + [15][0] = "OSS", + [32+11][0] = "VCN0", + [0][1] = "DBGU0", + [1][1] = "DBGU1", + [2][1] = "DCEDWB", + [3][1] = "DCEDMC", + [4][1] = "DCEVGA", + [5][1] = "MP0", + [6][1] = "MP1", + [7][1] = "XDP", + [9][1] = "VCNU0", + [10][1] = "JPEG", + [11][1] = "VCN0", + [12][1] = "VCNU1", + [13][1] = "VCN1", + [14][1] = "HDP", + [15][1] = "OSS", +}; + static uint32_t mmhub_v2_0_get_invalidate_req(unsigned int vmid, uint32_t flush_type) { @@ -60,12 +117,33 @@ static void mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, uint32_t status) { + uint32_t cid, rw; + const char *mmhub_cid = NULL; + + cid = REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, CID); + rw = REG_GET_FIELD(status, + MMVM_L2_PROTECTION_FAULT_STATUS, RW); + dev_err(adev->dev, "MMVM_L2_PROTECTION_FAULT_STATUS:0x%08X\n", status); - dev_err(adev->dev, "\t Faulty UTCL2 client ID: 0x%lx\n", - REG_GET_FIELD(status, - MMVM_L2_PROTECTION_FAULT_STATUS, CID)); + switch (adev->asic_type) { + case CHIP_NAVI10: + case CHIP_NAVI12: + case CHIP_NAVI14: + mmhub_cid = mmhub_client_ids_navi1x[cid][rw]; + break; + case CHIP_SIENNA_CICHLID: + case CHIP_NAVY_FLOUNDER: + mmhub_cid = mmhub_client_ids_sienna_cichlid[cid][rw]; + break; + default: + mmhub_cid = NULL; + break; + } + dev_err(adev->dev, "\t Faulty UTCL2 client ID: %s (0x%x)\n", + mmhub_cid ? mmhub_cid : "unknown", cid); dev_err(adev->dev, "\t MORE_FAULTS: 0x%lx\n", REG_GET_FIELD(status, MMVM_L2_PROTECTION_FAULT_STATUS, MORE_FAULTS)); @@ -78,9 +156,7 @@ mmhub_v2_0_print_l2_protection_fault_status(struct amdgpu_device *adev, dev_err(adev->dev, "\t MAPPING_ERROR: 0x%lx\n", REG_GET_FIELD(status, MMVM_L2_PROTECTION_FAULT_STATUS, MAPPING_ERROR)); - dev_err(adev->dev, "\t RW: 0x%lx\n", - REG_GET_FIELD(status, - MMVM_L2_PROTECTION_FAULT_STATUS, RW)); + dev_err(adev->dev, "\t RW: 0x%x\n", rw); } static void mmhub_v2_0_setup_vm_pt_regs(struct amdgpu_device *adev, uint32_t vmid, -- cgit v1.2.3 From f71800228dc74711c3df43854ce7089562a3bc2d Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Thu, 20 Aug 2020 22:31:44 +0200 Subject: drm/tve200: Stabilize enable/disable The TVE200 will occasionally print a bunch of lost interrupts and similar dmesg messages, sometimes during boot and sometimes after disabling and coming back to enablement. This is probably because the hardware is left in an unknown state by the boot loader that displays a logo. This can be fixed by bringing the controller into a known state by resetting the controller while enabling it. We retry reset 5 times like the vendor driver does. We also put the controller into reset before de-clocking it and clear all interrupts before enabling the vblank IRQ. This makes the video enable/disable/enable cycle rock solid on the D-Link DIR-685. Tested extensively. Signed-off-by: Linus Walleij Acked-by: Daniel Vetter Cc: stable@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20200820203144.271081-1-linus.walleij@linaro.org --- drivers/gpu/drm/tve200/tve200_display.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index d733bbc4ac0e..17ff24d999d1 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -130,9 +131,25 @@ static void tve200_display_enable(struct drm_simple_display_pipe *pipe, struct drm_connector *connector = priv->connector; u32 format = fb->format->format; u32 ctrl1 = 0; + int retries; clk_prepare_enable(priv->clk); + /* Reset the TVE200 and wait for it to come back online */ + writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4); + for (retries = 0; retries < 5; retries++) { + usleep_range(30000, 50000); + if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) + continue; + else + break; + } + if (retries == 5 && + readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) { + dev_err(drm->dev, "can't get hardware out of reset\n"); + return; + } + /* Function 1 */ ctrl1 |= TVE200_CTRL_CSMODE; /* Interlace mode for CCIR656: parameterize? */ @@ -230,8 +247,9 @@ static void tve200_display_disable(struct drm_simple_display_pipe *pipe) drm_crtc_vblank_off(crtc); - /* Disable and Power Down */ + /* Disable put into reset and Power Down */ writel(0, priv->regs + TVE200_CTRL); + writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4); clk_disable_unprepare(priv->clk); } @@ -279,6 +297,8 @@ static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe) struct drm_device *drm = crtc->dev; struct tve200_drm_dev_private *priv = drm->dev_private; + /* Clear any IRQs and enable */ + writel(0xFF, priv->regs + TVE200_INT_CLR); writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN); return 0; } -- cgit v1.2.3 From 9e2369c06c8a181478039258a4598c1ddd2cadfa Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Tue, 1 Sep 2020 10:33:26 +0200 Subject: xen: add helpers to allocate unpopulated memory To be used in order to create foreign mappings. This is based on the ZONE_DEVICE facility which is used by persistent memory devices in order to create struct pages and kernel virtual mappings for the IOMEM areas of such devices. Note that on kernels without support for ZONE_DEVICE Xen will fallback to use ballooned pages in order to create foreign mappings. The newly added helpers use the same parameters as the existing {alloc/free}_xenballooned_pages functions, which allows for in-place replacement of the callers. Once a memory region has been added to be used as scratch mapping space it will no longer be released, and pages returned are kept in a linked list. This allows to have a buffer of pages and prevents resorting to frequent additions and removals of regions. If enabled (because ZONE_DEVICE is supported) the usage of the new functionality untangles Xen balloon and RAM hotplug from the usage of unpopulated physical memory ranges to map foreign pages, which is the correct thing to do in order to avoid mappings of foreign pages depend on memory hotplug. Note the driver is currently not enabled on Arm platforms because it would interfere with the identity mapping required on some platforms. Signed-off-by: Roger Pau Monné Reviewed-by: Juergen Gross Link: https://lore.kernel.org/r/20200901083326.21264-4-roger.pau@citrix.com Signed-off-by: Juergen Gross --- drivers/gpu/drm/xen/xen_drm_front_gem.c | 9 +- drivers/xen/Kconfig | 10 ++ drivers/xen/Makefile | 1 + drivers/xen/balloon.c | 4 +- drivers/xen/grant-table.c | 4 +- drivers/xen/privcmd.c | 4 +- drivers/xen/unpopulated-alloc.c | 183 ++++++++++++++++++++++++++++++++ drivers/xen/xenbus/xenbus_client.c | 6 +- drivers/xen/xlate_mmu.c | 4 +- include/xen/xen.h | 9 ++ 10 files changed, 219 insertions(+), 15 deletions(-) create mode 100644 drivers/xen/unpopulated-alloc.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index 39ff95b75357..534daf37c97e 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -18,6 +18,7 @@ #include #include +#include #include "xen_drm_front.h" #include "xen_drm_front_gem.h" @@ -99,8 +100,8 @@ static struct xen_gem_object *gem_create(struct drm_device *dev, size_t size) * allocate ballooned pages which will be used to map * grant references provided by the backend */ - ret = alloc_xenballooned_pages(xen_obj->num_pages, - xen_obj->pages); + ret = xen_alloc_unpopulated_pages(xen_obj->num_pages, + xen_obj->pages); if (ret < 0) { DRM_ERROR("Cannot allocate %zu ballooned pages: %d\n", xen_obj->num_pages, ret); @@ -152,8 +153,8 @@ void xen_drm_front_gem_free_object_unlocked(struct drm_gem_object *gem_obj) } else { if (xen_obj->pages) { if (xen_obj->be_alloc) { - free_xenballooned_pages(xen_obj->num_pages, - xen_obj->pages); + xen_free_unpopulated_pages(xen_obj->num_pages, + xen_obj->pages); gem_free_pages_array(xen_obj); } else { drm_gem_put_pages(&xen_obj->base, diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 46e7fd099904..0ab54df82520 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig @@ -324,4 +324,14 @@ config XEN_HAVE_VPMU config XEN_FRONT_PGDIR_SHBUF tristate +config XEN_UNPOPULATED_ALLOC + bool "Use unpopulated memory ranges for guest mappings" + depends on X86 && ZONE_DEVICE + default XEN_BACKEND || XEN_GNTDEV || XEN_DOM0 + help + Use unpopulated memory ranges in order to create mappings for guest + memory regions, including grant maps and foreign pages. This avoids + having to balloon out RAM regions in order to obtain physical memory + space to create such mappings. + endmenu diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index 0d322f3d90cd..3cca2be28824 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -42,3 +42,4 @@ xen-gntdev-$(CONFIG_XEN_GNTDEV_DMABUF) += gntdev-dmabuf.o xen-gntalloc-y := gntalloc.o xen-privcmd-y := privcmd.o privcmd-buf.o obj-$(CONFIG_XEN_FRONT_PGDIR_SHBUF) += xen-front-pgdir-shbuf.o +obj-$(CONFIG_XEN_UNPOPULATED_ALLOC) += unpopulated-alloc.o diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b1d8b028bf80..4bfbe71705e4 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -654,7 +654,7 @@ void free_xenballooned_pages(int nr_pages, struct page **pages) } EXPORT_SYMBOL(free_xenballooned_pages); -#ifdef CONFIG_XEN_PV +#if defined(CONFIG_XEN_PV) && !defined(CONFIG_XEN_UNPOPULATED_ALLOC) static void __init balloon_add_region(unsigned long start_pfn, unsigned long pages) { @@ -708,7 +708,7 @@ static int __init balloon_init(void) register_sysctl_table(xen_root); #endif -#ifdef CONFIG_XEN_PV +#if defined(CONFIG_XEN_PV) && !defined(CONFIG_XEN_UNPOPULATED_ALLOC) { int i; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 8d06bf1cc347..523dcdf39cc9 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -801,7 +801,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages) { int ret; - ret = alloc_xenballooned_pages(nr_pages, pages); + ret = xen_alloc_unpopulated_pages(nr_pages, pages); if (ret < 0) return ret; @@ -836,7 +836,7 @@ EXPORT_SYMBOL_GPL(gnttab_pages_clear_private); void gnttab_free_pages(int nr_pages, struct page **pages) { gnttab_pages_clear_private(nr_pages, pages); - free_xenballooned_pages(nr_pages, pages); + xen_free_unpopulated_pages(nr_pages, pages); } EXPORT_SYMBOL_GPL(gnttab_free_pages); diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 095d683ad574..8bcb0ce223a5 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c @@ -425,7 +425,7 @@ static int alloc_empty_pages(struct vm_area_struct *vma, int numpgs) if (pages == NULL) return -ENOMEM; - rc = alloc_xenballooned_pages(numpgs, pages); + rc = xen_alloc_unpopulated_pages(numpgs, pages); if (rc != 0) { pr_warn("%s Could not alloc %d pfns rc:%d\n", __func__, numpgs, rc); @@ -896,7 +896,7 @@ static void privcmd_close(struct vm_area_struct *vma) rc = xen_unmap_domain_gfn_range(vma, numgfns, pages); if (rc == 0) - free_xenballooned_pages(numpgs, pages); + xen_free_unpopulated_pages(numpgs, pages); else pr_crit("unable to unmap MFN range: leaking %d pages. rc=%d\n", numpgs, rc); diff --git a/drivers/xen/unpopulated-alloc.c b/drivers/xen/unpopulated-alloc.c new file mode 100644 index 000000000000..3b98dc921426 --- /dev/null +++ b/drivers/xen/unpopulated-alloc.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +static DEFINE_MUTEX(list_lock); +static LIST_HEAD(page_list); +static unsigned int list_count; + +static int fill_list(unsigned int nr_pages) +{ + struct dev_pagemap *pgmap; + void *vaddr; + unsigned int i, alloc_pages = round_up(nr_pages, PAGES_PER_SECTION); + int ret; + + pgmap = kzalloc(sizeof(*pgmap), GFP_KERNEL); + if (!pgmap) + return -ENOMEM; + + pgmap->type = MEMORY_DEVICE_GENERIC; + pgmap->res.name = "Xen scratch"; + pgmap->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; + + ret = allocate_resource(&iomem_resource, &pgmap->res, + alloc_pages * PAGE_SIZE, 0, -1, + PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); + if (ret < 0) { + pr_err("Cannot allocate new IOMEM resource\n"); + kfree(pgmap); + return ret; + } + +#ifdef CONFIG_XEN_HAVE_PVMMU + /* + * memremap will build page tables for the new memory so + * the p2m must contain invalid entries so the correct + * non-present PTEs will be written. + * + * If a failure occurs, the original (identity) p2m entries + * are not restored since this region is now known not to + * conflict with any devices. + */ + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + xen_pfn_t pfn = PFN_DOWN(pgmap->res.start); + + for (i = 0; i < alloc_pages; i++) { + if (!set_phys_to_machine(pfn + i, INVALID_P2M_ENTRY)) { + pr_warn("set_phys_to_machine() failed, no memory added\n"); + release_resource(&pgmap->res); + kfree(pgmap); + return -ENOMEM; + } + } + } +#endif + + vaddr = memremap_pages(pgmap, NUMA_NO_NODE); + if (IS_ERR(vaddr)) { + pr_err("Cannot remap memory range\n"); + release_resource(&pgmap->res); + kfree(pgmap); + return PTR_ERR(vaddr); + } + + for (i = 0; i < alloc_pages; i++) { + struct page *pg = virt_to_page(vaddr + PAGE_SIZE * i); + + BUG_ON(!virt_addr_valid(vaddr + PAGE_SIZE * i)); + list_add(&pg->lru, &page_list); + list_count++; + } + + return 0; +} + +/** + * xen_alloc_unpopulated_pages - alloc unpopulated pages + * @nr_pages: Number of pages + * @pages: pages returned + * @return 0 on success, error otherwise + */ +int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages) +{ + unsigned int i; + int ret = 0; + + mutex_lock(&list_lock); + if (list_count < nr_pages) { + ret = fill_list(nr_pages - list_count); + if (ret) + goto out; + } + + for (i = 0; i < nr_pages; i++) { + struct page *pg = list_first_entry_or_null(&page_list, + struct page, + lru); + + BUG_ON(!pg); + list_del(&pg->lru); + list_count--; + pages[i] = pg; + +#ifdef CONFIG_XEN_HAVE_PVMMU + if (!xen_feature(XENFEAT_auto_translated_physmap)) { + ret = xen_alloc_p2m_entry(page_to_pfn(pg)); + if (ret < 0) { + unsigned int j; + + for (j = 0; j <= i; j++) { + list_add(&pages[j]->lru, &page_list); + list_count++; + } + goto out; + } + } +#endif + } + +out: + mutex_unlock(&list_lock); + return ret; +} +EXPORT_SYMBOL(xen_alloc_unpopulated_pages); + +/** + * xen_free_unpopulated_pages - return unpopulated pages + * @nr_pages: Number of pages + * @pages: pages to return + */ +void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages) +{ + unsigned int i; + + mutex_lock(&list_lock); + for (i = 0; i < nr_pages; i++) { + list_add(&pages[i]->lru, &page_list); + list_count++; + } + mutex_unlock(&list_lock); +} +EXPORT_SYMBOL(xen_free_unpopulated_pages); + +#ifdef CONFIG_XEN_PV +static int __init init(void) +{ + unsigned int i; + + if (!xen_domain()) + return -ENODEV; + + if (!xen_pv_domain()) + return 0; + + /* + * Initialize with pages from the extra memory regions (see + * arch/x86/xen/setup.c). + */ + for (i = 0; i < XEN_EXTRA_MEM_MAX_REGIONS; i++) { + unsigned int j; + + for (j = 0; j < xen_extra_mem[i].n_pfns; j++) { + struct page *pg = + pfn_to_page(xen_extra_mem[i].start_pfn + j); + + list_add(&pg->lru, &page_list); + list_count++; + } + } + + return 0; +} +subsys_initcall(init); +#endif diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c index 907bcbb93afb..2690318ad50f 100644 --- a/drivers/xen/xenbus/xenbus_client.c +++ b/drivers/xen/xenbus/xenbus_client.c @@ -621,7 +621,7 @@ static int xenbus_map_ring_hvm(struct xenbus_device *dev, bool leaked = false; unsigned int nr_pages = XENBUS_PAGES(nr_grefs); - err = alloc_xenballooned_pages(nr_pages, node->hvm.pages); + err = xen_alloc_unpopulated_pages(nr_pages, node->hvm.pages); if (err) goto out_err; @@ -662,7 +662,7 @@ static int xenbus_map_ring_hvm(struct xenbus_device *dev, addr, nr_pages); out_free_ballooned_pages: if (!leaked) - free_xenballooned_pages(nr_pages, node->hvm.pages); + xen_free_unpopulated_pages(nr_pages, node->hvm.pages); out_err: return err; } @@ -858,7 +858,7 @@ static int xenbus_unmap_ring_hvm(struct xenbus_device *dev, void *vaddr) info.addrs); if (!rv) { vunmap(vaddr); - free_xenballooned_pages(nr_pages, node->hvm.pages); + xen_free_unpopulated_pages(nr_pages, node->hvm.pages); } else WARN(1, "Leaking %p, size %u page(s)\n", vaddr, nr_pages); diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c index 7b1077f0abcb..34742c6e189e 100644 --- a/drivers/xen/xlate_mmu.c +++ b/drivers/xen/xlate_mmu.c @@ -232,7 +232,7 @@ int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt, kfree(pages); return -ENOMEM; } - rc = alloc_xenballooned_pages(nr_pages, pages); + rc = xen_alloc_unpopulated_pages(nr_pages, pages); if (rc) { pr_warn("%s Couldn't balloon alloc %ld pages rc:%d\n", __func__, nr_pages, rc); @@ -249,7 +249,7 @@ int __init xen_xlate_map_ballooned_pages(xen_pfn_t **gfns, void **virt, if (!vaddr) { pr_warn("%s Couldn't map %ld pages rc:%d\n", __func__, nr_pages, rc); - free_xenballooned_pages(nr_pages, pages); + xen_free_unpopulated_pages(nr_pages, pages); kfree(pages); kfree(pfns); return -ENOMEM; diff --git a/include/xen/xen.h b/include/xen/xen.h index 19a72f591e2b..43efba045acc 100644 --- a/include/xen/xen.h +++ b/include/xen/xen.h @@ -52,4 +52,13 @@ bool xen_biovec_phys_mergeable(const struct bio_vec *vec1, extern u64 xen_saved_max_mem_size; #endif +#ifdef CONFIG_XEN_UNPOPULATED_ALLOC +int xen_alloc_unpopulated_pages(unsigned int nr_pages, struct page **pages); +void xen_free_unpopulated_pages(unsigned int nr_pages, struct page **pages); +#else +#define xen_alloc_unpopulated_pages alloc_xenballooned_pages +#define xen_free_unpopulated_pages free_xenballooned_pages +#include +#endif + #endif /* _XEN_XEN_H */ -- cgit v1.2.3 From 0ee9f600e69d901d31469359287b90bbe8e54553 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Wed, 2 Sep 2020 00:03:05 +0200 Subject: drm/sun4i: Fix DE2 YVU handling Function sun8i_vi_layer_get_csc_mode() is supposed to return CSC mode but due to inproper return type (bool instead of u32) it returns just 0 or 1. Colors are wrong for YVU formats because of that. Fixes: daab3d0e8e2b ("drm/sun4i: de2: csc_mode in de2 format struct is mostly redundant") Reported-by: Roman Stratiienko Signed-off-by: Jernej Skrabec Tested-by: Roman Stratiienko Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20200901220305.6809-1-jernej.skrabec@siol.net --- drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 22c8c5375d0d..c0147af6a840 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -211,7 +211,7 @@ static int sun8i_vi_layer_update_coord(struct sun8i_mixer *mixer, int channel, return 0; } -static bool sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format) +static u32 sun8i_vi_layer_get_csc_mode(const struct drm_format_info *format) { if (!format->is_yuv) return SUN8I_CSC_MODE_OFF; -- cgit v1.2.3 From e359c70462d2a82aae80274d027351d38792dde6 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 28 Jul 2020 15:48:09 +0200 Subject: drm/sun4i: backend: Support alpha property on lowest plane Unlike what we previously thought, only the per-pixel alpha is broken on the lowest plane and the per-plane alpha isn't. Remove the check on the alpha property being set on the lowest plane to reject a mode. Fixes: dcf496a6a608 ("drm/sun4i: sun4i: Introduce a quirk for lowest plane alpha support") Signed-off-by: Maxime Ripard Reviewed-by: Chen-Yu Tsai Cc: Paul Kocialkowski Link: https://patchwork.freedesktop.org/patch/msgid/20200728134810.883457-1-maxime@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_backend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 072ea113e6be..30672c4c634d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -589,8 +589,7 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, /* We can't have an alpha plane at the lowest position */ if (!backend->quirks->supports_lowest_plane_alpha && - (plane_states[0]->fb->format->has_alpha || - (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE))) + (plane_states[0]->alpha != DRM_BLEND_ALPHA_OPAQUE)) return -EINVAL; for (i = 1; i < num_planes; i++) { -- cgit v1.2.3 From 5e2e2600a3744491a8b49b92597c13b693692082 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 28 Jul 2020 15:48:10 +0200 Subject: drm/sun4i: backend: Disable alpha on the lowest plane on the A20 Unlike we previously thought, the per-pixel alpha is just as broken on the A20 as it is on the A10. Remove the quirk that says we can use it. Fixes: dcf496a6a608 ("drm/sun4i: sun4i: Introduce a quirk for lowest plane alpha support") Signed-off-by: Maxime Ripard Reviewed-by: Chen-Yu Tsai Cc: Paul Kocialkowski Link: https://patchwork.freedesktop.org/patch/msgid/20200728134810.883457-2-maxime@cerno.tech --- drivers/gpu/drm/sun4i/sun4i_backend.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 30672c4c634d..ed5d86617802 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -994,7 +994,6 @@ static const struct sun4i_backend_quirks sun6i_backend_quirks = { static const struct sun4i_backend_quirks sun7i_backend_quirks = { .needs_output_muxing = true, - .supports_lowest_plane_alpha = true, }; static const struct sun4i_backend_quirks sun8i_a33_backend_quirks = { -- cgit v1.2.3 From fc7f148feb8975784bd40e41fff875d33f698be8 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 18 Aug 2020 09:25:11 +0200 Subject: drm/virtio: drop virtio_gpu_output->enabled Not needed, already tracked by drm_crtc_state->active. Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20200818072511.6745-3-kraxel@redhat.com (cherry picked from commit 1174c8a0f33c1e5c442ac40381fe124248c08b3a) --- drivers/gpu/drm/virtio/virtgpu_display.c | 4 ---- drivers/gpu/drm/virtio/virtgpu_drv.h | 1 - drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 97170998cd0e..afd0f9200f90 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -97,9 +97,6 @@ static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) static void virtio_gpu_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { - struct virtio_gpu_output *output = drm_crtc_to_virtio_gpu_output(crtc); - - output->enabled = true; } static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, @@ -111,7 +108,6 @@ static void virtio_gpu_crtc_atomic_disable(struct drm_crtc *crtc, virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, 0, 0, 0, 0); virtio_gpu_notify(vgdev); - output->enabled = false; } static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 4ab1b0ba2925..fbc04272db4f 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -137,7 +137,6 @@ struct virtio_gpu_output { struct edid *edid; int cur_x; int cur_y; - bool enabled; bool needs_modeset; }; #define drm_crtc_to_virtio_gpu_output(x) \ diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 65757409d9ed..6a311cd93440 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -142,7 +142,7 @@ static void virtio_gpu_primary_plane_update(struct drm_plane *plane, if (WARN_ON(!output)) return; - if (!plane->state->fb || !output->enabled) { + if (!plane->state->fb || !output->crtc.state->active) { DRM_DEBUG("nofb\n"); virtio_gpu_cmd_set_scanout(vgdev, output->index, 0, plane->state->src_w >> 16, -- cgit v1.2.3 From a308c71bf1e6e19cc2e4ced31853ee0fc7cb439a Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Fri, 21 Aug 2020 19:49:57 -0400 Subject: mm/gup: Remove enfornced COW mechanism With the more strict (but greatly simplified) page reuse logic in do_wp_page(), we can safely go back to the world where cow is not enforced with writes. This essentially reverts commit 17839856fd58 ("gup: document and work around 'COW can break either way' issue"). There are some context differences due to some changes later on around it: 2170ecfa7688 ("drm/i915: convert get_user_pages() --> pin_user_pages()", 2020-06-03) 376a34efa4ee ("mm/gup: refactor and de-duplicate gup_fast() code", 2020-06-03) Some lines moved back and forth with those, but this revert patch should have striped out and covered all the enforced cow bits anyways. Suggested-by: Linus Torvalds Signed-off-by: Peter Xu Signed-off-by: Linus Torvalds --- drivers/gpu/drm/i915/gem/i915_gem_userptr.c | 8 ------ mm/gup.c | 40 ++++------------------------- mm/huge_memory.c | 7 ++--- 3 files changed, 9 insertions(+), 46 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c index c31a6744daee..853184db8e83 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c @@ -599,14 +599,6 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN); - /* - * Using __get_user_pages_fast() with a read-only - * access is questionable. A read-only page may be - * COW-broken, and then this might end up giving - * the wrong side of the COW.. - * - * We may or may not care. - */ if (pvec) { /* defer to worker if malloc fails */ if (!i915_gem_object_is_readonly(obj)) diff --git a/mm/gup.c b/mm/gup.c index 6f47697f8fb0..e3bd0d0b5120 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -381,22 +381,13 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, } /* - * FOLL_FORCE or a forced COW break can write even to unwritable pte's, - * but only after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE can write to even unwritable pte's, but only + * after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pte(pte_t pte, unsigned int flags) { - return pte_write(pte) || ((flags & FOLL_COW) && pte_dirty(pte)); -} - -/* - * A (separate) COW fault might break the page the other way and - * get_user_pages() would return the page from what is now the wrong - * VM. So we need to force a COW break at GUP time even for reads. - */ -static inline bool should_force_cow_break(struct vm_area_struct *vma, unsigned int flags) -{ - return is_cow_mapping(vma->vm_flags) && (flags & (FOLL_GET | FOLL_PIN)); + return pte_write(pte) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte)); } static struct page *follow_page_pte(struct vm_area_struct *vma, @@ -1075,11 +1066,9 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, goto out; } if (is_vm_hugetlb_page(vma)) { - if (should_force_cow_break(vma, foll_flags)) - foll_flags |= FOLL_WRITE; i = follow_hugetlb_page(mm, vma, pages, vmas, &start, &nr_pages, i, - foll_flags, locked); + gup_flags, locked); if (locked && *locked == 0) { /* * We've got a VM_FAULT_RETRY @@ -1093,10 +1082,6 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, continue; } } - - if (should_force_cow_break(vma, foll_flags)) - foll_flags |= FOLL_WRITE; - retry: /* * If we have a pending SIGKILL, don't keep faulting pages and @@ -2763,19 +2748,6 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages, return -EFAULT; /* - * The FAST_GUP case requires FOLL_WRITE even for pure reads, - * because get_user_pages() may need to cause an early COW in - * order to avoid confusing the normal COW routines. So only - * targets that are already writable are safe to do by just - * looking at the page tables. - * - * NOTE! With FOLL_FAST_ONLY we allow read-only gup_fast() here, - * because there is no slow path to fall back on. But you'd - * better be careful about possible COW pages - you'll get _a_ - * COW page, but not necessarily the one you intended to get - * depending on what COW event happens after this. COW may break - * the page copy in a random direction. - * * Disable interrupts. The nested form is used, in order to allow * full, general purpose use of this routine. * @@ -2788,8 +2760,6 @@ static int internal_get_user_pages_fast(unsigned long start, int nr_pages, */ if (IS_ENABLED(CONFIG_HAVE_FAST_GUP) && gup_fast_permitted(start, end)) { unsigned long fast_flags = gup_flags; - if (!(gup_flags & FOLL_FAST_ONLY)) - fast_flags |= FOLL_WRITE; local_irq_save(flags); gup_pgd_range(addr, end, fast_flags, pages, &nr_pinned); diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 78c84bee7e29..6f74f3d93839 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1312,12 +1312,13 @@ fallback: } /* - * FOLL_FORCE or a forced COW break can write even to unwritable pmd's, - * but only after we've gone through a COW cycle and they are dirty. + * FOLL_FORCE can write to even unwritable pmd's, but only + * after we've gone through a COW cycle and they are dirty. */ static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags) { - return pmd_write(pmd) || ((flags & FOLL_COW) && pmd_dirty(pmd)); + return pmd_write(pmd) || + ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd)); } struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, -- cgit v1.2.3 From 34221545d2069dc947131f42392fd4cebabe1b39 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 3 Sep 2020 20:03:10 -0600 Subject: drm/msm: Split the a5xx preemption record The main a5xx preemption record can be marked as privileged to protect it from user access but the counters storage needs to be remain unprivileged. Split the buffers and mark the critical memory as privileged. Cc: stable@vger.kernel.org Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.h | 1 + drivers/gpu/drm/msm/adreno/a5xx_preempt.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index 54868d4e3958..1e5b1a15a70f 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -31,6 +31,7 @@ struct a5xx_gpu { struct msm_ringbuffer *next_ring; struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS]; + struct drm_gem_object *preempt_counters_bo[MSM_GPU_MAX_RINGS]; struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS]; uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c index 9cf9353a7ff1..9f3fe177b00e 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -226,19 +226,31 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, struct adreno_gpu *adreno_gpu = &a5xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; struct a5xx_preempt_record *ptr; - struct drm_gem_object *bo = NULL; - u64 iova = 0; + void *counters; + struct drm_gem_object *bo = NULL, *counters_bo = NULL; + u64 iova = 0, counters_iova = 0; ptr = msm_gem_kernel_new(gpu->dev, A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE, - MSM_BO_UNCACHED, gpu->aspace, &bo, &iova); + MSM_BO_UNCACHED | MSM_BO_MAP_PRIV, gpu->aspace, &bo, &iova); if (IS_ERR(ptr)) return PTR_ERR(ptr); + /* The buffer to store counters needs to be unprivileged */ + counters = msm_gem_kernel_new(gpu->dev, + A5XX_PREEMPT_COUNTER_SIZE, + MSM_BO_UNCACHED, gpu->aspace, &counters_bo, &counters_iova); + if (IS_ERR(counters)) { + msm_gem_kernel_put(bo, gpu->aspace, true); + return PTR_ERR(counters); + } + msm_gem_object_set_name(bo, "preempt"); + msm_gem_object_set_name(counters_bo, "preempt_counters"); a5xx_gpu->preempt_bo[ring->id] = bo; + a5xx_gpu->preempt_counters_bo[ring->id] = counters_bo; a5xx_gpu->preempt_iova[ring->id] = iova; a5xx_gpu->preempt[ring->id] = ptr; @@ -249,7 +261,7 @@ static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, ptr->data = 0; ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; ptr->rptr_addr = rbmemptr(ring, rptr); - ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE; + ptr->counter = counters_iova; return 0; } @@ -260,8 +272,11 @@ void a5xx_preempt_fini(struct msm_gpu *gpu) struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); int i; - for (i = 0; i < gpu->nr_rings; i++) + for (i = 0; i < gpu->nr_rings; i++) { msm_gem_kernel_put(a5xx_gpu->preempt_bo[i], gpu->aspace, true); + msm_gem_kernel_put(a5xx_gpu->preempt_counters_bo[i], + gpu->aspace, true); + } } void a5xx_preempt_init(struct msm_gpu *gpu) -- cgit v1.2.3 From 604234f33658cdd72f686be405a99646b397d0b3 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 3 Sep 2020 20:03:11 -0600 Subject: drm/msm: Enable expanded apriv support for a650 a650 supports expanded apriv support that allows us to map critical buffers (ringbuffer and memstore) as as privileged to protect them from corruption. Cc: stable@vger.kernel.org Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +++++- drivers/gpu/drm/msm/msm_gpu.c | 2 +- drivers/gpu/drm/msm/msm_gpu.h | 11 +++++++++++ drivers/gpu/drm/msm/msm_ringbuffer.c | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index c5a3e4d4c007..406efaac95a7 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -678,7 +678,8 @@ static int a6xx_hw_init(struct msm_gpu *gpu) A6XX_PROTECT_RDONLY(0x980, 0x4)); gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0)); - if (adreno_is_a650(adreno_gpu)) { + /* Enable expanded apriv for targets that support it */ + if (gpu->hw_apriv) { gpu_write(gpu, REG_A6XX_CP_APRIV_CNTL, (1 << 6) | (1 << 5) | (1 << 3) | (1 << 2) | (1 << 1)); } @@ -1056,6 +1057,9 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = NULL; adreno_gpu->reg_offsets = a6xx_register_offsets; + if (adreno_is_a650(adreno_gpu)) + adreno_gpu->base.hw_apriv = true; + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) { a6xx_destroy(&(a6xx_gpu->base.base)); diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index d5645472b25d..57ddc9438351 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -908,7 +908,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, memptrs = msm_gem_kernel_new(drm, sizeof(struct msm_rbmemptrs) * nr_rings, - MSM_BO_UNCACHED, gpu->aspace, &gpu->memptrs_bo, + check_apriv(gpu, MSM_BO_UNCACHED), gpu->aspace, &gpu->memptrs_bo, &memptrs_iova); if (IS_ERR(memptrs)) { diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 0db117a7339b..37cffac4cbe3 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -15,6 +15,7 @@ #include "msm_drv.h" #include "msm_fence.h" #include "msm_ringbuffer.h" +#include "msm_gem.h" struct msm_gem_submit; struct msm_gpu_perfcntr; @@ -139,6 +140,8 @@ struct msm_gpu { } devfreq; struct msm_gpu_state *crashstate; + /* True if the hardware supports expanded apriv (a650 and newer) */ + bool hw_apriv; }; /* It turns out that all targets use the same ringbuffer size */ @@ -327,4 +330,12 @@ static inline void msm_gpu_crashstate_put(struct msm_gpu *gpu) mutex_unlock(&gpu->dev->struct_mutex); } +/* + * Simple macro to semi-cleanly add the MAP_PRIV flag for targets that can + * support expanded privileges + */ +#define check_apriv(gpu, flags) \ + (((gpu)->hw_apriv ? MSM_BO_MAP_PRIV : 0) | (flags)) + + #endif /* __MSM_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index 39ecb5a18431..935bf9b1d941 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -27,8 +27,8 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, ring->id = id; ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ, - MSM_BO_WC | MSM_BO_GPU_READONLY, gpu->aspace, &ring->bo, - &ring->iova); + check_apriv(gpu, MSM_BO_WC | MSM_BO_GPU_READONLY), + gpu->aspace, &ring->bo, &ring->iova); if (IS_ERR(ring->start)) { ret = PTR_ERR(ring->start); -- cgit v1.2.3 From 7b3f3948c8b7053d771acc9f79810cc410f5e2e0 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 3 Sep 2020 20:03:12 -0600 Subject: drm/msm: Disable preemption on all 5xx targets Temporarily disable preemption on a5xx targets pending some improvements to protect the RPTR shadow from being corrupted. Cc: stable@vger.kernel.org Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 9e63a190642c..e718f964d590 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1511,7 +1511,8 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) check_speed_bin(&pdev->dev); - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); + /* Restricting nr_rings to 1 to temporarily disable preemption */ + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) { a5xx_destroy(&(a5xx_gpu->base.base)); return ERR_PTR(ret); -- cgit v1.2.3 From f6828e0c4045f03f9cf2df6c2a768102641183f4 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Thu, 3 Sep 2020 20:03:13 -0600 Subject: drm/msm: Disable the RPTR shadow Disable the RPTR shadow across all targets. It will be selectively re-enabled later for targets that need it. Cc: stable@vger.kernel.org Signed-off-by: Jordan Crouse Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a2xx_gpu.c | 5 +++++ drivers/gpu/drm/msm/adreno/a3xx_gpu.c | 10 ++++++++++ drivers/gpu/drm/msm/adreno/a4xx_gpu.c | 10 ++++++++++ drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 11 +++++++++-- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 7 +++++++ drivers/gpu/drm/msm/adreno/adreno_gpu.c | 27 ++------------------------- 6 files changed, 43 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c index 6021f8d9efd1..48fa49f69d6d 100644 --- a/drivers/gpu/drm/msm/adreno/a2xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a2xx_gpu.c @@ -164,6 +164,11 @@ static int a2xx_hw_init(struct msm_gpu *gpu) if (ret) return ret; + gpu_write(gpu, REG_AXXX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + + gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); + /* NOTE: PM4/micro-engine firmware registers look to be the same * for a2xx and a3xx.. we could possibly push that part down to * adreno_gpu base class. Or push both PM4 and PFP but diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 0a5ea9f56cb8..f6471145a7a6 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -211,6 +211,16 @@ static int a3xx_hw_init(struct msm_gpu *gpu) if (ret) return ret; + /* + * Use the default ringbuffer size and block size but disable the RPTR + * shadow + */ + gpu_write(gpu, REG_AXXX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + + /* Set the ringbuffer address */ + gpu_write(gpu, REG_AXXX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); + /* setup access protection: */ gpu_write(gpu, REG_A3XX_CP_PROTECT_CTRL, 0x00000007); diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index b9b26b2bf9c5..954753600625 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -267,6 +267,16 @@ static int a4xx_hw_init(struct msm_gpu *gpu) if (ret) return ret; + /* + * Use the default ringbuffer size and block size but disable the RPTR + * shadow + */ + gpu_write(gpu, REG_A4XX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + + /* Set the ringbuffer address */ + gpu_write(gpu, REG_A4XX_CP_RB_BASE, lower_32_bits(gpu->rb[0]->iova)); + /* Load PM4: */ ptr = (uint32_t *)(adreno_gpu->fw[ADRENO_FW_PM4]->data); len = adreno_gpu->fw[ADRENO_FW_PM4]->size / 4; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index e718f964d590..ce3c0b5c167b 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -703,8 +703,6 @@ static int a5xx_hw_init(struct msm_gpu *gpu) if (ret) return ret; - a5xx_preempt_hw_init(gpu); - if (!adreno_is_a510(adreno_gpu)) a5xx_gpmu_ucode_init(gpu); @@ -712,6 +710,15 @@ static int a5xx_hw_init(struct msm_gpu *gpu) if (ret) return ret; + /* Set the ringbuffer address */ + gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI, + gpu->rb[0]->iova); + + gpu_write(gpu, REG_A5XX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + + a5xx_preempt_hw_init(gpu); + /* Disable the interrupts through the initial bringup stage */ gpu_write(gpu, REG_A5XX_RBBM_INT_0_MASK, A5XX_INT_MASK); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 406efaac95a7..74bc27eb4203 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -695,6 +695,13 @@ static int a6xx_hw_init(struct msm_gpu *gpu) if (ret) goto out; + /* Set the ringbuffer address */ + gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI, + gpu->rb[0]->iova); + + gpu_write(gpu, REG_A6XX_CP_RB_CNTL, + MSM_GPU_RB_CNTL_DEFAULT | AXXX_CP_RB_CNTL_NO_UPDATE); + /* Always come up on rb 0 */ a6xx_gpu->cur_ring = gpu->rb[0]; diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index d2dbb6968cba..459f10a3710b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -400,26 +400,6 @@ int adreno_hw_init(struct msm_gpu *gpu) ring->memptrs->rptr = 0; } - /* - * Setup REG_CP_RB_CNTL. The same value is used across targets (with - * the excpetion of A430 that disables the RPTR shadow) - the cacluation - * for the ringbuffer size and block size is moved to msm_gpu.h for the - * pre-processor to deal with and the A430 variant is ORed in here - */ - adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL, - MSM_GPU_RB_CNTL_DEFAULT | - (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0)); - - /* Setup ringbuffer address - use ringbuffer[0] for GPU init */ - adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE, - REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova); - - if (!adreno_is_a430(adreno_gpu)) { - adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR, - REG_ADRENO_CP_RB_RPTR_ADDR_HI, - rbmemptr(gpu->rb[0], rptr)); - } - return 0; } @@ -427,11 +407,8 @@ int adreno_hw_init(struct msm_gpu *gpu) static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, struct msm_ringbuffer *ring) { - if (adreno_is_a430(adreno_gpu)) - return ring->memptrs->rptr = adreno_gpu_read( - adreno_gpu, REG_ADRENO_CP_RB_RPTR); - else - return ring->memptrs->rptr; + return ring->memptrs->rptr = adreno_gpu_read( + adreno_gpu, REG_ADRENO_CP_RB_RPTR); } struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu) -- cgit v1.2.3 From 3e8b2403545efd46c6347002e27eae4708205fd4 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 29 Jul 2020 01:23:32 +0300 Subject: drm: xlnx: dpsub: Fix DMADEVICES Kconfig dependency The dpsub driver uses the DMA engine API, and thus selects DMA_ENGINE to provide that API. DMA_ENGINE depends on DMADEVICES, which can be deselected by the user, creating a possibly unmet indirect dependency: WARNING: unmet direct dependencies detected for DMA_ENGINE Depends on [n]: DMADEVICES [=n] Selected by [m]: - DRM_ZYNQMP_DPSUB [=m] && HAS_IOMEM [=y] && (ARCH_ZYNQMP || COMPILE_TEST [=y]) && COMMON_CLK [=y] && DRM [=m] && OF [=y] Add a dependency on DMADEVICES to fix this. Reported-by: Randy Dunlap Signed-off-by: Laurent Pinchart Acked-by: Randy Dunlap --- drivers/gpu/drm/xlnx/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/xlnx/Kconfig b/drivers/gpu/drm/xlnx/Kconfig index aa6cd889bd11..b52c6cdfc0b8 100644 --- a/drivers/gpu/drm/xlnx/Kconfig +++ b/drivers/gpu/drm/xlnx/Kconfig @@ -2,6 +2,7 @@ config DRM_ZYNQMP_DPSUB tristate "ZynqMP DisplayPort Controller Driver" depends on ARCH_ZYNQMP || COMPILE_TEST depends on COMMON_CLK && DRM && OF + depends on DMADEVICES select DMA_ENGINE select DRM_GEM_CMA_HELPER select DRM_KMS_CMA_HELPER -- cgit v1.2.3 From 3f6a6f343c57a773ed146e54de8c626f72dd2be7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2020 11:07:54 +0100 Subject: drm/i915: Reduce i915_request.lock contention for i915_request_wait Currently, we use i915_request_completed() directly in i915_request_wait() and follow up with a manual invocation of dma_fence_signal(). This appears to cause a large number of contentions on i915_request.lock as when the process is woken up after the fence is signaled by an interrupt, we will then try and call dma_fence_signal() ourselves while the signaler is still holding the lock. dma_fence_is_signaled() has the benefit of checking the DMA_FENCE_FLAG_SIGNALED_BIT prior to calling dma_fence_signal() and so avoids most of that contention. Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200716100754.5670-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_request.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 7a05850ca931..0ec0beb1a83e 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1640,7 +1640,7 @@ static bool busywait_stop(unsigned long timeout, unsigned int cpu) return this_cpu != cpu; } -static bool __i915_spin_request(const struct i915_request * const rq, int state) +static bool __i915_spin_request(struct i915_request * const rq, int state) { unsigned long timeout_ns; unsigned int cpu; @@ -1673,7 +1673,7 @@ static bool __i915_spin_request(const struct i915_request * const rq, int state) timeout_ns = READ_ONCE(rq->engine->props.max_busywait_duration_ns); timeout_ns += local_clock_ns(&cpu); do { - if (i915_request_completed(rq)) + if (dma_fence_is_signaled(&rq->fence)) return true; if (signal_pending_state(state, current)) @@ -1697,7 +1697,7 @@ static void request_wait_wake(struct dma_fence *fence, struct dma_fence_cb *cb) { struct request_wait *wait = container_of(cb, typeof(*wait), cb); - wake_up_process(wait->tsk); + wake_up_process(fetch_and_zero(&wait->tsk)); } /** @@ -1766,10 +1766,8 @@ long i915_request_wait(struct i915_request *rq, * duration, which we currently lack. */ if (IS_ACTIVE(CONFIG_DRM_I915_MAX_REQUEST_BUSYWAIT) && - __i915_spin_request(rq, state)) { - dma_fence_signal(&rq->fence); + __i915_spin_request(rq, state)) goto out; - } /* * This client is about to stall waiting for the GPU. In many cases @@ -1793,10 +1791,8 @@ long i915_request_wait(struct i915_request *rq, for (;;) { set_current_state(state); - if (i915_request_completed(rq)) { - dma_fence_signal(&rq->fence); + if (dma_fence_is_signaled(&rq->fence)) break; - } intel_engine_flush_submission(rq->engine); @@ -1814,7 +1810,9 @@ long i915_request_wait(struct i915_request *rq, } __set_current_state(TASK_RUNNING); - dma_fence_remove_callback(&rq->fence, &wait.cb); + if (READ_ONCE(wait.tsk)) + dma_fence_remove_callback(&rq->fence, &wait.cb); + GEM_BUG_ON(!list_empty(&wait.cb.node)); out: mutex_release(&rq->engine->gt->reset.mutex.dep_map, _THIS_IP_); -- cgit v1.2.3 From e3d0e213960ece147954ea86a340329361d10e5b Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Jul 2020 16:58:58 +0100 Subject: drm/i915/selftests: Mock the status_page.vma for the kernel_context Since we assert that the kernel_context is using the perma-pinned HWSP, make it so. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2179 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200715155858.16410-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/mock_engine.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index b8dd3cbc8696..06303ba98c19 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -332,6 +332,9 @@ int mock_engine_init(struct intel_engine_cs *engine) if (IS_ERR(ce)) goto err_breadcrumbs; + /* We insist the kernel context is using the status_page */ + engine->status_page.vma = ce->timeline->hwsp_ggtt; + engine->kernel_context = ce; return 0; -- cgit v1.2.3 From 3adee4ac2922e30d2fe0583c0126c1e5fee4cc54 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Jul 2020 12:50:51 +0100 Subject: drm/i915: Soften the tasklet flush frequency before waits We include a tasklet flush before waiting on a request as a precaution against the HW being lax in event signaling. We now have a precautionary flush in the engine's heartbeat and so do not need to be quite so zealous on every request wait. If we focus on the request, the only tasklet flush that matters is if there is a delay in submitting this request to HW, so if the request is not ready to be executed, no advantage in reducing this wait can be gained by running the tasklet. And there is little point in doing busy work for no result. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200715115147.11866-10-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_request.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 0ec0beb1a83e..44c759490641 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1788,14 +1788,30 @@ long i915_request_wait(struct i915_request *rq, if (dma_fence_add_callback(&rq->fence, &wait.cb, request_wait_wake)) goto out; + /* + * Flush the submission tasklet, but only if it may help this request. + * + * We sometimes experience some latency between the HW interrupts and + * tasklet execution (mostly due to ksoftirqd latency, but it can also + * be due to lazy CS events), so lets run the tasklet manually if there + * is a chance it may submit this request. If the request is not ready + * to run, as it is waiting for other fences to be signaled, flushing + * the tasklet is busy work without any advantage for this client. + * + * If the HW is being lazy, this is the last chance before we go to + * sleep to catch any pending events. We will check periodically in + * the heartbeat to flush the submission tasklets as a last resort + * for unhappy HW. + */ + if (i915_request_is_ready(rq)) + intel_engine_flush_submission(rq->engine); + for (;;) { set_current_state(state); if (dma_fence_is_signaled(&rq->fence)) break; - intel_engine_flush_submission(rq->engine); - if (signal_pending_state(state, current)) { timeout = -ERESTARTSYS; break; -- cgit v1.2.3 From 27a5dcfe73f4b696b3de8c23a560199bb1c193a4 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:20:10 +0100 Subject: drm/i915/gem: Remove disordered per-file request list for throttling I915_GEM_THROTTLE dates back to the time before contexts where there was just a single engine, and therefore a single timeline and request list globally. That request list was in execution/retirement order, and so walking it to find a particular aged request made sense and could be split per file. That is no more. We now have many timelines with a file, as many as the user wants to construct (essentially per-engine, per-context). Each of those run independently and so make the single list futile. Remove the disordered list, and iterate over all the timelines to find a request to wait on in each to satisfy the criteria that the CPU is no more than 20ms ahead of its oldest request. It should go without saying that the I915_GEM_THROTTLE ioctl is no longer used as the primary means of throttling, so it makes sense to push the complication into the ioctl where it only impacts upon its few irregular users, rather than the execbuf/retire where everybody has to pay the cost. Fortunately, the few users do not create vast amount of contexts, so the loops over contexts/engines should be concise. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: Mika Kuoppala Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200728152010.30701-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 13 ----- drivers/gpu/drm/i915/gem/i915_gem_throttle.c | 67 ++++++++++++++++++-------- drivers/gpu/drm/i915/gt/selftest_lrc.c | 5 +- drivers/gpu/drm/i915/i915_drv.c | 1 - drivers/gpu/drm/i915/i915_drv.h | 6 --- drivers/gpu/drm/i915/i915_gem.c | 18 ------- drivers/gpu/drm/i915/i915_request.c | 21 -------- drivers/gpu/drm/i915/i915_request.h | 4 -- 8 files changed, 50 insertions(+), 85 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 02b1630f513e..90d77cdc6f66 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1928,18 +1928,6 @@ err: return err; } -static void -add_to_client(struct i915_request *rq, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv = file->driver_priv; - - rq->file_priv = file_priv; - - spin_lock(&file_priv->mm.lock); - list_add_tail(&rq->client_link, &file_priv->mm.request_list); - spin_unlock(&file_priv->mm.lock); -} - static int eb_submit(struct i915_execbuffer *eb, struct i915_vma *batch) { int err; @@ -2772,7 +2760,6 @@ i915_gem_do_execbuffer(struct drm_device *dev, trace_i915_request_queue(eb.request, eb.batch_flags); err = eb_submit(&eb, batch); err_request: - add_to_client(eb.request, file); i915_request_get(eb.request); eb_request_add(&eb); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_throttle.c b/drivers/gpu/drm/i915/gem/i915_gem_throttle.c index 540ef0551789..1929d6cf4150 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_throttle.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_throttle.c @@ -9,6 +9,7 @@ #include #include "i915_drv.h" +#include "i915_gem_context.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" @@ -35,9 +36,10 @@ int i915_gem_throttle_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { + const unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; struct drm_i915_file_private *file_priv = file->driver_priv; - unsigned long recent_enough = jiffies - DRM_I915_THROTTLE_JIFFIES; - struct i915_request *request, *target = NULL; + struct i915_gem_context *ctx; + unsigned long idx; long ret; /* ABI: return -EIO if already wedged */ @@ -45,27 +47,54 @@ i915_gem_throttle_ioctl(struct drm_device *dev, void *data, if (ret) return ret; - spin_lock(&file_priv->mm.lock); - list_for_each_entry(request, &file_priv->mm.request_list, client_link) { - if (time_after_eq(request->emitted_jiffies, recent_enough)) - break; + rcu_read_lock(); + xa_for_each(&file_priv->context_xa, idx, ctx) { + struct i915_gem_engines_iter it; + struct intel_context *ce; - if (target && xchg(&target->file_priv, NULL)) - list_del(&target->client_link); + if (!kref_get_unless_zero(&ctx->ref)) + continue; + rcu_read_unlock(); - target = request; - } - if (target) - i915_request_get(target); - spin_unlock(&file_priv->mm.lock); + for_each_gem_engine(ce, + i915_gem_context_lock_engines(ctx), + it) { + struct i915_request *rq, *target = NULL; + + if (!ce->timeline) + continue; + + mutex_lock(&ce->timeline->mutex); + list_for_each_entry_reverse(rq, + &ce->timeline->requests, + link) { + if (i915_request_completed(rq)) + break; - if (!target) - return 0; + if (time_after(rq->emitted_jiffies, + recent_enough)) + continue; - ret = i915_request_wait(target, - I915_WAIT_INTERRUPTIBLE, - MAX_SCHEDULE_TIMEOUT); - i915_request_put(target); + target = i915_request_get(rq); + break; + } + mutex_unlock(&ce->timeline->mutex); + if (!target) + continue; + + ret = i915_request_wait(target, + I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT); + i915_request_put(target); + if (ret < 0) + break; + } + i915_gem_context_unlock_engines(ctx); + i915_gem_context_put(ctx); + + rcu_read_lock(); + } + rcu_read_unlock(); return ret < 0 ? ret : 0; } diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 3fc5de961280..f749071f54a7 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -2729,7 +2729,7 @@ static int create_gang(struct intel_engine_cs *engine, i915_gem_object_put(obj); intel_context_put(ce); - rq->client_link.next = &(*prev)->client_link; + rq->mock.link.next = &(*prev)->mock.link; *prev = rq; return 0; @@ -2970,8 +2970,7 @@ static int live_preempt_gang(void *arg) } while (rq) { /* wait for each rq from highest to lowest prio */ - struct i915_request *n = - list_next_entry(rq, client_link); + struct i915_request *n = list_next_entry(rq, mock.link); if (err == 0 && i915_request_wait(rq, 0, HZ / 5) < 0) { struct drm_printer p = diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e6918c7c0709..d8aaa882560b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1119,7 +1119,6 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; i915_gem_context_close(file); - i915_gem_release(dev, file); kfree_rcu(file_priv, rcu); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1314e0e92c41..0fb83a780b21 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -203,11 +203,6 @@ struct drm_i915_file_private { struct rcu_head rcu; }; - struct { - spinlock_t lock; - struct list_head request_list; - } mm; - struct xarray context_xa; struct xarray vm_xa; @@ -1867,7 +1862,6 @@ void i915_gem_suspend_late(struct drm_i915_private *dev_priv); void i915_gem_resume(struct drm_i915_private *dev_priv); int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file); -void i915_gem_release(struct drm_device *dev, struct drm_file *file); int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, enum i915_cache_level cache_level); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9aa3066cb75d..e1de50780ed5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1301,21 +1301,6 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) return 0; } -void i915_gem_release(struct drm_device *dev, struct drm_file *file) -{ - struct drm_i915_file_private *file_priv = file->driver_priv; - struct i915_request *request; - - /* Clean up our request list when the client is going away, so that - * later retire_requests won't dereference our soon-to-be-gone - * file_priv. - */ - spin_lock(&file_priv->mm.lock); - list_for_each_entry(request, &file_priv->mm.request_list, client_link) - request->file_priv = NULL; - spin_unlock(&file_priv->mm.lock); -} - int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv; @@ -1331,9 +1316,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) file_priv->dev_priv = i915; file_priv->file = file; - spin_lock_init(&file_priv->mm.lock); - INIT_LIST_HEAD(&file_priv->mm.request_list); - file_priv->bsd_engine = -1; file_priv->hang_timestamp = jiffies; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 44c759490641..bb0cf8199c2d 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -212,24 +212,6 @@ static void __notify_execute_cb(struct i915_request *rq) init_llist_head(&rq->execute_cb); } -static inline void -remove_from_client(struct i915_request *request) -{ - struct drm_i915_file_private *file_priv; - - if (!READ_ONCE(request->file_priv)) - return; - - rcu_read_lock(); - file_priv = xchg(&request->file_priv, NULL); - if (file_priv) { - spin_lock(&file_priv->mm.lock); - list_del(&request->client_link); - spin_unlock(&file_priv->mm.lock); - } - rcu_read_unlock(); -} - static void free_capture_list(struct i915_request *request) { struct i915_capture_list *capture; @@ -330,7 +312,6 @@ bool i915_request_retire(struct i915_request *rq) GEM_BUG_ON(!llist_empty(&rq->execute_cb)); spin_unlock_irq(&rq->lock); - remove_from_client(rq); __list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */ intel_context_exit(rq->context); @@ -757,7 +738,6 @@ static void __i915_request_ctor(void *arg) dma_fence_init(&rq->fence, &i915_fence_ops, &rq->lock, 0, 0); - rq->file_priv = NULL; rq->capture_list = NULL; init_llist_head(&rq->execute_cb); @@ -847,7 +827,6 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp) /* No zalloc, everything must be cleared after use */ rq->batch = NULL; - GEM_BUG_ON(rq->file_priv); GEM_BUG_ON(rq->capture_list); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index 590762820761..fc18378c685d 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -284,10 +284,6 @@ struct i915_request { /** timeline->request entry for this request */ struct list_head link; - struct drm_i915_file_private *file_priv; - /** file_priv list entry for this request */ - struct list_head client_link; - I915_SELFTEST_DECLARE(struct { struct list_head link; unsigned long delay; -- cgit v1.2.3 From a817c891c12471ce9fc285c1246372474c39a3f2 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:21:09 +0100 Subject: drm/i915/gt: Disable preparser around xcs invalidations on tgl Unlike rcs where we have conclusive evidence from our selftesting that disabling the preparser before performing the TLB invalidate and relocations does impact upon the GPU execution, the evidence for the same requirement on xcs is much more circumstantial. Let's apply the preparser disable between batches as we invalidate the TLB as a dose of healthy paranoia, just in case. References: https://gitlab.freedesktop.org/drm/intel/-/issues/2169 Signed-off-by: Chris Wilson Cc: Mika Kuoppala Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200728152110.830-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index d03da2f64a49..1138b5c56e2f 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -4757,14 +4757,21 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode) intel_engine_mask_t aux_inv = 0; u32 cmd, *cs; + cmd = 4; + if (mode & EMIT_INVALIDATE) + cmd += 2; if (mode & EMIT_INVALIDATE) aux_inv = request->engine->mask & ~BIT(BCS0); + if (aux_inv) + cmd += 2 * hweight8(aux_inv) + 2; - cs = intel_ring_begin(request, - 4 + (aux_inv ? 2 * hweight8(aux_inv) + 2 : 0)); + cs = intel_ring_begin(request, cmd); if (IS_ERR(cs)) return PTR_ERR(cs); + if (mode & EMIT_INVALIDATE) + *cs++ = preparser_disable(true); + cmd = MI_FLUSH_DW + 1; /* We always require a command barrier so that subsequent @@ -4797,6 +4804,10 @@ static int gen12_emit_flush(struct i915_request *request, u32 mode) } *cs++ = MI_NOOP; } + + if (mode & EMIT_INVALIDATE) + *cs++ = preparser_disable(false); + intel_ring_advance(request, cs); return 0; -- cgit v1.2.3 From 06b73c2d0b65f17e698f6a662affd7a08853c86f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 09:02:45 +0100 Subject: drm/i915/gt: Delay taking the spinlock for grabbing from the buffer pool Some very low hanging fruit, but contention on the pool->lock is noticeable between intel_gt_get_buffer_pool() and pool_retire(), with the majority of the hold time due to the locked list iteration. If we make the node itself RCU protected, we can perform the search for an suitable node just under RCU, reserving taking the lock itself for claiming the node and manipulating the list. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200729080245.8070-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 100 ++++++++++++--------- .../gpu/drm/i915/gt/intel_gt_buffer_pool_types.h | 6 +- 2 files changed, 64 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 418ae184cecf..16dbf5436179 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -35,39 +35,62 @@ static void node_free(struct intel_gt_buffer_pool_node *node) { i915_gem_object_put(node->obj); i915_active_fini(&node->active); - kfree(node); + kfree_rcu(node, rcu); } -static void pool_free_work(struct work_struct *wrk) +static bool +pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) { - struct intel_gt_buffer_pool *pool = - container_of(wrk, typeof(*pool), work.work); - struct intel_gt_buffer_pool_node *node, *next; - unsigned long old = jiffies - HZ; + struct intel_gt_buffer_pool_node *node, *stale = NULL; bool active = false; - LIST_HEAD(stale); int n; /* Free buffers that have not been used in the past second */ - spin_lock_irq(&pool->lock); for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) { struct list_head *list = &pool->cache_list[n]; - /* Most recent at head; oldest at tail */ - list_for_each_entry_safe_reverse(node, next, list, link) { - if (time_before(node->age, old)) - break; + if (list_empty(list)) + continue; + + if (spin_trylock_irq(&pool->lock)) { + struct list_head *pos; - list_move(&node->link, &stale); + /* Most recent at head; oldest at tail */ + list_for_each_prev(pos, list) { + node = list_entry(pos, typeof(*node), link); + if (time_before(node->age, old)) + break; + + /* Check we are the first to claim this node */ + if (!xchg(&node->age, 0)) + break; + + node->free = stale; + stale = node; + } + if (!list_is_last(pos, list)) + __list_del_many(pos, list); + + spin_unlock_irq(&pool->lock); } + active |= !list_empty(list); } - spin_unlock_irq(&pool->lock); - list_for_each_entry_safe(node, next, &stale, link) + while ((node = stale)) { + stale = stale->free; node_free(node); + } + + return active; +} + +static void pool_free_work(struct work_struct *wrk) +{ + struct intel_gt_buffer_pool *pool = + container_of(wrk, typeof(*pool), work.work); - if (active) + if (pool_free_older_than(pool, jiffies - HZ)) schedule_delayed_work(&pool->work, round_jiffies_up_relative(HZ)); } @@ -108,9 +131,9 @@ static void pool_retire(struct i915_active *ref) /* Return this object to the shrinker pool */ i915_gem_object_make_purgeable(node->obj); + WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_lock_irqsave(&pool->lock, flags); - node->age = jiffies; - list_add(&node->link, list); + list_add_rcu(&node->link, list); spin_unlock_irqrestore(&pool->lock, flags); schedule_delayed_work(&pool->work, @@ -151,20 +174,30 @@ intel_gt_get_buffer_pool(struct intel_gt *gt, size_t size) struct intel_gt_buffer_pool *pool = >->buffer_pool; struct intel_gt_buffer_pool_node *node; struct list_head *list; - unsigned long flags; int ret; size = PAGE_ALIGN(size); list = bucket_for_size(pool, size); - spin_lock_irqsave(&pool->lock, flags); - list_for_each_entry(node, list, link) { + rcu_read_lock(); + list_for_each_entry_rcu(node, list, link) { + unsigned long age; + if (node->obj->base.size < size) continue; - list_del(&node->link); - break; + + age = READ_ONCE(node->age); + if (!age) + continue; + + if (cmpxchg(&node->age, age, 0) == age) { + spin_lock_irq(&pool->lock); + list_del_rcu(&node->link); + spin_unlock_irq(&pool->lock); + break; + } } - spin_unlock_irqrestore(&pool->lock, flags); + rcu_read_unlock(); if (&node->link == list) { node = node_create(pool, size); @@ -192,28 +225,13 @@ void intel_gt_init_buffer_pool(struct intel_gt *gt) INIT_DELAYED_WORK(&pool->work, pool_free_work); } -static void pool_free_imm(struct intel_gt_buffer_pool *pool) -{ - int n; - - spin_lock_irq(&pool->lock); - for (n = 0; n < ARRAY_SIZE(pool->cache_list); n++) { - struct intel_gt_buffer_pool_node *node, *next; - struct list_head *list = &pool->cache_list[n]; - - list_for_each_entry_safe(node, next, list, link) - node_free(node); - INIT_LIST_HEAD(list); - } - spin_unlock_irq(&pool->lock); -} - void intel_gt_flush_buffer_pool(struct intel_gt *gt) { struct intel_gt_buffer_pool *pool = >->buffer_pool; do { - pool_free_imm(pool); + while (pool_free_older_than(pool, jiffies + 1)) + ; } while (cancel_delayed_work_sync(&pool->work)); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h index e28bdda771ed..bcf1658c9633 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool_types.h @@ -25,7 +25,11 @@ struct intel_gt_buffer_pool_node { struct i915_active active; struct drm_i915_gem_object *obj; struct list_head link; - struct intel_gt_buffer_pool *pool; + union { + struct intel_gt_buffer_pool *pool; + struct intel_gt_buffer_pool_node *free; + struct rcu_head rcu; + }; unsigned long age; }; -- cgit v1.2.3 From 62b1522cc3217e75478b607562c678b052d9179a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:33:25 +0100 Subject: drm/i915/selftests: Flush the active barriers before asserting Before we peek at the barrier status for an assert, first serialise with its callbacks so that we see a stable value. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200728153325.28351-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/selftest_context.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/selftest_context.c b/drivers/gpu/drm/i915/gt/selftest_context.c index 52af1cee9a94..1f4020e906a8 100644 --- a/drivers/gpu/drm/i915/gt/selftest_context.c +++ b/drivers/gpu/drm/i915/gt/selftest_context.c @@ -68,6 +68,8 @@ static int context_sync(struct intel_context *ce) } while (!err); mutex_unlock(&tl->mutex); + /* Wait for all barriers to complete (remote CPU) before we check */ + i915_active_unlock_wait(&ce->active); return err; } -- cgit v1.2.3 From a30e4ec176c823fb1f3fed51483c07e813c4c9c5 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 12:07:56 +0100 Subject: drm/i915/gt: Fix termination condition for freeing all buffer objects A last minute change, that unfortunately broke CI so badly it declared SUCCESS, was to refactor the debug free all buffer pool code to reuse the normal worker, inverted the termination condition so that it instead of discarding the nodes, they were all declared young enough and eligible for reuse. Fixes: 06b73c2d0b65 ("drm/i915/gt: Delay taking the spinlock for grabbing from the buffer pool") Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200729110756.2344-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Updating Fixes: link after rebasing and reordering into drm-intel-gt-next] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 16dbf5436179..9e938d4f6bfe 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -38,8 +38,7 @@ static void node_free(struct intel_gt_buffer_pool_node *node) kfree_rcu(node, rcu); } -static bool -pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) +static bool pool_free_older_than(struct intel_gt_buffer_pool *pool, long keep) { struct intel_gt_buffer_pool_node *node, *stale = NULL; bool active = false; @@ -57,8 +56,12 @@ pool_free_older_than(struct intel_gt_buffer_pool *pool, unsigned long old) /* Most recent at head; oldest at tail */ list_for_each_prev(pos, list) { + unsigned long age; + node = list_entry(pos, typeof(*node), link); - if (time_before(node->age, old)) + + age = READ_ONCE(node->age); + if (!age || jiffies - age < keep) break; /* Check we are the first to claim this node */ @@ -90,7 +93,7 @@ static void pool_free_work(struct work_struct *wrk) struct intel_gt_buffer_pool *pool = container_of(wrk, typeof(*pool), work.work); - if (pool_free_older_than(pool, jiffies - HZ)) + if (pool_free_older_than(pool, HZ)) schedule_delayed_work(&pool->work, round_jiffies_up_relative(HZ)); } @@ -230,7 +233,7 @@ void intel_gt_flush_buffer_pool(struct intel_gt *gt) struct intel_gt_buffer_pool *pool = >->buffer_pool; do { - while (pool_free_older_than(pool, jiffies + 1)) + while (pool_free_older_than(pool, 0)) ; } while (cancel_delayed_work_sync(&pool->work)); } -- cgit v1.2.3 From eb4dedae920a07c485328af3da2202ec5184fb17 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Jul 2020 10:28:56 +0100 Subject: drm/i915/gem: Delay tracking the GEM context until it is registered Avoid exposing a partially constructed context by deferring the list_add() from the initial construction to the end of registration. Otherwise, if we peek into the list of contexts from inside debugfs, we may see the partially constructed context and chase down some dangling incomplete pointers. Reported-by: CQ Tang Fixes: 3aa9945a528e ("drm/i915: Separate GEM context construction and registration to userspace") References: f6e8aa387171 ("drm/i915: Report the number of closed vma held by each context in debugfs") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: CQ Tang Cc: # v5.2+ Reviewed-by: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20200730092856.23615-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d0bdb6d447ed..efc4ba34c06e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -713,6 +713,7 @@ __create_context(struct drm_i915_private *i915) ctx->i915 = i915; ctx->sched.priority = I915_USER_PRIORITY(I915_PRIORITY_NORMAL); mutex_init(&ctx->mutex); + INIT_LIST_HEAD(&ctx->link); spin_lock_init(&ctx->stale.lock); INIT_LIST_HEAD(&ctx->stale.engines); @@ -740,10 +741,6 @@ __create_context(struct drm_i915_private *i915) for (i = 0; i < ARRAY_SIZE(ctx->hang_timestamp); i++) ctx->hang_timestamp[i] = jiffies - CONTEXT_FAST_HANG_JIFFIES; - spin_lock(&i915->gem.contexts.lock); - list_add_tail(&ctx->link, &i915->gem.contexts.list); - spin_unlock(&i915->gem.contexts.lock); - return ctx; err_free: @@ -931,6 +928,7 @@ static int gem_context_register(struct i915_gem_context *ctx, struct drm_i915_file_private *fpriv, u32 *id) { + struct drm_i915_private *i915 = ctx->i915; struct i915_address_space *vm; int ret; @@ -949,8 +947,16 @@ static int gem_context_register(struct i915_gem_context *ctx, /* And finally expose ourselves to userspace via the idr */ ret = xa_alloc(&fpriv->context_xa, id, ctx, xa_limit_32b, GFP_KERNEL); if (ret) - put_pid(fetch_and_zero(&ctx->pid)); + goto err_pid; + + spin_lock(&i915->gem.contexts.lock); + list_add_tail(&ctx->link, &i915->gem.contexts.list); + spin_unlock(&i915->gem.contexts.lock); + + return 0; +err_pid: + put_pid(fetch_and_zero(&ctx->pid)); return ret; } -- cgit v1.2.3 From d1bf5dd8f6d510999b8a12687ee2662e26ab720c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Jul 2020 19:39:06 +0100 Subject: drm/i915/gt: Support multiple pinned timelines We may need to allocate more than one pinned context/timeline for each engine which can utilise the per-engine HWSP, so we need to give each a different offset within it. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200730183906.25422-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 18 +++++++++++++++--- drivers/gpu/drm/i915/gt/intel_lrc.c | 20 +++++++++++++------- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 3 ++- drivers/gpu/drm/i915/gt/intel_timeline.c | 12 +++++++----- drivers/gpu/drm/i915/gt/intel_timeline.h | 21 +++++++++++++++++++-- drivers/gpu/drm/i915/gt/mock_engine.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 6 +++--- 8 files changed, 61 insertions(+), 23 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index efc4ba34c06e..d8cccbab7a51 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -886,7 +886,7 @@ i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags) if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) { struct intel_timeline *timeline; - timeline = intel_timeline_create(&i915->gt, NULL); + timeline = intel_timeline_create(&i915->gt); if (IS_ERR(timeline)) { context_close(ctx); return ERR_CAST(timeline); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index dd1a42c4d344..86651bbef3a0 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -785,9 +785,11 @@ intel_engine_init_active(struct intel_engine_cs *engine, unsigned int subclass) } static struct intel_context * -create_kernel_context(struct intel_engine_cs *engine) +create_pinned_context(struct intel_engine_cs *engine, + unsigned int hwsp, + struct lock_class_key *key, + const char *name) { - static struct lock_class_key kernel; struct intel_context *ce; int err; @@ -796,6 +798,7 @@ create_kernel_context(struct intel_engine_cs *engine) return ce; __set_bit(CONTEXT_BARRIER_BIT, &ce->flags); + ce->timeline = page_pack_bits(NULL, hwsp); err = intel_context_pin(ce); /* perma-pin so it is always available */ if (err) { @@ -809,11 +812,20 @@ create_kernel_context(struct intel_engine_cs *engine) * should we need to inject GPU operations during their request * construction. */ - lockdep_set_class(&ce->timeline->mutex, &kernel); + lockdep_set_class_and_name(&ce->timeline->mutex, key, name); return ce; } +static struct intel_context * +create_kernel_context(struct intel_engine_cs *engine) +{ + static struct lock_class_key kernel; + + return create_pinned_context(engine, I915_GEM_HWS_SEQNO_ADDR, + &kernel, "kernel_context"); +} + /** * intel_engines_init_common - initialize cengine state which might require hw access * @engine: Engine to initialize. diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 1138b5c56e2f..4cc385e1e77e 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -5306,6 +5306,14 @@ populate_lr_context(struct intel_context *ce, return 0; } +static struct intel_timeline *pinned_timeline(struct intel_context *ce) +{ + struct intel_timeline *tl = fetch_and_zero(&ce->timeline); + + return intel_timeline_create_from_engine(ce->engine, + page_unmask_bits(tl)); +} + static int __execlists_context_alloc(struct intel_context *ce, struct intel_engine_cs *engine) { @@ -5336,19 +5344,17 @@ static int __execlists_context_alloc(struct intel_context *ce, goto error_deref_obj; } - if (!ce->timeline) { + if (!page_mask_bits(ce->timeline)) { struct intel_timeline *tl; - struct i915_vma *hwsp; /* * Use the static global HWSP for the kernel context, and * a dynamically allocated cacheline for everyone else. */ - hwsp = NULL; - if (unlikely(intel_context_is_barrier(ce))) - hwsp = engine->status_page.vma; - - tl = intel_timeline_create(engine->gt, hwsp); + if (unlikely(ce->timeline)) + tl = pinned_timeline(ce); + else + tl = intel_timeline_create(engine->gt); if (IS_ERR(tl)) { ret = PTR_ERR(tl); goto error_deref_obj; diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 94915f668715..87cef6d01141 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -1250,7 +1250,8 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) return -ENODEV; } - timeline = intel_timeline_create(engine->gt, engine->status_page.vma); + timeline = intel_timeline_create_from_engine(engine, + I915_GEM_HWS_SEQNO_ADDR); if (IS_ERR(timeline)) { err = PTR_ERR(timeline); goto err; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 46d20f5f3ddc..4f446534bad0 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -215,7 +215,8 @@ static void cacheline_free(struct intel_timeline_cacheline *cl) static int intel_timeline_init(struct intel_timeline *timeline, struct intel_gt *gt, - struct i915_vma *hwsp) + struct i915_vma *hwsp, + unsigned int offset) { void *vaddr; @@ -246,8 +247,7 @@ static int intel_timeline_init(struct intel_timeline *timeline, vaddr = page_mask_bits(cl->vaddr); } else { - timeline->hwsp_offset = I915_GEM_HWS_SEQNO_ADDR; - + timeline->hwsp_offset = offset; vaddr = i915_gem_object_pin_map(hwsp->obj, I915_MAP_WB); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -297,7 +297,9 @@ static void intel_timeline_fini(struct intel_timeline *timeline) } struct intel_timeline * -intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp) +__intel_timeline_create(struct intel_gt *gt, + struct i915_vma *global_hwsp, + unsigned int offset) { struct intel_timeline *timeline; int err; @@ -306,7 +308,7 @@ intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp) if (!timeline) return ERR_PTR(-ENOMEM); - err = intel_timeline_init(timeline, gt, global_hwsp); + err = intel_timeline_init(timeline, gt, global_hwsp, offset); if (err) { kfree(timeline); return ERR_PTR(err); diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.h b/drivers/gpu/drm/i915/gt/intel_timeline.h index 4298b9ac7327..06bd06c6595f 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline.h @@ -29,10 +29,27 @@ #include "i915_active.h" #include "i915_syncmap.h" -#include "gt/intel_timeline_types.h" +#include "intel_timeline_types.h" struct intel_timeline * -intel_timeline_create(struct intel_gt *gt, struct i915_vma *global_hwsp); +__intel_timeline_create(struct intel_gt *gt, + struct i915_vma *global_hwsp, + unsigned int offset); + +static inline struct intel_timeline * +intel_timeline_create(struct intel_gt *gt) +{ + return __intel_timeline_create(gt, NULL, 0); +} + +static inline struct intel_timeline * +intel_timeline_create_from_engine(struct intel_engine_cs *engine, + unsigned int offset) +{ + return __intel_timeline_create(engine->gt, + engine->status_page.vma, + offset); +} static inline struct intel_timeline * intel_timeline_get(struct intel_timeline *timeline) diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 06303ba98c19..d5beb116261f 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -153,7 +153,7 @@ static int mock_context_alloc(struct intel_context *ce) return -ENOMEM; GEM_BUG_ON(ce->timeline); - ce->timeline = intel_timeline_create(ce->engine->gt, NULL); + ce->timeline = intel_timeline_create(ce->engine->gt); if (IS_ERR(ce->timeline)) { kfree(ce->engine); return PTR_ERR(ce->timeline); diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 6564c989dbee..98ceac2fb77d 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -72,7 +72,7 @@ static int __mock_hwsp_timeline(struct mock_hwsp_freelist *state, unsigned long cacheline; int err; - tl = intel_timeline_create(state->gt, NULL); + tl = intel_timeline_create(state->gt); if (IS_ERR(tl)) return PTR_ERR(tl); @@ -487,7 +487,7 @@ checked_intel_timeline_create(struct intel_gt *gt) { struct intel_timeline *tl; - tl = intel_timeline_create(gt, NULL); + tl = intel_timeline_create(gt); if (IS_ERR(tl)) return tl; @@ -660,7 +660,7 @@ static int live_hwsp_wrap(void *arg) * foreign GPU references. */ - tl = intel_timeline_create(gt, NULL); + tl = intel_timeline_create(gt); if (IS_ERR(tl)) return PTR_ERR(tl); -- cgit v1.2.3 From 13106019f79bee105af1d3afdcb38b38771d81b9 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 30 Jul 2020 14:40:49 +0100 Subject: drm/i915/gt: Pull release of node->age under the spinlock We need to ensure that the list is valid prior to marking the node as retrievable, otherwise we may see two threads compete over the same node in intel_gt_get_buffer_pool(). If the first thread acquires and releases the node in the same jiffie, the second thread may then acquire it (as the jiffie now again matches the expected value) and claim the node before it is put back into the list. Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200730134049.8822-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c index 9e938d4f6bfe..4b7671ac5dca 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_buffer_pool.c @@ -134,9 +134,9 @@ static void pool_retire(struct i915_active *ref) /* Return this object to the shrinker pool */ i915_gem_object_make_purgeable(node->obj); - WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_lock_irqsave(&pool->lock, flags); list_add_rcu(&node->link, list); + WRITE_ONCE(node->age, jiffies ?: 1); /* 0 reserved for active nodes */ spin_unlock_irqrestore(&pool->lock, flags); schedule_delayed_work(&pool->work, -- cgit v1.2.3 From bde246d893fca22cf84f6fb044395ab0a47589b7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 11:22:06 +0100 Subject: drm/i915/selftests: Drop stale timeline constructor assert Since we pass around encoded parameters to the kernel context constructor using the ce->timeline pointer, we can no longer assert that it should be zero for mock timeline construction. Fixes: d1bf5dd8f6d5 ("drm/i915/gt: Support multiple pinned timelines") Signed-off-by: Chris Wilson Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200731102206.6793-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Updated Fixes: link after rebasing and reordering into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/mock_engine.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index d5beb116261f..027de53cd05b 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -152,7 +152,6 @@ static int mock_context_alloc(struct intel_context *ce) if (!ce->ring) return -ENOMEM; - GEM_BUG_ON(ce->timeline); ce->timeline = intel_timeline_create(ce->engine->gt); if (IS_ERR(ce->timeline)) { kfree(ce->engine); -- cgit v1.2.3 From 04240e30ed06498c02dd43e57dfef9433e5f1ced Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:10 +0100 Subject: drm/i915: Skip taking acquire mutex for no ref->active callback If no active callback is defined for i915_active, we do not need to serialise its enabling with the mutex. We still do only want to call the debug activate once, and must still serialise with a concurrent retire. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_active.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 1e1253207425..8c6197f8dd0b 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -416,6 +416,14 @@ bool i915_active_acquire_if_busy(struct i915_active *ref) return atomic_add_unless(&ref->count, 1, 0); } +static void __i915_active_activate(struct i915_active *ref) +{ + spin_lock_irq(&ref->tree_lock); /* __active_retire() */ + if (!atomic_fetch_inc(&ref->count)) + debug_active_activate(ref); + spin_unlock_irq(&ref->tree_lock); +} + int i915_active_acquire(struct i915_active *ref) { int err; @@ -423,19 +431,19 @@ int i915_active_acquire(struct i915_active *ref) if (i915_active_acquire_if_busy(ref)) return 0; + if (!ref->active) { + __i915_active_activate(ref); + return 0; + } + err = mutex_lock_interruptible(&ref->mutex); if (err) return err; if (likely(!i915_active_acquire_if_busy(ref))) { - if (ref->active) - err = ref->active(ref); - if (!err) { - spin_lock_irq(&ref->tree_lock); /* __active_retire() */ - debug_active_activate(ref); - atomic_inc(&ref->count); - spin_unlock_irq(&ref->tree_lock); - } + err = ref->active(ref); + if (!err) + __i915_active_activate(ref); } mutex_unlock(&ref->mutex); -- cgit v1.2.3 From 5d9341370f57c058a8d880490ba9e79e761b2d7a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:11 +0100 Subject: drm/i915: Export a preallocate variant of i915_active_acquire() Sometimes we have to be very careful not to allocate underneath a mutex (or spinlock) and yet still want to track activity. Enter i915_active_acquire_for_context(). This raises the activity counter on i915_active prior to use and ensures that the fence-tree contains a slot for the context. v2: Refactor active_lookup() so it can be called again before/after locking to resolve contention. Since we protect the rbtree until we idle, we can do a lockfree lookup, with the caveat that if another thread performs a concurrent insertion, the rotations from the insert may cause us to not find our target. A second pass holding the treelock will find the target if it exists, or the place to perform our insertion. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/gt/intel_timeline.c | 4 +- drivers/gpu/drm/i915/i915_active.c | 150 +++++++++++++++++++------ drivers/gpu/drm/i915/i915_active.h | 12 +- 4 files changed, 130 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 90d77cdc6f66..9ce114d67288 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1741,7 +1741,7 @@ __parser_mark_active(struct i915_vma *vma, { struct intel_gt_buffer_pool_node *node = vma->private; - return i915_active_ref(&node->active, tl, fence); + return i915_active_ref(&node->active, tl->fence_context, fence); } static int diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 4f446534bad0..2baecf414acb 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -486,7 +486,9 @@ __intel_timeline_get_seqno(struct intel_timeline *tl, * free it after the current request is retired, which ensures that * all writes into the cacheline from previous requests are complete. */ - err = i915_active_ref(&tl->hwsp_cacheline->active, tl, &rq->fence); + err = i915_active_ref(&tl->hwsp_cacheline->active, + tl->fence_context, + &rq->fence); if (err) goto err_cacheline; diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 8c6197f8dd0b..9890db303fed 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -28,12 +28,14 @@ static struct i915_global_active { } global; struct active_node { + struct rb_node node; struct i915_active_fence base; struct i915_active *ref; - struct rb_node node; u64 timeline; }; +#define fetch_node(x) rb_entry(READ_ONCE(x), typeof(struct active_node), node) + static inline struct active_node * node_from_active(struct i915_active_fence *active) { @@ -216,12 +218,9 @@ excl_retire(struct dma_fence *fence, struct dma_fence_cb *cb) active_retire(container_of(cb, struct i915_active, excl.cb)); } -static struct i915_active_fence * -active_instance(struct i915_active *ref, struct intel_timeline *tl) +static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) { - struct active_node *node, *prealloc; - struct rb_node **p, *parent; - u64 idx = tl->fence_context; + struct active_node *it; /* * We track the most recently used timeline to skip a rbtree search @@ -230,8 +229,39 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) * after the previous activity has been retired, or if it matches the * current timeline. */ - node = READ_ONCE(ref->cache); - if (node && node->timeline == idx) + it = READ_ONCE(ref->cache); + if (it && it->timeline == idx) + return it; + + BUILD_BUG_ON(offsetof(typeof(*it), node)); + + /* While active, the tree can only be built; not destroyed */ + GEM_BUG_ON(i915_active_is_idle(ref)); + + it = fetch_node(ref->tree.rb_node); + while (it) { + if (it->timeline < idx) { + it = fetch_node(it->node.rb_right); + } else if (it->timeline > idx) { + it = fetch_node(it->node.rb_left); + } else { + WRITE_ONCE(ref->cache, it); + break; + } + } + + /* NB: If the tree rotated beneath us, we may miss our target. */ + return it; +} + +static struct i915_active_fence * +active_instance(struct i915_active *ref, u64 idx) +{ + struct active_node *node, *prealloc; + struct rb_node **p, *parent; + + node = __active_lookup(ref, idx); + if (likely(node)) return &node->base; /* Preallocate a replacement, just in case */ @@ -268,10 +298,9 @@ active_instance(struct i915_active *ref, struct intel_timeline *tl) rb_insert_color(&node->node, &ref->tree); out: - ref->cache = node; + WRITE_ONCE(ref->cache, node); spin_unlock_irq(&ref->tree_lock); - BUILD_BUG_ON(offsetof(typeof(*node), base)); return &node->base; } @@ -353,63 +382,102 @@ __active_del_barrier(struct i915_active *ref, struct active_node *node) return ____active_del_barrier(ref, node, barrier_to_engine(node)); } -int i915_active_ref(struct i915_active *ref, - struct intel_timeline *tl, - struct dma_fence *fence) +static bool +replace_barrier(struct i915_active *ref, struct i915_active_fence *active) +{ + if (!is_barrier(active)) /* proto-node used by our idle barrier? */ + return false; + + /* + * This request is on the kernel_context timeline, and so + * we can use it to substitute for the pending idle-barrer + * request that we want to emit on the kernel_context. + */ + __active_del_barrier(ref, node_from_active(active)); + return true; +} + +int i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence) { struct i915_active_fence *active; int err; - lockdep_assert_held(&tl->mutex); - /* Prevent reaping in case we malloc/wait while building the tree */ err = i915_active_acquire(ref); if (err) return err; - active = active_instance(ref, tl); + active = active_instance(ref, idx); if (!active) { err = -ENOMEM; goto out; } - if (is_barrier(active)) { /* proto-node used by our idle barrier */ - /* - * This request is on the kernel_context timeline, and so - * we can use it to substitute for the pending idle-barrer - * request that we want to emit on the kernel_context. - */ - __active_del_barrier(ref, node_from_active(active)); + if (replace_barrier(ref, active)) { RCU_INIT_POINTER(active->fence, NULL); atomic_dec(&ref->count); } if (!__i915_active_fence_set(active, fence)) - atomic_inc(&ref->count); + __i915_active_acquire(ref); out: i915_active_release(ref); return err; } -struct dma_fence * -i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f) +static struct dma_fence * +__i915_active_set_fence(struct i915_active *ref, + struct i915_active_fence *active, + struct dma_fence *fence) { struct dma_fence *prev; - /* We expect the caller to manage the exclusive timeline ordering */ - GEM_BUG_ON(i915_active_is_idle(ref)); + if (replace_barrier(ref, active)) { + RCU_INIT_POINTER(active->fence, fence); + return NULL; + } rcu_read_lock(); - prev = __i915_active_fence_set(&ref->excl, f); + prev = __i915_active_fence_set(active, fence); if (prev) prev = dma_fence_get_rcu(prev); else - atomic_inc(&ref->count); + __i915_active_acquire(ref); rcu_read_unlock(); return prev; } +static struct i915_active_fence * +__active_fence(struct i915_active *ref, u64 idx) +{ + struct active_node *it; + + it = __active_lookup(ref, idx); + if (unlikely(!it)) { /* Contention with parallel tree builders! */ + spin_lock_irq(&ref->tree_lock); + it = __active_lookup(ref, idx); + spin_unlock_irq(&ref->tree_lock); + } + GEM_BUG_ON(!it); /* slot must be preallocated */ + + return &it->base; +} + +struct dma_fence * +__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence) +{ + /* Only valid while active, see i915_active_acquire_for_context() */ + return __i915_active_set_fence(ref, __active_fence(ref, idx), fence); +} + +struct dma_fence * +i915_active_set_exclusive(struct i915_active *ref, struct dma_fence *f) +{ + /* We expect the caller to manage the exclusive timeline ordering */ + return __i915_active_set_fence(ref, &ref->excl, f); +} + bool i915_active_acquire_if_busy(struct i915_active *ref) { debug_active_assert(ref); @@ -451,6 +519,24 @@ int i915_active_acquire(struct i915_active *ref) return err; } +int i915_active_acquire_for_context(struct i915_active *ref, u64 idx) +{ + struct i915_active_fence *active; + int err; + + err = i915_active_acquire(ref); + if (err) + return err; + + active = active_instance(ref, idx); + if (!active) { + i915_active_release(ref); + return -ENOMEM; + } + + return 0; /* return with active ref */ +} + void i915_active_release(struct i915_active *ref) { debug_active_assert(ref); @@ -754,7 +840,7 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) match: rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */ if (p == &ref->cache->node) - ref->cache = NULL; + WRITE_ONCE(ref->cache, NULL); spin_unlock_irq(&ref->tree_lock); return rb_entry(p, struct active_node, node); @@ -809,7 +895,7 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, */ RCU_INIT_POINTER(node->base.fence, ERR_PTR(-EAGAIN)); node->base.cb.node.prev = (void *)engine; - atomic_inc(&ref->count); + __i915_active_acquire(ref); } GEM_BUG_ON(rcu_access_pointer(node->base.fence) != ERR_PTR(-EAGAIN)); diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index cf4058150966..73ded3c52a04 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -163,14 +163,16 @@ void __i915_active_init(struct i915_active *ref, __i915_active_init(ref, active, retire, &__mkey, &__wkey); \ } while (0) -int i915_active_ref(struct i915_active *ref, - struct intel_timeline *tl, - struct dma_fence *fence); +struct dma_fence * +__i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence); +int i915_active_ref(struct i915_active *ref, u64 idx, struct dma_fence *fence); static inline int i915_active_add_request(struct i915_active *ref, struct i915_request *rq) { - return i915_active_ref(ref, i915_request_timeline(rq), &rq->fence); + return i915_active_ref(ref, + i915_request_timeline(rq)->fence_context, + &rq->fence); } struct dma_fence * @@ -198,7 +200,9 @@ int i915_request_await_active(struct i915_request *rq, #define I915_ACTIVE_AWAIT_BARRIER BIT(2) int i915_active_acquire(struct i915_active *ref); +int i915_active_acquire_for_context(struct i915_active *ref, u64 idx); bool i915_active_acquire_if_busy(struct i915_active *ref); + void i915_active_release(struct i915_active *ref); static inline void __i915_active_acquire(struct i915_active *ref) -- cgit v1.2.3 From 99a7f4dae7ee6081df04741e0c4ea5e49b139540 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:12 +0100 Subject: drm/i915: Keep the most recently used active-fence upon discard Whenever an i915_active idles, we prune its tree of old fence slots to prevent a gradual leak should it be used to track many, many timelines. The downside is that we then have to frequently reallocate the rbtree. A compromise is that we keep the most recently used fence slot, and reuse that for the next active reference as that is the most likely timeline to be reused. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-4-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_active.c | 27 ++++++++++++++++++++------- drivers/gpu/drm/i915/i915_active.h | 4 ---- 2 files changed, 20 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 9890db303fed..e63578c80f53 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -130,8 +130,8 @@ static inline void debug_active_assert(struct i915_active *ref) { } static void __active_retire(struct i915_active *ref) { + struct rb_root root = RB_ROOT; struct active_node *it, *n; - struct rb_root root; unsigned long flags; GEM_BUG_ON(i915_active_is_idle(ref)); @@ -143,9 +143,21 @@ __active_retire(struct i915_active *ref) GEM_BUG_ON(rcu_access_pointer(ref->excl.fence)); debug_active_deactivate(ref); - root = ref->tree; - ref->tree = RB_ROOT; - ref->cache = NULL; + /* Even if we have not used the cache, we may still have a barrier */ + if (!ref->cache) + ref->cache = fetch_node(ref->tree.rb_node); + + /* Keep the MRU cached node for reuse */ + if (ref->cache) { + /* Discard all other nodes in the tree */ + rb_erase(&ref->cache->node, &ref->tree); + root = ref->tree; + + /* Rebuild the tree with only the cached node */ + rb_link_node(&ref->cache->node, NULL, &ref->tree.rb_node); + rb_insert_color(&ref->cache->node, &ref->tree); + GEM_BUG_ON(ref->tree.rb_node != &ref->cache->node); + } spin_unlock_irqrestore(&ref->tree_lock, flags); @@ -156,6 +168,7 @@ __active_retire(struct i915_active *ref) /* ... except if you wait on it, you must manage your own references! */ wake_up_var(ref); + /* Finally free the discarded timeline tree */ rbtree_postorder_for_each_entry_safe(it, n, &root, node) { GEM_BUG_ON(i915_active_fence_isset(&it->base)); kmem_cache_free(global.slab_cache, it); @@ -745,16 +758,16 @@ int i915_sw_fence_await_active(struct i915_sw_fence *fence, return await_active(ref, flags, sw_await_fence, fence, fence); } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) void i915_active_fini(struct i915_active *ref) { debug_active_fini(ref); GEM_BUG_ON(atomic_read(&ref->count)); GEM_BUG_ON(work_pending(&ref->work)); - GEM_BUG_ON(!RB_EMPTY_ROOT(&ref->tree)); mutex_destroy(&ref->mutex); + + if (ref->cache) + kmem_cache_free(global.slab_cache, ref->cache); } -#endif static inline bool is_idle_barrier(struct active_node *node, u64 idx) { diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index 73ded3c52a04..b9e0394e2975 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -217,11 +217,7 @@ i915_active_is_idle(const struct i915_active *ref) return !atomic_read(&ref->count); } -#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) void i915_active_fini(struct i915_active *ref); -#else -static inline void i915_active_fini(struct i915_active *ref) { } -#endif int i915_active_acquire_preallocate_barrier(struct i915_active *ref, struct intel_engine_cs *engine); -- cgit v1.2.3 From e28860ae21da258a1f983b52941a3f581281d114 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:13 +0100 Subject: drm/i915: Make the stale cached active node available for any timeline Rather than require the next timeline after idling to match the MRU before idling, reset the index on the node and allow it to match the first request. However, this requires cmpxchg(u64) and so is not trivial on 32b, so for compatibility we just fallback to keeping the cached node pointing to the MRU timeline. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-5-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_active.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index e63578c80f53..89c34a69a2ea 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -157,6 +157,10 @@ __active_retire(struct i915_active *ref) rb_link_node(&ref->cache->node, NULL, &ref->tree.rb_node); rb_insert_color(&ref->cache->node, &ref->tree); GEM_BUG_ON(ref->tree.rb_node != &ref->cache->node); + + /* Make the cached node available for reuse with any timeline */ + if (IS_ENABLED(CONFIG_64BIT)) + ref->cache->timeline = 0; /* needs cmpxchg(u64) */ } spin_unlock_irqrestore(&ref->tree_lock, flags); @@ -235,6 +239,8 @@ static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) { struct active_node *it; + GEM_BUG_ON(idx == 0); /* 0 is the unordered timeline, rsvd for cache */ + /* * We track the most recently used timeline to skip a rbtree search * for the common case, under typical loads we never need the rbtree @@ -243,8 +249,28 @@ static struct active_node *__active_lookup(struct i915_active *ref, u64 idx) * current timeline. */ it = READ_ONCE(ref->cache); - if (it && it->timeline == idx) - return it; + if (it) { + u64 cached = READ_ONCE(it->timeline); + + /* Once claimed, this slot will only belong to this idx */ + if (cached == idx) + return it; + +#ifdef CONFIG_64BIT /* for cmpxchg(u64) */ + /* + * An unclaimed cache [.timeline=0] can only be claimed once. + * + * If the value is already non-zero, some other thread has + * claimed the cache and we know that is does not match our + * idx. If, and only if, the timeline is currently zero is it + * worth competing to claim it atomically for ourselves (for + * only the winner of that race will cmpxchg return the old + * value of 0). + */ + if (!cached && !cmpxchg(&it->timeline, 0, idx)) + return it; +#endif + } BUILD_BUG_ON(offsetof(typeof(*it), node)); -- cgit v1.2.3 From 9ff33bbcda259a7d1d4df8c977b32cf431972387 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:14 +0100 Subject: drm/i915: Reduce locking around i915_active_acquire_preallocate_barrier() As the conversion between idle-barrier and full i915_active_fence is already serialised by explicit memory barriers, we can reduce the spinlock in i915_active_acquire_preallocate_barrier() for finding an idle-barrier to reuse to an RCU read lock to ensure the fence remains valid, only taking the spinlock for the update of the rbtree itself. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-6-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_active.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index 89c34a69a2ea..b0a6522be3d1 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -807,7 +807,6 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) if (RB_EMPTY_ROOT(&ref->tree)) return NULL; - spin_lock_irq(&ref->tree_lock); GEM_BUG_ON(i915_active_is_idle(ref)); /* @@ -833,9 +832,9 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) prev = p; if (node->timeline < idx) - p = p->rb_right; + p = READ_ONCE(p->rb_right); else - p = p->rb_left; + p = READ_ONCE(p->rb_left); } /* @@ -872,11 +871,10 @@ static struct active_node *reuse_idle_barrier(struct i915_active *ref, u64 idx) goto match; } - spin_unlock_irq(&ref->tree_lock); - return NULL; match: + spin_lock_irq(&ref->tree_lock); rb_erase(p, &ref->tree); /* Hide from waits and sibling allocations */ if (p == &ref->cache->node) WRITE_ONCE(ref->cache, NULL); @@ -910,7 +908,9 @@ int i915_active_acquire_preallocate_barrier(struct i915_active *ref, struct llist_node *prev = first; struct active_node *node; + rcu_read_lock(); node = reuse_idle_barrier(ref, idx); + rcu_read_unlock(); if (!node) { node = kmem_cache_alloc(global.slab_cache, GFP_KERNEL); if (!node) -- cgit v1.2.3 From af5c6fcf403288e8656143549881c3eb716cae53 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 09:50:15 +0100 Subject: drm/i915: Provide a fastpath for waiting on vma bindings Before we can execute a request, we must wait for all of its vma to be bound. This is a frequent operation for which we can optimise away a few atomic operations (notably a cmpxchg) in lieu of the RCU protection. Signed-off-by: Chris Wilson Reviewed-by: Thomas Hellström Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731085015.32368-7-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_active.h | 15 +++++++++++++++ drivers/gpu/drm/i915/i915_vma.c | 9 +++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_active.h b/drivers/gpu/drm/i915/i915_active.h index b9e0394e2975..fb165d3f01cf 100644 --- a/drivers/gpu/drm/i915/i915_active.h +++ b/drivers/gpu/drm/i915/i915_active.h @@ -231,4 +231,19 @@ struct i915_active *i915_active_create(void); struct i915_active *i915_active_get(struct i915_active *ref); void i915_active_put(struct i915_active *ref); +static inline int __i915_request_await_exclusive(struct i915_request *rq, + struct i915_active *active) +{ + struct dma_fence *fence; + int err = 0; + + fence = i915_active_fence_get(&active->excl); + if (fence) { + err = i915_request_await_dma_fence(rq, fence); + dma_fence_put(fence); + } + + return err; +} + #endif /* _I915_ACTIVE_H_ */ diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index bc64f773dcdb..cd12047c7791 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1167,6 +1167,12 @@ void i915_vma_revoke_mmap(struct i915_vma *vma) list_del(&vma->obj->userfault_link); } +static int +__i915_request_await_bind(struct i915_request *rq, struct i915_vma *vma) +{ + return __i915_request_await_exclusive(rq, &vma->active); +} + int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq) { int err; @@ -1174,8 +1180,7 @@ int __i915_vma_move_to_active(struct i915_vma *vma, struct i915_request *rq) GEM_BUG_ON(!i915_vma_is_pinned(vma)); /* Wait for the vma to be bound before we start! */ - err = i915_request_await_active(rq, &vma->active, - I915_ACTIVE_AWAIT_EXCL); + err = __i915_request_await_bind(rq, vma); if (err) return err; -- cgit v1.2.3 From c18636f76344fd544c5b444d030a2d1d74bb0103 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 16:48:31 +0100 Subject: drm/i915: Remove requirement for holding i915_request.lock for breadcrumbs Since the breadcrumb enabling/cancelling itself is serialised by the breadcrumbs.irq_lock, with a bit of care we can remove the outer serialisation with i915_request.lock for concurrent dma_fence_enable_signaling(). This has the important side-effect of eliminating the nested i915_request.lock within request submission. The challenge in serialisation is around the unsubmission where we take an active request that wants a breadcrumb on the signaling engine and put it to sleep. We do not want a concurrent dma_fence_enable_signaling() to attach a breadcrumb as we unsubmit, so we must mark the request as no longer active before serialising with the concurrent enable-signaling. On retire, we serialise with the concurrent enable-signaling, but instead of clearing ACTIVE, we mark it as SIGNALED. Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Rebased and reordered into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 130 ++++++++++++++++++---------- drivers/gpu/drm/i915/gt/intel_lrc.c | 14 --- drivers/gpu/drm/i915/i915_request.c | 66 ++++++++------ 3 files changed, 123 insertions(+), 87 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 91786310c114..3d211a0c2b5a 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -220,17 +220,17 @@ static void signal_irq_work(struct irq_work *work) } } -static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) +static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { struct intel_engine_cs *engine = container_of(b, struct intel_engine_cs, breadcrumbs); lockdep_assert_held(&b->irq_lock); if (b->irq_armed) - return true; + return; if (!intel_gt_pm_get_if_awake(engine->gt)) - return false; + return; /* * The breadcrumb irq will be disarmed on the interrupt after the @@ -250,8 +250,6 @@ static bool __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) if (!b->irq_enabled++) irq_enable(engine); - - return true; } void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) @@ -310,57 +308,99 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) { } -bool i915_request_enable_breadcrumb(struct i915_request *rq) +static void insert_breadcrumb(struct i915_request *rq, + struct intel_breadcrumbs *b) { - lockdep_assert_held(&rq->lock); + struct intel_context *ce = rq->context; + struct list_head *pos; - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) - return true; + if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) + return; - if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) { - struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; - struct intel_context *ce = rq->context; - struct list_head *pos; + __intel_breadcrumbs_arm_irq(b); - spin_lock(&b->irq_lock); + /* + * We keep the seqno in retirement order, so we can break + * inside intel_engine_signal_breadcrumbs as soon as we've + * passed the last completed request (or seen a request that + * hasn't event started). We could walk the timeline->requests, + * but keeping a separate signalers_list has the advantage of + * hopefully being much smaller than the full list and so + * provides faster iteration and detection when there are no + * more interrupts required for this context. + * + * We typically expect to add new signalers in order, so we + * start looking for our insertion point from the tail of + * the list. + */ + list_for_each_prev(pos, &ce->signals) { + struct i915_request *it = + list_entry(pos, typeof(*it), signal_link); - if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) - goto unlock; + if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) + break; + } + list_add(&rq->signal_link, pos); + if (pos == &ce->signals) /* catch transitions from empty list */ + list_move_tail(&ce->signal_link, &b->signalers); + GEM_BUG_ON(!check_signal_order(ce, rq)); - if (!__intel_breadcrumbs_arm_irq(b)) - goto unlock; + set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); +} - /* - * We keep the seqno in retirement order, so we can break - * inside intel_engine_signal_breadcrumbs as soon as we've - * passed the last completed request (or seen a request that - * hasn't event started). We could walk the timeline->requests, - * but keeping a separate signalers_list has the advantage of - * hopefully being much smaller than the full list and so - * provides faster iteration and detection when there are no - * more interrupts required for this context. - * - * We typically expect to add new signalers in order, so we - * start looking for our insertion point from the tail of - * the list. - */ - list_for_each_prev(pos, &ce->signals) { - struct i915_request *it = - list_entry(pos, typeof(*it), signal_link); +bool i915_request_enable_breadcrumb(struct i915_request *rq) +{ + struct intel_breadcrumbs *b; - if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) - break; - } - list_add(&rq->signal_link, pos); - if (pos == &ce->signals) /* catch transitions from empty list */ - list_move_tail(&ce->signal_link, &b->signalers); - GEM_BUG_ON(!check_signal_order(ce, rq)); + /* Serialises with i915_request_retire() using rq->lock */ + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &rq->fence.flags)) + return true; - set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); -unlock: + /* + * Peek at i915_request_submit()/i915_request_unsubmit() status. + * + * If the request is not yet active (and not signaled), we will + * attach the breadcrumb later. + */ + if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) + return true; + + /* + * rq->engine is locked by rq->engine->active.lock. That however + * is not known until after rq->engine has been dereferenced and + * the lock acquired. Hence we acquire the lock and then validate + * that rq->engine still matches the lock we hold for it. + * + * Here, we are using the breadcrumb lock as a proxy for the + * rq->engine->active.lock, and we know that since the breadcrumb + * will be serialised within i915_request_submit/i915_request_unsubmit, + * the engine cannot change while active as long as we hold the + * breadcrumb lock on that engine. + * + * From the dma_fence_enable_signaling() path, we are outside of the + * request submit/unsubmit path, and so we must be more careful to + * acquire the right lock. + */ + b = &READ_ONCE(rq->engine)->breadcrumbs; + spin_lock(&b->irq_lock); + while (unlikely(b != &READ_ONCE(rq->engine)->breadcrumbs)) { spin_unlock(&b->irq_lock); + b = &READ_ONCE(rq->engine)->breadcrumbs; + spin_lock(&b->irq_lock); } + /* + * Now that we are finally serialised with request submit/unsubmit, + * [with b->irq_lock] and with i915_request_retire() [via checking + * SIGNALED with rq->lock] confirm the request is indeed active. If + * it is no longer active, the breadcrumb will be attached upon + * i915_request_submit(). + */ + if (test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) + insert_breadcrumb(rq, b); + + spin_unlock(&b->irq_lock); + return !__request_completed(rq); } @@ -368,8 +408,6 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) { struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; - lockdep_assert_held(&rq->lock); - /* * We must wait for b->irq_lock so that we know the interrupt handler * has released its reference to the intel_context and has completed diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 4cc385e1e77e..35174bf33207 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1148,20 +1148,6 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine) } else { struct intel_engine_cs *owner = rq->context->engine; - /* - * Decouple the virtual breadcrumb before moving it - * back to the virtual engine -- we don't want the - * request to complete in the background and try - * and cancel the breadcrumb on the virtual engine - * (instead of the old engine where it is linked)! - */ - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, - &rq->fence.flags)) { - spin_lock_nested(&rq->lock, - SINGLE_DEPTH_NESTING); - i915_request_cancel_breadcrumb(rq); - spin_unlock(&rq->lock); - } WRITE_ONCE(rq->engine, owner); owner->submit_request(rq); active = NULL; diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index bb0cf8199c2d..956edbe5b196 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -301,14 +301,24 @@ bool i915_request_retire(struct i915_request *rq) dma_fence_signal_locked(&rq->fence); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags)) i915_request_cancel_breadcrumb(rq); + spin_unlock_irq(&rq->lock); + if (i915_request_has_waitboost(rq)) { GEM_BUG_ON(!atomic_read(&rq->engine->gt->rps.num_waiters)); atomic_dec(&rq->engine->gt->rps.num_waiters); } - if (!test_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags)) { - set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags); - __notify_execute_cb(rq); - } + + /* + * We only loosely track inflight requests across preemption, + * and so we may find ourselves attempting to retire a _completed_ + * request that we have removed from the HW and put back on a run + * queue. + * + * As we set I915_FENCE_FLAG_ACTIVE on the request, this should be + * after removing the breadcrumb and signaling it, so that we do not + * inadvertently attach the breadcrumb to a completed request. + */ + remove_from_engine(rq); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); spin_unlock_irq(&rq->lock); @@ -547,19 +557,21 @@ xfer: clear_bit(I915_FENCE_FLAG_PQUEUE, &request->fence.flags); } - /* We may be recursing from the signal callback of another i915 fence */ - if (!i915_request_signaled(request)) { - spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); - - __notify_execute_cb(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, - &request->fence.flags) && - !i915_request_enable_breadcrumb(request)) - intel_engine_signal_breadcrumbs(engine); + /* + * XXX Rollback bonded-execution on __i915_request_unsubmit()? + * + * In the future, perhaps when we have an active time-slicing scheduler, + * it will be interesting to unsubmit parallel execution and remove + * busywaits from the GPU until their master is restarted. This is + * quite hairy, we have to carefully rollback the fence and do a + * preempt-to-idle cycle on the target engine, all the while the + * master execute_cb may refire. + */ + __notify_execute_cb(request); - spin_unlock(&request->lock); - GEM_BUG_ON(!llist_empty(&request->execute_cb)); - } + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && + !i915_request_enable_breadcrumb(request)) + intel_engine_signal_breadcrumbs(engine); return result; } @@ -581,27 +593,27 @@ void __i915_request_unsubmit(struct i915_request *request) { struct intel_engine_cs *engine = request->engine; + /* + * Only unwind in reverse order, required so that the per-context list + * is kept in seqno/ring order. + */ RQ_TRACE(request, "\n"); GEM_BUG_ON(!irqs_disabled()); lockdep_assert_held(&engine->active.lock); /* - * Only unwind in reverse order, required so that the per-context list - * is kept in seqno/ring order. + * Before we remove this breadcrumb from the signal list, we have + * to ensure that a concurrent dma_fence_enable_signaling() does not + * attach itself. We first mark the request as no longer active and + * make sure that is visible to other cores, and then remove the + * breadcrumb if attached. */ - - /* We may be recursing from the signal callback of another i915 fence */ - spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); - + GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags)); + clear_bit_unlock(I915_FENCE_FLAG_ACTIVE, &request->fence.flags); if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) i915_request_cancel_breadcrumb(request); - GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags)); - clear_bit(I915_FENCE_FLAG_ACTIVE, &request->fence.flags); - - spin_unlock(&request->lock); - /* We've already spun, don't charge on resubmitting. */ if (request->sched.semaphores && i915_request_started(request)) request->sched.semaphores = 0; -- cgit v1.2.3 From 2854d866327a390540c71ca3f76ce516ae7af66f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 16:48:32 +0100 Subject: drm/i915/gt: Replace intel_engine_transfer_stale_breadcrumbs After staring at the breadcrumb enabling/cancellation and coming to the conclusion that the cause of the mysterious stale breadcrumbs must the act of submitting a completed requests, we can then redirect those completed requests onto a dedicated signaled_list at the time of construction and so eliminate intel_engine_transfer_stale_breadcrumbs(). Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 50 +++++++++++------------------ drivers/gpu/drm/i915/gt/intel_engine.h | 3 -- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 --------- drivers/gpu/drm/i915/i915_request.c | 5 ++- 4 files changed, 21 insertions(+), 52 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 3d211a0c2b5a..fbdc465a5870 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -142,16 +142,16 @@ static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) intel_engine_add_retire(engine, tl); } -static void __signal_request(struct i915_request *rq, struct list_head *signals) +static bool __signal_request(struct i915_request *rq, struct list_head *signals) { - GEM_BUG_ON(!test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)); clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); if (!__dma_fence_signal(&rq->fence)) - return; + return false; i915_request_get(rq); list_add_tail(&rq->signal_link, signals); + return true; } static void signal_irq_work(struct irq_work *work) @@ -278,32 +278,6 @@ void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) spin_unlock_irqrestore(&b->irq_lock, flags); } -void intel_engine_transfer_stale_breadcrumbs(struct intel_engine_cs *engine, - struct intel_context *ce) -{ - struct intel_breadcrumbs *b = &engine->breadcrumbs; - unsigned long flags; - - spin_lock_irqsave(&b->irq_lock, flags); - if (!list_empty(&ce->signals)) { - struct i915_request *rq, *next; - - /* Queue for executing the signal callbacks in the irq_work */ - list_for_each_entry_safe(rq, next, &ce->signals, signal_link) { - GEM_BUG_ON(rq->engine != engine); - GEM_BUG_ON(!__request_completed(rq)); - - __signal_request(rq, &b->signaled_requests); - } - - INIT_LIST_HEAD(&ce->signals); - list_del_init(&ce->signal_link); - - irq_work_queue(&b->irq_work); - } - spin_unlock_irqrestore(&b->irq_lock, flags); -} - void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) { } @@ -317,6 +291,17 @@ static void insert_breadcrumb(struct i915_request *rq, if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) return; + /* + * If the request is already completed, we can transfer it + * straight onto a signaled list, and queue the irq worker for + * its signal completion. + */ + if (__request_completed(rq)) { + if (__signal_request(rq, &b->signaled_requests)) + irq_work_queue(&b->irq_work); + return; + } + __intel_breadcrumbs_arm_irq(b); /* @@ -344,8 +329,11 @@ static void insert_breadcrumb(struct i915_request *rq, if (pos == &ce->signals) /* catch transitions from empty list */ list_move_tail(&ce->signal_link, &b->signalers); GEM_BUG_ON(!check_signal_order(ce, rq)); - set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); + + /* Check after attaching to irq, interrupt may have already fired. */ + if (__request_completed(rq)) + irq_work_queue(&b->irq_work); } bool i915_request_enable_breadcrumb(struct i915_request *rq) @@ -401,7 +389,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) spin_unlock(&b->irq_lock); - return !__request_completed(rq); + return true; } void i915_request_cancel_breadcrumb(struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index a9249a23903a..faf00a353e25 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -237,9 +237,6 @@ intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_transfer_stale_breadcrumbs(struct intel_engine_cs *engine, - struct intel_context *ce); - void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, struct drm_printer *p); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 35174bf33207..17e70778bf9d 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1805,18 +1805,6 @@ static bool virtual_matches(const struct virtual_engine *ve, return true; } -static void virtual_xfer_breadcrumbs(struct virtual_engine *ve) -{ - /* - * All the outstanding signals on ve->siblings[0] must have - * been completed, just pending the interrupt handler. As those - * signals still refer to the old sibling (via rq->engine), we must - * transfer those to the old irq_worker to keep our locking - * consistent. - */ - intel_engine_transfer_stale_breadcrumbs(ve->siblings[0], &ve->context); -} - #define for_each_waiter(p__, rq__) \ list_for_each_entry_lockless(p__, \ &(rq__)->sched.waiters_list, \ @@ -2267,9 +2255,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine) virtual_update_register_offsets(regs, engine); - if (!list_empty(&ve->context.signals)) - virtual_xfer_breadcrumbs(ve); - /* * Move the bound engine to the top of the list * for future execution. We then kick this diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 956edbe5b196..e9d5ce247ae9 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -569,9 +569,8 @@ xfer: */ __notify_execute_cb(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags) && - !i915_request_enable_breadcrumb(request)) - intel_engine_signal_breadcrumbs(engine); + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) + i915_request_enable_breadcrumb(request); return result; } -- cgit v1.2.3 From 56f581bad4bf25b336593a7f7531b24424b1ecf8 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 16:48:33 +0100 Subject: drm/i915/gt: Only transfer the virtual context to the new engine if active One more complication of preempt-to-busy with respect to the virtual engine is that we may have retired the last request along the virtual engine at the same time as preparing to submit the completed request to a new engine. That submit will be shortcircuited, but not before we have updated the context with the new register offsets and marked the virtual engine as bound to the new engine (by calling swap on ve->siblings[]). As we may have just retired the completed request, we may also be in the middle of calling virtual_context_exit() to turn off the power management associated with the virtual engine, and that in turn walks the ve->siblings[]. If we happen to call swap() on the array as we walk, we will call intel_engine_pm_put() twice on the same engine. In this patch, we prevent this by only updating the bound engine after a successful submission which weeds out the already completed requests. Alternatively, we could walk a non-volatile array for the pm, such as using the engine->mask. The small advantage to performing the update after the submit is that we then only have to do a swap for active requests. Fixes: 22b7a426bbe1 ("drm/i915/execlists: Preempt-to-busy") References: 6d06779e8672 ("drm/i915: Load balancing across a virtual engine" Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Cc: "Nayana, Venkata Ramana" Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_lrc.c | 65 +++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 25 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 17e70778bf9d..e5a37d14bce8 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1805,6 +1805,33 @@ static bool virtual_matches(const struct virtual_engine *ve, return true; } +static void virtual_xfer_context(struct virtual_engine *ve, + struct intel_engine_cs *engine) +{ + unsigned int n; + + if (likely(engine == ve->siblings[0])) + return; + + GEM_BUG_ON(READ_ONCE(ve->context.inflight)); + if (!intel_engine_has_relative_mmio(engine)) + virtual_update_register_offsets(ve->context.lrc_reg_state, + engine); + + /* + * Move the bound engine to the top of the list for + * future execution. We then kick this tasklet first + * before checking others, so that we preferentially + * reuse this set of bound registers. + */ + for (n = 1; n < ve->num_siblings; n++) { + if (ve->siblings[n] == engine) { + swap(ve->siblings[n], ve->siblings[0]); + break; + } + } +} + #define for_each_waiter(p__, rq__) \ list_for_each_entry_lockless(p__, \ &(rq__)->sched.waiters_list, \ @@ -2245,35 +2272,23 @@ static void execlists_dequeue(struct intel_engine_cs *engine) GEM_BUG_ON(!(rq->execution_mask & engine->mask)); WRITE_ONCE(rq->engine, engine); - if (engine != ve->siblings[0]) { - u32 *regs = ve->context.lrc_reg_state; - unsigned int n; - - GEM_BUG_ON(READ_ONCE(ve->context.inflight)); - - if (!intel_engine_has_relative_mmio(engine)) - virtual_update_register_offsets(regs, - engine); - + if (__i915_request_submit(rq)) { /* - * Move the bound engine to the top of the list - * for future execution. We then kick this - * tasklet first before checking others, so that - * we preferentially reuse this set of bound - * registers. + * Only after we confirm that we will submit + * this request (i.e. it has not already + * completed), do we want to update the context. + * + * This serves two purposes. It avoids + * unnecessary work if we are resubmitting an + * already completed request after timeslicing. + * But more importantly, it prevents us altering + * ve->siblings[] on an idle context, where + * we may be using ve->siblings[] in + * virtual_context_enter / virtual_context_exit. */ - for (n = 1; n < ve->num_siblings; n++) { - if (ve->siblings[n] == engine) { - swap(ve->siblings[n], - ve->siblings[0]); - break; - } - } - + virtual_xfer_context(ve, engine); GEM_BUG_ON(ve->siblings[0] != engine); - } - if (__i915_request_submit(rq)) { submit = true; last = rq; } -- cgit v1.2.3 From b3786b29379c0e5d1e4e162ad5464d77aa4bc4db Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 31 Jul 2020 16:48:34 +0100 Subject: drm/i915/gt: Distinguish the virtual breadcrumbs from the irq breadcrumbs On the virtual engines, we only use the intel_breadcrumbs for tracking signaling of stale breadcrumbs from the irq_workers. They do not have any associated interrupt handling, active requests are passed to a physical engine and associated breadcrumb interrupt handler. This causes issues for us as we need to ensure that we do not actually try and enable interrupts and the powermanagement required for them on the virtual engine, as they will never be disabled. Instead, let's specify the physical engine used for interrupt handler on a particular breadcrumb. v2: Drop b->irq_armed = true mocking for no interrupt HW Fixes: 4fe6abb8f513 ("drm/i915/gt: Ignore irq enabling on the virtual engines") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200731154834.8378-4-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 76 ++++++++++++----------- drivers/gpu/drm/i915/gt/intel_breadcrumbs.h | 36 +++++++++++ drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h | 47 ++++++++++++++ drivers/gpu/drm/i915/gt/intel_engine.h | 17 ----- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 14 ++++- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 3 +- drivers/gpu/drm/i915/gt/intel_engine_types.h | 31 +-------- drivers/gpu/drm/i915/gt/intel_gt_irq.c | 1 + drivers/gpu/drm/i915/gt/intel_lrc.c | 11 +++- drivers/gpu/drm/i915/gt/intel_reset.c | 1 + drivers/gpu/drm/i915/gt/intel_ring_submission.c | 3 +- drivers/gpu/drm/i915/gt/intel_rps.c | 1 + drivers/gpu/drm/i915/gt/mock_engine.c | 10 ++- drivers/gpu/drm/i915/i915_irq.c | 1 + drivers/gpu/drm/i915/i915_request.c | 1 + drivers/gpu/drm/i915/i915_request.h | 4 -- 16 files changed, 162 insertions(+), 95 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/intel_breadcrumbs.h create mode 100644 drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index fbdc465a5870..2ffd47a86656 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -28,6 +28,7 @@ #include "i915_drv.h" #include "i915_trace.h" +#include "intel_breadcrumbs.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" @@ -55,30 +56,28 @@ static void irq_disable(struct intel_engine_cs *engine) static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - lockdep_assert_held(&b->irq_lock); + if (!b->irq_engine || !b->irq_armed) + return; + GEM_BUG_ON(!b->irq_enabled); if (!--b->irq_enabled) - irq_disable(engine); + irq_disable(b->irq_engine); WRITE_ONCE(b->irq_armed, false); - intel_gt_pm_put_async(engine->gt); + intel_gt_pm_put_async(b->irq_engine->gt); } -void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_park(struct intel_breadcrumbs *b) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; unsigned long flags; if (!READ_ONCE(b->irq_armed)) return; spin_lock_irqsave(&b->irq_lock, flags); - if (b->irq_armed) - __intel_breadcrumbs_disarm_irq(b); + __intel_breadcrumbs_disarm_irq(b); spin_unlock_irqrestore(&b->irq_lock, flags); } @@ -133,13 +132,8 @@ __dma_fence_signal__notify(struct dma_fence *fence, static void add_retire(struct intel_breadcrumbs *b, struct intel_timeline *tl) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - - if (unlikely(intel_engine_is_virtual(engine))) - engine = intel_virtual_engine_get_sibling(engine, 0); - - intel_engine_add_retire(engine, tl); + if (b->irq_engine) + intel_engine_add_retire(b->irq_engine, tl); } static bool __signal_request(struct i915_request *rq, struct list_head *signals) @@ -164,7 +158,7 @@ static void signal_irq_work(struct irq_work *work) spin_lock(&b->irq_lock); - if (b->irq_armed && list_empty(&b->signalers)) + if (list_empty(&b->signalers)) __intel_breadcrumbs_disarm_irq(b); list_splice_init(&b->signaled_requests, &signal); @@ -222,14 +216,12 @@ static void signal_irq_work(struct irq_work *work) static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) { - struct intel_engine_cs *engine = - container_of(b, struct intel_engine_cs, breadcrumbs); - lockdep_assert_held(&b->irq_lock); - if (b->irq_armed) + + if (!b->irq_engine || b->irq_armed) return; - if (!intel_gt_pm_get_if_awake(engine->gt)) + if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) return; /* @@ -249,37 +241,49 @@ static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) */ if (!b->irq_enabled++) - irq_enable(engine); + irq_enable(b->irq_engine); } -void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) +struct intel_breadcrumbs * +intel_breadcrumbs_create(struct intel_engine_cs *irq_engine) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct intel_breadcrumbs *b; + + b = kzalloc(sizeof(*b), GFP_KERNEL); + if (!b) + return NULL; spin_lock_init(&b->irq_lock); INIT_LIST_HEAD(&b->signalers); INIT_LIST_HEAD(&b->signaled_requests); init_irq_work(&b->irq_work, signal_irq_work); + + b->irq_engine = irq_engine; + + return b; } -void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_reset(struct intel_breadcrumbs *b) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; unsigned long flags; + if (!b->irq_engine) + return; + spin_lock_irqsave(&b->irq_lock, flags); if (b->irq_enabled) - irq_enable(engine); + irq_enable(b->irq_engine); else - irq_disable(engine); + irq_disable(b->irq_engine); spin_unlock_irqrestore(&b->irq_lock, flags); } -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) +void intel_breadcrumbs_free(struct intel_breadcrumbs *b) { + kfree(b); } static void insert_breadcrumb(struct i915_request *rq, @@ -369,11 +373,11 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) * request submit/unsubmit path, and so we must be more careful to * acquire the right lock. */ - b = &READ_ONCE(rq->engine)->breadcrumbs; + b = READ_ONCE(rq->engine)->breadcrumbs; spin_lock(&b->irq_lock); - while (unlikely(b != &READ_ONCE(rq->engine)->breadcrumbs)) { + while (unlikely(b != READ_ONCE(rq->engine)->breadcrumbs)) { spin_unlock(&b->irq_lock); - b = &READ_ONCE(rq->engine)->breadcrumbs; + b = READ_ONCE(rq->engine)->breadcrumbs; spin_lock(&b->irq_lock); } @@ -394,7 +398,7 @@ bool i915_request_enable_breadcrumb(struct i915_request *rq) void i915_request_cancel_breadcrumb(struct i915_request *rq) { - struct intel_breadcrumbs *b = &rq->engine->breadcrumbs; + struct intel_breadcrumbs *b = rq->engine->breadcrumbs; /* * We must wait for b->irq_lock so that we know the interrupt handler @@ -418,11 +422,11 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, struct drm_printer *p) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; + struct intel_breadcrumbs *b = engine->breadcrumbs; struct intel_context *ce; struct i915_request *rq; - if (list_empty(&b->signalers)) + if (!b || list_empty(&b->signalers)) return; drm_printf(p, "Signals:\n"); diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h new file mode 100644 index 000000000000..ed3d1deabfbd --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_BREADCRUMBS__ +#define __INTEL_BREADCRUMBS__ + +#include + +#include "intel_engine_types.h" + +struct drm_printer; +struct i915_request; +struct intel_breadcrumbs; + +struct intel_breadcrumbs * +intel_breadcrumbs_create(struct intel_engine_cs *irq_engine); +void intel_breadcrumbs_free(struct intel_breadcrumbs *b); + +void intel_breadcrumbs_reset(struct intel_breadcrumbs *b); +void intel_breadcrumbs_park(struct intel_breadcrumbs *b); + +static inline void +intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) +{ + irq_work_queue(&engine->breadcrumbs->irq_work); +} + +void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, + struct drm_printer *p); + +bool i915_request_enable_breadcrumb(struct i915_request *request); +void i915_request_cancel_breadcrumb(struct i915_request *request); + +#endif /* __INTEL_BREADCRUMBS__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h new file mode 100644 index 000000000000..8e53b9942695 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs_types.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2019 Intel Corporation + */ + +#ifndef __INTEL_BREADCRUMBS_TYPES__ +#define __INTEL_BREADCRUMBS_TYPES__ + +#include +#include +#include +#include + +/* + * Rather than have every client wait upon all user interrupts, + * with the herd waking after every interrupt and each doing the + * heavyweight seqno dance, we delegate the task (of being the + * bottom-half of the user interrupt) to the first client. After + * every interrupt, we wake up one client, who does the heavyweight + * coherent seqno read and either goes back to sleep (if incomplete), + * or wakes up all the completed clients in parallel, before then + * transferring the bottom-half status to the next client in the queue. + * + * Compared to walking the entire list of waiters in a single dedicated + * bottom-half, we reduce the latency of the first waiter by avoiding + * a context switch, but incur additional coherent seqno reads when + * following the chain of request breadcrumbs. Since it is most likely + * that we have a single client waiting on each seqno, then reducing + * the overhead of waking that client is much preferred. + */ +struct intel_breadcrumbs { + spinlock_t irq_lock; /* protects the lists used in hardirq context */ + + /* Not all breadcrumbs are attached to physical HW */ + struct intel_engine_cs *irq_engine; + + struct list_head signalers; + struct list_head signaled_requests; + + struct irq_work irq_work; /* for use from inside irq_lock */ + + unsigned int irq_enabled; + + bool irq_armed; +}; + +#endif /* __INTEL_BREADCRUMBS_TYPES__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index faf00a353e25..08e2c000dcc3 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -223,23 +223,6 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine, void intel_engine_init_execlists(struct intel_engine_cs *engine); -void intel_engine_init_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); - -void intel_engine_disarm_breadcrumbs(struct intel_engine_cs *engine); - -static inline void -intel_engine_signal_breadcrumbs(struct intel_engine_cs *engine) -{ - irq_work_queue(&engine->breadcrumbs.irq_work); -} - -void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); -void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); - -void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, - struct drm_printer *p); - static inline u32 *__gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) { memset(batch, 0, 6 * sizeof(u32)); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 86651bbef3a0..ea4ba2afe9f9 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -28,6 +28,7 @@ #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine.h" #include "intel_engine_pm.h" @@ -700,8 +701,13 @@ static int engine_setup_common(struct intel_engine_cs *engine) if (err) return err; + engine->breadcrumbs = intel_breadcrumbs_create(engine); + if (!engine->breadcrumbs) { + err = -ENOMEM; + goto err_status; + } + intel_engine_init_active(engine, ENGINE_PHYSICAL); - intel_engine_init_breadcrumbs(engine); intel_engine_init_execlists(engine); intel_engine_init_cmd_parser(engine); intel_engine_init__pm(engine); @@ -716,6 +722,10 @@ static int engine_setup_common(struct intel_engine_cs *engine) intel_engine_init_ctx_wa(engine); return 0; + +err_status: + cleanup_status_page(engine); + return err; } struct measure_breadcrumb { @@ -914,9 +924,9 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) tasklet_kill(&engine->execlists.tasklet); /* flush the callback */ cleanup_status_page(engine); + intel_breadcrumbs_free(engine->breadcrumbs); intel_engine_fini_retire(engine); - intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); if (engine->default_state) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index 8ec3eecf3e39..f7b2e07e2229 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -6,6 +6,7 @@ #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine.h" #include "intel_engine_heartbeat.h" @@ -247,7 +248,7 @@ static int __engine_park(struct intel_wakeref *wf) call_idle_barriers(engine); /* cleanup after wedging */ intel_engine_park_heartbeat(engine); - intel_engine_disarm_breadcrumbs(engine); + intel_breadcrumbs_park(engine->breadcrumbs); /* Must be reset upon idling, or we may miss the busy wakeup. */ GEM_BUG_ON(engine->execlists.queue_priority_hint != INT_MIN); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 8de92fd7d392..c400aaa2287b 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -22,6 +22,7 @@ #include "i915_pmu.h" #include "i915_priolist_types.h" #include "i915_selftest.h" +#include "intel_breadcrumbs_types.h" #include "intel_sseu.h" #include "intel_timeline_types.h" #include "intel_uncore.h" @@ -373,34 +374,8 @@ struct intel_engine_cs { */ struct ewma__engine_latency latency; - /* Rather than have every client wait upon all user interrupts, - * with the herd waking after every interrupt and each doing the - * heavyweight seqno dance, we delegate the task (of being the - * bottom-half of the user interrupt) to the first client. After - * every interrupt, we wake up one client, who does the heavyweight - * coherent seqno read and either goes back to sleep (if incomplete), - * or wakes up all the completed clients in parallel, before then - * transferring the bottom-half status to the next client in the queue. - * - * Compared to walking the entire list of waiters in a single dedicated - * bottom-half, we reduce the latency of the first waiter by avoiding - * a context switch, but incur additional coherent seqno reads when - * following the chain of request breadcrumbs. Since it is most likely - * that we have a single client waiting on each seqno, then reducing - * the overhead of waking that client is much preferred. - */ - struct intel_breadcrumbs { - spinlock_t irq_lock; - struct list_head signalers; - - struct list_head signaled_requests; - - struct irq_work irq_work; /* for use from inside irq_lock */ - - unsigned int irq_enabled; - - bool irq_armed; - } breadcrumbs; + /* Keep track of all the seqno used, a trail of breadcrumbs */ + struct intel_breadcrumbs *breadcrumbs; struct intel_engine_pmu { /** diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c index b05da68e52f4..257063a57101 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c @@ -8,6 +8,7 @@ #include "i915_drv.h" #include "i915_irq.h" +#include "intel_breadcrumbs.h" #include "intel_gt.h" #include "intel_gt_irq.h" #include "intel_uncore.h" diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index e5a37d14bce8..801ebe1326f3 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -137,6 +137,7 @@ #include "i915_perf.h" #include "i915_trace.h" #include "i915_vgpu.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_engine_pm.h" #include "intel_gt.h" @@ -4112,7 +4113,7 @@ static int execlists_resume(struct intel_engine_cs *engine) { intel_mocs_init_engine(engine); - intel_engine_reset_breadcrumbs(engine); + intel_breadcrumbs_reset(engine->breadcrumbs); if (GEM_SHOW_DEBUG() && unexpected_starting_state(engine)) { struct drm_printer p = drm_debug_printer(__func__); @@ -5714,9 +5715,7 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings, snprintf(ve->base.name, sizeof(ve->base.name), "virtual"); intel_engine_init_active(&ve->base, ENGINE_VIRTUAL); - intel_engine_init_breadcrumbs(&ve->base); intel_engine_init_execlists(&ve->base); - ve->base.breadcrumbs.irq_armed = true; /* fake HW, used for irq_work */ ve->base.cops = &virtual_context_ops; ve->base.request_alloc = execlists_request_alloc; @@ -5733,6 +5732,12 @@ intel_execlists_create_virtual(struct intel_engine_cs **siblings, intel_context_init(&ve->context, &ve->base); + ve->base.breadcrumbs = intel_breadcrumbs_create(NULL); + if (!ve->base.breadcrumbs) { + err = -ENOMEM; + goto err_put; + } + for (n = 0; n < count; n++) { struct intel_engine_cs *sibling = siblings[n]; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 46a5ceffc22f..ac36b67fb46b 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -15,6 +15,7 @@ #include "i915_drv.h" #include "i915_gpu_error.h" #include "i915_irq.h" +#include "intel_breadcrumbs.h" #include "intel_engine_pm.h" #include "intel_gt.h" #include "intel_gt_pm.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 87cef6d01141..84da20f6515c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -32,6 +32,7 @@ #include "gen6_ppgtt.h" #include "gen7_renderclear.h" #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_context.h" #include "intel_gt.h" #include "intel_reset.h" @@ -255,7 +256,7 @@ static int xcs_resume(struct intel_engine_cs *engine) else ring_setup_status_page(engine); - intel_engine_reset_breadcrumbs(engine); + intel_breadcrumbs_reset(engine->breadcrumbs); /* Enforce ordering by reading HEAD register back */ ENGINE_POSTING_READ(engine, RING_HEAD); diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 97ba14ad52e4..e6a00eea0631 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -7,6 +7,7 @@ #include #include "i915_drv.h" +#include "intel_breadcrumbs.h" #include "intel_gt.h" #include "intel_gt_clock_utils.h" #include "intel_gt_irq.h" diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 027de53cd05b..79764305b8ec 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -260,11 +260,12 @@ static void mock_engine_release(struct intel_engine_cs *engine) GEM_BUG_ON(timer_pending(&mock->hw_delay)); + intel_breadcrumbs_free(engine->breadcrumbs); + intel_context_unpin(engine->kernel_context); intel_context_put(engine->kernel_context); intel_engine_fini_retire(engine); - intel_engine_fini_breadcrumbs(engine); } struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, @@ -322,11 +323,14 @@ int mock_engine_init(struct intel_engine_cs *engine) struct intel_context *ce; intel_engine_init_active(engine, ENGINE_MOCK); - intel_engine_init_breadcrumbs(engine); intel_engine_init_execlists(engine); intel_engine_init__pm(engine); intel_engine_init_retire(engine); + engine->breadcrumbs = intel_breadcrumbs_create(NULL); + if (!engine->breadcrumbs) + return -ENOMEM; + ce = create_kernel_context(engine); if (IS_ERR(ce)) goto err_breadcrumbs; @@ -338,7 +342,7 @@ int mock_engine_init(struct intel_engine_cs *engine) return 0; err_breadcrumbs: - intel_engine_fini_breadcrumbs(engine); + intel_breadcrumbs_free(engine->breadcrumbs); return -ENOMEM; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 1fa67700d8f4..f113fe44572b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -41,6 +41,7 @@ #include "display/intel_lpe_audio.h" #include "display/intel_psr.h" +#include "gt/intel_breadcrumbs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_irq.h" #include "gt/intel_gt_pm_irq.h" diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index e9d5ce247ae9..fcb00b283b4f 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -31,6 +31,7 @@ #include #include "gem/i915_gem_context.h" +#include "gt/intel_breadcrumbs.h" #include "gt/intel_context.h" #include "gt/intel_ring.h" #include "gt/intel_rps.h" diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h index fc18378c685d..16b721080195 100644 --- a/drivers/gpu/drm/i915/i915_request.h +++ b/drivers/gpu/drm/i915/i915_request.h @@ -361,10 +361,6 @@ void i915_request_submit(struct i915_request *request); void __i915_request_unsubmit(struct i915_request *request); void i915_request_unsubmit(struct i915_request *request); -/* Note: part of the intel_breadcrumbs family */ -bool i915_request_enable_breadcrumb(struct i915_request *request); -void i915_request_cancel_breadcrumb(struct i915_request *request); - long i915_request_wait(struct i915_request *rq, unsigned int flags, long timeout) -- cgit v1.2.3 From cd0452aa2a0d146ff2c695877a4f5d3e4d09b435 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 17:42:17 +0100 Subject: drm/i915: Preallocate stashes for vma page-directories We need to make the DMA allocations used for page directories to be performed up front so that we can include those allocations in our memory reservation pass. The downside is that we have to assume the worst case, even before we know the final layout, and always allocate enough page directories for this object, even when there will be overlap. This unfortunately can be quite expensive, especially as we have to clear/reset the page directories and DMA pages, but it should only be required during early phases of a workload when new objects are being discovered, or after memory/eviction pressure when we need to rebind. Once we reach steady state, the objects should not be moved and we no longer need to preallocating the pages tables. It should be noted that the lifetime for the page directories DMA is more or less decoupled from individual fences as they will be shared across objects across timelines. v2: Only allocate enough PD space for the PTE we may use, we do not need to allocate PD that will be left as scratch. v3: Store the shift unto the first PD level to encapsulate the different PTE counts for gen6/gen8. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_client_blt.c | 11 ++-- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 40 +++++-------- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 78 +++++++----------------- drivers/gpu/drm/i915/gt/intel_ggtt.c | 60 +++++++++---------- drivers/gpu/drm/i915/gt/intel_gtt.h | 46 +++++++++----- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 83 ++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_vma.c | 27 +++++---- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 60 +++++++++++-------- drivers/gpu/drm/i915/selftests/mock_gtt.c | 22 +++---- 9 files changed, 237 insertions(+), 190 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index 278664f831e7..947c8aa8e13e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -32,12 +32,13 @@ static void vma_clear_pages(struct i915_vma *vma) vma->pages = NULL; } -static int vma_bind(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void vma_bind(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { - return vm->vma_ops.bind_vma(vm, vma, cache_level, flags); + vm->vma_ops.bind_vma(vm, stash, vma, cache_level, flags); } static void vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index cdc0b9c54305..4e6c1f7f48ef 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -177,16 +177,16 @@ static void gen6_flush_pd(struct gen6_ppgtt *ppgtt, u64 start, u64 end) mutex_unlock(&ppgtt->flush); } -static int gen6_alloc_va_range(struct i915_address_space *vm, - u64 start, u64 length) +static void gen6_alloc_va_range(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length) { struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_table *pt, *alloc = NULL; + struct i915_page_table *pt; bool flush = false; u64 from = start; unsigned int pde; - int ret = 0; spin_lock(&pd->lock); gen6_for_each_pde(pt, pd, start, length, pde) { @@ -195,21 +195,17 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, if (px_base(pt) == px_base(&vm->scratch[1])) { spin_unlock(&pd->lock); - pt = fetch_and_zero(&alloc); - if (!pt) - pt = alloc_pt(vm); - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto unwind_out; - } + pt = stash->pt[0]; + GEM_BUG_ON(!pt); fill32_px(pt, vm->scratch[0].encode); spin_lock(&pd->lock); if (pd->entry[pde] == &vm->scratch[1]) { + stash->pt[0] = pt->stash; + atomic_set(&pt->used, 0); pd->entry[pde] = pt; } else { - alloc = pt; pt = pd->entry[pde]; } @@ -226,15 +222,6 @@ static int gen6_alloc_va_range(struct i915_address_space *vm, with_intel_runtime_pm(&vm->i915->runtime_pm, wakeref) gen6_flush_pd(ppgtt, from, start); } - - goto out; - -unwind_out: - gen6_ppgtt_clear_range(vm, from, start - from); -out: - if (alloc) - free_px(vm, alloc); - return ret; } static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) @@ -302,10 +289,11 @@ static void pd_vma_clear_pages(struct i915_vma *vma) vma->pages = NULL; } -static int pd_vma_bind(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 unused) +static void pd_vma_bind(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 unused) { struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); struct gen6_ppgtt *ppgtt = vma->private; @@ -315,7 +303,6 @@ static int pd_vma_bind(struct i915_address_space *vm, ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total); - return 0; } static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) @@ -448,6 +435,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) mutex_init(&ppgtt->pin_mutex); ppgtt_init(&ppgtt->base, gt); + ppgtt->base.vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen6_pte_t)); ppgtt->base.vm.top = 1; ppgtt->base.vm.bind_async_flags = I915_VMA_LOCAL_BIND; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index 699125928272..08cb65bfb313 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -269,14 +269,12 @@ static void gen8_ppgtt_clear(struct i915_address_space *vm, start, start + length, vm->top); } -static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, - struct i915_page_directory * const pd, - u64 * const start, const u64 end, int lvl) +static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, + struct i915_vm_pt_stash *stash, + struct i915_page_directory * const pd, + u64 * const start, const u64 end, int lvl) { - const struct i915_page_scratch * const scratch = &vm->scratch[lvl]; - struct i915_page_table *alloc = NULL; unsigned int idx, len; - int ret = 0; GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT); @@ -297,49 +295,30 @@ static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, DBG("%s(%p):{ lvl:%d, idx:%d } allocating new tree\n", __func__, vm, lvl + 1, idx); - pt = fetch_and_zero(&alloc); - if (lvl) { - if (!pt) { - pt = &alloc_pd(vm)->pt; - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto out; - } - } + pt = stash->pt[!!lvl]; + GEM_BUG_ON(!pt); + if (lvl || + gen8_pt_count(*start, end) < I915_PDES || + intel_vgpu_active(vm->i915)) fill_px(pt, vm->scratch[lvl].encode); - } else { - if (!pt) { - pt = alloc_pt(vm); - if (IS_ERR(pt)) { - ret = PTR_ERR(pt); - goto out; - } - } - - if (intel_vgpu_active(vm->i915) || - gen8_pt_count(*start, end) < I915_PDES) - fill_px(pt, vm->scratch[lvl].encode); - } spin_lock(&pd->lock); - if (likely(!pd->entry[idx])) + if (likely(!pd->entry[idx])) { + stash->pt[!!lvl] = pt->stash; + atomic_set(&pt->used, 0); set_pd_entry(pd, idx, pt); - else - alloc = pt, pt = pd->entry[idx]; + } else { + pt = pd->entry[idx]; + } } if (lvl) { atomic_inc(&pt->used); spin_unlock(&pd->lock); - ret = __gen8_ppgtt_alloc(vm, as_pd(pt), - start, end, lvl); - if (unlikely(ret)) { - if (release_pd_entry(pd, idx, pt, scratch)) - free_px(vm, pt); - goto out; - } + __gen8_ppgtt_alloc(vm, stash, + as_pd(pt), start, end, lvl); spin_lock(&pd->lock); atomic_dec(&pt->used); @@ -359,18 +338,12 @@ static int __gen8_ppgtt_alloc(struct i915_address_space * const vm, } } while (idx++, --len); spin_unlock(&pd->lock); -out: - if (alloc) - free_px(vm, alloc); - return ret; } -static int gen8_ppgtt_alloc(struct i915_address_space *vm, - u64 start, u64 length) +static void gen8_ppgtt_alloc(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length) { - u64 from; - int err; - GEM_BUG_ON(!IS_ALIGNED(start, BIT_ULL(GEN8_PTE_SHIFT))); GEM_BUG_ON(!IS_ALIGNED(length, BIT_ULL(GEN8_PTE_SHIFT))); GEM_BUG_ON(range_overflows(start, length, vm->total)); @@ -378,15 +351,9 @@ static int gen8_ppgtt_alloc(struct i915_address_space *vm, start >>= GEN8_PTE_SHIFT; length >>= GEN8_PTE_SHIFT; GEM_BUG_ON(length == 0); - from = start; - - err = __gen8_ppgtt_alloc(vm, i915_vm_to_ppgtt(vm)->pd, - &start, start + length, vm->top); - if (unlikely(err && from != start)) - __gen8_ppgtt_clear(vm, i915_vm_to_ppgtt(vm)->pd, - from, start, vm->top); - return err; + __gen8_ppgtt_alloc(vm, stash, i915_vm_to_ppgtt(vm)->pd, + &start, start + length, vm->top); } static __always_inline void @@ -703,6 +670,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt) ppgtt_init(ppgtt, gt); ppgtt->vm.top = i915_vm_is_4lvl(&ppgtt->vm) ? 3 : 2; + ppgtt->vm.pd_shift = ilog2(SZ_4K * SZ_4K / sizeof(gen8_pte_t)); /* * From bdw, there is hw support for read-only pages in the PPGTT. diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 62979ea591f0..5a33056ab976 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -436,16 +436,17 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm, intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT); } -static int ggtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void ggtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { struct drm_i915_gem_object *obj = vma->obj; u32 pte_flags; if (i915_vma_is_bound(vma, ~flags & I915_VMA_BIND_MASK)) - return 0; + return; /* Applicable to VLV (gen8+ do not support RO in the GGTT) */ pte_flags = 0; @@ -454,8 +455,6 @@ static int ggtt_bind_vma(struct i915_address_space *vm, vm->insert_entries(vm, vma, cache_level, pte_flags); vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; - - return 0; } static void ggtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) @@ -568,31 +567,25 @@ err: return ret; } -static int aliasing_gtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void aliasing_gtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { u32 pte_flags; - int ret; /* Currently applicable only to VLV */ pte_flags = 0; if (i915_gem_object_is_readonly(vma->obj)) pte_flags |= PTE_READ_ONLY; - if (flags & I915_VMA_LOCAL_BIND) { - struct i915_ppgtt *alias = i915_vm_to_ggtt(vm)->alias; - - ret = ppgtt_bind_vma(&alias->vm, vma, cache_level, flags); - if (ret) - return ret; - } + if (flags & I915_VMA_LOCAL_BIND) + ppgtt_bind_vma(&i915_vm_to_ggtt(vm)->alias->vm, + stash, vma, cache_level, flags); if (flags & I915_VMA_GLOBAL_BIND) vm->insert_entries(vm, vma, cache_level, pte_flags); - - return 0; } static void aliasing_gtt_unbind_vma(struct i915_address_space *vm, @@ -607,6 +600,7 @@ static void aliasing_gtt_unbind_vma(struct i915_address_space *vm, static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) { + struct i915_vm_pt_stash stash = {}; struct i915_ppgtt *ppgtt; int err; @@ -619,15 +613,17 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) goto err_ppgtt; } + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, ggtt->vm.total); + if (err) + goto err_ppgtt; + /* * Note we only pre-allocate as far as the end of the global * GTT. On 48b / 4-level page-tables, the difference is very, * very significant! We have to preallocate as GVT/vgpu does * not like the page directory disappearing. */ - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, 0, ggtt->vm.total); - if (err) - goto err_ppgtt; + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, ggtt->vm.total); ggtt->alias = ppgtt; ggtt->vm.bind_async_flags |= ppgtt->vm.bind_async_flags; @@ -638,6 +634,7 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) GEM_BUG_ON(ggtt->vm.vma_ops.unbind_vma != ggtt_unbind_vma); ggtt->vm.vma_ops.unbind_vma = aliasing_gtt_unbind_vma; + i915_vm_free_pt_stash(&ppgtt->vm, &stash); return 0; err_ppgtt: @@ -1165,11 +1162,6 @@ void i915_ggtt_disable_guc(struct i915_ggtt *ggtt) ggtt->invalidate(ggtt); } -static unsigned int clear_bind(struct i915_vma *vma) -{ - return atomic_fetch_and(~I915_VMA_BIND_MASK, &vma->flags); -} - void i915_ggtt_resume(struct i915_ggtt *ggtt) { struct i915_vma *vma; @@ -1187,11 +1179,13 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt) /* clflush objects bound into the GGTT and rebind them. */ list_for_each_entry(vma, &ggtt->vm.bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; - unsigned int was_bound = clear_bind(vma); + unsigned int was_bound = + atomic_read(&vma->flags) & I915_VMA_BIND_MASK; - WARN_ON(i915_vma_bind(vma, - obj ? obj->cache_level : 0, - was_bound, NULL)); + GEM_BUG_ON(!was_bound); + vma->ops->bind_vma(&ggtt->vm, NULL, vma, + obj ? obj->cache_level : 0, + was_bound); if (obj) { /* only used during resume => exclusive access */ flush |= fetch_and_zero(&obj->write_domain); obj->read_domains |= I915_GEM_DOMAIN_GTT; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index f2b75078e05f..0d9f29aea6b4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -159,7 +159,10 @@ struct i915_page_scratch { struct i915_page_table { struct i915_page_dma base; - atomic_t used; + union { + atomic_t used; + struct i915_page_table *stash; + }; }; struct i915_page_directory { @@ -196,12 +199,18 @@ struct drm_i915_gem_object; struct i915_vma; struct intel_gt; +struct i915_vm_pt_stash { + /* preallocated chains of page tables/directories */ + struct i915_page_table *pt[2]; +}; + struct i915_vma_ops { /* Map an object into an address space with the given cache flags. */ - int (*bind_vma)(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); + void (*bind_vma)(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); /* * Unmap an object from an address space. This usually consists of * setting the valid PTE entries to a reserved scratch page. @@ -257,9 +266,6 @@ struct i915_address_space { #define VM_CLASS_PPGTT 1 struct i915_page_scratch scratch[4]; - unsigned int scratch_order; - unsigned int top; - /** * List of vma currently bound. */ @@ -276,13 +282,18 @@ struct i915_address_space { /* Some systems support read-only mappings for GGTT and/or PPGTT */ bool has_read_only:1; + u8 top; + u8 pd_shift; + u8 scratch_order; + u64 (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, u32 flags); /* Create a valid PTE */ #define PTE_READ_ONLY BIT(0) - int (*allocate_va_range)(struct i915_address_space *vm, - u64 start, u64 length); + void (*allocate_va_range)(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 start, u64 length); void (*clear_range)(struct i915_address_space *vm, u64 start, u64 length); void (*insert_page)(struct i915_address_space *vm, @@ -568,10 +579,11 @@ int ggtt_set_pages(struct i915_vma *vma); int ppgtt_set_pages(struct i915_vma *vma); void clear_pages(struct i915_vma *vma); -int ppgtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags); +void ppgtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags); void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma); @@ -579,6 +591,12 @@ void gtt_write_workarounds(struct intel_gt *gt); void setup_private_pat(struct intel_uncore *uncore); +int i915_vm_alloc_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 size); +void i915_vm_free_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash); + static inline struct sgt_dma { struct scatterlist *sg; dma_addr_t dma, max; diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index f0862e924d11..09056544bc29 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -155,19 +155,16 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt) return ppgtt; } -int ppgtt_bind_vma(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +void ppgtt_bind_vma(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { u32 pte_flags; - int err; if (!test_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma))) { - err = vm->allocate_va_range(vm, vma->node.start, vma->size); - if (err) - return err; - + vm->allocate_va_range(vm, stash, vma->node.start, vma->size); set_bit(I915_VMA_ALLOC_BIT, __i915_vma_flags(vma)); } @@ -178,8 +175,6 @@ int ppgtt_bind_vma(struct i915_address_space *vm, vm->insert_entries(vm, vma, cache_level, pte_flags); wmb(); - - return 0; } void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) @@ -188,12 +183,76 @@ void ppgtt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma) vm->clear_range(vm, vma->node.start, vma->size); } +static unsigned long pd_count(u64 size, int shift) +{ + /* Beware later misalignment */ + return (size + 2 * (BIT_ULL(shift) - 1)) >> shift; +} + +int i915_vm_alloc_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + u64 size) +{ + unsigned long count; + int shift, n; + + shift = vm->pd_shift; + if (!shift) + return 0; + + count = pd_count(size, shift); + while (count--) { + struct i915_page_table *pt; + + pt = alloc_pt(vm); + if (IS_ERR(pt)) { + i915_vm_free_pt_stash(vm, stash); + return PTR_ERR(pt); + } + + pt->stash = stash->pt[0]; + stash->pt[0] = pt; + } + + for (n = 1; n < vm->top; n++) { + shift += ilog2(I915_PDES); /* Each PD holds 512 entries */ + count = pd_count(size, shift); + while (count--) { + struct i915_page_directory *pd; + + pd = alloc_pd(vm); + if (IS_ERR(pd)) { + i915_vm_free_pt_stash(vm, stash); + return PTR_ERR(pd); + } + + pd->pt.stash = stash->pt[1]; + stash->pt[1] = &pd->pt; + } + } + + return 0; +} + +void i915_vm_free_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash) +{ + struct i915_page_table *pt; + int n; + + for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { + while ((pt = stash->pt[n])) { + stash->pt[n] = pt->stash; + free_px(vm, pt); + } + } +} + int ppgtt_set_pages(struct i915_vma *vma) { GEM_BUG_ON(vma->pages); vma->pages = vma->obj->mm.pages; - vma->page_sizes = vma->obj->mm.page_sizes; return 0; diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index cd12047c7791..a9e79b67035e 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -291,6 +291,8 @@ i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_vma_work { struct dma_fence_work base; + struct i915_address_space *vm; + struct i915_vm_pt_stash stash; struct i915_vma *vma; struct drm_i915_gem_object *pinned; struct i915_sw_dma_fence_cb cb; @@ -302,13 +304,10 @@ static int __vma_bind(struct dma_fence_work *work) { struct i915_vma_work *vw = container_of(work, typeof(*vw), base); struct i915_vma *vma = vw->vma; - int err; - - err = vma->ops->bind_vma(vma->vm, vma, vw->cache_level, vw->flags); - if (err) - atomic_or(I915_VMA_ERROR, &vma->flags); - return err; + vma->ops->bind_vma(vw->vm, &vw->stash, + vma, vw->cache_level, vw->flags); + return 0; } static void __vma_release(struct dma_fence_work *work) @@ -317,6 +316,9 @@ static void __vma_release(struct dma_fence_work *work) if (vw->pinned) __i915_gem_object_unpin_pages(vw->pinned); + + i915_vm_free_pt_stash(vw->vm, &vw->stash); + i915_vm_put(vw->vm); } static const struct dma_fence_work_ops bind_ops = { @@ -376,7 +378,6 @@ int i915_vma_bind(struct i915_vma *vma, { u32 bind_flags; u32 vma_flags; - int ret; GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(vma->size > vma->node.size); @@ -433,9 +434,7 @@ int i915_vma_bind(struct i915_vma *vma, work->pinned = vma->obj; } } else { - ret = vma->ops->bind_vma(vma->vm, vma, cache_level, bind_flags); - if (ret) - return ret; + vma->ops->bind_vma(vma->vm, NULL, vma, cache_level, bind_flags); } atomic_or(bind_flags, &vma->flags); @@ -879,6 +878,14 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) err = -ENOMEM; goto err_pages; } + + work->vm = i915_vm_get(vma->vm); + + /* Allocate enough page directories to used PTE */ + if (vma->vm->allocate_va_range) + i915_vm_alloc_pt_stash(vma->vm, + &work->stash, + vma->size); } if (flags & PIN_GLOBAL) diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 0016ffc7d914..9b8fc990e9ef 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -172,35 +172,33 @@ static int igt_ppgtt_alloc(void *arg) /* Check we can allocate the entire range */ for (size = 4096; size <= limit; size <<= 2) { - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, 0, size); - if (err) { - if (err == -ENOMEM) { - pr_info("[1] Ran out of memory for va_range [0 + %llx] [bit %d]\n", - size, ilog2(size)); - err = 0; /* virtual space too large! */ - } + struct i915_vm_pt_stash stash = {}; + + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, size); + if (err) goto err_ppgtt_cleanup; - } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, size); cond_resched(); ppgtt->vm.clear_range(&ppgtt->vm, 0, size); + + i915_vm_free_pt_stash(&ppgtt->vm, &stash); } /* Check we can incrementally allocate the entire range */ for (last = 0, size = 4096; size <= limit; last = size, size <<= 2) { - err = ppgtt->vm.allocate_va_range(&ppgtt->vm, - last, size - last); - if (err) { - if (err == -ENOMEM) { - pr_info("[2] Ran out of memory for va_range [%llx + %llx] [bit %d]\n", - last, size - last, ilog2(size)); - err = 0; /* virtual space too large! */ - } + struct i915_vm_pt_stash stash = {}; + + err = i915_vm_alloc_pt_stash(&ppgtt->vm, &stash, size - last); + if (err) goto err_ppgtt_cleanup; - } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, + last, size - last); cond_resched(); + + i915_vm_free_pt_stash(&ppgtt->vm, &stash); } err_ppgtt_cleanup: @@ -284,9 +282,18 @@ static int lowlevel_hole(struct i915_address_space *vm, break; } - if (vm->allocate_va_range && - vm->allocate_va_range(vm, addr, BIT_ULL(size))) - break; + if (vm->allocate_va_range) { + struct i915_vm_pt_stash stash = {}; + + if (i915_vm_alloc_pt_stash(vm, &stash, + BIT_ULL(size))) + break; + + vm->allocate_va_range(vm, &stash, + addr, BIT_ULL(size)); + + i915_vm_free_pt_stash(vm, &stash); + } mock_vma->pages = obj->mm.pages; mock_vma->node.size = BIT_ULL(size); @@ -1881,6 +1888,7 @@ static int igt_cs_tlb(void *arg) continue; while (!__igt_timeout(end_time, NULL)) { + struct i915_vm_pt_stash stash = {}; struct i915_request *rq; u64 offset; @@ -1888,10 +1896,6 @@ static int igt_cs_tlb(void *arg) 0, vm->total - PAGE_SIZE, chunk_size, PAGE_SIZE); - err = vm->allocate_va_range(vm, offset, chunk_size); - if (err) - goto end; - memset32(result, STACK_MAGIC, PAGE_SIZE / sizeof(u32)); vma = i915_vma_instance(bbe, vm, NULL); @@ -1904,6 +1908,14 @@ static int igt_cs_tlb(void *arg) if (err) goto end; + err = i915_vm_alloc_pt_stash(vm, &stash, chunk_size); + if (err) + goto end; + + vm->allocate_va_range(vm, &stash, offset, chunk_size); + + i915_vm_free_pt_stash(vm, &stash); + /* Prime the TLB with the dummy pages */ for (i = 0; i < count; i++) { vma->node.start = offset + i * PAGE_SIZE; diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index b173086411ef..5e4fb0fba34b 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -38,14 +38,14 @@ static void mock_insert_entries(struct i915_address_space *vm, { } -static int mock_bind_ppgtt(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void mock_bind_ppgtt(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { GEM_BUG_ON(flags & I915_VMA_GLOBAL_BIND); set_bit(I915_VMA_LOCAL_BIND_BIT, __i915_vma_flags(vma)); - return 0; } static void mock_unbind_ppgtt(struct i915_address_space *vm, @@ -74,6 +74,7 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) ppgtt->vm.i915 = i915; ppgtt->vm.total = round_down(U64_MAX, PAGE_SIZE); ppgtt->vm.file = ERR_PTR(-ENODEV); + ppgtt->vm.dma = &i915->drm.pdev->dev; i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT); @@ -90,13 +91,12 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) return ppgtt; } -static int mock_bind_ggtt(struct i915_address_space *vm, - struct i915_vma *vma, - enum i915_cache_level cache_level, - u32 flags) +static void mock_bind_ggtt(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash, + struct i915_vma *vma, + enum i915_cache_level cache_level, + u32 flags) { - atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags); - return 0; } static void mock_unbind_ggtt(struct i915_address_space *vm, -- cgit v1.2.3 From 89351925a477441ae5fdd0136aec80b49ea1c53c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 17:42:18 +0100 Subject: drm/i915/gt: Switch to object allocations for page directories The GEM object is grossly overweight for the practicality of tracking large numbers of individual pages, yet it is currently our only abstraction for tracking DMA allocations. Since those allocations need to be reserved upfront before an operation, and that we need to break away from simple system memory, we need to ditch using plain struct page wrappers. In the process, we drop the WC mapping as we ended up clflushing everything anyway due to various issues across a wider range of platforms. Though in a future step, we need to drop the kmap_atomic approach which suggests we need to pre-map all the pages and keep them mapped. v2: Verify our large scratch page is suitably DMA aligned; and manually clear the scratch since we are allocating plain struct pages full of prior content. Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 1 + drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 53 ++-- drivers/gpu/drm/i915/gt/gen6_ppgtt.h | 1 + drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 89 +++--- drivers/gpu/drm/i915/gt/intel_ggtt.c | 37 +-- drivers/gpu/drm/i915/gt/intel_gtt.c | 300 ++++----------------- drivers/gpu/drm/i915/gt/intel_gtt.h | 94 +++---- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 42 ++- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 16 +- drivers/gpu/drm/i915/gvt/scheduler.c | 17 +- drivers/gpu/drm/i915/i915_drv.c | 1 + drivers/gpu/drm/i915/i915_drv.h | 5 - drivers/gpu/drm/i915/i915_vma.c | 18 +- drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 23 ++ drivers/gpu/drm/i915/selftests/i915_perf.c | 4 +- drivers/gpu/drm/i915/selftests/mock_gtt.c | 4 + 18 files changed, 289 insertions(+), 420 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 5335f799b548..d0847d7896f9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -282,6 +282,7 @@ struct drm_i915_gem_object { } userptr; unsigned long scratch; + u64 encode; void *gvt_info; }; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 8291ede6902c..e2f3d014acb2 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -393,7 +393,7 @@ static int igt_mock_exhaust_device_supported_pages(void *arg) */ for (i = 1; i < BIT(ARRAY_SIZE(page_sizes)); i++) { - unsigned int combination = 0; + unsigned int combination = SZ_4K; /* Required for ppGTT */ for (j = 0; j < ARRAY_SIZE(page_sizes); j++) { if (i & BIT(j)) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 7ffc3c751432..d176b015353f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1748,7 +1748,7 @@ static int check_scratch_page(struct i915_gem_context *ctx, u32 *out) if (!vm) return -ENODEV; - page = vm->scratch[0].base.page; + page = __px_page(vm->scratch[0]); if (!page) { pr_err("No scratch page!\n"); return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index 4e6c1f7f48ef..fb702e1de739 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -16,8 +16,10 @@ static inline void gen6_write_pde(const struct gen6_ppgtt *ppgtt, const unsigned int pde, const struct i915_page_table *pt) { + dma_addr_t addr = pt ? px_dma(pt) : px_dma(ppgtt->base.vm.scratch[1]); + /* Caller needs to make sure the write completes if necessary */ - iowrite32(GEN6_PDE_ADDR_ENCODE(px_dma(pt)) | GEN6_PDE_VALID, + iowrite32(GEN6_PDE_ADDR_ENCODE(addr) | GEN6_PDE_VALID, ppgtt->pd_addr + pde); } @@ -79,7 +81,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, { struct gen6_ppgtt * const ppgtt = to_gen6_ppgtt(i915_vm_to_ppgtt(vm)); const unsigned int first_entry = start / I915_GTT_PAGE_SIZE; - const gen6_pte_t scratch_pte = vm->scratch[0].encode; + const gen6_pte_t scratch_pte = vm->scratch[0]->encode; unsigned int pde = first_entry / GEN6_PTES; unsigned int pte = first_entry % GEN6_PTES; unsigned int num_entries = length / I915_GTT_PAGE_SIZE; @@ -90,8 +92,6 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, const unsigned int count = min(num_entries, GEN6_PTES - pte); gen6_pte_t *vaddr; - GEM_BUG_ON(px_base(pt) == px_base(&vm->scratch[1])); - num_entries -= count; GEM_BUG_ON(count > atomic_read(&pt->used)); @@ -127,7 +127,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, struct sgt_dma iter = sgt_dma(vma); gen6_pte_t *vaddr; - GEM_BUG_ON(pd->entry[act_pt] == &vm->scratch[1]); + GEM_BUG_ON(!pd->entry[act_pt]); vaddr = kmap_atomic_px(i915_pt_entry(pd, act_pt)); do { @@ -192,16 +192,17 @@ static void gen6_alloc_va_range(struct i915_address_space *vm, gen6_for_each_pde(pt, pd, start, length, pde) { const unsigned int count = gen6_pte_count(start, length); - if (px_base(pt) == px_base(&vm->scratch[1])) { + if (!pt) { spin_unlock(&pd->lock); pt = stash->pt[0]; - GEM_BUG_ON(!pt); + __i915_gem_object_pin_pages(pt->base); + i915_gem_object_make_unshrinkable(pt->base); - fill32_px(pt, vm->scratch[0].encode); + fill32_px(pt, vm->scratch[0]->encode); spin_lock(&pd->lock); - if (pd->entry[pde] == &vm->scratch[1]) { + if (!pd->entry[pde]) { stash->pt[0] = pt->stash; atomic_set(&pt->used, 0); pd->entry[pde] = pt; @@ -227,24 +228,27 @@ static void gen6_alloc_va_range(struct i915_address_space *vm, static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) { struct i915_address_space * const vm = &ppgtt->base.vm; - struct i915_page_directory * const pd = ppgtt->base.pd; int ret; - ret = setup_scratch_page(vm, __GFP_HIGHMEM); + ret = setup_scratch_page(vm); if (ret) return ret; - vm->scratch[0].encode = - vm->pte_encode(px_dma(&vm->scratch[0]), + vm->scratch[0]->encode = + vm->pte_encode(px_dma(vm->scratch[0]), I915_CACHE_NONE, PTE_READ_ONLY); - if (unlikely(setup_page_dma(vm, px_base(&vm->scratch[1])))) { - cleanup_scratch_page(vm); - return -ENOMEM; + vm->scratch[1] = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(vm->scratch[1])) + return PTR_ERR(vm->scratch[1]); + + ret = pin_pt_dma(vm, vm->scratch[1]); + if (ret) { + i915_gem_object_put(vm->scratch[1]); + return ret; } - fill32_px(&vm->scratch[1], vm->scratch[0].encode); - memset_p(pd->entry, &vm->scratch[1], I915_PDES); + fill32_px(vm->scratch[1], vm->scratch[0]->encode); return 0; } @@ -252,13 +256,11 @@ static int gen6_ppgtt_init_scratch(struct gen6_ppgtt *ppgtt) static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt) { struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_dma * const scratch = - px_base(&ppgtt->base.vm.scratch[1]); struct i915_page_table *pt; u32 pde; gen6_for_all_pdes(pt, pd, pde) - if (px_base(pt) != scratch) + if (pt) free_px(&ppgtt->base.vm, pt); } @@ -299,7 +301,7 @@ static void pd_vma_bind(struct i915_address_space *vm, struct gen6_ppgtt *ppgtt = vma->private; u32 ggtt_offset = i915_ggtt_offset(vma) / I915_GTT_PAGE_SIZE; - px_base(ppgtt->base.pd)->ggtt_offset = ggtt_offset * sizeof(gen6_pte_t); + ppgtt->pp_dir = ggtt_offset * sizeof(gen6_pte_t) << 10; ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm + ggtt_offset; gen6_flush_pd(ppgtt, 0, ppgtt->base.vm.total); @@ -309,8 +311,6 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) { struct gen6_ppgtt *ppgtt = vma->private; struct i915_page_directory * const pd = ppgtt->base.pd; - struct i915_page_dma * const scratch = - px_base(&ppgtt->base.vm.scratch[1]); struct i915_page_table *pt; unsigned int pde; @@ -319,11 +319,11 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) /* Free all no longer used page tables */ gen6_for_all_pdes(pt, ppgtt->base.pd, pde) { - if (px_base(pt) == scratch || atomic_read(&pt->used)) + if (!pt || atomic_read(&pt->used)) continue; free_px(&ppgtt->base.vm, pt); - pd->entry[pde] = scratch; + pd->entry[pde] = NULL; } ppgtt->scan_for_unused_pt = false; @@ -444,6 +444,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) ppgtt->base.vm.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.vm.cleanup = gen6_ppgtt_cleanup; + ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma; ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode; ppgtt->base.pd = __alloc_pd(sizeof(*ppgtt->base.pd)); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h index 72e481806c96..7249672e5802 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h @@ -14,6 +14,7 @@ struct gen6_ppgtt { struct mutex flush; struct i915_vma *vma; gen6_pte_t __iomem *pd_addr; + u32 pp_dir; atomic_t pin_count; struct mutex pin_mutex; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index 08cb65bfb313..a40cb7ea8c66 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -199,7 +199,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, struct i915_page_directory * const pd, u64 start, const u64 end, int lvl) { - const struct i915_page_scratch * const scratch = &vm->scratch[lvl]; + const struct drm_i915_gem_object * const scratch = vm->scratch[lvl]; unsigned int idx, len; GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT); @@ -239,7 +239,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, vaddr = kmap_atomic_px(pt); memset64(vaddr + gen8_pd_index(start, 0), - vm->scratch[0].encode, + vm->scratch[0]->encode, count); kunmap_atomic(vaddr); @@ -296,12 +296,13 @@ static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, __func__, vm, lvl + 1, idx); pt = stash->pt[!!lvl]; - GEM_BUG_ON(!pt); + __i915_gem_object_pin_pages(pt->base); + i915_gem_object_make_unshrinkable(pt->base); if (lvl || gen8_pt_count(*start, end) < I915_PDES || intel_vgpu_active(vm->i915)) - fill_px(pt, vm->scratch[lvl].encode); + fill_px(pt, vm->scratch[lvl]->encode); spin_lock(&pd->lock); if (likely(!pd->entry[idx])) { @@ -356,16 +357,6 @@ static void gen8_ppgtt_alloc(struct i915_address_space *vm, &start, start + length, vm->top); } -static __always_inline void -write_pte(gen8_pte_t *pte, const gen8_pte_t val) -{ - /* Magic delays? Or can we refine these to flush all in one pass? */ - *pte = val; - wmb(); /* cpu to cache */ - clflush(pte); /* cache to memory */ - wmb(); /* visible to all */ -} - static __always_inline u64 gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, struct i915_page_directory *pdp, @@ -382,8 +373,7 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1))); do { GEM_BUG_ON(iter->sg->length < I915_GTT_PAGE_SIZE); - write_pte(&vaddr[gen8_pd_index(idx, 0)], - pte_encode | iter->dma); + vaddr[gen8_pd_index(idx, 0)] = pte_encode | iter->dma; iter->dma += I915_GTT_PAGE_SIZE; if (iter->dma >= iter->max) { @@ -406,10 +396,12 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, pd = pdp->entry[gen8_pd_index(idx, 2)]; } + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); vaddr = kmap_atomic_px(i915_pt_entry(pd, gen8_pd_index(idx, 1))); } } while (1); + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); return idx; @@ -465,7 +457,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, do { GEM_BUG_ON(iter->sg->length < page_size); - write_pte(&vaddr[index++], encode | iter->dma); + vaddr[index++] = encode | iter->dma; start += page_size; iter->dma += page_size; @@ -490,6 +482,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, } } while (rem >= page_size && index < I915_PDES); + clflush_cache_range(vaddr, PAGE_SIZE); kunmap_atomic(vaddr); /* @@ -521,7 +514,7 @@ static void gen8_ppgtt_insert_huge(struct i915_vma *vma, if (I915_SELFTEST_ONLY(vma->vm->scrub_64K)) { u16 i; - encode = vma->vm->scratch[0].encode; + encode = vma->vm->scratch[0]->encode; vaddr = kmap_atomic_px(i915_pt_entry(pd, maybe_64K)); for (i = 1; i < index; i += 16) @@ -575,27 +568,37 @@ static int gen8_init_scratch(struct i915_address_space *vm) GEM_BUG_ON(!clone->has_read_only); vm->scratch_order = clone->scratch_order; - memcpy(vm->scratch, clone->scratch, sizeof(vm->scratch)); - px_dma(&vm->scratch[0]) = 0; /* no xfer of ownership */ + for (i = 0; i <= vm->top; i++) + vm->scratch[i] = i915_gem_object_get(clone->scratch[i]); + return 0; } - ret = setup_scratch_page(vm, __GFP_HIGHMEM); + ret = setup_scratch_page(vm); if (ret) return ret; - vm->scratch[0].encode = - gen8_pte_encode(px_dma(&vm->scratch[0]), + vm->scratch[0]->encode = + gen8_pte_encode(px_dma(vm->scratch[0]), I915_CACHE_LLC, vm->has_read_only); for (i = 1; i <= vm->top; i++) { - if (unlikely(setup_page_dma(vm, px_base(&vm->scratch[i])))) + struct drm_i915_gem_object *obj; + + obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(obj)) goto free_scratch; - fill_px(&vm->scratch[i], vm->scratch[i - 1].encode); - vm->scratch[i].encode = - gen8_pde_encode(px_dma(&vm->scratch[i]), - I915_CACHE_LLC); + ret = pin_pt_dma(vm, obj); + if (ret) { + i915_gem_object_put(obj); + goto free_scratch; + } + + fill_px(obj, vm->scratch[i - 1]->encode); + obj->encode = gen8_pde_encode(px_dma(obj), I915_CACHE_LLC); + + vm->scratch[i] = obj; } return 0; @@ -616,12 +619,20 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt) for (idx = 0; idx < GEN8_3LVL_PDPES; idx++) { struct i915_page_directory *pde; + int err; pde = alloc_pd(vm); if (IS_ERR(pde)) return PTR_ERR(pde); - fill_px(pde, vm->scratch[1].encode); + err = pin_pt_dma(vm, pde->pt.base); + if (err) { + i915_gem_object_put(pde->pt.base); + kfree(pde); + return err; + } + + fill_px(pde, vm->scratch[1]->encode); set_pd_entry(pd, idx, pde); atomic_inc(px_used(pde)); /* keep pinned */ } @@ -635,6 +646,7 @@ gen8_alloc_top_pd(struct i915_address_space *vm) { const unsigned int count = gen8_pd_top_count(vm); struct i915_page_directory *pd; + int err; GEM_BUG_ON(count > ARRAY_SIZE(pd->entry)); @@ -642,12 +654,20 @@ gen8_alloc_top_pd(struct i915_address_space *vm) if (unlikely(!pd)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, px_base(pd)))) { + pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pd->pt.base)) { kfree(pd); return ERR_PTR(-ENOMEM); } - fill_page_dma(px_base(pd), vm->scratch[vm->top].encode, count); + err = pin_pt_dma(vm, pd->pt.base); + if (err) { + i915_gem_object_put(pd->pt.base); + kfree(pd); + return ERR_PTR(err); + } + + fill_page_dma(px_base(pd), vm->scratch[vm->top]->encode, count); atomic_inc(px_used(pd)); /* mark as pinned */ return pd; } @@ -682,12 +702,7 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt) */ ppgtt->vm.has_read_only = !IS_GEN_RANGE(gt->i915, 11, 12); - /* - * There are only few exceptions for gen >=6. chv and bxt. - * And we are not sure about the latter so play safe for now. - */ - if (IS_CHERRYVIEW(gt->i915) || IS_BROXTON(gt->i915)) - ppgtt->vm.pt_kmap_wc = true; + ppgtt->vm.alloc_pt_dma = alloc_pt_dma; err = gen8_init_scratch(&ppgtt->vm); if (err) diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 5a33056ab976..33a3f627ddb1 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -78,8 +78,6 @@ int i915_ggtt_init_hw(struct drm_i915_private *i915) { int ret; - stash_init(&i915->mm.wc_stash); - /* * Note that we use page colouring to enforce a guard page at the * end of the address space. This is required as the CS may prefetch @@ -232,7 +230,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, /* Fill the allocated but "unused" space beyond the end of the buffer */ while (gte < end) - gen8_set_pte(gte++, vm->scratch[0].encode); + gen8_set_pte(gte++, vm->scratch[0]->encode); /* * We want to flush the TLBs only after we're certain all the PTE @@ -283,7 +281,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, /* Fill the allocated but "unused" space beyond the end of the buffer */ while (gte < end) - iowrite32(vm->scratch[0].encode, gte++); + iowrite32(vm->scratch[0]->encode, gte++); /* * We want to flush the TLBs only after we're certain all the PTE @@ -303,7 +301,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); unsigned int first_entry = start / I915_GTT_PAGE_SIZE; unsigned int num_entries = length / I915_GTT_PAGE_SIZE; - const gen8_pte_t scratch_pte = vm->scratch[0].encode; + const gen8_pte_t scratch_pte = vm->scratch[0]->encode; gen8_pte_t __iomem *gtt_base = (gen8_pte_t __iomem *)ggtt->gsm + first_entry; const int max_entries = ggtt_total_entries(ggtt) - first_entry; @@ -401,7 +399,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->scratch[0].encode; + scratch_pte = vm->scratch[0]->encode; for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); } @@ -617,6 +615,10 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) if (err) goto err_ppgtt; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) + goto err_stash; + /* * Note we only pre-allocate as far as the end of the global * GTT. On 48b / 4-level page-tables, the difference is very, @@ -637,6 +639,8 @@ static int init_aliasing_ppgtt(struct i915_ggtt *ggtt) i915_vm_free_pt_stash(&ppgtt->vm, &stash); return 0; +err_stash: + i915_vm_free_pt_stash(&ppgtt->vm, &stash); err_ppgtt: i915_vm_put(&ppgtt->vm); return err; @@ -712,18 +716,11 @@ static void ggtt_cleanup_hw(struct i915_ggtt *ggtt) void i915_ggtt_driver_release(struct drm_i915_private *i915) { struct i915_ggtt *ggtt = &i915->ggtt; - struct pagevec *pvec; fini_aliasing_ppgtt(ggtt); intel_ggtt_fini_fences(ggtt); ggtt_cleanup_hw(ggtt); - - pvec = &i915->mm.wc_stash.pvec; - if (pvec->nr) { - set_pages_array_wb(pvec->pages, pvec->nr); - __pagevec_release(pvec); - } } static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl) @@ -786,7 +783,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return -ENOMEM; } - ret = setup_scratch_page(&ggtt->vm, GFP_DMA32); + ret = setup_scratch_page(&ggtt->vm); if (ret) { drm_err(&i915->drm, "Scratch setup failed\n"); /* iounmap will also get called at remove, but meh */ @@ -794,8 +791,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return ret; } - ggtt->vm.scratch[0].encode = - ggtt->vm.pte_encode(px_dma(&ggtt->vm.scratch[0]), + ggtt->vm.scratch[0]->encode = + ggtt->vm.pte_encode(px_dma(ggtt->vm.scratch[0]), I915_CACHE_NONE, 0); return 0; @@ -821,7 +818,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm) struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); iounmap(ggtt->gsm); - cleanup_scratch_page(vm); + free_scratch(vm); } static struct resource pci_resource(struct pci_dev *pdev, int bar) @@ -849,6 +846,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) else size = gen8_get_total_gtt_size(snb_gmch_ctl); + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE; ggtt->vm.cleanup = gen6_gmch_remove; ggtt->vm.insert_page = gen8_ggtt_insert_page; @@ -997,6 +996,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) size = gen6_get_total_gtt_size(snb_gmch_ctl); ggtt->vm.total = (size / sizeof(gen6_pte_t)) * I915_GTT_PAGE_SIZE; + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.clear_range = nop_clear_range; if (!HAS_FULL_PPGTT(i915) || intel_scanout_needs_vtd_wa(i915)) ggtt->vm.clear_range = gen6_ggtt_clear_range; @@ -1047,6 +1048,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt) ggtt->gmadr = (struct resource)DEFINE_RES_MEM(gmadr_base, ggtt->mappable_end); + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->do_idle_maps = needs_idle_maps(i915); ggtt->vm.insert_page = i915_ggtt_insert_page; ggtt->vm.insert_entries = i915_ggtt_insert_entries; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 2a72cce63fd9..3f1114b58b01 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -11,160 +11,24 @@ #include "intel_gt.h" #include "intel_gtt.h" -void stash_init(struct pagestash *stash) +struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz) { - pagevec_init(&stash->pvec); - spin_lock_init(&stash->lock); -} - -static struct page *stash_pop_page(struct pagestash *stash) -{ - struct page *page = NULL; - - spin_lock(&stash->lock); - if (likely(stash->pvec.nr)) - page = stash->pvec.pages[--stash->pvec.nr]; - spin_unlock(&stash->lock); - - return page; -} - -static void stash_push_pagevec(struct pagestash *stash, struct pagevec *pvec) -{ - unsigned int nr; - - spin_lock_nested(&stash->lock, SINGLE_DEPTH_NESTING); - - nr = min_t(typeof(nr), pvec->nr, pagevec_space(&stash->pvec)); - memcpy(stash->pvec.pages + stash->pvec.nr, - pvec->pages + pvec->nr - nr, - sizeof(pvec->pages[0]) * nr); - stash->pvec.nr += nr; - - spin_unlock(&stash->lock); - - pvec->nr -= nr; -} - -static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) -{ - struct pagevec stack; - struct page *page; - if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1))) i915_gem_shrink_all(vm->i915); - page = stash_pop_page(&vm->free_pages); - if (page) - return page; - - if (!vm->pt_kmap_wc) - return alloc_page(gfp); - - /* Look in our global stash of WC pages... */ - page = stash_pop_page(&vm->i915->mm.wc_stash); - if (page) - return page; - - /* - * Otherwise batch allocate pages to amortize cost of set_pages_wc. - * - * We have to be careful as page allocation may trigger the shrinker - * (via direct reclaim) which will fill up the WC stash underneath us. - * So we add our WB pages into a temporary pvec on the stack and merge - * them into the WC stash after all the allocations are complete. - */ - pagevec_init(&stack); - do { - struct page *page; - - page = alloc_page(gfp); - if (unlikely(!page)) - break; - - stack.pages[stack.nr++] = page; - } while (pagevec_space(&stack)); - - if (stack.nr && !set_pages_array_wc(stack.pages, stack.nr)) { - page = stack.pages[--stack.nr]; - - /* Merge spare WC pages to the global stash */ - if (stack.nr) - stash_push_pagevec(&vm->i915->mm.wc_stash, &stack); - - /* Push any surplus WC pages onto the local VM stash */ - if (stack.nr) - stash_push_pagevec(&vm->free_pages, &stack); - } - - /* Return unwanted leftovers */ - if (unlikely(stack.nr)) { - WARN_ON_ONCE(set_pages_array_wb(stack.pages, stack.nr)); - __pagevec_release(&stack); - } - - return page; + return i915_gem_object_create_internal(vm->i915, sz); } -static void vm_free_pages_release(struct i915_address_space *vm, - bool immediate) +int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj) { - struct pagevec *pvec = &vm->free_pages.pvec; - struct pagevec stack; - - lockdep_assert_held(&vm->free_pages.lock); - GEM_BUG_ON(!pagevec_count(pvec)); - - if (vm->pt_kmap_wc) { - /* - * When we use WC, first fill up the global stash and then - * only if full immediately free the overflow. - */ - stash_push_pagevec(&vm->i915->mm.wc_stash, pvec); - - /* - * As we have made some room in the VM's free_pages, - * we can wait for it to fill again. Unless we are - * inside i915_address_space_fini() and must - * immediately release the pages! - */ - if (pvec->nr <= (immediate ? 0 : PAGEVEC_SIZE - 1)) - return; + int err; - /* - * We have to drop the lock to allow ourselves to sleep, - * so take a copy of the pvec and clear the stash for - * others to use it as we sleep. - */ - stack = *pvec; - pagevec_reinit(pvec); - spin_unlock(&vm->free_pages.lock); - - pvec = &stack; - set_pages_array_wb(pvec->pages, pvec->nr); - - spin_lock(&vm->free_pages.lock); - } + err = i915_gem_object_pin_pages(obj); + if (err) + return err; - __pagevec_release(pvec); -} - -static void vm_free_page(struct i915_address_space *vm, struct page *page) -{ - /* - * On !llc, we need to change the pages back to WB. We only do so - * in bulk, so we rarely need to change the page attributes here, - * but doing so requires a stop_machine() from deep inside arch/x86/mm. - * To make detection of the possible sleep more likely, use an - * unconditional might_sleep() for everybody. - */ - might_sleep(); - spin_lock(&vm->free_pages.lock); - while (!pagevec_space(&vm->free_pages.pvec)) - vm_free_pages_release(vm, false); - GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec) >= PAGEVEC_SIZE); - pagevec_add(&vm->free_pages.pvec, page); - spin_unlock(&vm->free_pages.lock); + i915_gem_object_make_unshrinkable(obj); + return 0; } void __i915_vm_close(struct i915_address_space *vm) @@ -194,14 +58,7 @@ void __i915_vm_close(struct i915_address_space *vm) void i915_address_space_fini(struct i915_address_space *vm) { - spin_lock(&vm->free_pages.lock); - if (pagevec_count(&vm->free_pages.pvec)) - vm_free_pages_release(vm, true); - GEM_BUG_ON(pagevec_count(&vm->free_pages.pvec)); - spin_unlock(&vm->free_pages.lock); - drm_mm_takedown(&vm->mm); - mutex_destroy(&vm->mutex); } @@ -246,8 +103,6 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass) drm_mm_init(&vm->mm, 0, vm->total); vm->mm.head_node.color = I915_COLOR_UNEVICTABLE; - stash_init(&vm->free_pages); - INIT_LIST_HEAD(&vm->bound_list); } @@ -264,64 +119,50 @@ void clear_pages(struct i915_vma *vma) memset(&vma->page_sizes, 0, sizeof(vma->page_sizes)); } -static int __setup_page_dma(struct i915_address_space *vm, - struct i915_page_dma *p, - gfp_t gfp) -{ - p->page = vm_alloc_page(vm, gfp | I915_GFP_ALLOW_FAIL); - if (unlikely(!p->page)) - return -ENOMEM; - - p->daddr = dma_map_page_attrs(vm->dma, - p->page, 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC | - DMA_ATTR_NO_WARN); - if (unlikely(dma_mapping_error(vm->dma, p->daddr))) { - vm_free_page(vm, p->page); - return -ENOMEM; - } - - return 0; -} - -int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p) +dma_addr_t __px_dma(struct drm_i915_gem_object *p) { - return __setup_page_dma(vm, p, __GFP_HIGHMEM); + GEM_BUG_ON(!i915_gem_object_has_pages(p)); + return sg_dma_address(p->mm.pages->sgl); } -void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p) +struct page *__px_page(struct drm_i915_gem_object *p) { - dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - vm_free_page(vm, p->page); + GEM_BUG_ON(!i915_gem_object_has_pages(p)); + return sg_page(p->mm.pages->sgl); } void -fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count) +fill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count) { - kunmap_atomic(memset64(kmap_atomic(p->page), val, count)); + struct page *page = __px_page(p); + void *vaddr; + + vaddr = kmap(page); + memset64(vaddr, val, count); + clflush_cache_range(vaddr, PAGE_SIZE); + kunmap(page); } -static void poison_scratch_page(struct page *page, unsigned long size) +static void poison_scratch_page(struct drm_i915_gem_object *scratch) { - if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) - return; + struct sgt_iter sgt; + struct page *page; + u8 val; - GEM_BUG_ON(!IS_ALIGNED(size, PAGE_SIZE)); + val = 0; + if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) + val = POISON_FREE; - do { + for_each_sgt_page(page, sgt, scratch->mm.pages) { void *vaddr; vaddr = kmap(page); - memset(vaddr, POISON_FREE, PAGE_SIZE); + memset(vaddr, val, PAGE_SIZE); kunmap(page); - - page = pfn_to_page(page_to_pfn(page) + 1); - size -= PAGE_SIZE; - } while (size); + } } -int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) +int setup_scratch_page(struct i915_address_space *vm) { unsigned long size; @@ -338,21 +179,27 @@ int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) */ size = I915_GTT_PAGE_SIZE_4K; if (i915_vm_is_4lvl(vm) && - HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) { + HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) size = I915_GTT_PAGE_SIZE_64K; - gfp |= __GFP_NOWARN; - } - gfp |= __GFP_ZERO | __GFP_RETRY_MAYFAIL; do { - unsigned int order = get_order(size); - struct page *page; - dma_addr_t addr; + struct drm_i915_gem_object *obj; - page = alloc_pages(gfp, order); - if (unlikely(!page)) + obj = vm->alloc_pt_dma(vm, size); + if (IS_ERR(obj)) goto skip; + if (pin_pt_dma(vm, obj)) + goto skip_obj; + + /* We need a single contiguous page for our scratch */ + if (obj->mm.page_sizes.sg < size) + goto skip_obj; + + /* And it needs to be correspondingly aligned */ + if (__px_dma(obj) & (size - 1)) + goto skip_obj; + /* * Use a non-zero scratch page for debugging. * @@ -362,61 +209,28 @@ int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) * should it ever be accidentally used, the effect should be * fairly benign. */ - poison_scratch_page(page, size); - - addr = dma_map_page_attrs(vm->dma, - page, 0, size, - PCI_DMA_BIDIRECTIONAL, - DMA_ATTR_SKIP_CPU_SYNC | - DMA_ATTR_NO_WARN); - if (unlikely(dma_mapping_error(vm->dma, addr))) - goto free_page; - - if (unlikely(!IS_ALIGNED(addr, size))) - goto unmap_page; - - vm->scratch[0].base.page = page; - vm->scratch[0].base.daddr = addr; - vm->scratch_order = order; + poison_scratch_page(obj); + + vm->scratch[0] = obj; + vm->scratch_order = get_order(size); return 0; -unmap_page: - dma_unmap_page(vm->dma, addr, size, PCI_DMA_BIDIRECTIONAL); -free_page: - __free_pages(page, order); +skip_obj: + i915_gem_object_put(obj); skip: if (size == I915_GTT_PAGE_SIZE_4K) return -ENOMEM; size = I915_GTT_PAGE_SIZE_4K; - gfp &= ~__GFP_NOWARN; } while (1); } -void cleanup_scratch_page(struct i915_address_space *vm) -{ - struct i915_page_dma *p = px_base(&vm->scratch[0]); - unsigned int order = vm->scratch_order; - - dma_unmap_page(vm->dma, p->daddr, BIT(order) << PAGE_SHIFT, - PCI_DMA_BIDIRECTIONAL); - __free_pages(p->page, order); -} - void free_scratch(struct i915_address_space *vm) { int i; - if (!px_dma(&vm->scratch[0])) /* set to 0 on clones */ - return; - - for (i = 1; i <= vm->top; i++) { - if (!px_dma(&vm->scratch[i])) - break; - cleanup_page_dma(vm, px_base(&vm->scratch[i])); - } - - cleanup_scratch_page(vm); + for (i = 0; i <= vm->top; i++) + i915_gem_object_put(vm->scratch[i]); } void gtt_write_workarounds(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 0d9f29aea6b4..6abab2d37b6f 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -134,31 +134,19 @@ typedef u64 gen8_pte_t; #define GEN8_PDE_IPS_64K BIT(11) #define GEN8_PDE_PS_2M BIT(7) +enum i915_cache_level; + +struct drm_i915_file_private; +struct drm_i915_gem_object; struct i915_fence_reg; +struct i915_vma; +struct intel_gt; #define for_each_sgt_daddr(__dp, __iter, __sgt) \ __for_each_sgt_daddr(__dp, __iter, __sgt, I915_GTT_PAGE_SIZE) -struct i915_page_dma { - struct page *page; - union { - dma_addr_t daddr; - - /* - * For gen6/gen7 only. This is the offset in the GGTT - * where the page directory entries for PPGTT begin - */ - u32 ggtt_offset; - }; -}; - -struct i915_page_scratch { - struct i915_page_dma base; - u64 encode; -}; - struct i915_page_table { - struct i915_page_dma base; + struct drm_i915_gem_object *base; union { atomic_t used; struct i915_page_table *stash; @@ -179,12 +167,14 @@ struct i915_page_directory { other) #define px_base(px) \ - __px_choose_expr(px, struct i915_page_dma *, __x, \ - __px_choose_expr(px, struct i915_page_scratch *, &__x->base, \ - __px_choose_expr(px, struct i915_page_table *, &__x->base, \ - __px_choose_expr(px, struct i915_page_directory *, &__x->pt.base, \ - (void)0)))) -#define px_dma(px) (px_base(px)->daddr) + __px_choose_expr(px, struct drm_i915_gem_object *, __x, \ + __px_choose_expr(px, struct i915_page_table *, __x->base, \ + __px_choose_expr(px, struct i915_page_directory *, __x->pt.base, \ + (void)0))) + +struct page *__px_page(struct drm_i915_gem_object *p); +dma_addr_t __px_dma(struct drm_i915_gem_object *p); +#define px_dma(px) (__px_dma(px_base(px))) #define px_pt(px) \ __px_choose_expr(px, struct i915_page_table *, __x, \ @@ -192,13 +182,6 @@ struct i915_page_directory { (void)0)) #define px_used(px) (&px_pt(px)->used) -enum i915_cache_level; - -struct drm_i915_file_private; -struct drm_i915_gem_object; -struct i915_vma; -struct intel_gt; - struct i915_vm_pt_stash { /* preallocated chains of page tables/directories */ struct i915_page_table *pt[2]; @@ -222,13 +205,6 @@ struct i915_vma_ops { void (*clear_pages)(struct i915_vma *vma); }; -struct pagestash { - spinlock_t lock; - struct pagevec pvec; -}; - -void stash_init(struct pagestash *stash); - struct i915_address_space { struct kref ref; struct rcu_work rcu; @@ -265,20 +241,15 @@ struct i915_address_space { #define VM_CLASS_GGTT 0 #define VM_CLASS_PPGTT 1 - struct i915_page_scratch scratch[4]; + struct drm_i915_gem_object *scratch[4]; /** * List of vma currently bound. */ struct list_head bound_list; - struct pagestash free_pages; - /* Global GTT */ bool is_ggtt:1; - /* Some systems require uncached updates of the page directories */ - bool pt_kmap_wc:1; - /* Some systems support read-only mappings for GGTT and/or PPGTT */ bool has_read_only:1; @@ -286,6 +257,9 @@ struct i915_address_space { u8 pd_shift; u8 scratch_order; + struct drm_i915_gem_object * + (*alloc_pt_dma)(struct i915_address_space *vm, int sz); + u64 (*pte_encode)(dma_addr_t addr, enum i915_cache_level level, u32 flags); /* Create a valid PTE */ @@ -501,9 +475,9 @@ i915_pd_entry(const struct i915_page_directory * const pdp, static inline dma_addr_t i915_page_dir_dma_addr(const struct i915_ppgtt *ppgtt, const unsigned int n) { - struct i915_page_dma *pt = ppgtt->pd->entry[n]; + struct i915_page_table *pt = ppgtt->pd->entry[n]; - return px_dma(pt ?: px_base(&ppgtt->vm.scratch[ppgtt->vm.top])); + return __px_dma(pt ? px_base(pt) : ppgtt->vm.scratch[ppgtt->vm.top]); } void ppgtt_init(struct i915_ppgtt *ppgtt, struct intel_gt *gt); @@ -528,13 +502,10 @@ struct i915_ppgtt *i915_ppgtt_create(struct intel_gt *gt); void i915_ggtt_suspend(struct i915_ggtt *gtt); void i915_ggtt_resume(struct i915_ggtt *ggtt); -int setup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p); -void cleanup_page_dma(struct i915_address_space *vm, struct i915_page_dma *p); - -#define kmap_atomic_px(px) kmap_atomic(px_base(px)->page) +#define kmap_atomic_px(px) kmap_atomic(__px_page(px_base(px))) void -fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count); +fill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count); #define fill_px(px, v) fill_page_dma(px_base(px), (v), PAGE_SIZE / sizeof(u64)) #define fill32_px(px, v) do { \ @@ -542,37 +513,38 @@ fill_page_dma(const struct i915_page_dma *p, const u64 val, unsigned int count); fill_px((px), v__ << 32 | v__); \ } while (0) -int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp); -void cleanup_scratch_page(struct i915_address_space *vm); +int setup_scratch_page(struct i915_address_space *vm); void free_scratch(struct i915_address_space *vm); +struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz); struct i915_page_table *alloc_pt(struct i915_address_space *vm); struct i915_page_directory *alloc_pd(struct i915_address_space *vm); struct i915_page_directory *__alloc_pd(size_t sz); -void free_pd(struct i915_address_space *vm, struct i915_page_dma *pd); +int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj); -#define free_px(vm, px) free_pd(vm, px_base(px)) +void free_pt(struct i915_address_space *vm, struct i915_page_table *pt); +#define free_px(vm, px) free_pt(vm, px_pt(px)) void __set_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - struct i915_page_dma * const to, + struct i915_page_table *pt, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)); #define set_pd_entry(pd, idx, to) \ - __set_pd_entry((pd), (idx), px_base(to), gen8_pde_encode) + __set_pd_entry((pd), (idx), px_pt(to), gen8_pde_encode) void clear_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - const struct i915_page_scratch * const scratch); + const struct drm_i915_gem_object * const scratch); bool release_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, struct i915_page_table * const pt, - const struct i915_page_scratch * const scratch); + const struct drm_i915_gem_object * const scratch); void gen6_ggtt_invalidate(struct i915_ggtt *ggtt); int ggtt_set_pages(struct i915_vma *vma); @@ -594,6 +566,8 @@ void setup_private_pat(struct intel_uncore *uncore); int i915_vm_alloc_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash, u64 size); +int i915_vm_pin_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash); void i915_vm_free_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash); diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index 09056544bc29..ede6369a9092 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -18,7 +18,8 @@ struct i915_page_table *alloc_pt(struct i915_address_space *vm) if (unlikely(!pt)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, &pt->base))) { + pt->base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pt->base)) { kfree(pt); return ERR_PTR(-ENOMEM); } @@ -47,7 +48,8 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) if (unlikely(!pd)) return ERR_PTR(-ENOMEM); - if (unlikely(setup_page_dma(vm, px_base(pd)))) { + pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); + if (IS_ERR(pd->pt.base)) { kfree(pd); return ERR_PTR(-ENOMEM); } @@ -55,27 +57,28 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) return pd; } -void free_pd(struct i915_address_space *vm, struct i915_page_dma *pd) +void free_pt(struct i915_address_space *vm, struct i915_page_table *pt) { - cleanup_page_dma(vm, pd); - kfree(pd); + i915_gem_object_put(pt->base); + kfree(pt); } static inline void -write_dma_entry(struct i915_page_dma * const pdma, +write_dma_entry(struct drm_i915_gem_object * const pdma, const unsigned short idx, const u64 encoded_entry) { - u64 * const vaddr = kmap_atomic(pdma->page); + u64 * const vaddr = kmap_atomic(__px_page(pdma)); vaddr[idx] = encoded_entry; + clflush_cache_range(&vaddr[idx], sizeof(u64)); kunmap_atomic(vaddr); } void __set_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - struct i915_page_dma * const to, + struct i915_page_table * const to, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) { /* Each thread pre-pins the pd, and we may have a thread per pde. */ @@ -83,13 +86,13 @@ __set_pd_entry(struct i915_page_directory * const pd, atomic_inc(px_used(pd)); pd->entry[idx] = to; - write_dma_entry(px_base(pd), idx, encode(to->daddr, I915_CACHE_LLC)); + write_dma_entry(px_base(pd), idx, encode(px_dma(to), I915_CACHE_LLC)); } void clear_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, - const struct i915_page_scratch * const scratch) + const struct drm_i915_gem_object * const scratch) { GEM_BUG_ON(atomic_read(px_used(pd)) == 0); @@ -102,7 +105,7 @@ bool release_pd_entry(struct i915_page_directory * const pd, const unsigned short idx, struct i915_page_table * const pt, - const struct i915_page_scratch * const scratch) + const struct drm_i915_gem_object * const scratch) { bool free = false; @@ -234,6 +237,23 @@ int i915_vm_alloc_pt_stash(struct i915_address_space *vm, return 0; } +int i915_vm_pin_pt_stash(struct i915_address_space *vm, + struct i915_vm_pt_stash *stash) +{ + struct i915_page_table *pt; + int n, err; + + for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { + for (pt = stash->pt[n]; pt; pt = pt->stash) { + err = pin_pt_dma(vm, pt->base); + if (err) + return err; + } + } + + return 0; +} + void i915_vm_free_pt_stash(struct i915_address_space *vm, struct i915_vm_pt_stash *stash) { diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 84da20f6515c..a3b10f3c83eb 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -202,16 +202,18 @@ static struct i915_address_space *vm_alias(struct i915_address_space *vm) return vm; } +static u32 pp_dir(struct i915_address_space *vm) +{ + return to_gen6_ppgtt(i915_vm_to_ppgtt(vm))->pp_dir; +} + static void set_pp_dir(struct intel_engine_cs *engine) { struct i915_address_space *vm = vm_alias(engine->gt->vm); if (vm) { - struct i915_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); - ENGINE_WRITE(engine, RING_PP_DIR_DCLV, PP_DIR_DCLV_2G); - ENGINE_WRITE(engine, RING_PP_DIR_BASE, - px_base(ppgtt->pd)->ggtt_offset << 10); + ENGINE_WRITE(engine, RING_PP_DIR_BASE, pp_dir(vm)); } } @@ -609,7 +611,7 @@ static const struct intel_context_ops ring_context_ops = { }; static int load_pd_dir(struct i915_request *rq, - const struct i915_ppgtt *ppgtt, + struct i915_address_space *vm, u32 valid) { const struct intel_engine_cs * const engine = rq->engine; @@ -625,7 +627,7 @@ static int load_pd_dir(struct i915_request *rq, *cs++ = MI_LOAD_REGISTER_IMM(1); *cs++ = i915_mmio_reg_offset(RING_PP_DIR_BASE(engine->mmio_base)); - *cs++ = px_base(ppgtt->pd)->ggtt_offset << 10; + *cs++ = pp_dir(vm); /* Stall until the page table load is complete? */ *cs++ = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT; @@ -827,7 +829,7 @@ static int switch_mm(struct i915_request *rq, struct i915_address_space *vm) * post-sync op, this extra pass appears vital before a * mm switch! */ - ret = load_pd_dir(rq, i915_vm_to_ppgtt(vm), PP_DIR_DCLV_2G); + ret = load_pd_dir(rq, vm, PP_DIR_DCLV_2G); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 3c3b9842bbbd..1570eb8aa978 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -403,6 +403,14 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) wa_ctx->indirect_ctx.shadow_va = NULL; } +static void set_dma_address(struct i915_page_directory *pd, dma_addr_t addr) +{ + struct scatterlist *sg = pd->pt.base->mm.pages->sgl; + + /* This is not a good idea */ + sg->dma_address = addr; +} + static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, struct intel_context *ce) { @@ -411,7 +419,7 @@ static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, int i = 0; if (mm->ppgtt_mm.root_entry_type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) { - px_dma(ppgtt->pd) = mm->ppgtt_mm.shadow_pdps[0]; + set_dma_address(ppgtt->pd, mm->ppgtt_mm.shadow_pdps[0]); } else { for (i = 0; i < GVT_RING_CTX_NR_PDPS; i++) { struct i915_page_directory * const pd = @@ -421,7 +429,8 @@ static void set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload, shadow ppgtt. */ if (!pd) break; - px_dma(pd) = mm->ppgtt_mm.shadow_pdps[i]; + + set_dma_address(pd, mm->ppgtt_mm.shadow_pdps[i]); } } } @@ -1240,13 +1249,13 @@ i915_context_ppgtt_root_restore(struct intel_vgpu_submission *s, int i; if (i915_vm_is_4lvl(&ppgtt->vm)) { - px_dma(ppgtt->pd) = s->i915_context_pml4; + set_dma_address(ppgtt->pd, s->i915_context_pml4); } else { for (i = 0; i < GEN8_3LVL_PDPES; i++) { struct i915_page_directory * const pd = i915_pd_entry(ppgtt->pd, i); - px_dma(pd) = s->i915_context_pdps[i]; + set_dma_address(pd, s->i915_context_pdps[i]); } } } diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d8aaa882560b..00292a849c34 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1075,6 +1075,7 @@ static void i915_driver_release(struct drm_device *dev) intel_memory_regions_driver_release(dev_priv); i915_ggtt_driver_release(dev_priv); + i915_gem_drain_freed_objects(dev_priv); i915_driver_mmio_release(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0fb83a780b21..2b95467b760a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -587,11 +587,6 @@ struct i915_gem_mm { */ atomic_t free_count; - /** - * Small stash of WC pages - */ - struct pagestash wc_stash; - /** * tmpfs instance used for shmem backed objects */ diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index a9e79b67035e..c6bf04ca2032 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -872,24 +872,30 @@ int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) if (err) return err; + if (flags & PIN_GLOBAL) + wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm); + if (flags & vma->vm->bind_async_flags) { work = i915_vma_work(); if (!work) { err = -ENOMEM; - goto err_pages; + goto err_rpm; } work->vm = i915_vm_get(vma->vm); /* Allocate enough page directories to used PTE */ - if (vma->vm->allocate_va_range) + if (vma->vm->allocate_va_range) { i915_vm_alloc_pt_stash(vma->vm, &work->stash, vma->size); - } - if (flags & PIN_GLOBAL) - wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm); + err = i915_vm_pin_pt_stash(vma->vm, + &work->stash); + if (err) + goto err_fence; + } + } /* * Differentiate between user/kernel vma inside the aliasing-ppgtt. @@ -978,9 +984,9 @@ err_unlock: err_fence: if (work) dma_fence_work_commit_imm(&work->base); +err_rpm: if (wakeref) intel_runtime_pm_put(&vma->vm->i915->runtime_pm, wakeref); -err_pages: vma_put_pages(vma); return err; } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 9b8fc990e9ef..af8205a2bd8f 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -178,6 +178,12 @@ static int igt_ppgtt_alloc(void *arg) if (err) goto err_ppgtt_cleanup; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) { + i915_vm_free_pt_stash(&ppgtt->vm, &stash); + goto err_ppgtt_cleanup; + } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, 0, size); cond_resched(); @@ -194,6 +200,12 @@ static int igt_ppgtt_alloc(void *arg) if (err) goto err_ppgtt_cleanup; + err = i915_vm_pin_pt_stash(&ppgtt->vm, &stash); + if (err) { + i915_vm_free_pt_stash(&ppgtt->vm, &stash); + goto err_ppgtt_cleanup; + } + ppgtt->vm.allocate_va_range(&ppgtt->vm, &stash, last, size - last); cond_resched(); @@ -289,6 +301,11 @@ static int lowlevel_hole(struct i915_address_space *vm, BIT_ULL(size))) break; + if (i915_vm_pin_pt_stash(vm, &stash)) { + i915_vm_free_pt_stash(vm, &stash); + break; + } + vm->allocate_va_range(vm, &stash, addr, BIT_ULL(size)); @@ -1912,6 +1929,12 @@ static int igt_cs_tlb(void *arg) if (err) goto end; + err = i915_vm_pin_pt_stash(vm, &stash); + if (err) { + i915_vm_free_pt_stash(vm, &stash); + goto end; + } + vm->allocate_va_range(vm, &stash, offset, chunk_size); i915_vm_free_pt_stash(vm, &stash); diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c index c2d001d9c0ec..debbac660519 100644 --- a/drivers/gpu/drm/i915/selftests/i915_perf.c +++ b/drivers/gpu/drm/i915/selftests/i915_perf.c @@ -307,7 +307,7 @@ static int live_noa_gpr(void *arg) } /* Poison the ce->vm so we detect writes not to the GGTT gt->scratch */ - scratch = kmap(ce->vm->scratch[0].base.page); + scratch = kmap(__px_page(ce->vm->scratch[0])); memset(scratch, POISON_FREE, PAGE_SIZE); rq = intel_context_create_request(ce); @@ -405,7 +405,7 @@ static int live_noa_gpr(void *arg) out_rq: i915_request_put(rq); out_ce: - kunmap(ce->vm->scratch[0].base.page); + kunmap(__px_page(ce->vm->scratch[0])); intel_context_put(ce); out: stream_destroy(stream); diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index 5e4fb0fba34b..7270fc8ca801 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -78,6 +78,8 @@ struct i915_ppgtt *mock_ppgtt(struct drm_i915_private *i915, const char *name) i915_address_space_init(&ppgtt->vm, VM_CLASS_PPGTT); + ppgtt->vm.alloc_pt_dma = alloc_pt_dma; + ppgtt->vm.clear_range = mock_clear_range; ppgtt->vm.insert_page = mock_insert_page; ppgtt->vm.insert_entries = mock_insert_entries; @@ -116,6 +118,8 @@ void mock_init_ggtt(struct drm_i915_private *i915, struct i915_ggtt *ggtt) ggtt->mappable_end = resource_size(&ggtt->gmadr); ggtt->vm.total = 4096 * PAGE_SIZE; + ggtt->vm.alloc_pt_dma = alloc_pt_dma; + ggtt->vm.clear_range = mock_clear_range; ggtt->vm.insert_page = mock_insert_page; ggtt->vm.insert_entries = mock_insert_entries; -- cgit v1.2.3 From 82adf901138cc0564656dc8dc3a47862a546cb2a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 29 Jul 2020 17:42:19 +0100 Subject: drm/i915/gt: Shrink i915_page_directory's slab bucket kmalloc uses power-of-two slab buckets for small allocations (up to a few pages). Since i915_page_directory is a page of pointers, plus a couple more, this is rounded up to 8K, and we waste nearly 50% of that allocation. Long terms this leads to poor memory utilisation, bloating the kernel footprint, but the problem is exacerbated by our conservative preallocation scheme for binding VMA. As we are required to allocate all levels for each vma just in case we need to insert them upon binding, this leads to a large multiplication factor for a single page vma. By halving the allocation we need for the page directory structure, we halve the impact of that factor, bringing workloads that once fitted into memory, hopefully back to fitting into memory. We maintain the split between i915_page_directory and i915_page_table as we only need half the allocation for the lowest, most populous, level. Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200729164219.5737-3-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 11 ++++++----- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 26 ++++++++++++++------------ drivers/gpu/drm/i915/gt/intel_gtt.h | 10 ++++++---- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 31 ++++++++++++++++++++++++------- 4 files changed, 50 insertions(+), 28 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index fb702e1de739..7e5a86b774a7 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -261,7 +261,7 @@ static void gen6_ppgtt_free_pd(struct gen6_ppgtt *ppgtt) gen6_for_all_pdes(pt, pd, pde) if (pt) - free_px(&ppgtt->base.vm, pt); + free_pt(&ppgtt->base.vm, pt); } static void gen6_ppgtt_cleanup(struct i915_address_space *vm) @@ -275,7 +275,8 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm) mutex_destroy(&ppgtt->flush); mutex_destroy(&ppgtt->pin_mutex); - kfree(ppgtt->base.pd); + + free_pd(&ppgtt->base.vm, ppgtt->base.pd); } static int pd_vma_set_pages(struct i915_vma *vma) @@ -322,7 +323,7 @@ static void pd_vma_unbind(struct i915_address_space *vm, struct i915_vma *vma) if (!pt || atomic_read(&pt->used)) continue; - free_px(&ppgtt->base.vm, pt); + free_pt(&ppgtt->base.vm, pt); pd->entry[pde] = NULL; } @@ -447,7 +448,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) ppgtt->base.vm.alloc_pt_dma = alloc_pt_dma; ppgtt->base.vm.pte_encode = ggtt->vm.pte_encode; - ppgtt->base.pd = __alloc_pd(sizeof(*ppgtt->base.pd)); + ppgtt->base.pd = __alloc_pd(I915_PDES); if (!ppgtt->base.pd) { err = -ENOMEM; goto err_free; @@ -468,7 +469,7 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt) err_scratch: free_scratch(&ppgtt->base.vm); err_pd: - kfree(ppgtt->base.pd); + free_pd(&ppgtt->base.vm, ppgtt->base.pd); err_free: mutex_destroy(&ppgtt->pin_mutex); kfree(ppgtt); diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index a40cb7ea8c66..eb64f474a78c 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -181,7 +181,7 @@ static void __gen8_ppgtt_cleanup(struct i915_address_space *vm, } while (pde++, --count); } - free_px(vm, pd); + free_px(vm, &pd->pt, lvl); } static void gen8_ppgtt_cleanup(struct i915_address_space *vm) @@ -248,7 +248,7 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, } if (release_pd_entry(pd, idx, pt, scratch)) - free_px(vm, pt); + free_px(vm, pt, lvl); } while (idx++, --len); return start; @@ -628,7 +628,7 @@ static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt) err = pin_pt_dma(vm, pde->pt.base); if (err) { i915_gem_object_put(pde->pt.base); - kfree(pde); + free_pd(vm, pde); return err; } @@ -648,28 +648,30 @@ gen8_alloc_top_pd(struct i915_address_space *vm) struct i915_page_directory *pd; int err; - GEM_BUG_ON(count > ARRAY_SIZE(pd->entry)); + GEM_BUG_ON(count > I915_PDES); - pd = __alloc_pd(offsetof(typeof(*pd), entry[count])); + pd = __alloc_pd(count); if (unlikely(!pd)) return ERR_PTR(-ENOMEM); pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); if (IS_ERR(pd->pt.base)) { - kfree(pd); - return ERR_PTR(-ENOMEM); + err = PTR_ERR(pd->pt.base); + pd->pt.base = NULL; + goto err_pd; } err = pin_pt_dma(vm, pd->pt.base); - if (err) { - i915_gem_object_put(pd->pt.base); - kfree(pd); - return ERR_PTR(err); - } + if (err) + goto err_pd; fill_page_dma(px_base(pd), vm->scratch[vm->top]->encode, count); atomic_inc(px_used(pd)); /* mark as pinned */ return pd; + +err_pd: + free_pd(vm, pd); + return ERR_PTR(err); } /* diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 6abab2d37b6f..c13c650ced22 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -156,7 +156,7 @@ struct i915_page_table { struct i915_page_directory { struct i915_page_table pt; spinlock_t lock; - void *entry[512]; + void **entry; }; #define __px_choose_expr(x, type, expr, other) \ @@ -519,12 +519,14 @@ void free_scratch(struct i915_address_space *vm); struct drm_i915_gem_object *alloc_pt_dma(struct i915_address_space *vm, int sz); struct i915_page_table *alloc_pt(struct i915_address_space *vm); struct i915_page_directory *alloc_pd(struct i915_address_space *vm); -struct i915_page_directory *__alloc_pd(size_t sz); +struct i915_page_directory *__alloc_pd(int npde); int pin_pt_dma(struct i915_address_space *vm, struct drm_i915_gem_object *obj); -void free_pt(struct i915_address_space *vm, struct i915_page_table *pt); -#define free_px(vm, px) free_pt(vm, px_pt(px)) +void free_px(struct i915_address_space *vm, + struct i915_page_table *pt, int lvl); +#define free_pt(vm, px) free_px(vm, px, 0) +#define free_pd(vm, px) free_px(vm, px_pt(px), 1) void __set_pd_entry(struct i915_page_directory * const pd, diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index ede6369a9092..46d9aceda64c 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -28,14 +28,20 @@ struct i915_page_table *alloc_pt(struct i915_address_space *vm) return pt; } -struct i915_page_directory *__alloc_pd(size_t sz) +struct i915_page_directory *__alloc_pd(int count) { struct i915_page_directory *pd; - pd = kzalloc(sz, I915_GFP_ALLOW_FAIL); + pd = kzalloc(sizeof(*pd), I915_GFP_ALLOW_FAIL); if (unlikely(!pd)) return NULL; + pd->entry = kcalloc(count, sizeof(*pd->entry), I915_GFP_ALLOW_FAIL); + if (unlikely(!pd->entry)) { + kfree(pd); + return NULL; + } + spin_lock_init(&pd->lock); return pd; } @@ -44,12 +50,13 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) { struct i915_page_directory *pd; - pd = __alloc_pd(sizeof(*pd)); + pd = __alloc_pd(I915_PDES); if (unlikely(!pd)) return ERR_PTR(-ENOMEM); pd->pt.base = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K); if (IS_ERR(pd->pt.base)) { + kfree(pd->entry); kfree(pd); return ERR_PTR(-ENOMEM); } @@ -57,9 +64,19 @@ struct i915_page_directory *alloc_pd(struct i915_address_space *vm) return pd; } -void free_pt(struct i915_address_space *vm, struct i915_page_table *pt) +void free_px(struct i915_address_space *vm, struct i915_page_table *pt, int lvl) { - i915_gem_object_put(pt->base); + BUILD_BUG_ON(offsetof(struct i915_page_directory, pt)); + + if (lvl) { + struct i915_page_directory *pd = + container_of(pt, typeof(*pd), pt); + kfree(pd->entry); + } + + if (pt->base) + i915_gem_object_put(pt->base); + kfree(pt); } @@ -82,7 +99,7 @@ __set_pd_entry(struct i915_page_directory * const pd, u64 (*encode)(const dma_addr_t, const enum i915_cache_level)) { /* Each thread pre-pins the pd, and we may have a thread per pde. */ - GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * ARRAY_SIZE(pd->entry)); + GEM_BUG_ON(atomic_read(px_used(pd)) > NALLOC * I915_PDES); atomic_inc(px_used(pd)); pd->entry[idx] = to; @@ -263,7 +280,7 @@ void i915_vm_free_pt_stash(struct i915_address_space *vm, for (n = 0; n < ARRAY_SIZE(stash->pt); n++) { while ((pt = stash->pt[n])) { stash->pt[n] = pt->stash; - free_px(vm, pt); + free_px(vm, pt, n); } } } -- cgit v1.2.3 From 3f7dc1071665c38a195e24d28d8418b68c441584 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 1 Aug 2020 17:02:24 +0100 Subject: drm/i915/gt: Move intel_breadcrumbs_arm_irq earlier Move the __intel_breadcrumbs_arm_irq earlier, next to the disarm_irq, so that we can make use of it in the following patch. Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200801160225.6814-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 84 ++++++++++++++--------------- 1 file changed, 42 insertions(+), 42 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 2ffd47a86656..9dd99969fd07 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -54,6 +54,36 @@ static void irq_disable(struct intel_engine_cs *engine) spin_unlock(&engine->gt->irq_lock); } +static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) +{ + lockdep_assert_held(&b->irq_lock); + + if (!b->irq_engine || b->irq_armed) + return; + + if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) + return; + + /* + * The breadcrumb irq will be disarmed on the interrupt after the + * waiters are signaled. This gives us a single interrupt window in + * which we can add a new waiter and avoid the cost of re-enabling + * the irq. + */ + WRITE_ONCE(b->irq_armed, true); + + /* + * Since we are waiting on a request, the GPU should be busy + * and should have its own rpm reference. This is tracked + * by i915->gt.awake, we can forgo holding our own wakref + * for the interrupt as before i915->gt.awake is released (when + * the driver is idle) we disarm the breadcrumbs. + */ + + if (!b->irq_enabled++) + irq_enable(b->irq_engine); +} + static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) { lockdep_assert_held(&b->irq_lock); @@ -69,18 +99,6 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) intel_gt_pm_put_async(b->irq_engine->gt); } -void intel_breadcrumbs_park(struct intel_breadcrumbs *b) -{ - unsigned long flags; - - if (!READ_ONCE(b->irq_armed)) - return; - - spin_lock_irqsave(&b->irq_lock, flags); - __intel_breadcrumbs_disarm_irq(b); - spin_unlock_irqrestore(&b->irq_lock, flags); -} - static inline bool __request_completed(const struct i915_request *rq) { return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); @@ -214,36 +232,6 @@ static void signal_irq_work(struct irq_work *work) } } -static void __intel_breadcrumbs_arm_irq(struct intel_breadcrumbs *b) -{ - lockdep_assert_held(&b->irq_lock); - - if (!b->irq_engine || b->irq_armed) - return; - - if (!intel_gt_pm_get_if_awake(b->irq_engine->gt)) - return; - - /* - * The breadcrumb irq will be disarmed on the interrupt after the - * waiters are signaled. This gives us a single interrupt window in - * which we can add a new waiter and avoid the cost of re-enabling - * the irq. - */ - WRITE_ONCE(b->irq_armed, true); - - /* - * Since we are waiting on a request, the GPU should be busy - * and should have its own rpm reference. This is tracked - * by i915->gt.awake, we can forgo holding our own wakref - * for the interrupt as before i915->gt.awake is released (when - * the driver is idle) we disarm the breadcrumbs. - */ - - if (!b->irq_enabled++) - irq_enable(b->irq_engine); -} - struct intel_breadcrumbs * intel_breadcrumbs_create(struct intel_engine_cs *irq_engine) { @@ -281,6 +269,18 @@ void intel_breadcrumbs_reset(struct intel_breadcrumbs *b) spin_unlock_irqrestore(&b->irq_lock, flags); } +void intel_breadcrumbs_park(struct intel_breadcrumbs *b) +{ + unsigned long flags; + + if (!READ_ONCE(b->irq_armed)) + return; + + spin_lock_irqsave(&b->irq_lock, flags); + __intel_breadcrumbs_disarm_irq(b); + spin_unlock_irqrestore(&b->irq_lock, flags); +} + void intel_breadcrumbs_free(struct intel_breadcrumbs *b) { kfree(b); -- cgit v1.2.3 From e23005604b2f815720b00c2b36c9597fd43923cf Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 1 Aug 2020 17:02:25 +0100 Subject: drm/i915/gt: Hold context/request reference while breadcrumbs are active Currently we hold no actual reference to the request nor context while they are attached to a breadcrumb. To avoid freeing the request/context too early, we serialise with cancel-breadcrumbs by taking the irq spinlock in i915_request_retire(). The alternative is to take a reference for a new breadcrumb and release it upon signaling; removing the more frequently hit contention point in i915_request_retire(). Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200801160225.6814-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Rebased and reordered into drm-intel-gt-next branch] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 103 +++++++++++++++++++--------- drivers/gpu/drm/i915/i915_request.c | 9 ++- 2 files changed, 74 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 9dd99969fd07..d8b206e53660 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -29,6 +29,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_breadcrumbs.h" +#include "intel_context.h" #include "intel_gt_pm.h" #include "intel_gt_requests.h" @@ -99,6 +100,22 @@ static void __intel_breadcrumbs_disarm_irq(struct intel_breadcrumbs *b) intel_gt_pm_put_async(b->irq_engine->gt); } +static void add_signaling_context(struct intel_breadcrumbs *b, + struct intel_context *ce) +{ + intel_context_get(ce); + list_add_tail(&ce->signal_link, &b->signalers); + if (list_is_first(&ce->signal_link, &b->signalers)) + __intel_breadcrumbs_arm_irq(b); +} + +static void remove_signaling_context(struct intel_breadcrumbs *b, + struct intel_context *ce) +{ + list_del(&ce->signal_link); + intel_context_put(ce); +} + static inline bool __request_completed(const struct i915_request *rq) { return i915_seqno_passed(__hwsp_seqno(rq), rq->fence.seqno); @@ -107,6 +124,9 @@ static inline bool __request_completed(const struct i915_request *rq) __maybe_unused static bool check_signal_order(struct intel_context *ce, struct i915_request *rq) { + if (rq->context != ce) + return false; + if (!list_is_last(&rq->signal_link, &ce->signals) && i915_seqno_passed(rq->fence.seqno, list_next_entry(rq, signal_link)->fence.seqno)) @@ -158,10 +178,11 @@ static bool __signal_request(struct i915_request *rq, struct list_head *signals) { clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); - if (!__dma_fence_signal(&rq->fence)) + if (!__dma_fence_signal(&rq->fence)) { + i915_request_put(rq); return false; + } - i915_request_get(rq); list_add_tail(&rq->signal_link, signals); return true; } @@ -209,8 +230,8 @@ static void signal_irq_work(struct irq_work *work) /* Advance the list to the first incomplete request */ __list_del_many(&ce->signals, pos); if (&ce->signals == pos) { /* now empty */ - list_del_init(&ce->signal_link); add_retire(b, ce->timeline); + remove_signaling_context(b, ce); } } } @@ -279,6 +300,9 @@ void intel_breadcrumbs_park(struct intel_breadcrumbs *b) spin_lock_irqsave(&b->irq_lock, flags); __intel_breadcrumbs_disarm_irq(b); spin_unlock_irqrestore(&b->irq_lock, flags); + + if (!list_empty(&b->signalers)) + irq_work_queue(&b->irq_work); } void intel_breadcrumbs_free(struct intel_breadcrumbs *b) @@ -295,6 +319,8 @@ static void insert_breadcrumb(struct i915_request *rq, if (test_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags)) return; + i915_request_get(rq); + /* * If the request is already completed, we can transfer it * straight onto a signaled list, and queue the irq worker for @@ -306,32 +332,33 @@ static void insert_breadcrumb(struct i915_request *rq, return; } - __intel_breadcrumbs_arm_irq(b); - - /* - * We keep the seqno in retirement order, so we can break - * inside intel_engine_signal_breadcrumbs as soon as we've - * passed the last completed request (or seen a request that - * hasn't event started). We could walk the timeline->requests, - * but keeping a separate signalers_list has the advantage of - * hopefully being much smaller than the full list and so - * provides faster iteration and detection when there are no - * more interrupts required for this context. - * - * We typically expect to add new signalers in order, so we - * start looking for our insertion point from the tail of - * the list. - */ - list_for_each_prev(pos, &ce->signals) { - struct i915_request *it = - list_entry(pos, typeof(*it), signal_link); + if (list_empty(&ce->signals)) { + add_signaling_context(b, ce); + pos = &ce->signals; + } else { + /* + * We keep the seqno in retirement order, so we can break + * inside intel_engine_signal_breadcrumbs as soon as we've + * passed the last completed request (or seen a request that + * hasn't event started). We could walk the timeline->requests, + * but keeping a separate signalers_list has the advantage of + * hopefully being much smaller than the full list and so + * provides faster iteration and detection when there are no + * more interrupts required for this context. + * + * We typically expect to add new signalers in order, so we + * start looking for our insertion point from the tail of + * the list. + */ + list_for_each_prev(pos, &ce->signals) { + struct i915_request *it = + list_entry(pos, typeof(*it), signal_link); - if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) - break; + if (i915_seqno_passed(rq->fence.seqno, it->fence.seqno)) + break; + } } list_add(&rq->signal_link, pos); - if (pos == &ce->signals) /* catch transitions from empty list */ - list_move_tail(&ce->signal_link, &b->signalers); GEM_BUG_ON(!check_signal_order(ce, rq)); set_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); @@ -412,23 +439,19 @@ void i915_request_cancel_breadcrumb(struct i915_request *rq) list_del(&rq->signal_link); if (list_empty(&ce->signals)) - list_del_init(&ce->signal_link); + remove_signaling_context(b, ce); clear_bit(I915_FENCE_FLAG_SIGNAL, &rq->fence.flags); + i915_request_put(rq); } spin_unlock(&b->irq_lock); } -void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, - struct drm_printer *p) +static void print_signals(struct intel_breadcrumbs *b, struct drm_printer *p) { - struct intel_breadcrumbs *b = engine->breadcrumbs; struct intel_context *ce; struct i915_request *rq; - if (!b || list_empty(&b->signalers)) - return; - drm_printf(p, "Signals:\n"); spin_lock_irq(&b->irq_lock); @@ -444,3 +467,17 @@ void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, } spin_unlock_irq(&b->irq_lock); } + +void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, + struct drm_printer *p) +{ + struct intel_breadcrumbs *b; + + b = engine->breadcrumbs; + if (!b) + return; + + drm_printf(p, "IRQ: %s\n", enableddisabled(b->irq_armed)); + if (!list_empty(&b->signalers)) + print_signals(b, p); +} diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index fcb00b283b4f..20ba3d9fcc5e 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -296,13 +296,12 @@ bool i915_request_retire(struct i915_request *rq) */ remove_from_engine(rq); - spin_lock_irq(&rq->lock); i915_request_mark_complete(rq); - if (!i915_request_signaled(rq)) + if (!i915_request_signaled(rq)) { + spin_lock_irq(&rq->lock); dma_fence_signal_locked(&rq->fence); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &rq->fence.flags)) - i915_request_cancel_breadcrumb(rq); - spin_unlock_irq(&rq->lock); + spin_unlock_irq(&rq->lock); + } if (i915_request_has_waitboost(rq)) { GEM_BUG_ON(!atomic_read(&rq->engine->gt->rps.num_waiters)); -- cgit v1.2.3 From dd5e024956bf3035be380a3f022b77c06166112a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Aug 2020 15:57:28 +0100 Subject: drm/i915/selftests: Prevent selecting 0 for our random width/align When igt_random_offset() is a given a range of [0, PAGE_SIZE], it is allowed to return 0. However, attempting to use a size of 0 for the igt_lmem_write_cpu() byte poking, leads to call igt_random_offset() with a range of [offset, offset + 0] and ask it to find a length of 4 within it. This triggers the bug on that the requested length should fit within the range! Signed-off-by: Chris Wilson Cc: Matthew Auld Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200806145728.16495-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/selftests/intel_memory_region.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 6e80d99048e4..741270fcb6b9 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -522,9 +522,9 @@ static int igt_lmem_write_cpu(void *arg) goto out_unpin; } - /* We want to throw in a random width/align */ - bytes[0] = igt_random_offset(&prng, 0, PAGE_SIZE, sizeof(u32), - sizeof(u32)); + /* A random multiple of u32, picked between [64, PAGE_SIZE - 64] */ + bytes[0] = igt_random_offset(&prng, 64, PAGE_SIZE - 64, 0, sizeof(u32)); + GEM_BUG_ON(!IS_ALIGNED(bytes[0], sizeof(u32))); i = 0; do { -- cgit v1.2.3 From 736e785f9b28cd9ef2d16a80960a04fd00e64b22 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Aug 2020 11:59:54 +0100 Subject: drm/i915/gem: Reduce context termination list iteration guard to RCU As we now protect the timeline list using RCU, we can drop the timeline->mutex for guarding the list iteration during context close, as we are searching for an inflight request. Any new request will see the context is banned and not be submitted. In doing so, pull the checks for a concurrent submission of the request (notably the i915_request_completed()) under the engine spinlock, to fully serialise with __i915_request_submit()). That is in the case of preempt-to-busy where the request may be completed during the __i915_request_submit(), we need to be careful that we sample the request status after serialising so that we don't miss the request the engine is actually submitting. Fixes: 4a3174152147 ("drm/i915/gem: Refine occupancy test in kill_context()") References: d22d2d073ef8 ("drm/i915: Protect i915_request_await_start from early waits") # rcu protection of timeline->requests References: https://gitlab.freedesktop.org/drm/intel/-/issues/1622 References: https://gitlab.freedesktop.org/drm/intel/-/issues/2158 Signed-off-by: Chris Wilson Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200806105954.7766-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 32 +++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d8cccbab7a51..db893f6c516b 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -439,29 +439,36 @@ static bool __cancel_engine(struct intel_engine_cs *engine) return __reset_engine(engine); } -static struct intel_engine_cs *__active_engine(struct i915_request *rq) +static bool +__active_engine(struct i915_request *rq, struct intel_engine_cs **active) { struct intel_engine_cs *engine, *locked; + bool ret = false; /* * Serialise with __i915_request_submit() so that it sees * is-banned?, or we know the request is already inflight. + * + * Note that rq->engine is unstable, and so we double + * check that we have acquired the lock on the final engine. */ locked = READ_ONCE(rq->engine); spin_lock_irq(&locked->active.lock); while (unlikely(locked != (engine = READ_ONCE(rq->engine)))) { spin_unlock(&locked->active.lock); - spin_lock(&engine->active.lock); locked = engine; + spin_lock(&locked->active.lock); } - engine = NULL; - if (i915_request_is_active(rq) && rq->fence.error != -EIO) - engine = rq->engine; + if (!i915_request_completed(rq)) { + if (i915_request_is_active(rq) && rq->fence.error != -EIO) + *active = locked; + ret = true; + } spin_unlock_irq(&locked->active.lock); - return engine; + return ret; } static struct intel_engine_cs *active_engine(struct intel_context *ce) @@ -472,17 +479,16 @@ static struct intel_engine_cs *active_engine(struct intel_context *ce) if (!ce->timeline) return NULL; - mutex_lock(&ce->timeline->mutex); - list_for_each_entry_reverse(rq, &ce->timeline->requests, link) { - if (i915_request_completed(rq)) - break; + rcu_read_lock(); + list_for_each_entry_rcu(rq, &ce->timeline->requests, link) { + if (i915_request_is_active(rq) && i915_request_completed(rq)) + continue; /* Check with the backend if the request is inflight */ - engine = __active_engine(rq); - if (engine) + if (__active_engine(rq, &engine)) break; } - mutex_unlock(&ce->timeline->mutex); + rcu_read_unlock(); return engine; } -- cgit v1.2.3 From da1ea128a6a4d6d52b02ded82933944161c1cb01 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 6 Aug 2020 17:10:56 +0100 Subject: drm/i915/gem: Free the fence after a fence-chain lookup failure If dma_fence_chain_find_seqno() reports an error, it does so in its preamble before it disposes of the input fence. On handling the error, we need to drop the reference to the fence. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2292 Signed-off-by: Chris Wilson Cc: Lionel Landwerlin Fixes: 13149e8bafc4 ("drm/i915: add syncobj timeline support") Reviewed-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20200806161056.17593-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 9ce114d67288..24a1486d2dc5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2289,6 +2289,7 @@ add_timeline_fence_array(struct i915_execbuffer *eb, if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) { DRM_DEBUG("Syncobj handle missing requested point %llu\n", point); + dma_fence_put(fence); drm_syncobj_put(syncobj); return err; } -- cgit v1.2.3 From 102a0a9051f4bb61c105bd2c68b82456325c7c2a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:41 +0200 Subject: Revert "drm/i915/gem: Async GPU relocations only" This reverts commit 9e0f9464e2ab ("drm/i915/gem: Async GPU relocations only"), and related commit 7ac2d2536dfa7 ("drm/i915/gem: Delete unused code"). Async GPU relocations are not the path forward, we want to remove GPU accelerated relocation support eventually when userspace is fixed to use VM_BIND, and this is the first step towards that. We will keep async gpu relocations around for now, until userspace is fixed. Relocation support will be disabled completely on platforms where there was never any userspace that depends on it, as the hardware doesn't require it from at least gen9+ onward. For older platforms, the plan is to use cpu relocations only. The igt side is fixed in igt commit 39e9aa1032a4e ("tests/i915: Remove subtests that rely on async relocation behavior"). Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-2-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 319 +++++++++++++++++++-- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 21 +- 2 files changed, 313 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 24a1486d2dc5..c6a613d92a13 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -46,6 +46,13 @@ struct eb_vma_array { struct eb_vma vma[]; }; +enum { + FORCE_CPU_RELOC = 1, + FORCE_GTT_RELOC, + FORCE_GPU_RELOC, +#define DBG_FORCE_RELOC 0 /* choose one of the above! */ +}; + #define __EXEC_OBJECT_HAS_PIN BIT(31) #define __EXEC_OBJECT_HAS_FENCE BIT(30) #define __EXEC_OBJECT_NEEDS_MAP BIT(29) @@ -261,6 +268,8 @@ struct i915_execbuffer { */ struct reloc_cache { struct drm_mm_node node; /** temporary GTT binding */ + unsigned long vaddr; /** Current kmap address */ + unsigned long page; /** Currently mapped page index */ unsigned int gen; /** Cached value of INTEL_GEN */ bool use_64bit_reloc : 1; bool has_llc : 1; @@ -607,6 +616,23 @@ eb_add_vma(struct i915_execbuffer *eb, } } +static inline int use_cpu_reloc(const struct reloc_cache *cache, + const struct drm_i915_gem_object *obj) +{ + if (!i915_gem_object_has_struct_page(obj)) + return false; + + if (DBG_FORCE_RELOC == FORCE_CPU_RELOC) + return true; + + if (DBG_FORCE_RELOC == FORCE_GTT_RELOC) + return false; + + return (cache->has_llc || + obj->cache_dirty || + obj->cache_level != I915_CACHE_NONE); +} + static int eb_reserve_vma(const struct i915_execbuffer *eb, struct eb_vma *ev, u64 pin_flags) @@ -937,6 +963,8 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc, static void reloc_cache_init(struct reloc_cache *cache, struct drm_i915_private *i915) { + cache->page = -1; + cache->vaddr = 0; /* Must be a variable in the struct to allow GCC to unroll. */ cache->gen = INTEL_GEN(i915); cache->has_llc = HAS_LLC(i915); @@ -948,6 +976,25 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->target = NULL; } +static inline void *unmask_page(unsigned long p) +{ + return (void *)(uintptr_t)(p & PAGE_MASK); +} + +static inline unsigned int unmask_flags(unsigned long p) +{ + return p & ~PAGE_MASK; +} + +#define KMAP 0x4 /* after CLFLUSH_FLAGS */ + +static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) +{ + struct drm_i915_private *i915 = + container_of(cache, struct i915_execbuffer, reloc_cache)->i915; + return &i915->ggtt; +} + #define RELOC_TAIL 4 static int reloc_gpu_chain(struct reloc_cache *cache) @@ -1060,6 +1107,186 @@ static int reloc_gpu_flush(struct reloc_cache *cache) return err; } +static void reloc_cache_reset(struct reloc_cache *cache) +{ + void *vaddr; + + if (!cache->vaddr) + return; + + vaddr = unmask_page(cache->vaddr); + if (cache->vaddr & KMAP) { + if (cache->vaddr & CLFLUSH_AFTER) + mb(); + + kunmap_atomic(vaddr); + i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm); + } else { + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __iomem *)vaddr); + + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.clear_range(&ggtt->vm, + cache->node.start, + cache->node.size); + mutex_lock(&ggtt->vm.mutex); + drm_mm_remove_node(&cache->node); + mutex_unlock(&ggtt->vm.mutex); + } else { + i915_vma_unpin((struct i915_vma *)cache->node.mm); + } + } + + cache->vaddr = 0; + cache->page = -1; +} + +static void *reloc_kmap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long pageno) +{ + void *vaddr; + struct page *page; + + if (cache->vaddr) { + kunmap_atomic(unmask_page(cache->vaddr)); + } else { + unsigned int flushes; + int err; + + err = i915_gem_object_prepare_write(obj, &flushes); + if (err) + return ERR_PTR(err); + + BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); + BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); + + cache->vaddr = flushes | KMAP; + cache->node.mm = (void *)obj; + if (flushes) + mb(); + } + + page = i915_gem_object_get_page(obj, pageno); + if (!obj->mm.dirty) + set_page_dirty(page); + + vaddr = kmap_atomic(page); + cache->vaddr = unmask_flags(cache->vaddr) | (unsigned long)vaddr; + cache->page = pageno; + + return vaddr; +} + +static void *reloc_iomap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + unsigned long offset; + void *vaddr; + + if (cache->vaddr) { + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); + } else { + struct i915_vma *vma; + int err; + + if (i915_gem_object_is_tiled(obj)) + return ERR_PTR(-EINVAL); + + if (use_cpu_reloc(cache, obj)) + return NULL; + + i915_gem_object_lock(obj); + err = i915_gem_object_set_to_gtt_domain(obj, true); + i915_gem_object_unlock(obj); + if (err) + return ERR_PTR(err); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (IS_ERR(vma)) { + memset(&cache->node, 0, sizeof(cache->node)); + mutex_lock(&ggtt->vm.mutex); + err = drm_mm_insert_node_in_range + (&ggtt->vm.mm, &cache->node, + PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE, + 0, ggtt->mappable_end, + DRM_MM_INSERT_LOW); + mutex_unlock(&ggtt->vm.mutex); + if (err) /* no inactive aperture space, use cpu reloc */ + return NULL; + } else { + cache->node.start = vma->node.start; + cache->node.mm = (void *)vma; + } + } + + offset = cache->node.start; + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.insert_page(&ggtt->vm, + i915_gem_object_get_dma_address(obj, page), + offset, I915_CACHE_NONE, 0); + } else { + offset += page << PAGE_SHIFT; + } + + vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap, + offset); + cache->page = page; + cache->vaddr = (unsigned long)vaddr; + + return vaddr; +} + +static void *reloc_vaddr(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + void *vaddr; + + if (cache->page == page) { + vaddr = unmask_page(cache->vaddr); + } else { + vaddr = NULL; + if ((cache->vaddr & KMAP) == 0) + vaddr = reloc_iomap(obj, cache, page); + if (!vaddr) + vaddr = reloc_kmap(obj, cache, page); + } + + return vaddr; +} + +static void clflush_write32(u32 *addr, u32 value, unsigned int flushes) +{ + if (unlikely(flushes & (CLFLUSH_BEFORE | CLFLUSH_AFTER))) { + if (flushes & CLFLUSH_BEFORE) { + clflushopt(addr); + mb(); + } + + *addr = value; + + /* + * Writes to the same cacheline are serialised by the CPU + * (including clflush). On the write path, we only require + * that it hits memory in an orderly fashion and place + * mb barriers at the start and end of the relocation phase + * to ensure ordering of clflush wrt to the system. + */ + if (flushes & CLFLUSH_AFTER) + clflushopt(addr); + } else + *addr = value; +} + static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -1225,6 +1452,17 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, return cmd; } +static inline bool use_reloc_gpu(struct i915_vma *vma) +{ + if (DBG_FORCE_RELOC == FORCE_GPU_RELOC) + return true; + + if (DBG_FORCE_RELOC) + return false; + + return !dma_resv_test_signaled_rcu(vma->resv, true); +} + static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) { struct page *page; @@ -1239,10 +1477,10 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static int __reloc_entry_gpu(struct i915_execbuffer *eb, - struct i915_vma *vma, - u64 offset, - u64 target_addr) +static bool __reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) { const unsigned int gen = eb->reloc_cache.gen; unsigned int len; @@ -1258,7 +1496,7 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, batch = reloc_gpu(eb, vma, len); if (IS_ERR(batch)) - return PTR_ERR(batch); + return false; addr = gen8_canonical_addr(vma->node.start + offset); if (gen >= 8) { @@ -1307,21 +1545,55 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, *batch++ = target_addr; } - return 0; + return true; +} + +static bool reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) +{ + if (eb->reloc_cache.vaddr) + return false; + + if (!use_reloc_gpu(vma)) + return false; + + return __reloc_entry_gpu(eb, vma, offset, target_addr); } static u64 -relocate_entry(struct i915_execbuffer *eb, - struct i915_vma *vma, +relocate_entry(struct i915_vma *vma, const struct drm_i915_gem_relocation_entry *reloc, + struct i915_execbuffer *eb, const struct i915_vma *target) { u64 target_addr = relocation_target(reloc, target); - int err; - - err = __reloc_entry_gpu(eb, vma, reloc->offset, target_addr); - if (err) - return err; + u64 offset = reloc->offset; + + if (!reloc_entry_gpu(eb, vma, offset, target_addr)) { + bool wide = eb->reloc_cache.use_64bit_reloc; + void *vaddr; + +repeat: + vaddr = reloc_vaddr(vma->obj, + &eb->reloc_cache, + offset >> PAGE_SHIFT); + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + + GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32))); + clflush_write32(vaddr + offset_in_page(offset), + lower_32_bits(target_addr), + eb->reloc_cache.vaddr); + + if (wide) { + offset += sizeof(u32); + target_addr >>= 32; + wide = false; + goto repeat; + } + } return target->node.start | UPDATE; } @@ -1386,7 +1658,8 @@ eb_relocate_entry(struct i915_execbuffer *eb, * If the relocation already has the right value in it, no * more work needs to be done. */ - if (gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) + if (!DBG_FORCE_RELOC && + gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) return 0; /* Check that the relocation address is valid... */ @@ -1418,7 +1691,7 @@ eb_relocate_entry(struct i915_execbuffer *eb, ev->flags &= ~EXEC_OBJECT_ASYNC; /* and update the user's relocation entry */ - return relocate_entry(eb, ev->vma, reloc, target->vma); + return relocate_entry(ev->vma, reloc, eb, target->vma); } static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) @@ -1456,8 +1729,10 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) * this is bad and so lockdep complains vehemently. */ copied = __copy_from_user(r, urelocs, count * sizeof(r[0])); - if (unlikely(copied)) - return -EFAULT; + if (unlikely(copied)) { + remain = -EFAULT; + goto out; + } remain -= count; do { @@ -1465,7 +1740,8 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) if (likely(offset == 0)) { } else if ((s64)offset < 0) { - return (int)offset; + remain = (int)offset; + goto out; } else { /* * Note that reporting an error now @@ -1495,8 +1771,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) } while (r++, --count); urelocs += ARRAY_SIZE(stack); } while (remain); - - return 0; +out: + reloc_cache_reset(&eb->reloc_cache); + return remain; } static int eb_relocate(struct i915_execbuffer *eb) @@ -2573,7 +2850,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.i915 = i915; eb.file = file; eb.args = args; - if (!(args->flags & I915_EXEC_NO_RELOC)) + if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC)) args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 57c14d3340cd..a49016f8ee0d 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -37,14 +37,20 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, return err; /* 8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[0] * sizeof(u32), + 0)) { + err = -EIO; goto unpin_vma; + } /* !8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[1] * sizeof(u32), + 1)) { + err = -EIO; goto unpin_vma; + } /* Skip to the end of the cmd page */ i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1; @@ -54,9 +60,12 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, eb->reloc_cache.rq_size += i; /* Force batch chaining */ - err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[2] * sizeof(u32), + 2)) { + err = -EIO; goto unpin_vma; + } GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); -- cgit v1.2.3 From 50ae6c61a17ce12c81fb1aa8b1bd21c284b81768 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:42 +0200 Subject: drm/i915: Revert relocation chaining commits. This reverts commit 964a9b0f611ee ("drm/i915/gem: Use chained reloc batches") and commit 0e97fbb080553 ("drm/i915/gem: Use a single chained reloc batches for a single execbuf"). When adding ww locking to execbuf, it's hard enough to deal with a single BO that is part of relocation execution. Chaining is hard to get right, and with GPU relocation deprecated, it's best to drop this altogether, instead of trying to fix something we will remove. This is not a completely 1:1 revert, we reset rq_size to 0 in reloc_cache_init, this was from e3d291301f99 ("drm/i915/gem: Implement legacy MI_STORE_DATA_IMM"), because we don't want to break the selftests. (Daniel) Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-3-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 171 ++++----------------- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 8 +- 2 files changed, 35 insertions(+), 144 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index c6a613d92a13..6acbd08f82f0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -276,9 +276,7 @@ struct i915_execbuffer { bool has_fence : 1; bool needs_unfenced : 1; - struct i915_vma *target; struct i915_request *rq; - struct i915_vma *rq_vma; u32 *rq_cmd; unsigned int rq_size; } reloc_cache; @@ -973,7 +971,7 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment; cache->node.flags = 0; cache->rq = NULL; - cache->target = NULL; + cache->rq_size = 0; } static inline void *unmask_page(unsigned long p) @@ -995,122 +993,29 @@ static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) return &i915->ggtt; } -#define RELOC_TAIL 4 - -static int reloc_gpu_chain(struct reloc_cache *cache) +static void reloc_gpu_flush(struct reloc_cache *cache) { - struct intel_gt_buffer_pool_node *pool; - struct i915_request *rq = cache->rq; - struct i915_vma *batch; - u32 *cmd; - int err; - - pool = intel_gt_get_buffer_pool(rq->engine->gt, PAGE_SIZE); - if (IS_ERR(pool)) - return PTR_ERR(pool); - - batch = i915_vma_instance(pool->obj, rq->context->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_pool; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER | PIN_NONBLOCK); - if (err) - goto out_pool; - - GEM_BUG_ON(cache->rq_size + RELOC_TAIL > PAGE_SIZE / sizeof(u32)); - cmd = cache->rq_cmd + cache->rq_size; - *cmd++ = MI_ARB_CHECK; - if (cache->gen >= 8) - *cmd++ = MI_BATCH_BUFFER_START_GEN8; - else if (cache->gen >= 6) - *cmd++ = MI_BATCH_BUFFER_START; - else - *cmd++ = MI_BATCH_BUFFER_START | MI_BATCH_GTT; - *cmd++ = lower_32_bits(batch->node.start); - *cmd++ = upper_32_bits(batch->node.start); /* Always 0 for gen<8 */ - i915_gem_object_flush_map(cache->rq_vma->obj); - i915_gem_object_unpin_map(cache->rq_vma->obj); - cache->rq_vma = NULL; - - err = intel_gt_buffer_pool_mark_active(pool, rq); - if (err == 0) { - i915_vma_lock(batch); - err = i915_request_await_object(rq, batch->obj, false); - if (err == 0) - err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); - } - i915_vma_unpin(batch); - if (err) - goto out_pool; + struct drm_i915_gem_object *obj = cache->rq->batch->obj; - cmd = i915_gem_object_pin_map(batch->obj, - cache->has_llc ? - I915_MAP_FORCE_WB : - I915_MAP_FORCE_WC); - if (IS_ERR(cmd)) { - err = PTR_ERR(cmd); - goto out_pool; - } + GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32)); + cache->rq_cmd[cache->rq_size] = MI_BATCH_BUFFER_END; - /* Return with batch mapping (cmd) still pinned */ - cache->rq_cmd = cmd; - cache->rq_size = 0; - cache->rq_vma = batch; + __i915_gem_object_flush_map(obj, 0, sizeof(u32) * (cache->rq_size + 1)); + i915_gem_object_unpin_map(obj); -out_pool: - intel_gt_buffer_pool_put(pool); - return err; -} + intel_gt_chipset_flush(cache->rq->engine->gt); -static unsigned int reloc_bb_flags(const struct reloc_cache *cache) -{ - return cache->gen > 5 ? 0 : I915_DISPATCH_SECURE; -} - -static int reloc_gpu_flush(struct reloc_cache *cache) -{ - struct i915_request *rq; - int err; - - rq = fetch_and_zero(&cache->rq); - if (!rq) - return 0; - - if (cache->rq_vma) { - struct drm_i915_gem_object *obj = cache->rq_vma->obj; - - GEM_BUG_ON(cache->rq_size >= obj->base.size / sizeof(u32)); - cache->rq_cmd[cache->rq_size++] = MI_BATCH_BUFFER_END; - - __i915_gem_object_flush_map(obj, - 0, sizeof(u32) * cache->rq_size); - i915_gem_object_unpin_map(obj); - } - - err = 0; - if (rq->engine->emit_init_breadcrumb) - err = rq->engine->emit_init_breadcrumb(rq); - if (!err) - err = rq->engine->emit_bb_start(rq, - rq->batch->node.start, - PAGE_SIZE, - reloc_bb_flags(cache)); - if (err) - i915_request_set_error_once(rq, err); - - intel_gt_chipset_flush(rq->engine->gt); - i915_request_add(rq); - - return err; + i915_request_add(cache->rq); + cache->rq = NULL; } static void reloc_cache_reset(struct reloc_cache *cache) { void *vaddr; + if (cache->rq) + reloc_gpu_flush(cache); + if (!cache->vaddr) return; @@ -1309,6 +1214,7 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) static int __reloc_gpu_alloc(struct i915_execbuffer *eb, struct intel_engine_cs *engine, + struct i915_vma *vma, unsigned int len) { struct reloc_cache *cache = &eb->reloc_cache; @@ -1331,7 +1237,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, goto out_pool; } - batch = i915_vma_instance(pool->obj, eb->context->vm, NULL); + batch = i915_vma_instance(pool->obj, vma->vm, NULL); if (IS_ERR(batch)) { err = PTR_ERR(batch); goto err_unmap; @@ -1367,6 +1273,16 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto err_request; + err = reloc_move_to_gpu(rq, vma); + if (err) + goto err_request; + + err = eb->engine->emit_bb_start(rq, + batch->node.start, PAGE_SIZE, + cache->gen > 5 ? 0 : I915_DISPATCH_SECURE); + if (err) + goto skip_request; + i915_vma_lock(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) @@ -1381,7 +1297,6 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, cache->rq = rq; cache->rq_cmd = cmd; cache->rq_size = 0; - cache->rq_vma = batch; /* Return with batch mapping (cmd) still pinned */ goto out_pool; @@ -1410,9 +1325,12 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, { struct reloc_cache *cache = &eb->reloc_cache; u32 *cmd; - int err; + + if (cache->rq_size > PAGE_SIZE/sizeof(u32) - (len + 1)) + reloc_gpu_flush(cache); if (unlikely(!cache->rq)) { + int err; struct intel_engine_cs *engine = eb->engine; if (!reloc_can_use_engine(engine)) { @@ -1421,31 +1339,11 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, return ERR_PTR(-ENODEV); } - err = __reloc_gpu_alloc(eb, engine, len); + err = __reloc_gpu_alloc(eb, engine, vma, len); if (unlikely(err)) return ERR_PTR(err); } - if (vma != cache->target) { - err = reloc_move_to_gpu(cache->rq, vma); - if (unlikely(err)) { - i915_request_set_error_once(cache->rq, err); - return ERR_PTR(err); - } - - cache->target = vma; - } - - if (unlikely(cache->rq_size + len > - PAGE_SIZE / sizeof(u32) - RELOC_TAIL)) { - err = reloc_gpu_chain(cache); - if (unlikely(err)) { - i915_request_set_error_once(cache->rq, err); - return ERR_PTR(err); - } - } - - GEM_BUG_ON(cache->rq_size + len >= PAGE_SIZE / sizeof(u32)); cmd = cache->rq_cmd + cache->rq_size; cache->rq_size += len; @@ -1793,20 +1691,15 @@ static int eb_relocate(struct i915_execbuffer *eb) /* The objects are in their final locations, apply the relocations. */ if (eb->args->flags & __EXEC_HAS_RELOC) { struct eb_vma *ev; - int flush; list_for_each_entry(ev, &eb->relocs, reloc_link) { err = eb_relocate_vma(eb, ev); if (err) - break; + return err; } - - flush = reloc_gpu_flush(&eb->reloc_cache); - if (!err) - err = flush; } - return err; + return 0; } static int eb_move_to_gpu(struct i915_execbuffer *eb) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index a49016f8ee0d..580884cffec3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -53,13 +53,13 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, } /* Skip to the end of the cmd page */ - i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1; + i = PAGE_SIZE / sizeof(u32) - 1; i -= eb->reloc_cache.rq_size; memset32(eb->reloc_cache.rq_cmd + eb->reloc_cache.rq_size, MI_NOOP, i); eb->reloc_cache.rq_size += i; - /* Force batch chaining */ + /* Force next batch */ if (!__reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2)) { @@ -69,9 +69,7 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); - err = reloc_gpu_flush(&eb->reloc_cache); - if (err) - goto put_rq; + reloc_gpu_flush(&eb->reloc_cache); GEM_BUG_ON(eb->reloc_cache.rq); err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, HZ / 2); -- cgit v1.2.3 From fd1500fcd4420eee06e2c7f3aa6067b78ac05871 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:43 +0200 Subject: Revert "drm/i915/gem: Drop relocation slowpath". This reverts commit 7dc8f1143778 ("drm/i915/gem: Drop relocation slowpath"). We need the slowpath relocation for taking ww-mutex inside the page fault handler, and we will take this mutex when pinning all objects. We also functionally revert ef398881d27d ("drm/i915/gem: Limit struct_mutex to eb_reserve"), as we need the struct_mutex in the slowpath as well, and a tiny part of 003d8b9143a6 ("drm/i915/gem: Only call eb_lookup_vma once during execbuf ioctl"). Specifically, we make the -EAGAIN handling part of fallback to slowpath again. With this, we have a proper working slowpath again, which will allow us to do fault handling with WW locks held. [mlankhorst: Adjusted for reloc_gpu_flush() changes] Cc: Chris Wilson Cc: Matthew Auld Signed-off-by: Maarten Lankhorst [mlankhorst: Removed extra reloc_gpu_flush()] Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-4-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 262 ++++++++++++++++++++++++- 1 file changed, 252 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 6acbd08f82f0..e8d713f78323 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -707,7 +707,7 @@ static int eb_reserve(struct i915_execbuffer *eb) if (err) break; } - if (!(err == -ENOSPC || err == -EAGAIN)) + if (err != -ENOSPC) break; /* Resort *all* the objects into priority order */ @@ -738,13 +738,6 @@ static int eb_reserve(struct i915_execbuffer *eb) } list_splice_tail(&last, &eb->unbound); - if (err == -EAGAIN) { - mutex_unlock(&eb->i915->drm.struct_mutex); - flush_workqueue(eb->i915->mm.userptr_wq); - mutex_lock(&eb->i915->drm.struct_mutex); - continue; - } - switch (pass++) { case 0: break; @@ -1626,7 +1619,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) * we would try to acquire the struct mutex again. Obviously * this is bad and so lockdep complains vehemently. */ - copied = __copy_from_user(r, urelocs, count * sizeof(r[0])); + pagefault_disable(); + copied = __copy_from_user_inatomic(r, urelocs, count * sizeof(r[0])); + pagefault_enable(); if (unlikely(copied)) { remain = -EFAULT; goto out; @@ -1674,6 +1669,250 @@ out: return remain; } +static int +eb_relocate_vma_slow(struct i915_execbuffer *eb, struct eb_vma *ev) +{ + const struct drm_i915_gem_exec_object2 *entry = ev->exec; + struct drm_i915_gem_relocation_entry *relocs = + u64_to_ptr(typeof(*relocs), entry->relocs_ptr); + unsigned int i; + int err; + + for (i = 0; i < entry->relocation_count; i++) { + u64 offset = eb_relocate_entry(eb, ev, &relocs[i]); + + if ((s64)offset < 0) { + err = (int)offset; + goto err; + } + } + err = 0; +err: + reloc_cache_reset(&eb->reloc_cache); + return err; +} + +static int check_relocations(const struct drm_i915_gem_exec_object2 *entry) +{ + const char __user *addr, *end; + unsigned long size; + char __maybe_unused c; + + size = entry->relocation_count; + if (size == 0) + return 0; + + if (size > N_RELOC(ULONG_MAX)) + return -EINVAL; + + addr = u64_to_user_ptr(entry->relocs_ptr); + size *= sizeof(struct drm_i915_gem_relocation_entry); + if (!access_ok(addr, size)) + return -EFAULT; + + end = addr + size; + for (; addr < end; addr += PAGE_SIZE) { + int err = __get_user(c, addr); + if (err) + return err; + } + return __get_user(c, end - 1); +} + +static int eb_copy_relocations(const struct i915_execbuffer *eb) +{ + struct drm_i915_gem_relocation_entry *relocs; + const unsigned int count = eb->buffer_count; + unsigned int i; + int err; + + for (i = 0; i < count; i++) { + const unsigned int nreloc = eb->exec[i].relocation_count; + struct drm_i915_gem_relocation_entry __user *urelocs; + unsigned long size; + unsigned long copied; + + if (nreloc == 0) + continue; + + err = check_relocations(&eb->exec[i]); + if (err) + goto err; + + urelocs = u64_to_user_ptr(eb->exec[i].relocs_ptr); + size = nreloc * sizeof(*relocs); + + relocs = kvmalloc_array(size, 1, GFP_KERNEL); + if (!relocs) { + err = -ENOMEM; + goto err; + } + + /* copy_from_user is limited to < 4GiB */ + copied = 0; + do { + unsigned int len = + min_t(u64, BIT_ULL(31), size - copied); + + if (__copy_from_user((char *)relocs + copied, + (char __user *)urelocs + copied, + len)) + goto end; + + copied += len; + } while (copied < size); + + /* + * As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + if (!user_access_begin(urelocs, size)) + goto end; + + for (copied = 0; copied < nreloc; copied++) + unsafe_put_user(-1, + &urelocs[copied].presumed_offset, + end_user); + user_access_end(); + + eb->exec[i].relocs_ptr = (uintptr_t)relocs; + } + + return 0; + +end_user: + user_access_end(); +end: + kvfree(relocs); + err = -EFAULT; +err: + while (i--) { + relocs = u64_to_ptr(typeof(*relocs), eb->exec[i].relocs_ptr); + if (eb->exec[i].relocation_count) + kvfree(relocs); + } + return err; +} + +static int eb_prefault_relocations(const struct i915_execbuffer *eb) +{ + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + int err; + + err = check_relocations(&eb->exec[i]); + if (err) + return err; + } + + return 0; +} + +static noinline int eb_relocate_slow(struct i915_execbuffer *eb) +{ + bool have_copy = false; + struct eb_vma *ev; + int err = 0; + +repeat: + if (signal_pending(current)) { + err = -ERESTARTSYS; + goto out; + } + + /* + * We take 3 passes through the slowpatch. + * + * 1 - we try to just prefault all the user relocation entries and + * then attempt to reuse the atomic pagefault disabled fast path again. + * + * 2 - we copy the user entries to a local buffer here outside of the + * local and allow ourselves to wait upon any rendering before + * relocations + * + * 3 - we already have a local copy of the relocation entries, but + * were interrupted (EAGAIN) whilst waiting for the objects, try again. + */ + if (!err) { + err = eb_prefault_relocations(eb); + } else if (!have_copy) { + err = eb_copy_relocations(eb); + have_copy = err == 0; + } else { + cond_resched(); + err = 0; + } + + flush_workqueue(eb->i915->mm.userptr_wq); + + if (err) + goto out; + + err = mutex_lock_interruptible(&eb->i915->drm.struct_mutex); + if (err) + goto out; + + list_for_each_entry(ev, &eb->relocs, reloc_link) { + if (!have_copy) { + pagefault_disable(); + err = eb_relocate_vma(eb, ev); + pagefault_enable(); + if (err) + break; + } else { + err = eb_relocate_vma_slow(eb, ev); + if (err) + break; + } + } + + mutex_unlock(&eb->i915->drm.struct_mutex); + if (err && !have_copy) + goto repeat; + + if (err) + goto err; + + /* + * Leave the user relocations as are, this is the painfully slow path, + * and we want to avoid the complication of dropping the lock whilst + * having buffers reserved in the aperture and so causing spurious + * ENOSPC for random operations. + */ + +err: + if (err == -EAGAIN) + goto repeat; + +out: + if (have_copy) { + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + const struct drm_i915_gem_exec_object2 *entry = + &eb->exec[i]; + struct drm_i915_gem_relocation_entry *relocs; + + if (!entry->relocation_count) + continue; + + relocs = u64_to_ptr(typeof(*relocs), entry->relocs_ptr); + kvfree(relocs); + } + } + + return err; +} + static int eb_relocate(struct i915_execbuffer *eb) { int err; @@ -1695,8 +1934,11 @@ static int eb_relocate(struct i915_execbuffer *eb) list_for_each_entry(ev, &eb->relocs, reloc_link) { err = eb_relocate_vma(eb, ev); if (err) - return err; + break; } + + if (err) + return eb_relocate_slow(eb); } return 0; -- cgit v1.2.3 From 8ae275c288d3629cd7a2d0191c09f9c9edcec4c0 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:44 +0200 Subject: Revert "drm/i915/gem: Split eb_vma into its own allocation" This reverts commit 0f1dd02295f3 ("drm/i915/gem: Split eb_vma into its own allocation") and also moves all unreserving to a single place at the end, which is a minor simplification. With the WW locking, we will drop all references only at the end when unlocking, so refcounting can now be removed. Signed-off-by: Maarten Lankhorst Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-5-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 124 ++++++++++--------------- 1 file changed, 51 insertions(+), 73 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index e8d713f78323..ccaaf9e599a0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -41,11 +41,6 @@ struct eb_vma { u32 handle; }; -struct eb_vma_array { - struct kref kref; - struct eb_vma vma[]; -}; - enum { FORCE_CPU_RELOC = 1, FORCE_GTT_RELOC, @@ -58,6 +53,7 @@ enum { #define __EXEC_OBJECT_NEEDS_MAP BIT(29) #define __EXEC_OBJECT_NEEDS_BIAS BIT(28) #define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 28) /* all of the above */ +#define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE) #define __EXEC_HAS_RELOC BIT(31) #define __EXEC_INTERNAL_FLAGS (~0u << 31) @@ -295,7 +291,6 @@ struct i915_execbuffer { */ int lut_size; struct hlist_head *buckets; /** ht for relocation handles */ - struct eb_vma_array *array; struct eb_fence *fences; unsigned long num_fences; @@ -308,62 +303,8 @@ static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) eb->args->batch_len); } -static struct eb_vma_array *eb_vma_array_create(unsigned int count) -{ - struct eb_vma_array *arr; - - arr = kvmalloc(struct_size(arr, vma, count), GFP_KERNEL | __GFP_NOWARN); - if (!arr) - return NULL; - - kref_init(&arr->kref); - arr->vma[0].vma = NULL; - - return arr; -} - -static inline void eb_unreserve_vma(struct eb_vma *ev) -{ - struct i915_vma *vma = ev->vma; - - if (unlikely(ev->flags & __EXEC_OBJECT_HAS_FENCE)) - __i915_vma_unpin_fence(vma); - - if (ev->flags & __EXEC_OBJECT_HAS_PIN) - __i915_vma_unpin(vma); - - ev->flags &= ~(__EXEC_OBJECT_HAS_PIN | - __EXEC_OBJECT_HAS_FENCE); -} - -static void eb_vma_array_destroy(struct kref *kref) -{ - struct eb_vma_array *arr = container_of(kref, typeof(*arr), kref); - struct eb_vma *ev = arr->vma; - - while (ev->vma) { - eb_unreserve_vma(ev); - i915_vma_put(ev->vma); - ev++; - } - - kvfree(arr); -} - -static void eb_vma_array_put(struct eb_vma_array *arr) -{ - kref_put(&arr->kref, eb_vma_array_destroy); -} - static int eb_create(struct i915_execbuffer *eb) { - /* Allocate an extra slot for use by the command parser + sentinel */ - eb->array = eb_vma_array_create(eb->buffer_count + 2); - if (!eb->array) - return -ENOMEM; - - eb->vma = eb->array->vma; - if (!(eb->args->flags & I915_EXEC_HANDLE_LUT)) { unsigned int size = 1 + ilog2(eb->buffer_count); @@ -397,10 +338,8 @@ static int eb_create(struct i915_execbuffer *eb) break; } while (--size); - if (unlikely(!size)) { - eb_vma_array_put(eb->array); + if (unlikely(!size)) return -ENOMEM; - } eb->lut_size = size; } else { @@ -511,6 +450,26 @@ eb_pin_vma(struct i915_execbuffer *eb, return !eb_vma_misplaced(entry, vma, ev->flags); } +static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags) +{ + GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN)); + + if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE)) + __i915_vma_unpin_fence(vma); + + __i915_vma_unpin(vma); +} + +static inline void +eb_unreserve_vma(struct eb_vma *ev) +{ + if (!(ev->flags & __EXEC_OBJECT_HAS_PIN)) + return; + + __eb_unreserve_vma(ev->vma, ev->flags); + ev->flags &= ~__EXEC_OBJECT_RESERVED; +} + static int eb_validate_vma(struct i915_execbuffer *eb, struct drm_i915_gem_exec_object2 *entry, @@ -933,13 +892,31 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } +static void eb_release_vmas(const struct i915_execbuffer *eb) +{ + const unsigned int count = eb->buffer_count; + unsigned int i; + + for (i = 0; i < count; i++) { + struct eb_vma *ev = &eb->vma[i]; + struct i915_vma *vma = ev->vma; + + if (!vma) + break; + + eb->vma[i].vma = NULL; + + if (ev->flags & __EXEC_OBJECT_HAS_PIN) + __eb_unreserve_vma(vma, ev->flags); + + i915_vma_put(vma); + } +} + static void eb_destroy(const struct i915_execbuffer *eb) { GEM_BUG_ON(eb->reloc_cache.rq); - if (eb->array) - eb_vma_array_put(eb->array); - if (eb->lut_size > 0) kfree(eb->buckets); } @@ -2021,12 +1998,9 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) err = i915_vma_move_to_active(vma, eb->request, flags); i915_vma_unlock(vma); - eb_unreserve_vma(ev); } ww_acquire_fini(&acquire); - eb_vma_array_put(fetch_and_zero(&eb->array)); - if (unlikely(err)) goto err_skip; @@ -2323,7 +2297,6 @@ static int eb_parse(struct i915_execbuffer *eb) eb->vma[eb->buffer_count].vma = i915_vma_get(shadow); eb->vma[eb->buffer_count].flags = __EXEC_OBJECT_HAS_PIN; eb->batch = &eb->vma[eb->buffer_count++]; - eb->vma[eb->buffer_count].vma = NULL; eb->trampoline = trampoline; eb->batch_start_offset = 0; @@ -2989,6 +2962,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; + eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); + eb.vma[0].vma = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3198,6 +3173,8 @@ err_parse: if (batch->private) intel_gt_buffer_pool_put(batch->private); err_vma: + if (eb.exec) + eb_release_vmas(&eb); if (eb.trampoline) i915_vma_unpin(eb.trampoline); eb_unpin_engine(&eb); @@ -3217,7 +3194,7 @@ err_ext: static size_t eb_element_size(void) { - return sizeof(struct drm_i915_gem_exec_object2); + return sizeof(struct drm_i915_gem_exec_object2) + sizeof(struct eb_vma); } static bool check_buffer_count(size_t count) @@ -3273,7 +3250,7 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, /* Copy in the exec list from userland */ exec_list = kvmalloc_array(count, sizeof(*exec_list), __GFP_NOWARN | GFP_KERNEL); - exec2_list = kvmalloc_array(count, eb_element_size(), + exec2_list = kvmalloc_array(count + 1, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec_list == NULL || exec2_list == NULL) { drm_dbg(&i915->drm, @@ -3350,7 +3327,8 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, if (err) return err; - exec2_list = kvmalloc_array(count, eb_element_size(), + /* Allocate an extra slot for use by the command parser */ + exec2_list = kvmalloc_array(count + 1, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec2_list == NULL) { drm_dbg(&i915->drm, "Failed to allocate exec list for %zd buffers\n", -- cgit v1.2.3 From 80f0b679d6f0683f23cf98a511af3e44dd509472 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:45 +0200 Subject: drm/i915: Add an implementation for i915_gem_ww_ctx locking, v2. i915_gem_ww_ctx is used to lock all gem bo's for pinning and memory eviction. We don't use it yet, but lets start adding the definition first. To use it, we have to pass a non-NULL ww to gem_object_lock, and don't unlock directly. It is done in i915_gem_ww_ctx_fini. Changes since v1: - Change ww_ctx and obj order in locking functions (Jonas Lahtinen) Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-6-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/display/intel_display.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_client_blt.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 10 ++--- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_object.h | 38 +++++++++++++--- drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 9 ++++ drivers/gpu/drm/i915/gem/i915_gem_pm.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 2 +- .../drm/i915/gem/selftests/i915_gem_client_blt.c | 2 +- .../drm/i915/gem/selftests/i915_gem_coherency.c | 10 ++--- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 4 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 4 +- drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c | 2 +- drivers/gpu/drm/i915/gt/selftest_workarounds.c | 2 +- drivers/gpu/drm/i915/gvt/cmd_parser.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 52 ++++++++++++++++++++-- drivers/gpu/drm/i915/i915_gem.h | 11 +++++ drivers/gpu/drm/i915/selftests/i915_gem.c | 41 +++++++++++++++++ drivers/gpu/drm/i915/selftests/i915_vma.c | 2 +- .../gpu/drm/i915/selftests/intel_memory_region.c | 2 +- 22 files changed, 170 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7d50b7177d40..27c0a2140441 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2311,7 +2311,7 @@ err: void intel_unpin_fb_vma(struct i915_vma *vma, unsigned long flags) { - i915_gem_object_lock(vma->obj); + i915_gem_object_lock(vma->obj, NULL); if (flags & PLANE_HAS_FENCE) i915_vma_unpin_fence(vma); i915_gem_object_unpin_from_display_plane(vma); @@ -17194,7 +17194,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb, if (!intel_fb->frontbuffer) return -ENOMEM; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); tiling = i915_gem_object_get_tiling(obj); stride = i915_gem_object_get_stride(obj); i915_gem_object_unlock(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index 947c8aa8e13e..a85907f29c53 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -288,7 +288,7 @@ int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj, dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0); i915_sw_fence_init(&work->wait, clear_pages_work_notify); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_sw_fence_await_reservation(&work->wait, obj->base.resv, NULL, true, 0, I915_FENCE_GFP); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 2679380159fc..27fddc22a7c6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -128,7 +128,7 @@ static int i915_gem_begin_cpu_access(struct dma_buf *dma_buf, enum dma_data_dire if (err) return err; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out; @@ -149,7 +149,7 @@ static int i915_gem_end_cpu_access(struct dma_buf *dma_buf, enum dma_data_direct if (err) return err; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 7f76fc68f498..c0acfc97fae3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -32,7 +32,7 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) if (!i915_gem_object_is_framebuffer(obj)) return; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); __i915_gem_object_flush_for_display(obj); i915_gem_object_unlock(obj); } @@ -197,7 +197,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; @@ -536,7 +536,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, if (err) goto out; - err = i915_gem_object_lock_interruptible(obj); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) goto out_unpin; @@ -576,7 +576,7 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; @@ -630,7 +630,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index ccaaf9e599a0..51395a0ceb15 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1076,7 +1076,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (use_cpu_reloc(cache, obj)) return NULL; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index e5b9276d254c..488459143366 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -110,20 +110,44 @@ i915_gem_object_put(struct drm_i915_gem_object *obj) #define assert_object_held(obj) dma_resv_assert_held((obj)->base.resv) -static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj) +static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + bool intr) { - dma_resv_lock(obj->base.resv, NULL); + int ret; + + if (intr) + ret = dma_resv_lock_interruptible(obj->base.resv, ww ? &ww->ctx : NULL); + else + ret = dma_resv_lock(obj->base.resv, ww ? &ww->ctx : NULL); + + if (!ret && ww) + list_add_tail(&obj->obj_link, &ww->obj_list); + if (ret == -EALREADY) + ret = 0; + + if (ret == -EDEADLK) + ww->contended = obj; + + return ret; } -static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj) +static inline int i915_gem_object_lock(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww) { - return dma_resv_trylock(obj->base.resv); + return __i915_gem_object_lock(obj, ww, ww && ww->intr); } -static inline int -i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj) +static inline int i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww) { - return dma_resv_lock_interruptible(obj->base.resv, NULL); + WARN_ON(ww && !ww->intr); + return __i915_gem_object_lock(obj, ww, true); +} + +static inline bool i915_gem_object_trylock(struct drm_i915_gem_object *obj) +{ + return dma_resv_trylock(obj->base.resv); } static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index d0847d7896f9..b5c15557cc87 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -123,6 +123,15 @@ struct drm_i915_gem_object { struct list_head lut_list; spinlock_t lut_lock; /* guards lut_list */ + /** + * @obj_link: Link into @i915_gem_ww_ctx.obj_list + * + * When we lock this object through i915_gem_object_lock() with a + * context, we add it to the list to ensure we can unlock everything + * when i915_gem_ww_ctx_backoff() or i915_gem_ww_ctx_fini() are called. + */ + struct list_head obj_link; + /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; union { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c index 3d215164dd5a..40d3e40500fa 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c @@ -84,7 +84,7 @@ void i915_gem_suspend_late(struct drm_i915_private *i915) spin_unlock_irqrestore(&i915->mm.obj_lock, flags); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); drm_WARN_ON(&i915->drm, i915_gem_object_set_to_gtt_domain(obj, false)); i915_gem_object_unlock(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index ff72ee2fd9cd..ffcaee74a249 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -249,7 +249,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, * whilst executing a fenced command for an untiled object. */ - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); if (i915_gem_object_is_framebuffer(obj)) { i915_gem_object_unlock(obj); return -EBUSY; diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index e2f3d014acb2..68c3631f3746 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -947,7 +947,7 @@ static int gpu_write(struct intel_context *ce, { int err; - i915_gem_object_lock(vma->obj); + i915_gem_object_lock(vma->obj, NULL); err = i915_gem_object_set_to_gtt_domain(vma->obj, true); i915_gem_object_unlock(vma->obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c index 299c29e9ad86..4e36d4897ea6 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c @@ -75,7 +75,7 @@ static int __igt_client_fill(struct intel_engine_cs *engine) if (err) goto err_unpin; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 87d7d8aa080f..1de2959b153c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -82,7 +82,7 @@ static int gtt_set(struct context *ctx, unsigned long offset, u32 v) u32 __iomem *map; int err = 0; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) @@ -115,7 +115,7 @@ static int gtt_get(struct context *ctx, unsigned long offset, u32 *v) u32 __iomem *map; int err = 0; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, false); i915_gem_object_unlock(ctx->obj); if (err) @@ -147,7 +147,7 @@ static int wc_set(struct context *ctx, unsigned long offset, u32 v) u32 *map; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_wc_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) @@ -170,7 +170,7 @@ static int wc_get(struct context *ctx, unsigned long offset, u32 *v) u32 *map; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_wc_domain(ctx->obj, false); i915_gem_object_unlock(ctx->obj); if (err) @@ -193,7 +193,7 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) u32 *cs; int err; - i915_gem_object_lock(ctx->obj); + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); i915_gem_object_unlock(ctx->obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index d176b015353f..52af9a52b743 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -950,7 +950,7 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return PTR_ERR(vma); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, false); i915_gem_object_unlock(obj); if (err) @@ -1709,7 +1709,7 @@ static int read_from_scratch(struct i915_gem_context *ctx, i915_request_add(rq); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 9c7402ce5bf9..9fb95a45bcad 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -103,7 +103,7 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { @@ -188,7 +188,7 @@ static int check_partial_mappings(struct drm_i915_gem_object *obj, GEM_BUG_ON(i915_gem_object_get_tiling(obj) != tile->tiling); GEM_BUG_ON(i915_gem_object_get_stride(obj) != tile->stride); - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c index 34932871b3a5..a94243dc4c5c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_phys.c @@ -44,7 +44,7 @@ static int mock_phys_object(void *arg) } /* Make the object dirty so that put_pages must do copy back the data */ - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) { diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c index febc9e6692ba..61a0532d0f3d 100644 --- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c +++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c @@ -214,7 +214,7 @@ static int check_whitelist(struct i915_gem_context *ctx, return PTR_ERR(results); err = 0; - i915_gem_object_lock(results); + i915_gem_object_lock(results, NULL); intel_wedge_on_timeout(&wedge, engine->gt, HZ / 5) /* safety net! */ err = i915_gem_object_set_to_cpu_domain(results, false); i915_gem_object_unlock(results); diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index f1940939260a..943c8d232703 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -2982,7 +2982,7 @@ static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) goto put_obj; } - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); ret = i915_gem_object_set_to_cpu_domain(obj, false); i915_gem_object_unlock(obj); if (ret) { diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e1de50780ed5..4bc8fdb94019 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -420,7 +420,7 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj, GEM_BUG_ON(!drm_mm_node_allocated(&node)); } - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) goto out_unpin; @@ -619,7 +619,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, GEM_BUG_ON(!drm_mm_node_allocated(&node)); } - ret = i915_gem_object_lock_interruptible(obj); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) goto out_unpin; @@ -1290,7 +1290,7 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) i915_gem_drain_freed_objects(i915); list_for_each_entry(obj, &i915->mm.shrink_list, mm.link) { - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); drm_WARN_ON(&i915->drm, i915_gem_object_set_to_cpu_domain(obj, true)); i915_gem_object_unlock(obj); @@ -1326,6 +1326,52 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) return ret; } +void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr) +{ + ww_acquire_init(&ww->ctx, &reservation_ww_class); + INIT_LIST_HEAD(&ww->obj_list); + ww->intr = intr; + ww->contended = NULL; +} + +static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) +{ + struct drm_i915_gem_object *obj; + + while ((obj = list_first_entry_or_null(&ww->obj_list, struct drm_i915_gem_object, obj_link))) { + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); + } +} + +void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww) +{ + i915_gem_ww_ctx_unlock_all(ww); + WARN_ON(ww->contended); + ww_acquire_fini(&ww->ctx); +} + +int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww) +{ + int ret = 0; + + if (WARN_ON(!ww->contended)) + return -EINVAL; + + i915_gem_ww_ctx_unlock_all(ww); + if (ww->intr) + ret = dma_resv_lock_slow_interruptible(ww->contended->base.resv, &ww->ctx); + else + dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx); + + if (!ret) + list_add_tail(&ww->contended->obj_link, &ww->obj_list); + + ww->contended = NULL; + + return ret; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_gem_device.c" #include "selftests/i915_gem.c" diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index f333e88a2b6e..427ebd02fceb 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -116,4 +116,15 @@ static inline bool __tasklet_is_scheduled(struct tasklet_struct *t) return test_bit(TASKLET_STATE_SCHED, &t->state); } +struct i915_gem_ww_ctx { + struct ww_acquire_ctx ctx; + struct list_head obj_list; + bool intr; + struct drm_i915_gem_object *contended; +}; + +void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr); +void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); +int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); + #endif /* __I915_GEM_H__ */ diff --git a/drivers/gpu/drm/i915/selftests/i915_gem.c b/drivers/gpu/drm/i915/selftests/i915_gem.c index 88d400b9df88..23a6132c5f4e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem.c @@ -199,11 +199,52 @@ out: return err; } +static int igt_gem_ww_ctx(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct drm_i915_gem_object *obj, *obj2; + struct i915_gem_ww_ctx ww; + int err = 0; + + obj = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + obj2 = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto put1; + } + + i915_gem_ww_ctx_init(&ww, true); +retry: + /* Lock the objects, twice for good measure (-EALREADY handling) */ + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_gem_object_lock_interruptible(obj, &ww); + if (!err) + err = i915_gem_object_lock_interruptible(obj2, &ww); + if (!err) + err = i915_gem_object_lock(obj2, &ww); + + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + i915_gem_object_put(obj2); +put1: + i915_gem_object_put(obj); + return err; +} + int i915_gem_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { SUBTEST(igt_gem_suspend), SUBTEST(igt_gem_hibernate), + SUBTEST(igt_gem_ww_ctx), }; if (intel_gt_is_wedged(&i915->gt)) diff --git a/drivers/gpu/drm/i915/selftests/i915_vma.c b/drivers/gpu/drm/i915/selftests/i915_vma.c index af89c7fc8f59..88c5e9acb84c 100644 --- a/drivers/gpu/drm/i915/selftests/i915_vma.c +++ b/drivers/gpu/drm/i915/selftests/i915_vma.c @@ -892,7 +892,7 @@ static int igt_vma_remapped_gtt(void *arg) unsigned int x, y; int err; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); i915_gem_object_unlock(obj); if (err) diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 741270fcb6b9..93a38a323584 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -509,7 +509,7 @@ static int igt_lmem_write_cpu(void *arg) if (err) goto out_unpin; - i915_gem_object_lock(obj); + i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_wc_domain(obj, true); i915_gem_object_unlock(obj); if (err) -- cgit v1.2.3 From 1af343cdc1971ff953f08f9dcf0efad464cf057f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:46 +0200 Subject: drm/i915: Remove locking from i915_gem_object_prepare_read/write Execbuffer submission will perform its own WW locking, and we cannot rely on the implicit lock there. This also makes it clear that the GVT code will get a lockdep splat when multiple batchbuffer shadows need to be performed in the same instance, fix that up. Signed-off-by: Maarten Lankhorst Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-7-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 20 ++++++-------------- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 13 +++++++++++-- drivers/gpu/drm/i915/gem/i915_gem_object.h | 1 - drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 5 ++++- .../gpu/drm/i915/gem/selftests/i915_gem_coherency.c | 14 ++++++++++---- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 12 +++++++++--- drivers/gpu/drm/i915/gvt/cmd_parser.c | 1 + drivers/gpu/drm/i915/i915_gem.c | 20 ++++++++++++++++++-- 8 files changed, 59 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index c0acfc97fae3..8ebceebd11b0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -576,19 +576,17 @@ int i915_gem_object_prepare_read(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; + assert_object_held(obj); ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); if (ret) - goto err_unlock; + return ret; ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_unlock; + return ret; if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ || !static_cpu_has(X86_FEATURE_CLFLUSH)) { @@ -616,8 +614,6 @@ out: err_unpin: i915_gem_object_unpin_pages(obj); -err_unlock: - i915_gem_object_unlock(obj); return ret; } @@ -630,20 +626,18 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj, if (!i915_gem_object_has_struct_page(obj)) return -ENODEV; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; + assert_object_held(obj); ret = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL, MAX_SCHEDULE_TIMEOUT); if (ret) - goto err_unlock; + return ret; ret = i915_gem_object_pin_pages(obj); if (ret) - goto err_unlock; + return ret; if (obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE || !static_cpu_has(X86_FEATURE_CLFLUSH)) { @@ -680,7 +674,5 @@ out: err_unpin: i915_gem_object_unpin_pages(obj); -err_unlock: - i915_gem_object_unlock(obj); return ret; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 51395a0ceb15..ac2001f10b61 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -991,11 +991,14 @@ static void reloc_cache_reset(struct reloc_cache *cache) vaddr = unmask_page(cache->vaddr); if (cache->vaddr & KMAP) { + struct drm_i915_gem_object *obj = + (struct drm_i915_gem_object *)cache->node.mm; if (cache->vaddr & CLFLUSH_AFTER) mb(); kunmap_atomic(vaddr); - i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm); + i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); } else { struct i915_ggtt *ggtt = cache_to_ggtt(cache); @@ -1031,10 +1034,16 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, unsigned int flushes; int err; - err = i915_gem_object_prepare_write(obj, &flushes); + err = i915_gem_object_lock_interruptible(obj, NULL); if (err) return ERR_PTR(err); + err = i915_gem_object_prepare_write(obj, &flushes); + if (err) { + i915_gem_object_unlock(obj); + return ERR_PTR(err); + } + BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 488459143366..45d79d75e73a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -432,7 +432,6 @@ static inline void i915_gem_object_finish_access(struct drm_i915_gem_object *obj) { i915_gem_object_unpin_pages(obj); - i915_gem_object_unlock(obj); } static inline struct intel_engine_cs * diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 68c3631f3746..5daf4a2be422 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -964,9 +964,10 @@ __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val) unsigned long n; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_read(obj, &needs_flush); if (err) - return err; + goto err_unlock; for (n = 0; n < obj->base.size >> PAGE_SHIFT; ++n) { u32 *ptr = kmap_atomic(i915_gem_object_get_page(obj, n)); @@ -986,6 +987,8 @@ __cpu_check_shmem(struct drm_i915_gem_object *obj, u32 dword, u32 val) } i915_gem_object_finish_access(obj); +err_unlock: + i915_gem_object_unlock(obj); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index 1de2959b153c..dcdfc396f2f8 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -27,9 +27,10 @@ static int cpu_set(struct context *ctx, unsigned long offset, u32 v) u32 *cpu; int err; + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_prepare_write(ctx->obj, &needs_clflush); if (err) - return err; + goto out; page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT); map = kmap_atomic(page); @@ -46,7 +47,9 @@ static int cpu_set(struct context *ctx, unsigned long offset, u32 v) kunmap_atomic(map); i915_gem_object_finish_access(ctx->obj); - return 0; +out: + i915_gem_object_unlock(ctx->obj); + return err; } static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) @@ -57,9 +60,10 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) u32 *cpu; int err; + i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_prepare_read(ctx->obj, &needs_clflush); if (err) - return err; + goto out; page = i915_gem_object_get_page(ctx->obj, offset >> PAGE_SHIFT); map = kmap_atomic(page); @@ -73,7 +77,9 @@ static int cpu_get(struct context *ctx, unsigned long offset, u32 *v) kunmap_atomic(map); i915_gem_object_finish_access(ctx->obj); - return 0; +out: + i915_gem_object_unlock(ctx->obj); + return err; } static int gtt_set(struct context *ctx, unsigned long offset, u32 v) diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 52af9a52b743..9160a335c684 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -461,9 +461,10 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) unsigned int n, m, need_flush; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_write(obj, &need_flush); if (err) - return err; + goto out; for (n = 0; n < real_page_count(obj); n++) { u32 *map; @@ -479,7 +480,9 @@ static int cpu_fill(struct drm_i915_gem_object *obj, u32 value) i915_gem_object_finish_access(obj); obj->read_domains = I915_GEM_DOMAIN_GTT | I915_GEM_DOMAIN_CPU; obj->write_domain = 0; - return 0; +out: + i915_gem_object_unlock(obj); + return err; } static noinline int cpu_check(struct drm_i915_gem_object *obj, @@ -488,9 +491,10 @@ static noinline int cpu_check(struct drm_i915_gem_object *obj, unsigned int n, m, needs_flush; int err; + i915_gem_object_lock(obj, NULL); err = i915_gem_object_prepare_read(obj, &needs_flush); if (err) - return err; + goto out_unlock; for (n = 0; n < real_page_count(obj); n++) { u32 *map; @@ -527,6 +531,8 @@ out_unmap: } i915_gem_object_finish_access(obj); +out_unlock: + i915_gem_object_unlock(obj); return err; } diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 943c8d232703..d0a599b51bfe 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1923,6 +1923,7 @@ static int perform_bb_shadow(struct parser_exec_state *s) if (ret) goto err_unmap; + i915_gem_object_unlock(bb->obj); INIT_LIST_HEAD(&bb->list); list_add(&bb->list, &s->workload->shadow_bb); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4bc8fdb94019..55158e487a7f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -335,12 +335,20 @@ i915_gem_shmem_pread(struct drm_i915_gem_object *obj, u64 remain; int ret; - ret = i915_gem_object_prepare_read(obj, &needs_clflush); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; + ret = i915_gem_object_prepare_read(obj, &needs_clflush); + if (ret) { + i915_gem_object_unlock(obj); + return ret; + } + fence = i915_gem_object_lock_fence(obj); i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); + if (!fence) return -ENOMEM; @@ -734,12 +742,20 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj, u64 remain; int ret; - ret = i915_gem_object_prepare_write(obj, &needs_clflush); + ret = i915_gem_object_lock_interruptible(obj, NULL); if (ret) return ret; + ret = i915_gem_object_prepare_write(obj, &needs_clflush); + if (ret) { + i915_gem_object_unlock(obj); + return ret; + } + fence = i915_gem_object_lock_fence(obj); i915_gem_object_finish_access(obj); + i915_gem_object_unlock(obj); + if (!fence) return -ENOMEM; -- cgit v1.2.3 From 8e4ba491b0ba6fef69270d3c4e48fc517096ef41 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:47 +0200 Subject: drm/i915: Parse command buffer earlier in eb_relocate(slow) We want to introduce backoff logic, but we need to lock the pool object as well for command parsing. Because of this, we will need backoff logic for the engine pool obj, move the batch validation up slightly to eb_lookup_vmas, and the actual command parsing in a separate function which can get called from execbuf relocation fast and slowpath. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-8-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 68 ++++++++++++++------------ 1 file changed, 37 insertions(+), 31 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index ac2001f10b61..c34e55cff73d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -296,6 +296,8 @@ struct i915_execbuffer { unsigned long num_fences; }; +static int eb_parse(struct i915_execbuffer *eb); + static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { return intel_engine_requires_cmd_parser(eb->engine) || @@ -843,6 +845,7 @@ static struct i915_vma *eb_lookup_vma(struct i915_execbuffer *eb, u32 handle) static int eb_lookup_vmas(struct i915_execbuffer *eb) { + struct drm_i915_private *i915 = eb->i915; unsigned int batch = eb_batch_index(eb); unsigned int i; int err = 0; @@ -856,18 +859,37 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) vma = eb_lookup_vma(eb, eb->exec[i].handle); if (IS_ERR(vma)) { err = PTR_ERR(vma); - break; + goto err; } err = eb_validate_vma(eb, &eb->exec[i], vma); if (unlikely(err)) { i915_vma_put(vma); - break; + goto err; } eb_add_vma(eb, i, batch, vma); } + if (unlikely(eb->batch->flags & EXEC_OBJECT_WRITE)) { + drm_dbg(&i915->drm, + "Attempting to use self-modifying batch buffer\n"); + return -EINVAL; + } + + if (range_overflows_t(u64, + eb->batch_start_offset, eb->batch_len, + eb->batch->vma->size)) { + drm_dbg(&i915->drm, "Attempting to use out-of-bounds batch\n"); + return -EINVAL; + } + + if (eb->batch_len == 0) + eb->batch_len = eb->batch->vma->size - eb->batch_start_offset; + + return 0; + +err: eb->vma[i].vma = NULL; return err; } @@ -1802,7 +1824,7 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) return 0; } -static noinline int eb_relocate_slow(struct i915_execbuffer *eb) +static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) { bool have_copy = false; struct eb_vma *ev; @@ -1867,6 +1889,11 @@ repeat: if (err) goto err; + /* as last step, parse the command buffer */ + err = eb_parse(eb); + if (err) + goto err; + /* * Leave the user relocations as are, this is the painfully slow path, * and we want to avoid the complication of dropping the lock whilst @@ -1899,7 +1926,7 @@ out: return err; } -static int eb_relocate(struct i915_execbuffer *eb) +static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; @@ -1924,10 +1951,10 @@ static int eb_relocate(struct i915_execbuffer *eb) } if (err) - return eb_relocate_slow(eb); + return eb_relocate_parse_slow(eb); } - return 0; + return eb_parse(eb); } static int eb_move_to_gpu(struct i915_execbuffer *eb) @@ -3045,7 +3072,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_context; - err = eb_relocate(&eb); + err = eb_relocate_parse(&eb); if (err) { /* * If the user expects the execobject.offset and @@ -3058,33 +3085,10 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_vma; } - if (unlikely(eb.batch->flags & EXEC_OBJECT_WRITE)) { - drm_dbg(&i915->drm, - "Attempting to use self-modifying batch buffer\n"); - err = -EINVAL; - goto err_vma; - } - - if (range_overflows_t(u64, - eb.batch_start_offset, eb.batch_len, - eb.batch->vma->size)) { - drm_dbg(&i915->drm, "Attempting to use out-of-bounds batch\n"); - err = -EINVAL; - goto err_vma; - } - - if (eb.batch_len == 0) - eb.batch_len = eb.batch->vma->size - eb.batch_start_offset; - - err = eb_parse(&eb); - if (err) - goto err_vma; - /* * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. * hsw should have this fixed, but bdw mucks it up again. */ - batch = eb.batch->vma; if (eb.batch_flags & I915_DISPATCH_SECURE) { struct i915_vma *vma; @@ -3098,13 +3102,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, * fitting due to fragmentation. * So this is actually safe. */ - vma = i915_gem_object_ggtt_pin(batch->obj, NULL, 0, 0, 0); + vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { err = PTR_ERR(vma); goto err_parse; } batch = vma; + } else { + batch = eb.batch->vma; } /* All GPU relocation batches must be submitted prior to the user rq */ -- cgit v1.2.3 From c43ce12328df0770ce899feabdf9c430c54c766a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:48 +0200 Subject: drm/i915: Use per object locking in execbuf, v12. Now that we changed execbuf submission slightly to allow us to do all pinning in one place, we can now simply add ww versions on top of struct_mutex. All we have to do is a separate path for -EDEADLK handling, which needs to unpin all gem bo's before dropping the lock, then starting over. This finally allows us to do parallel submission, but because not all of the pinning code uses the ww ctx yet, we cannot completely drop struct_mutex yet. Changes since v1: - Keep struct_mutex for now. :( Changes since v2: - Make sure we always lock the ww context in slowpath. Changes since v3: - Don't call __eb_unreserve_vma in eb_move_to_gpu now; this can be done on normal unlock path. - Unconditionally release vmas and context. Changes since v4: - Rebased on top of struct_mutex reduction. Changes since v5: - Remove training wheels. Changes since v6: - Fix accidentally broken -ENOSPC handling. Changes since v7: - Handle gt buffer pool better. Changes since v8: - Properly clear variables, to make -EDEADLK handling not BUG. Change since v9: - Fix unpinning fence on pnv and below. Changes since v10: - Make relocation gpu chaining working again. Changes since v11: - Remove relocation chaining, pain to make it work. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-9-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 363 ++++++++++++--------- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 62 ++-- drivers/gpu/drm/i915/i915_gem.c | 6 + drivers/gpu/drm/i915/i915_gem.h | 1 + 4 files changed, 262 insertions(+), 170 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index c34e55cff73d..13b996830e25 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -257,6 +257,8 @@ struct i915_execbuffer { /** list of vma that have execobj.relocation_count */ struct list_head relocs; + struct i915_gem_ww_ctx ww; + /** * Track the most recently used object for relocations, as we * frequently have to perform multiple relocations within the same @@ -275,14 +277,18 @@ struct i915_execbuffer { struct i915_request *rq; u32 *rq_cmd; unsigned int rq_size; + struct intel_gt_buffer_pool_node *pool; } reloc_cache; + struct intel_gt_buffer_pool_node *reloc_pool; /** relocation pool for -EDEADLK handling */ + u64 invalid_flags; /** Set of execobj.flags that are invalid */ u32 context_flags; /** Set of execobj.flags to insert from the ctx */ u32 batch_start_offset; /** Location within object of batch */ u32 batch_len; /** Length of batch within object */ u32 batch_flags; /** Flags composed for emit_bb_start() */ + struct intel_gt_buffer_pool_node *batch_pool; /** pool node for batch buffer */ /** * Indicate either the size of the hastable used to resolve @@ -452,23 +458,16 @@ eb_pin_vma(struct i915_execbuffer *eb, return !eb_vma_misplaced(entry, vma, ev->flags); } -static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags) -{ - GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN)); - - if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE)) - __i915_vma_unpin_fence(vma); - - __i915_vma_unpin(vma); -} - static inline void eb_unreserve_vma(struct eb_vma *ev) { if (!(ev->flags & __EXEC_OBJECT_HAS_PIN)) return; - __eb_unreserve_vma(ev->vma, ev->flags); + if (unlikely(ev->flags & __EXEC_OBJECT_HAS_FENCE)) + __i915_vma_unpin_fence(ev->vma); + + __i915_vma_unpin(ev->vma); ev->flags &= ~__EXEC_OBJECT_RESERVED; } @@ -563,16 +562,6 @@ eb_add_vma(struct i915_execbuffer *eb, eb->batch = ev; } - - if (eb_pin_vma(eb, entry, ev)) { - if (entry->offset != vma->node.start) { - entry->offset = vma->node.start | UPDATE; - eb->args->flags |= __EXEC_HAS_RELOC; - } - } else { - eb_unreserve_vma(ev); - list_add_tail(&ev->bind_link, &eb->unbound); - } } static inline int use_cpu_reloc(const struct reloc_cache *cache, @@ -657,10 +646,6 @@ static int eb_reserve(struct i915_execbuffer *eb) * This avoid unnecessary unbinding of later objects in order to make * room for the earlier objects *unless* we need to defragment. */ - - if (mutex_lock_interruptible(&eb->i915->drm.struct_mutex)) - return -EINTR; - pass = 0; do { list_for_each_entry(ev, &eb->unbound, bind_link) { @@ -669,7 +654,7 @@ static int eb_reserve(struct i915_execbuffer *eb) break; } if (err != -ENOSPC) - break; + return err; /* Resort *all* the objects into priority order */ INIT_LIST_HEAD(&eb->unbound); @@ -709,20 +694,15 @@ static int eb_reserve(struct i915_execbuffer *eb) err = i915_gem_evict_vm(eb->context->vm); mutex_unlock(&eb->context->vm->mutex); if (err) - goto unlock; + return err; break; default: - err = -ENOSPC; - goto unlock; + return -ENOSPC; } pin_flags = PIN_USER; } while (1); - -unlock: - mutex_unlock(&eb->i915->drm.struct_mutex); - return err; } static unsigned int eb_batch_index(const struct i915_execbuffer *eb) @@ -851,7 +831,6 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) int err = 0; INIT_LIST_HEAD(&eb->relocs); - INIT_LIST_HEAD(&eb->unbound); for (i = 0; i < eb->buffer_count; i++) { struct i915_vma *vma; @@ -894,6 +873,48 @@ err: return err; } +static int eb_validate_vmas(struct i915_execbuffer *eb) +{ + unsigned int i; + int err; + + INIT_LIST_HEAD(&eb->unbound); + + for (i = 0; i < eb->buffer_count; i++) { + struct drm_i915_gem_exec_object2 *entry = &eb->exec[i]; + struct eb_vma *ev = &eb->vma[i]; + struct i915_vma *vma = ev->vma; + + err = i915_gem_object_lock(vma->obj, &eb->ww); + if (err) + return err; + + if (eb_pin_vma(eb, entry, ev)) { + if (entry->offset != vma->node.start) { + entry->offset = vma->node.start | UPDATE; + eb->args->flags |= __EXEC_HAS_RELOC; + } + } else { + eb_unreserve_vma(ev); + + list_add_tail(&ev->bind_link, &eb->unbound); + if (drm_mm_node_allocated(&vma->node)) { + err = i915_vma_unbind(vma); + if (err) + return err; + } + } + + GEM_BUG_ON(drm_mm_node_allocated(&vma->node) && + eb_vma_misplaced(&eb->exec[i], vma, ev->flags)); + } + + if (!list_empty(&eb->unbound)) + return eb_reserve(eb); + + return 0; +} + static struct eb_vma * eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) { @@ -914,7 +935,7 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } -static void eb_release_vmas(const struct i915_execbuffer *eb) +static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) { const unsigned int count = eb->buffer_count; unsigned int i; @@ -926,12 +947,10 @@ static void eb_release_vmas(const struct i915_execbuffer *eb) if (!vma) break; - eb->vma[i].vma = NULL; - - if (ev->flags & __EXEC_OBJECT_HAS_PIN) - __eb_unreserve_vma(vma, ev->flags); + eb_unreserve_vma(ev); - i915_vma_put(vma); + if (final) + i915_vma_put(vma); } } @@ -950,6 +969,14 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc, return gen8_canonical_addr((int)reloc->delta + target->node.start); } +static void reloc_cache_clear(struct reloc_cache *cache) +{ + cache->rq = NULL; + cache->rq_cmd = NULL; + cache->pool = NULL; + cache->rq_size = 0; +} + static void reloc_cache_init(struct reloc_cache *cache, struct drm_i915_private *i915) { @@ -962,8 +989,7 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->has_fence = cache->gen < 4; cache->needs_unfenced = INTEL_INFO(i915)->unfenced_needs_alignment; cache->node.flags = 0; - cache->rq = NULL; - cache->rq_size = 0; + reloc_cache_clear(cache); } static inline void *unmask_page(unsigned long p) @@ -985,7 +1011,23 @@ static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) return &i915->ggtt; } -static void reloc_gpu_flush(struct reloc_cache *cache) +static void reloc_cache_put_pool(struct i915_execbuffer *eb, struct reloc_cache *cache) +{ + if (!cache->pool) + return; + + /* + * This is a bit nasty, normally we keep objects locked until the end + * of execbuffer, but we already submit this, and have to unlock before + * dropping the reference. Fortunately we can only hold 1 pool node at + * a time, so this should be harmless. + */ + i915_gem_ww_unlock_single(cache->pool->obj); + intel_gt_buffer_pool_put(cache->pool); + cache->pool = NULL; +} + +static void reloc_gpu_flush(struct i915_execbuffer *eb, struct reloc_cache *cache) { struct drm_i915_gem_object *obj = cache->rq->batch->obj; @@ -998,15 +1040,18 @@ static void reloc_gpu_flush(struct reloc_cache *cache) intel_gt_chipset_flush(cache->rq->engine->gt); i915_request_add(cache->rq); - cache->rq = NULL; + reloc_cache_put_pool(eb, cache); + reloc_cache_clear(cache); + + eb->reloc_pool = NULL; } -static void reloc_cache_reset(struct reloc_cache *cache) +static void reloc_cache_reset(struct reloc_cache *cache, struct i915_execbuffer *eb) { void *vaddr; if (cache->rq) - reloc_gpu_flush(cache); + reloc_gpu_flush(eb, cache); if (!cache->vaddr) return; @@ -1020,7 +1065,6 @@ static void reloc_cache_reset(struct reloc_cache *cache) kunmap_atomic(vaddr); i915_gem_object_finish_access(obj); - i915_gem_object_unlock(obj); } else { struct i915_ggtt *ggtt = cache_to_ggtt(cache); @@ -1056,16 +1100,10 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, unsigned int flushes; int err; - err = i915_gem_object_lock_interruptible(obj, NULL); + err = i915_gem_object_prepare_write(obj, &flushes); if (err) return ERR_PTR(err); - err = i915_gem_object_prepare_write(obj, &flushes); - if (err) { - i915_gem_object_unlock(obj); - return ERR_PTR(err); - } - BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); @@ -1107,9 +1145,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (use_cpu_reloc(cache, obj)) return NULL; - i915_gem_object_lock(obj, NULL); err = i915_gem_object_set_to_gtt_domain(obj, true); - i915_gem_object_unlock(obj); if (err) return ERR_PTR(err); @@ -1198,7 +1234,7 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) struct drm_i915_gem_object *obj = vma->obj; int err; - i915_vma_lock(vma); + assert_vma_held(vma); if (obj->cache_dirty & ~obj->cache_coherent) i915_gem_clflush_object(obj, 0); @@ -1208,8 +1244,6 @@ static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - return err; } @@ -1219,15 +1253,22 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, unsigned int len) { struct reloc_cache *cache = &eb->reloc_cache; - struct intel_gt_buffer_pool_node *pool; + struct intel_gt_buffer_pool_node *pool = eb->reloc_pool; struct i915_request *rq; struct i915_vma *batch; u32 *cmd; int err; - pool = intel_gt_get_buffer_pool(engine->gt, PAGE_SIZE); - if (IS_ERR(pool)) - return PTR_ERR(pool); + if (!pool) { + pool = intel_gt_get_buffer_pool(engine->gt, PAGE_SIZE); + if (IS_ERR(pool)) + return PTR_ERR(pool); + } + eb->reloc_pool = NULL; + + err = i915_gem_object_lock(pool->obj, &eb->ww); + if (err) + goto err_pool; cmd = i915_gem_object_pin_map(pool->obj, cache->has_llc ? @@ -1235,7 +1276,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, I915_MAP_FORCE_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_pool; + goto err_pool; } batch = i915_vma_instance(pool->obj, vma->vm, NULL); @@ -1284,11 +1325,10 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (err) goto skip_request; - i915_vma_lock(batch); + assert_vma_held(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); if (err) goto skip_request; @@ -1298,9 +1338,10 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, cache->rq = rq; cache->rq_cmd = cmd; cache->rq_size = 0; + cache->pool = pool; /* Return with batch mapping (cmd) still pinned */ - goto out_pool; + return 0; skip_request: i915_request_set_error_once(rq, err); @@ -1310,8 +1351,8 @@ err_unpin: i915_vma_unpin(batch); err_unmap: i915_gem_object_unpin_map(pool->obj); -out_pool: - intel_gt_buffer_pool_put(pool); +err_pool: + eb->reloc_pool = pool; return err; } @@ -1328,7 +1369,7 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, u32 *cmd; if (cache->rq_size > PAGE_SIZE/sizeof(u32) - (len + 1)) - reloc_gpu_flush(cache); + reloc_gpu_flush(eb, cache); if (unlikely(!cache->rq)) { int err; @@ -1376,7 +1417,7 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static bool __reloc_entry_gpu(struct i915_execbuffer *eb, +static int __reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1394,7 +1435,9 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, len = 3; batch = reloc_gpu(eb, vma, len); - if (IS_ERR(batch)) + if (batch == ERR_PTR(-EDEADLK)) + return (s64)-EDEADLK; + else if (IS_ERR(batch)) return false; addr = gen8_canonical_addr(vma->node.start + offset); @@ -1447,7 +1490,7 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, return true; } -static bool reloc_entry_gpu(struct i915_execbuffer *eb, +static int reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1469,8 +1512,12 @@ relocate_entry(struct i915_vma *vma, { u64 target_addr = relocation_target(reloc, target); u64 offset = reloc->offset; + int reloc_gpu = reloc_entry_gpu(eb, vma, offset, target_addr); + + if (reloc_gpu < 0) + return reloc_gpu; - if (!reloc_entry_gpu(eb, vma, offset, target_addr)) { + if (!reloc_gpu) { bool wide = eb->reloc_cache.use_64bit_reloc; void *vaddr; @@ -1673,7 +1720,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) urelocs += ARRAY_SIZE(stack); } while (remain); out: - reloc_cache_reset(&eb->reloc_cache); + reloc_cache_reset(&eb->reloc_cache, eb); return remain; } @@ -1696,7 +1743,7 @@ eb_relocate_vma_slow(struct i915_execbuffer *eb, struct eb_vma *ev) } err = 0; err: - reloc_cache_reset(&eb->reloc_cache); + reloc_cache_reset(&eb->reloc_cache, eb); return err; } @@ -1836,6 +1883,10 @@ repeat: goto out; } + /* We may process another execbuffer during the unlock... */ + eb_release_vmas(eb, false); + i915_gem_ww_ctx_fini(&eb->ww); + /* * We take 3 passes through the slowpatch. * @@ -1861,12 +1912,17 @@ repeat: flush_workqueue(eb->i915->mm.userptr_wq); + i915_gem_ww_ctx_init(&eb->ww, true); if (err) goto out; - err = mutex_lock_interruptible(&eb->i915->drm.struct_mutex); + /* reacquire the objects */ +repeat_validate: + err = eb_validate_vmas(eb); if (err) - goto out; + goto err; + + GEM_BUG_ON(!eb->batch); list_for_each_entry(ev, &eb->relocs, reloc_link) { if (!have_copy) { @@ -1882,7 +1938,9 @@ repeat: } } - mutex_unlock(&eb->i915->drm.struct_mutex); + if (err == -EDEADLK) + goto err; + if (err && !have_copy) goto repeat; @@ -1902,6 +1960,13 @@ repeat: */ err: + if (err == -EDEADLK) { + eb_release_vmas(eb, false); + err = i915_gem_ww_ctx_backoff(&eb->ww); + if (!err) + goto repeat_validate; + } + if (err == -EAGAIN) goto repeat; @@ -1930,15 +1995,12 @@ static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; - err = eb_lookup_vmas(eb); - if (err) - return err; - - if (!list_empty(&eb->unbound)) { - err = eb_reserve(eb); - if (err) - return err; - } +retry: + err = eb_validate_vmas(eb); + if (err == -EAGAIN) + goto slow; + else if (err) + goto err; /* The objects are in their final locations, apply the relocations. */ if (eb->args->flags & __EXEC_HAS_RELOC) { @@ -1950,45 +2012,46 @@ static int eb_relocate_parse(struct i915_execbuffer *eb) break; } - if (err) - return eb_relocate_parse_slow(eb); + if (err == -EDEADLK) + goto err; + else if (err) + goto slow; + } + + if (!err) + err = eb_parse(eb); + +err: + if (err == -EDEADLK) { + eb_release_vmas(eb, false); + err = i915_gem_ww_ctx_backoff(&eb->ww); + if (!err) + goto retry; } - return eb_parse(eb); + return err; + +slow: + err = eb_relocate_parse_slow(eb); + if (err) + /* + * If the user expects the execobject.offset and + * reloc.presumed_offset to be an exact match, + * as for using NO_RELOC, then we cannot update + * the execobject.offset until we have completed + * relocation. + */ + eb->args->flags &= ~__EXEC_HAS_RELOC; + + return err; } static int eb_move_to_gpu(struct i915_execbuffer *eb) { const unsigned int count = eb->buffer_count; - struct ww_acquire_ctx acquire; - unsigned int i; + unsigned int i = count; int err = 0; - ww_acquire_init(&acquire, &reservation_ww_class); - - for (i = 0; i < count; i++) { - struct eb_vma *ev = &eb->vma[i]; - struct i915_vma *vma = ev->vma; - - err = ww_mutex_lock_interruptible(&vma->resv->lock, &acquire); - if (err == -EDEADLK) { - GEM_BUG_ON(i == 0); - do { - int j = i - 1; - - ww_mutex_unlock(&eb->vma[j].vma->resv->lock); - - swap(eb->vma[i], eb->vma[j]); - } while (--i); - - err = ww_mutex_lock_slow_interruptible(&vma->resv->lock, - &acquire); - } - if (err) - break; - } - ww_acquire_done(&acquire); - while (i--) { struct eb_vma *ev = &eb->vma[i]; struct i915_vma *vma = ev->vma; @@ -2032,10 +2095,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) if (err == 0) err = i915_vma_move_to_active(vma, eb->request, flags); - - i915_vma_unlock(vma); } - ww_acquire_fini(&acquire); if (unlikely(err)) goto err_skip; @@ -2227,36 +2287,26 @@ static int eb_parse_pipeline(struct i915_execbuffer *eb, if (err) goto err_commit; - err = dma_resv_lock_interruptible(pw->batch->resv, NULL); - if (err) - goto err_commit; - err = dma_resv_reserve_shared(pw->batch->resv, 1); if (err) - goto err_commit_unlock; + goto err_commit; /* Wait for all writes (and relocs) into the batch to complete */ err = i915_sw_fence_await_reservation(&pw->base.chain, pw->batch->resv, NULL, false, 0, I915_FENCE_GFP); if (err < 0) - goto err_commit_unlock; + goto err_commit; /* Keep the batch alive and unwritten as we parse */ dma_resv_add_shared_fence(pw->batch->resv, &pw->base.dma); - dma_resv_unlock(pw->batch->resv); - /* Force execution to wait for completion of the parser */ - dma_resv_lock(shadow->resv, NULL); dma_resv_add_excl_fence(shadow->resv, &pw->base.dma); - dma_resv_unlock(shadow->resv); dma_fence_work_commit_imm(&pw->base); return 0; -err_commit_unlock: - dma_resv_unlock(pw->batch->resv); err_commit: i915_sw_fence_set_error_once(&pw->base.chain, err); dma_fence_work_commit_imm(&pw->base); @@ -2274,7 +2324,7 @@ err_free: static int eb_parse(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; - struct intel_gt_buffer_pool_node *pool; + struct intel_gt_buffer_pool_node *pool = eb->batch_pool; struct i915_vma *shadow, *trampoline; unsigned int len; int err; @@ -2297,9 +2347,16 @@ static int eb_parse(struct i915_execbuffer *eb) len += I915_CMD_PARSER_TRAMPOLINE_SIZE; } - pool = intel_gt_get_buffer_pool(eb->engine->gt, len); - if (IS_ERR(pool)) - return PTR_ERR(pool); + if (!pool) { + pool = intel_gt_get_buffer_pool(eb->engine->gt, len); + if (IS_ERR(pool)) + return PTR_ERR(pool); + eb->batch_pool = pool; + } + + err = i915_gem_object_lock(pool->obj, &eb->ww); + if (err) + goto err; shadow = shadow_batch_pin(pool->obj, eb->context->vm, PIN_USER); if (IS_ERR(shadow)) { @@ -2345,7 +2402,6 @@ err_trampoline: err_shadow: i915_vma_unpin(shadow); err: - intel_gt_buffer_pool_put(pool); return err; } @@ -3000,6 +3056,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.exec = exec; eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); eb.vma[0].vma = NULL; + eb.reloc_pool = eb.batch_pool = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3072,6 +3129,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_context; + err = eb_lookup_vmas(&eb); + if (err) { + eb_release_vmas(&eb, true); + goto err_engine; + } + + i915_gem_ww_ctx_init(&eb.ww, true); + err = eb_relocate_parse(&eb); if (err) { /* @@ -3085,6 +3150,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, goto err_vma; } + ww_acquire_done(&eb.ww.ctx); + /* * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure * batch" bit. Hence we need to pin secure batches into the global gtt. @@ -3105,7 +3172,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); if (IS_ERR(vma)) { err = PTR_ERR(vma); - goto err_parse; + goto err_vma; } batch = vma; @@ -3157,8 +3224,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, * to explicitly hold another reference here. */ eb.request->batch = batch; - if (batch->private) - intel_gt_buffer_pool_mark_active(batch->private, eb.request); + if (eb.batch_pool) + intel_gt_buffer_pool_mark_active(eb.batch_pool, eb.request); trace_i915_request_queue(eb.request, eb.batch_flags); err = eb_submit(&eb, batch); @@ -3184,14 +3251,18 @@ err_request: err_batch_unpin: if (eb.batch_flags & I915_DISPATCH_SECURE) i915_vma_unpin(batch); -err_parse: - if (batch->private) - intel_gt_buffer_pool_put(batch->private); err_vma: - if (eb.exec) - eb_release_vmas(&eb); + eb_release_vmas(&eb, true); if (eb.trampoline) i915_vma_unpin(eb.trampoline); + WARN_ON(err == -EDEADLK); + i915_gem_ww_ctx_fini(&eb.ww); + + if (eb.batch_pool) + intel_gt_buffer_pool_put(eb.batch_pool); + if (eb.reloc_pool) + intel_gt_buffer_pool_put(eb.reloc_pool); +err_engine: eb_unpin_engine(&eb); err_context: i915_gem_context_put(eb.gem_context); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 580884cffec3..bc08c02b5767 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -32,25 +32,23 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, if (IS_ERR(vma)) return PTR_ERR(vma); + err = i915_gem_object_lock(obj, &eb->ww); + if (err) + return err; + err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH); if (err) return err; /* 8-Byte aligned */ - if (!__reloc_entry_gpu(eb, vma, - offsets[0] * sizeof(u32), - 0)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0); + if (err <= 0) + goto reloc_err; /* !8-Byte aligned */ - if (!__reloc_entry_gpu(eb, vma, - offsets[1] * sizeof(u32), - 1)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1); + if (err <= 0) + goto reloc_err; /* Skip to the end of the cmd page */ i = PAGE_SIZE / sizeof(u32) - 1; @@ -60,16 +58,13 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, eb->reloc_cache.rq_size += i; /* Force next batch */ - if (!__reloc_entry_gpu(eb, vma, - offsets[2] * sizeof(u32), - 2)) { - err = -EIO; - goto unpin_vma; - } + err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2); + if (err <= 0) + goto reloc_err; GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); - reloc_gpu_flush(&eb->reloc_cache); + reloc_gpu_flush(eb, &eb->reloc_cache); GEM_BUG_ON(eb->reloc_cache.rq); err = i915_gem_object_wait(obj, I915_WAIT_INTERRUPTIBLE, HZ / 2); @@ -101,6 +96,11 @@ put_rq: unpin_vma: i915_vma_unpin(vma); return err; + +reloc_err: + if (!err) + err = -EIO; + goto unpin_vma; } static int igt_gpu_reloc(void *arg) @@ -122,6 +122,8 @@ static int igt_gpu_reloc(void *arg) goto err_scratch; } + intel_gt_pm_get(&eb.i915->gt); + for_each_uabi_engine(eb.engine, eb.i915) { reloc_cache_init(&eb.reloc_cache, eb.i915); memset(map, POISON_INUSE, 4096); @@ -132,15 +134,26 @@ static int igt_gpu_reloc(void *arg) err = PTR_ERR(eb.context); goto err_pm; } + eb.reloc_pool = NULL; + i915_gem_ww_ctx_init(&eb.ww, false); +retry: err = intel_context_pin(eb.context); - if (err) - goto err_put; + if (!err) { + err = __igt_gpu_reloc(&eb, scratch); + + intel_context_unpin(eb.context); + } + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&eb.ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&eb.ww); - err = __igt_gpu_reloc(&eb, scratch); + if (eb.reloc_pool) + intel_gt_buffer_pool_put(eb.reloc_pool); - intel_context_unpin(eb.context); -err_put: intel_context_put(eb.context); err_pm: intel_engine_pm_put(eb.engine); @@ -151,6 +164,7 @@ err_pm: if (igt_flush_test(eb.i915)) err = -EIO; + intel_gt_pm_put(&eb.i915->gt); err_scratch: i915_gem_object_put(scratch); return err; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 55158e487a7f..f6615d942b60 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1360,6 +1360,12 @@ static void i915_gem_ww_ctx_unlock_all(struct i915_gem_ww_ctx *ww) } } +void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj) +{ + list_del(&obj->obj_link); + i915_gem_object_unlock(obj); +} + void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ww) { i915_gem_ww_ctx_unlock_all(ww); diff --git a/drivers/gpu/drm/i915/i915_gem.h b/drivers/gpu/drm/i915/i915_gem.h index 427ebd02fceb..a4cad3f154ca 100644 --- a/drivers/gpu/drm/i915/i915_gem.h +++ b/drivers/gpu/drm/i915/i915_gem.h @@ -126,5 +126,6 @@ struct i915_gem_ww_ctx { void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ctx, bool intr); void i915_gem_ww_ctx_fini(struct i915_gem_ww_ctx *ctx); int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ctx); +void i915_gem_ww_unlock_single(struct drm_i915_gem_object *obj); #endif /* __I915_GEM_H__ */ -- cgit v1.2.3 From bfdf8b1d38680dd40f43b95710b2b4e6c6f7f57f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:49 +0200 Subject: drm/i915: Use ww locking in intel_renderstate. We want to start using ww locking in intel_context_pin, for this we need to lock multiple objects, and the single i915_gem_object_lock is not enough. Convert to using ww-waiting, and make sure we always pin intel_context_state, even if we don't have a renderstate object. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-10-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_gt.c | 21 +++++---- drivers/gpu/drm/i915/gt/intel_renderstate.c | 73 +++++++++++++++++++++-------- drivers/gpu/drm/i915/gt/intel_renderstate.h | 9 ++-- 3 files changed, 71 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index e0755f1a904b..8694ddbdac4c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -406,21 +406,20 @@ static int __engines_record_defaults(struct intel_gt *gt) /* We must be able to switch to something! */ GEM_BUG_ON(!engine->kernel_context); - err = intel_renderstate_init(&so, engine); - if (err) - goto out; - ce = intel_context_create(engine); if (IS_ERR(ce)) { err = PTR_ERR(ce); goto out; } - rq = intel_context_create_request(ce); + err = intel_renderstate_init(&so, ce); + if (err) + goto err; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - intel_context_put(ce); - goto out; + goto err_fini; } err = intel_engine_emit_ctx_wa(rq); @@ -434,9 +433,13 @@ static int __engines_record_defaults(struct intel_gt *gt) err_rq: requests[id] = i915_request_get(rq); i915_request_add(rq); - intel_renderstate_fini(&so); - if (err) +err_fini: + intel_renderstate_fini(&so, ce); +err: + if (err) { + intel_context_put(ce); goto out; + } } /* Flush the default context image to memory, and enable powersaving. */ diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c index 1bfad589c63b..5164de04049d 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.c +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c @@ -27,6 +27,7 @@ #include "i915_drv.h" #include "intel_renderstate.h" +#include "gt/intel_context.h" #include "intel_ring.h" static const struct intel_renderstate_rodata * @@ -157,33 +158,47 @@ out: #undef OUT_BATCH int intel_renderstate_init(struct intel_renderstate *so, - struct intel_engine_cs *engine) + struct intel_context *ce) { - struct drm_i915_gem_object *obj; + struct intel_engine_cs *engine = ce->engine; + struct drm_i915_gem_object *obj = NULL; int err; memset(so, 0, sizeof(*so)); so->rodata = render_state_get_rodata(engine); - if (!so->rodata) - return 0; + if (so->rodata) { + if (so->rodata->batch_items * 4 > PAGE_SIZE) + return -EINVAL; + + obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); + if (IS_ERR(so->vma)) { + err = PTR_ERR(so->vma); + goto err_obj; + } + } - if (so->rodata->batch_items * 4 > PAGE_SIZE) - return -EINVAL; + i915_gem_ww_ctx_init(&so->ww, true); +retry: + err = intel_context_pin(ce); + if (err) + goto err_fini; - obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); - if (IS_ERR(obj)) - return PTR_ERR(obj); + /* return early if there's nothing to setup */ + if (!err && !so->rodata) + return 0; - so->vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); - if (IS_ERR(so->vma)) { - err = PTR_ERR(so->vma); - goto err_obj; - } + err = i915_gem_object_lock(so->vma->obj, &so->ww); + if (err) + goto err_context; err = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); if (err) - goto err_obj; + goto err_context; err = render_state_setup(so, engine->i915); if (err) @@ -193,8 +208,18 @@ int intel_renderstate_init(struct intel_renderstate *so, err_unpin: i915_vma_unpin(so->vma); +err_context: + intel_context_unpin(ce); +err_fini: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&so->ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&so->ww); err_obj: - i915_gem_object_put(obj); + if (obj) + i915_gem_object_put(obj); so->vma = NULL; return err; } @@ -208,11 +233,9 @@ int intel_renderstate_emit(struct intel_renderstate *so, if (!so->vma) return 0; - i915_vma_lock(so->vma); err = i915_request_await_object(rq, so->vma->obj, false); if (err == 0) err = i915_vma_move_to_active(so->vma, rq, 0); - i915_vma_unlock(so->vma); if (err) return err; @@ -233,7 +256,17 @@ int intel_renderstate_emit(struct intel_renderstate *so, return 0; } -void intel_renderstate_fini(struct intel_renderstate *so) +void intel_renderstate_fini(struct intel_renderstate *so, + struct intel_context *ce) { - i915_vma_unpin_and_release(&so->vma, 0); + if (so->vma) { + i915_vma_unpin(so->vma); + i915_vma_close(so->vma); + } + + intel_context_unpin(ce); + i915_gem_ww_ctx_fini(&so->ww); + + if (so->vma) + i915_gem_object_put(so->vma->obj); } diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.h b/drivers/gpu/drm/i915/gt/intel_renderstate.h index 5700be69a05a..713aa1e86c80 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.h +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.h @@ -25,9 +25,10 @@ #define _INTEL_RENDERSTATE_H_ #include +#include "i915_gem.h" struct i915_request; -struct intel_engine_cs; +struct intel_context; struct i915_vma; struct intel_renderstate_rodata { @@ -49,6 +50,7 @@ extern const struct intel_renderstate_rodata gen8_null_state; extern const struct intel_renderstate_rodata gen9_null_state; struct intel_renderstate { + struct i915_gem_ww_ctx ww; const struct intel_renderstate_rodata *rodata; struct i915_vma *vma; u32 batch_offset; @@ -58,9 +60,10 @@ struct intel_renderstate { }; int intel_renderstate_init(struct intel_renderstate *so, - struct intel_engine_cs *engine); + struct intel_context *ce); int intel_renderstate_emit(struct intel_renderstate *so, struct i915_request *rq); -void intel_renderstate_fini(struct intel_renderstate *so); +void intel_renderstate_fini(struct intel_renderstate *so, + struct intel_context *ce); #endif /* _INTEL_RENDERSTATE_H_ */ -- cgit v1.2.3 From 99f08d674e2d96f24d39452bd162b20e7d6bed12 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:50 +0200 Subject: drm/i915: Add ww context handling to context_barrier_task This is required if we want to pass a ww context in intel_context_pin and gen6_ppgtt_pin(). Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-11-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 55 ++++++++++++++++------ .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 22 ++++----- 2 files changed, 48 insertions(+), 29 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index db893f6c516b..34c8b0dd85e0 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1106,6 +1106,7 @@ I915_SELFTEST_DECLARE(static intel_engine_mask_t context_barrier_inject_fault); static int context_barrier_task(struct i915_gem_context *ctx, intel_engine_mask_t engines, bool (*skip)(struct intel_context *ce, void *data), + int (*pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data), int (*emit)(struct i915_request *rq, void *data), void (*task)(void *data), void *data) @@ -1113,6 +1114,7 @@ static int context_barrier_task(struct i915_gem_context *ctx, struct context_barrier_task *cb; struct i915_gem_engines_iter it; struct i915_gem_engines *e; + struct i915_gem_ww_ctx ww; struct intel_context *ce; int err = 0; @@ -1150,10 +1152,21 @@ static int context_barrier_task(struct i915_gem_context *ctx, if (skip && skip(ce, data)) continue; - rq = intel_context_create_request(ce); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = intel_context_pin(ce); + if (err) + goto err; + + if (pin) + err = pin(ce, &ww, data); + if (err) + goto err_unpin; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - break; + goto err_unpin; } err = 0; @@ -1163,6 +1176,16 @@ static int context_barrier_task(struct i915_gem_context *ctx, err = i915_active_add_request(&cb->base, rq); i915_request_add(rq); +err_unpin: + intel_context_unpin(ce); +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + if (err) break; } @@ -1218,6 +1241,17 @@ static void set_ppgtt_barrier(void *data) i915_vm_close(old); } +static int pin_ppgtt_update(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void *data) +{ + struct i915_address_space *vm = ce->vm; + + if (!HAS_LOGICAL_RING_CONTEXTS(vm->i915)) + /* ppGTT is not part of the legacy context image */ + return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm)); + + return 0; +} + static int emit_ppgtt_update(struct i915_request *rq, void *data) { struct i915_address_space *vm = rq->context->vm; @@ -1274,20 +1308,10 @@ static int emit_ppgtt_update(struct i915_request *rq, void *data) static bool skip_ppgtt_update(struct intel_context *ce, void *data) { - if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) - return true; - if (HAS_LOGICAL_RING_CONTEXTS(ce->engine->i915)) - return false; - - if (!atomic_read(&ce->pin_count)) - return true; - - /* ppGTT is not part of the legacy context image */ - if (gen6_ppgtt_pin(i915_vm_to_ppgtt(ce->vm))) - return true; - - return false; + return !ce->state; + else + return !atomic_read(&ce->pin_count); } static int set_ppgtt(struct drm_i915_file_private *file_priv, @@ -1338,6 +1362,7 @@ static int set_ppgtt(struct drm_i915_file_private *file_priv, */ err = context_barrier_task(ctx, ALL_ENGINES, skip_ppgtt_update, + pin_ppgtt_update, emit_ppgtt_update, set_ppgtt_barrier, old); diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index 9160a335c684..fa40006b453a 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -1920,8 +1920,8 @@ static int mock_context_barrier(void *arg) return -ENOMEM; counter = 0; - err = context_barrier_task(ctx, 0, - NULL, NULL, mock_barrier_task, &counter); + err = context_barrier_task(ctx, 0, NULL, NULL, NULL, + mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; @@ -1933,11 +1933,8 @@ static int mock_context_barrier(void *arg) } counter = 0; - err = context_barrier_task(ctx, ALL_ENGINES, - skip_unused_engines, - NULL, - mock_barrier_task, - &counter); + err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines, + NULL, NULL, mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; @@ -1957,8 +1954,8 @@ static int mock_context_barrier(void *arg) counter = 0; context_barrier_inject_fault = BIT(RCS0); - err = context_barrier_task(ctx, ALL_ENGINES, - NULL, NULL, mock_barrier_task, &counter); + err = context_barrier_task(ctx, ALL_ENGINES, NULL, NULL, NULL, + mock_barrier_task, &counter); context_barrier_inject_fault = 0; if (err == -ENXIO) err = 0; @@ -1972,11 +1969,8 @@ static int mock_context_barrier(void *arg) goto out; counter = 0; - err = context_barrier_task(ctx, ALL_ENGINES, - skip_unused_engines, - NULL, - mock_barrier_task, - &counter); + err = context_barrier_task(ctx, ALL_ENGINES, skip_unused_engines, + NULL, NULL, mock_barrier_task, &counter); if (err) { pr_err("Failed at line %d, err=%d\n", __LINE__, err); goto out; -- cgit v1.2.3 From b49a7d51c32e73b0e971247903e7e2a168c4482e Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:51 +0200 Subject: drm/i915: Nuke arguments to eb_pin_engine Those arguments are already set as eb.file and eb.args, so kill off the extra arguments. This will allow us to move eb_pin_engine() to after we reserved all BO's. Signed-off-by: Maarten Lankhorst Reviewed-by: Tvrtko Ursulin Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-12-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 13b996830e25..2ccc566f9154 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2610,11 +2610,10 @@ static void eb_unpin_engine(struct i915_execbuffer *eb) } static unsigned int -eb_select_legacy_ring(struct i915_execbuffer *eb, - struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args) +eb_select_legacy_ring(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; + struct drm_i915_gem_execbuffer2 *args = eb->args; unsigned int user_ring_id = args->flags & I915_EXEC_RING_MASK; if (user_ring_id != I915_EXEC_BSD && @@ -2629,7 +2628,7 @@ eb_select_legacy_ring(struct i915_execbuffer *eb, unsigned int bsd_idx = args->flags & I915_EXEC_BSD_MASK; if (bsd_idx == I915_EXEC_BSD_DEFAULT) { - bsd_idx = gen8_dispatch_bsd_engine(i915, file); + bsd_idx = gen8_dispatch_bsd_engine(i915, eb->file); } else if (bsd_idx >= I915_EXEC_BSD_RING1 && bsd_idx <= I915_EXEC_BSD_RING2) { bsd_idx >>= I915_EXEC_BSD_SHIFT; @@ -2654,18 +2653,16 @@ eb_select_legacy_ring(struct i915_execbuffer *eb, } static int -eb_pin_engine(struct i915_execbuffer *eb, - struct drm_file *file, - struct drm_i915_gem_execbuffer2 *args) +eb_pin_engine(struct i915_execbuffer *eb) { struct intel_context *ce; unsigned int idx; int err; if (i915_gem_context_user_engines(eb->gem_context)) - idx = args->flags & I915_EXEC_RING_MASK; + idx = eb->args->flags & I915_EXEC_RING_MASK; else - idx = eb_select_legacy_ring(eb, file, args); + idx = eb_select_legacy_ring(eb); ce = i915_gem_context_get_engine(eb->gem_context, idx); if (IS_ERR(ce)) @@ -3125,7 +3122,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_destroy; - err = eb_pin_engine(&eb, file, args); + err = eb_pin_engine(&eb); if (unlikely(err)) goto err_context; -- cgit v1.2.3 From 2bf541ff6d06f4169e198adaa6c4133e178caaa5 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:52 +0200 Subject: drm/i915: Pin engine before pinning all objects, v5. We want to lock all gem objects, including the engine context objects, rework the throttling to ensure that we can do this. Now we only throttle once, but can take eb_pin_engine while acquiring objects. This means we will have to drop the lock to wait. If we don't have to throttle we can still take the fastpath, if not we will take the slowpath and wait for the throttle request while unlocked. The engine has to be pinned as first step, otherwise gpu relocations won't work. Changes since v1: - Only need to get a throttled request in the fastpath, no need for a global flag any more. - Always free the waited request correctly. Changes since v2: - Use intel_engine_pm_get()/put() to keeep engine pool alive during EDEADLK handling. Changes since v3: - Fix small rq leak. Changes since v4: - Use a single reloc_context, for intel_context_pin_ww(). Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-13-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 214 ++++++++++++++------- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 3 + 2 files changed, 152 insertions(+), 65 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 2ccc566f9154..d3c47390ef53 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -56,7 +56,8 @@ enum { #define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE) #define __EXEC_HAS_RELOC BIT(31) -#define __EXEC_INTERNAL_FLAGS (~0u << 31) +#define __EXEC_ENGINE_PINNED BIT(30) +#define __EXEC_INTERNAL_FLAGS (~0u << 30) #define UPDATE PIN_OFFSET_FIXED #define BATCH_OFFSET_BIAS (256*1024) @@ -281,6 +282,7 @@ struct i915_execbuffer { } reloc_cache; struct intel_gt_buffer_pool_node *reloc_pool; /** relocation pool for -EDEADLK handling */ + struct intel_context *reloc_context; u64 invalid_flags; /** Set of execobj.flags that are invalid */ u32 context_flags; /** Set of execobj.flags to insert from the ctx */ @@ -303,6 +305,9 @@ struct i915_execbuffer { }; static int eb_parse(struct i915_execbuffer *eb); +static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, + bool throttle); +static void eb_unpin_engine(struct i915_execbuffer *eb); static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) { @@ -935,7 +940,7 @@ eb_get_vma(const struct i915_execbuffer *eb, unsigned long handle) } } -static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) +static void eb_release_vmas(struct i915_execbuffer *eb, bool final) { const unsigned int count = eb->buffer_count; unsigned int i; @@ -952,6 +957,8 @@ static void eb_release_vmas(const struct i915_execbuffer *eb, bool final) if (final) i915_vma_put(vma); } + + eb_unpin_engine(eb); } static void eb_destroy(const struct i915_execbuffer *eb) @@ -1292,19 +1299,26 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, if (engine == eb->context->engine) { rq = i915_request_create(eb->context); } else { - struct intel_context *ce; + struct intel_context *ce = eb->reloc_context; - ce = intel_context_create(engine); - if (IS_ERR(ce)) { - err = PTR_ERR(ce); - goto err_unpin; + if (!ce) { + ce = intel_context_create(engine); + if (IS_ERR(ce)) { + err = PTR_ERR(ce); + goto err_unpin; + } + + i915_vm_put(ce->vm); + ce->vm = i915_vm_get(eb->context->vm); + eb->reloc_context = ce; } - i915_vm_put(ce->vm); - ce->vm = i915_vm_get(eb->context->vm); + err = intel_context_pin(ce); + if (err) + goto err_unpin; - rq = intel_context_create_request(ce); - intel_context_put(ce); + rq = i915_request_create(ce); + intel_context_unpin(ce); } if (IS_ERR(rq)) { err = PTR_ERR(rq); @@ -1871,7 +1885,8 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) return 0; } -static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb) +static noinline int eb_relocate_parse_slow(struct i915_execbuffer *eb, + struct i915_request *rq) { bool have_copy = false; struct eb_vma *ev; @@ -1887,6 +1902,21 @@ repeat: eb_release_vmas(eb, false); i915_gem_ww_ctx_fini(&eb->ww); + if (rq) { + /* nonblocking is always false */ + if (i915_request_wait(rq, I915_WAIT_INTERRUPTIBLE, + MAX_SCHEDULE_TIMEOUT) < 0) { + i915_request_put(rq); + rq = NULL; + + err = -EINTR; + goto err_relock; + } + + i915_request_put(rq); + rq = NULL; + } + /* * We take 3 passes through the slowpatch. * @@ -1910,14 +1940,25 @@ repeat: err = 0; } - flush_workqueue(eb->i915->mm.userptr_wq); + if (!err) + flush_workqueue(eb->i915->mm.userptr_wq); +err_relock: i915_gem_ww_ctx_init(&eb->ww, true); if (err) goto out; /* reacquire the objects */ repeat_validate: + rq = eb_pin_engine(eb, false); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + goto err; + } + + /* We didn't throttle, should be NULL */ + GEM_WARN_ON(rq); + err = eb_validate_vmas(eb); if (err) goto err; @@ -1988,14 +2029,49 @@ out: } } + if (rq) + i915_request_put(rq); + return err; } static int eb_relocate_parse(struct i915_execbuffer *eb) { int err; + struct i915_request *rq = NULL; + bool throttle = true; retry: + rq = eb_pin_engine(eb, throttle); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + rq = NULL; + if (err != -EDEADLK) + return err; + + goto err; + } + + if (rq) { + bool nonblock = eb->file->filp->f_flags & O_NONBLOCK; + + /* Need to drop all locks now for throttling, take slowpath */ + err = i915_request_wait(rq, I915_WAIT_INTERRUPTIBLE, 0); + if (err == -ETIME) { + if (nonblock) { + err = -EWOULDBLOCK; + i915_request_put(rq); + goto err; + } + goto slow; + } + i915_request_put(rq); + rq = NULL; + } + + /* only throttle once, even if we didn't need to throttle */ + throttle = false; + err = eb_validate_vmas(eb); if (err == -EAGAIN) goto slow; @@ -2032,7 +2108,7 @@ err: return err; slow: - err = eb_relocate_parse_slow(eb); + err = eb_relocate_parse_slow(eb, rq); if (err) /* * If the user expects the execobject.offset and @@ -2486,7 +2562,7 @@ static const enum intel_engine_id user_ring_map[] = { [I915_EXEC_VEBOX] = VECS0 }; -static struct i915_request *eb_throttle(struct intel_context *ce) +static struct i915_request *eb_throttle(struct i915_execbuffer *eb, struct intel_context *ce) { struct intel_ring *ring = ce->ring; struct intel_timeline *tl = ce->timeline; @@ -2520,22 +2596,17 @@ static struct i915_request *eb_throttle(struct intel_context *ce) return i915_request_get(rq); } -static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) +static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, bool throttle) { + struct intel_context *ce = eb->context; struct intel_timeline *tl; - struct i915_request *rq; + struct i915_request *rq = NULL; int err; - /* - * ABI: Before userspace accesses the GPU (e.g. execbuffer), report - * EIO if the GPU is already wedged. - */ - err = intel_gt_terminally_wedged(ce->engine->gt); - if (err) - return err; + GEM_BUG_ON(eb->args->flags & __EXEC_ENGINE_PINNED); if (unlikely(intel_context_is_banned(ce))) - return -EIO; + return ERR_PTR(-EIO); /* * Pinning the contexts may generate requests in order to acquire @@ -2544,7 +2615,7 @@ static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) */ err = intel_context_pin(ce); if (err) - return err; + return ERR_PTR(err); /* * Take a local wakeref for preparing to dispatch the execbuf as @@ -2556,45 +2627,17 @@ static int __eb_pin_engine(struct i915_execbuffer *eb, struct intel_context *ce) */ tl = intel_context_timeline_lock(ce); if (IS_ERR(tl)) { - err = PTR_ERR(tl); - goto err_unpin; + intel_context_unpin(ce); + return ERR_CAST(tl); } intel_context_enter(ce); - rq = eb_throttle(ce); - + if (throttle) + rq = eb_throttle(eb, ce); intel_context_timeline_unlock(tl); - if (rq) { - bool nonblock = eb->file->filp->f_flags & O_NONBLOCK; - long timeout; - - timeout = MAX_SCHEDULE_TIMEOUT; - if (nonblock) - timeout = 0; - - timeout = i915_request_wait(rq, - I915_WAIT_INTERRUPTIBLE, - timeout); - i915_request_put(rq); - - if (timeout < 0) { - err = nonblock ? -EWOULDBLOCK : timeout; - goto err_exit; - } - } - - eb->engine = ce->engine; - eb->context = ce; - return 0; - -err_exit: - mutex_lock(&tl->mutex); - intel_context_exit(ce); - intel_context_timeline_unlock(tl); -err_unpin: - intel_context_unpin(ce); - return err; + eb->args->flags |= __EXEC_ENGINE_PINNED; + return rq; } static void eb_unpin_engine(struct i915_execbuffer *eb) @@ -2602,6 +2645,11 @@ static void eb_unpin_engine(struct i915_execbuffer *eb) struct intel_context *ce = eb->context; struct intel_timeline *tl = ce->timeline; + if (!(eb->args->flags & __EXEC_ENGINE_PINNED)) + return; + + eb->args->flags &= ~__EXEC_ENGINE_PINNED; + mutex_lock(&tl->mutex); intel_context_exit(ce); mutex_unlock(&tl->mutex); @@ -2653,7 +2701,7 @@ eb_select_legacy_ring(struct i915_execbuffer *eb) } static int -eb_pin_engine(struct i915_execbuffer *eb) +eb_select_engine(struct i915_execbuffer *eb) { struct intel_context *ce; unsigned int idx; @@ -2668,12 +2716,45 @@ eb_pin_engine(struct i915_execbuffer *eb) if (IS_ERR(ce)) return PTR_ERR(ce); - err = __eb_pin_engine(eb, ce); - intel_context_put(ce); + intel_gt_pm_get(ce->engine->gt); + if (!test_bit(CONTEXT_ALLOC_BIT, &ce->flags)) { + err = intel_context_alloc_state(ce); + if (err) + goto err; + } + + /* + * ABI: Before userspace accesses the GPU (e.g. execbuffer), report + * EIO if the GPU is already wedged. + */ + err = intel_gt_terminally_wedged(ce->engine->gt); + if (err) + goto err; + + eb->context = ce; + eb->engine = ce->engine; + + /* + * Make sure engine pool stays alive even if we call intel_context_put + * during ww handling. The pool is destroyed when last pm reference + * is dropped, which breaks our -EDEADLK handling. + */ + return err; + +err: + intel_gt_pm_put(ce->engine->gt); + intel_context_put(ce); return err; } +static void +eb_put_engine(struct i915_execbuffer *eb) +{ + intel_gt_pm_put(eb->engine->gt); + intel_context_put(eb->context); +} + static void __free_fence_array(struct eb_fence *fences, unsigned int n) { @@ -3054,6 +3135,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.vma = (struct eb_vma *)(exec + args->buffer_count + 1); eb.vma[0].vma = NULL; eb.reloc_pool = eb.batch_pool = NULL; + eb.reloc_context = NULL; eb.invalid_flags = __EXEC_OBJECT_UNKNOWN_FLAGS; reloc_cache_init(&eb.reloc_cache, eb.i915); @@ -3122,7 +3204,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, if (unlikely(err)) goto err_destroy; - err = eb_pin_engine(&eb); + err = eb_select_engine(&eb); if (unlikely(err)) goto err_context; @@ -3259,8 +3341,10 @@ err_vma: intel_gt_buffer_pool_put(eb.batch_pool); if (eb.reloc_pool) intel_gt_buffer_pool_put(eb.reloc_pool); + if (eb.reloc_context) + intel_context_put(eb.reloc_context); err_engine: - eb_unpin_engine(&eb); + eb_put_engine(&eb); err_context: i915_gem_context_put(eb.gem_context); err_destroy: diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index bc08c02b5767..563839cbaf1c 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -135,6 +135,7 @@ static int igt_gpu_reloc(void *arg) goto err_pm; } eb.reloc_pool = NULL; + eb.reloc_context = NULL; i915_gem_ww_ctx_init(&eb.ww, false); retry: @@ -153,6 +154,8 @@ retry: if (eb.reloc_pool) intel_gt_buffer_pool_put(eb.reloc_pool); + if (eb.reloc_context) + intel_context_put(eb.reloc_context); intel_context_put(eb.context); err_pm: -- cgit v1.2.3 From 3999a7087989af0bfb9406b77d3d8444031aab7d Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:53 +0200 Subject: drm/i915: Rework intel_context pinning to do everything outside of pin_mutex Instead of doing everything inside of pin_mutex, we move all pinning outside. Because i915_active has its own reference counting and pinning is also having the same issues vs mutexes, we make sure everything is pinned first, so the pinning in i915_active only needs to bump refcounts. This allows us to take pin refcounts correctly all the time. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-14-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_context.c | 232 ++++++++++++++---------- drivers/gpu/drm/i915/gt/intel_context_types.h | 4 +- drivers/gpu/drm/i915/gt/intel_lrc.c | 34 ++-- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 13 +- drivers/gpu/drm/i915/gt/mock_engine.c | 13 +- 5 files changed, 190 insertions(+), 106 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 52db2bde44a3..efe9a7a89ede 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -93,79 +93,6 @@ static void intel_context_active_release(struct intel_context *ce) i915_active_release(&ce->active); } -int __intel_context_do_pin(struct intel_context *ce) -{ - int err; - - if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { - err = intel_context_alloc_state(ce); - if (err) - return err; - } - - err = i915_active_acquire(&ce->active); - if (err) - return err; - - if (mutex_lock_interruptible(&ce->pin_mutex)) { - err = -EINTR; - goto out_release; - } - - if (unlikely(intel_context_is_closed(ce))) { - err = -ENOENT; - goto out_unlock; - } - - if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { - err = intel_context_active_acquire(ce); - if (unlikely(err)) - goto out_unlock; - - err = ce->ops->pin(ce); - if (unlikely(err)) - goto err_active; - - CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n", - i915_ggtt_offset(ce->ring->vma), - ce->ring->head, ce->ring->tail); - - smp_mb__before_atomic(); /* flush pin before it is visible */ - atomic_inc(&ce->pin_count); - } - - GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ - GEM_BUG_ON(i915_active_is_idle(&ce->active)); - goto out_unlock; - -err_active: - intel_context_active_release(ce); -out_unlock: - mutex_unlock(&ce->pin_mutex); -out_release: - i915_active_release(&ce->active); - return err; -} - -void intel_context_unpin(struct intel_context *ce) -{ - if (!atomic_dec_and_test(&ce->pin_count)) - return; - - CE_TRACE(ce, "unpin\n"); - ce->ops->unpin(ce); - - /* - * Once released, we may asynchronously drop the active reference. - * As that may be the only reference keeping the context alive, - * take an extra now so that it is not freed before we finish - * dereferencing it. - */ - intel_context_get(ce); - intel_context_active_release(ce); - intel_context_put(ce); -} - static int __context_pin_state(struct i915_vma *vma) { unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; @@ -225,6 +152,138 @@ static void __ring_retire(struct intel_ring *ring) intel_ring_unpin(ring); } +static int intel_context_pre_pin(struct intel_context *ce) +{ + int err; + + CE_TRACE(ce, "active\n"); + + err = __ring_active(ce->ring); + if (err) + return err; + + err = intel_timeline_pin(ce->timeline); + if (err) + goto err_ring; + + if (!ce->state) + return 0; + + err = __context_pin_state(ce->state); + if (err) + goto err_timeline; + + + return 0; + +err_timeline: + intel_timeline_unpin(ce->timeline); +err_ring: + __ring_retire(ce->ring); + return err; +} + +static void intel_context_post_unpin(struct intel_context *ce) +{ + if (ce->state) + __context_unpin_state(ce->state); + + intel_timeline_unpin(ce->timeline); + __ring_retire(ce->ring); +} + +int __intel_context_do_pin(struct intel_context *ce) +{ + bool handoff = false; + void *vaddr; + int err = 0; + + if (unlikely(!test_bit(CONTEXT_ALLOC_BIT, &ce->flags))) { + err = intel_context_alloc_state(ce); + if (err) + return err; + } + + /* + * We always pin the context/ring/timeline here, to ensure a pin + * refcount for __intel_context_active(), which prevent a lock + * inversion of ce->pin_mutex vs dma_resv_lock(). + */ + err = intel_context_pre_pin(ce); + if (err) + return err; + + err = i915_active_acquire(&ce->active); + if (err) + goto err_ctx_unpin; + + err = ce->ops->pre_pin(ce, &vaddr); + if (err) + goto err_release; + + err = mutex_lock_interruptible(&ce->pin_mutex); + if (err) + goto err_post_unpin; + + if (unlikely(intel_context_is_closed(ce))) { + err = -ENOENT; + goto err_unlock; + } + + if (likely(!atomic_add_unless(&ce->pin_count, 1, 0))) { + err = intel_context_active_acquire(ce); + if (unlikely(err)) + goto err_unlock; + + err = ce->ops->pin(ce, vaddr); + if (err) { + intel_context_active_release(ce); + goto err_unlock; + } + + CE_TRACE(ce, "pin ring:{start:%08x, head:%04x, tail:%04x}\n", + i915_ggtt_offset(ce->ring->vma), + ce->ring->head, ce->ring->tail); + + handoff = true; + smp_mb__before_atomic(); /* flush pin before it is visible */ + atomic_inc(&ce->pin_count); + } + + GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */ + +err_unlock: + mutex_unlock(&ce->pin_mutex); +err_post_unpin: + if (!handoff) + ce->ops->post_unpin(ce); +err_release: + i915_active_release(&ce->active); +err_ctx_unpin: + intel_context_post_unpin(ce); + return err; +} + +void intel_context_unpin(struct intel_context *ce) +{ + if (!atomic_dec_and_test(&ce->pin_count)) + return; + + CE_TRACE(ce, "unpin\n"); + ce->ops->unpin(ce); + ce->ops->post_unpin(ce); + + /* + * Once released, we may asynchronously drop the active reference. + * As that may be the only reference keeping the context alive, + * take an extra now so that it is not freed before we finish + * dereferencing it. + */ + intel_context_get(ce); + intel_context_active_release(ce); + intel_context_put(ce); +} + __i915_active_call static void __intel_context_retire(struct i915_active *active) { @@ -235,12 +294,7 @@ static void __intel_context_retire(struct i915_active *active) intel_context_get_avg_runtime_ns(ce)); set_bit(CONTEXT_VALID_BIT, &ce->flags); - if (ce->state) - __context_unpin_state(ce->state); - - intel_timeline_unpin(ce->timeline); - __ring_retire(ce->ring); - + intel_context_post_unpin(ce); intel_context_put(ce); } @@ -249,29 +303,25 @@ static int __intel_context_active(struct i915_active *active) struct intel_context *ce = container_of(active, typeof(*ce), active); int err; - CE_TRACE(ce, "active\n"); - intel_context_get(ce); + /* everything should already be activated by intel_context_pre_pin() */ err = __ring_active(ce->ring); - if (err) + if (GEM_WARN_ON(err)) goto err_put; err = intel_timeline_pin(ce->timeline); - if (err) + if (GEM_WARN_ON(err)) goto err_ring; - if (!ce->state) - return 0; - - err = __context_pin_state(ce->state); - if (err) - goto err_timeline; + if (ce->state) { + GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active)); + __i915_vma_pin(ce->state); + i915_vma_make_unshrinkable(ce->state); + } return 0; -err_timeline: - intel_timeline_unpin(ce->timeline); err_ring: __ring_retire(ce->ring); err_put: diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 4954b0df4864..ca8e05b4d3ef 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -30,8 +30,10 @@ struct intel_ring; struct intel_context_ops { int (*alloc)(struct intel_context *ce); - int (*pin)(struct intel_context *ce); + int (*pre_pin)(struct intel_context *ce, void **vaddr); + int (*pin)(struct intel_context *ce, void *vaddr); void (*unpin)(struct intel_context *ce); + void (*post_unpin)(struct intel_context *ce); void (*enter)(struct intel_context *ce); void (*exit)(struct intel_context *ce); diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 801ebe1326f3..1f6dc69b2490 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3296,7 +3296,10 @@ static void execlists_context_unpin(struct intel_context *ce) { check_redzone((void *)ce->lrc_reg_state - LRC_STATE_OFFSET, ce->engine); +} +static void execlists_context_post_unpin(struct intel_context *ce) +{ i915_gem_object_unpin_map(ce->state->obj); } @@ -3458,20 +3461,23 @@ __execlists_update_reg_state(const struct intel_context *ce, } static int -__execlists_context_pin(struct intel_context *ce, - struct intel_engine_cs *engine) +execlists_context_pre_pin(struct intel_context *ce, void **vaddr) { - void *vaddr; - GEM_BUG_ON(!ce->state); GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); - vaddr = i915_gem_object_pin_map(ce->state->obj, - i915_coherent_map_type(engine->i915) | + *vaddr = i915_gem_object_pin_map(ce->state->obj, + i915_coherent_map_type(ce->engine->i915) | I915_MAP_OVERRIDE); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); + return PTR_ERR_OR_ZERO(*vaddr); +} + +static int +__execlists_context_pin(struct intel_context *ce, + struct intel_engine_cs *engine, + void *vaddr) +{ ce->lrc.lrca = lrc_descriptor(ce, engine) | CTX_DESC_FORCE_RESTORE; ce->lrc_reg_state = vaddr + LRC_STATE_OFFSET; __execlists_update_reg_state(ce, engine, ce->ring->tail); @@ -3479,9 +3485,9 @@ __execlists_context_pin(struct intel_context *ce, return 0; } -static int execlists_context_pin(struct intel_context *ce) +static int execlists_context_pin(struct intel_context *ce, void *vaddr) { - return __execlists_context_pin(ce, ce->engine); + return __execlists_context_pin(ce, ce->engine, vaddr); } static int execlists_context_alloc(struct intel_context *ce) @@ -3507,8 +3513,10 @@ static void execlists_context_reset(struct intel_context *ce) static const struct intel_context_ops execlists_context_ops = { .alloc = execlists_context_alloc, + .pre_pin = execlists_context_pre_pin, .pin = execlists_context_pin, .unpin = execlists_context_unpin, + .post_unpin = execlists_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, @@ -5447,12 +5455,12 @@ static int virtual_context_alloc(struct intel_context *ce) return __execlists_context_alloc(ce, ve->siblings[0]); } -static int virtual_context_pin(struct intel_context *ce) +static int virtual_context_pin(struct intel_context *ce, void *vaddr) { struct virtual_engine *ve = container_of(ce, typeof(*ve), context); /* Note: we must use a real engine class for setting up reg state */ - return __execlists_context_pin(ce, ve->siblings[0]); + return __execlists_context_pin(ce, ve->siblings[0], vaddr); } static void virtual_context_enter(struct intel_context *ce) @@ -5480,8 +5488,10 @@ static void virtual_context_exit(struct intel_context *ce) static const struct intel_context_ops virtual_context_ops = { .alloc = virtual_context_alloc, + .pre_pin = execlists_context_pre_pin, .pin = virtual_context_pin, .unpin = execlists_context_unpin, + .post_unpin = execlists_context_post_unpin, .enter = virtual_context_enter, .exit = virtual_context_exit, diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index a3b10f3c83eb..93cf72cfd318 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -499,6 +499,10 @@ static void __context_unpin_ppgtt(struct intel_context *ce) } static void ring_context_unpin(struct intel_context *ce) +{ +} + +static void ring_context_post_unpin(struct intel_context *ce) { __context_unpin_ppgtt(ce); } @@ -587,11 +591,16 @@ static int ring_context_alloc(struct intel_context *ce) return 0; } -static int ring_context_pin(struct intel_context *ce) +static int ring_context_pre_pin(struct intel_context *ce, void **unused) { return __context_pin_ppgtt(ce); } +static int ring_context_pin(struct intel_context *ce, void *unused) +{ + return 0; +} + static void ring_context_reset(struct intel_context *ce) { intel_ring_reset(ce->ring, ce->ring->emit); @@ -600,8 +609,10 @@ static void ring_context_reset(struct intel_context *ce) static const struct intel_context_ops ring_context_ops = { .alloc = ring_context_alloc, + .pre_pin = ring_context_pre_pin, .pin = ring_context_pin, .unpin = ring_context_unpin, + .post_unpin = ring_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index 79764305b8ec..c8e631222f23 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -131,6 +131,10 @@ static void mock_context_unpin(struct intel_context *ce) { } +static void mock_context_post_unpin(struct intel_context *ce) +{ +} + static void mock_context_destroy(struct kref *ref) { struct intel_context *ce = container_of(ref, typeof(*ce), ref); @@ -163,7 +167,12 @@ static int mock_context_alloc(struct intel_context *ce) return 0; } -static int mock_context_pin(struct intel_context *ce) +static int mock_context_pre_pin(struct intel_context *ce, void **unused) +{ + return 0; +} + +static int mock_context_pin(struct intel_context *ce, void *unused) { return 0; } @@ -175,8 +184,10 @@ static void mock_context_reset(struct intel_context *ce) static const struct intel_context_ops mock_context_ops = { .alloc = mock_context_alloc, + .pre_pin = mock_context_pre_pin, .pin = mock_context_pin, .unpin = mock_context_unpin, + .post_unpin = mock_context_post_unpin, .enter = intel_context_enter_engine, .exit = intel_context_exit_engine, -- cgit v1.2.3 From 47b086934f429561b3828a6b248e3406b5121939 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:54 +0200 Subject: drm/i915: Make sure execbuffer always passes ww state to i915_vma_pin. As a preparation step for full object locking and wait/wound handling during pin and object mapping, ensure that we always pass the ww context in i915_gem_execbuffer.c to i915_vma_pin, use lockdep to ensure this happens. This also requires changing the order of eb_parse slightly, to ensure we pass ww at a point where we could still handle -EDEADLK safely. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-15-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/display/intel_display.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 140 +++++++++++---------- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 4 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 4 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.h | 4 +- drivers/gpu/drm/i915/gt/intel_context.c | 65 ++++++---- drivers/gpu/drm/i915/gt/intel_context.h | 13 ++ drivers/gpu/drm/i915/gt/intel_context_types.h | 3 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- drivers/gpu/drm/i915/gt/intel_lrc.c | 5 +- drivers/gpu/drm/i915/gt/intel_renderstate.c | 2 +- drivers/gpu/drm/i915/gt/intel_ring.c | 10 +- drivers/gpu/drm/i915/gt/intel_ring.h | 3 +- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 15 +-- drivers/gpu/drm/i915/gt/intel_timeline.c | 12 +- drivers/gpu/drm/i915/gt/intel_timeline.h | 3 +- drivers/gpu/drm/i915/gt/mock_engine.c | 3 +- drivers/gpu/drm/i915/gt/selftest_lrc.c | 2 +- drivers/gpu/drm/i915/gt/selftest_timeline.c | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 13 +- drivers/gpu/drm/i915/i915_gem.c | 11 +- drivers/gpu/drm/i915/i915_vma.c | 13 +- drivers/gpu/drm/i915/i915_vma.h | 13 +- 26 files changed, 217 insertions(+), 137 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 27c0a2140441..c8b1dd1a9e46 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3451,7 +3451,7 @@ initial_plane_vma(struct drm_i915_private *i915, if (IS_ERR(vma)) goto err_obj; - if (i915_ggtt_pin(vma, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) + if (i915_ggtt_pin(vma, NULL, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) goto err_obj; if (i915_gem_object_is_tiled(obj) && diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 34c8b0dd85e0..cf5ecbde9e06 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1154,7 +1154,7 @@ static int context_barrier_task(struct i915_gem_context *ctx, i915_gem_ww_ctx_init(&ww, true); retry: - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &ww); if (err) goto err; @@ -1247,7 +1247,7 @@ static int pin_ppgtt_update(struct intel_context *ce, struct i915_gem_ww_ctx *ww if (!HAS_LOGICAL_RING_CONTEXTS(vm->i915)) /* ppGTT is not part of the legacy context image */ - return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm)); + return gen6_ppgtt_pin(i915_vm_to_ppgtt(vm), ww); return 0; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index d3c47390ef53..ae63748e90bd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -436,16 +436,17 @@ eb_pin_vma(struct i915_execbuffer *eb, pin_flags |= PIN_GLOBAL; /* Attempt to reuse the current location if available */ - if (unlikely(i915_vma_pin(vma, 0, 0, pin_flags))) { + /* TODO: Add -EDEADLK handling here */ + if (unlikely(i915_vma_pin_ww(vma, &eb->ww, 0, 0, pin_flags))) { if (entry->flags & EXEC_OBJECT_PINNED) return false; /* Failing that pick any _free_ space if suitable */ - if (unlikely(i915_vma_pin(vma, - entry->pad_to_size, - entry->alignment, - eb_pin_flags(entry, ev->flags) | - PIN_USER | PIN_NOEVICT))) + if (unlikely(i915_vma_pin_ww(vma, &eb->ww, + entry->pad_to_size, + entry->alignment, + eb_pin_flags(entry, ev->flags) | + PIN_USER | PIN_NOEVICT))) return false; } @@ -586,7 +587,7 @@ static inline int use_cpu_reloc(const struct reloc_cache *cache, obj->cache_level != I915_CACHE_NONE); } -static int eb_reserve_vma(const struct i915_execbuffer *eb, +static int eb_reserve_vma(struct i915_execbuffer *eb, struct eb_vma *ev, u64 pin_flags) { @@ -601,7 +602,7 @@ static int eb_reserve_vma(const struct i915_execbuffer *eb, return err; } - err = i915_vma_pin(vma, + err = i915_vma_pin_ww(vma, &eb->ww, entry->pad_to_size, entry->alignment, eb_pin_flags(entry, ev->flags) | pin_flags); if (err) @@ -1132,9 +1133,10 @@ static void *reloc_kmap(struct drm_i915_gem_object *obj, } static void *reloc_iomap(struct drm_i915_gem_object *obj, - struct reloc_cache *cache, + struct i915_execbuffer *eb, unsigned long page) { + struct reloc_cache *cache = &eb->reloc_cache; struct i915_ggtt *ggtt = cache_to_ggtt(cache); unsigned long offset; void *vaddr; @@ -1156,10 +1158,13 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, if (err) return ERR_PTR(err); - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | - PIN_NONBLOCK /* NOWARN */ | - PIN_NOEVICT); + vma = i915_gem_object_ggtt_pin_ww(obj, &eb->ww, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (vma == ERR_PTR(-EDEADLK)) + return vma; + if (IS_ERR(vma)) { memset(&cache->node, 0, sizeof(cache->node)); mutex_lock(&ggtt->vm.mutex); @@ -1195,9 +1200,10 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, } static void *reloc_vaddr(struct drm_i915_gem_object *obj, - struct reloc_cache *cache, + struct i915_execbuffer *eb, unsigned long page) { + struct reloc_cache *cache = &eb->reloc_cache; void *vaddr; if (cache->page == page) { @@ -1205,7 +1211,7 @@ static void *reloc_vaddr(struct drm_i915_gem_object *obj, } else { vaddr = NULL; if ((cache->vaddr & KMAP) == 0) - vaddr = reloc_iomap(obj, cache, page); + vaddr = reloc_iomap(obj, eb, page); if (!vaddr) vaddr = reloc_kmap(obj, cache, page); } @@ -1292,7 +1298,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, goto err_unmap; } - err = i915_vma_pin(batch, 0, 0, PIN_USER | PIN_NONBLOCK); + err = i915_vma_pin_ww(batch, &eb->ww, 0, 0, PIN_USER | PIN_NONBLOCK); if (err) goto err_unmap; @@ -1313,7 +1319,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, eb->reloc_context = ce; } - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &eb->ww); if (err) goto err_unpin; @@ -1536,8 +1542,7 @@ relocate_entry(struct i915_vma *vma, void *vaddr; repeat: - vaddr = reloc_vaddr(vma->obj, - &eb->reloc_cache, + vaddr = reloc_vaddr(vma->obj, eb, offset >> PAGE_SHIFT); if (IS_ERR(vaddr)) return PTR_ERR(vaddr); @@ -1953,6 +1958,7 @@ repeat_validate: rq = eb_pin_engine(eb, false); if (IS_ERR(rq)) { err = PTR_ERR(rq); + rq = NULL; goto err; } @@ -2236,7 +2242,8 @@ static int i915_reset_gen7_sol_offsets(struct i915_request *rq) } static struct i915_vma * -shadow_batch_pin(struct drm_i915_gem_object *obj, +shadow_batch_pin(struct i915_execbuffer *eb, + struct drm_i915_gem_object *obj, struct i915_address_space *vm, unsigned int flags) { @@ -2247,7 +2254,7 @@ shadow_batch_pin(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return vma; - err = i915_vma_pin(vma, 0, 0, flags); + err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, flags); if (err) return ERR_PTR(err); @@ -2397,16 +2404,33 @@ err_free: return err; } +static struct i915_vma *eb_dispatch_secure(struct i915_execbuffer *eb, struct i915_vma *vma) +{ + /* + * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure + * batch" bit. Hence we need to pin secure batches into the global gtt. + * hsw should have this fixed, but bdw mucks it up again. */ + if (eb->batch_flags & I915_DISPATCH_SECURE) + return i915_gem_object_ggtt_pin_ww(vma->obj, &eb->ww, NULL, 0, 0, 0); + + return NULL; +} + static int eb_parse(struct i915_execbuffer *eb) { struct drm_i915_private *i915 = eb->i915; struct intel_gt_buffer_pool_node *pool = eb->batch_pool; - struct i915_vma *shadow, *trampoline; + struct i915_vma *shadow, *trampoline, *batch; unsigned int len; int err; - if (!eb_use_cmdparser(eb)) - return 0; + if (!eb_use_cmdparser(eb)) { + batch = eb_dispatch_secure(eb, eb->batch->vma); + if (IS_ERR(batch)) + return PTR_ERR(batch); + + goto secure_batch; + } len = eb->batch_len; if (!CMDPARSER_USES_GGTT(eb->i915)) { @@ -2434,7 +2458,7 @@ static int eb_parse(struct i915_execbuffer *eb) if (err) goto err; - shadow = shadow_batch_pin(pool->obj, eb->context->vm, PIN_USER); + shadow = shadow_batch_pin(eb, pool->obj, eb->context->vm, PIN_USER); if (IS_ERR(shadow)) { err = PTR_ERR(shadow); goto err; @@ -2446,7 +2470,7 @@ static int eb_parse(struct i915_execbuffer *eb) if (CMDPARSER_USES_GGTT(eb->i915)) { trampoline = shadow; - shadow = shadow_batch_pin(pool->obj, + shadow = shadow_batch_pin(eb, pool->obj, &eb->engine->gt->ggtt->vm, PIN_GLOBAL); if (IS_ERR(shadow)) { @@ -2459,19 +2483,34 @@ static int eb_parse(struct i915_execbuffer *eb) eb->batch_flags |= I915_DISPATCH_SECURE; } + batch = eb_dispatch_secure(eb, shadow); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto err_trampoline; + } + err = eb_parse_pipeline(eb, shadow, trampoline); if (err) - goto err_trampoline; + goto err_unpin_batch; - eb->vma[eb->buffer_count].vma = i915_vma_get(shadow); - eb->vma[eb->buffer_count].flags = __EXEC_OBJECT_HAS_PIN; eb->batch = &eb->vma[eb->buffer_count++]; + eb->batch->vma = i915_vma_get(shadow); + eb->batch->flags = __EXEC_OBJECT_HAS_PIN; eb->trampoline = trampoline; eb->batch_start_offset = 0; +secure_batch: + if (batch) { + eb->batch = &eb->vma[eb->buffer_count++]; + eb->batch->flags = __EXEC_OBJECT_HAS_PIN; + eb->batch->vma = i915_vma_get(batch); + } return 0; +err_unpin_batch: + if (batch) + i915_vma_unpin(batch); err_trampoline: if (trampoline) i915_vma_unpin(trampoline); @@ -2613,7 +2652,7 @@ static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, bool throt * GGTT space, so do this first before we reserve a seqno for * ourselves. */ - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &eb->ww); if (err) return ERR_PTR(err); @@ -3231,33 +3270,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, ww_acquire_done(&eb.ww.ctx); - /* - * snb/ivb/vlv conflate the "batch in ppgtt" bit with the "non-secure - * batch" bit. Hence we need to pin secure batches into the global gtt. - * hsw should have this fixed, but bdw mucks it up again. */ - if (eb.batch_flags & I915_DISPATCH_SECURE) { - struct i915_vma *vma; - - /* - * So on first glance it looks freaky that we pin the batch here - * outside of the reservation loop. But: - * - The batch is already pinned into the relevant ppgtt, so we - * already have the backing storage fully allocated. - * - No other BO uses the global gtt (well contexts, but meh), - * so we don't really have issues with multiple objects not - * fitting due to fragmentation. - * So this is actually safe. - */ - vma = i915_gem_object_ggtt_pin(eb.batch->vma->obj, NULL, 0, 0, 0); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err_vma; - } - - batch = vma; - } else { - batch = eb.batch->vma; - } + batch = eb.batch->vma; /* All GPU relocation batches must be submitted prior to the user rq */ GEM_BUG_ON(eb.reloc_cache.rq); @@ -3266,7 +3279,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.request = i915_request_create(eb.context); if (IS_ERR(eb.request)) { err = PTR_ERR(eb.request); - goto err_batch_unpin; + goto err_vma; } if (in_fence) { @@ -3327,9 +3340,6 @@ err_request: } i915_request_put(eb.request); -err_batch_unpin: - if (eb.batch_flags & I915_DISPATCH_SECURE) - i915_vma_unpin(batch); err_vma: eb_release_vmas(&eb, true); if (eb.trampoline) @@ -3417,7 +3427,9 @@ i915_gem_execbuffer_ioctl(struct drm_device *dev, void *data, /* Copy in the exec list from userland */ exec_list = kvmalloc_array(count, sizeof(*exec_list), __GFP_NOWARN | GFP_KERNEL); - exec2_list = kvmalloc_array(count + 1, eb_element_size(), + + /* Allocate extra slots for use by the command parser */ + exec2_list = kvmalloc_array(count + 2, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec_list == NULL || exec2_list == NULL) { drm_dbg(&i915->drm, @@ -3494,8 +3506,8 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, if (err) return err; - /* Allocate an extra slot for use by the command parser */ - exec2_list = kvmalloc_array(count + 1, eb_element_size(), + /* Allocate extra slots for use by the command parser */ + exec2_list = kvmalloc_array(count + 2, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec2_list == NULL) { drm_dbg(&i915->drm, "Failed to allocate exec list for %zd buffers\n", diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 563839cbaf1c..e1d50a5a1477 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -36,7 +36,7 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, if (err) return err; - err = i915_vma_pin(vma, 0, 0, PIN_USER | PIN_HIGH); + err = i915_vma_pin_ww(vma, &eb->ww, 0, 0, PIN_USER | PIN_HIGH); if (err) return err; @@ -139,7 +139,7 @@ static int igt_gpu_reloc(void *arg) i915_gem_ww_ctx_init(&eb.ww, false); retry: - err = intel_context_pin(eb.context); + err = intel_context_pin_ww(eb.context, &eb.ww); if (!err) { err = __igt_gpu_reloc(&eb, scratch); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index 7e5a86b774a7..fd0d24d28763 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -368,7 +368,7 @@ static struct i915_vma *pd_vma_create(struct gen6_ppgtt *ppgtt, int size) return vma; } -int gen6_ppgtt_pin(struct i915_ppgtt *base) +int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww) { struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base); int err; @@ -394,7 +394,7 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base) */ err = 0; if (!atomic_read(&ppgtt->pin_count)) - err = i915_ggtt_pin(ppgtt->vma, GEN6_PD_ALIGN, PIN_HIGH); + err = i915_ggtt_pin(ppgtt->vma, ww, GEN6_PD_ALIGN, PIN_HIGH); if (!err) atomic_inc(&ppgtt->pin_count); mutex_unlock(&ppgtt->pin_mutex); diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h index 7249672e5802..3357228f3304 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.h +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.h @@ -8,6 +8,8 @@ #include "intel_gtt.h" +struct i915_gem_ww_ctx; + struct gen6_ppgtt { struct i915_ppgtt base; @@ -67,7 +69,7 @@ static inline struct gen6_ppgtt *to_gen6_ppgtt(struct i915_ppgtt *base) (pt = i915_pt_entry(pd, iter), true); \ ++iter) -int gen6_ppgtt_pin(struct i915_ppgtt *base); +int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww); void gen6_ppgtt_unpin(struct i915_ppgtt *base); void gen6_ppgtt_unpin_all(struct i915_ppgtt *base); void gen6_ppgtt_enable(struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index efe9a7a89ede..c05ef213bdc2 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -93,12 +93,12 @@ static void intel_context_active_release(struct intel_context *ce) i915_active_release(&ce->active); } -static int __context_pin_state(struct i915_vma *vma) +static int __context_pin_state(struct i915_vma *vma, struct i915_gem_ww_ctx *ww) { unsigned int bias = i915_ggtt_pin_bias(vma) | PIN_OFFSET_BIAS; int err; - err = i915_ggtt_pin(vma, 0, bias | PIN_HIGH); + err = i915_ggtt_pin(vma, ww, 0, bias | PIN_HIGH); if (err) return err; @@ -127,11 +127,12 @@ static void __context_unpin_state(struct i915_vma *vma) __i915_vma_unpin(vma); } -static int __ring_active(struct intel_ring *ring) +static int __ring_active(struct intel_ring *ring, + struct i915_gem_ww_ctx *ww) { int err; - err = intel_ring_pin(ring); + err = intel_ring_pin(ring, ww); if (err) return err; @@ -152,24 +153,25 @@ static void __ring_retire(struct intel_ring *ring) intel_ring_unpin(ring); } -static int intel_context_pre_pin(struct intel_context *ce) +static int intel_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) { int err; CE_TRACE(ce, "active\n"); - err = __ring_active(ce->ring); + err = __ring_active(ce->ring, ww); if (err) return err; - err = intel_timeline_pin(ce->timeline); + err = intel_timeline_pin(ce->timeline, ww); if (err) goto err_ring; if (!ce->state) return 0; - err = __context_pin_state(ce->state); + err = __context_pin_state(ce->state, ww); if (err) goto err_timeline; @@ -192,7 +194,8 @@ static void intel_context_post_unpin(struct intel_context *ce) __ring_retire(ce->ring); } -int __intel_context_do_pin(struct intel_context *ce) +int __intel_context_do_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) { bool handoff = false; void *vaddr; @@ -209,7 +212,14 @@ int __intel_context_do_pin(struct intel_context *ce) * refcount for __intel_context_active(), which prevent a lock * inversion of ce->pin_mutex vs dma_resv_lock(). */ - err = intel_context_pre_pin(ce); + + err = i915_gem_object_lock(ce->timeline->hwsp_ggtt->obj, ww); + if (!err && ce->ring->vma->obj) + err = i915_gem_object_lock(ce->ring->vma->obj, ww); + if (!err && ce->state) + err = i915_gem_object_lock(ce->state->obj, ww); + if (!err) + err = intel_context_pre_pin(ce, ww); if (err) return err; @@ -217,7 +227,7 @@ int __intel_context_do_pin(struct intel_context *ce) if (err) goto err_ctx_unpin; - err = ce->ops->pre_pin(ce, &vaddr); + err = ce->ops->pre_pin(ce, ww, &vaddr); if (err) goto err_release; @@ -264,6 +274,23 @@ err_ctx_unpin: return err; } +int __intel_context_do_pin(struct intel_context *ce) +{ + struct i915_gem_ww_ctx ww; + int err; + + i915_gem_ww_ctx_init(&ww, true); +retry: + err = __intel_context_do_pin_ww(ce, &ww); + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + return err; +} + void intel_context_unpin(struct intel_context *ce) { if (!atomic_dec_and_test(&ce->pin_count)) @@ -301,18 +328,14 @@ static void __intel_context_retire(struct i915_active *active) static int __intel_context_active(struct i915_active *active) { struct intel_context *ce = container_of(active, typeof(*ce), active); - int err; intel_context_get(ce); /* everything should already be activated by intel_context_pre_pin() */ - err = __ring_active(ce->ring); - if (GEM_WARN_ON(err)) - goto err_put; + GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->ring->vma->active)); + __intel_ring_pin(ce->ring); - err = intel_timeline_pin(ce->timeline); - if (GEM_WARN_ON(err)) - goto err_ring; + __intel_timeline_pin(ce->timeline); if (ce->state) { GEM_WARN_ON(!i915_active_acquire_if_busy(&ce->state->active)); @@ -321,12 +344,6 @@ static int __intel_context_active(struct i915_active *active) } return 0; - -err_ring: - __ring_retire(ce->ring); -err_put: - intel_context_put(ce); - return err; } void diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h index 07be021882cc..fda2eba81e22 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.h +++ b/drivers/gpu/drm/i915/gt/intel_context.h @@ -25,6 +25,8 @@ ##__VA_ARGS__); \ } while (0) +struct i915_gem_ww_ctx; + void intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine); void intel_context_fini(struct intel_context *ce); @@ -81,6 +83,8 @@ static inline void intel_context_unlock_pinned(struct intel_context *ce) } int __intel_context_do_pin(struct intel_context *ce); +int __intel_context_do_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww); static inline bool intel_context_pin_if_active(struct intel_context *ce) { @@ -95,6 +99,15 @@ static inline int intel_context_pin(struct intel_context *ce) return __intel_context_do_pin(ce); } +static inline int intel_context_pin_ww(struct intel_context *ce, + struct i915_gem_ww_ctx *ww) +{ + if (likely(intel_context_pin_if_active(ce))) + return 0; + + return __intel_context_do_pin_ww(ce, ww); +} + static inline void __intel_context_pin(struct intel_context *ce) { GEM_BUG_ON(!intel_context_is_pinned(ce)); diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index ca8e05b4d3ef..552cb57a2e8c 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -23,6 +23,7 @@ DECLARE_EWMA(runtime, 3, 8); struct i915_gem_context; +struct i915_gem_ww_ctx; struct i915_vma; struct intel_context; struct intel_ring; @@ -30,7 +31,7 @@ struct intel_ring; struct intel_context_ops { int (*alloc)(struct intel_context *ce); - int (*pre_pin)(struct intel_context *ce, void **vaddr); + int (*pre_pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void **vaddr); int (*pin)(struct intel_context *ce, void *vaddr); void (*unpin)(struct intel_context *ce); void (*post_unpin)(struct intel_context *ce); diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index ea4ba2afe9f9..f231edd3fa3a 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -635,7 +635,7 @@ static int pin_ggtt_status_page(struct intel_engine_cs *engine, else flags = PIN_HIGH; - return i915_ggtt_pin(vma, 0, flags); + return i915_ggtt_pin(vma, NULL, 0, flags); } static int init_status_page(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8694ddbdac4c..39b428c5049c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -356,7 +356,7 @@ static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) goto err_unref; } - ret = i915_ggtt_pin(vma, 0, PIN_HIGH); + ret = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (ret) goto err_unref; diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 1f6dc69b2490..47a90dbf8b70 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -3461,7 +3461,8 @@ __execlists_update_reg_state(const struct intel_context *ce, } static int -execlists_context_pre_pin(struct intel_context *ce, void **vaddr) +execlists_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, void **vaddr) { GEM_BUG_ON(!ce->state); GEM_BUG_ON(!i915_vma_is_pinned(ce->state)); @@ -3880,7 +3881,7 @@ static int lrc_setup_wa_ctx(struct intel_engine_cs *engine) goto err; } - err = i915_ggtt_pin(vma, 0, PIN_HIGH); + err = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (err) goto err; diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c index 5164de04049d..ea2a77c7b469 100644 --- a/drivers/gpu/drm/i915/gt/intel_renderstate.c +++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c @@ -184,7 +184,7 @@ int intel_renderstate_init(struct intel_renderstate *so, i915_gem_ww_ctx_init(&so->ww, true); retry: - err = intel_context_pin(ce); + err = intel_context_pin_ww(ce, &so->ww); if (err) goto err_fini; diff --git a/drivers/gpu/drm/i915/gt/intel_ring.c b/drivers/gpu/drm/i915/gt/intel_ring.c index bdb324167ef3..4034a4bac7f0 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.c +++ b/drivers/gpu/drm/i915/gt/intel_ring.c @@ -21,7 +21,13 @@ unsigned int intel_ring_update_space(struct intel_ring *ring) return space; } -int intel_ring_pin(struct intel_ring *ring) +void __intel_ring_pin(struct intel_ring *ring) +{ + GEM_BUG_ON(!atomic_read(&ring->pin_count)); + atomic_inc(&ring->pin_count); +} + +int intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww) { struct i915_vma *vma = ring->vma; unsigned int flags; @@ -39,7 +45,7 @@ int intel_ring_pin(struct intel_ring *ring) else flags |= PIN_HIGH; - ret = i915_ggtt_pin(vma, 0, flags); + ret = i915_ggtt_pin(vma, ww, 0, flags); if (unlikely(ret)) goto err_unpin; diff --git a/drivers/gpu/drm/i915/gt/intel_ring.h b/drivers/gpu/drm/i915/gt/intel_ring.h index cc0ebca65167..1700579bdc93 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring.h +++ b/drivers/gpu/drm/i915/gt/intel_ring.h @@ -21,7 +21,8 @@ int intel_ring_cacheline_align(struct i915_request *rq); unsigned int intel_ring_update_space(struct intel_ring *ring); -int intel_ring_pin(struct intel_ring *ring); +void __intel_ring_pin(struct intel_ring *ring); +int intel_ring_pin(struct intel_ring *ring, struct i915_gem_ww_ctx *ww); void intel_ring_unpin(struct intel_ring *ring); void intel_ring_reset(struct intel_ring *ring, u32 tail); diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 93cf72cfd318..1ca1bac81cf6 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -477,14 +477,16 @@ static void ring_context_destroy(struct kref *ref) intel_context_free(ce); } -static int __context_pin_ppgtt(struct intel_context *ce) +static int ring_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, + void **unused) { struct i915_address_space *vm; int err = 0; vm = vm_alias(ce->vm); if (vm) - err = gen6_ppgtt_pin(i915_vm_to_ppgtt((vm))); + err = gen6_ppgtt_pin(i915_vm_to_ppgtt((vm)), ww); return err; } @@ -591,11 +593,6 @@ static int ring_context_alloc(struct intel_context *ce) return 0; } -static int ring_context_pre_pin(struct intel_context *ce, void **unused) -{ - return __context_pin_ppgtt(ce); -} - static int ring_context_pin(struct intel_context *ce, void *unused) { return 0; @@ -1272,7 +1269,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) } GEM_BUG_ON(timeline->has_initial_breadcrumb); - err = intel_timeline_pin(timeline); + err = intel_timeline_pin(timeline, NULL); if (err) goto err_timeline; @@ -1282,7 +1279,7 @@ int intel_ring_submission_setup(struct intel_engine_cs *engine) goto err_timeline_unpin; } - err = intel_ring_pin(ring); + err = intel_ring_pin(ring, NULL); if (err) goto err_ring; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.c b/drivers/gpu/drm/i915/gt/intel_timeline.c index 2baecf414acb..a2f74cefe4c3 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.c +++ b/drivers/gpu/drm/i915/gt/intel_timeline.c @@ -317,14 +317,20 @@ __intel_timeline_create(struct intel_gt *gt, return timeline; } -int intel_timeline_pin(struct intel_timeline *tl) +void __intel_timeline_pin(struct intel_timeline *tl) +{ + GEM_BUG_ON(!atomic_read(&tl->pin_count)); + atomic_inc(&tl->pin_count); +} + +int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww) { int err; if (atomic_add_unless(&tl->pin_count, 1, 0)) return 0; - err = i915_ggtt_pin(tl->hwsp_ggtt, 0, PIN_HIGH); + err = i915_ggtt_pin(tl->hwsp_ggtt, ww, 0, PIN_HIGH); if (err) return err; @@ -467,7 +473,7 @@ __intel_timeline_get_seqno(struct intel_timeline *tl, goto err_rollback; } - err = i915_ggtt_pin(vma, 0, PIN_HIGH); + err = i915_ggtt_pin(vma, NULL, 0, PIN_HIGH); if (err) { __idle_hwsp_free(vma->private, cacheline); goto err_rollback; diff --git a/drivers/gpu/drm/i915/gt/intel_timeline.h b/drivers/gpu/drm/i915/gt/intel_timeline.h index 06bd06c6595f..9882cd911d8e 100644 --- a/drivers/gpu/drm/i915/gt/intel_timeline.h +++ b/drivers/gpu/drm/i915/gt/intel_timeline.h @@ -88,7 +88,8 @@ static inline bool intel_timeline_sync_is_later(struct intel_timeline *tl, return __intel_timeline_sync_is_later(tl, fence->context, fence->seqno); } -int intel_timeline_pin(struct intel_timeline *tl); +void __intel_timeline_pin(struct intel_timeline *tl); +int intel_timeline_pin(struct intel_timeline *tl, struct i915_gem_ww_ctx *ww); void intel_timeline_enter(struct intel_timeline *tl); int intel_timeline_get_seqno(struct intel_timeline *tl, struct i915_request *rq, diff --git a/drivers/gpu/drm/i915/gt/mock_engine.c b/drivers/gpu/drm/i915/gt/mock_engine.c index c8e631222f23..dfd1cfb8a7ec 100644 --- a/drivers/gpu/drm/i915/gt/mock_engine.c +++ b/drivers/gpu/drm/i915/gt/mock_engine.c @@ -167,7 +167,8 @@ static int mock_context_alloc(struct intel_context *ce) return 0; } -static int mock_context_pre_pin(struct intel_context *ce, void **unused) +static int mock_context_pre_pin(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, void **unused) { return 0; } diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index f749071f54a7..7faba9f91224 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -3089,7 +3089,7 @@ static struct i915_vma *create_global(struct intel_gt *gt, size_t sz) return vma; } - err = i915_ggtt_pin(vma, 0, 0); + err = i915_ggtt_pin(vma, NULL, 0, 0); if (err) { i915_vma_put(vma); return ERR_PTR(err); diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 98ceac2fb77d..96d164a3841d 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -455,7 +455,7 @@ tl_write(struct intel_timeline *tl, struct intel_engine_cs *engine, u32 value) struct i915_request *rq; int err; - err = intel_timeline_pin(tl); + err = intel_timeline_pin(tl, NULL); if (err) { rq = ERR_PTR(err); goto out; @@ -667,7 +667,7 @@ static int live_hwsp_wrap(void *arg) if (!tl->has_initial_breadcrumb || !tl->hwsp_cacheline) goto out_free; - err = intel_timeline_pin(tl); + err = intel_timeline_pin(tl, NULL); if (err) goto out_free; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 861657897c0f..942c7c187adb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -677,7 +677,7 @@ struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) goto err; flags = PIN_OFFSET_BIAS | i915_ggtt_pin_bias(vma); - ret = i915_ggtt_pin(vma, 0, flags); + ret = i915_ggtt_pin(vma, NULL, 0, flags); if (ret) { vma = ERR_PTR(ret); goto err; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2b95467b760a..ab17084af0ff 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1816,11 +1816,18 @@ static inline void i915_gem_drain_workqueue(struct drm_i915_private *i915) } struct i915_vma * __must_check +i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + const struct i915_ggtt_view *view, + u64 size, u64 alignment, u64 flags); + +static inline struct i915_vma * __must_check i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags); + u64 size, u64 alignment, u64 flags) +{ + return i915_gem_object_ggtt_pin_ww(obj, NULL, view, size, alignment, flags); +} int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index f6615d942b60..bb0c12975f38 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -962,11 +962,10 @@ static void discard_ggtt_vma(struct i915_vma *vma) } struct i915_vma * -i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, - const struct i915_ggtt_view *view, - u64 size, - u64 alignment, - u64 flags) +i915_gem_object_ggtt_pin_ww(struct drm_i915_gem_object *obj, + struct i915_gem_ww_ctx *ww, + const struct i915_ggtt_view *view, + u64 size, u64 alignment, u64 flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_ggtt *ggtt = &i915->ggtt; @@ -1032,7 +1031,7 @@ new_vma: return ERR_PTR(ret); } - ret = i915_vma_pin(vma, size, alignment, flags | PIN_GLOBAL); + ret = i915_vma_pin_ww(vma, ww, size, alignment, flags | PIN_GLOBAL); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index c6bf04ca2032..495d28f6d160 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -852,13 +852,19 @@ static void vma_unbind_pages(struct i915_vma *vma) __vma_put_pages(vma, count | count << I915_VMA_PAGES_BIAS); } -int i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) +int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u64 size, u64 alignment, u64 flags) { struct i915_vma_work *work = NULL; intel_wakeref_t wakeref = 0; unsigned int bound; int err; +#ifdef CONFIG_PROVE_LOCKING + if (debug_locks && lockdep_is_held(&vma->vm->i915->drm.struct_mutex)) + WARN_ON(!ww); +#endif + BUILD_BUG_ON(PIN_GLOBAL != I915_VMA_GLOBAL_BIND); BUILD_BUG_ON(PIN_USER != I915_VMA_LOCAL_BIND); @@ -1002,7 +1008,8 @@ static void flush_idle_contexts(struct intel_gt *gt) intel_gt_wait_for_idle(gt, MAX_SCHEDULE_TIMEOUT); } -int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags) +int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u32 align, unsigned int flags) { struct i915_address_space *vm = vma->vm; int err; @@ -1010,7 +1017,7 @@ int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags) GEM_BUG_ON(!i915_vma_is_ggtt(vma)); do { - err = i915_vma_pin(vma, 0, align, flags | PIN_GLOBAL); + err = i915_vma_pin_ww(vma, ww, 0, align, flags | PIN_GLOBAL); if (err != -ENOSPC) { if (!err) { err = i915_vma_wait_for_bind(vma); diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index d0d01f909548..5b3a3c653454 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -237,8 +237,17 @@ static inline void i915_vma_unlock(struct i915_vma *vma) } int __must_check -i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags); -int i915_ggtt_pin(struct i915_vma *vma, u32 align, unsigned int flags); +i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u64 size, u64 alignment, u64 flags); + +static inline int __must_check +i915_vma_pin(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) +{ + return i915_vma_pin_ww(vma, NULL, size, alignment, flags); +} + +int i915_ggtt_pin(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, + u32 align, unsigned int flags); static inline int i915_vma_pin_count(const struct i915_vma *vma) { -- cgit v1.2.3 From 6b05030496f773f35f24299b1bd49dc8aa10a580 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:55 +0200 Subject: drm/i915: Convert i915_gem_object/client_blt.c to use ww locking as well, v2. This is the last part outside of selftests that still don't use the correct lock ordering of timeline->mutex vs resv_lock. With gem fixed, there are a few places that still get locking wrong: - gvt/scheduler.c - i915_perf.c - Most if not all selftests. Changes since v1: - Add intel_engine_pm_get/put() calls to fix use-after-free when using intel_engine_get_pool(). Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-16-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_client_blt.c | 78 ++++++++++--- drivers/gpu/drm/i915/gem/i915_gem_object_blt.c | 152 ++++++++++++++++--------- drivers/gpu/drm/i915/gem/i915_gem_object_blt.h | 3 + 3 files changed, 163 insertions(+), 70 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index a85907f29c53..272cf3ea68d5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -158,6 +158,7 @@ static void clear_pages_worker(struct work_struct *work) struct clear_pages_work *w = container_of(work, typeof(*w), work); struct drm_i915_gem_object *obj = w->sleeve->vma->obj; struct i915_vma *vma = w->sleeve->vma; + struct i915_gem_ww_ctx ww; struct i915_request *rq; struct i915_vma *batch; int err = w->dma.error; @@ -173,17 +174,20 @@ static void clear_pages_worker(struct work_struct *work) obj->read_domains = I915_GEM_GPU_DOMAINS; obj->write_domain = 0; - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (unlikely(err)) + i915_gem_ww_ctx_init(&ww, false); + intel_engine_pm_get(w->ce->engine); +retry: + err = intel_context_pin_ww(w->ce, &ww); + if (err) goto out_signal; - batch = intel_emit_vma_fill_blt(w->ce, vma, w->value); + batch = intel_emit_vma_fill_blt(w->ce, vma, &ww, w->value); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto out_unpin; + goto out_ctx; } - rq = intel_context_create_request(w->ce); + rq = i915_request_create(w->ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -225,9 +229,19 @@ out_request: i915_request_add(rq); out_batch: intel_emit_vma_release(w->ce, batch); -out_unpin: - i915_vma_unpin(vma); +out_ctx: + intel_context_unpin(w->ce); out_signal: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + i915_vma_unpin(w->sleeve->vma); + intel_engine_pm_put(w->ce->engine); + if (unlikely(err)) { dma_fence_set_error(&w->dma, err); dma_fence_signal(&w->dma); @@ -235,6 +249,44 @@ out_signal: } } +static int pin_wait_clear_pages_work(struct clear_pages_work *w, + struct intel_context *ce) +{ + struct i915_vma *vma = w->sleeve->vma; + struct i915_gem_ww_ctx ww; + int err; + + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out; + + err = i915_sw_fence_await_reservation(&w->wait, + vma->obj->base.resv, NULL, + true, 0, I915_FENCE_GFP); + if (err) + goto err_unpin_vma; + + dma_resv_add_excl_fence(vma->obj->base.resv, &w->dma); + +err_unpin_vma: + if (err) + i915_vma_unpin(vma); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + return err; +} + static int __i915_sw_fence_call clear_pages_work_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) @@ -288,17 +340,9 @@ int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj, dma_fence_init(&work->dma, &clear_pages_work_ops, &fence_lock, 0, 0); i915_sw_fence_init(&work->wait, clear_pages_work_notify); - i915_gem_object_lock(obj, NULL); - err = i915_sw_fence_await_reservation(&work->wait, - obj->base.resv, NULL, true, 0, - I915_FENCE_GFP); - if (err < 0) { + err = pin_wait_clear_pages_work(work, ce); + if (err < 0) dma_fence_set_error(&work->dma, err); - } else { - dma_resv_add_excl_fence(obj->base.resv, &work->dma); - err = 0; - } - i915_gem_object_unlock(obj); dma_fence_get(&work->dma); i915_sw_fence_commit(&work->wait); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c index bfdb32d46877..d93eb36160c9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.c @@ -14,6 +14,7 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, struct i915_vma *vma, + struct i915_gem_ww_ctx *ww, u32 value) { struct drm_i915_private *i915 = ce->vm->i915; @@ -39,10 +40,24 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, goto out_pm; } + err = i915_gem_object_lock(pool->obj, ww); + if (err) + goto out_put; + + batch = i915_vma_instance(pool->obj, ce->vm, NULL); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto out_put; + } + + err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out_put; + cmd = i915_gem_object_pin_map(pool->obj, I915_MAP_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_put; + goto out_unpin; } rem = vma->size; @@ -84,19 +99,11 @@ struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, intel_gt_chipset_flush(ce->vm->gt); - batch = i915_vma_instance(pool->obj, ce->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_put; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER); - if (unlikely(err)) - goto out_put; - batch->private = pool; return batch; +out_unpin: + i915_vma_unpin(batch); out_put: intel_gt_buffer_pool_put(pool); out_pm: @@ -108,11 +115,9 @@ int intel_emit_vma_mark_active(struct i915_vma *vma, struct i915_request *rq) { int err; - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (err == 0) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); if (unlikely(err)) return err; @@ -141,6 +146,7 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, struct intel_context *ce, u32 value) { + struct i915_gem_ww_ctx ww; struct i915_request *rq; struct i915_vma *batch; struct i915_vma *vma; @@ -150,17 +156,28 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (unlikely(err)) - return err; + i915_gem_ww_ctx_init(&ww, true); + intel_engine_pm_get(ce->engine); +retry: + err = i915_gem_object_lock(obj, &ww); + if (err) + goto out; - batch = intel_emit_vma_fill_blt(ce, vma, value); + err = intel_context_pin_ww(ce, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (err) + goto out_ctx; + + batch = intel_emit_vma_fill_blt(ce, vma, &ww, value); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto out_unpin; + goto out_vma; } - rq = intel_context_create_request(ce); + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -170,11 +187,9 @@ int i915_gem_object_fill_blt(struct drm_i915_gem_object *obj, if (unlikely(err)) goto out_request; - i915_vma_lock(vma); err = move_obj_to_gpu(vma->obj, rq, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); if (unlikely(err)) goto out_request; @@ -193,8 +208,18 @@ out_request: i915_request_add(rq); out_batch: intel_emit_vma_release(ce, batch); -out_unpin: +out_vma: i915_vma_unpin(vma); +out_ctx: + intel_context_unpin(ce); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); return err; } @@ -210,6 +235,7 @@ static bool wa_1209644611_applies(struct drm_i915_private *i915, u32 size) } struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, struct i915_vma *src, struct i915_vma *dst) { @@ -236,10 +262,24 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, goto out_pm; } + err = i915_gem_object_lock(pool->obj, ww); + if (err) + goto out_put; + + batch = i915_vma_instance(pool->obj, ce->vm, NULL); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto out_put; + } + + err = i915_vma_pin_ww(batch, ww, 0, 0, PIN_USER); + if (unlikely(err)) + goto out_put; + cmd = i915_gem_object_pin_map(pool->obj, I915_MAP_WC); if (IS_ERR(cmd)) { err = PTR_ERR(cmd); - goto out_put; + goto out_unpin; } rem = src->size; @@ -296,20 +336,11 @@ struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, i915_gem_object_unpin_map(pool->obj); intel_gt_chipset_flush(ce->vm->gt); - - batch = i915_vma_instance(pool->obj, ce->vm, NULL); - if (IS_ERR(batch)) { - err = PTR_ERR(batch); - goto out_put; - } - - err = i915_vma_pin(batch, 0, 0, PIN_USER); - if (unlikely(err)) - goto out_put; - batch->private = pool; return batch; +out_unpin: + i915_vma_unpin(batch); out_put: intel_gt_buffer_pool_put(pool); out_pm: @@ -321,10 +352,9 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, struct drm_i915_gem_object *dst, struct intel_context *ce) { - struct drm_gem_object *objs[] = { &src->base, &dst->base }; struct i915_address_space *vm = ce->vm; struct i915_vma *vma[2], *batch; - struct ww_acquire_ctx acquire; + struct i915_gem_ww_ctx ww; struct i915_request *rq; int err, i; @@ -332,25 +362,36 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, if (IS_ERR(vma[0])) return PTR_ERR(vma[0]); - err = i915_vma_pin(vma[0], 0, 0, PIN_USER); - if (unlikely(err)) - return err; - vma[1] = i915_vma_instance(dst, vm, NULL); if (IS_ERR(vma[1])) - goto out_unpin_src; + return PTR_ERR(vma); - err = i915_vma_pin(vma[1], 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, true); + intel_engine_pm_get(ce->engine); +retry: + err = i915_gem_object_lock(src, &ww); + if (!err) + err = i915_gem_object_lock(dst, &ww); + if (!err) + err = intel_context_pin_ww(ce, &ww); + if (err) + goto out; + + err = i915_vma_pin_ww(vma[0], &ww, 0, 0, PIN_USER); + if (err) + goto out_ctx; + + err = i915_vma_pin_ww(vma[1], &ww, 0, 0, PIN_USER); if (unlikely(err)) goto out_unpin_src; - batch = intel_emit_vma_copy_blt(ce, vma[0], vma[1]); + batch = intel_emit_vma_copy_blt(ce, &ww, vma[0], vma[1]); if (IS_ERR(batch)) { err = PTR_ERR(batch); goto out_unpin_dst; } - rq = intel_context_create_request(ce); + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto out_batch; @@ -360,14 +401,10 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, if (unlikely(err)) goto out_request; - err = drm_gem_lock_reservations(objs, ARRAY_SIZE(objs), &acquire); - if (unlikely(err)) - goto out_request; - for (i = 0; i < ARRAY_SIZE(vma); i++) { err = move_obj_to_gpu(vma[i]->obj, rq, i); if (unlikely(err)) - goto out_unlock; + goto out_request; } for (i = 0; i < ARRAY_SIZE(vma); i++) { @@ -375,20 +412,19 @@ int i915_gem_object_copy_blt(struct drm_i915_gem_object *src, err = i915_vma_move_to_active(vma[i], rq, flags); if (unlikely(err)) - goto out_unlock; + goto out_request; } if (rq->engine->emit_init_breadcrumb) { err = rq->engine->emit_init_breadcrumb(rq); if (unlikely(err)) - goto out_unlock; + goto out_request; } err = rq->engine->emit_bb_start(rq, batch->node.start, batch->node.size, 0); -out_unlock: - drm_gem_unlock_reservations(objs, ARRAY_SIZE(objs), &acquire); + out_request: if (unlikely(err)) i915_request_set_error_once(rq, err); @@ -400,6 +436,16 @@ out_unpin_dst: i915_vma_unpin(vma[1]); out_unpin_src: i915_vma_unpin(vma[0]); +out_ctx: + intel_context_unpin(ce); +out: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); return err; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h index 8bcd336a90dc..2409fdcccf0e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_blt.h @@ -13,12 +13,15 @@ #include "i915_vma.h" struct drm_i915_gem_object; +struct i915_gem_ww_ctx; struct i915_vma *intel_emit_vma_fill_blt(struct intel_context *ce, struct i915_vma *vma, + struct i915_gem_ww_ctx *ww, u32 value); struct i915_vma *intel_emit_vma_copy_blt(struct intel_context *ce, + struct i915_gem_ww_ctx *ww, struct i915_vma *src, struct i915_vma *dst); -- cgit v1.2.3 From c8d225946a7803230ae48fead6652b6b5943233f Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:56 +0200 Subject: drm/i915: Kill last user of intel_context_create_request outside of selftests Instead of using intel_context_create_request(), use intel_context_pin() and i915_create_request directly. Now all those calls are gone outside of selftests. :) Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-17-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 43 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index be5a4685c991..a3f72b75c61e 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2088,6 +2088,7 @@ static int engine_wa_list_verify(struct intel_context *ce, const struct i915_wa *wa; struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; unsigned int i; u32 *results; int err; @@ -2100,29 +2101,34 @@ static int engine_wa_list_verify(struct intel_context *ce, return PTR_ERR(vma); intel_engine_pm_get(ce->engine); - rq = intel_context_create_request(ce); - intel_engine_pm_put(ce->engine); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err == 0) + err = intel_context_pin_ww(ce, &ww); + if (err) + goto err_pm; + + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_vma; + goto err_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - if (err) { - i915_request_add(rq); - goto err_vma; - } - - err = wa_list_srm(rq, wal, vma); - if (err) - goto err_vma; + if (err == 0) + err = wa_list_srm(rq, wal, vma); i915_request_get(rq); + if (err) + i915_request_set_error_once(rq, err); i915_request_add(rq); + + if (err) + goto err_rq; + if (i915_request_wait(rq, 0, HZ / 5) < 0) { err = -ETIME; goto err_rq; @@ -2147,7 +2153,16 @@ static int engine_wa_list_verify(struct intel_context *ce, err_rq: i915_request_put(rq); -err_vma: +err_unpin: + intel_context_unpin(ce); +err_pm: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + intel_engine_pm_put(ce->engine); i915_vma_unpin(vma); i915_vma_put(vma); return err; -- cgit v1.2.3 From f00ecc2ef55861c3cbc3dde93c082b612114efdc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:57 +0200 Subject: drm/i915: Convert i915_perf to ww locking as well We have the ordering of timeline->mutex vs resv_lock wrong, convert the i915_pin_vma and intel_context_pin as well to future-proof this. We may need to do future changes to do this more transaction-like, and only get down to a single i915_gem_ww_ctx, but for now this should work. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-18-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_perf.c | 57 +++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index c6f6370283cf..e94976976571 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -1195,24 +1195,39 @@ static struct intel_context *oa_pin_context(struct i915_perf_stream *stream) struct i915_gem_engines_iter it; struct i915_gem_context *ctx = stream->ctx; struct intel_context *ce; - int err; + struct i915_gem_ww_ctx ww; + int err = -ENODEV; for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) { if (ce->engine != stream->engine) /* first match! */ continue; - /* - * As the ID is the gtt offset of the context's vma we - * pin the vma to ensure the ID remains fixed. - */ - err = intel_context_pin(ce); - if (err == 0) { - stream->pinned_ctx = ce; - break; - } + err = 0; + break; } i915_gem_context_unlock_engines(ctx); + if (err) + return ERR_PTR(err); + + i915_gem_ww_ctx_init(&ww, true); +retry: + /* + * As the ID is the gtt offset of the context's vma we + * pin the vma to ensure the ID remains fixed. + */ + err = intel_context_pin_ww(ce, &ww); + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + if (err) + return ERR_PTR(err); + + stream->pinned_ctx = ce; return stream->pinned_ctx; } @@ -1923,15 +1938,22 @@ emit_oa_config(struct i915_perf_stream *stream, { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; int err; vma = get_oa_vma(stream, oa_config); if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL | PIN_HIGH); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = i915_gem_object_lock(vma->obj, &ww); + if (err) + goto err; + + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_GLOBAL | PIN_HIGH); if (err) - goto err_vma_put; + goto err; intel_engine_pm_get(ce->engine); rq = i915_request_create(ce); @@ -1953,11 +1975,9 @@ emit_oa_config(struct i915_perf_stream *stream, goto err_add_request; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, 0); if (!err) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); if (err) goto err_add_request; @@ -1971,7 +1991,14 @@ err_add_request: i915_request_add(rq); err_vma_unpin: i915_vma_unpin(vma); -err_vma_put: +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + + i915_gem_ww_ctx_fini(&ww); i915_vma_put(vma); return err; } -- cgit v1.2.3 From dd878c0cec75530ca3ffdb6c759f798eb91cc1df Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:58 +0200 Subject: drm/i915: Dirty hack to fix selftests locking inversion Some i915 selftests still use i915_vma_lock() as inner lock, and intel_context_create_request() intel_timeline->mutex as outer lock. Fortunately for selftests this is not an issue, they should be fixed but we can move ahead and cleanify lockdep now. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-19-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_context.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index c05ef213bdc2..671081b0e4d6 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -459,6 +459,18 @@ struct i915_request *intel_context_create_request(struct intel_context *ce) rq = i915_request_create(ce); intel_context_unpin(ce); + if (IS_ERR(rq)) + return rq; + + /* + * timeline->mutex should be the inner lock, but is used as outer lock. + * Hack around this to shut up lockdep in selftests.. + */ + lockdep_unpin_lock(&ce->timeline->mutex, rq->cookie); + mutex_release(&ce->timeline->mutex.dep_map, _RET_IP_); + mutex_acquire(&ce->timeline->mutex.dep_map, SINGLE_DEPTH_NESTING, 0, _RET_IP_); + rq->cookie = lockdep_pin_lock(&ce->timeline->mutex); + return rq; } -- cgit v1.2.3 From 052e04f170561b38665fd227365c523347bdba03 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:08:59 +0200 Subject: drm/i915/selftests: Fix locking inversion in lrc selftest. This function does not use intel_context_create_request, so it has to use the same locking order as normal code. This is required to shut up lockdep in selftests. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-20-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/selftest_lrc.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 7faba9f91224..95d41c01d0e0 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -4996,6 +4996,7 @@ static int __live_lrc_state(struct intel_engine_cs *engine, { struct intel_context *ce; struct i915_request *rq; + struct i915_gem_ww_ctx ww; enum { RING_START_IDX = 0, RING_TAIL_IDX, @@ -5010,7 +5011,11 @@ static int __live_lrc_state(struct intel_engine_cs *engine, if (IS_ERR(ce)) return PTR_ERR(ce); - err = intel_context_pin(ce); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(scratch->obj, &ww); + if (!err) + err = intel_context_pin_ww(ce, &ww); if (err) goto err_put; @@ -5039,11 +5044,9 @@ static int __live_lrc_state(struct intel_engine_cs *engine, *cs++ = i915_ggtt_offset(scratch) + RING_TAIL_IDX * sizeof(u32); *cs++ = 0; - i915_vma_lock(scratch); err = i915_request_await_object(rq, scratch->obj, true); if (!err) err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(scratch); i915_request_get(rq); i915_request_add(rq); @@ -5080,6 +5083,12 @@ err_rq: err_unpin: intel_context_unpin(ce); err_put: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); intel_context_put(ce); return err; } -- cgit v1.2.3 From 8a929c9eb1c298e7f12ce9062e57bd00d2c40bc3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:09:00 +0200 Subject: drm/i915: Use ww pinning for intel_context_create_request() We want to get rid of intel_context_pin(), convert intel_context_create_request() first. :) Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-21-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_context.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 671081b0e4d6..61b05cd4c47a 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -449,15 +449,25 @@ int intel_context_prepare_remote_request(struct intel_context *ce, struct i915_request *intel_context_create_request(struct intel_context *ce) { + struct i915_gem_ww_ctx ww; struct i915_request *rq; int err; - err = intel_context_pin(ce); - if (unlikely(err)) - return ERR_PTR(err); + i915_gem_ww_ctx_init(&ww, true); +retry: + err = intel_context_pin_ww(ce, &ww); + if (!err) { + rq = i915_request_create(ce); + intel_context_unpin(ce); + } else if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } else { + rq = ERR_PTR(err); + } - rq = i915_request_create(ce); - intel_context_unpin(ce); + i915_gem_ww_ctx_fini(&ww); if (IS_ERR(rq)) return rq; -- cgit v1.2.3 From 15b6c92498704975b741a87c5c85d7b7f2489790 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:09:01 +0200 Subject: drm/i915: Move i915_vma_lock in the selftests to avoid lock inversion, v3. Make sure vma_lock is not used as inner lock when kernel context is used, and add ww handling where appropriate. Ensure that execbuf selftests keep passing by using ww handling. Changes since v2: - Fix i915_gem_context finally. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-22-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- .../drm/i915/gem/selftests/i915_gem_coherency.c | 26 ++--- .../gpu/drm/i915/gem/selftests/i915_gem_context.c | 106 ++++++++++----------- drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 41 ++++++-- drivers/gpu/drm/i915/gt/selftest_rps.c | 30 +++--- drivers/gpu/drm/i915/selftests/i915_request.c | 18 ++-- 5 files changed, 125 insertions(+), 96 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c index dcdfc396f2f8..7049a6bbc03d 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c @@ -201,25 +201,25 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) i915_gem_object_lock(ctx->obj, NULL); err = i915_gem_object_set_to_gtt_domain(ctx->obj, true); - i915_gem_object_unlock(ctx->obj); if (err) - return err; + goto out_unlock; vma = i915_gem_object_ggtt_pin(ctx->obj, NULL, 0, 0, 0); - if (IS_ERR(vma)) - return PTR_ERR(vma); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_unlock; + } rq = intel_engine_create_kernel_request(ctx->engine); if (IS_ERR(rq)) { - i915_vma_unpin(vma); - return PTR_ERR(rq); + err = PTR_ERR(rq); + goto out_unpin; } cs = intel_ring_begin(rq, 4); if (IS_ERR(cs)) { - i915_request_add(rq); - i915_vma_unpin(vma); - return PTR_ERR(cs); + err = PTR_ERR(cs); + goto out_rq; } if (INTEL_GEN(ctx->engine->i915) >= 8) { @@ -240,14 +240,16 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v) } intel_ring_advance(rq, cs); - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); - i915_vma_unpin(vma); +out_rq: i915_request_add(rq); +out_unpin: + i915_vma_unpin(vma); +out_unlock: + i915_gem_object_unlock(ctx->obj); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index fa40006b453a..99becb86abd3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -893,24 +893,15 @@ out_file: return err; } -static struct i915_vma *rpcs_query_batch(struct i915_vma *vma) +static int rpcs_query_batch(struct drm_i915_gem_object *rpcs, struct i915_vma *vma) { - struct drm_i915_gem_object *obj; u32 *cmd; - int err; - if (INTEL_GEN(vma->vm->i915) < 8) - return ERR_PTR(-EINVAL); + GEM_BUG_ON(INTEL_GEN(vma->vm->i915) < 8); - obj = i915_gem_object_create_internal(vma->vm->i915, PAGE_SIZE); - if (IS_ERR(obj)) - return ERR_CAST(obj); - - cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); - if (IS_ERR(cmd)) { - err = PTR_ERR(cmd); - goto err; - } + cmd = i915_gem_object_pin_map(rpcs, I915_MAP_WB); + if (IS_ERR(cmd)) + return PTR_ERR(cmd); *cmd++ = MI_STORE_REGISTER_MEM_GEN8; *cmd++ = i915_mmio_reg_offset(GEN8_R_PWR_CLK_STATE); @@ -918,26 +909,12 @@ static struct i915_vma *rpcs_query_batch(struct i915_vma *vma) *cmd++ = upper_32_bits(vma->node.start); *cmd = MI_BATCH_BUFFER_END; - __i915_gem_object_flush_map(obj, 0, 64); - i915_gem_object_unpin_map(obj); + __i915_gem_object_flush_map(rpcs, 0, 64); + i915_gem_object_unpin_map(rpcs); intel_gt_chipset_flush(vma->vm->gt); - vma = i915_vma_instance(obj, vma->vm, NULL); - if (IS_ERR(vma)) { - err = PTR_ERR(vma); - goto err; - } - - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) - goto err; - - return vma; - -err: - i915_gem_object_put(obj); - return ERR_PTR(err); + return 0; } static int @@ -945,52 +922,68 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, struct intel_context *ce, struct i915_request **rq_out) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct i915_request *rq; + struct i915_gem_ww_ctx ww; struct i915_vma *batch; struct i915_vma *vma; + struct drm_i915_gem_object *rpcs; int err; GEM_BUG_ON(!intel_engine_can_store_dword(ce->engine)); + if (INTEL_GEN(i915) < 8) + return -EINVAL; + vma = i915_vma_instance(obj, ce->vm, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); - i915_gem_object_lock(obj, NULL); - err = i915_gem_object_set_to_gtt_domain(obj, false); - i915_gem_object_unlock(obj); - if (err) - return err; + rpcs = i915_gem_object_create_internal(i915, PAGE_SIZE); + if (IS_ERR(rpcs)) + return PTR_ERR(rpcs); - err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) - return err; - - batch = rpcs_query_batch(vma); + batch = i915_vma_instance(rpcs, ce->vm, NULL); if (IS_ERR(batch)) { err = PTR_ERR(batch); - goto err_vma; + goto err_put; } + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_gem_object_lock(rpcs, &ww); + if (!err) + err = i915_gem_object_set_to_gtt_domain(obj, false); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); + if (err) + goto err_put; + + err = i915_vma_pin_ww(batch, &ww, 0, 0, PIN_USER); + if (err) + goto err_vma; + + err = rpcs_query_batch(rpcs, vma); + if (err) + goto err_batch; + rq = i915_request_create(ce); if (IS_ERR(rq)) { err = PTR_ERR(rq); goto err_batch; } - i915_vma_lock(batch); err = i915_request_await_object(rq, batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, rq, 0); - i915_vma_unlock(batch); if (err) goto skip_request; - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); if (err) goto skip_request; @@ -1006,23 +999,24 @@ emit_rpcs_query(struct drm_i915_gem_object *obj, if (err) goto skip_request; - i915_vma_unpin_and_release(&batch, 0); - i915_vma_unpin(vma); - *rq_out = i915_request_get(rq); - i915_request_add(rq); - - return 0; - skip_request: - i915_request_set_error_once(rq, err); + if (err) + i915_request_set_error_once(rq, err); i915_request_add(rq); err_batch: - i915_vma_unpin_and_release(&batch, 0); + i915_vma_unpin(batch); err_vma: i915_vma_unpin(vma); - +err_put: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + i915_gem_object_put(rpcs); return err; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 9fb95a45bcad..d27d87a678c8 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -528,31 +528,42 @@ static int make_obj_busy(struct drm_i915_gem_object *obj) for_each_uabi_engine(engine, i915) { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; int err; vma = i915_vma_instance(obj, &engine->gt->ggtt->vm, NULL); if (IS_ERR(vma)) return PTR_ERR(vma); - err = i915_vma_pin(vma, 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); if (err) - return err; + goto err; rq = intel_engine_create_kernel_request(engine); if (IS_ERR(rq)) { - i915_vma_unpin(vma); - return PTR_ERR(rq); + err = PTR_ERR(rq); + goto err_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, true); if (err == 0) err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); - i915_vma_unlock(vma); i915_request_add(rq); +err_unpin: i915_vma_unpin(vma); +err: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); if (err) return err; } @@ -1123,6 +1134,7 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, for_each_uabi_engine(engine, i915) { struct i915_request *rq; struct i915_vma *vma; + struct i915_gem_ww_ctx ww; vma = i915_vma_instance(obj, engine->kernel_context->vm, NULL); if (IS_ERR(vma)) { @@ -1130,9 +1142,13 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, goto out_unmap; } - err = i915_vma_pin(vma, 0, 0, PIN_USER); + i915_gem_ww_ctx_init(&ww, false); +retry: + err = i915_gem_object_lock(obj, &ww); + if (!err) + err = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_USER); if (err) - goto out_unmap; + goto out_ww; rq = i915_request_create(engine->kernel_context); if (IS_ERR(rq)) { @@ -1140,11 +1156,9 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, goto out_unpin; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (err == 0) err = i915_vma_move_to_active(vma, rq, 0); - i915_vma_unlock(vma); err = engine->emit_bb_start(rq, vma->node.start, 0, 0); i915_request_get(rq); @@ -1166,6 +1180,13 @@ static int __igt_mmap_gpu(struct drm_i915_private *i915, out_unpin: i915_vma_unpin(vma); +out_ww: + if (err == -EDEADLK) { + err = i915_gem_ww_ctx_backoff(&ww); + if (!err) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); if (err) goto out_unmap; } diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c index 34b403d47840..3540ba9bd459 100644 --- a/drivers/gpu/drm/i915/gt/selftest_rps.c +++ b/drivers/gpu/drm/i915/gt/selftest_rps.c @@ -77,20 +77,20 @@ create_spin_counter(struct intel_engine_cs *engine, vma = i915_vma_instance(obj, vm, NULL); if (IS_ERR(vma)) { - i915_gem_object_put(obj); - return vma; + err = PTR_ERR(vma); + goto err_put; } err = i915_vma_pin(vma, 0, 0, PIN_USER); - if (err) { - i915_vma_put(vma); - return ERR_PTR(err); - } + if (err) + goto err_unlock; + + i915_vma_lock(vma); base = i915_gem_object_pin_map(obj, I915_MAP_WC); if (IS_ERR(base)) { - i915_gem_object_put(obj); - return ERR_CAST(base); + err = PTR_ERR(base); + goto err_unpin; } cs = base; @@ -134,6 +134,14 @@ create_spin_counter(struct intel_engine_cs *engine, *cancel = base + loop; *counter = srm ? memset32(base + end, 0, 1) : NULL; return vma; + +err_unpin: + i915_vma_unpin(vma); +err_unlock: + i915_vma_unlock(vma); +err_put: + i915_gem_object_put(obj); + return ERR_PTR(err); } static u8 wait_for_freq(struct intel_rps *rps, u8 freq, int timeout_ms) @@ -639,7 +647,6 @@ int live_rps_frequency_cs(void *arg) goto err_vma; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (!err) err = i915_vma_move_to_active(vma, rq, 0); @@ -647,7 +654,6 @@ int live_rps_frequency_cs(void *arg) err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); - i915_vma_unlock(vma); i915_request_add(rq); if (err) goto err_vma; @@ -708,6 +714,7 @@ err_vma: i915_gem_object_flush_map(vma->obj); i915_gem_object_unpin_map(vma->obj); i915_vma_unpin(vma); + i915_vma_unlock(vma); i915_vma_put(vma); st_engine_heartbeat_enable(engine); @@ -781,7 +788,6 @@ int live_rps_frequency_srm(void *arg) goto err_vma; } - i915_vma_lock(vma); err = i915_request_await_object(rq, vma->obj, false); if (!err) err = i915_vma_move_to_active(vma, rq, 0); @@ -789,7 +795,6 @@ int live_rps_frequency_srm(void *arg) err = rq->engine->emit_bb_start(rq, vma->node.start, PAGE_SIZE, 0); - i915_vma_unlock(vma); i915_request_add(rq); if (err) goto err_vma; @@ -849,6 +854,7 @@ err_vma: i915_gem_object_flush_map(vma->obj); i915_gem_object_unpin_map(vma->obj); i915_vma_unpin(vma); + i915_vma_unlock(vma); i915_vma_put(vma); st_engine_heartbeat_enable(engine); diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c index c1dcd4b91bda..3092ca763789 100644 --- a/drivers/gpu/drm/i915/selftests/i915_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_request.c @@ -862,6 +862,8 @@ static int live_all_engines(void *arg) goto out_free; } + i915_vma_lock(batch); + idx = 0; for_each_uabi_engine(engine, i915) { request[idx] = intel_engine_create_kernel_request(engine); @@ -872,11 +874,9 @@ static int live_all_engines(void *arg) goto out_request; } - i915_vma_lock(batch); err = i915_request_await_object(request[idx], batch->obj, 0); if (err == 0) err = i915_vma_move_to_active(batch, request[idx], 0); - i915_vma_unlock(batch); GEM_BUG_ON(err); err = engine->emit_bb_start(request[idx], @@ -891,6 +891,8 @@ static int live_all_engines(void *arg) idx++; } + i915_vma_unlock(batch); + idx = 0; for_each_uabi_engine(engine, i915) { if (i915_request_completed(request[idx])) { @@ -981,12 +983,13 @@ static int live_sequential_engines(void *arg) goto out_free; } + i915_vma_lock(batch); request[idx] = intel_engine_create_kernel_request(engine); if (IS_ERR(request[idx])) { err = PTR_ERR(request[idx]); pr_err("%s: Request allocation failed for %s with err=%d\n", __func__, engine->name, err); - goto out_request; + goto out_unlock; } if (prev) { @@ -996,16 +999,14 @@ static int live_sequential_engines(void *arg) i915_request_add(request[idx]); pr_err("%s: Request await failed for %s with err=%d\n", __func__, engine->name, err); - goto out_request; + goto out_unlock; } } - i915_vma_lock(batch); err = i915_request_await_object(request[idx], batch->obj, false); if (err == 0) err = i915_vma_move_to_active(batch, request[idx], 0); - i915_vma_unlock(batch); GEM_BUG_ON(err); err = engine->emit_bb_start(request[idx], @@ -1020,6 +1021,11 @@ static int live_sequential_engines(void *arg) prev = request[idx]; idx++; + +out_unlock: + i915_vma_unlock(batch); + if (err) + goto out_request; } idx = 0; -- cgit v1.2.3 From 3c0ffa277ef6fb3a26ff0be730564b1bd81ca139 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:09:02 +0200 Subject: drm/i915: Add ww locking to vm_fault_gtt We want to start requiring the reservation_lock instead of obj->mm.lock for pinning objects, take the ww lock inside vm_fault_gtt as a first step towards the legacy lock removal. Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-23-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 51 +++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index b23368529a40..548ed9fb427d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -283,37 +283,46 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) struct intel_runtime_pm *rpm = &i915->runtime_pm; struct i915_ggtt *ggtt = &i915->ggtt; bool write = area->vm_flags & VM_WRITE; + struct i915_gem_ww_ctx ww; intel_wakeref_t wakeref; struct i915_vma *vma; pgoff_t page_offset; int srcu; int ret; - /* Sanity check that we allow writing into this object */ - if (i915_gem_object_is_readonly(obj) && write) - return VM_FAULT_SIGBUS; - /* We don't use vmf->pgoff since that has the fake offset */ page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT; trace_i915_gem_object_fault(obj, page_offset, true, write); - ret = i915_gem_object_pin_pages(obj); + wakeref = intel_runtime_pm_get(rpm); + + i915_gem_ww_ctx_init(&ww, true); +retry: + ret = i915_gem_object_lock(obj, &ww); if (ret) - goto err; + goto err_rpm; - wakeref = intel_runtime_pm_get(rpm); + /* Sanity check that we allow writing into this object */ + if (i915_gem_object_is_readonly(obj) && write) { + ret = -EFAULT; + goto err_rpm; + } - ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu); + ret = i915_gem_object_pin_pages(obj); if (ret) goto err_rpm; + ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu); + if (ret) + goto err_pages; + /* Now pin it into the GTT as needed */ - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | - PIN_NONBLOCK /* NOWARN */ | - PIN_NOEVICT); - if (IS_ERR(vma)) { + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { /* Use a partial view if it is bigger than available space */ struct i915_ggtt_view view = compute_partial_view(obj, page_offset, MIN_CHUNK_PAGES); @@ -328,11 +337,11 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) * all hope that the hardware is able to track future writes. */ - vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); - if (IS_ERR(vma)) { + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) { flags = PIN_MAPPABLE; view.type = I915_GGTT_VIEW_PARTIAL; - vma = i915_gem_object_ggtt_pin(obj, &view, 0, 0, flags); + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, &view, 0, 0, flags); } /* The entire mappable GGTT is pinned? Unexpected! */ @@ -389,10 +398,16 @@ err_unpin: __i915_vma_unpin(vma); err_reset: intel_gt_reset_unlock(ggtt->vm.gt, srcu); +err_pages: + i915_gem_object_unpin_pages(obj); err_rpm: + if (ret == -EDEADLK) { + ret = i915_gem_ww_ctx_backoff(&ww); + if (!ret) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); intel_runtime_pm_put(rpm, wakeref); - i915_gem_object_unpin_pages(obj); -err: return i915_error_to_vmf_fault(ret); } -- cgit v1.2.3 From c1793ba86a41f420a3497d08c5755210783656bc Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Wed, 19 Aug 2020 16:09:03 +0200 Subject: drm/i915: Add ww locking to pin_to_display_plane, v2. Use ww locking for pin_to_display_plane for all the pinning and locking. With the locking removed from set_cache_level, we need to fix i915_gem_set_caching_ioctl to take the object reservation lock. As this is a single lock, we don't need to use the ww dance. Changes since v1: - Do not use ww locking in i915_gem_set_caching_ioctl (Thomas). Signed-off-by: Maarten Lankhorst Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20200819140904.1708856-24-maarten.lankhorst@linux.intel.com Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gem/i915_gem_domain.c | 56 +++++++++++++++++++++--------- drivers/gpu/drm/i915/gem/i915_gem_object.h | 1 + 2 files changed, 41 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_domain.c b/drivers/gpu/drm/i915/gem/i915_gem_domain.c index 8ebceebd11b0..7c90a63c273d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_domain.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_domain.c @@ -37,6 +37,12 @@ void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) i915_gem_object_unlock(obj); } +void i915_gem_object_flush_if_display_locked(struct drm_i915_gem_object *obj) +{ + if (i915_gem_object_is_framebuffer(obj)) + __i915_gem_object_flush_for_display(obj); +} + /** * Moves a single object to the WC read, and possibly write domain. * @obj: object to act on @@ -197,18 +203,12 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, if (ret) return ret; - ret = i915_gem_object_lock_interruptible(obj, NULL); - if (ret) - return ret; - /* Always invalidate stale cachelines */ if (obj->cache_level != cache_level) { i915_gem_object_set_cache_coherency(obj, cache_level); obj->cache_dirty = true; } - i915_gem_object_unlock(obj); - /* The cache-level will be applied when each vma is rebound. */ return i915_gem_object_unbind(obj, I915_GEM_OBJECT_UNBIND_ACTIVE | @@ -293,7 +293,12 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, goto out; } + ret = i915_gem_object_lock_interruptible(obj, NULL); + if (ret) + goto out; + ret = i915_gem_object_set_cache_level(obj, level); + i915_gem_object_unlock(obj); out: i915_gem_object_put(obj); @@ -313,6 +318,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, unsigned int flags) { struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_gem_ww_ctx ww; struct i915_vma *vma; int ret; @@ -320,6 +326,11 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, if (HAS_LMEM(i915) && !i915_gem_object_is_lmem(obj)) return ERR_PTR(-EINVAL); + i915_gem_ww_ctx_init(&ww, true); +retry: + ret = i915_gem_object_lock(obj, &ww); + if (ret) + goto err; /* * The display engine is not coherent with the LLC cache on gen6. As * a result, we make sure that the pinning that is about to occur is @@ -334,7 +345,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE); if (ret) - return ERR_PTR(ret); + goto err; /* * As the user may map the buffer once pinned in the display plane @@ -347,18 +358,31 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, vma = ERR_PTR(-ENOSPC); if ((flags & PIN_MAPPABLE) == 0 && (!view || view->type == I915_GGTT_VIEW_NORMAL)) - vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, - flags | - PIN_MAPPABLE | - PIN_NONBLOCK); - if (IS_ERR(vma)) - vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); - if (IS_ERR(vma)) - return vma; + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, view, 0, alignment, + flags | PIN_MAPPABLE | + PIN_NONBLOCK); + if (IS_ERR(vma) && vma != ERR_PTR(-EDEADLK)) + vma = i915_gem_object_ggtt_pin_ww(obj, &ww, view, 0, + alignment, flags); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; + } vma->display_alignment = max_t(u64, vma->display_alignment, alignment); - i915_gem_object_flush_if_display(obj); + i915_gem_object_flush_if_display_locked(obj); + +err: + if (ret == -EDEADLK) { + ret = i915_gem_ww_ctx_backoff(&ww); + if (!ret) + goto retry; + } + i915_gem_ww_ctx_fini(&ww); + + if (ret) + return ERR_PTR(ret); return vma; } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 45d79d75e73a..afde1952c119 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -454,6 +454,7 @@ i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj) void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj, unsigned int cache_level); void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj); +void i915_gem_object_flush_if_display_locked(struct drm_i915_gem_object *obj); int __must_check i915_gem_object_set_to_wc_domain(struct drm_i915_gem_object *obj, bool write); -- cgit v1.2.3 From b4d9145b0154f8c71dafc2db5fd445f1f3db9426 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2020 15:22:06 +0100 Subject: drm/i915: Be wary of data races when reading the active execlists To implement preempt-to-busy (and so efficient timeslicing and best utilization of the hardware submission ports) we let the GPU run asynchronously in respect to the ELSP submission queue. This created challenges in keeping and accessing the driver state mirroring the asynchronous GPU execution. The latest occurence of this was spotted by KCSAN: [ 1413.563200] BUG: KCSAN: data-race in __await_execution+0x217/0x370 [i915] [ 1413.563221] [ 1413.563236] race at unknown origin, with read to 0xffff88885bb6c478 of 8 bytes by task 9654 on cpu 1: [ 1413.563548] __await_execution+0x217/0x370 [i915] [ 1413.563891] i915_request_await_dma_fence+0x4eb/0x6a0 [i915] [ 1413.564235] i915_request_await_object+0x421/0x490 [i915] [ 1413.564577] i915_gem_do_execbuffer+0x29b7/0x3c40 [i915] [ 1413.564967] i915_gem_execbuffer2_ioctl+0x22f/0x5c0 [i915] [ 1413.564998] drm_ioctl_kernel+0x156/0x1b0 [ 1413.565022] drm_ioctl+0x2ff/0x480 [ 1413.565046] __x64_sys_ioctl+0x87/0xd0 [ 1413.565069] do_syscall_64+0x4d/0x80 [ 1413.565094] entry_SYSCALL_64_after_hwframe+0x44/0xa9 To complicate matters, we have to both avoid the read tearing of *active and avoid any write tearing as perform the pending[] -> inflight[] promotion of the execlists. This is because we cannot rely on the memcpy doing u64 aligned copies on all kernels/platforms and so we opt to open-code it with explicit WRITE_ONCE annotations to satisfy KCSAN. v2: When in doubt, write the same comment again. v3: Expanded commit message. Fixes: b55230e5e800 ("drm/i915: Check for awaits on still currently executing requests") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200716142207.13003-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added expanded commit message from Tvrtko and Chris] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_lrc.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_request.c | 25 +++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 47a90dbf8b70..0412a44f25f2 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -2062,6 +2062,14 @@ static inline void clear_ports(struct i915_request **ports, int count) memset_p((void **)ports, NULL, count); } +static inline void +copy_ports(struct i915_request **dst, struct i915_request **src, int count) +{ + /* A memcpy_p() would be very useful here! */ + while (count--) + WRITE_ONCE(*dst++, *src++); /* avoid write tearing */ +} + static void execlists_dequeue(struct intel_engine_cs *engine) { struct intel_engine_execlists * const execlists = &engine->execlists; @@ -2635,10 +2643,9 @@ static void process_csb(struct intel_engine_cs *engine) /* switch pending to inflight */ GEM_BUG_ON(!assert_pending_valid(execlists, "promote")); - memcpy(execlists->inflight, - execlists->pending, - execlists_num_ports(execlists) * - sizeof(*execlists->pending)); + copy_ports(execlists->inflight, + execlists->pending, + execlists_num_ports(execlists)); smp_wmb(); /* complete the seqlock */ WRITE_ONCE(execlists->active, execlists->inflight); diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 20ba3d9fcc5e..4f7f67a785ac 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -379,17 +379,38 @@ static bool __request_in_flight(const struct i915_request *signal) * As we know that there are always preemption points between * requests, we know that only the currently executing request * may be still active even though we have cleared the flag. - * However, we can't rely on our tracking of ELSP[0] to known + * However, we can't rely on our tracking of ELSP[0] to know * which request is currently active and so maybe stuck, as * the tracking maybe an event behind. Instead assume that * if the context is still inflight, then it is still active * even if the active flag has been cleared. + * + * To further complicate matters, if there a pending promotion, the HW + * may either perform a context switch to the second inflight execlists, + * or it may switch to the pending set of execlists. In the case of the + * latter, it may send the ACK and we process the event copying the + * pending[] over top of inflight[], _overwriting_ our *active. Since + * this implies the HW is arbitrating and not struck in *active, we do + * not worry about complete accuracy, but we do require no read/write + * tearing of the pointer [the read of the pointer must be valid, even + * as the array is being overwritten, for which we require the writes + * to avoid tearing.] + * + * Note that the read of *execlists->active may race with the promotion + * of execlists->pending[] to execlists->inflight[], overwritting + * the value at *execlists->active. This is fine. The promotion implies + * that we received an ACK from the HW, and so the context is not + * stuck -- if we do not see ourselves in *active, the inflight status + * is valid. If instead we see ourselves being copied into *active, + * we are inflight and may signal the callback. */ if (!intel_context_inflight(signal->context)) return false; rcu_read_lock(); - for (port = __engine_active(signal->engine); (rq = *port); port++) { + for (port = __engine_active(signal->engine); + (rq = READ_ONCE(*port)); /* may race with promotion of pending[] */ + port++) { if (rq->context == signal->context) { inflight = i915_seqno_passed(rq->fence.seqno, signal->fence.seqno); -- cgit v1.2.3 From 2e4c6c1a9db5e12556a12ea722df71096247e178 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 16 Jul 2020 15:22:07 +0100 Subject: drm/i915: Remove i915_request.lock requirement for execution callbacks To implement preempt-to-busy (and so efficient timeslicing and best utilization of the hardware submission ports) we let the GPU run asynchronously in respect to the ELSP submission queue. This created challenges in keeping and accessing the driver state mirroring the asynchronous GPU execution. Previous fix 1d9221e9d395 ("drm/i915: Skip signaling a signaled request") however did not correctly serialize request retirement with the execution callbacks. We were using the i915_request.lock to serialise adding an execution callback with __i915_request_submit. However, if we use an atomic llist_add to serialise multiple waiters and then check to see if the request is already executing, we can remove the irq-spinlock and fix serialization between retirement and execution callbacks in one go. v2: Avoid using the irq_work when outside of the irq-spinlocks, where we can execute the callbacks immediately. v3: Pay close attention to the order of setting ACTIVE on retirement, we need to ensure the request is signaled and breadcrumbs detached before we finish removing the request from the engine. v4: Expanded commit message. Fixes: 1d9221e9d395 ("drm/i915: Skip signaling a signaled request") Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20200716142207.13003-2-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added expanded commit message from Tvrtko and Chris] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_request.c | 105 ++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 47 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 4f7f67a785ac..11e272422fb7 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -187,30 +187,34 @@ static void irq_execute_cb_hook(struct irq_work *wrk) irq_execute_cb(wrk); } -static void __notify_execute_cb(struct i915_request *rq) +static __always_inline void +__notify_execute_cb(struct i915_request *rq, bool (*fn)(struct irq_work *wrk)) { struct execute_cb *cb, *cn; - lockdep_assert_held(&rq->lock); - - GEM_BUG_ON(!i915_request_is_active(rq)); if (llist_empty(&rq->execute_cb)) return; - llist_for_each_entry_safe(cb, cn, rq->execute_cb.first, work.llnode) - irq_work_queue(&cb->work); + llist_for_each_entry_safe(cb, cn, + llist_del_all(&rq->execute_cb), + work.llnode) + fn(&cb->work); +} - /* - * XXX Rollback on __i915_request_unsubmit() - * - * In the future, perhaps when we have an active time-slicing scheduler, - * it will be interesting to unsubmit parallel execution and remove - * busywaits from the GPU until their master is restarted. This is - * quite hairy, we have to carefully rollback the fence and do a - * preempt-to-idle cycle on the target engine, all the while the - * master execute_cb may refire. - */ - init_llist_head(&rq->execute_cb); +static void __notify_execute_cb_irq(struct i915_request *rq) +{ + __notify_execute_cb(rq, irq_work_queue); +} + +static bool irq_work_imm(struct irq_work *wrk) +{ + wrk->func(wrk); + return false; +} + +static void __notify_execute_cb_imm(struct i915_request *rq) +{ + __notify_execute_cb(rq, irq_work_imm); } static void free_capture_list(struct i915_request *request) @@ -257,9 +261,16 @@ static void remove_from_engine(struct i915_request *rq) locked = engine; } list_del_init(&rq->sched.link); + clear_bit(I915_FENCE_FLAG_PQUEUE, &rq->fence.flags); clear_bit(I915_FENCE_FLAG_HOLD, &rq->fence.flags); + + /* Prevent further __await_execution() registering a cb, then flush */ + set_bit(I915_FENCE_FLAG_ACTIVE, &rq->fence.flags); + spin_unlock_irq(&locked->active.lock); + + __notify_execute_cb_imm(rq); } bool i915_request_retire(struct i915_request *rq) @@ -271,6 +282,7 @@ bool i915_request_retire(struct i915_request *rq) GEM_BUG_ON(!i915_sw_fence_signaled(&rq->submit)); trace_i915_request_retire(rq); + i915_request_mark_complete(rq); /* * We know the GPU must have read the request to have @@ -288,15 +300,6 @@ bool i915_request_retire(struct i915_request *rq) __i915_request_fill(rq, POISON_FREE); rq->ring->head = rq->postfix; - /* - * We only loosely track inflight requests across preemption, - * and so we may find ourselves attempting to retire a _completed_ - * request that we have removed from the HW and put back on a run - * queue. - */ - remove_from_engine(rq); - - i915_request_mark_complete(rq); if (!i915_request_signaled(rq)) { spin_lock_irq(&rq->lock); dma_fence_signal_locked(&rq->fence); @@ -320,7 +323,6 @@ bool i915_request_retire(struct i915_request *rq) */ remove_from_engine(rq); GEM_BUG_ON(!llist_empty(&rq->execute_cb)); - spin_unlock_irq(&rq->lock); __list_del_entry(&rq->link); /* poison neither prev/next (RCU walks) */ @@ -348,12 +350,6 @@ void i915_request_retire_upto(struct i915_request *rq) } while (i915_request_retire(tmp) && tmp != rq); } -static void __llist_add(struct llist_node *node, struct llist_head *head) -{ - node->next = head->first; - head->first = node; -} - static struct i915_request * const * __engine_active(struct intel_engine_cs *engine) { @@ -451,18 +447,24 @@ __await_execution(struct i915_request *rq, cb->work.func = irq_execute_cb_hook; } - spin_lock_irq(&signal->lock); - if (i915_request_is_active(signal) || __request_in_flight(signal)) { - if (hook) { - hook(rq, &signal->fence); - i915_request_put(signal); - } - i915_sw_fence_complete(cb->fence); - kmem_cache_free(global.slab_execute_cbs, cb); - } else { - __llist_add(&cb->work.llnode, &signal->execute_cb); + /* + * Register the callback first, then see if the signaler is already + * active. This ensures that if we race with the + * __notify_execute_cb from i915_request_submit() and we are not + * included in that list, we get a second bite of the cherry and + * execute it ourselves. After this point, a future + * i915_request_submit() will notify us. + * + * In i915_request_retire() we set the ACTIVE bit on a completed + * request (then flush the execute_cb). So by registering the + * callback first, then checking the ACTIVE bit, we serialise with + * the completed/retired request. + */ + if (llist_add(&cb->work.llnode, &signal->execute_cb)) { + if (i915_request_is_active(signal) || + __request_in_flight(signal)) + __notify_execute_cb_imm(signal); } - spin_unlock_irq(&signal->lock); return 0; } @@ -588,10 +590,19 @@ xfer: * preempt-to-idle cycle on the target engine, all the while the * master execute_cb may refire. */ - __notify_execute_cb(request); + __notify_execute_cb_irq(request); - if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &request->fence.flags)) - i915_request_enable_breadcrumb(request); + /* We may be recursing from the signal callback of another i915 fence */ + if (!i915_request_signaled(request)) { + spin_lock_nested(&request->lock, SINGLE_DEPTH_NESTING); + + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, + &request->fence.flags) && + !i915_request_enable_breadcrumb(request)) + intel_engine_signal_breadcrumbs(engine); + + spin_unlock(&request->lock); + } return result; } -- cgit v1.2.3 From f4b3c395540aa3d4f5a6275c5bdd83ab89034806 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2020 16:21:44 +0100 Subject: drm/i915: Filter wake_flags passed to default_wake_function (NOTE: This is the minimal backportable fix, a full fix is being developed at https://patchwork.freedesktop.org/patch/388048/) The flags passed to the wait_entry.func are passed onwards to try_to_wake_up(), which has a very particular interpretation for its wake_flags. In particular, beyond the published WF_SYNC, it has a few internal flags as well. Since we passed the fence->error down the chain via the flags argument, these ended up in the default_wake_function confusing the kernel/sched. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/2110 Fixes: ef4688497512 ("drm/i915: Propagate fence errors") Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: # v5.4+ Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20200728152144.1100-1-chris@chris-wilson.co.uk Signed-off-by: Rodrigo Vivi [Joonas: Rebased and reordered into drm-intel-gt-next branch] [Joonas: Added a note and link about more complete fix] Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_sw_fence.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 295b9829e2da..4cd2038cbe35 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -164,9 +164,13 @@ static void __i915_sw_fence_wake_up_all(struct i915_sw_fence *fence, do { list_for_each_entry_safe(pos, next, &x->head, entry) { - pos->func(pos, - TASK_NORMAL, fence->error, - &extra); + int wake_flags; + + wake_flags = fence->error; + if (pos->func == autoremove_wake_function) + wake_flags = 0; + + pos->func(pos, TASK_NORMAL, wake_flags, &extra); } if (list_empty(&extra)) -- cgit v1.2.3 From e0ee152fce25dc9269c7ea5280c98aa4b3682759 Mon Sep 17 00:00:00 2001 From: Thomas Hellström Date: Thu, 3 Sep 2020 15:07:17 +0200 Subject: drm/i915: Unlock the shared hwsp_gtt object after pinning The hwsp_gtt object is used for sub-allocation and could therefore be shared by many contexts causing unnecessary contention during concurrent context pinning. However since we're currently locking it only for pinning, it remains resident until we unpin it, and therefore it's safe to drop the lock early, allowing for concurrent thread access. Signed-off-by: Thomas Hellström Reviewed-by: Chris Wilson Signed-off-by: Joonas Lahtinen --- drivers/gpu/drm/i915/gt/intel_context.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 61b05cd4c47a..d301dda1b261 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -271,6 +271,15 @@ err_release: i915_active_release(&ce->active); err_ctx_unpin: intel_context_post_unpin(ce); + + /* + * Unlock the hwsp_ggtt object since it's shared. + * In principle we can unlock all the global state locked above + * since it's pinned and doesn't need fencing, and will + * thus remain resident until it is explicitly unpinned. + */ + i915_gem_ww_unlock_single(ce->timeline->hwsp_ggtt->obj); + return err; } -- cgit v1.2.3 From 4993a8a378088be8b2f64fd9d00de9c6fb0a7ce9 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 8 Sep 2020 15:40:43 +1000 Subject: Revert "drm/i915: Remove i915_gem_object_get_dirty_page()" These commits caused a regression on Lenovo t520 sandybridge machine belonging to reporter. We are reverting them for 5.10 for other reasons, so just do it for 5.9 as well. This reverts commit 763fedd6a216f94c2eb98d2f7ca21be3d3806e69. Reported-by: Harald Arnesen Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/gem/i915_gem_object.h | 4 ++++ drivers/gpu/drm/i915/gem/i915_gem_pages.c | 14 ++++++++++++++ 2 files changed, 18 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index e5b9276d254c..9cf4ad78ece6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -258,6 +258,10 @@ struct page * i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n); +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, + unsigned int n); + dma_addr_t i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, unsigned long n, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c index d15ff6748a50..e8a083743e09 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c @@ -548,6 +548,20 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, unsigned int n) return nth_page(sg_page(sg), offset); } +/* Like i915_gem_object_get_page(), but mark the returned page dirty */ +struct page * +i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, + unsigned int n) +{ + struct page *page; + + page = i915_gem_object_get_page(obj, n); + if (!obj->mm.dirty) + set_page_dirty(page); + + return page; +} + dma_addr_t i915_gem_object_get_dma_address_len(struct drm_i915_gem_object *obj, unsigned long n, -- cgit v1.2.3 From ad5d95e4d538737ed3fa25493777decf264a3011 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 8 Sep 2020 15:41:17 +1000 Subject: Revert "drm/i915/gem: Async GPU relocations only" These commits caused a regression on Lenovo t520 sandybridge machine belonging to reporter. We are reverting them for 5.10 for other reasons, so just do it for 5.9 as well. This reverts commit 9e0f9464e2ab36b864359a59b0e9058fdef0ce47. Reported-by: Harald Arnesen Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 295 +++++++++++++++++++-- .../drm/i915/gem/selftests/i915_gem_execbuffer.c | 21 +- 2 files changed, 289 insertions(+), 27 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 6b4ec66cb558..64901cf52b7a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -45,6 +45,13 @@ struct eb_vma_array { struct eb_vma vma[]; }; +enum { + FORCE_CPU_RELOC = 1, + FORCE_GTT_RELOC, + FORCE_GPU_RELOC, +#define DBG_FORCE_RELOC 0 /* choose one of the above! */ +}; + #define __EXEC_OBJECT_HAS_PIN BIT(31) #define __EXEC_OBJECT_HAS_FENCE BIT(30) #define __EXEC_OBJECT_NEEDS_MAP BIT(29) @@ -253,6 +260,8 @@ struct i915_execbuffer { */ struct reloc_cache { struct drm_mm_node node; /** temporary GTT binding */ + unsigned long vaddr; /** Current kmap address */ + unsigned long page; /** Currently mapped page index */ unsigned int gen; /** Cached value of INTEL_GEN */ bool use_64bit_reloc : 1; bool has_llc : 1; @@ -596,6 +605,23 @@ eb_add_vma(struct i915_execbuffer *eb, } } +static inline int use_cpu_reloc(const struct reloc_cache *cache, + const struct drm_i915_gem_object *obj) +{ + if (!i915_gem_object_has_struct_page(obj)) + return false; + + if (DBG_FORCE_RELOC == FORCE_CPU_RELOC) + return true; + + if (DBG_FORCE_RELOC == FORCE_GTT_RELOC) + return false; + + return (cache->has_llc || + obj->cache_dirty || + obj->cache_level != I915_CACHE_NONE); +} + static int eb_reserve_vma(const struct i915_execbuffer *eb, struct eb_vma *ev, u64 pin_flags) @@ -926,6 +952,8 @@ relocation_target(const struct drm_i915_gem_relocation_entry *reloc, static void reloc_cache_init(struct reloc_cache *cache, struct drm_i915_private *i915) { + cache->page = -1; + cache->vaddr = 0; /* Must be a variable in the struct to allow GCC to unroll. */ cache->gen = INTEL_GEN(i915); cache->has_llc = HAS_LLC(i915); @@ -1049,6 +1077,181 @@ static int reloc_gpu_flush(struct reloc_cache *cache) return err; } +static void reloc_cache_reset(struct reloc_cache *cache) +{ + void *vaddr; + + if (!cache->vaddr) + return; + + vaddr = unmask_page(cache->vaddr); + if (cache->vaddr & KMAP) { + if (cache->vaddr & CLFLUSH_AFTER) + mb(); + + kunmap_atomic(vaddr); + i915_gem_object_finish_access((struct drm_i915_gem_object *)cache->node.mm); + } else { + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __iomem *)vaddr); + + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.clear_range(&ggtt->vm, + cache->node.start, + cache->node.size); + mutex_lock(&ggtt->vm.mutex); + drm_mm_remove_node(&cache->node); + mutex_unlock(&ggtt->vm.mutex); + } else { + i915_vma_unpin((struct i915_vma *)cache->node.mm); + } + } + + cache->vaddr = 0; + cache->page = -1; +} + +static void *reloc_kmap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + void *vaddr; + + if (cache->vaddr) { + kunmap_atomic(unmask_page(cache->vaddr)); + } else { + unsigned int flushes; + int err; + + err = i915_gem_object_prepare_write(obj, &flushes); + if (err) + return ERR_PTR(err); + + BUILD_BUG_ON(KMAP & CLFLUSH_FLAGS); + BUILD_BUG_ON((KMAP | CLFLUSH_FLAGS) & PAGE_MASK); + + cache->vaddr = flushes | KMAP; + cache->node.mm = (void *)obj; + if (flushes) + mb(); + } + + vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj, page)); + cache->vaddr = unmask_flags(cache->vaddr) | (unsigned long)vaddr; + cache->page = page; + + return vaddr; +} + +static void *reloc_iomap(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + struct i915_ggtt *ggtt = cache_to_ggtt(cache); + unsigned long offset; + void *vaddr; + + if (cache->vaddr) { + intel_gt_flush_ggtt_writes(ggtt->vm.gt); + io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); + } else { + struct i915_vma *vma; + int err; + + if (i915_gem_object_is_tiled(obj)) + return ERR_PTR(-EINVAL); + + if (use_cpu_reloc(cache, obj)) + return NULL; + + i915_gem_object_lock(obj); + err = i915_gem_object_set_to_gtt_domain(obj, true); + i915_gem_object_unlock(obj); + if (err) + return ERR_PTR(err); + + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, + PIN_MAPPABLE | + PIN_NONBLOCK /* NOWARN */ | + PIN_NOEVICT); + if (IS_ERR(vma)) { + memset(&cache->node, 0, sizeof(cache->node)); + mutex_lock(&ggtt->vm.mutex); + err = drm_mm_insert_node_in_range + (&ggtt->vm.mm, &cache->node, + PAGE_SIZE, 0, I915_COLOR_UNEVICTABLE, + 0, ggtt->mappable_end, + DRM_MM_INSERT_LOW); + mutex_unlock(&ggtt->vm.mutex); + if (err) /* no inactive aperture space, use cpu reloc */ + return NULL; + } else { + cache->node.start = vma->node.start; + cache->node.mm = (void *)vma; + } + } + + offset = cache->node.start; + if (drm_mm_node_allocated(&cache->node)) { + ggtt->vm.insert_page(&ggtt->vm, + i915_gem_object_get_dma_address(obj, page), + offset, I915_CACHE_NONE, 0); + } else { + offset += page << PAGE_SHIFT; + } + + vaddr = (void __force *)io_mapping_map_atomic_wc(&ggtt->iomap, + offset); + cache->page = page; + cache->vaddr = (unsigned long)vaddr; + + return vaddr; +} + +static void *reloc_vaddr(struct drm_i915_gem_object *obj, + struct reloc_cache *cache, + unsigned long page) +{ + void *vaddr; + + if (cache->page == page) { + vaddr = unmask_page(cache->vaddr); + } else { + vaddr = NULL; + if ((cache->vaddr & KMAP) == 0) + vaddr = reloc_iomap(obj, cache, page); + if (!vaddr) + vaddr = reloc_kmap(obj, cache, page); + } + + return vaddr; +} + +static void clflush_write32(u32 *addr, u32 value, unsigned int flushes) +{ + if (unlikely(flushes & (CLFLUSH_BEFORE | CLFLUSH_AFTER))) { + if (flushes & CLFLUSH_BEFORE) { + clflushopt(addr); + mb(); + } + + *addr = value; + + /* + * Writes to the same cacheline are serialised by the CPU + * (including clflush). On the write path, we only require + * that it hits memory in an orderly fashion and place + * mb barriers at the start and end of the relocation phase + * to ensure ordering of clflush wrt to the system. + */ + if (flushes & CLFLUSH_AFTER) + clflushopt(addr); + } else + *addr = value; +} + static int reloc_move_to_gpu(struct i915_request *rq, struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -1214,6 +1417,17 @@ static u32 *reloc_gpu(struct i915_execbuffer *eb, return cmd; } +static inline bool use_reloc_gpu(struct i915_vma *vma) +{ + if (DBG_FORCE_RELOC == FORCE_GPU_RELOC) + return true; + + if (DBG_FORCE_RELOC) + return false; + + return !dma_resv_test_signaled_rcu(vma->resv, true); +} + static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) { struct page *page; @@ -1228,10 +1442,10 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static int __reloc_entry_gpu(struct i915_execbuffer *eb, - struct i915_vma *vma, - u64 offset, - u64 target_addr) +static bool __reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) { const unsigned int gen = eb->reloc_cache.gen; unsigned int len; @@ -1247,7 +1461,7 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, batch = reloc_gpu(eb, vma, len); if (IS_ERR(batch)) - return PTR_ERR(batch); + return false; addr = gen8_canonical_addr(vma->node.start + offset); if (gen >= 8) { @@ -1296,21 +1510,55 @@ static int __reloc_entry_gpu(struct i915_execbuffer *eb, *batch++ = target_addr; } - return 0; + return true; +} + +static bool reloc_entry_gpu(struct i915_execbuffer *eb, + struct i915_vma *vma, + u64 offset, + u64 target_addr) +{ + if (eb->reloc_cache.vaddr) + return false; + + if (!use_reloc_gpu(vma)) + return false; + + return __reloc_entry_gpu(eb, vma, offset, target_addr); } static u64 -relocate_entry(struct i915_execbuffer *eb, - struct i915_vma *vma, +relocate_entry(struct i915_vma *vma, const struct drm_i915_gem_relocation_entry *reloc, + struct i915_execbuffer *eb, const struct i915_vma *target) { u64 target_addr = relocation_target(reloc, target); - int err; - - err = __reloc_entry_gpu(eb, vma, reloc->offset, target_addr); - if (err) - return err; + u64 offset = reloc->offset; + + if (!reloc_entry_gpu(eb, vma, offset, target_addr)) { + bool wide = eb->reloc_cache.use_64bit_reloc; + void *vaddr; + +repeat: + vaddr = reloc_vaddr(vma->obj, + &eb->reloc_cache, + offset >> PAGE_SHIFT); + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + + GEM_BUG_ON(!IS_ALIGNED(offset, sizeof(u32))); + clflush_write32(vaddr + offset_in_page(offset), + lower_32_bits(target_addr), + eb->reloc_cache.vaddr); + + if (wide) { + offset += sizeof(u32); + target_addr >>= 32; + wide = false; + goto repeat; + } + } return target->node.start | UPDATE; } @@ -1375,7 +1623,8 @@ eb_relocate_entry(struct i915_execbuffer *eb, * If the relocation already has the right value in it, no * more work needs to be done. */ - if (gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) + if (!DBG_FORCE_RELOC && + gen8_canonical_addr(target->vma->node.start) == reloc->presumed_offset) return 0; /* Check that the relocation address is valid... */ @@ -1407,7 +1656,7 @@ eb_relocate_entry(struct i915_execbuffer *eb, ev->flags &= ~EXEC_OBJECT_ASYNC; /* and update the user's relocation entry */ - return relocate_entry(eb, ev->vma, reloc, target->vma); + return relocate_entry(ev->vma, reloc, eb, target->vma); } static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) @@ -1445,8 +1694,10 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) * this is bad and so lockdep complains vehemently. */ copied = __copy_from_user(r, urelocs, count * sizeof(r[0])); - if (unlikely(copied)) - return -EFAULT; + if (unlikely(copied)) { + remain = -EFAULT; + goto out; + } remain -= count; do { @@ -1454,7 +1705,8 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) if (likely(offset == 0)) { } else if ((s64)offset < 0) { - return (int)offset; + remain = (int)offset; + goto out; } else { /* * Note that reporting an error now @@ -1484,8 +1736,9 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct eb_vma *ev) } while (r++, --count); urelocs += ARRAY_SIZE(stack); } while (remain); - - return 0; +out: + reloc_cache_reset(&eb->reloc_cache); + return remain; } static int eb_relocate(struct i915_execbuffer *eb) @@ -2392,7 +2645,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, eb.i915 = i915; eb.file = file; eb.args = args; - if (!(args->flags & I915_EXEC_NO_RELOC)) + if (DBG_FORCE_RELOC || !(args->flags & I915_EXEC_NO_RELOC)) args->flags |= __EXEC_HAS_RELOC; eb.exec = exec; diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c index 57c14d3340cd..a49016f8ee0d 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_execbuffer.c @@ -37,14 +37,20 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, return err; /* 8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[0] * sizeof(u32), 0); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[0] * sizeof(u32), + 0)) { + err = -EIO; goto unpin_vma; + } /* !8-Byte aligned */ - err = __reloc_entry_gpu(eb, vma, offsets[1] * sizeof(u32), 1); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[1] * sizeof(u32), + 1)) { + err = -EIO; goto unpin_vma; + } /* Skip to the end of the cmd page */ i = PAGE_SIZE / sizeof(u32) - RELOC_TAIL - 1; @@ -54,9 +60,12 @@ static int __igt_gpu_reloc(struct i915_execbuffer *eb, eb->reloc_cache.rq_size += i; /* Force batch chaining */ - err = __reloc_entry_gpu(eb, vma, offsets[2] * sizeof(u32), 2); - if (err) + if (!__reloc_entry_gpu(eb, vma, + offsets[2] * sizeof(u32), + 2)) { + err = -EIO; goto unpin_vma; + } GEM_BUG_ON(!eb->reloc_cache.rq); rq = i915_request_get(eb->reloc_cache.rq); -- cgit v1.2.3 From 20561da3a2e1e0e827ef5510cb0f74bcfd377e41 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 8 Sep 2020 15:41:43 +1000 Subject: Revert "drm/i915/gem: Delete unused code" These commits caused a regression on Lenovo t520 sandybridge machine belonging to reporter. We are reverting them for 5.10 for other reasons, so just do it for 5.9 as well. This reverts commit 7ac2d2536dfa71c275a74813345779b1e7522c91. Reported-by: Harald Arnesen Signed-off-by: Dave Airlie --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 64901cf52b7a..446e76e95c38 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -965,6 +965,25 @@ static void reloc_cache_init(struct reloc_cache *cache, cache->target = NULL; } +static inline void *unmask_page(unsigned long p) +{ + return (void *)(uintptr_t)(p & PAGE_MASK); +} + +static inline unsigned int unmask_flags(unsigned long p) +{ + return p & ~PAGE_MASK; +} + +#define KMAP 0x4 /* after CLFLUSH_FLAGS */ + +static inline struct i915_ggtt *cache_to_ggtt(struct reloc_cache *cache) +{ + struct drm_i915_private *i915 = + container_of(cache, struct i915_execbuffer, reloc_cache)->i915; + return &i915->ggtt; +} + #define RELOC_TAIL 4 static int reloc_gpu_chain(struct reloc_cache *cache) -- cgit v1.2.3 From 0c4c801b31f89cfc1b97207abbab687f43d8e258 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Tue, 1 Sep 2020 18:10:36 +0300 Subject: drm/i915: fix regression leading to display audio probe failure on GLK In commit 4f0b4352bd26 ("drm/i915: Extract cdclk requirements checking to separate function") the order of force_min_cdclk_changed check and intel_modeset_checks(), was reversed. This broke the mechanism to immediately force a new CDCLK minimum, and lead to driver probe errors for display audio on GLK platform with 5.9-rc1 kernel. Fix the issue by moving intel_modeset_checks() call later. [vsyrjala: It also broke the ability of planes to bump up the cdclk and thus could lead to underruns when eg. flipping from 32bpp to 64bpp framebuffer. To be clear, we still compute the new cdclk correctly but fail to actually program it to the hardware due to intel_set_cdclk_{pre,post}_plane_update() not getting called on account of state->modeset==false.] Fixes: 4f0b4352bd26 ("drm/i915: Extract cdclk requirements checking to separate function") BugLink: https://github.com/thesofproject/linux/issues/2410 Signed-off-by: Kai Vehmanen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20200901151036.1312357-1-kai.vehmanen@linux.intel.com (cherry picked from commit cf696856bc54a31f78e6538b84c8f7a006b6108b) Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 68325678f5ef..b18c5ac2934d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -14956,12 +14956,6 @@ static int intel_atomic_check(struct drm_device *dev, if (dev_priv->wm.distrust_bios_wm) any_ms = true; - if (any_ms) { - ret = intel_modeset_checks(state); - if (ret) - goto fail; - } - intel_fbc_choose_crtc(dev_priv, state); ret = calc_watermark_data(state); if (ret) @@ -14976,6 +14970,10 @@ static int intel_atomic_check(struct drm_device *dev, goto fail; if (any_ms) { + ret = intel_modeset_checks(state); + if (ret) + goto fail; + ret = intel_modeset_calc_cdclk(state); if (ret) return ret; -- cgit v1.2.3 From 166774a2c2c6b82da5d984f587567071ff00c1f3 Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Thu, 10 Sep 2020 13:12:25 +0200 Subject: drm/i915: Fix slightly botched merge in __reloc_entry_gpu This function should be an int, not a bool. Presumably because we had the same 2 reverts in a slightly different way, git got confused. Thanks to Dan for reporting. :) The conflict is between the 3 reverts in drm-fixes: 4993a8a37808 ("Revert "drm/i915: Remove i915_gem_object_get_dirty_page()"") ad5d95e4d538 ("Revert "drm/i915/gem: Async GPU relocations only"") 20561da3a2e1 ("Revert "drm/i915/gem: Delete unused code"") And the slightly different combined revert in drm-intel-gt-next, but with the same goal: 102a0a9051f4 ("Revert "drm/i915/gem: Async GPU relocations only"") In the merge commit 1f4b2aca794f ("Merge tag 'drm-intel-gt-next-2020-09-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next") things went wrong, but the merge commit view now doesn't show any conflict anymore (as git tends to do when the resolution picks one or the other branch). The need to handle other than just true/false error codes in __reloc_entry_gpu was added in the dma_resv locking changes in c43ce12328df ("drm/i915: Use per object locking in execbuf, v12.") Signed-off-by: Maarten Lankhorst Reported-by: Dan Carpenter Cc: Dave Airlie [danvet: Explain this entire saga a lot better, adding tons of commit references. Also note that this was merged before full intel-gfx-CI results, only after BAT, since the breakage at the BAT run is already severe enough to block all pre-merge testing.] Fixes: 1f4b2aca794f ("Merge tag 'drm-intel-gt-next-2020-09-07' of git://anongit.freedesktop.org/drm/drm-intel into drm-next") Acked-by: Joonas Lahtinen Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20200910111225.2184193-1-maarten.lankhorst@linux.intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 804339255df1..5509946f1a1d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1437,7 +1437,7 @@ static unsigned long vma_phys_addr(struct i915_vma *vma, u32 offset) return addr + offset_in_page(offset); } -static bool __reloc_entry_gpu(struct i915_execbuffer *eb, +static int __reloc_entry_gpu(struct i915_execbuffer *eb, struct i915_vma *vma, u64 offset, u64 target_addr) @@ -1456,7 +1456,7 @@ static bool __reloc_entry_gpu(struct i915_execbuffer *eb, batch = reloc_gpu(eb, vma, len); if (batch == ERR_PTR(-EDEADLK)) - return (s64)-EDEADLK; + return -EDEADLK; else if (IS_ERR(batch)) return false; -- cgit v1.2.3